Improved desktop mode
This commit is contained in:
parent
4cc9e7d4c3
commit
34044e74bb
|
@ -165,26 +165,51 @@
|
||||||
"description": "Title of the behavior settings section",
|
"description": "Title of the behavior settings section",
|
||||||
"context": "Visible in the settings view"
|
"context": "Visible in the settings view"
|
||||||
},
|
},
|
||||||
|
"settingsDescriptionBehavior": "Change the behavior of the AI to your liking.",
|
||||||
|
"@settingsDescriptionBehavior": {
|
||||||
|
"description": "Description of the behavior settings section",
|
||||||
|
"context": "Visible in the settings view"
|
||||||
|
},
|
||||||
"settingsTitleInterface": "Interface",
|
"settingsTitleInterface": "Interface",
|
||||||
"@settingsTitleInterface": {
|
"@settingsTitleInterface": {
|
||||||
"description": "Title of the interface settings section",
|
"description": "Title of the interface settings section",
|
||||||
"context": "Visible in the settings view"
|
"context": "Visible in the settings view"
|
||||||
},
|
},
|
||||||
|
"settingsDescriptionInterface": "Edit how Ollama App looks and behaves.",
|
||||||
|
"@settingsDescriptionInterface": {
|
||||||
|
"description": "Description of the interface settings section",
|
||||||
|
"context": "Visible in the settings view"
|
||||||
|
},
|
||||||
"settingsTitleVoice": "Voice",
|
"settingsTitleVoice": "Voice",
|
||||||
"@settingsTitleVoice": {
|
"@settingsTitleVoice": {
|
||||||
"description": "Title of the voice settings section. Do not translate if not required!",
|
"description": "Title of the voice settings section. Do not translate if not required!",
|
||||||
"context": "Visible in the settings view"
|
"context": "Visible in the settings view"
|
||||||
},
|
},
|
||||||
|
"settingsDescriptionVoice": "Enable voice mode and configure voice settings.",
|
||||||
|
"@settingsDescriptionVoice": {
|
||||||
|
"description": "Description of the voice settings section",
|
||||||
|
"context": "Visible in the settings view"
|
||||||
|
},
|
||||||
"settingsTitleExport": "Export",
|
"settingsTitleExport": "Export",
|
||||||
"@settingsTitleExport": {
|
"@settingsTitleExport": {
|
||||||
"description": "Title of the export settings section",
|
"description": "Title of the export settings section",
|
||||||
"context": "Visible in the settings view"
|
"context": "Visible in the settings view"
|
||||||
},
|
},
|
||||||
|
"settingsDescriptionExport": "Export and import your chat history.",
|
||||||
|
"@settingsDescriptionExport": {
|
||||||
|
"description": "Description of the export settings section",
|
||||||
|
"context": "Visible in the settings view"
|
||||||
|
},
|
||||||
"settingsTitleAbout": "About",
|
"settingsTitleAbout": "About",
|
||||||
"@settingsTitleAbout": {
|
"@settingsTitleAbout": {
|
||||||
"description": "Title of the about settings section",
|
"description": "Title of the about settings section",
|
||||||
"context": "Visible in the settings view"
|
"context": "Visible in the settings view"
|
||||||
},
|
},
|
||||||
|
"settingsDescriptionAbout": "Check for updates and learn more about Ollama App.",
|
||||||
|
"@settingsDescriptionAbout": {
|
||||||
|
"description": "Description of the about settings section",
|
||||||
|
"context": "Visible in the settings view"
|
||||||
|
},
|
||||||
"settingsSavedAutomatically": "Settings are saved automatically",
|
"settingsSavedAutomatically": "Settings are saved automatically",
|
||||||
"@settingsSavedAutomatically": {
|
"@settingsSavedAutomatically": {
|
||||||
"description": "Text displayed when settings are saved automatically",
|
"description": "Text displayed when settings are saved automatically",
|
||||||
|
|
|
@ -259,7 +259,8 @@ class _MainAppState extends State<MainApp> {
|
||||||
left: desktopLayoutRequired(context) ? 17 : 12,
|
left: desktopLayoutRequired(context) ? 17 : 12,
|
||||||
right: desktopLayoutRequired(context) ? 17 : 12);
|
right: desktopLayoutRequired(context) ? 17 : 12);
|
||||||
return List.from([
|
return List.from([
|
||||||
desktopLayout(context)
|
desktopFeature() ? const SizedBox(height: 8) : const SizedBox.shrink(),
|
||||||
|
desktopLayoutNotRequired(context)
|
||||||
? const SizedBox.shrink()
|
? const SizedBox.shrink()
|
||||||
: (Padding(
|
: (Padding(
|
||||||
padding: padding,
|
padding: padding,
|
||||||
|
@ -282,11 +283,14 @@ class _MainAppState extends State<MainApp> {
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
]))))),
|
]))))),
|
||||||
desktopLayout(context)
|
desktopLayoutNotRequired(context)
|
||||||
? const SizedBox.shrink()
|
? const SizedBox.shrink()
|
||||||
: (!allowMultipleChats && !allowSettings)
|
: (!allowMultipleChats && !allowSettings)
|
||||||
? const SizedBox.shrink()
|
? const SizedBox.shrink()
|
||||||
: const Divider(),
|
: Divider(
|
||||||
|
color: desktopLayout(context)
|
||||||
|
? Theme.of(context).colorScheme.onSurface.withAlpha(20)
|
||||||
|
: null),
|
||||||
(allowMultipleChats)
|
(allowMultipleChats)
|
||||||
? (Padding(
|
? (Padding(
|
||||||
padding: padding,
|
padding: padding,
|
||||||
|
@ -1513,7 +1517,7 @@ class _MainAppState extends State<MainApp> {
|
||||||
drawerEdgeDragWidth:
|
drawerEdgeDragWidth:
|
||||||
desktopLayout(context) ? null : MediaQuery.of(context).size.width,
|
desktopLayout(context) ? null : MediaQuery.of(context).size.width,
|
||||||
drawer: Builder(builder: (context) {
|
drawer: Builder(builder: (context) {
|
||||||
if (desktopLayoutRequired(context)) {
|
if (desktopLayoutRequired(context) && !settingsOpen) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (Navigator.of(context).canPop()) {
|
if (Navigator.of(context).canPop()) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
|
@ -19,6 +19,7 @@ import 'package:dartx/dartx.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
||||||
import 'package:dynamic_color/dynamic_color.dart';
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
|
import 'package:transparent_image/transparent_image.dart';
|
||||||
|
|
||||||
Widget toggle(BuildContext context, String text, bool value,
|
Widget toggle(BuildContext context, String text, bool value,
|
||||||
Function(bool value) onChanged,
|
Function(bool value) onChanged,
|
||||||
|
@ -120,49 +121,99 @@ Widget title(String text, {double top = 16, double bottom = 16}) {
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget titleDivider({double top = 16, double bottom = 16}) {
|
Widget titleDivider({double? top, double? bottom, BuildContext? context}) {
|
||||||
|
top ??= (context != null && desktopLayoutNotRequired(context)) ? 32 : 16;
|
||||||
|
bottom ??= (context != null && desktopLayoutNotRequired(context)) ? 32 : 16;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(left: 8, right: 8, top: top, bottom: bottom),
|
padding: EdgeInsets.only(left: 8, right: 8, top: top, bottom: bottom),
|
||||||
child: const Row(
|
child: const Row(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: [
|
children: [Expanded(child: Divider())]));
|
||||||
Expanded(child: Divider()),
|
}
|
||||||
],
|
|
||||||
));
|
Widget verticalTitleDivider(
|
||||||
|
{double? left, double? right, BuildContext? context}) {
|
||||||
|
left ??= (context != null && desktopLayoutNotRequired(context)) ? 32 : 16;
|
||||||
|
right ??= (context != null && desktopLayoutNotRequired(context)) ? 32 : 16;
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(left: left, right: right, top: 8, bottom: 8),
|
||||||
|
child: const Row(mainAxisSize: MainAxisSize.max, children: [
|
||||||
|
// Expanded(child:
|
||||||
|
VerticalDivider()
|
||||||
|
// ),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget button(String text, IconData? icon, void Function()? onPressed,
|
Widget button(String text, IconData? icon, void Function()? onPressed,
|
||||||
{Color? color,
|
{BuildContext? context,
|
||||||
|
Color? color,
|
||||||
bool disabled = false,
|
bool disabled = false,
|
||||||
|
bool replaceIconIfNull = false,
|
||||||
|
String? description,
|
||||||
void Function()? onDisabledTap,
|
void Function()? onDisabledTap,
|
||||||
void Function()? onLongTap,
|
void Function()? onLongTap,
|
||||||
void Function()? onDoubleTap}) {
|
void Function()? onDoubleTap}) {
|
||||||
return InkWell(
|
if (description != null &&
|
||||||
onTap: disabled
|
(context != null && desktopLayoutNotRequired(context)) &&
|
||||||
? () {
|
!description.startsWith("\n")) {
|
||||||
selectionHaptic();
|
description = " • $description";
|
||||||
if (onDisabledTap != null) {
|
}
|
||||||
onDisabledTap();
|
return Padding(
|
||||||
|
padding: (context != null && desktopLayoutNotRequired(context))
|
||||||
|
? const EdgeInsets.only(top: 8, bottom: 8)
|
||||||
|
: EdgeInsets.zero,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: disabled
|
||||||
|
? () {
|
||||||
|
selectionHaptic();
|
||||||
|
if (onDisabledTap != null) {
|
||||||
|
onDisabledTap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
: onPressed,
|
||||||
: onPressed,
|
onLongPress: (description != null && context != null)
|
||||||
onLongPress: onLongTap,
|
? desktopLayoutNotRequired(context)
|
||||||
onDoubleTap: onDoubleTap,
|
? null
|
||||||
borderRadius: BorderRadius.circular(8),
|
: () {
|
||||||
child: Padding(
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
padding: const EdgeInsets.all(8),
|
content: Text(description!.trim()),
|
||||||
child: Row(children: [
|
showCloseIcon: true));
|
||||||
(icon != null)
|
}
|
||||||
? Icon(icon, color: disabled ? Colors.grey : color)
|
: onLongTap,
|
||||||
: const SizedBox.shrink(),
|
onDoubleTap: onDoubleTap,
|
||||||
(icon != null)
|
borderRadius: BorderRadius.circular(8),
|
||||||
? const SizedBox(width: 16, height: 42)
|
child: Padding(
|
||||||
: const SizedBox.shrink(),
|
padding: const EdgeInsets.all(8),
|
||||||
Expanded(
|
child: Row(children: [
|
||||||
child: Text(text,
|
(icon != null || replaceIconIfNull)
|
||||||
style: TextStyle(color: disabled ? Colors.grey : color)))
|
? replaceIconIfNull
|
||||||
]),
|
? ImageIcon(MemoryImage(kTransparentImage))
|
||||||
));
|
: Icon(icon, color: disabled ? Colors.grey : color)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
(icon != null || replaceIconIfNull)
|
||||||
|
? const SizedBox(width: 16, height: 42)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
Expanded(
|
||||||
|
child: (context != null)
|
||||||
|
? RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
text: text,
|
||||||
|
style: DefaultTextStyle.of(context).style.copyWith(
|
||||||
|
color: disabled ? Colors.grey : color),
|
||||||
|
children: [
|
||||||
|
(description != null &&
|
||||||
|
desktopLayoutNotRequired(context))
|
||||||
|
? TextSpan(
|
||||||
|
text: description,
|
||||||
|
style: const TextStyle(color: Colors.grey))
|
||||||
|
: const TextSpan()
|
||||||
|
]))
|
||||||
|
: Text(text,
|
||||||
|
style:
|
||||||
|
TextStyle(color: disabled ? Colors.grey : color)))
|
||||||
|
]),
|
||||||
|
)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScreenSettings extends StatefulWidget {
|
class ScreenSettings extends StatefulWidget {
|
||||||
|
@ -233,6 +284,10 @@ class _ScreenSettingsState extends State<ScreenSettings> {
|
||||||
selectionHaptic();
|
selectionHaptic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double iconSize = 1;
|
||||||
|
bool animatedInitialized = false;
|
||||||
|
bool animatedDesktop = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -249,6 +304,10 @@ class _ScreenSettingsState extends State<ScreenSettings> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
if (!animatedInitialized) {
|
||||||
|
animatedInitialized = true;
|
||||||
|
animatedDesktop = desktopLayoutNotRequired(context);
|
||||||
|
}
|
||||||
return PopScope(
|
return PopScope(
|
||||||
canPop: !hostLoading,
|
canPop: !hostLoading,
|
||||||
onPopInvoked: (didPop) {
|
onPopInvoked: (didPop) {
|
||||||
|
@ -267,222 +326,323 @@ class _ScreenSettingsState extends State<ScreenSettings> {
|
||||||
actions: desktopControlsActions(context)),
|
actions: desktopControlsActions(context)),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||||
child: Column(children: [
|
child: LayoutBuilder(builder: (context, constraints) {
|
||||||
Expanded(
|
var column1 =
|
||||||
child: ListView(children: [
|
Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
const SizedBox(height: 8),
|
AnimatedContainer(
|
||||||
TextField(
|
duration: const Duration(milliseconds: 200),
|
||||||
controller: hostInputController,
|
height: animatedDesktop ? 8 : 0,
|
||||||
keyboardType: TextInputType.url,
|
child: const SizedBox.shrink()),
|
||||||
readOnly: useHost,
|
const SizedBox(height: 8),
|
||||||
onSubmitted: (value) {
|
TextField(
|
||||||
selectionHaptic();
|
controller: hostInputController,
|
||||||
checkHost();
|
keyboardType: TextInputType.url,
|
||||||
},
|
readOnly: useHost,
|
||||||
decoration: InputDecoration(
|
onSubmitted: (value) {
|
||||||
labelText: AppLocalizations.of(context)!
|
selectionHaptic();
|
||||||
.settingsHost,
|
checkHost();
|
||||||
hintText: "http://localhost:11434",
|
},
|
||||||
prefixIcon: IconButton(
|
decoration: InputDecoration(
|
||||||
tooltip: AppLocalizations.of(context)!
|
labelText:
|
||||||
.tooltipAddHostHeaders,
|
AppLocalizations.of(context)!.settingsHost,
|
||||||
onPressed: () async {
|
hintText: "http://localhost:11434",
|
||||||
selectionHaptic();
|
prefixIcon: IconButton(
|
||||||
String tmp = await prompt(context,
|
tooltip: AppLocalizations.of(context)!
|
||||||
placeholder:
|
.tooltipAddHostHeaders,
|
||||||
"{\"Authorization\": \"Bearer ...\"}",
|
onPressed: () async {
|
||||||
title: AppLocalizations.of(context)!
|
selectionHaptic();
|
||||||
.settingsHostHeaderTitle,
|
String tmp = await prompt(context,
|
||||||
value: (prefs!
|
placeholder:
|
||||||
.getString("hostHeaders") ??
|
"{\"Authorization\": \"Bearer ...\"}",
|
||||||
""),
|
title: AppLocalizations.of(context)!
|
||||||
valueIfCanceled: "{}",
|
.settingsHostHeaderTitle,
|
||||||
validator: (content) async {
|
value: (prefs!
|
||||||
try {
|
.getString("hostHeaders") ??
|
||||||
var tmp = jsonDecode(content);
|
""),
|
||||||
tmp as Map<String, dynamic>;
|
valueIfCanceled: "{}",
|
||||||
return true;
|
validator: (content) async {
|
||||||
} catch (_) {
|
try {
|
||||||
return false;
|
var tmp = jsonDecode(content);
|
||||||
}
|
tmp as Map<String, dynamic>;
|
||||||
},
|
return true;
|
||||||
validatorError:
|
} catch (_) {
|
||||||
AppLocalizations.of(context)!
|
return false;
|
||||||
.settingsHostHeaderInvalid,
|
}
|
||||||
prefill: !((prefs!.getString(
|
|
||||||
"hostHeaders") ??
|
|
||||||
{}) ==
|
|
||||||
"{}"));
|
|
||||||
prefs!.setString("hostHeaders", tmp);
|
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.add_rounded)),
|
validatorError:
|
||||||
suffixIcon: useHost
|
AppLocalizations.of(context)!
|
||||||
? const SizedBox.shrink()
|
.settingsHostHeaderInvalid,
|
||||||
: (hostLoading
|
prefill: !((prefs!.getString(
|
||||||
? Transform.scale(
|
"hostHeaders") ??
|
||||||
scale: 0.5,
|
{}) ==
|
||||||
child:
|
"{}"));
|
||||||
const CircularProgressIndicator())
|
prefs!.setString("hostHeaders", tmp);
|
||||||
: IconButton(
|
},
|
||||||
tooltip:
|
icon: const Icon(Icons.add_rounded)),
|
||||||
AppLocalizations.of(context)!
|
suffixIcon: useHost
|
||||||
.tooltipSave,
|
? const SizedBox.shrink()
|
||||||
onPressed: () {
|
: (hostLoading
|
||||||
selectionHaptic();
|
? Transform.scale(
|
||||||
checkHost();
|
scale: 0.5,
|
||||||
},
|
child:
|
||||||
icon: const Icon(
|
const CircularProgressIndicator())
|
||||||
Icons.save_rounded),
|
: IconButton(
|
||||||
)),
|
tooltip:
|
||||||
border: const OutlineInputBorder(),
|
AppLocalizations.of(context)!
|
||||||
error: (hostInvalidHost || hostInvalidUrl)
|
.tooltipSave,
|
||||||
? InkWell(
|
onPressed: () {
|
||||||
onTap: () {
|
selectionHaptic();
|
||||||
selectionHaptic();
|
checkHost();
|
||||||
ScaffoldMessenger.of(context)
|
},
|
||||||
.showSnackBar(SnackBar(
|
icon:
|
||||||
content: Text(AppLocalizations
|
const Icon(Icons.save_rounded),
|
||||||
.of(context)!
|
)),
|
||||||
.settingsHostInvalidDetailed(
|
border: const OutlineInputBorder(),
|
||||||
hostInvalidHost
|
error: (hostInvalidHost || hostInvalidUrl)
|
||||||
? "host"
|
? InkWell(
|
||||||
: "url")),
|
onTap: () {
|
||||||
showCloseIcon: true));
|
selectionHaptic();
|
||||||
},
|
ScaffoldMessenger.of(context)
|
||||||
highlightColor: Colors.transparent,
|
.showSnackBar(SnackBar(
|
||||||
splashFactory: NoSplash.splashFactory,
|
content: Text(AppLocalizations
|
||||||
child: Row(
|
.of(context)!
|
||||||
|
.settingsHostInvalidDetailed(
|
||||||
|
hostInvalidHost
|
||||||
|
? "host"
|
||||||
|
: "url")),
|
||||||
|
showCloseIcon: true));
|
||||||
|
},
|
||||||
|
splashFactory: NoSplash.splashFactory,
|
||||||
|
highlightColor: Colors.transparent,
|
||||||
|
hoverColor: Colors.transparent,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.error_rounded,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.error),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
AppLocalizations.of(context)!
|
||||||
|
.settingsHostInvalid(
|
||||||
|
hostInvalidHost
|
||||||
|
? "host"
|
||||||
|
: "url"),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.error))
|
||||||
|
],
|
||||||
|
))
|
||||||
|
: null,
|
||||||
|
helper: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
selectionHaptic();
|
||||||
|
},
|
||||||
|
splashFactory: NoSplash.splashFactory,
|
||||||
|
highlightColor: Colors.transparent,
|
||||||
|
hoverColor: Colors.transparent,
|
||||||
|
child: hostLoading
|
||||||
|
? Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.error_rounded,
|
const Icon(Icons.search_rounded,
|
||||||
color: Theme.of(context)
|
color: Colors.grey),
|
||||||
.colorScheme
|
|
||||||
.error),
|
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
AppLocalizations.of(context)!
|
AppLocalizations.of(context)!
|
||||||
.settingsHostInvalid(
|
.settingsHostChecking,
|
||||||
hostInvalidHost
|
style: const TextStyle(
|
||||||
? "host"
|
color: Colors.grey,
|
||||||
: "url"),
|
fontFamily: "monospace"))
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.error))
|
|
||||||
],
|
],
|
||||||
))
|
)
|
||||||
: null,
|
: Row(
|
||||||
helper: InkWell(
|
children: [
|
||||||
onTap: () {
|
Icon(Icons.check_rounded,
|
||||||
selectionHaptic();
|
color: Colors.green
|
||||||
},
|
.harmonizeWith(
|
||||||
highlightColor: Colors.transparent,
|
Theme.of(context)
|
||||||
splashFactory: NoSplash.splashFactory,
|
.colorScheme
|
||||||
child: hostLoading
|
.primary)),
|
||||||
? Row(
|
const SizedBox(width: 8),
|
||||||
children: [
|
Text(
|
||||||
const Icon(Icons.search_rounded,
|
AppLocalizations.of(context)!
|
||||||
color: Colors.grey),
|
.settingsHostValid,
|
||||||
const SizedBox(width: 8),
|
style: TextStyle(
|
||||||
Text(
|
color: Colors.green
|
||||||
|
.harmonizeWith(
|
||||||
|
Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.primary),
|
||||||
|
fontFamily: "monospace"))
|
||||||
|
],
|
||||||
|
))))
|
||||||
|
]);
|
||||||
|
var column2 =
|
||||||
|
Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
|
button(
|
||||||
|
AppLocalizations.of(context)!.settingsTitleBehavior,
|
||||||
|
Icons.psychology_rounded, () {
|
||||||
|
selectionHaptic();
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const ScreenSettingsBehavior()));
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
description:
|
||||||
|
"\n${AppLocalizations.of(context)!.settingsDescriptionBehavior}"),
|
||||||
|
button(
|
||||||
|
AppLocalizations.of(context)!
|
||||||
|
.settingsTitleInterface,
|
||||||
|
Icons.web_asset_rounded, () {
|
||||||
|
selectionHaptic();
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const ScreenSettingsInterface()));
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
description:
|
||||||
|
"\n${AppLocalizations.of(context)!.settingsDescriptionInterface}"),
|
||||||
|
(!desktopFeature())
|
||||||
|
? button(
|
||||||
|
AppLocalizations.of(context)!
|
||||||
|
.settingsTitleVoice,
|
||||||
|
Icons.headphones_rounded, () {
|
||||||
|
selectionHaptic();
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const ScreenSettingsVoice()));
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
description:
|
||||||
|
"\n${AppLocalizations.of(context)!.settingsDescriptionVoice}")
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
button(
|
||||||
|
AppLocalizations.of(context)!.settingsTitleExport,
|
||||||
|
Icons.share_rounded, () {
|
||||||
|
selectionHaptic();
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const ScreenSettingsExport()));
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
description:
|
||||||
|
"\n${AppLocalizations.of(context)!.settingsDescriptionExport}"),
|
||||||
|
button(AppLocalizations.of(context)!.settingsTitleAbout,
|
||||||
|
Icons.help_rounded, () {
|
||||||
|
selectionHaptic();
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const ScreenSettingsAbout()));
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
description:
|
||||||
|
"\n${AppLocalizations.of(context)!.settingsDescriptionAbout}")
|
||||||
|
]);
|
||||||
|
animatedDesktop = desktopLayoutNotRequired(context);
|
||||||
|
return Column(children: [
|
||||||
|
Expanded(
|
||||||
|
child: desktopLayoutNotRequired(context)
|
||||||
|
? Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
column1,
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: InkWell(
|
||||||
|
splashFactory:
|
||||||
|
NoSplash.splashFactory,
|
||||||
|
highlightColor:
|
||||||
|
Colors.transparent,
|
||||||
|
enableFeedback: false,
|
||||||
|
hoverColor: Colors.transparent,
|
||||||
|
onTap: () async {
|
||||||
|
if (iconSize != 1) return;
|
||||||
|
heavyHaptic();
|
||||||
|
setState(() {
|
||||||
|
iconSize = 0.8;
|
||||||
|
});
|
||||||
|
await Future.delayed(
|
||||||
|
const Duration(
|
||||||
|
milliseconds: 200));
|
||||||
|
setState(() {
|
||||||
|
iconSize = 1.2;
|
||||||
|
});
|
||||||
|
await Future.delayed(
|
||||||
|
const Duration(
|
||||||
|
milliseconds: 200));
|
||||||
|
setState(() {
|
||||||
|
iconSize = 1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: AnimatedScale(
|
||||||
|
scale: iconSize,
|
||||||
|
duration: const Duration(
|
||||||
|
milliseconds: 400),
|
||||||
|
child: const ImageIcon(
|
||||||
|
AssetImage(
|
||||||
|
"assets/logo512.png"),
|
||||||
|
size: 44),
|
||||||
|
),
|
||||||
|
))),
|
||||||
|
Transform.translate(
|
||||||
|
offset: const Offset(0, 8),
|
||||||
|
child: button(
|
||||||
AppLocalizations.of(
|
AppLocalizations.of(
|
||||||
context)!
|
context)!
|
||||||
.settingsHostChecking,
|
.settingsSavedAutomatically,
|
||||||
style: const TextStyle(
|
Icons.info_rounded,
|
||||||
color: Colors.grey,
|
null,
|
||||||
fontFamily:
|
color: Colors.grey
|
||||||
"monospace"))
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.check_rounded,
|
|
||||||
color: Colors.green
|
|
||||||
.harmonizeWith(
|
.harmonizeWith(
|
||||||
Theme.of(context)
|
Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.primary)),
|
.primary)),
|
||||||
const SizedBox(width: 8),
|
)
|
||||||
Text(
|
])),
|
||||||
AppLocalizations.of(
|
verticalTitleDivider(context: context),
|
||||||
context)!
|
Expanded(child: column2)
|
||||||
.settingsHostValid,
|
])
|
||||||
style: TextStyle(
|
: ListView(children: [
|
||||||
color: Colors.green
|
column1,
|
||||||
.harmonizeWith(
|
AnimatedOpacity(
|
||||||
Theme.of(
|
opacity: animatedDesktop ? 0 : 1,
|
||||||
context)
|
duration:
|
||||||
.colorScheme
|
const Duration(milliseconds: 200),
|
||||||
.primary),
|
child: titleDivider(bottom: 4)),
|
||||||
fontFamily:
|
AnimatedOpacity(
|
||||||
"monospace"))
|
opacity: animatedDesktop ? 0 : 1,
|
||||||
],
|
duration:
|
||||||
)))),
|
const Duration(milliseconds: 200),
|
||||||
titleDivider(bottom: 4),
|
child: column2)
|
||||||
button(
|
])),
|
||||||
AppLocalizations.of(context)!
|
const SizedBox(height: 8),
|
||||||
.settingsTitleBehavior,
|
desktopLayoutNotRequired(context)
|
||||||
Icons.psychology_rounded, () {
|
? const SizedBox.shrink()
|
||||||
selectionHaptic();
|
: button(
|
||||||
Navigator.push(
|
AppLocalizations.of(context)!
|
||||||
context,
|
.settingsSavedAutomatically,
|
||||||
MaterialPageRoute(
|
Icons.info_rounded,
|
||||||
builder: (context) =>
|
null,
|
||||||
const ScreenSettingsBehavior()));
|
color: Colors.grey.harmonizeWith(
|
||||||
}),
|
Theme.of(context).colorScheme.primary))
|
||||||
button(
|
]);
|
||||||
AppLocalizations.of(context)!
|
})))));
|
||||||
.settingsTitleInterface,
|
|
||||||
Icons.web_asset_rounded, () {
|
|
||||||
selectionHaptic();
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) =>
|
|
||||||
const ScreenSettingsInterface()));
|
|
||||||
}),
|
|
||||||
(!desktopFeature())
|
|
||||||
? button(
|
|
||||||
AppLocalizations.of(context)!
|
|
||||||
.settingsTitleVoice,
|
|
||||||
Icons.headphones_rounded, () {
|
|
||||||
selectionHaptic();
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) =>
|
|
||||||
const ScreenSettingsVoice()));
|
|
||||||
})
|
|
||||||
: const SizedBox.shrink(),
|
|
||||||
button(
|
|
||||||
AppLocalizations.of(context)!.settingsTitleExport,
|
|
||||||
Icons.share_rounded, () {
|
|
||||||
selectionHaptic();
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) =>
|
|
||||||
const ScreenSettingsExport()));
|
|
||||||
}),
|
|
||||||
button(
|
|
||||||
AppLocalizations.of(context)!.settingsTitleAbout,
|
|
||||||
Icons.help_rounded, () {
|
|
||||||
selectionHaptic();
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) =>
|
|
||||||
const ScreenSettingsAbout()));
|
|
||||||
})
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
button(
|
|
||||||
AppLocalizations.of(context)!
|
|
||||||
.settingsSavedAutomatically,
|
|
||||||
Icons.info_rounded,
|
|
||||||
null,
|
|
||||||
color: Colors.grey.harmonizeWith(
|
|
||||||
Theme.of(context).colorScheme.primary))
|
|
||||||
])))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,13 +37,11 @@ class _ScreenSettingsAboutState extends State<ScreenSettingsAbout> {
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(children: [
|
title: Row(children: [
|
||||||
Text(AppLocalizations.of(context)!.settingsTitleAbout),
|
Text(AppLocalizations.of(context)!.settingsTitleAbout),
|
||||||
Expanded(child: SizedBox(height: 200, child: MoveWindow()))
|
Expanded(child: SizedBox(height: 200, child: MoveWindow()))
|
||||||
]),
|
]),
|
||||||
actions:
|
actions: desktopControlsActions(context)),
|
||||||
desktopControlsActions(context)
|
|
||||||
),
|
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
|
@ -110,7 +108,7 @@ class _ScreenSettingsAboutState extends State<ScreenSettingsAbout> {
|
||||||
prefs!.setBool("checkUpdateOnSettingsOpen", value);
|
prefs!.setBool("checkUpdateOnSettingsOpen", value);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}),
|
}),
|
||||||
titleDivider(),
|
titleDivider(context: context),
|
||||||
button(AppLocalizations.of(context)!.settingsGithub,
|
button(AppLocalizations.of(context)!.settingsGithub,
|
||||||
SimpleIcons.github, () {
|
SimpleIcons.github, () {
|
||||||
selectionHaptic();
|
selectionHaptic();
|
||||||
|
|
|
@ -46,7 +46,7 @@ class _ScreenSettingsBehaviorState extends State<ScreenSettingsBehavior> {
|
||||||
TextField(
|
TextField(
|
||||||
controller: systemInputController,
|
controller: systemInputController,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
maxLines: 2,
|
maxLines: desktopLayoutNotRequired(context) ? 5 : 2,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: AppLocalizations.of(context)!
|
labelText: AppLocalizations.of(context)!
|
||||||
.settingsSystemMessage,
|
.settingsSystemMessage,
|
||||||
|
|
|
@ -64,7 +64,9 @@ class _ScreenSettingsInterfaceState extends State<ScreenSettingsInterface> {
|
||||||
prefs!.setBool("resetOnModelSelect", value);
|
prefs!.setBool("resetOnModelSelect", value);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}),
|
}),
|
||||||
titleDivider(bottom: 20),
|
titleDivider(
|
||||||
|
bottom: desktopLayoutNotRequired(context) ? 38 : 20,
|
||||||
|
context: context),
|
||||||
SegmentedButton(
|
SegmentedButton(
|
||||||
segments: [
|
segments: [
|
||||||
ButtonSegment(
|
ButtonSegment(
|
||||||
|
@ -121,7 +123,7 @@ class _ScreenSettingsInterfaceState extends State<ScreenSettingsInterface> {
|
||||||
prefs!.setBool("tips", value);
|
prefs!.setBool("tips", value);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}),
|
}),
|
||||||
titleDivider(),
|
titleDivider(context: context),
|
||||||
toggle(
|
toggle(
|
||||||
context,
|
context,
|
||||||
AppLocalizations.of(context)!
|
AppLocalizations.of(context)!
|
||||||
|
@ -240,7 +242,7 @@ class _ScreenSettingsInterfaceState extends State<ScreenSettingsInterface> {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
titleDivider(),
|
titleDivider(context: context),
|
||||||
toggle(
|
toggle(
|
||||||
context,
|
context,
|
||||||
AppLocalizations.of(context)!
|
AppLocalizations.of(context)!
|
||||||
|
|
Loading…
Reference in New Issue