Properly implemented toggle

Not hacky anymore 🎉
This commit is contained in:
JHubi1 2024-09-08 00:36:34 +02:00
parent 6c84f51267
commit 0629a8c0b5
No known key found for this signature in database
GPG Key ID: 7BF82570CBBBD050
3 changed files with 166 additions and 125 deletions

View File

@ -1,7 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:ollama_app/worker/theme.dart';
import 'main.dart'; import 'main.dart';
import 'worker/haptic.dart'; import 'worker/haptic.dart';
@ -29,9 +28,8 @@ Widget toggle(BuildContext context, String text, bool value,
void Function()? onDisabledTap, void Function()? onDisabledTap,
void Function()? onLongTap, void Function()? onLongTap,
void Function()? onDoubleTap, void Function()? onDoubleTap,
Widget? icon}) { Widget? icon,
var space = ""; // Invisible character: U+2063 bool? iconAfterwards}) {
var spacePlus = " $space";
return InkWell( return InkWell(
enableFeedback: false, enableFeedback: false,
splashFactory: NoSplash.splashFactory, splashFactory: NoSplash.splashFactory,
@ -51,65 +49,66 @@ Widget toggle(BuildContext context, String text, bool value,
onDoubleTap: onDoubleTap, onDoubleTap: onDoubleTap,
child: Padding( child: Padding(
padding: const EdgeInsets.only(top: 4, bottom: 4), padding: const EdgeInsets.only(top: 4, bottom: 4),
child: Stack(children: [ child: Row(children: [
Expanded(
child: LayoutBuilder(builder: (context, constraints) {
return Row(mainAxisSize: MainAxisSize.max, children: [
(icon != null && !(iconAfterwards ?? false))
? Padding(
padding: const EdgeInsets.only(right: 8),
child: icon,
)
: const SizedBox.shrink(),
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: constraints.maxWidth - (icon != null ? 32 : 0)),
child: Text(text,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(color: disabled ? Colors.grey : null)),
),
(icon != null && (iconAfterwards ?? false))
? Transform.translate(
offset: const Offset(0, 1),
child: Padding(
padding: const EdgeInsets.only(left: 8),
child: icon,
))
: const SizedBox.shrink(),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 16),
child: Divider(color: Theme.of(context).dividerColor)),
),
]);
}),
),
Padding( Padding(
padding: EdgeInsets.only( padding: const EdgeInsets.only(left: 16),
left: (icon == null) ? 16 : 32, right: 16, top: 12), child: Switch(
child: Divider(color: Theme.of(context).dividerColor)), value: value,
Row(mainAxisSize: MainAxisSize.max, children: [ onChanged: disabled
(icon != null) ? (onDisabledTap != null)
? Padding( ? (p0) {
padding: const EdgeInsets.only(right: 8), selectionHaptic();
child: icon, onDisabledTap();
) }
: const SizedBox.shrink(), : null
Expanded( : onChanged,
child: Text(text + spacePlus, activeTrackColor: disabled
overflow: TextOverflow.ellipsis, ? Theme.of(context).colorScheme.primary.withAlpha(50)
maxLines: 1, : null,
style: TextStyle( trackOutlineColor: disabled
color: disabled ? Colors.grey : null, ? WidgetStatePropertyAll(
backgroundColor: Theme.of(context).colorScheme.primary.withAlpha(150))
(Theme.of(context).brightness == Brightness.light) : null,
? themeLight().colorScheme.surface thumbColor: disabled
: themeDark().colorScheme.surface))), ? WidgetStatePropertyAll(
Container( Theme.of(context).colorScheme.primary.withAlpha(150))
padding: const EdgeInsets.only(left: 16), : !(prefs?.getBool("useDeviceTheme") ?? false) && value
color: (Theme.of(context).brightness == Brightness.light) ? WidgetStatePropertyAll(
? themeLight().colorScheme.surface Theme.of(context).colorScheme.secondary)
: themeDark().colorScheme.surface, : null))
child: SizedBox(
height: 40,
child: Switch(
value: value,
onChanged: disabled
? (onDisabledTap != null)
? (p0) {
selectionHaptic();
onDisabledTap();
}
: null
: onChanged,
activeTrackColor: disabled
? Theme.of(context).colorScheme.primary.withAlpha(50)
: null,
trackOutlineColor: disabled
? WidgetStatePropertyAll(Theme.of(context)
.colorScheme
.primary
.withAlpha(150))
: null,
thumbColor: disabled
? WidgetStatePropertyAll(Theme.of(context)
.colorScheme
.primary
.withAlpha(150))
: !(prefs?.getBool("useDeviceTheme") ?? false) &&
value
? WidgetStatePropertyAll(
Theme.of(context).colorScheme.secondary)
: null)))
]),
]), ]),
), ),
); );
@ -160,6 +159,7 @@ Widget button(String text, IconData? icon, void Function()? onPressed,
bool alwaysMobileDescription = false, bool alwaysMobileDescription = false,
String? badge, String? badge,
String? iconBadge, String? iconBadge,
bool? iconAfterwards,
void Function()? onDisabledTap, void Function()? onDisabledTap,
void Function()? onLongTap, void Function()? onLongTap,
void Function()? onDoubleTap}) { void Function()? onDoubleTap}) {
@ -177,6 +177,10 @@ Widget button(String text, IconData? icon, void Function()? onPressed,
: EdgeInsets.zero, : EdgeInsets.zero,
child: InkWell( child: InkWell(
enableFeedback: false, enableFeedback: false,
// disable hint that clickable, other tap functions still functional
splashFactory: (onPressed == null) ? NoSplash.splashFactory : null,
highlightColor: (onPressed == null) ? Colors.transparent : null,
hoverColor: (onPressed == null) ? Colors.transparent : null,
onTap: disabled onTap: disabled
? () { ? () {
selectionHaptic(); selectionHaptic();
@ -208,67 +212,99 @@ Widget button(String text, IconData? icon, void Function()? onPressed,
var iconContent = (icon != null || replaceIconIfNull) var iconContent = (icon != null || replaceIconIfNull)
? replaceIconIfNull ? replaceIconIfNull
? ImageIcon(MemoryImage(kTransparentImage)) ? ImageIcon(MemoryImage(kTransparentImage))
: Icon(icon, color: disabled ? Colors.grey : color) : Icon(icon,
color: disabled || (iconAfterwards ?? false)
? Colors.grey
: color)
: const SizedBox.shrink(); : const SizedBox.shrink();
return Row(children: [ return Row(
(iconBadge == null) crossAxisAlignment: CrossAxisAlignment.center,
? iconContent children: [
: Badge( !(iconAfterwards ?? false)
label: (iconBadge != "") ? Text(iconBadge) : null, ? (iconBadge == null)
child: iconContent), ? iconContent
(icon != null || replaceIconIfNull) : Badge(
? const SizedBox(width: 16, height: 42) label: (iconBadge != "") ? Text(iconBadge) : null,
: const SizedBox.shrink(), child: iconContent)
Expanded(child: Builder(builder: (context) { : const SizedBox.shrink(),
Widget textWidget = Text(text, (icon != null || replaceIconIfNull)
style: TextStyle(color: disabled ? Colors.grey : color)); ? SizedBox(
if (badge != null) { width: !(iconAfterwards ?? false) ? 16 : null,
textWidget = Badge( height: 42)
label: Text(badge), : const SizedBox.shrink(),
offset: const Offset(20, -4), Expanded(child: Builder(builder: (context) {
backgroundColor: Theme.of(context).colorScheme.primary, Widget textWidget = Text(text,
textColor: Theme.of(context).colorScheme.onPrimary, style:
child: textWidget); TextStyle(color: disabled ? Colors.grey : color));
} if (badge != null) {
if (description == null || description!.startsWith("\n")) { textWidget = Badge(
description = description?.removePrefix("\n"); label: Text(badge),
return Column( offset: const Offset(20, -4),
crossAxisAlignment: CrossAxisAlignment.start, backgroundColor:
mainAxisSize: MainAxisSize.min, Theme.of(context).colorScheme.primary,
mainAxisAlignment: MainAxisAlignment.center, textColor: Theme.of(context).colorScheme.onPrimary,
children: [ child: textWidget);
textWidget, }
(description != null && if (iconAfterwards ?? false) {
!alwaysMobileDescription && return Row(
(desktopLayoutNotRequired(context) || mainAxisAlignment: MainAxisAlignment.start,
!onlyDesktopDescription)) crossAxisAlignment: CrossAxisAlignment.center,
? Text(description!, children: [
style: const TextStyle( textWidget,
color: Colors.grey, // same info distance as [toggle]
overflow: TextOverflow.ellipsis)) const SizedBox(width: 8),
: const SizedBox.shrink() Transform.translate(
]); offset: const Offset(0, 1),
} else { child: (iconBadge == null)
return Row( ? iconContent
mainAxisAlignment: MainAxisAlignment.start, : Badge(
crossAxisAlignment: CrossAxisAlignment.center, label: (iconBadge != "")
children: [ ? Text(iconBadge)
textWidget, : null,
(description != null && child: iconContent)),
!alwaysMobileDescription && ]);
(desktopLayoutNotRequired(context) || } else {
!onlyDesktopDescription)) if (description == null ||
? Expanded( description!.startsWith("\n")) {
child: Text(description!, description = description?.removePrefix("\n");
style: const TextStyle( return Column(
color: Colors.grey, crossAxisAlignment: CrossAxisAlignment.start,
overflow: TextOverflow.ellipsis)), mainAxisSize: MainAxisSize.min,
) mainAxisAlignment: MainAxisAlignment.center,
: const SizedBox.shrink() children: [
]); textWidget,
} (description != null &&
})) !alwaysMobileDescription &&
]); (desktopLayoutNotRequired(context) ||
!onlyDesktopDescription))
? Text(description!,
style: const TextStyle(
color: Colors.grey,
overflow: TextOverflow.ellipsis))
: const SizedBox.shrink()
]);
} else {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
textWidget,
(description != null &&
!alwaysMobileDescription &&
(desktopLayoutNotRequired(context) ||
!onlyDesktopDescription))
? Expanded(
child: Text(description!,
style: const TextStyle(
color: Colors.grey,
overflow: TextOverflow.ellipsis)),
)
: const SizedBox.shrink()
]);
}
}
}))
]);
}), }),
)), )),
); );

View File

@ -78,7 +78,9 @@ class _ScreenSettingsBehaviorState extends State<ScreenSettingsBehavior> {
prefs!.setBool("useSystem", value); prefs!.setBool("useSystem", value);
setState(() {}); setState(() {});
}, },
icon: const Icon(Icons.info_outline_rounded), icon: const Icon(Icons.info_rounded,
color: Colors.grey),
iconAfterwards: true,
onLongTap: () { onLongTap: () {
selectionHaptic(); selectionHaptic();
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(

View File

@ -290,8 +290,9 @@ class _ScreenSettingsInterfaceState extends State<ScreenSettingsInterface> {
button( button(
AppLocalizations.of(context)! AppLocalizations.of(context)!
.settingsTimeoutMultiplier, .settingsTimeoutMultiplier,
Icons.info_outline_rounded, Icons.info_rounded,
null, null,
iconAfterwards: true,
context: context, context: context,
alwaysMobileDescription: true, alwaysMobileDescription: true,
description: description:
@ -380,7 +381,9 @@ class _ScreenSettingsInterfaceState extends State<ScreenSettingsInterface> {
setMainAppState!(() {}); setMainAppState!(() {});
setState(() {}); setState(() {});
}), }),
const SizedBox(height: 8), AnimatedContainer(
duration: const Duration(milliseconds: 200),
height: desktopLayoutNotRequired(context) ? 16 : 8),
(colorSchemeLight != null && colorSchemeDark != null) (colorSchemeLight != null && colorSchemeDark != null)
? SegmentedButton( ? SegmentedButton(
segments: [ segments: [