settings page

This commit is contained in:
nyne
2024-10-11 21:47:50 +08:00
parent f228c7ee17
commit a26e5e20de
21 changed files with 1515 additions and 26 deletions

View File

@@ -251,3 +251,225 @@ class _SliderSettingState extends State<_SliderSetting> {
);
}
}
class _PopupWindowSetting extends StatelessWidget {
const _PopupWindowSetting({required this.title, required this.builder});
final Widget Function() builder;
final String title;
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(title),
trailing: const Icon(Icons.arrow_right),
onTap: () {
showPopUpWidget(App.rootContext, builder());
},
);
}
}
class _MultiPagesFilter extends StatefulWidget {
const _MultiPagesFilter({
required this.title,
required this.settingsIndex,
required this.pages,
});
final String title;
final String settingsIndex;
// key - name
final Map<String, String> pages;
@override
State<_MultiPagesFilter> createState() => _MultiPagesFilterState();
}
class _MultiPagesFilterState extends State<_MultiPagesFilter> {
late List<String> keys;
@override
void initState() {
keys = List.from(appdata.settings[widget.settingsIndex]);
keys.remove("");
super.initState();
}
var reorderWidgetKey = UniqueKey();
var scrollController = ScrollController();
final _key = GlobalKey();
@override
Widget build(BuildContext context) {
var tiles = keys.map((e) => buildItem(e)).toList();
var view = ReorderableBuilder(
key: reorderWidgetKey,
scrollController: scrollController,
longPressDelay: App.isDesktop
? const Duration(milliseconds: 100)
: const Duration(milliseconds: 500),
dragChildBoxDecoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 5,
offset: Offset(0, 2),
spreadRadius: 2)
],
),
onReorder: (reorderFunc) {
setState(() {
keys = List.from(reorderFunc(keys));
});
updateSetting();
},
children: tiles,
builder: (children) {
return GridView(
key: _key,
controller: scrollController,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
mainAxisExtent: 48,
),
children: children,
);
},
);
return PopUpWidgetScaffold(
title: widget.title,
tailing: [
if (keys.length < widget.pages.length)
IconButton(onPressed: showAddDialog, icon: const Icon(Icons.add))
],
body: view,
);
}
Widget buildItem(String key) {
Widget removeButton = Padding(
padding: const EdgeInsets.only(right: 8),
child: IconButton(
onPressed: () {
setState(() {
keys.remove(key);
});
updateSetting();
},
icon: const Icon(Icons.delete)),
);
return ListTile(
title: Text(widget.pages[key] ?? "(Invalid) $key"),
key: Key(key),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
removeButton,
const Icon(Icons.drag_handle),
],
),
);
}
void showAddDialog() {
var canAdd = <String, String>{};
widget.pages.forEach((key, value) {
if (!keys.contains(key)) {
canAdd[key] = value;
}
});
showDialog(
context: context,
builder: (context) {
return SimpleDialog(
title: const Text("Add"),
children: canAdd.entries
.map((e) => InkWell(
child: ListTile(title: Text(e.value), key: Key(e.key)),
onTap: () {
context.pop();
setState(() {
keys.add(e.key);
});
updateSetting();
},
))
.toList(),
);
});
}
void updateSetting() {
appdata.settings[widget.settingsIndex] = keys;
appdata.saveData();
}
}
class _CallbackSetting extends StatelessWidget {
const _CallbackSetting({
required this.title,
required this.callback,
required this.actionTitle,
this.subtitle,
});
final String title;
final String? subtitle;
final VoidCallback callback;
final String actionTitle;
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(title),
subtitle: subtitle == null ? null : Text(subtitle!),
trailing: FilledButton(
onPressed: callback,
child: Text(actionTitle),
).fixHeight(28),
onTap: callback,
);
}
}
class _SettingPartTitle extends StatelessWidget {
const _SettingPartTitle({required this.title, required this.icon});
final String title;
final IconData icon;
@override
Widget build(BuildContext context) {
return SliverToBoxAdapter(
child: Container(
padding: const EdgeInsets.only(left: 16, top: 16, bottom: 8),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: context.colorScheme.onSurface.withOpacity(0.1),
),
),
),
child: Row(
children: [
Icon(icon, size: 24),
const SizedBox(width: 8),
Text(title, style: ts.s18),
],
),
),
);
}
}