mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
settings page
This commit is contained in:
@@ -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),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user