diff --git a/ReaderTranslator/Components/SpeechSynthesizer.swift b/ReaderTranslator/Components/SpeechSynthesizer.swift index 8c479cd..f1c30f0 100644 --- a/ReaderTranslator/Components/SpeechSynthesizer.swift +++ b/ReaderTranslator/Components/SpeechSynthesizer.swift @@ -67,7 +67,7 @@ class SpeechSynthesizer { text: String = Store.shared.translateAction.getText(), voiceName: String = AudioStore.shared.voiceName, stopSpeaking: Bool = false, - isVoiceEnabled: Bool = AudioStore.shared.isEnabled + isVoiceEnabled: Bool = AudioStore.shared.isSpeakSentences ) { if speechSynthesizer.isSpeaking { SpeechSynthesizer.stop() @@ -88,7 +88,7 @@ class SpeechSynthesizer { let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: text) speechUtterance.voice = AVSpeechSynthesisVoice.speechVoices().first(where: { $0.name == voiceName }) - speechUtterance.volume = AudioStore.shared.volume + speechUtterance.volume = AudioStore.shared.sentencesVolume speechUtterance.rate = AudioStore.shared.rate if isVoiceEnabled { speechSynthesizer = AVSpeechSynthesizer() diff --git a/ReaderTranslator/Components/ViewRepresentable/Scripts/reader-translator.js b/ReaderTranslator/Components/ViewRepresentable/Scripts/reader-translator.js index 2735a3a..ac1bc72 100644 --- a/ReaderTranslator/Components/ViewRepresentable/Scripts/reader-translator.js +++ b/ReaderTranslator/Components/ViewRepresentable/Scripts/reader-translator.js @@ -264,11 +264,11 @@ if(elm) { if(event.shiftKey) { elm.style.color = "yellow" - sendIn200('selectionchange', 'document', event, getSelectedPhrases()) + sendIn500('selectionchange', 'document', event, getSelectedPhrases()) }else{ clearAllSelections() elm.style.color = "yellow" - sendIn200('selectionchange', 'document', event, elm.text.trim()) + sendIn500('selectionchange', 'document', event, elm.text.trim()) } lastElm = elm lastElm.click() @@ -288,11 +288,11 @@ } if(event.shiftKey) { lastElm.style.color = "yellow" - sendIn200('selectionchange', 'document', event, getSelectedPhrases()) + sendIn500('selectionchange', 'document', event, getSelectedPhrases()) }else{ clearAllSelections() lastElm.style.color = "yellow" - sendIn200('selectionchange', 'document', event, lastElm.text.trim()) + sendIn500('selectionchange', 'document', event, lastElm.text.trim()) } lastElm.click() } diff --git a/ReaderTranslator/Extentions/Stack.swift b/ReaderTranslator/Extentions/Stack.swift index 5a4e682..c921fc0 100644 --- a/ReaderTranslator/Extentions/Stack.swift +++ b/ReaderTranslator/Extentions/Stack.swift @@ -11,11 +11,17 @@ import Foundation struct Stack { private var items = [Element]() + var value: Element? { items.first } + var count: Int { items.count } + mutating func push(_ item: Element) { items.append(item) } + mutating func pop() -> Element? { guard items.isEmpty == false else { return nil } return items.removeFirst() } - var value: Element? { items.first } - var count: Int { items.count } + + mutating func removeAll() { + items.removeAll() + } } diff --git a/ReaderTranslator/Stores/AudioStore.swift b/ReaderTranslator/Stores/AudioStore.swift index cbb1c72..a905bb4 100644 --- a/ReaderTranslator/Stores/AudioStore.swift +++ b/ReaderTranslator/Stores/AudioStore.swift @@ -15,8 +15,10 @@ final class AudioStore: ObservableObject { @Published(key: "favoriteVoiceNames") var favoriteVoiceNames: [FavoriteVoiceName] = [] @Published(key: "voiceLanguage") var language = "Select language" @Published(key: "voiceName") var voiceName = "Select voice" - @Published(key: "isVoiceEnabled") var isEnabled = true { didSet { SpeechSynthesizer.speak() } } + @Published(key: "isSpeakSentences") var isSpeakSentences = true { didSet { SpeechSynthesizer.speak() } } + @Published(key: "isSpeakWords") var isSpeakWords = true { didSet { SpeechSynthesizer.speak() } } @Published(key: "voiceRate") var rate: Float = 0.5 - @Published(key: "voiceVolume") var volume: Float = 1 + @Published(key: "sentencesVolume") var sentencesVolume: Float = 1 + @Published(key: "wordsVolume") var wordsVolume: Float = 1 @Published(key: "playbackRate") var playbackRate: Float = 1.0 } diff --git a/ReaderTranslator/Stores/LongmanStore.swift b/ReaderTranslator/Stores/LongmanStore.swift index 5ea186d..a45c247 100644 --- a/ReaderTranslator/Stores/LongmanStore.swift +++ b/ReaderTranslator/Stores/LongmanStore.swift @@ -52,6 +52,7 @@ final class LongmanStore: NSObject, ObservableObject { do { let document = try SwiftSoup.parse(html) + self.audioUrls.removeAll() let isBreExist = self.addAudio(selector: ".brefile", document: document) let isAmeExist = self.addAudio(selector: ".amefile", document: document) @@ -122,7 +123,7 @@ extension LongmanStore { func play() { guard let url = audioUrls.pop() else { return } - if AudioStore.shared.isEnabled { + if AudioStore.shared.isSpeakWords { player = AVAudioNetPlayer() player?.delegate = self player?.play(url: url) @@ -136,7 +137,7 @@ extension LongmanStore: AVAudioNetPlayerDelegate { func audioPlayerCreateSuccessOccur(player: AVAudioPlayer) { player.enableRate = true player.rate = audioRate - player.volume = AudioStore.shared.volume + player.volume = AudioStore.shared.wordsVolume player.play() } diff --git a/ReaderTranslator/Views/ReaderView/Modes/ReaderView_Pdf/ReaderView_Pdf_Toolbar_PlayButtons.swift b/ReaderTranslator/Views/ReaderView/Modes/ReaderView_Pdf/ReaderView_Pdf_Toolbar_PlayButtons.swift index 37601f1..ba4d1ab 100644 --- a/ReaderTranslator/Views/ReaderView/Modes/ReaderView_Pdf/ReaderView_Pdf_Toolbar_PlayButtons.swift +++ b/ReaderTranslator/Views/ReaderView/Modes/ReaderView_Pdf/ReaderView_Pdf_Toolbar_PlayButtons.swift @@ -76,7 +76,7 @@ struct ReaderView_Pdf_Toolbar_PlayButtons: View { timer = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true) { _ in guard let player = self.audioPlayer.player else { return } self.currentStatus = self.audioPlayer.status - player.volume = self.audioStore.volume + player.volume = self.audioStore.sentencesVolume if self.isPlaying != player.isPlaying { self.isPlaying = player.isPlaying } } } diff --git a/ReaderTranslator/Views/ReaderView/Modes/SafariView.swift b/ReaderTranslator/Views/ReaderView/Modes/SafariView.swift index 52f3450..30fe9b9 100644 --- a/ReaderTranslator/Views/ReaderView/Modes/SafariView.swift +++ b/ReaderTranslator/Views/ReaderView/Modes/SafariView.swift @@ -48,7 +48,7 @@ struct SafariView: View { extra.shiftKey != true, extra.metaKey != true { if extra.altKey == true, extra.keyCode == 65 { // Alt+a - audioStore.isEnabled.toggle() + audioStore.isSpeakSentences.toggle() return } if extra.altKey == true, extra.keyCode == 83 { // Alt+s diff --git a/ReaderTranslator/Views/StatusBarView/StatusBarView_Voice/StatusBarView_Voice_Toggle.swift b/ReaderTranslator/Views/StatusBarView/StatusBarView_Voice/StatusBarView_Voice_Toggle.swift index e7f9658..ac056d8 100644 --- a/ReaderTranslator/Views/StatusBarView/StatusBarView_Voice/StatusBarView_Voice_Toggle.swift +++ b/ReaderTranslator/Views/StatusBarView/StatusBarView_Voice/StatusBarView_Voice_Toggle.swift @@ -10,19 +10,36 @@ import SwiftUI struct StatusBarView_Voice_Toggle: View { @ObservedObject var audio = AudioStore.shared + + private var isSpeakSentencesSign: Character { + audio.isSpeakSentences ? "👍" : "👎" + } + + private var isSpeakWordsSign: Character { + audio.isSpeakWords ? "👍" : "👎" + } var body: some View { Group { - Toggle(isOn: $audio.isEnabled) { - Text("On:") - }.fixedSize() - Image.sfSymbol(audio.isEnabled ? "speaker.3.fill" : "speaker") - .onTapGesture { - SpeechSynthesizer.speak(stopSpeaking: true, isVoiceEnabled: true) - } - .contextMenu { - Slider(value: $audio.volume, in: 0.1 ... 1.0).frame(width: 100, height: 50) + MenuButton("Speaker: \(isSpeakSentencesSign)\(isSpeakWordsSign)") { + VStack(spacing: 0) { + Text("Speak sentences") + HStack { + Image.sfSymbol(audio.isSpeakSentences ? "speaker.3.fill" : "speaker") + .onTapGesture { self.audio.isSpeakSentences.toggle() } + Slider(value: $audio.sentencesVolume, in: 0.1 ... 1.0).frame(width: 100) + } + Divider() + Text("Speak words") + HStack { + Image.sfSymbol(audio.isSpeakWords ? "speaker.3.fill" : "speaker") + .onTapGesture { self.audio.isSpeakWords.toggle() } + Slider(value: $audio.wordsVolume, in: 0.1 ... 1.0).frame(width: 100) + } } + } + .menuButtonStyle(BorderlessButtonMenuButtonStyle()) + .fixedSize() } } } diff --git a/ReaderTranslatorMac/Info.plist b/ReaderTranslatorMac/Info.plist index 368af98..fcb1bfb 100644 --- a/ReaderTranslatorMac/Info.plist +++ b/ReaderTranslatorMac/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.9.2 + 1.9.3 CFBundleVersion 1800 LSApplicationCategoryType