This commit is contained in:
@@ -824,5 +824,21 @@
|
||||
"Selected Text Rules": "قواعد النص المحدد",
|
||||
"No selected text replacement rules": "لا توجد قواعد استبدال نص محدد",
|
||||
"Book Specific Rules": "قواعد خاصة بالكتاب",
|
||||
"No book-level replacement rules": "لا توجد قواعد استبدال على مستوى الكتاب"
|
||||
"No book-level replacement rules": "لا توجد قواعد استبدال على مستوى الكتاب",
|
||||
"Disable Quick Action": "تعطيل الإجراء السريع",
|
||||
"Enable Quick Action on Selection": "تمكين الإجراء السريع عند التحديد",
|
||||
"None": "لا شيء",
|
||||
"Annotation Tools": "أدوات التعليق",
|
||||
"Enable Quick Actions": "تمكين الإجراءات السريعة",
|
||||
"Quick Action": "الإجراء السريع",
|
||||
"Copy to Notebook": "نسخ إلى الدفتر",
|
||||
"Copy text after selection": "نسخ النص بعد التحديد",
|
||||
"Highlight text after selection": "تمييز النص بعد التحديد",
|
||||
"Annotate text after selection": "تعليق على النص بعد التحديد",
|
||||
"Search text after selection": "البحث في النص بعد التحديد",
|
||||
"Look up text in dictionary after selection": "البحث عن النص في القاموس بعد التحديد",
|
||||
"Look up text in Wikipedia after selection": "البحث عن النص في ويكيبيديا بعد التحديد",
|
||||
"Translate text after selection": "ترجمة النص بعد التحديد",
|
||||
"Read text aloud after selection": "قراءة النص بصوت عالٍ بعد التحديد",
|
||||
"Proofread text after selection": "تدقيق النص بعد التحديد"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "নির্বাচিত টেক্সট নিয়ম",
|
||||
"No selected text replacement rules": "কোনও নির্বাচিত টেক্সট বিকল্প নিয়ম নেই",
|
||||
"Book Specific Rules": "বই নির্দিষ্ট নিয়ম",
|
||||
"No book-level replacement rules": "কোনও বই-স্তরের বিকল্প নিয়ম নেই"
|
||||
"No book-level replacement rules": "কোনও বই-স্তরের বিকল্প নিয়ম নেই",
|
||||
"Disable Quick Action": "দ্রুত ক্রিয়া নিষ্ক্রিয় করুন",
|
||||
"Enable Quick Action on Selection": "নির্বাচনের উপর দ্রুত ক্রিয়া সক্ষম করুন",
|
||||
"None": "কোনোটিই নয়",
|
||||
"Annotation Tools": "অ্যনোটেশন সরঞ্জামসমূহ",
|
||||
"Enable Quick Actions": "দ্রুত ক্রিয়া সক্ষম করুন",
|
||||
"Quick Action": "দ্রুত ক্রিয়া",
|
||||
"Copy to Notebook": "নোটবুকে কপি করুন",
|
||||
"Copy text after selection": "নির্বাচনের পরে টেক্সট কপি করুন",
|
||||
"Highlight text after selection": "নির্বাচনের পরে টেক্সট হাইলাইট করুন",
|
||||
"Annotate text after selection": "নির্বাচনের পরে টেক্সট মন্তব্য করুন",
|
||||
"Search text after selection": "নির্বাচনের পরে টেক্সট অনুসন্ধান করুন",
|
||||
"Look up text in dictionary after selection": "নির্বাচনের পরে টেক্সট অভিধানে দেখুন",
|
||||
"Look up text in Wikipedia after selection": "নির্বাচনের পরে টেক্সট উইকিপিডিয়ায় দেখুন",
|
||||
"Translate text after selection": "নির্বাচনের পরে টেক্সট অনুবাদ করুন",
|
||||
"Read text aloud after selection": "নির্বাচনের পরে টেক্সট উচ্চারণ করুন",
|
||||
"Proofread text after selection": "নির্বাচনের পরে টেক্সট প্রুফরিড করুন"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "བདམས་པའི་ཡིག་ཆ་བརྗེ་སྒྱུར་སྲིད་སྒྲིག",
|
||||
"No selected text replacement rules": "བདམས་པའི་ཡིག་ཆ་བརྗེ་སྒྱུར་སྲིད་སྒྲིག་མེད་པ",
|
||||
"Book Specific Rules": "དེབ་སྒོས་ཀྱི་བརྗེ་སྒྱུར་སྲིད་སྒྲིག",
|
||||
"No book-level replacement rules": "དེབ་རིམ་གྱི་བརྗེ་སྒྱུར་སྲིད་སྒྲིག་མེད་པ"
|
||||
"No book-level replacement rules": "དེབ་རིམ་གྱི་བརྗེ་སྒྱུར་སྲིད་སྒྲིག་མེད་པ",
|
||||
"Disable Quick Action": "མགྱོགས་མྱུར་བྱ་བ་སྤང་",
|
||||
"Enable Quick Action on Selection": "འདེམས་པའི་སྐབས་མགྱོགས་མྱུར་བྱ་བ་སྤྱོད་",
|
||||
"None": "མེད་",
|
||||
"Annotation Tools": "མཆན་འགྲེལ་ལག་ཆ་",
|
||||
"Enable Quick Actions": "མགྱོགས་མྱུར་བྱ་བ་སྤྱོད་",
|
||||
"Quick Action": "མགྱོགས་མྱུར་བྱ་བ་",
|
||||
"Copy to Notebook": "ཟིན་དེབ་ནང་འདྲ་བཤུས་",
|
||||
"Copy text after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་འདྲ་བཤུས་",
|
||||
"Highlight text after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་མངོན་གསལ་བྱེད་",
|
||||
"Annotate text after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་མཆན་འགྲེལ་བྱེད་",
|
||||
"Search text after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་འཚོལ་ཞིབ་བྱེད་",
|
||||
"Look up text in dictionary after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་ཚིག་མཛོད་ནང་འཚོལ་",
|
||||
"Look up text in Wikipedia after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་ཝེ་ཀི་པི་ཌི་ཡི་ནང་འཚོལ་",
|
||||
"Translate text after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་སྐད་བསྒྱུར་བྱེད་",
|
||||
"Read text aloud after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་སྐད་ཀྱིས་ཀློག་",
|
||||
"Proofread text after selection": "ཡིག་ཆ་འདེམས་པའི་ཐབས་ཀྱིས་ཞིབ་བཤེར་བྱེད་"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "Regeln für ausgewählten Text",
|
||||
"No selected text replacement rules": "Keine Ersetzungsregeln für ausgewählten Text",
|
||||
"Book Specific Rules": "Buchspezifische Regeln",
|
||||
"No book-level replacement rules": "Keine Ersetzungsregeln auf Buchebene"
|
||||
"No book-level replacement rules": "Keine Ersetzungsregeln auf Buchebene",
|
||||
"Disable Quick Action": "Schnellaktion deaktivieren",
|
||||
"Enable Quick Action on Selection": "Schnellaktion bei Auswahl aktivieren",
|
||||
"None": "Keine",
|
||||
"Annotation Tools": "Anmerkungswerkzeuge",
|
||||
"Enable Quick Actions": "Schnellaktionen aktivieren",
|
||||
"Quick Action": "Schnellaktion",
|
||||
"Copy to Notebook": "In Notizbuch kopieren",
|
||||
"Copy text after selection": "Text nach Auswahl kopieren",
|
||||
"Highlight text after selection": "Text nach Auswahl hervorheben",
|
||||
"Annotate text after selection": "Text nach Auswahl annotieren",
|
||||
"Search text after selection": "Text nach Auswahl suchen",
|
||||
"Look up text in dictionary after selection": "Text nach Auswahl im Wörterbuch nachschlagen",
|
||||
"Look up text in Wikipedia after selection": "Text nach Auswahl in Wikipedia nachschlagen",
|
||||
"Translate text after selection": "Text nach Auswahl übersetzen",
|
||||
"Read text aloud after selection": "Text nach Auswahl vorlesen",
|
||||
"Proofread text after selection": "Text nach Auswahl Korrektur lesen"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "Κανόνες επιλεγμένου κειμένου",
|
||||
"No selected text replacement rules": "Δεν υπάρχουν κανόνες αντικατάστασης για το επιλεγμένο κείμενο",
|
||||
"Book Specific Rules": "Κανόνες για συγκεκριμένο βιβλίο",
|
||||
"No book-level replacement rules": "Δεν υπάρχουν κανόνες αντικατάστασης σε επίπεδο βιβλίου"
|
||||
"No book-level replacement rules": "Δεν υπάρχουν κανόνες αντικατάστασης σε επίπεδο βιβλίου",
|
||||
"Disable Quick Action": "Απενεργοποίηση γρήγορης ενέργειας",
|
||||
"Enable Quick Action on Selection": "Ενεργοποίηση γρήγορης ενέργειας κατά την επιλογή",
|
||||
"None": "Καμία",
|
||||
"Annotation Tools": "Εργαλεία σχολιασμού",
|
||||
"Enable Quick Actions": "Ενεργοποίηση γρήγορων ενεργειών",
|
||||
"Quick Action": "Γρήγορη ενέργεια",
|
||||
"Copy to Notebook": "Αντιγραφή στο σημειωματάριο",
|
||||
"Copy text after selection": "Αντιγραφή κειμένου μετά την επιλογή",
|
||||
"Highlight text after selection": "Επισήμανση κειμένου μετά την επιλογή",
|
||||
"Annotate text after selection": "Σχολιασμός κειμένου μετά την επιλογή",
|
||||
"Search text after selection": "Αναζήτηση κειμένου μετά την επιλογή",
|
||||
"Look up text in dictionary after selection": "Αναζήτηση κειμένου στο λεξικό μετά την επιλογή",
|
||||
"Look up text in Wikipedia after selection": "Αναζήτηση κειμένου στη Wikipedia μετά την επιλογή",
|
||||
"Translate text after selection": "Μετάφραση κειμένου μετά την επιλογή",
|
||||
"Read text aloud after selection": "Ανάγνωση κειμένου μετά την επιλογή",
|
||||
"Proofread text after selection": "Διόρθωση κειμένου μετά την επιλογή"
|
||||
}
|
||||
|
||||
@@ -794,5 +794,21 @@
|
||||
"Selected Text Rules": "Reglas de texto seleccionado",
|
||||
"No selected text replacement rules": "No hay reglas de reemplazo para el texto seleccionado",
|
||||
"Book Specific Rules": "Reglas específicas del libro",
|
||||
"No book-level replacement rules": "No hay reglas de reemplazo a nivel de libro"
|
||||
"No book-level replacement rules": "No hay reglas de reemplazo a nivel de libro",
|
||||
"Disable Quick Action": "Desactivar acción rápida",
|
||||
"Enable Quick Action on Selection": "Activar acción rápida al seleccionar",
|
||||
"None": "Ninguna",
|
||||
"Annotation Tools": "Herramientas de anotación",
|
||||
"Enable Quick Actions": "Activar acciones rápidas",
|
||||
"Quick Action": "Acción rápida",
|
||||
"Copy to Notebook": "Copiar al cuaderno",
|
||||
"Copy text after selection": "Copiar texto después de la selección",
|
||||
"Highlight text after selection": "Resaltar texto después de la selección",
|
||||
"Annotate text after selection": "Anotar texto después de la selección",
|
||||
"Search text after selection": "Buscar texto después de la selección",
|
||||
"Look up text in dictionary after selection": "Buscar texto en el diccionario después de la selección",
|
||||
"Look up text in Wikipedia after selection": "Buscar texto en Wikipedia después de la selección",
|
||||
"Translate text after selection": "Traducir texto después de la selección",
|
||||
"Read text aloud after selection": "Leer texto en voz alta después de la selección",
|
||||
"Proofread text after selection": "Corregir texto después de la selección"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "قوانین متن انتخابشده",
|
||||
"No selected text replacement rules": "هیچ قانون جایگزینی برای متن انتخابشده وجود ندارد",
|
||||
"Book Specific Rules": "قوانین مخصوص کتاب",
|
||||
"No book-level replacement rules": "هیچ قانون جایگزینی در سطح کتاب وجود ندارد"
|
||||
"No book-level replacement rules": "هیچ قانون جایگزینی در سطح کتاب وجود ندارد",
|
||||
"Disable Quick Action": "غیرفعالسازی اقدام سریع",
|
||||
"Enable Quick Action on Selection": "فعالسازی اقدام سریع هنگام انتخاب",
|
||||
"None": "هیچکدام",
|
||||
"Annotation Tools": "ابزارهای یادداشتگذاری",
|
||||
"Enable Quick Actions": "فعالسازی اقدامات سریع",
|
||||
"Quick Action": "اقدام سریع",
|
||||
"Copy to Notebook": "کپی به دفترچه",
|
||||
"Copy text after selection": "کپی متن پس از انتخاب",
|
||||
"Highlight text after selection": "برجستهسازی متن پس از انتخاب",
|
||||
"Annotate text after selection": "یادداشتگذاری متن پس از انتخاب",
|
||||
"Search text after selection": "جستجوی متن پس از انتخاب",
|
||||
"Look up text in dictionary after selection": "جستجوی متن در فرهنگ لغت پس از انتخاب",
|
||||
"Look up text in Wikipedia after selection": "جستجوی متن در ویکیپدیا پس از انتخاب",
|
||||
"Translate text after selection": "ترجمه متن پس از انتخاب",
|
||||
"Read text aloud after selection": "خواندن متن با صدای بلند پس از انتخاب",
|
||||
"Proofread text after selection": "بازبینی متن پس از انتخاب"
|
||||
}
|
||||
|
||||
@@ -794,5 +794,21 @@
|
||||
"Selected Text Rules": "Règles du texte sélectionné",
|
||||
"No selected text replacement rules": "Aucune règle de remplacement pour le texte sélectionné",
|
||||
"Book Specific Rules": "Règles spécifiques au livre",
|
||||
"No book-level replacement rules": "Aucune règle de remplacement au niveau du livre"
|
||||
"No book-level replacement rules": "Aucune règle de remplacement au niveau du livre",
|
||||
"Disable Quick Action": "Désactiver l’action rapide",
|
||||
"Enable Quick Action on Selection": "Activer l’action rapide lors de la sélection",
|
||||
"None": "Aucune",
|
||||
"Annotation Tools": "Outils d’annotation",
|
||||
"Enable Quick Actions": "Activer les actions rapides",
|
||||
"Quick Action": "Action rapide",
|
||||
"Copy to Notebook": "Copier dans le carnet",
|
||||
"Copy text after selection": "Copier le texte après la sélection",
|
||||
"Highlight text after selection": "Mettre en surbrillance le texte après la sélection",
|
||||
"Annotate text after selection": "Annoter le texte après la sélection",
|
||||
"Search text after selection": "Rechercher le texte après la sélection",
|
||||
"Look up text in dictionary after selection": "Chercher le texte dans le dictionnaire après la sélection",
|
||||
"Look up text in Wikipedia after selection": "Chercher le texte dans Wikipédia après la sélection",
|
||||
"Translate text after selection": "Traduire le texte après la sélection",
|
||||
"Read text aloud after selection": "Lire le texte à haute voix après la sélection",
|
||||
"Proofread text after selection": "Relire le texte après la sélection"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "चयनित पाठ के नियम",
|
||||
"No selected text replacement rules": "चयनित पाठ के लिए कोई प्रतिस्थापन नियम नहीं हैं",
|
||||
"Book Specific Rules": "पुस्तक-विशिष्ट नियम",
|
||||
"No book-level replacement rules": "पुस्तक स्तर पर कोई प्रतिस्थापन नियम नहीं हैं"
|
||||
"No book-level replacement rules": "पुस्तक स्तर पर कोई प्रतिस्थापन नियम नहीं हैं",
|
||||
"Disable Quick Action": "त्वरित क्रिया अक्षम करें",
|
||||
"Enable Quick Action on Selection": "चयन पर त्वरित क्रिया सक्षम करें",
|
||||
"None": "कोई नहीं",
|
||||
"Annotation Tools": "टिप्पणी उपकरण",
|
||||
"Enable Quick Actions": "त्वरित क्रियाएँ सक्षम करें",
|
||||
"Quick Action": "त्वरित क्रिया",
|
||||
"Copy to Notebook": "नोटबुक में कॉपी करें",
|
||||
"Copy text after selection": "पाठ कॉपी करें चयन के बाद",
|
||||
"Highlight text after selection": "चयन के बाद पाठ हाइलाइट करें",
|
||||
"Annotate text after selection": "चयन के बाद पाठ पर टिप्पणी करें",
|
||||
"Search text after selection": "चयन के बाद पाठ खोजें",
|
||||
"Look up text in dictionary after selection": "चयन के बाद शब्दकोश में पाठ देखें",
|
||||
"Look up text in Wikipedia after selection": "चयन के बाद विकिपीडिया में पाठ देखें",
|
||||
"Translate text after selection": "चयन के बाद पाठ का अनुवाद करें",
|
||||
"Read text aloud after selection": "चयन के बाद पाठ को जोर से पढ़ें",
|
||||
"Proofread text after selection": "चयन के बाद पाठ को प्रूफरीड करें"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "Aturan teks terpilih",
|
||||
"No selected text replacement rules": "Tidak ada aturan penggantian untuk teks terpilih",
|
||||
"Book Specific Rules": "Aturan khusus buku",
|
||||
"No book-level replacement rules": "Tidak ada aturan penggantian tingkat buku"
|
||||
"No book-level replacement rules": "Tidak ada aturan penggantian tingkat buku",
|
||||
"Disable Quick Action": "Nonaktifkan Aksi Cepat",
|
||||
"Enable Quick Action on Selection": "Aktifkan Aksi Cepat saat memilih",
|
||||
"None": "Tidak ada",
|
||||
"Annotation Tools": "Alat Anotasi",
|
||||
"Enable Quick Actions": "Aktifkan Aksi Cepat",
|
||||
"Quick Action": "Aksi Cepat",
|
||||
"Copy to Notebook": "Salin ke Buku Catatan",
|
||||
"Copy text after selection": "Salin teks setelah pemilihan",
|
||||
"Highlight text after selection": "Sorot teks setelah pemilihan",
|
||||
"Annotate text after selection": "Anotasi teks setelah pemilihan",
|
||||
"Search text after selection": "Cari teks setelah pemilihan",
|
||||
"Look up text in dictionary after selection": "Cari teks di kamus setelah pemilihan",
|
||||
"Look up text in Wikipedia after selection": "Cari teks di Wikipedia setelah pemilihan",
|
||||
"Translate text after selection": "Terjemahkan teks setelah pemilihan",
|
||||
"Read text aloud after selection": "Bacakan teks setelah pemilihan",
|
||||
"Proofread text after selection": "Periksa teks setelah pemilihan"
|
||||
}
|
||||
|
||||
@@ -794,5 +794,21 @@
|
||||
"Selected Text Rules": "Regole per il testo selezionato",
|
||||
"No selected text replacement rules": "Nessuna regola di sostituzione per il testo selezionato",
|
||||
"Book Specific Rules": "Regole specifiche del libro",
|
||||
"No book-level replacement rules": "Nessuna regola di sostituzione a livello di libro"
|
||||
"No book-level replacement rules": "Nessuna regola di sostituzione a livello di libro",
|
||||
"Disable Quick Action": "Disattiva azione rapida",
|
||||
"Enable Quick Action on Selection": "Attiva azione rapida sulla selezione",
|
||||
"None": "Nessuno",
|
||||
"Annotation Tools": "Strumenti di annotazione",
|
||||
"Enable Quick Actions": "Attiva azioni rapide",
|
||||
"Quick Action": "Azione rapida",
|
||||
"Copy to Notebook": "Copia nel taccuino",
|
||||
"Copy text after selection": "Copia testo dopo la selezione",
|
||||
"Highlight text after selection": "Evidenzia testo dopo la selezione",
|
||||
"Annotate text after selection": "Annota testo dopo la selezione",
|
||||
"Search text after selection": "Cerca testo dopo la selezione",
|
||||
"Look up text in dictionary after selection": "Cerca testo nel dizionario dopo la selezione",
|
||||
"Look up text in Wikipedia after selection": "Cerca testo in Wikipedia dopo la selezione",
|
||||
"Translate text after selection": "Traduci testo dopo la selezione",
|
||||
"Read text aloud after selection": "Leggi ad alta voce il testo dopo la selezione",
|
||||
"Proofread text after selection": "Correggi il testo dopo la selezione"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "選択テキストのルール",
|
||||
"No selected text replacement rules": "選択されたテキストの置換ルールはありません",
|
||||
"Book Specific Rules": "書籍別ルール",
|
||||
"No book-level replacement rules": "書籍レベルの置換ルールはありません"
|
||||
"No book-level replacement rules": "書籍レベルの置換ルールはありません",
|
||||
"Disable Quick Action": "クイックアクションを無効にする",
|
||||
"Enable Quick Action on Selection": "選択時にクイックアクションを有効にする",
|
||||
"None": "なし",
|
||||
"Annotation Tools": "注釈ツール",
|
||||
"Enable Quick Actions": "クイックアクションを有効にする",
|
||||
"Quick Action": "クイックアクション",
|
||||
"Copy to Notebook": "ノートにコピー",
|
||||
"Copy text after selection": "選択後のテキストをコピー",
|
||||
"Highlight text after selection": "選択後のテキストをハイライト",
|
||||
"Annotate text after selection": "選択後のテキストに注釈を付ける",
|
||||
"Search text after selection": "選択後のテキストを検索",
|
||||
"Look up text in dictionary after selection": "選択後のテキストを辞書で調べる",
|
||||
"Look up text in Wikipedia after selection": "選択後のテキストをWikipediaで調べる",
|
||||
"Translate text after selection": "選択後のテキストを翻訳する",
|
||||
"Read text aloud after selection": "選択後のテキストを音読する",
|
||||
"Proofread text after selection": "選択後のテキストを校正する"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "선택한 텍스트 규칙",
|
||||
"No selected text replacement rules": "선택한 텍스트에 대한 대체 규칙이 없습니다",
|
||||
"Book Specific Rules": "책별 규칙",
|
||||
"No book-level replacement rules": "책 수준의 대체 규칙이 없습니다"
|
||||
"No book-level replacement rules": "책 수준의 대체 규칙이 없습니다",
|
||||
"Disable Quick Action": "빠른 작업 비활성화",
|
||||
"Enable Quick Action on Selection": "선택 시 빠른 작업 활성화",
|
||||
"None": "없음",
|
||||
"Annotation Tools": "주석 도구",
|
||||
"Enable Quick Actions": "빠른 작업 활성화",
|
||||
"Quick Action": "빠른 작업",
|
||||
"Copy to Notebook": "노트에 복사",
|
||||
"Copy text after selection": "선택 후 텍스트 복사",
|
||||
"Highlight text after selection": "선택 후 텍스트 강조",
|
||||
"Annotate text after selection": "선택 후 텍스트 주석 달기",
|
||||
"Search text after selection": "선택 후 텍스트 검색",
|
||||
"Look up text in dictionary after selection": "선택 후 텍스트를 사전에서 찾기",
|
||||
"Look up text in Wikipedia after selection": "선택 후 텍스트를 위키피디아에서 찾기",
|
||||
"Translate text after selection": "선택 후 텍스트 번역",
|
||||
"Read text aloud after selection": "선택 후 텍스트 음성 읽기",
|
||||
"Proofread text after selection": "선택 후 텍스트 교정"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "Peraturan teks dipilih",
|
||||
"No selected text replacement rules": "Tiada peraturan penggantian untuk teks dipilih",
|
||||
"Book Specific Rules": "Peraturan khusus buku",
|
||||
"No book-level replacement rules": "Tiada peraturan penggantian peringkat buku"
|
||||
"No book-level replacement rules": "Tiada peraturan penggantian peringkat buku",
|
||||
"Disable Quick Action": "Nyahaktifkan Tindakan Pantas",
|
||||
"Enable Quick Action on Selection": "Aktifkan Tindakan Pantas pada Pilihan",
|
||||
"None": "Tiada",
|
||||
"Annotation Tools": "Alat Anotasi",
|
||||
"Enable Quick Actions": "Aktifkan Tindakan Pantas",
|
||||
"Quick Action": "Tindakan Pantas",
|
||||
"Copy to Notebook": "Salin ke Buku Nota",
|
||||
"Copy text after selection": "Salin teks selepas pilihan",
|
||||
"Highlight text after selection": "Sorot teks selepas pilihan",
|
||||
"Annotate text after selection": "Anotasi teks selepas pilihan",
|
||||
"Search text after selection": "Cari teks selepas pilihan",
|
||||
"Look up text in dictionary after selection": "Cari teks dalam kamus selepas pilihan",
|
||||
"Look up text in Wikipedia after selection": "Cari teks dalam Wikipedia selepas pilihan",
|
||||
"Translate text after selection": "Terjemah teks selepas pilihan",
|
||||
"Read text aloud after selection": "Baca teks dengan kuat selepas pilihan",
|
||||
"Proofread text after selection": "Semak teks selepas pilihan"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "Regels voor geselecteerde tekst",
|
||||
"No selected text replacement rules": "Geen vervangingsregels voor geselecteerde tekst",
|
||||
"Book Specific Rules": "Boekspecifieke regels",
|
||||
"No book-level replacement rules": "Geen vervangingsregels op boekniveau"
|
||||
"No book-level replacement rules": "Geen vervangingsregels op boekniveau",
|
||||
"Disable Quick Action": "Snelle actie uitschakelen",
|
||||
"Enable Quick Action on Selection": "Snelle actie bij selectie inschakelen",
|
||||
"None": "Geen",
|
||||
"Annotation Tools": "Annotatiehulpmiddelen",
|
||||
"Enable Quick Actions": "Snelle acties inschakelen",
|
||||
"Quick Action": "Snelle actie",
|
||||
"Copy to Notebook": "Kopiëren naar notitieboek",
|
||||
"Copy text after selection": "Kopieer tekst na selectie",
|
||||
"Highlight text after selection": "Markeer tekst na selectie",
|
||||
"Annotate text after selection": "Annoteren tekst na selectie",
|
||||
"Search text after selection": "Zoek tekst na selectie",
|
||||
"Look up text in dictionary after selection": "Zoek tekst op in woordenboek na selectie",
|
||||
"Look up text in Wikipedia after selection": "Zoek tekst op in Wikipedia na selectie",
|
||||
"Translate text after selection": "Vertaal tekst na selectie",
|
||||
"Read text aloud after selection": "Lees tekst hardop na selectie",
|
||||
"Proofread text after selection": "Corrigeer tekst na selectie"
|
||||
}
|
||||
|
||||
@@ -804,5 +804,21 @@
|
||||
"Selected Text Rules": "Reguły dla zaznaczonego tekstu",
|
||||
"No selected text replacement rules": "Brak reguł zastępowania dla zaznaczonego tekstu",
|
||||
"Book Specific Rules": "Reguły specyficzne dla książki",
|
||||
"No book-level replacement rules": "Brak reguł zastępowania na poziomie książki"
|
||||
"No book-level replacement rules": "Brak reguł zastępowania na poziomie książki",
|
||||
"Disable Quick Action": "Wyłącz szybką akcję",
|
||||
"Enable Quick Action on Selection": "Włącz szybką akcję przy zaznaczeniu",
|
||||
"None": "Brak",
|
||||
"Annotation Tools": "Narzędzia do adnotacji",
|
||||
"Enable Quick Actions": "Włącz szybkie akcje",
|
||||
"Quick Action": "Szybka akcja",
|
||||
"Copy to Notebook": "Kopiuj do notatnika",
|
||||
"Copy text after selection": "Kopiuj zaznaczony tekst",
|
||||
"Highlight text after selection": "Podświetl zaznaczony tekst",
|
||||
"Annotate text after selection": "Dodaj adnotację do zaznaczonego tekstu",
|
||||
"Search text after selection": "Wyszukaj zaznaczony tekst",
|
||||
"Look up text in dictionary after selection": "Sprawdź zaznaczony tekst w słowniku",
|
||||
"Look up text in Wikipedia after selection": "Sprawdź zaznaczony tekst w Wikipedii",
|
||||
"Translate text after selection": "Przetłumacz zaznaczony tekst",
|
||||
"Read text aloud after selection": "Odczytaj zaznaczony tekst na głos",
|
||||
"Proofread text after selection": "Sprawdź zaznaczony tekst"
|
||||
}
|
||||
|
||||
@@ -794,5 +794,21 @@
|
||||
"Selected Text Rules": "Regras do texto selecionado",
|
||||
"No selected text replacement rules": "Não existem regras de substituição para o texto selecionado",
|
||||
"Book Specific Rules": "Regras específicas do livro",
|
||||
"No book-level replacement rules": "Não existem regras de substituição ao nível do livro"
|
||||
"No book-level replacement rules": "Não existem regras de substituição ao nível do livro",
|
||||
"Disable Quick Action": "Desativar Ação Rápida",
|
||||
"Enable Quick Action on Selection": "Ativar Ação Rápida na Seleção",
|
||||
"None": "Nenhum",
|
||||
"Annotation Tools": "Ferramentas de Anotação",
|
||||
"Enable Quick Actions": "Ativar Ações Rápidas",
|
||||
"Quick Action": "Ação Rápida",
|
||||
"Copy to Notebook": "Copiar para o Caderno",
|
||||
"Copy text after selection": "Copiar texto após a seleção",
|
||||
"Highlight text after selection": "Destacar texto após a seleção",
|
||||
"Annotate text after selection": "Anotar texto após a seleção",
|
||||
"Search text after selection": "Pesquisar texto após a seleção",
|
||||
"Look up text in dictionary after selection": "Procurar texto no dicionário após a seleção",
|
||||
"Look up text in Wikipedia after selection": "Procurar texto na Wikipedia após a seleção",
|
||||
"Translate text after selection": "Traduzir texto após a seleção",
|
||||
"Read text aloud after selection": "Ler texto em voz alta após a seleção",
|
||||
"Proofread text after selection": "Revisar texto após a seleção"
|
||||
}
|
||||
|
||||
@@ -804,5 +804,21 @@
|
||||
"Selected Text Rules": "Правила для выделенного текста",
|
||||
"No selected text replacement rules": "Нет правил замены для выделенного текста",
|
||||
"Book Specific Rules": "Правила для конкретной книги",
|
||||
"No book-level replacement rules": "Нет правил замены на уровне книги"
|
||||
"No book-level replacement rules": "Нет правил замены на уровне книги",
|
||||
"Disable Quick Action": "Отключить быстрые действия",
|
||||
"Enable Quick Action on Selection": "Включить быстрые действия при выборе",
|
||||
"None": "Нет",
|
||||
"Annotation Tools": "Инструменты для аннотаций",
|
||||
"Enable Quick Actions": "Включить быстрые действия",
|
||||
"Quick Action": "Быстрое действие",
|
||||
"Copy to Notebook": "Скопировать в блокнот",
|
||||
"Copy text after selection": "Копировать текст после выделения",
|
||||
"Highlight text after selection": "Выделить текст после выделения",
|
||||
"Annotate text after selection": "Аннотировать текст после выделения",
|
||||
"Search text after selection": "Искать текст после выделения",
|
||||
"Look up text in dictionary after selection": "Искать текст в словаре после выделения",
|
||||
"Look up text in Wikipedia after selection": "Искать текст в Википедии после выделения",
|
||||
"Translate text after selection": "Перевести текст после выделения",
|
||||
"Read text aloud after selection": "Прочитать текст вслух после выделения",
|
||||
"Proofread text after selection": "Корректировать текст после выделения"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "තේරූ පෙළ සඳහා නියමයන්",
|
||||
"No selected text replacement rules": "තේරූ පෙළ සඳහා ප්රතිස්ථාපන නියමයන් නොමැත",
|
||||
"Book Specific Rules": "පොතට විශේෂිත නියමයන්",
|
||||
"No book-level replacement rules": "පොත් මට්ටමේ ප්රතිස්ථාපන නියමයන් නොමැත"
|
||||
"No book-level replacement rules": "පොත් මට්ටමේ ප්රතිස්ථාපන නියමයන් නොමැත",
|
||||
"Disable Quick Action": "තට්ටු ක්රියාව අක්රිය කරන්න",
|
||||
"Enable Quick Action on Selection": "තෝරා ගැනීමේදී තට්ටු ක්රියාව සක්රීය කරන්න",
|
||||
"None": "කිසිවක් නැත",
|
||||
"Annotation Tools": "සටහන් මෙවලම්",
|
||||
"Enable Quick Actions": "තට්ටු ක්රියාවන් සක්රීය කරන්න",
|
||||
"Quick Action": "තට්ටු ක්රියාව",
|
||||
"Copy to Notebook": "සටහන් පොතට පිටපත් කරන්න",
|
||||
"Copy text after selection": "තේරීමෙන් පසු පෙළ පිටපත් කරන්න",
|
||||
"Highlight text after selection": "තේරීමෙන් පසු පෙළ හයිලයිට් කරන්න",
|
||||
"Annotate text after selection": "තේරීමෙන් පසු පෙළ සටහන් කරන්න",
|
||||
"Search text after selection": "තේරීමෙන් පසු පෙළ සෙවීම",
|
||||
"Look up text in dictionary after selection": "තේරීමෙන් පසු ශබ්දකෝෂයේ පෙළ සෙවීම",
|
||||
"Look up text in Wikipedia after selection": "තේරීමෙන් පසු විකිපීඩියාවේ පෙළ සෙවීම",
|
||||
"Translate text after selection": "තේරීමෙන් පසු පෙළ පරිවර්තනය කරන්න",
|
||||
"Read text aloud after selection": "තේරීමෙන් පසු පෙළ උච්චාරණය කරන්න",
|
||||
"Proofread text after selection": "තේරීමෙන් පසු පෙළ සංශෝධනය කරන්න"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "Regler för markerad text",
|
||||
"No selected text replacement rules": "Inga ersättningsregler för markerad text",
|
||||
"Book Specific Rules": "Bokspecifika regler",
|
||||
"No book-level replacement rules": "Inga ersättningsregler på boknivå"
|
||||
"No book-level replacement rules": "Inga ersättningsregler på boknivå",
|
||||
"Disable Quick Action": "Inaktivera snabbåtgärd",
|
||||
"Enable Quick Action on Selection": "Aktivera snabbåtgärd vid val",
|
||||
"None": "Ingen",
|
||||
"Annotation Tools": "Anteckningsverktyg",
|
||||
"Enable Quick Actions": "Aktivera snabba åtgärder",
|
||||
"Quick Action": "Snabbåtgärd",
|
||||
"Copy to Notebook": "Kopiera till anteckningsbok",
|
||||
"Copy text after selection": "Kopiera text efter markering",
|
||||
"Highlight text after selection": "Markera text efter markering",
|
||||
"Annotate text after selection": "Anteckna text efter markering",
|
||||
"Search text after selection": "Sök text efter markering",
|
||||
"Look up text in dictionary after selection": "Slå upp text i ordbok efter markering",
|
||||
"Look up text in Wikipedia after selection": "Slå upp text i Wikipedia efter markering",
|
||||
"Translate text after selection": "Översätt text efter markering",
|
||||
"Read text aloud after selection": "Läs upp text efter markering",
|
||||
"Proofread text after selection": "Korrekturläs text efter markering"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "தேர்ந்தெடுக்கப்பட்ட உரைக்கான விதிகள்",
|
||||
"No selected text replacement rules": "தேர்ந்தெடுக்கப்பட்ட உரைக்கான மாற்று விதிகள் இல்லை",
|
||||
"Book Specific Rules": "புத்தகத்திற்கு குறிப்பிட்ட விதிகள்",
|
||||
"No book-level replacement rules": "புத்தக மட்டத்தில் மாற்று விதிகள் இல்லை"
|
||||
"No book-level replacement rules": "புத்தக மட்டத்தில் மாற்று விதிகள் இல்லை",
|
||||
"Disable Quick Action": "விரைவு செயலை முடக்கு",
|
||||
"Enable Quick Action on Selection": "தேர்வில் விரைவு செயலை இயக்கு",
|
||||
"None": "எதுவும் இல்லை",
|
||||
"Annotation Tools": "கருத்துரை கருவிகள்",
|
||||
"Enable Quick Actions": "விரைவு செயல்களை இயக்கு",
|
||||
"Quick Action": "விரைவு செயல்",
|
||||
"Copy to Notebook": "குறிப்பேட்டியில் நகலெடு",
|
||||
"Copy text after selection": "உரையை தேர்வுக்குப் பிறகு நகலெடு",
|
||||
"Highlight text after selection": "உரையை தேர்வுக்குப் பிறகு முத்திரை இடு",
|
||||
"Annotate text after selection": "உரையை தேர்வுக்குப் பிறகு கருத்துரை இடு",
|
||||
"Search text after selection": "உரையை தேர்வுக்குப் பிறகு தேடு",
|
||||
"Look up text in dictionary after selection": "தேர்வுக்குப் பிறகு அகராதியில் உரையைத் தேடு",
|
||||
"Look up text in Wikipedia after selection": "தேர்வுக்குப் பிறகு விக்கிப்பீடியாவில் உரையைத் தேடு",
|
||||
"Translate text after selection": "தேர்வுக்குப் பிறகு உரையை மொழிபெயர்",
|
||||
"Read text aloud after selection": "தேர்வுக்குப் பிறகு உரையை ஓதுக",
|
||||
"Proofread text after selection": "தேர்வுக்குப் பிறகு உரையை திருத்துக"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "กฎสำหรับข้อความที่เลือก",
|
||||
"No selected text replacement rules": "ไม่มีกฎการแทนที่สำหรับข้อความที่เลือก",
|
||||
"Book Specific Rules": "กฎเฉพาะของหนังสือ",
|
||||
"No book-level replacement rules": "ไม่มีกฎการแทนที่ระดับหนังสือ"
|
||||
"No book-level replacement rules": "ไม่มีกฎการแทนที่ระดับหนังสือ",
|
||||
"Disable Quick Action": "ปิดใช้งานการดำเนินการด่วน",
|
||||
"Enable Quick Action on Selection": "เปิดใช้งานการดำเนินการด่วนเมื่อเลือก",
|
||||
"None": "ไม่มี",
|
||||
"Annotation Tools": "เครื่องมือหมายเหตุ",
|
||||
"Enable Quick Actions": "เปิดใช้งานการดำเนินการด่วน",
|
||||
"Quick Action": "การดำเนินการด่วน",
|
||||
"Copy to Notebook": "คัดลอกไปยังสมุดบันทึก",
|
||||
"Copy text after selection": "คัดลอกข้อความหลังการเลือก",
|
||||
"Highlight text after selection": "ไฮไลต์ข้อความหลังการเลือก",
|
||||
"Annotate text after selection": "เพิ่มหมายเหตุข้อความหลังการเลือก",
|
||||
"Search text after selection": "ค้นหาข้อความหลังการเลือก",
|
||||
"Look up text in dictionary after selection": "ค้นหาข้อความในพจนานุกรมหลังการเลือก",
|
||||
"Look up text in Wikipedia after selection": "ค้นหาข้อความในวิกิพีเดียหลังการเลือก",
|
||||
"Translate text after selection": "แปลข้อความหลังการเลือก",
|
||||
"Read text aloud after selection": "อ่านข้อความออกเสียงหลังการเลือก",
|
||||
"Proofread text after selection": "ตรวจทานข้อความหลังการเลือก"
|
||||
}
|
||||
|
||||
@@ -784,5 +784,21 @@
|
||||
"Selected Text Rules": "Seçili Metin Kuralları",
|
||||
"No selected text replacement rules": "Seçili metin için değiştirme kuralı yok",
|
||||
"Book Specific Rules": "Kitaba Özel Kurallar",
|
||||
"No book-level replacement rules": "Kitap düzeyinde değiştirme kuralı yok"
|
||||
"No book-level replacement rules": "Kitap düzeyinde değiştirme kuralı yok",
|
||||
"Disable Quick Action": "Hızlı işlemi devre dışı bırak",
|
||||
"Enable Quick Action on Selection": "Seçimde hızlı işlemi etkinleştir",
|
||||
"None": "Hiçbiri",
|
||||
"Annotation Tools": "Not araçları",
|
||||
"Enable Quick Actions": "Hızlı işlemleri etkinleştir",
|
||||
"Quick Action": "Hızlı işlem",
|
||||
"Copy to Notebook": "Deftere kopyala",
|
||||
"Copy text after selection": "Seçimden sonra metni kopyala",
|
||||
"Highlight text after selection": "Seçimden sonra metni vurgula",
|
||||
"Annotate text after selection": "Seçimden sonra metni not al",
|
||||
"Search text after selection": "Seçimden sonra metni ara",
|
||||
"Look up text in dictionary after selection": "Seçimden sonra metni sözlükte ara",
|
||||
"Look up text in Wikipedia after selection": "Seçimden sonra metni Vikipedya'da ara",
|
||||
"Translate text after selection": "Seçimden sonra metni çevir",
|
||||
"Read text aloud after selection": "Seçimden sonra metni sesli oku",
|
||||
"Proofread text after selection": "Seçimden sonra metni düzelt"
|
||||
}
|
||||
|
||||
@@ -804,5 +804,21 @@
|
||||
"Selected Text Rules": "Правила для виділеного тексту",
|
||||
"No selected text replacement rules": "Немає правил заміни для виділеного тексту",
|
||||
"Book Specific Rules": "Правила для конкретної книги",
|
||||
"No book-level replacement rules": "Немає правил заміни на рівні книги"
|
||||
"No book-level replacement rules": "Немає правил заміни на рівні книги",
|
||||
"Disable Quick Action": "Вимкнути швидку дію",
|
||||
"Enable Quick Action on Selection": "Увімкнути швидку дію при виборі",
|
||||
"None": "Жоден",
|
||||
"Annotation Tools": "Інструменти анотацій",
|
||||
"Enable Quick Actions": "Увімкнути швидкі дії",
|
||||
"Quick Action": "Швидка дія",
|
||||
"Copy to Notebook": "Скопіювати до блокнота",
|
||||
"Copy text after selection": "Скопіювати текст після виділення",
|
||||
"Highlight text after selection": "Виділити текст після виділення",
|
||||
"Annotate text after selection": "Додати анотацію до тексту після виділення",
|
||||
"Search text after selection": "Шукати текст після виділення",
|
||||
"Look up text in dictionary after selection": "Шукати текст у словнику після виділення",
|
||||
"Look up text in Wikipedia after selection": "Шукати текст у Вікіпедії після виділення",
|
||||
"Translate text after selection": "Перекласти текст після виділення",
|
||||
"Read text aloud after selection": "Прочитати текст вголос після виділення",
|
||||
"Proofread text after selection": "Вичитати текст після виділення"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "Quy tắc cho văn bản đã chọn",
|
||||
"No selected text replacement rules": "Không có quy tắc thay thế cho văn bản đã chọn",
|
||||
"Book Specific Rules": "Quy tắc dành riêng cho sách",
|
||||
"No book-level replacement rules": "Không có quy tắc thay thế ở cấp sách"
|
||||
"No book-level replacement rules": "Không có quy tắc thay thế ở cấp sách",
|
||||
"Disable Quick Action": "Vô hiệu hóa Hành động Nhanh",
|
||||
"Enable Quick Action on Selection": "Bật Hành động Nhanh khi chọn",
|
||||
"None": "Không có",
|
||||
"Annotation Tools": "Công cụ chú thích",
|
||||
"Enable Quick Actions": "Bật Hành động Nhanh",
|
||||
"Quick Action": "Hành động Nhanh",
|
||||
"Copy to Notebook": "Sao chép vào Sổ tay",
|
||||
"Copy text after selection": "Sao chép văn bản sau khi chọn",
|
||||
"Highlight text after selection": "Đánh dấu văn bản sau khi chọn",
|
||||
"Annotate text after selection": "Chú thích văn bản sau khi chọn",
|
||||
"Search text after selection": "Tìm kiếm văn bản sau khi chọn",
|
||||
"Look up text in dictionary after selection": "Tra cứu văn bản trong từ điển sau khi chọn",
|
||||
"Look up text in Wikipedia after selection": "Tra cứu văn bản trong Wikipedia sau khi chọn",
|
||||
"Translate text after selection": "Dịch văn bản sau khi chọn",
|
||||
"Read text aloud after selection": "Đọc to văn bản sau khi chọn",
|
||||
"Proofread text after selection": "Hiệu đính văn bản sau khi chọn"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "选中文本规则",
|
||||
"No selected text replacement rules": "暂无选中文本的替换规则",
|
||||
"Book Specific Rules": "书籍范围规则",
|
||||
"No book-level replacement rules": "暂无书籍级别的替换规则"
|
||||
"No book-level replacement rules": "暂无书籍级别的替换规则",
|
||||
"Disable Quick Action": "禁用快速操作",
|
||||
"Enable Quick Action on Selection": "在选择时启用快速操作",
|
||||
"None": "无",
|
||||
"Annotation Tools": "注释工具",
|
||||
"Enable Quick Actions": "启用快捷操作",
|
||||
"Quick Action": "快捷操作",
|
||||
"Copy to Notebook": "复制到笔记本",
|
||||
"Copy text after selection": "复制选中文本",
|
||||
"Highlight text after selection": "划线选中文本",
|
||||
"Annotate text after selection": "注释选中文本",
|
||||
"Search text after selection": "搜索选中文本",
|
||||
"Look up text in dictionary after selection": "在字典中查找选中文本",
|
||||
"Look up text in Wikipedia after selection": "在维基百科中查找选中文本",
|
||||
"Translate text after selection": "翻译选中文本",
|
||||
"Read text aloud after selection": "朗读选中文本",
|
||||
"Proofread text after selection": "校对选中文本"
|
||||
}
|
||||
|
||||
@@ -774,5 +774,21 @@
|
||||
"Selected Text Rules": "已選取文字規則",
|
||||
"No selected text replacement rules": "沒有已選取文字的取代規則",
|
||||
"Book Specific Rules": "書籍層級規則",
|
||||
"No book-level replacement rules": "沒有書籍層級的取代規則"
|
||||
"No book-level replacement rules": "沒有書籍層級的取代規則",
|
||||
"Disable Quick Action": "停用快速操作",
|
||||
"Enable Quick Action on Selection": "選取時啟用快速操作",
|
||||
"None": "無",
|
||||
"Annotation Tools": "註解工具",
|
||||
"Enable Quick Actions": "啟用快速操作",
|
||||
"Quick Action": "快速操作",
|
||||
"Copy to Notebook": "複製到筆記本",
|
||||
"Copy text after selection": "複製選取後的文字",
|
||||
"Highlight text after selection": "劃線選取後的文字",
|
||||
"Annotate text after selection": "註解選取後的文字",
|
||||
"Search text after selection": "搜尋選取後的文字",
|
||||
"Look up text in dictionary after selection": "在字典中查找選取後的文字",
|
||||
"Look up text in Wikipedia after selection": "在維基百科中查找選取後的文字",
|
||||
"Translate text after selection": "翻譯選取後的文字",
|
||||
"Read text aloud after selection": "朗讀選取後的文字",
|
||||
"Proofread text after selection": "校對選取後的文字"
|
||||
}
|
||||
|
||||
+43
@@ -3,6 +3,7 @@ package com.bilingify.readest
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.webkit.WebView
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
@@ -47,6 +48,48 @@ class MainActivity : TauriActivity(), KeyDownInterceptor {
|
||||
interceptBackKeyEnabled = enabled
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
||||
val action = when (event.actionMasked) {
|
||||
MotionEvent.ACTION_DOWN -> "touchstart"
|
||||
MotionEvent.ACTION_UP -> "touchend"
|
||||
MotionEvent.ACTION_CANCEL -> "touchcancel"
|
||||
MotionEvent.ACTION_POINTER_DOWN -> "touchstart"
|
||||
MotionEvent.ACTION_POINTER_UP -> "touchend"
|
||||
else -> null
|
||||
}
|
||||
|
||||
action?.let { eventType ->
|
||||
val pointerIndex = event.actionIndex
|
||||
val pointerId = event.getPointerId(pointerIndex)
|
||||
val x = event.getX(pointerIndex)
|
||||
val y = event.getY(pointerIndex)
|
||||
val pressure = event.getPressure(pointerIndex)
|
||||
|
||||
wv.evaluateJavascript(
|
||||
"""
|
||||
try {
|
||||
if (window.onNativeTouch) {
|
||||
window.onNativeTouch({
|
||||
type: "$eventType",
|
||||
pointerId: $pointerId,
|
||||
x: $x,
|
||||
y: $y,
|
||||
pressure: $pressure,
|
||||
pointerCount: ${event.pointerCount},
|
||||
timestamp: ${event.eventTime}
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Native touch error:', err);
|
||||
}
|
||||
""".trimIndent(),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
return super.dispatchTouchEvent(event)
|
||||
}
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
if (event.action == KeyEvent.ACTION_DOWN) {
|
||||
val keyCode = event.keyCode
|
||||
|
||||
@@ -8,11 +8,18 @@ import { useThemeStore } from '@/store/themeStore';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useSidebarStore } from '@/store/sidebarStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useTrafficLightStore } from '@/store/trafficLightStore';
|
||||
import { useTrafficLight } from '@/hooks/useTrafficLight';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import WindowButtons from '@/components/WindowButtons';
|
||||
import { getHighlightColorHex } from '../utils/annotatorUtil';
|
||||
import { annotationToolQuickActions } from './annotator/AnnotationTools';
|
||||
import { AnnotationToolType } from '@/types/annotator';
|
||||
import { saveViewSettings } from '@/helpers/settings';
|
||||
import { HighlighterIcon } from '@/components/HighlighterIcon';
|
||||
import Dropdown from '@/components/Dropdown';
|
||||
import WindowButtons from '@/components/WindowButtons';
|
||||
import QuickActionMenu from './annotator/QuickActionMenu';
|
||||
import SidebarToggler from './SidebarToggler';
|
||||
import BookmarkToggler from './BookmarkToggler';
|
||||
import NotebookToggler from './NotebookToggler';
|
||||
@@ -38,12 +45,15 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
|
||||
onCloseBook,
|
||||
}) => {
|
||||
const _ = useTranslation();
|
||||
const { appService } = useEnv();
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { settings } = useSettingsStore();
|
||||
const { isTrafficLightVisible } = useTrafficLight();
|
||||
const { trafficLightInFullscreen, setTrafficLightVisibility } = useTrafficLightStore();
|
||||
const { bookKeys, hoveredBookKey, getView, setHoveredBookKey } = useReaderStore();
|
||||
const { systemUIVisible, statusBarHeight } = useThemeStore();
|
||||
const { bookKeys, hoveredBookKey } = useReaderStore();
|
||||
const { isDarkMode, systemUIVisible, statusBarHeight } = useThemeStore();
|
||||
const { isSideBarVisible } = useSidebarStore();
|
||||
const { getView, getViewSettings, setHoveredBookKey } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey);
|
||||
|
||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||
const view = getView(bookKey);
|
||||
@@ -54,11 +64,27 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
|
||||
const docs = view?.renderer.getContents() ?? [];
|
||||
const pointerInDoc = docs.some(({ doc }) => doc.body.style.cursor === 'pointer');
|
||||
|
||||
const enableAnnotationQuickActions = viewSettings?.enableAnnotationQuickActions;
|
||||
const annotationQuickActionButton =
|
||||
annotationToolQuickActions.find(
|
||||
(button) => button.type === viewSettings?.annotationQuickAction,
|
||||
) || annotationToolQuickActions[0]!;
|
||||
const annotationQuickAction = viewSettings?.annotationQuickAction;
|
||||
const AnnotationToolQuickActionIcon = annotationQuickActionButton.Icon;
|
||||
const highlightStyle = settings.globalReadSettings.highlightStyle;
|
||||
const highlightColor = settings.globalReadSettings.highlightStyles[highlightStyle];
|
||||
const highlightHexColor = getHighlightColorHex(settings, highlightColor);
|
||||
|
||||
const handleToggleDropdown = (isOpen: boolean) => {
|
||||
setIsDropdownOpen(isOpen);
|
||||
if (!isOpen) setHoveredBookKey('');
|
||||
};
|
||||
|
||||
const handleAnnotationQuickActionSelect = (action: AnnotationToolType | null) => {
|
||||
if (viewSettings?.annotationQuickAction === action) action = null;
|
||||
saveViewSettings(envConfig, bookKey, 'annotationQuickAction', action, false, true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!appService?.hasTrafficLight) return;
|
||||
if (isSideBarVisible) return;
|
||||
@@ -141,6 +167,40 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
|
||||
</div>
|
||||
<BookmarkToggler bookKey={bookKey} />
|
||||
<TranslationToggler bookKey={bookKey} />
|
||||
{enableAnnotationQuickActions && (
|
||||
<Dropdown
|
||||
label={
|
||||
annotationQuickAction
|
||||
? _('Disable Quick Action')
|
||||
: _('Enable Quick Action on Selection')
|
||||
}
|
||||
className='exclude-title-bar-mousedown dropdown-bottom'
|
||||
buttonClassName={clsx(
|
||||
'btn btn-ghost h-8 min-h-8 w-8 p-0',
|
||||
viewSettings?.annotationQuickAction && 'bg-base-300/50',
|
||||
)}
|
||||
toggleButton={
|
||||
annotationQuickAction === 'highlight' || annotationQuickAction === null ? (
|
||||
<HighlighterIcon
|
||||
size={iconSize16}
|
||||
tipColor={annotationQuickAction === null ? '#8F8F8F' : highlightHexColor}
|
||||
tipStyle={{
|
||||
opacity: annotationQuickAction === null ? 0.3 : 0.5,
|
||||
mixBlendMode: isDarkMode ? 'screen' : 'multiply',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<AnnotationToolQuickActionIcon size={iconSize16} />
|
||||
)
|
||||
}
|
||||
onToggle={handleToggleDropdown}
|
||||
>
|
||||
<QuickActionMenu
|
||||
selectedAction={viewSettings.annotationQuickAction}
|
||||
onActionSelect={handleAnnotationQuickActionSelect}
|
||||
/>
|
||||
</Dropdown>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { Position } from '@/utils/sel';
|
||||
import { BookNote, HighlightColor, HighlightStyle } from '@/types/book';
|
||||
import Popup from '@/components/Popup';
|
||||
import PopupButton from './PopupButton';
|
||||
import AnnotationToolButton from './AnnotationToolButton';
|
||||
import AnnotationNotes from './AnnotationNotes';
|
||||
import HighlightOptions from './HighlightOptions';
|
||||
|
||||
@@ -69,7 +69,7 @@ const AnnotationPopup: React.FC<AnnotationPopupProps> = ({
|
||||
{buttons.map((button, index) => {
|
||||
if (button.visible === false) return null;
|
||||
return (
|
||||
<PopupButton
|
||||
<AnnotationToolButton
|
||||
key={index}
|
||||
showTooltip={!highlightOptionsVisible}
|
||||
tooltipText={button.tooltipText}
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import clsx from 'clsx';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
interface PopupButtonProps {
|
||||
interface AnnotationToolButtonProps {
|
||||
showTooltip: boolean;
|
||||
tooltipText: string;
|
||||
disabled?: boolean;
|
||||
@@ -9,7 +9,7 @@ interface PopupButtonProps {
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
const PopupButton: React.FC<PopupButtonProps> = ({
|
||||
const AnnotationToolButton: React.FC<AnnotationToolButtonProps> = ({
|
||||
showTooltip,
|
||||
tooltipText,
|
||||
disabled,
|
||||
@@ -40,4 +40,4 @@ const PopupButton: React.FC<PopupButtonProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default PopupButton;
|
||||
export default AnnotationToolButton;
|
||||
@@ -0,0 +1,92 @@
|
||||
import { IconType } from 'react-icons';
|
||||
import { FiSearch } from 'react-icons/fi';
|
||||
import { FiCopy } from 'react-icons/fi';
|
||||
import { PiHighlighterFill } from 'react-icons/pi';
|
||||
import { FaWikipediaW } from 'react-icons/fa';
|
||||
import { BsPencilSquare } from 'react-icons/bs';
|
||||
import { BsTranslate } from 'react-icons/bs';
|
||||
import { TbHexagonLetterD } from 'react-icons/tb';
|
||||
import { FaHeadphones } from 'react-icons/fa6';
|
||||
import { IoIosBuild } from 'react-icons/io';
|
||||
import { AnnotationToolType } from '@/types/annotator';
|
||||
import { stubTranslation as _ } from '@/utils/misc';
|
||||
|
||||
type AnnotationToolButton = {
|
||||
type: AnnotationToolType;
|
||||
label: string;
|
||||
tooltip: string;
|
||||
Icon: IconType;
|
||||
quickAction?: boolean;
|
||||
};
|
||||
|
||||
function createAnnotationToolButtons<T extends AnnotationToolType>(
|
||||
buttons: AnnotationToolType extends T
|
||||
? {
|
||||
[K in T]: {
|
||||
type: K;
|
||||
label: string;
|
||||
tooltip: string;
|
||||
Icon: IconType;
|
||||
quickAction?: boolean;
|
||||
};
|
||||
}[T][]
|
||||
: never,
|
||||
): AnnotationToolButton[] {
|
||||
return buttons;
|
||||
}
|
||||
|
||||
export const annotationToolButtons = createAnnotationToolButtons([
|
||||
{ type: 'copy', label: _('Copy'), tooltip: _('Copy text after selection'), Icon: FiCopy },
|
||||
{
|
||||
type: 'highlight',
|
||||
label: _('Highlight'),
|
||||
tooltip: _('Highlight text after selection'),
|
||||
Icon: PiHighlighterFill,
|
||||
quickAction: true,
|
||||
},
|
||||
{
|
||||
type: 'annotate',
|
||||
label: _('Annotate'),
|
||||
tooltip: _('Annotate text after selection'),
|
||||
Icon: BsPencilSquare,
|
||||
},
|
||||
{ type: 'search', label: _('Search'), tooltip: _('Search text after selection'), Icon: FiSearch },
|
||||
{
|
||||
type: 'dictionary',
|
||||
label: _('Dictionary'),
|
||||
tooltip: _('Look up text in dictionary after selection'),
|
||||
Icon: TbHexagonLetterD,
|
||||
quickAction: true,
|
||||
},
|
||||
{
|
||||
type: 'wikipedia',
|
||||
label: _('Wikipedia'),
|
||||
tooltip: _('Look up text in Wikipedia after selection'),
|
||||
Icon: FaWikipediaW,
|
||||
quickAction: true,
|
||||
},
|
||||
{
|
||||
type: 'translate',
|
||||
label: _('Translate'),
|
||||
tooltip: _('Translate text after selection'),
|
||||
Icon: BsTranslate,
|
||||
quickAction: true,
|
||||
},
|
||||
{
|
||||
type: 'tts',
|
||||
label: _('Speak'),
|
||||
tooltip: _('Read text aloud after selection'),
|
||||
Icon: FaHeadphones,
|
||||
quickAction: true,
|
||||
},
|
||||
{
|
||||
type: 'proofread',
|
||||
label: _('Proofread'),
|
||||
tooltip: _('Proofread text after selection'),
|
||||
Icon: IoIosBuild,
|
||||
},
|
||||
]);
|
||||
|
||||
export const annotationToolQuickActions = annotationToolButtons.filter(
|
||||
(button) => button.quickAction,
|
||||
);
|
||||
@@ -1,20 +1,12 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { FiSearch } from 'react-icons/fi';
|
||||
import { FiCopy } from 'react-icons/fi';
|
||||
import { PiHighlighterFill } from 'react-icons/pi';
|
||||
import { FaWikipediaW } from 'react-icons/fa';
|
||||
import { BsPencilSquare } from 'react-icons/bs';
|
||||
import { RiDeleteBinLine } from 'react-icons/ri';
|
||||
import { BsTranslate } from 'react-icons/bs';
|
||||
import { TbHexagonLetterD } from 'react-icons/tb';
|
||||
import { FaHeadphones } from 'react-icons/fa6';
|
||||
import { IoIosBuild } from 'react-icons/io';
|
||||
|
||||
import * as CFI from 'foliate-js/epubcfi.js';
|
||||
import { Overlayer } from 'foliate-js/overlayer.js';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { BookNote, BooknoteGroup, HighlightColor, HighlightStyle } from '@/types/book';
|
||||
import { NOTE_PREFIX } from '@/types/view';
|
||||
import { NativeTouchEventType } from '@/types/system';
|
||||
import { getOSPlatform, uniqueId } from '@/utils/misc';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
@@ -22,6 +14,7 @@ import { useReaderStore } from '@/store/readerStore';
|
||||
import { useNotebookStore } from '@/store/notebookStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { useDeviceControlStore } from '@/store/deviceStore';
|
||||
import { useFoliateEvents } from '../../hooks/useFoliateEvents';
|
||||
import { useNotesSync } from '../../hooks/useNotesSync';
|
||||
import { useTextSelector } from '../../hooks/useTextSelector';
|
||||
@@ -30,8 +23,9 @@ import { eventDispatcher } from '@/utils/event';
|
||||
import { findTocItemBS } from '@/utils/toc';
|
||||
import { throttle } from '@/utils/throttle';
|
||||
import { runSimpleCC } from '@/utils/simplecc';
|
||||
import { HIGHLIGHT_COLOR_HEX } from '@/services/constants';
|
||||
import { getWordCount } from '@/utils/word';
|
||||
import { getHighlightColorHex } from '../../utils/annotatorUtil';
|
||||
import { annotationToolButtons } from './AnnotationTools';
|
||||
import AnnotationPopup from './AnnotationPopup';
|
||||
import WiktionaryPopup from './WiktionaryPopup';
|
||||
import WikipediaPopup from './WikipediaPopup';
|
||||
@@ -46,6 +40,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const { getConfig, saveConfig, getBookData, updateBooknotes } = useBookDataStore();
|
||||
const { getProgress, getView, getViewsById, getViewSettings } = useReaderStore();
|
||||
const { setNotebookVisible, setNotebookNewAnnotation } = useNotebookStore();
|
||||
const { listenToNativeTouchEvents } = useDeviceControlStore();
|
||||
|
||||
useNotesSync(bookKey);
|
||||
|
||||
@@ -163,12 +158,8 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
[],
|
||||
);
|
||||
|
||||
const handleDismissPopupAndSelection = () => {
|
||||
handleDismissPopup();
|
||||
view?.deselect();
|
||||
};
|
||||
|
||||
const {
|
||||
isTextSelected,
|
||||
handleScroll,
|
||||
handleTouchStart,
|
||||
handleTouchEnd,
|
||||
@@ -180,6 +171,12 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
handleContextmenu,
|
||||
} = useTextSelector(bookKey, setSelection, handleDismissPopup);
|
||||
|
||||
const handleDismissPopupAndSelection = () => {
|
||||
handleDismissPopup();
|
||||
view?.deselect();
|
||||
isTextSelected.current = false;
|
||||
};
|
||||
|
||||
const onLoad = (event: Event) => {
|
||||
const detail = (event as CustomEvent).detail;
|
||||
const { doc, index } = detail;
|
||||
@@ -190,6 +187,21 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
setShowAnnotPopup(false);
|
||||
};
|
||||
|
||||
const handleNativeTouch = (event: CustomEvent) => {
|
||||
const ev = event.detail as NativeTouchEventType;
|
||||
if (ev.type === 'touchstart') {
|
||||
handleTouchStart();
|
||||
} else if (ev.type === 'touchend') {
|
||||
handleTouchEnd();
|
||||
handlePointerup(doc, index);
|
||||
}
|
||||
};
|
||||
|
||||
if (appService?.isAndroidApp) {
|
||||
listenToNativeTouchEvents();
|
||||
eventDispatcher.on('native-touch', handleNativeTouch);
|
||||
}
|
||||
|
||||
// Attach generic selection listeners for all formats, including PDF.
|
||||
// For PDF we only guarantee Copy & Translate; highlight/annotate may be limited by CFI support.
|
||||
view?.renderer?.addEventListener('scroll', handleScroll);
|
||||
@@ -204,7 +216,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
detail.doc?.addEventListener('pointerup', (ev: PointerEvent) =>
|
||||
handlePointerup(doc, index, ev),
|
||||
);
|
||||
detail.doc?.addEventListener('selectionchange', () => handleSelectionchange(doc, index));
|
||||
detail.doc?.addEventListener('selectionchange', () => handleSelectionchange(doc));
|
||||
|
||||
// For PDF selections, enable right-click context menu to directly open translator popup.
|
||||
if (bookData.book?.format === 'PDF') {
|
||||
@@ -242,9 +254,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const detail = (event as CustomEvent).detail;
|
||||
const { draw, annotation, doc, range } = detail;
|
||||
const { style, color } = annotation as BookNote;
|
||||
const customColors = settings.globalReadSettings.customHighlightColors;
|
||||
const hexColor =
|
||||
color && customColors ? customColors[color] : color ? HIGHLIGHT_COLOR_HEX[color] : color;
|
||||
const hexColor = getHighlightColorHex(settings, color);
|
||||
if (annotation.note) {
|
||||
const { defaultView } = doc;
|
||||
const node = range.startContainer;
|
||||
@@ -361,6 +371,32 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const handleQuickAction = () => {
|
||||
const action = viewSettings.annotationQuickAction;
|
||||
switch (action) {
|
||||
case 'copy':
|
||||
handleCopy(false);
|
||||
handleDismissPopupAndSelection();
|
||||
break;
|
||||
case 'highlight':
|
||||
handleHighlight();
|
||||
handleDismissPopupAndSelection();
|
||||
break;
|
||||
case 'dictionary':
|
||||
handleDictionary();
|
||||
break;
|
||||
case 'wikipedia':
|
||||
handleWikipedia();
|
||||
break;
|
||||
case 'translate':
|
||||
handleTranslation();
|
||||
break;
|
||||
case 'tts':
|
||||
handleSpeakText(true);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setHighlightOptionsVisible(!!(selection && selection.annotated));
|
||||
if (selection && selection.text.trim().length > 0) {
|
||||
@@ -406,10 +442,16 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
setTranslatorPopupPosition(transPopupPos);
|
||||
setProofreadPopupPosition(proofreadPopupPos);
|
||||
setTrianglePosition(triangPos);
|
||||
handleShowAnnotPopup();
|
||||
|
||||
const { enableAnnotationQuickActions, annotationQuickAction } = viewSettings;
|
||||
if (enableAnnotationQuickActions && annotationQuickAction && isTextSelected.current) {
|
||||
handleQuickAction();
|
||||
} else {
|
||||
handleShowAnnotPopup();
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selection, bookKey]);
|
||||
}, [selection?.cfi, bookKey]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!progress) return;
|
||||
@@ -465,7 +507,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
setShowWikipediaPopup(false);
|
||||
};
|
||||
|
||||
const handleCopy = (copyToNotebook = true, dismissPopup = true) => {
|
||||
const handleCopy = (dismissPopup = true) => {
|
||||
if (!selection || !selection.text) return;
|
||||
setTimeout(() => {
|
||||
// Delay to ensure it won't be overridden by system clipboard actions
|
||||
@@ -475,7 +517,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
handleDismissPopupAndSelection();
|
||||
}
|
||||
|
||||
if (!copyToNotebook) return;
|
||||
if (!viewSettings?.copyToNotebook) return;
|
||||
|
||||
eventDispatcher.dispatch('toast', {
|
||||
type: 'info',
|
||||
@@ -604,13 +646,13 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
setShowDeepLPopup(true);
|
||||
};
|
||||
|
||||
const handleSpeakText = async () => {
|
||||
const handleSpeakText = async (oneTime = false) => {
|
||||
if (!selection || !selection.text) return;
|
||||
setShowAnnotPopup(false);
|
||||
eventDispatcher.dispatch('tts-speak', { bookKey, range: selection.range });
|
||||
eventDispatcher.dispatch('tts-speak', { bookKey, range: selection.range, oneTime });
|
||||
};
|
||||
|
||||
const handleShowProofreadOptions = () => {
|
||||
const handleProofread = () => {
|
||||
if (!selection || !selection.text) return;
|
||||
setShowAnnotPopup(false);
|
||||
setShowProofreadPopup(true);
|
||||
@@ -641,7 +683,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
handleSearch();
|
||||
},
|
||||
onCopySelection: () => {
|
||||
handleCopy(false, false);
|
||||
handleCopy(false);
|
||||
},
|
||||
onTranslateSelection: () => {
|
||||
handleTranslation();
|
||||
@@ -655,6 +697,9 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
onReadAloudSelection: () => {
|
||||
handleSpeakText();
|
||||
},
|
||||
onProofreadSelection: () => {
|
||||
handleProofread();
|
||||
},
|
||||
},
|
||||
[selection?.text],
|
||||
);
|
||||
@@ -745,42 +790,55 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
};
|
||||
|
||||
const selectionAnnotated = selection?.annotated;
|
||||
const buttons = [
|
||||
{ tooltipText: _('Copy'), Icon: FiCopy, onClick: handleCopy },
|
||||
{
|
||||
tooltipText: selectionAnnotated ? _('Delete Highlight') : _('Highlight'),
|
||||
Icon: selectionAnnotated ? RiDeleteBinLine : PiHighlighterFill,
|
||||
onClick: handleHighlight,
|
||||
disabled: bookData.book?.format === 'PDF',
|
||||
},
|
||||
{
|
||||
tooltipText: _('Annotate'),
|
||||
Icon: BsPencilSquare,
|
||||
onClick: handleAnnotate,
|
||||
disabled: bookData.book?.format === 'PDF',
|
||||
},
|
||||
{
|
||||
tooltipText: _('Search'),
|
||||
Icon: FiSearch,
|
||||
onClick: handleSearch,
|
||||
disabled: bookData.book?.format === 'PDF',
|
||||
},
|
||||
{ tooltipText: _('Dictionary'), Icon: TbHexagonLetterD, onClick: handleDictionary },
|
||||
{ tooltipText: _('Wikipedia'), Icon: FaWikipediaW, onClick: handleWikipedia },
|
||||
{ tooltipText: _('Translate'), Icon: BsTranslate, onClick: handleTranslation },
|
||||
{
|
||||
tooltipText: _('Speak'),
|
||||
Icon: FaHeadphones,
|
||||
onClick: handleSpeakText,
|
||||
disabled: bookData.book?.format === 'PDF',
|
||||
},
|
||||
{
|
||||
tooltipText: _('Proofread'),
|
||||
Icon: IoIosBuild,
|
||||
onClick: handleShowProofreadOptions,
|
||||
disabled: bookData.book?.format !== 'EPUB',
|
||||
},
|
||||
];
|
||||
const toolButtons = annotationToolButtons.map(({ type, label, Icon }) => {
|
||||
switch (type) {
|
||||
case 'copy':
|
||||
return { tooltipText: _(label), Icon, onClick: handleCopy };
|
||||
case 'highlight':
|
||||
return {
|
||||
tooltipText: selectionAnnotated ? _('Delete Highlight') : _(label),
|
||||
Icon: selectionAnnotated ? RiDeleteBinLine : Icon,
|
||||
onClick: handleHighlight,
|
||||
disabled: bookData.book?.format === 'PDF',
|
||||
};
|
||||
case 'annotate':
|
||||
return {
|
||||
tooltipText: _(label),
|
||||
Icon,
|
||||
onClick: handleAnnotate,
|
||||
disabled: bookData.book?.format === 'PDF',
|
||||
};
|
||||
case 'search':
|
||||
return {
|
||||
tooltipText: _(label),
|
||||
Icon,
|
||||
onClick: handleSearch,
|
||||
disabled: bookData.book?.format === 'PDF',
|
||||
};
|
||||
case 'dictionary':
|
||||
return { tooltipText: _(label), Icon, onClick: handleDictionary };
|
||||
case 'wikipedia':
|
||||
return { tooltipText: _(label), Icon, onClick: handleWikipedia };
|
||||
case 'translate':
|
||||
return { tooltipText: _(label), Icon, onClick: handleTranslation };
|
||||
case 'tts':
|
||||
return {
|
||||
tooltipText: _(label),
|
||||
Icon,
|
||||
onClick: handleSpeakText,
|
||||
disabled: bookData.book?.format === 'PDF',
|
||||
};
|
||||
case 'proofread':
|
||||
return {
|
||||
tooltipText: _(label),
|
||||
Icon,
|
||||
onClick: handleProofread,
|
||||
disabled: bookData.book?.format !== 'EPUB',
|
||||
};
|
||||
default:
|
||||
return { tooltipText: '', Icon, onClick: () => {} };
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div ref={containerRef} role='toolbar' tabIndex={-1}>
|
||||
@@ -821,7 +879,7 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
bookKey={bookKey}
|
||||
dir={viewSettings.rtl ? 'rtl' : 'ltr'}
|
||||
isVertical={viewSettings.vertical}
|
||||
buttons={buttons}
|
||||
buttons={toolButtons}
|
||||
notes={annotationNotes}
|
||||
position={annotPopupPosition}
|
||||
trianglePosition={trianglePosition}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import { MdCheck } from 'react-icons/md';
|
||||
|
||||
import { AnnotationToolType } from '@/types/annotator';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { annotationToolQuickActions } from './AnnotationTools';
|
||||
import MenuItem from '@/components/MenuItem';
|
||||
import Menu from '@/components/Menu';
|
||||
|
||||
interface QuickActionMenuProps {
|
||||
selectedAction?: AnnotationToolType | null;
|
||||
onActionSelect: (action: AnnotationToolType) => void;
|
||||
setIsDropdownOpen?: (open: boolean) => void;
|
||||
}
|
||||
|
||||
const QuickActionMenu: React.FC<QuickActionMenuProps> = ({
|
||||
selectedAction,
|
||||
onActionSelect,
|
||||
setIsDropdownOpen,
|
||||
}) => {
|
||||
const _ = useTranslation();
|
||||
|
||||
const handleActionClick = (action: AnnotationToolType) => {
|
||||
onActionSelect(action);
|
||||
};
|
||||
|
||||
return (
|
||||
<Menu
|
||||
className={clsx(
|
||||
'annotation-quick-action-menu dropdown-content z-20 mt-1 border',
|
||||
'bgcolor-base-200 border-base-200 shadow-2xl',
|
||||
)}
|
||||
style={{
|
||||
maxWidth: `${window.innerWidth - 40}px`,
|
||||
}}
|
||||
onCancel={() => setIsDropdownOpen?.(false)}
|
||||
>
|
||||
{annotationToolQuickActions.map((button) => (
|
||||
<MenuItem
|
||||
key={button.type}
|
||||
label={_(button.label)}
|
||||
tooltip={_(button.tooltip)}
|
||||
Icon={selectedAction === button.type ? MdCheck : button.Icon}
|
||||
onClick={() => handleActionClick(button.type)}
|
||||
/>
|
||||
))}
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
export default QuickActionMenu;
|
||||
@@ -286,7 +286,7 @@ const TTSControl: React.FC<TTSControlProps> = ({ bookKey, gridInsets }) => {
|
||||
}, [getTTSTargetLang]);
|
||||
|
||||
const handleTTSSpeak = async (event: CustomEvent) => {
|
||||
const { bookKey: ttsBookKey, range } = event.detail;
|
||||
const { bookKey: ttsBookKey, range, oneTime = false } = event.detail;
|
||||
if (bookKey !== ttsBookKey) return;
|
||||
|
||||
const view = getView(bookKey);
|
||||
@@ -337,7 +337,9 @@ const TTSControl: React.FC<TTSControlProps> = ({ bookKey, gridInsets }) => {
|
||||
await initMediaSession();
|
||||
setTtsClientsInitialized(false);
|
||||
|
||||
setShowIndicator(true);
|
||||
if (!oneTime) {
|
||||
setShowIndicator(true);
|
||||
}
|
||||
const ttsController = new TTSController(appService, view, !!user?.id);
|
||||
ttsControllerRef.current = ttsController;
|
||||
setTtsController(ttsController);
|
||||
@@ -352,7 +354,7 @@ const TTSControl: React.FC<TTSControlProps> = ({ bookKey, gridInsets }) => {
|
||||
|
||||
ttsController.setLang(lang);
|
||||
ttsController.setRate(viewSettings.ttsRate);
|
||||
ttsController.speak(ssml);
|
||||
ttsController.speak(ssml, oneTime);
|
||||
ttsController.setTargetLang(getTTSTargetLang() || '');
|
||||
}
|
||||
setTtsClientsInitialized(true);
|
||||
|
||||
@@ -81,7 +81,7 @@ export const useTextSelector = (
|
||||
}, 30);
|
||||
}, 30);
|
||||
};
|
||||
const handleSelectionchange = (doc: Document, index: number) => {
|
||||
const handleSelectionchange = (doc: Document) => {
|
||||
// Available on iOS, Android and Desktop, fired when the selection is changed
|
||||
// Ideally the popup only shows when the selection is done,
|
||||
const sel = doc.getSelection() as Selection;
|
||||
@@ -98,12 +98,6 @@ export const useTextSelector = (
|
||||
return;
|
||||
}
|
||||
|
||||
// On Android no proper events are fired to notify selection done,
|
||||
// we make the popup show when the selection is changed
|
||||
// note that selection may be initiated by a tts speak
|
||||
if (isTouchStarted.current && osPlatform === 'android') {
|
||||
makeSelection(sel, index, false);
|
||||
}
|
||||
isUpToPopup.current = true;
|
||||
};
|
||||
const isPointerInsideSelection = (selection: Selection, ev: PointerEvent) => {
|
||||
@@ -127,14 +121,18 @@ export const useTextSelector = (
|
||||
const handlePointerdown = (e: PointerEvent) => {
|
||||
lastPointerType.current = e.pointerType;
|
||||
};
|
||||
const handlePointerup = (doc: Document, index: number, ev: PointerEvent) => {
|
||||
const handlePointerup = (doc: Document, index: number, ev?: PointerEvent) => {
|
||||
// Available on iOS and Desktop, fired at touchend or mouseup
|
||||
// Note that on Android, pointerup event is fired after an additional touch event
|
||||
// Note that on Android, we mock pointer events with native touch events
|
||||
const sel = doc.getSelection() as Selection;
|
||||
if (isValidSelection(sel) && isPointerInsideSelection(sel, ev)) {
|
||||
if (osPlatform === 'ios' || appService?.isIOSApp) {
|
||||
if (isValidSelection(sel)) {
|
||||
const isPointerInside = ev && isPointerInsideSelection(sel, ev);
|
||||
const isIOS = osPlatform === 'ios' || appService?.isIOSApp;
|
||||
const isAndroid = appService?.isAndroidApp;
|
||||
|
||||
if (isPointerInside && isIOS) {
|
||||
makeSelectionOnIOS(sel, index);
|
||||
} else {
|
||||
} else if (isPointerInside || isAndroid) {
|
||||
makeSelection(sel, index, true);
|
||||
}
|
||||
}
|
||||
@@ -228,6 +226,7 @@ export const useTextSelector = (
|
||||
}, []);
|
||||
|
||||
return {
|
||||
isTextSelected,
|
||||
handleScroll,
|
||||
handleTouchStart,
|
||||
handleTouchEnd,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { HIGHLIGHT_COLOR_HEX } from '@/services/constants';
|
||||
import { HighlightColor } from '@/types/book';
|
||||
import { SystemSettings } from '@/types/settings';
|
||||
|
||||
export const getHighlightColorHex = (settings: SystemSettings, color?: HighlightColor) => {
|
||||
if (!color) return color;
|
||||
|
||||
const customColors = settings.globalReadSettings.customHighlightColors;
|
||||
return customColors?.[color] ?? HIGHLIGHT_COLOR_HEX[color];
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
import { IconBaseProps } from 'react-icons';
|
||||
import { GenIcon } from 'react-icons/lib';
|
||||
|
||||
export function HighlighterIcon({
|
||||
tipColor = '#FFD700',
|
||||
tipStyle = {},
|
||||
...props
|
||||
}: IconBaseProps & { tipColor?: string; tipStyle?: React.CSSProperties }) {
|
||||
return GenIcon({
|
||||
tag: 'svg',
|
||||
attr: {
|
||||
viewBox: '0 0 256 256',
|
||||
fill: 'none',
|
||||
},
|
||||
child: [
|
||||
{
|
||||
tag: 'path',
|
||||
attr: {
|
||||
d: 'M253.66,106.34a8,8,0,0,0-11.32,0L192,156.69,107.31,72l50.35-50.34a8,8,0,1,0-11.32-11.32L96,60.69A16,16,0,0,0,93.18,79.5L72,100.69a16,16,0,0,0,0,22.62L76.69,128,136,187.31l4.69,4.69a16,16,0,0,0,22.62,0l21.18-21.18A16,16,0,0,0,203.31,168l50.35-50.34A8,8,0,0,0,253.66,106.34ZM152,180.69,83.31,112,104,91.31,172.69,160Z',
|
||||
fill: 'currentColor',
|
||||
},
|
||||
child: [],
|
||||
},
|
||||
{
|
||||
tag: 'path',
|
||||
attr: {
|
||||
d: 'M18.34,186.34c-4.209212,4.20621-2.516471,11.37196,3.13,13.25l72,24c0.815308,0.27382,1.669943,0.41232,2.53,0.41c2.12237,0.002,4.15842-0.84009,5.66-2.34L136,187.31c13.62143,13.61626-70.243446-70.24754-64-64l4.69,4.69z',
|
||||
fill: tipColor,
|
||||
style: tipStyle as unknown as string,
|
||||
},
|
||||
child: [],
|
||||
},
|
||||
],
|
||||
})(props);
|
||||
}
|
||||
@@ -11,7 +11,9 @@ import { getStyles } from '@/utils/style';
|
||||
import { getMaxInlineSize } from '@/utils/config';
|
||||
import { saveSysSettings, saveViewSettings } from '@/helpers/settings';
|
||||
import { SettingsPanelPanelProp } from './SettingsDialog';
|
||||
import { annotationToolQuickActions } from '@/app/reader/components/annotator/AnnotationTools';
|
||||
import NumberInput from './NumberInput';
|
||||
import Select from '../Select';
|
||||
|
||||
const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset }) => {
|
||||
const _ = useTranslation();
|
||||
@@ -32,6 +34,13 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
|
||||
const [fullscreenClickArea, setFullscreenClickArea] = useState(viewSettings.fullscreenClickArea);
|
||||
const [swapClickArea, setSwapClickArea] = useState(viewSettings.swapClickArea);
|
||||
const [isDisableDoubleClick, setIsDisableDoubleClick] = useState(viewSettings.disableDoubleClick);
|
||||
const [enableAnnotationQuickActions, setEnableAnnotationQuickActions] = useState(
|
||||
viewSettings.enableAnnotationQuickActions,
|
||||
);
|
||||
const [annotationQuickAction, setAnnotationQuickAction] = useState(
|
||||
viewSettings.annotationQuickAction,
|
||||
);
|
||||
const [copyToNotebook, setCopyToNotebook] = useState(viewSettings.copyToNotebook);
|
||||
const [animated, setAnimated] = useState(viewSettings.animated);
|
||||
const [isEink, setIsEink] = useState(viewSettings.isEink);
|
||||
const [autoScreenBrightness, setAutoScreenBrightness] = useState(settings.autoScreenBrightness);
|
||||
@@ -50,6 +59,10 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
|
||||
animated: setAnimated,
|
||||
isEink: setIsEink,
|
||||
allowScript: setAllowScript,
|
||||
fullscreenClickArea: setFullscreenClickArea,
|
||||
disableDoubleClick: setIsDisableDoubleClick,
|
||||
enableAnnotationQuickActions: setEnableAnnotationQuickActions,
|
||||
copyToNotebook: setCopyToNotebook,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -148,6 +161,42 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [allowScript]);
|
||||
|
||||
useEffect(() => {
|
||||
saveViewSettings(
|
||||
envConfig,
|
||||
bookKey,
|
||||
'enableAnnotationQuickActions',
|
||||
enableAnnotationQuickActions,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [enableAnnotationQuickActions]);
|
||||
|
||||
useEffect(() => {
|
||||
saveViewSettings(envConfig, bookKey, 'copyToNotebook', copyToNotebook, false, false);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [copyToNotebook]);
|
||||
|
||||
const getQuickActionOptions = () => {
|
||||
return [
|
||||
{
|
||||
value: '',
|
||||
label: _('None'),
|
||||
},
|
||||
...annotationToolQuickActions.map((button) => ({
|
||||
value: button.type,
|
||||
label: button.label,
|
||||
})),
|
||||
];
|
||||
};
|
||||
|
||||
const handleSelectAnnotationQuickAction = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const action = event.target.value as typeof annotationQuickAction;
|
||||
setAnnotationQuickAction(action);
|
||||
saveViewSettings(envConfig, bookKey, 'annotationQuickAction', action, false, true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='my-4 w-full space-y-6'>
|
||||
<div className='w-full'>
|
||||
@@ -250,6 +299,41 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='w-full'>
|
||||
<h2 className='mb-2 font-medium'>{_('Annotation Tools')}</h2>
|
||||
<div className='card border-base-200 bg-base-100 border shadow'>
|
||||
<div className='divide-base-200 divide-y'>
|
||||
<div className='config-item'>
|
||||
<span className=''>{_('Enable Quick Actions')}</span>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='toggle'
|
||||
checked={enableAnnotationQuickActions}
|
||||
onChange={() => setEnableAnnotationQuickActions(!enableAnnotationQuickActions)}
|
||||
/>
|
||||
</div>
|
||||
<div className='config-item'>
|
||||
<span className=''>{_('Quick Action')}</span>
|
||||
<Select
|
||||
value={annotationQuickAction || ''}
|
||||
onChange={handleSelectAnnotationQuickAction}
|
||||
options={getQuickActionOptions()}
|
||||
disabled={!enableAnnotationQuickActions}
|
||||
/>
|
||||
</div>
|
||||
<div className='config-item'>
|
||||
<span className=''>{_('Copy to Notebook')}</span>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='toggle'
|
||||
checked={copyToNotebook}
|
||||
onChange={() => setCopyToNotebook(!copyToNotebook)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='w-full'>
|
||||
<h2 className='mb-2 font-medium'>{_('Animation')}</h2>
|
||||
<div className='card border-base-200 bg-base-100 border shadow'>
|
||||
|
||||
@@ -16,6 +16,7 @@ const DEFAULT_SHORTCUTS = {
|
||||
onDictionarySelection: ['ctrl+d', 'cmd+d'],
|
||||
onWikipediaSelection: ['ctrl+w', 'cmd+w'],
|
||||
onReadAloudSelection: ['ctrl+r', 'cmd+r'],
|
||||
onProofreadSelection: ['ctrl+p', 'cmd+p'],
|
||||
onOpenFontLayoutSettings: ['shift+f', 'ctrl+,', 'cmd+,'],
|
||||
onOpenBooks: ['ctrl+o'],
|
||||
onReloadPage: ['shift+r'],
|
||||
|
||||
@@ -54,6 +54,7 @@ import {
|
||||
DEFAULT_FIXED_LAYOUT_VIEW_SETTINGS,
|
||||
SETTINGS_FILENAME,
|
||||
DEFAULT_MOBILE_SYSTEM_SETTINGS,
|
||||
DEFAULT_ANNOTATOR_CONFIG,
|
||||
} from './constants';
|
||||
import { fetch as tauriFetch } from '@tauri-apps/plugin-http';
|
||||
import { getOSPlatform, getTargetLang, isCJKEnv, isContentURI, isValidURL } from '@/utils/misc';
|
||||
@@ -199,6 +200,7 @@ export abstract class BaseAppService implements AppService {
|
||||
...DEFAULT_VIEW_CONFIG,
|
||||
...DEFAULT_TTS_CONFIG,
|
||||
...DEFAULT_SCREEN_CONFIG,
|
||||
...DEFAULT_ANNOTATOR_CONFIG,
|
||||
...{ ...DEFAULT_TRANSLATOR_CONFIG, translateTargetLang: getTargetLang() },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
AnnotatorConfig,
|
||||
BookFont,
|
||||
BookLanguage,
|
||||
BookLayout,
|
||||
@@ -245,6 +246,12 @@ export const DEFAULT_TRANSLATOR_CONFIG: TranslatorConfig = {
|
||||
ttsReadAloudText: 'both',
|
||||
};
|
||||
|
||||
export const DEFAULT_ANNOTATOR_CONFIG: AnnotatorConfig = {
|
||||
enableAnnotationQuickActions: true,
|
||||
annotationQuickAction: null,
|
||||
copyToNotebook: false,
|
||||
};
|
||||
|
||||
export const DEFAULT_SCREEN_CONFIG: ScreenConfig = {
|
||||
screenOrientation: 'auto',
|
||||
};
|
||||
|
||||
@@ -155,7 +155,7 @@ export class TTSController extends EventTarget {
|
||||
return ssml;
|
||||
}
|
||||
|
||||
async #speak(ssml: string | undefined | Promise<string>) {
|
||||
async #speak(ssml: string | undefined | Promise<string>, oneTime = false) {
|
||||
await this.stop();
|
||||
this.#currentSpeakAbortController = new AbortController();
|
||||
const { signal } = this.#currentSpeakAbortController;
|
||||
@@ -173,7 +173,7 @@ export class TTSController extends EventTarget {
|
||||
if (!ssml) {
|
||||
this.#nossmlCnt++;
|
||||
// FIXME: in case we are at the end of the book, need a better way to handle this
|
||||
if (this.#nossmlCnt < 10 && this.state === 'playing') {
|
||||
if (this.#nossmlCnt < 10 && this.state === 'playing' && !oneTime) {
|
||||
resolve();
|
||||
await this.view.next();
|
||||
await this.forward();
|
||||
@@ -185,7 +185,7 @@ export class TTSController extends EventTarget {
|
||||
}
|
||||
|
||||
const { plainText, marks } = parseSSMLMarks(ssml);
|
||||
if (!plainText || marks.length === 0) {
|
||||
if ((!plainText || marks.length === 0) && !oneTime) {
|
||||
resolve();
|
||||
return await this.forward();
|
||||
} else {
|
||||
@@ -202,7 +202,7 @@ export class TTSController extends EventTarget {
|
||||
lastCode = code;
|
||||
}
|
||||
|
||||
if (lastCode === 'end' && this.state === 'playing') {
|
||||
if (lastCode === 'end' && this.state === 'playing' && !oneTime) {
|
||||
resolve();
|
||||
await this.forward();
|
||||
}
|
||||
@@ -224,9 +224,9 @@ export class TTSController extends EventTarget {
|
||||
await this.#currentSpeakPromise.catch((e) => this.error(e));
|
||||
}
|
||||
|
||||
async speak(ssml: string | Promise<string>) {
|
||||
async speak(ssml: string | Promise<string>, oneTime = false) {
|
||||
await this.initViewTTS();
|
||||
this.#speak(ssml).catch((e) => this.error(e));
|
||||
this.#speak(ssml, oneTime).catch((e) => this.error(e));
|
||||
this.preloadNextSSML();
|
||||
this.dispatchSpeakMark();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { create } from 'zustand';
|
||||
import { interceptKeys, getScreenBrightness, setScreenBrightness } from '@/utils/bridge';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { NativeTouchEventType } from '@/types/system';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
onNativeKeyDown?: (keyName: string) => void;
|
||||
onNativeTouch?: (event: NativeTouchEventType) => void;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +31,7 @@ type DeviceControlState = {
|
||||
releaseVolumeKeyInterception: () => void;
|
||||
acquireBackKeyInterception: () => void;
|
||||
releaseBackKeyInterception: () => void;
|
||||
listenToNativeTouchEvents: () => void;
|
||||
};
|
||||
|
||||
export const useDeviceControlStore = create<DeviceControlState>((set, get) => ({
|
||||
@@ -77,6 +80,12 @@ export const useDeviceControlStore = create<DeviceControlState>((set, get) => ({
|
||||
}
|
||||
},
|
||||
|
||||
listenToNativeTouchEvents: () => {
|
||||
window.onNativeTouch = (event: NativeTouchEventType) => {
|
||||
return eventDispatcher.dispatch('native-touch', event);
|
||||
};
|
||||
},
|
||||
|
||||
getScreenBrightness: async () => {
|
||||
const res = await getScreenBrightness();
|
||||
return res.brightness;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
export type AnnotationToolType =
|
||||
| 'copy'
|
||||
| 'highlight'
|
||||
| 'annotate'
|
||||
| 'search'
|
||||
| 'dictionary'
|
||||
| 'wikipedia'
|
||||
| 'translate'
|
||||
| 'tts'
|
||||
| 'proofread';
|
||||
@@ -1,5 +1,6 @@
|
||||
import { BookMetadata } from '@/libs/document';
|
||||
import { TTSHighlightOptions } from '@/services/tts/types';
|
||||
import { AnnotationToolType } from './annotator';
|
||||
|
||||
export type BookFormat = 'EPUB' | 'PDF' | 'MOBI' | 'AZW' | 'AZW3' | 'CBZ' | 'FB2' | 'FBZ';
|
||||
export type BookNoteType = 'bookmark' | 'annotation' | 'excerpt';
|
||||
@@ -206,6 +207,12 @@ export interface TranslatorConfig {
|
||||
ttsReadAloudText: string;
|
||||
}
|
||||
|
||||
export interface AnnotatorConfig {
|
||||
enableAnnotationQuickActions: boolean;
|
||||
annotationQuickAction: AnnotationToolType | null;
|
||||
copyToNotebook: boolean;
|
||||
}
|
||||
|
||||
export interface ScreenConfig {
|
||||
screenOrientation: 'auto' | 'portrait' | 'landscape';
|
||||
}
|
||||
@@ -239,7 +246,8 @@ export interface ViewSettings
|
||||
TTSConfig,
|
||||
TranslatorConfig,
|
||||
ScreenConfig,
|
||||
ProofreadRulesConfig {}
|
||||
ProofreadRulesConfig,
|
||||
AnnotatorConfig {}
|
||||
|
||||
export interface BookProgress {
|
||||
location: string;
|
||||
|
||||
@@ -34,6 +34,16 @@ export type FileInfo = {
|
||||
birthtime: Date | null;
|
||||
};
|
||||
|
||||
export type NativeTouchEventType = {
|
||||
type: 'touchstart' | 'touchcancel' | 'touchend';
|
||||
pointerId: number;
|
||||
x: number;
|
||||
y: number;
|
||||
pressure: number;
|
||||
pointerCount: number;
|
||||
timestamp: number;
|
||||
};
|
||||
|
||||
export interface FileSystem {
|
||||
resolvePath(path: string, base: BaseDir): ResolvedPath;
|
||||
getURL(path: string): string;
|
||||
|
||||
Reference in New Issue
Block a user