From 20dbce2f3451ae892c2af1012906ae0ba9468ac4 Mon Sep 17 00:00:00 2001 From: JHubi1 Date: Fri, 23 Aug 2024 18:26:46 +0200 Subject: [PATCH] Added timeout multiplicator --- lib/l10n/app_en.arb | 55 ++++++++++--------------------------- lib/screen_settings.dart | 45 ++++++++++++++++++++++-------- lib/screen_voice.dart | 4 ++- lib/settings/interface.dart | 51 ++++++++++++++++++++++++++++++++++ lib/worker/sender.dart | 18 ++++++++---- lib/worker/setter.dart | 15 ++++++---- lib/worker/update.dart | 7 ++++- untranslated_messages.json | 12 ++++++++ 8 files changed, 142 insertions(+), 65 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 72e60d1..7f63882 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -398,6 +398,21 @@ } } }, + "settingsTimeoutMultiplier": "Timeout multiplier", + "@settingsTimeoutMultiplier": { + "description": "Text displayed as title for the timeout multiplier section", + "context": "Visible in the settings view" + }, + "settingsTimeoutMultiplierDescription": "Select the multiplier that is applied to every timeout value in the app. Can be useful with a slow internet connection or a slow host.", + "@settingsTimeoutMultiplierDescription": { + "description": "Description of the timeout multiplier section", + "context": "Visible in the settings view" + }, + "settingsTimeoutMultiplierExample": "E.g. message timeout:", + "@settingsTimeoutMultiplierExample": { + "description": "Example for the timeout multiplier", + "context": "Visible in the settings view" + }, "settingsEnableHapticFeedback": "Enable haptic feedback", "@settingsEnableHapticFeedback": { "description": "Text displayed as description for enable haptic feedback toggle", @@ -423,26 +438,6 @@ "description": "Text displayed as description for dark brightness option", "context": "Visible in the settings view" }, - "settingsBrightnessRestartTitle": "Restart Required", - "@settingsBrightnessRestartTitle": { - "description": "Title of the restart required dialog", - "context": "Visible in the settings view" - }, - "settingsBrightnessRestartDescription": "Changing the theme requires a restart.\nDo you want to restart now or cancel the action?", - "@settingsBrightnessRestartDescription": { - "description": "Description of the restart required dialog", - "context": "Visible in the settings view" - }, - "settingsBrightnessRestartRestart": "Restart", - "@settingsBrightnessRestartRestart": { - "description": "Text displayed for restart button, should be capitalized", - "context": "Visible in the settings view" - }, - "settingsBrightnessRestartCancel": "Cancel", - "@settingsBrightnessRestartCancel": { - "description": "Text displayed for cancel button, should be capitalized", - "context": "Visible in the settings view" - }, "settingsThemeDevice": "Device", "@settingsThemeDevice": { "description": "Text displayed as description for device theme option", @@ -453,26 +448,6 @@ "description": "Text displayed as description for Ollama theme option", "context": "Visible in the settings view" }, - "settingsThemeRestartTitle": "Restart Required", - "@settingsThemeRestartTitle": { - "description": "Title of the restart required dialog", - "context": "Visible in the settings view" - }, - "settingsThemeRestartDescription": "Changing the theme requires a restart.\nDo you want to restart now or cancel the action?", - "@settingsThemeRestartDescription": { - "description": "Description of the restart required dialog", - "context": "Visible in the settings view" - }, - "settingsThemeRestartRestart": "Restart", - "@settingsThemeRestartRestart": { - "description": "Text displayed for restart button, should be capitalized", - "context": "Visible in the settings view" - }, - "settingsThemeRestartCancel": "Cancel", - "@settingsThemeRestartCancel": { - "description": "Text displayed for cancel button, should be capitalized", - "context": "Visible in the settings view" - }, "settingsTemporaryFixes": "Temporary interface fixes", "@settingsTemporaryFixes": { "description": "Text displayed as description for temporary fixes section", diff --git a/lib/screen_settings.dart b/lib/screen_settings.dart index 24b2cc5..c27696c 100644 --- a/lib/screen_settings.dart +++ b/lib/screen_settings.dart @@ -122,7 +122,7 @@ Widget title(String text, {double top = 16, double bottom = 16}) { Padding( padding: const EdgeInsets.only(left: 24, right: 24), child: Text(text)), - const Expanded(child: Divider(height: 1)) + const Expanded(child: Divider()) ])); } @@ -155,16 +155,21 @@ Widget button(String text, IconData? icon, void Function()? onPressed, bool disabled = false, bool replaceIconIfNull = false, String? description, + bool onlyDesktopDescription = true, + bool alwaysMobileDescription = false, String? badge, void Function()? onDisabledTap, void Function()? onLongTap, void Function()? onDoubleTap}) { if (description != null && - (context != null && desktopLayoutNotRequired(context)) && + ((context != null && desktopLayoutNotRequired(context)) || + !onlyDesktopDescription) && + !alwaysMobileDescription && !description.startsWith("\n")) { description = " • $description"; } - return Padding( + return AnimatedContainer( + duration: const Duration(milliseconds: 200), padding: (context != null && desktopLayoutNotRequired(context)) ? const EdgeInsets.only(top: 8, bottom: 8) : EdgeInsets.zero, @@ -183,9 +188,11 @@ Widget button(String text, IconData? icon, void Function()? onPressed, } : onPressed, onLongPress: (description != null && context != null) - ? desktopLayoutNotRequired(context) + ? (desktopLayoutNotRequired(context) && !alwaysMobileDescription) || + !onlyDesktopDescription ? null : () { + selectionHaptic(); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(description!.trim()), showCloseIcon: true)); @@ -223,9 +230,14 @@ Widget button(String text, IconData? icon, void Function()? onPressed, mainAxisAlignment: MainAxisAlignment.center, children: [ textWidget, - (description != null && desktopLayoutNotRequired(context)) + (description != null && + !alwaysMobileDescription && + (desktopLayoutNotRequired(context) || + !onlyDesktopDescription)) ? Text(description!, - style: const TextStyle(color: Colors.grey)) + style: const TextStyle( + color: Colors.grey, + overflow: TextOverflow.ellipsis)) : const SizedBox.shrink() ]); } else { @@ -234,9 +246,16 @@ Widget button(String text, IconData? icon, void Function()? onPressed, crossAxisAlignment: CrossAxisAlignment.center, children: [ textWidget, - (description != null && desktopLayoutNotRequired(context)) - ? Text(description!, - style: const TextStyle(color: Colors.grey)) + (description != null && + !alwaysMobileDescription && + (desktopLayoutNotRequired(context) || + !onlyDesktopDescription)) + ? Expanded( + child: Text(description!, + style: const TextStyle( + color: Colors.grey, + overflow: TextOverflow.ellipsis)), + ) : const SizedBox.shrink() ]); } @@ -286,9 +305,11 @@ class _ScreenSettingsState extends State { .cast(), ) ..followRedirects = false; - request = await http.Response.fromStream(await requestBase - .send() - .timeout(const Duration(seconds: 5), onTimeout: () { + request = await http.Response.fromStream(await requestBase.send().timeout( + Duration( + milliseconds: + (5000.0 * (prefs!.getDouble("timeoutMultiplier") ?? 1.0)) + .round()), onTimeout: () { return http.StreamedResponse(const Stream.empty(), 408); })); client.close(); diff --git a/lib/screen_voice.dart b/lib/screen_voice.dart index ef5289b..a704a7d 100644 --- a/lib/screen_voice.dart +++ b/lib/screen_voice.dart @@ -118,7 +118,9 @@ class _ScreenVoiceState extends State { "Add punctuation and syntax to the following sentence. You must not change order of words or a word in itself! You must not add any word or phrase or remove one! Do not change between formal and personal form, keep the original one!\n\n$text", keepAlive: int.parse(prefs!.getString("keepAlive") ?? "300")), ) - .timeout(const Duration(seconds: 10)); + .timeout(Duration( + seconds: (10.0 * (prefs!.getDouble("timeoutMultiplier") ?? 1.0)) + .round())); setState(() { text = generated.response!; }); diff --git a/lib/settings/interface.dart b/lib/settings/interface.dart index 0d0b973..7df9f37 100644 --- a/lib/settings/interface.dart +++ b/lib/settings/interface.dart @@ -1,3 +1,4 @@ +import 'package:dartx/dartx.dart'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; @@ -21,6 +22,25 @@ class ScreenSettingsInterface extends StatefulWidget { _ScreenSettingsInterfaceState(); } +String secondsBeautify(double seconds) { + String? endString; + int? endMinutes; + int? endSeconds; + + if (seconds > 60) { + endSeconds = seconds.toInt() % 60; + endMinutes = (seconds - endSeconds) ~/ 60; + + endString = "${endMinutes}m"; + if (endSeconds > 0) { + endString += " ${endSeconds}s"; + } + return "($endString)"; + } else { + return ""; + } +} + class _ScreenSettingsInterfaceState extends State { @override Widget build(BuildContext context) { @@ -258,6 +278,37 @@ class _ScreenSettingsInterfaceState extends State { }); }), titleDivider(context: context), + button( + AppLocalizations.of(context)! + .settingsTimeoutMultiplier, + Icons.info_outline_rounded, + null, + context: context, + alwaysMobileDescription: true, + description: + "\n${AppLocalizations.of(context)!.settingsTimeoutMultiplierDescription}"), + Slider( + value: (prefs!.getDouble("timeoutMultiplier") ?? 1), + min: 0.5, + divisions: 19, + max: 10, + label: (prefs!.getDouble("timeoutMultiplier") ?? 1) + .toString() + .removeSuffix(".0"), + onChanged: (value) { + selectionHaptic(); + prefs!.setDouble("timeoutMultiplier", value); + setState(() {}); + }), + button( + AppLocalizations.of(context)! + .settingsTimeoutMultiplierExample, + Icons.calculate_rounded, + null, + onlyDesktopDescription: false, + description: + "\n${(prefs!.getDouble("timeoutMultiplier") ?? 1)} x 30s = ${((prefs!.getDouble("timeoutMultiplier") ?? 1) * 30).round()}s ${secondsBeautify((prefs!.getDouble("timeoutMultiplier") ?? 1) * 30)}"), + titleDivider(context: context), toggle( context, AppLocalizations.of(context)! diff --git a/lib/worker/sender.dart b/lib/worker/sender.dart index a7fa50c..9c3d11e 100644 --- a/lib/worker/sender.dart +++ b/lib/worker/sender.dart @@ -99,9 +99,11 @@ Future getTitleAi(List history) async { ], keepAlive: int.parse(prefs!.getString("keepAlive") ?? "300")), ) - .timeout(const Duration(seconds: 10)); + .timeout(Duration( + seconds: + (10.0 * (prefs!.getDouble("timeoutMultiplier") ?? 1.0)).round())); var title = generated.message.content; - title = title.replaceAll("\n", " ").trim(); + title = title.replaceAll("\n", " "); var terms = [ "\"", @@ -127,13 +129,13 @@ Future getTitleAi(List history) async { title = title.replaceAll(RegExp(r'<.*?>', dotAll: true), ""); if (title.split(":").length == 2) { - title = title.split(":")[1].trim(); + title = title.split(":")[1]; } while (title.contains(" ")) { title = title.replaceAll(" ", " "); } - return title; + return title.trim(); } Future setTitleAi(List history) async { @@ -231,7 +233,9 @@ Future send(String value, BuildContext context, Function setState, messages: history, keepAlive: int.parse(prefs!.getString("keepAlive") ?? "300")), ) - .timeout(const Duration(seconds: 30)); + .timeout(Duration( + seconds: (30.0 * (prefs!.getDouble("timeoutMultiplier") ?? 1.0)) + .round())); await for (final res in stream) { text += (res.message.content); @@ -263,7 +267,9 @@ Future send(String value, BuildContext context, Function setState, messages: history, keepAlive: int.parse(prefs!.getString("keepAlive") ?? "300")), ) - .timeout(const Duration(seconds: 30)); + .timeout(Duration( + seconds: (30.0 * (prefs!.getDouble("timeoutMultiplier") ?? 1.0)) + .round())); if (chatAllowed) return ""; messages.insert( 0, diff --git a/lib/worker/setter.dart b/lib/worker/setter.dart index fa0d255..32d3eae 100644 --- a/lib/worker/setter.dart +++ b/lib/worker/setter.dart @@ -35,7 +35,9 @@ void setModel(BuildContext context, Function setState) { .cast(), baseUrl: "$host/api") .listModels() - .timeout(const Duration(seconds: 10)); + .timeout(Duration( + seconds: (10.0 * (prefs!.getDouble("timeoutMultiplier") ?? 1.0)) + .round())); for (var i = 0; i < list.models!.length; i++) { models.add(list.models![i].model!.split(":")[0]); modelsReal.add(list.models![i].model!); @@ -125,7 +127,10 @@ void setModel(BuildContext context, Function setState) { int.parse(prefs!.getString("keepAlive") ?? "300") }), ) - .timeout(const Duration(seconds: 15)); + .timeout(Duration( + seconds: (10.0 * + (prefs!.getDouble("timeoutMultiplier") ?? 1.0)) + .round())); } catch (_) { // ignore: use_build_context_synchronously ScaffoldMessenger.of(context).showSnackBar(SnackBar( @@ -420,7 +425,7 @@ Future deleteChatDialog(BuildContext context, Function setState, uuid ??= chatUuid; bool returnValue = false; - void delete() { + void delete(BuildContext context) { returnValue = true; if (takeAction) { for (var i = 0; i < (prefs!.getStringList("chats") ?? []).length; i++) { @@ -468,7 +473,7 @@ Future deleteChatDialog(BuildContext context, Function setState, onPressed: () { selectionHaptic(); Navigator.of(context).pop(); - delete(); + delete(context); }, child: Text( AppLocalizations.of(context)!.deleteDialogDelete)) @@ -476,7 +481,7 @@ Future deleteChatDialog(BuildContext context, Function setState, }); }); } else { - delete(); + delete(context); } setState(() {}); return returnValue; diff --git a/lib/worker/update.dart b/lib/worker/update.dart index a7cbe59..b928c15 100644 --- a/lib/worker/update.dart +++ b/lib/worker/update.dart @@ -6,6 +6,8 @@ import 'package:ollama_app/worker/desktop.dart'; import 'haptic.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import '../main.dart'; + import 'package:http/http.dart' as http; import 'package:install_referrer/install_referrer.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -87,7 +89,10 @@ void checkUpdate(Function setState) async { var request = await http .get(Uri.parse( "https://api.github.com/repos/${repo[3]}/${repo[4]}/releases")) - .timeout(const Duration(seconds: 5)); + .timeout(Duration( + milliseconds: + (5000.0 * (prefs!.getDouble("timeoutMultiplier") ?? 1.0)) + .round())); if (request.statusCode == 403) { setState(() { updateStatus = "rateLimit"; diff --git a/untranslated_messages.json b/untranslated_messages.json index c098fe4..9d29ef0 100644 --- a/untranslated_messages.json +++ b/untranslated_messages.json @@ -10,6 +10,9 @@ "settingsUseSystem", "settingsUseSystemDescription", "settingsPreloadModels", + "settingsTimeoutMultiplier", + "settingsTimeoutMultiplierDescription", + "settingsTimeoutMultiplierExample", "settingsTemporaryFixes", "settingsTemporaryFixesDescription", "settingsTemporaryFixesInstructions", @@ -32,6 +35,9 @@ "settingsUseSystem", "settingsUseSystemDescription", "settingsPreloadModels", + "settingsTimeoutMultiplier", + "settingsTimeoutMultiplierDescription", + "settingsTimeoutMultiplierExample", "settingsTemporaryFixes", "settingsTemporaryFixesDescription", "settingsTemporaryFixesInstructions", @@ -54,6 +60,9 @@ "settingsUseSystem", "settingsUseSystemDescription", "settingsPreloadModels", + "settingsTimeoutMultiplier", + "settingsTimeoutMultiplierDescription", + "settingsTimeoutMultiplierExample", "settingsTemporaryFixes", "settingsTemporaryFixesDescription", "settingsTemporaryFixesInstructions", @@ -76,6 +85,9 @@ "settingsUseSystem", "settingsUseSystemDescription", "settingsPreloadModels", + "settingsTimeoutMultiplier", + "settingsTimeoutMultiplierDescription", + "settingsTimeoutMultiplierExample", "settingsTemporaryFixes", "settingsTemporaryFixesDescription", "settingsTemporaryFixesInstructions",