sonygod commited on
Commit
594497e
·
1 Parent(s): 8998663

添加总结字幕

Browse files
Files changed (1) hide show
  1. youtube_sub.js +142 -2
youtube_sub.js CHANGED
@@ -29,7 +29,8 @@ GM_addStyle(`
29
  }
30
  const WORD_CACHE_EXPIRY = 7 * 24 * 60 * 60 * 1000; // 7 days in ms
31
  const WORD_CACHE_KEY = 'youtube_subtitle_word_cache';
32
-
 
33
  // 增强的样式定义,添加过渡效果
34
  const styles = `
35
  .subtitle-manager {
@@ -524,6 +525,141 @@ GM_addStyle(`
524
  window.subtitleManagerInstance = this;
525
  this.speakerClickCount = 0; // Add counter
526
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
  cleanup() {
528
  // Remove existing instance
529
  if (this.container) {
@@ -856,7 +992,8 @@ GM_addStyle(`
856
  const tabsData = [
857
  { id: 'english', text: 'English' },
858
  { id: 'chinese', text: '中文' },
859
- { id: 'mixed', text: 'Mixed' }
 
860
  ];
861
 
862
  tabsData.forEach(tab => {
@@ -1849,6 +1986,9 @@ GM_addStyle(`
1849
  content.appendChild(this.createMessageElement('No subtitles available for mixed mode'));
1850
  }
1851
  break;
 
 
 
1852
  }
1853
 
1854
  // Fade in
 
29
  }
30
  const WORD_CACHE_EXPIRY = 7 * 24 * 60 * 60 * 1000; // 7 days in ms
31
  const WORD_CACHE_KEY = 'youtube_subtitle_word_cache';
32
+ // Add after WORD_CACHE_KEY constant:
33
+ const NEW_WORDS_CACHE_KEY = 'youtube_subtitle_newword';
34
  // 增强的样式定义,添加过渡效果
35
  const styles = `
36
  .subtitle-manager {
 
525
  window.subtitleManagerInstance = this;
526
  this.speakerClickCount = 0; // Add counter
527
  }
528
+
529
+ extractUniqueWords() {
530
+ // Get all English words from subtitles
531
+ const words = this.subtitles.english
532
+ .flatMap(sub => sub.words
533
+ .map(w => w.text.toLowerCase())
534
+ .filter(text =>
535
+ // Only include valid English words
536
+ /^[a-z]+$/.test(text) &&
537
+ text.length > 1
538
+ )
539
+ );
540
+
541
+ // Remove duplicates and sort
542
+ return [...new Set(words)].sort();
543
+ }
544
+
545
+ loadNewWordsCache() {
546
+ try {
547
+ const cached = localStorage.getItem(NEW_WORDS_CACHE_KEY);
548
+ return cached ? new Set(JSON.parse(cached)) : new Set();
549
+ } catch (e) {
550
+ debug.error('Failed to load words cache:', e);
551
+ return new Set();
552
+ }
553
+ }
554
+
555
+ updateNewWordsCache(words) {
556
+ try {
557
+ const existingWords = this.loadNewWordsCache();
558
+ const updatedWords = [...existingWords, ...words];
559
+ localStorage.setItem(NEW_WORDS_CACHE_KEY,
560
+ JSON.stringify([...new Set(updatedWords)]));
561
+ } catch (e) {
562
+ debug.error('Failed to update words cache:', e);
563
+ }
564
+ }
565
+
566
+ displayWordSummary(container) {
567
+ // Clear existing content safely
568
+ while (container.firstChild) {
569
+ container.removeChild(container.firstChild);
570
+ }
571
+
572
+ const uniqueWords = this.extractUniqueWords();
573
+ const existingWords = this.loadNewWordsCache();
574
+
575
+ // Add summary header
576
+ const summaryDiv = document.createElement('div');
577
+ summaryDiv.style.cssText = `
578
+ font-size: 18px;
579
+ padding: 15px;
580
+ margin-bottom: 20px;
581
+ border-bottom: 1px solid #ccc;
582
+ text-align: center;
583
+ font-weight: bold;
584
+ color: #4CAF50;
585
+ `;
586
+
587
+ container.appendChild(summaryDiv);
588
+
589
+ // Group words by first letter
590
+ const grouped = uniqueWords.reduce((acc, word) => {
591
+ const firstLetter = word[0].toUpperCase();
592
+ if (!acc[firstLetter]) acc[firstLetter] = [];
593
+ acc[firstLetter].push(word);
594
+ return acc;
595
+ }, {});
596
+
597
+ // Create letter sections with enhanced styling
598
+ Object.entries(grouped)
599
+ .sort(([a], [b]) => a.localeCompare(b))
600
+ .forEach(([letter, words]) => {
601
+ const section = document.createElement('div');
602
+ section.className = 'word-section';
603
+ section.style.margin = '0 15px 25px 15px';
604
+
605
+ const heading = document.createElement('h3');
606
+ heading.style.cssText = `
607
+ color: #4CAF50;
608
+ margin: 15px 0;
609
+ font-size: 24px;
610
+ font-weight: bold;
611
+ `;
612
+ heading.textContent = letter;
613
+ section.appendChild(heading);
614
+
615
+ const grid = document.createElement('div');
616
+ grid.className = 'word-grid';
617
+ grid.style.cssText = `
618
+ display: grid;
619
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
620
+ gap: 12px;
621
+ padding: 10px;
622
+ `;
623
+
624
+ words.forEach(word => {
625
+ const btn = document.createElement('button');
626
+ btn.className = `word-btn subtitle-word ${existingWords.has(word) ? 'known' : 'new'}`;
627
+ btn.style.cssText = `
628
+ text-align: left;
629
+ padding: 8px 12px;
630
+ font-size: 16px;
631
+ border-radius: 4px;
632
+ transition: all 0.2s;
633
+ cursor: pointer;
634
+ ${existingWords.has(word) ? 'opacity: 0.5;' : ''}
635
+ `;
636
+ btn.dataset.word = word;
637
+ btn.textContent = word;
638
+
639
+ btn.onclick = (e) => {
640
+ e.stopPropagation();
641
+ if (word) {
642
+ this.showWordDefinition(word);
643
+ }
644
+ };
645
+
646
+ grid.appendChild(btn);
647
+ });
648
+
649
+ section.appendChild(grid);
650
+ container.appendChild(section);
651
+ });
652
+
653
+ // Add new words to cache
654
+ this.updateNewWordsCache(uniqueWords);
655
+
656
+ // Get fresh count from cache after update
657
+ const freshCache = this.loadNewWordsCache();
658
+ const totalCachedWords = freshCache.size;
659
+
660
+ // Update summary text with fresh counts
661
+ summaryDiv.textContent = `Unique: ${uniqueWords.length} | Total: ${totalCachedWords}`;
662
+ }
663
  cleanup() {
664
  // Remove existing instance
665
  if (this.container) {
 
992
  const tabsData = [
993
  { id: 'english', text: 'English' },
994
  { id: 'chinese', text: '中文' },
995
+ { id: 'mixed', text: 'Mixed' },
996
+ { id: 'summary', text: 'Words' }
997
  ];
998
 
999
  tabsData.forEach(tab => {
 
1986
  content.appendChild(this.createMessageElement('No subtitles available for mixed mode'));
1987
  }
1988
  break;
1989
+ case 'summary':
1990
+ this.displayWordSummary(content);
1991
+ break;
1992
  }
1993
 
1994
  // Fade in