diff --git a/lib/data/provider/pve.g.dart b/lib/data/provider/pve.g.dart index 4eba8f66..374b0afa 100644 --- a/lib/data/provider/pve.g.dart +++ b/lib/data/provider/pve.g.dart @@ -58,7 +58,7 @@ final class PveNotifierProvider } } -String _$pveNotifierHash() => r'b5da7240db1b9ee7d61f238cebca45821b7a3445'; +String _$pveNotifierHash() => r'ba5f2d6cb47c33735f7cc09b771b4a86501b86c6'; final class PveNotifierFamily extends $Family with $ClassFamilyOverride { diff --git a/lib/data/provider/server/all.dart b/lib/data/provider/server/all.dart index f18a9207..7005315e 100644 --- a/lib/data/provider/server/all.dart +++ b/lib/data/provider/server/all.dart @@ -239,6 +239,50 @@ class ServersNotifier extends _$ServersNotifier { bakSync.sync(milliDelay: 1000); } + void updateServerOrder(List order) { + final seen = {}; + final newOrder = []; + + for (final id in order) { + if (!state.servers.containsKey(id)) { + continue; + } + if (!seen.add(id)) { + continue; + } + newOrder.add(id); + } + + for (final id in state.servers.keys) { + if (seen.add(id)) { + newOrder.add(id); + } + } + + if (_isSameOrder(newOrder, state.serverOrder)) { + return; + } + + state = state.copyWith(serverOrder: newOrder); + Stores.setting.serverOrder.put(newOrder); + bakSync.sync(milliDelay: 1000); + } + + bool _isSameOrder(List a, List b) { + if (identical(a, b)) { + return true; + } + if (a.length != b.length) { + return false; + } + for (var i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } + Future updateServer(Spi old, Spi newSpi) async { if (old != newSpi) { Stores.server.update(old, newSpi); diff --git a/lib/data/provider/server/all.g.dart b/lib/data/provider/server/all.g.dart index 3ac8f018..9c2c7df5 100644 --- a/lib/data/provider/server/all.g.dart +++ b/lib/data/provider/server/all.g.dart @@ -41,7 +41,7 @@ final class ServersNotifierProvider } } -String _$serversNotifierHash() => r'2b29ad3027a203c7a20bfd0142d384a503cbbcaa'; +String _$serversNotifierHash() => r'3292bdce7d602ff64687b05ff81d120e71761ec2'; abstract class _$ServersNotifier extends $Notifier { ServersState build(); diff --git a/lib/data/provider/server/single.g.dart b/lib/data/provider/server/single.g.dart index 14e3da84..7556a58b 100644 --- a/lib/data/provider/server/single.g.dart +++ b/lib/data/provider/server/single.g.dart @@ -58,7 +58,7 @@ final class ServerNotifierProvider } } -String _$serverNotifierHash() => r'd9724fbe6d132f2e2ea4dfa5af73aeab168e1c57'; +String _$serverNotifierHash() => r'185c6b4546c3bc526f5b2ca79d16aed665818863'; final class ServerNotifierFamily extends $Family with diff --git a/lib/data/provider/systemd.g.dart b/lib/data/provider/systemd.g.dart index bfe90827..8ef2a6e0 100644 --- a/lib/data/provider/systemd.g.dart +++ b/lib/data/provider/systemd.g.dart @@ -58,7 +58,7 @@ final class SystemdNotifierProvider } } -String _$systemdNotifierHash() => r'98466bd176518545be49cae52f8dbe12af3a88a6'; +String _$systemdNotifierHash() => r'030d556efc3d897419cd3462d37cb705813e24c7'; final class SystemdNotifierFamily extends $Family with diff --git a/lib/view/page/setting/seq/srv_seq.dart b/lib/view/page/setting/seq/srv_seq.dart index 58a312a8..d8b71ce2 100644 --- a/lib/view/page/setting/seq/srv_seq.dart +++ b/lib/view/page/setting/seq/srv_seq.dart @@ -1,11 +1,11 @@ import 'dart:ui'; import 'package:fl_lib/fl_lib.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/provider/server/all.dart'; -import 'package:server_box/data/res/store.dart'; class ServerOrderPage extends ConsumerStatefulWidget { const ServerOrderPage({super.key}); @@ -17,15 +17,32 @@ class ServerOrderPage extends ConsumerStatefulWidget { } class _ServerOrderPageState extends ConsumerState { + late List _order; + + @override + void initState() { + super.initState(); + _order = List.from(ref.read(serversProvider).serverOrder); + } + @override Widget build(BuildContext context) { + ref.listen(serversProvider, (_, next) { + if (listEquals(_order, next.serverOrder)) { + return; + } + setState(() { + _order = List.from(next.serverOrder); + }); + }); + return Scaffold( appBar: CustomAppBar(title: Text(l10n.serverOrder)), body: _buildBody(), ); } - Widget _proxyDecorator(Widget child, int index, Animation animation) { + Widget _proxyDecorator(Widget child, int _, Animation animation) { return AnimatedBuilder( animation: animation, builder: (BuildContext context, Widget? child) { @@ -37,50 +54,61 @@ class _ServerOrderPageState extends ConsumerState { child: Card(elevation: elevation, child: child), ); }, - child: _buildCardTile(index), + child: child, ); } Widget _buildBody() { final serverState = ref.watch(serversProvider); - final order = serverState.serverOrder; - + final order = _order; + if (order.isEmpty) { return Center(child: Text(libL10n.empty)); } return ReorderableListView.builder( footer: const SizedBox(height: 77), onReorder: (oldIndex, newIndex) { + var targetIndex = newIndex; + if (targetIndex > oldIndex) { + targetIndex -= 1; + } + if (targetIndex == oldIndex) { + return; + } + + final newOrder = List.from(order); + final moved = newOrder.removeAt(oldIndex); + newOrder.insert(targetIndex, moved); + setState(() { - final newOrder = List.from(order); - newOrder.move(oldIndex, newIndex); - Stores.setting.serverOrder.put(newOrder); + _order = newOrder; }); + ref.read(serversProvider.notifier).updateServerOrder(newOrder); }, padding: const EdgeInsets.all(8), buildDefaultDragHandles: false, - itemBuilder: (_, idx) => _buildItem(idx, order[idx]), + itemBuilder: (_, idx) { + final id = order[idx]; + final spi = serverState.servers[id]; + return _buildItem(idx, id, spi); + }, itemCount: order.length, proxyDecorator: _proxyDecorator, ); } - Widget _buildItem(int index, String id) { + Widget _buildItem(int index, String id, Spi? spi) { return ReorderableDelayedDragStartListener( key: ValueKey('server_item_$id'), index: index, child: Padding( - padding: const EdgeInsets.only(bottom: 8), - child: CardX(child: _buildCardTile(index)), + padding: const EdgeInsets.only(bottom: 3), + child: _buildCardTile(index, spi).cardx, ), ); } - Widget _buildCardTile(int index) { - final serverState = ref.watch(serversProvider); - final order = serverState.serverOrder; - final id = order[index]; - final spi = serverState.servers[id]; + Widget _buildCardTile(int index, Spi? spi) { if (spi == null) { return const SizedBox(); } @@ -89,8 +117,6 @@ class _ServerOrderPageState extends ConsumerState { title: Text(spi.name, style: const TextStyle(fontWeight: FontWeight.w500)), subtitle: Text(spi.oldId, style: UIs.textGrey), leading: CircleAvatar( - backgroundColor: Theme.of(context).colorScheme.primary, - foregroundColor: Theme.of(context).colorScheme.onPrimary, child: Text(spi.name[0]), ), trailing: ReorderableDragStartListener(index: index, child: const Icon(Icons.drag_handle)),