Added timeout multiplicator

This commit is contained in:
JHubi1 2024-08-23 18:26:46 +02:00
parent a9fed3e36d
commit 20dbce2f34
No known key found for this signature in database
GPG Key ID: 7BF82570CBBBD050
8 changed files with 142 additions and 65 deletions

View File

@ -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",

View File

@ -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<ScreenSettings> {
.cast<String, String>(),
)
..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();

View File

@ -118,7 +118,9 @@ class _ScreenVoiceState extends State<ScreenVoice> {
"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!;
});

View File

@ -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<ScreenSettingsInterface> {
@override
Widget build(BuildContext context) {
@ -258,6 +278,37 @@ class _ScreenSettingsInterfaceState extends State<ScreenSettingsInterface> {
});
}),
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)!

View File

@ -99,9 +99,11 @@ Future<String> 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<String> 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<void> setTitleAi(List history) async {
@ -231,7 +233,9 @@ Future<String> 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<String> 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,

View File

@ -35,7 +35,9 @@ void setModel(BuildContext context, Function setState) {
.cast<String, String>(),
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<bool> 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<bool> 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<bool> deleteChatDialog(BuildContext context, Function setState,
});
});
} else {
delete();
delete(context);
}
setState(() {});
return returnValue;

View File

@ -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";

View File

@ -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",