diff --git a/lib/views/ai_summarize_view.dart b/lib/views/ai_summarize_view.dart index 438efe9..6dca1c3 100644 --- a/lib/views/ai_summarize_view.dart +++ b/lib/views/ai_summarize_view.dart @@ -13,6 +13,7 @@ import 'package:news_assistant/services/news_service.dart'; import 'package:news_assistant/services/services.dart'; import 'package:news_assistant/utils/util.dart'; import 'package:rive/rive.dart'; +import 'package:text_to_speech/text_to_speech.dart'; final _newsService = getIt.get(); final _newsManager = @@ -28,6 +29,7 @@ class AiSummarizeView extends ConsumerStatefulWidget { } class _AiSummarizeViewState extends ConsumerState { + final tts = TextToSpeech(); GenerateContentResponse? response; bool loading = false; final languages = [ @@ -121,9 +123,20 @@ class _AiSummarizeViewState extends ConsumerState { ), floatingActionButton: snapshot.data == null ? null - : FloatingActionButton( - onPressed: () async => showTranslationList(), - child: const Icon(Icons.translate), + : Column( + children: [ + FloatingActionButton( + onPressed: () async => showTranslationList(), + child: const Icon(Icons.translate), + ), + const SizedBox( + height: 6, + ), + FloatingActionButton( + onPressed: () async => speakOutText(), + child: const Icon(Icons.volume_up_rounded), + ), + ], ), body: Padding( padding: const EdgeInsets.all(16.0), @@ -157,6 +170,14 @@ class _AiSummarizeViewState extends ConsumerState { ); } + speakOutText() async { + if (response?.text == null) return; + String text = response?.text ?? ""; + double volume = 1.0; + tts.setVolume(volume); + tts.speak(text); + } + showTranslationList() async { final language = await showModalBottomSheet( context: context, diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 7798fc3..1f45965 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,10 +9,12 @@ import path_provider_foundation import rive_common import share_plus import sqflite +import text_to_speech_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + TextToSpeechMacOsPlugin.register(with: registry.registrar(forPlugin: "TextToSpeechMacOsPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index f2eaf59..1938560 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -813,6 +813,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.1" + text_to_speech: + dependency: "direct main" + description: + name: text_to_speech + sha256: f9adeb82bf0c912fd7f0ce656b1283e49b0869f9247bf865859dcf0186ed32f3 + url: "https://pub.dev" + source: hosted + version: "0.2.3" + text_to_speech_macos: + dependency: transitive + description: + name: text_to_speech_macos + sha256: "11d1b7d4eff579743b04d371e86d17bebd599f7d998b9fa4cf07a5821cda3b6d" + url: "https://pub.dev" + source: hosted + version: "0.1.1" + text_to_speech_platform_interface: + dependency: transitive + description: + name: text_to_speech_platform_interface + sha256: "9d637f0ae36e296f42a0e555bd65ba4c64a28a7c26a2752fdae62f6d78b6c2d0" + url: "https://pub.dev" + source: hosted + version: "0.1.3" + text_to_speech_web: + dependency: transitive + description: + name: text_to_speech_web + sha256: "47d006c0a377c9eb3f6bcca4d92b3ece2c67f5eb31b9416727cc81b92c36d6d1" + url: "https://pub.dev" + source: hosted + version: "0.1.2" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ddeb8d1..42d25ed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,6 +22,7 @@ dependencies: rive: ^0.12.4 riverpod_annotation: ^2.3.4 share_plus: ^7.2.2 + text_to_speech: ^0.2.3