forked from TelegramMessenger/Telegram-iOS
-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
1,030 additions
and
266 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") | ||
|
||
swift_library( | ||
name = "NGSpeechToText", | ||
module_name = "NGSpeechToText", | ||
srcs = glob([ | ||
"Sources/**/*.swift", | ||
]), | ||
deps = [ | ||
"//submodules/AccountContext:AccountContext", | ||
"//submodules/Display:Display", | ||
"//submodules/ItemListUI:ItemListUI", | ||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", | ||
"//submodules/TelegramCore:TelegramCore", | ||
"//submodules/TelegramPresentationData:TelegramPresentationData", | ||
"//submodules/PresentationDataUtils:PresentationDataUtils", | ||
"//submodules/TelegramUI/Components/ChatControllerInteraction", | ||
"//submodules/TranslateUI:TranslateUI", | ||
"//submodules/Media/ConvertOpusToAAC", | ||
"//Nicegram/NGUI:NGUI", | ||
"@swiftpkg_nicegram_assistant_ios//:FeatPremiumUI", | ||
], | ||
visibility = [ | ||
"//visibility:public", | ||
], | ||
) |
224 changes: 224 additions & 0 deletions
224
Nicegram/NGSpeechToText/Sources/ConvertSpeechToText.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
import Foundation | ||
import TelegramCore | ||
import ChatControllerInteraction | ||
import Postbox | ||
import FeatPremiumUI | ||
import AccountContext | ||
import TelegramPresentationData | ||
import NGData | ||
import NGUI | ||
|
||
public enum SpeechToTextMessageSource { | ||
case chat, contextMenu | ||
} | ||
|
||
public func convertSpeechToText( | ||
from source: SpeechToTextMessageSource = .chat, | ||
languageStyle: RecognitionLanguagesControllerStyle = .normal, | ||
context: AccountContext, | ||
mediaFile: TelegramMediaFile, | ||
message: Message?, | ||
presentationData: PresentationData, | ||
controllerInteraction: ChatControllerInteraction, | ||
completion: (() -> Void)? = nil, | ||
closeWithoutSelect: (() -> Void)? = nil | ||
) { | ||
var id: Int64? | ||
if let peer = message?.peers.toDict().first?.value, | ||
languageStyle == .normal { | ||
switch EnginePeer(peer) { | ||
case let .channel(channel): | ||
id = channel.id.toInt64() | ||
case let .legacyGroup(group): | ||
id = group.id.toInt64() | ||
case let .user(user): | ||
id = user.id.toInt64() | ||
default: | ||
return | ||
} | ||
} | ||
|
||
if NGSettings.useOpenAI { | ||
startConvertSpeechToTextTask( | ||
from: source, | ||
context: context, | ||
mediaFile: mediaFile, | ||
source: .openAI, | ||
message: message, | ||
presentationData: presentationData, | ||
controllerInteraction: controllerInteraction, | ||
completion: completion | ||
) | ||
} else { | ||
if let id, | ||
let locale = NGSettings.appleSpeechToTextLocale[id] { | ||
startConvertSpeechToTextTask( | ||
from: source, | ||
context: context, | ||
mediaFile: mediaFile, | ||
source: .apple(locale), | ||
message: message, | ||
presentationData: presentationData, | ||
controllerInteraction: controllerInteraction, | ||
completion: completion | ||
) | ||
} else { | ||
showLanguages( | ||
with: context, | ||
controllerInteraction: controllerInteraction, | ||
style: languageStyle | ||
) { locale in | ||
if let id { | ||
var appleSpeechToTextLocale = NGSettings.appleSpeechToTextLocale | ||
appleSpeechToTextLocale[id] = locale | ||
NGSettings.appleSpeechToTextLocale = appleSpeechToTextLocale | ||
} | ||
_ = controllerInteraction.navigationController()?.popViewController(animated: true) | ||
startConvertSpeechToTextTask( | ||
from: source, | ||
context: context, | ||
mediaFile: mediaFile, | ||
source: .apple(locale), | ||
message: message, | ||
presentationData: presentationData, | ||
controllerInteraction: controllerInteraction, | ||
completion: completion | ||
) | ||
} selectWhisper: { | ||
_ = controllerInteraction.navigationController()?.popViewController(animated: true) | ||
|
||
PremiumUITgHelper.routeToPremium( | ||
source: .speechToText | ||
) | ||
} closeWithoutSelect: { | ||
closeWithoutSelect?() | ||
} | ||
} | ||
} | ||
} | ||
|
||
private func showLanguages( | ||
with context: AccountContext, | ||
controllerInteraction: ChatControllerInteraction, | ||
style: RecognitionLanguagesControllerStyle = .normal, | ||
selectLocale: @escaping (Locale) -> Void, | ||
selectWhisper: @escaping () -> Void, | ||
closeWithoutSelect: @escaping () -> Void | ||
) { | ||
let controller = recognitionLanguagesController( | ||
context: context, | ||
style: style, | ||
selectLocale: selectLocale, | ||
selectWhisper: selectWhisper, | ||
closeWithoutSelect: closeWithoutSelect | ||
) | ||
controller.navigationPresentation = .modal | ||
|
||
controllerInteraction.navigationController()?.pushViewController(controller, animated: true) | ||
} | ||
|
||
private func startConvertSpeechToTextTask( | ||
from messageSource: SpeechToTextMessageSource, | ||
context: AccountContext, | ||
mediaFile: TelegramMediaFile, | ||
source: TgSpeechToTextManager.Source, | ||
message: Message?, | ||
presentationData: PresentationData, | ||
controllerInteraction: ChatControllerInteraction, | ||
completion: (() -> Void)? = nil | ||
) { | ||
Task { @MainActor in | ||
let manager = TgSpeechToTextManager( | ||
accountContext: context | ||
) | ||
|
||
if messageSource == .contextMenu { | ||
message?.setSpeechToTextLoading(context: context) | ||
} | ||
|
||
let result = await manager.convertSpeechToText( | ||
mediaFile: mediaFile, | ||
source: source | ||
) | ||
|
||
switch result { | ||
case .success(let text): | ||
switch messageSource { | ||
case .chat: | ||
message?.updateAudioTranscriptionAttribute(text: text, error: nil, context: context) | ||
case .contextMenu: | ||
message?.setSpeechToTextTranslation(text, context: context) | ||
} | ||
case .needsPremium: | ||
PremiumUITgHelper.routeToPremium( | ||
source: .speechToText | ||
) | ||
case .error(let error): | ||
switch error { | ||
case .recognition(_): | ||
if messageSource == .contextMenu { | ||
message?.removeSpeechToTextMeta(context: context) | ||
} | ||
convertSpeechToText( | ||
from: messageSource, | ||
languageStyle: .whisper, | ||
context: context, | ||
mediaFile: mediaFile, | ||
message: message, | ||
presentationData: presentationData, | ||
controllerInteraction: controllerInteraction | ||
) | ||
case .notAvailable: | ||
if messageSource == .contextMenu { | ||
message?.removeSpeechToTextMeta(context: context) | ||
} | ||
let c = getIAPErrorController( | ||
context: context, | ||
"Speech to text recognizer not available.", | ||
presentationData | ||
) | ||
controllerInteraction.presentGlobalOverlayController(c, nil) | ||
case .authorizationStatus: | ||
if messageSource == .contextMenu { | ||
message?.removeSpeechToTextMeta(context: context) | ||
} | ||
let c = getIAPErrorController( | ||
context: context, | ||
"Speech to text recognizer autorization status error.", | ||
presentationData | ||
) | ||
controllerInteraction.presentGlobalOverlayController(c, nil) | ||
case let .api(error): | ||
switch messageSource { | ||
case .chat: | ||
message?.updateAudioTranscriptionAttribute(text: "", error: error, context: context) | ||
case .contextMenu: | ||
message?.removeSpeechToTextMeta(context: context) | ||
} | ||
|
||
let c = getIAPErrorController( | ||
context: context, | ||
error.localizedDescription, | ||
presentationData | ||
) | ||
controllerInteraction.presentGlobalOverlayController(c, nil) | ||
case let .other(error): | ||
switch messageSource { | ||
case .chat: | ||
message?.updateAudioTranscriptionAttribute(text: "", error: error, context: context) | ||
case .contextMenu: | ||
message?.removeSpeechToTextMeta(context: context) | ||
} | ||
|
||
let c = getIAPErrorController( | ||
context: context, | ||
error.localizedDescription, | ||
presentationData | ||
) | ||
controllerInteraction.presentGlobalOverlayController(c, nil) | ||
} | ||
} | ||
|
||
completion?() | ||
} | ||
} |
Oops, something went wrong.