diff --git a/lib/core/extension/server.dart b/lib/core/extension/server.dart index 27e587dd..3809058d 100644 --- a/lib/core/extension/server.dart +++ b/lib/core/extension/server.dart @@ -2,7 +2,7 @@ import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:server_box/data/model/app/scripts/cmd_types.dart'; import 'package:server_box/data/model/server/dist.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; import 'package:server_box/data/res/store.dart'; extension LogoExt on ServerState { diff --git a/lib/data/model/server/server_status_update_req.dart b/lib/data/model/server/server_status_update_req.dart index 22572423..9e40d211 100644 --- a/lib/data/model/server/server_status_update_req.dart +++ b/lib/data/model/server/server_status_update_req.dart @@ -104,6 +104,11 @@ Future _getLinuxStatus(ServerStatusUpdateReq req) async { try { req.ss.disk = Disk.parse(StatusCmdType.disk.findInMap(parsedOutput)); + } catch (e, s) { + Loggers.app.warning(e, s); + } + + try { req.ss.diskUsage = DiskUsage.parse(req.ss.disk); } catch (e, s) { Loggers.app.warning(e, s); diff --git a/lib/data/provider/providers.dart b/lib/data/provider/providers.dart index 231b65a1..d3656fbc 100644 --- a/lib/data/provider/providers.dart +++ b/lib/data/provider/providers.dart @@ -2,7 +2,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:server_box/data/provider/app.dart'; import 'package:server_box/data/provider/private_key.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/data/provider/sftp.dart'; import 'package:server_box/data/provider/snippet.dart'; @@ -45,7 +45,7 @@ final class ReadMyProvider { T call(ProviderBase provider) => ref.read(provider); // Specific provider getters - ServersState get server => ref.read(serverNotifierProvider); + ServersState get server => ref.read(serversNotifierProvider); SnippetState get snippet => ref.read(snippetNotifierProvider); AppState get app => ref.read(appStatesProvider); PrivateKeyState get privateKey => ref.read(privateKeyNotifierProvider); @@ -59,7 +59,7 @@ final class WatchMyProvider { T call(ProviderBase provider) => ref.watch(provider); // Specific provider getters - ServersState get server => ref.watch(serverNotifierProvider); + ServersState get server => ref.watch(serversNotifierProvider); SnippetState get snippet => ref.watch(snippetNotifierProvider); AppState get app => ref.watch(appStatesProvider); PrivateKeyState get privateKey => ref.watch(privateKeyNotifierProvider); @@ -74,7 +74,7 @@ final class UseNotifierMyProvider { ref.read(provider.notifier); // Specific provider notifier getters - ServerNotifier get server => ref.read(serverNotifierProvider.notifier); + ServersNotifier get server => ref.read(serversNotifierProvider.notifier); SnippetNotifier get snippet => ref.read(snippetNotifierProvider.notifier); AppStates get app => ref.read(appStatesProvider.notifier); PrivateKeyNotifier get privateKey => ref.read(privateKeyNotifierProvider.notifier); diff --git a/lib/data/provider/pve.dart b/lib/data/provider/pve.dart index 0da1ba5d..b96aeff1 100644 --- a/lib/data/provider/pve.dart +++ b/lib/data/provider/pve.dart @@ -13,7 +13,7 @@ import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/data/model/app/error.dart'; import 'package:server_box/data/model/server/pve.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; part 'pve.freezed.dart'; part 'pve.g.dart'; @@ -45,7 +45,7 @@ class PveNotifier extends _$PveNotifier { @override PveState build(Spi spiParam) { spi = spiParam; - final serverState = ref.watch(individualServerNotifierProvider(spi.id)); + final serverState = ref.watch(serverNotifierProvider(spi.id)); final client = serverState.client; if (client == null) { return const PveState(error: PveErr(type: PveErrType.net, message: 'Server client is null')); diff --git a/lib/data/provider/pve.g.dart b/lib/data/provider/pve.g.dart index bde21a40..dcd197fb 100644 --- a/lib/data/provider/pve.g.dart +++ b/lib/data/provider/pve.g.dart @@ -6,7 +6,7 @@ part of 'pve.dart'; // RiverpodGenerator // ************************************************************************** -String _$pveNotifierHash() => r'667cfb11cd7118d57b29918d137ef2cda2bad7ad'; +String _$pveNotifierHash() => r'b5da7240db1b9ee7d61f238cebca45821b7a3445'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/data/provider/server/all.dart b/lib/data/provider/server/all.dart new file mode 100644 index 00000000..4e4a194e --- /dev/null +++ b/lib/data/provider/server/all.dart @@ -0,0 +1,273 @@ + +import 'dart:async'; + +import 'package:fl_lib/fl_lib.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:server_box/core/sync.dart'; +import 'package:server_box/data/model/server/server.dart'; +import 'package:server_box/data/model/server/server_private_info.dart'; +import 'package:server_box/data/model/server/try_limiter.dart'; +import 'package:server_box/data/provider/server/single.dart'; +import 'package:server_box/data/res/store.dart'; +import 'package:server_box/data/ssh/session_manager.dart'; + +part 'all.freezed.dart'; +part 'all.g.dart'; + +@freezed +abstract class ServersState with _$ServersState { + const factory ServersState({ + @Default({}) Map servers, + @Default([]) List serverOrder, + @Default({}) Set tags, + @Default({}) Set manualDisconnectedIds, + Timer? autoRefreshTimer, + }) = _ServersState; +} + +@Riverpod(keepAlive: true) +class ServersNotifier extends _$ServersNotifier { + @override + ServersState build() { + // Initialize with empty state, load data asynchronously + Future.microtask(() => _load()); + return const ServersState(); + } + + Future _load() async { + final spis = Stores.server.fetch(); + final newServers = {}; + final newServerOrder = []; + + for (final spi in spis) { + newServers[spi.id] = spi; + } + + final serverOrder_ = Stores.setting.serverOrder.fetch(); + if (serverOrder_.isNotEmpty) { + spis.reorder(order: serverOrder_, finder: (n, id) => n.id == id); + newServerOrder.addAll(spis.map((e) => e.id)); + } else { + newServerOrder.addAll(newServers.keys); + } + + // Must use [equals] to compare [Order] here. + if (!newServerOrder.equals(serverOrder_)) { + Stores.setting.serverOrder.put(newServerOrder); + } + + final newTags = _calculateTags(newServers); + + state = state.copyWith(servers: newServers, serverOrder: newServerOrder, tags: newTags); + } + + Set _calculateTags(Map servers) { + final tags = {}; + for (final spi in servers.values) { + final spiTags = spi.tags; + if (spiTags == null) continue; + for (final t in spiTags) { + tags.add(t); + } + } + return tags; + } + + /// Get a [Spi] by [spi] or [id]. + /// + /// Priority: [spi] > [id] + Spi? pick({Spi? spi, String? id}) { + if (spi != null) { + return state.servers[spi.id]; + } + if (id != null) { + return state.servers[id]; + } + return null; + } + + /// if [spi] is specificed then only refresh this server + /// [onlyFailed] only refresh failed servers + Future refresh({Spi? spi, bool onlyFailed = false}) async { + if (spi != null) { + final newManualDisconnected = Set.from(state.manualDisconnectedIds)..remove(spi.id); + state = state.copyWith(manualDisconnectedIds: newManualDisconnected); + final serverNotifier = ref.read(serverNotifierProvider(spi.id).notifier); + await serverNotifier.refresh(); + return; + } + + await Future.wait( + state.servers.entries.map((entry) async { + final serverId = entry.key; + final spi = entry.value; + + if (onlyFailed) { + final serverState = ref.read(serverNotifierProvider(serverId)); + if (serverState.conn != ServerConn.failed) return; + TryLimiter.reset(serverId); + } + + if (state.manualDisconnectedIds.contains(serverId)) return; + + final serverState = ref.read(serverNotifierProvider(serverId)); + if (serverState.conn == ServerConn.disconnected && !spi.autoConnect) { + return; + } + + final serverNotifier = ref.read(serverNotifierProvider(serverId).notifier); + await serverNotifier.refresh(); + }), + ); + } + + Future startAutoRefresh() async { + var duration = Stores.setting.serverStatusUpdateInterval.fetch(); + stopAutoRefresh(); + if (duration == 0) return; + if (duration < 0 || duration > 10 || duration == 1) { + duration = 3; + Loggers.app.warning('Invalid duration: $duration, use default 3'); + } + final timer = Timer.periodic(Duration(seconds: duration), (_) async { + await refresh(); + }); + state = state.copyWith(autoRefreshTimer: timer); + } + + void stopAutoRefresh() { + final timer = state.autoRefreshTimer; + if (timer != null) { + timer.cancel(); + state = state.copyWith(autoRefreshTimer: null); + } + } + + bool get isAutoRefreshOn => state.autoRefreshTimer != null; + + void setDisconnected() { + for (final serverId in state.servers.keys) { + final serverNotifier = ref.read(serverNotifierProvider(serverId).notifier); + serverNotifier.updateConnection(ServerConn.disconnected); + + // Update SSH session status to disconnected + final sessionId = 'ssh_$serverId'; + TermSessionManager.updateStatus(sessionId, TermSessionStatus.disconnected); + } + //TryLimiter.clear(); + } + + void closeServer({String? id}) { + if (id == null) { + for (final serverId in state.servers.keys) { + closeOneServer(serverId); + } + return; + } + closeOneServer(id); + } + + void closeOneServer(String id) { + final spi = state.servers[id]; + if (spi == null) { + Loggers.app.warning('Server with id $id not found'); + return; + } + + final serverNotifier = ref.read(serverNotifierProvider(id).notifier); + serverNotifier.closeConnection(); + + final newManualDisconnected = Set.from(state.manualDisconnectedIds)..add(id); + state = state.copyWith(manualDisconnectedIds: newManualDisconnected); + + // Remove SSH session when server is manually closed + final sessionId = 'ssh_$id'; + TermSessionManager.remove(sessionId); + } + + void addServer(Spi spi) { + final newServers = Map.from(state.servers); + newServers[spi.id] = spi; + + final newOrder = List.from(state.serverOrder)..add(spi.id); + final newTags = _calculateTags(newServers); + + state = state.copyWith(servers: newServers, serverOrder: newOrder, tags: newTags); + + Stores.server.put(spi); + Stores.setting.serverOrder.put(newOrder); + refresh(spi: spi); + bakSync.sync(milliDelay: 1000); + } + + void delServer(String id) { + final newServers = Map.from(state.servers); + newServers.remove(id); + + final newOrder = List.from(state.serverOrder)..remove(id); + final newTags = _calculateTags(newServers); + + state = state.copyWith(servers: newServers, serverOrder: newOrder, tags: newTags); + + Stores.setting.serverOrder.put(newOrder); + Stores.server.delete(id); + + // Remove SSH session when server is deleted + final sessionId = 'ssh_$id'; + TermSessionManager.remove(sessionId); + + bakSync.sync(milliDelay: 1000); + } + + void deleteAll() { + // Remove all SSH sessions before clearing servers + for (final id in state.servers.keys) { + final sessionId = 'ssh_$id'; + TermSessionManager.remove(sessionId); + } + + state = const ServersState(); + + Stores.setting.serverOrder.put([]); + Stores.server.clear(); + bakSync.sync(milliDelay: 1000); + } + + Future updateServer(Spi old, Spi newSpi) async { + if (old != newSpi) { + Stores.server.update(old, newSpi); + + final newServers = Map.from(state.servers); + final newOrder = List.from(state.serverOrder); + + if (newSpi.id != old.id) { + newServers[newSpi.id] = newSpi; + newServers.remove(old.id); + newOrder.update(old.id, newSpi.id); + Stores.setting.serverOrder.put(newOrder); + + // Update SSH session ID when server ID changes + final oldSessionId = 'ssh_${old.id}'; + TermSessionManager.remove(oldSessionId); + // Session will be re-added when reconnecting if necessary + } else { + newServers[old.id] = newSpi; + // Update SPI in the corresponding IndividualServerNotifier + final serverNotifier = ref.read(serverNotifierProvider(old.id).notifier); + serverNotifier.updateSpi(newSpi); + } + + final newTags = _calculateTags(newServers); + state = state.copyWith(servers: newServers, serverOrder: newOrder, tags: newTags); + + // Only reconnect if neccessary + if (newSpi.shouldReconnect(old)) { + // Use [newSpi.id] instead of [old.id] because [old.id] may be changed + TryLimiter.reset(newSpi.id); + refresh(spi: newSpi); + } + } + bakSync.sync(milliDelay: 1000); + } +} \ No newline at end of file diff --git a/lib/data/provider/server.freezed.dart b/lib/data/provider/server/all.freezed.dart similarity index 55% rename from lib/data/provider/server.freezed.dart rename to lib/data/provider/server/all.freezed.dart index e6f64aad..9ddc62ff 100644 --- a/lib/data/provider/server.freezed.dart +++ b/lib/data/provider/server/all.freezed.dart @@ -3,7 +3,7 @@ // ignore_for_file: type=lint // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark -part of 'server.dart'; +part of 'all.dart'; // ************************************************************************** // FreezedGenerator @@ -304,291 +304,4 @@ as Timer?, } -/// @nodoc -mixin _$ServerState { - - Spi get spi; ServerStatus get status; ServerConn get conn; SSHClient? get client; Future? get updateFuture; -/// Create a copy of ServerState -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$ServerStateCopyWith get copyWith => _$ServerStateCopyWithImpl(this as ServerState, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is ServerState&&(identical(other.spi, spi) || other.spi == spi)&&(identical(other.status, status) || other.status == status)&&(identical(other.conn, conn) || other.conn == conn)&&(identical(other.client, client) || other.client == client)&&(identical(other.updateFuture, updateFuture) || other.updateFuture == updateFuture)); -} - - -@override -int get hashCode => Object.hash(runtimeType,spi,status,conn,client,updateFuture); - -@override -String toString() { - return 'ServerState(spi: $spi, status: $status, conn: $conn, client: $client, updateFuture: $updateFuture)'; -} - - -} - -/// @nodoc -abstract mixin class $ServerStateCopyWith<$Res> { - factory $ServerStateCopyWith(ServerState value, $Res Function(ServerState) _then) = _$ServerStateCopyWithImpl; -@useResult -$Res call({ - Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture -}); - - -$SpiCopyWith<$Res> get spi; - -} -/// @nodoc -class _$ServerStateCopyWithImpl<$Res> - implements $ServerStateCopyWith<$Res> { - _$ServerStateCopyWithImpl(this._self, this._then); - - final ServerState _self; - final $Res Function(ServerState) _then; - -/// Create a copy of ServerState -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? spi = null,Object? status = null,Object? conn = null,Object? client = freezed,Object? updateFuture = freezed,}) { - return _then(_self.copyWith( -spi: null == spi ? _self.spi : spi // ignore: cast_nullable_to_non_nullable -as Spi,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable -as ServerStatus,conn: null == conn ? _self.conn : conn // ignore: cast_nullable_to_non_nullable -as ServerConn,client: freezed == client ? _self.client : client // ignore: cast_nullable_to_non_nullable -as SSHClient?,updateFuture: freezed == updateFuture ? _self.updateFuture : updateFuture // ignore: cast_nullable_to_non_nullable -as Future?, - )); -} -/// Create a copy of ServerState -/// with the given fields replaced by the non-null parameter values. -@override -@pragma('vm:prefer-inline') -$SpiCopyWith<$Res> get spi { - - return $SpiCopyWith<$Res>(_self.spi, (value) { - return _then(_self.copyWith(spi: value)); - }); -} -} - - -/// Adds pattern-matching-related methods to [ServerState]. -extension ServerStatePatterns on ServerState { -/// A variant of `map` that fallback to returning `orElse`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeMap(TResult Function( _ServerState value)? $default,{required TResult orElse(),}){ -final _that = this; -switch (_that) { -case _ServerState() when $default != null: -return $default(_that);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// Callbacks receives the raw object, upcasted. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case final Subclass2 value: -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult map(TResult Function( _ServerState value) $default,){ -final _that = this; -switch (_that) { -case _ServerState(): -return $default(_that);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `map` that fallback to returning `null`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ServerState value)? $default,){ -final _that = this; -switch (_that) { -case _ServerState() when $default != null: -return $default(_that);case _: - return null; - -} -} -/// A variant of `when` that fallback to an `orElse` callback. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeWhen(TResult Function( Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture)? $default,{required TResult orElse(),}) {final _that = this; -switch (_that) { -case _ServerState() when $default != null: -return $default(_that.spi,_that.status,_that.conn,_that.client,_that.updateFuture);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// As opposed to `map`, this offers destructuring. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case Subclass2(:final field2): -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult when(TResult Function( Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture) $default,) {final _that = this; -switch (_that) { -case _ServerState(): -return $default(_that.spi,_that.status,_that.conn,_that.client,_that.updateFuture);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `when` that fallback to returning `null` -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? whenOrNull(TResult? Function( Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture)? $default,) {final _that = this; -switch (_that) { -case _ServerState() when $default != null: -return $default(_that.spi,_that.status,_that.conn,_that.client,_that.updateFuture);case _: - return null; - -} -} - -} - -/// @nodoc - - -class _ServerState implements ServerState { - const _ServerState({required this.spi, required this.status, this.conn = ServerConn.disconnected, this.client, this.updateFuture}); - - -@override final Spi spi; -@override final ServerStatus status; -@override@JsonKey() final ServerConn conn; -@override final SSHClient? client; -@override final Future? updateFuture; - -/// Create a copy of ServerState -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -_$ServerStateCopyWith<_ServerState> get copyWith => __$ServerStateCopyWithImpl<_ServerState>(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _ServerState&&(identical(other.spi, spi) || other.spi == spi)&&(identical(other.status, status) || other.status == status)&&(identical(other.conn, conn) || other.conn == conn)&&(identical(other.client, client) || other.client == client)&&(identical(other.updateFuture, updateFuture) || other.updateFuture == updateFuture)); -} - - -@override -int get hashCode => Object.hash(runtimeType,spi,status,conn,client,updateFuture); - -@override -String toString() { - return 'ServerState(spi: $spi, status: $status, conn: $conn, client: $client, updateFuture: $updateFuture)'; -} - - -} - -/// @nodoc -abstract mixin class _$ServerStateCopyWith<$Res> implements $ServerStateCopyWith<$Res> { - factory _$ServerStateCopyWith(_ServerState value, $Res Function(_ServerState) _then) = __$ServerStateCopyWithImpl; -@override @useResult -$Res call({ - Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture -}); - - -@override $SpiCopyWith<$Res> get spi; - -} -/// @nodoc -class __$ServerStateCopyWithImpl<$Res> - implements _$ServerStateCopyWith<$Res> { - __$ServerStateCopyWithImpl(this._self, this._then); - - final _ServerState _self; - final $Res Function(_ServerState) _then; - -/// Create a copy of ServerState -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? spi = null,Object? status = null,Object? conn = null,Object? client = freezed,Object? updateFuture = freezed,}) { - return _then(_ServerState( -spi: null == spi ? _self.spi : spi // ignore: cast_nullable_to_non_nullable -as Spi,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable -as ServerStatus,conn: null == conn ? _self.conn : conn // ignore: cast_nullable_to_non_nullable -as ServerConn,client: freezed == client ? _self.client : client // ignore: cast_nullable_to_non_nullable -as SSHClient?,updateFuture: freezed == updateFuture ? _self.updateFuture : updateFuture // ignore: cast_nullable_to_non_nullable -as Future?, - )); -} - -/// Create a copy of ServerState -/// with the given fields replaced by the non-null parameter values. -@override -@pragma('vm:prefer-inline') -$SpiCopyWith<$Res> get spi { - - return $SpiCopyWith<$Res>(_self.spi, (value) { - return _then(_self.copyWith(spi: value)); - }); -} -} - // dart format on diff --git a/lib/data/provider/server/all.g.dart b/lib/data/provider/server/all.g.dart new file mode 100644 index 00000000..c49070bb --- /dev/null +++ b/lib/data/provider/server/all.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'all.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$serversNotifierHash() => r'2ae641188f772794a32e8700c008f51ba0cc1ec9'; + +/// See also [ServersNotifier]. +@ProviderFor(ServersNotifier) +final serversNotifierProvider = + NotifierProvider.internal( + ServersNotifier.new, + name: r'serversNotifierProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$serversNotifierHash, + dependencies: null, + allTransitiveDependencies: null, + ); + +typedef _$ServersNotifier = Notifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/data/provider/server.dart b/lib/data/provider/server/single.dart similarity index 59% rename from lib/data/provider/server.dart rename to lib/data/provider/server/single.dart index 605c109a..215c53be 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server/single.dart @@ -8,7 +8,6 @@ import 'package:flutter_gbk2utf8/flutter_gbk2utf8.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:server_box/core/extension/ssh_client.dart'; -import 'package:server_box/core/sync.dart'; import 'package:server_box/core/utils/server.dart'; import 'package:server_box/core/utils/ssh_auth.dart'; import 'package:server_box/data/helper/system_detector.dart'; @@ -20,23 +19,13 @@ import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/server_status_update_req.dart'; import 'package:server_box/data/model/server/system.dart'; import 'package:server_box/data/model/server/try_limiter.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/data/res/status.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/ssh/session_manager.dart'; -part 'server.freezed.dart'; -part 'server.g.dart'; - -@freezed -abstract class ServersState with _$ServersState { - const factory ServersState({ - @Default({}) Map servers, - @Default([]) List serverOrder, - @Default({}) Set tags, - @Default({}) Set manualDisconnectedIds, - Timer? autoRefreshTimer, - }) = _ServersState; -} +part 'single.g.dart'; +part 'single.freezed.dart'; // Individual server state, including connection and status information @freezed @@ -50,20 +39,12 @@ abstract class ServerState with _$ServerState { }) = _ServerState; } -extension IndividualServerStateExtension on ServerState { - bool get needGenClient => conn < ServerConn.connecting; - - bool get canViewDetails => conn == ServerConn.finished; - - String get id => spi.id; -} - // Individual server state management @riverpod -class IndividualServerNotifier extends _$IndividualServerNotifier { +class ServerNotifier extends _$ServerNotifier { @override ServerState build(String serverId) { - final serverNotifier = ref.read(serverNotifierProvider); + final serverNotifier = ref.read(serversNotifierProvider); final spi = serverNotifier.servers[serverId]; if (spi == null) { throw StateError('Server $serverId not found'); @@ -169,7 +150,7 @@ class IndividualServerNotifier extends _$IndividualServerNotifier { id: sessionId, spi: spi, startTimeMs: time1.millisecondsSinceEpoch, - disconnect: () => ref.read(serverNotifierProvider.notifier)._closeOneServer(spi.id), + disconnect: () => ref.read(serversNotifierProvider.notifier).closeOneServer(spi.id), status: TermSessionStatus.connecting, ); TermSessionManager.setActive(sessionId, hasTerminal: false); @@ -371,249 +352,10 @@ class IndividualServerNotifier extends _$IndividualServerNotifier { } } -@Riverpod(keepAlive: true) -class ServerNotifier extends _$ServerNotifier { - @override - ServersState build() { - // Initialize with empty state, load data asynchronously - Future.microtask(() => _load()); - return const ServersState(); - } +extension IndividualServerStateExtension on ServerState { + bool get needGenClient => conn < ServerConn.connecting; - Future _load() async { - final spis = Stores.server.fetch(); - final newServers = {}; - final newServerOrder = []; + bool get canViewDetails => conn == ServerConn.finished; - for (final spi in spis) { - newServers[spi.id] = spi; - } - - final serverOrder_ = Stores.setting.serverOrder.fetch(); - if (serverOrder_.isNotEmpty) { - spis.reorder(order: serverOrder_, finder: (n, id) => n.id == id); - newServerOrder.addAll(spis.map((e) => e.id)); - } else { - newServerOrder.addAll(newServers.keys); - } - - // Must use [equals] to compare [Order] here. - if (!newServerOrder.equals(serverOrder_)) { - Stores.setting.serverOrder.put(newServerOrder); - } - - final newTags = _calculateTags(newServers); - - state = state.copyWith(servers: newServers, serverOrder: newServerOrder, tags: newTags); - } - - Set _calculateTags(Map servers) { - final tags = {}; - for (final spi in servers.values) { - final spiTags = spi.tags; - if (spiTags == null) continue; - for (final t in spiTags) { - tags.add(t); - } - } - return tags; - } - - /// Get a [Spi] by [spi] or [id]. - /// - /// Priority: [spi] > [id] - Spi? pick({Spi? spi, String? id}) { - if (spi != null) { - return state.servers[spi.id]; - } - if (id != null) { - return state.servers[id]; - } - return null; - } - - /// if [spi] is specificed then only refresh this server - /// [onlyFailed] only refresh failed servers - Future refresh({Spi? spi, bool onlyFailed = false}) async { - if (spi != null) { - final newManualDisconnected = Set.from(state.manualDisconnectedIds)..remove(spi.id); - state = state.copyWith(manualDisconnectedIds: newManualDisconnected); - final serverNotifier = ref.read(individualServerNotifierProvider(spi.id).notifier); - await serverNotifier.refresh(); - return; - } - - await Future.wait( - state.servers.entries.map((entry) async { - final serverId = entry.key; - final spi = entry.value; - - if (onlyFailed) { - final serverState = ref.read(individualServerNotifierProvider(serverId)); - if (serverState.conn != ServerConn.failed) return; - TryLimiter.reset(serverId); - } - - if (state.manualDisconnectedIds.contains(serverId)) return; - - final serverState = ref.read(individualServerNotifierProvider(serverId)); - if (serverState.conn == ServerConn.disconnected && !spi.autoConnect) { - return; - } - - final serverNotifier = ref.read(individualServerNotifierProvider(serverId).notifier); - await serverNotifier.refresh(); - }), - ); - } - - Future startAutoRefresh() async { - var duration = Stores.setting.serverStatusUpdateInterval.fetch(); - stopAutoRefresh(); - if (duration == 0) return; - if (duration < 0 || duration > 10 || duration == 1) { - duration = 3; - Loggers.app.warning('Invalid duration: $duration, use default 3'); - } - final timer = Timer.periodic(Duration(seconds: duration), (_) async { - await refresh(); - }); - state = state.copyWith(autoRefreshTimer: timer); - } - - void stopAutoRefresh() { - final timer = state.autoRefreshTimer; - if (timer != null) { - timer.cancel(); - state = state.copyWith(autoRefreshTimer: null); - } - } - - bool get isAutoRefreshOn => state.autoRefreshTimer != null; - - void setDisconnected() { - for (final serverId in state.servers.keys) { - final serverNotifier = ref.read(individualServerNotifierProvider(serverId).notifier); - serverNotifier.updateConnection(ServerConn.disconnected); - - // Update SSH session status to disconnected - final sessionId = 'ssh_$serverId'; - TermSessionManager.updateStatus(sessionId, TermSessionStatus.disconnected); - } - //TryLimiter.clear(); - } - - void closeServer({String? id}) { - if (id == null) { - for (final serverId in state.servers.keys) { - _closeOneServer(serverId); - } - return; - } - _closeOneServer(id); - } - - void _closeOneServer(String id) { - final spi = state.servers[id]; - if (spi == null) { - Loggers.app.warning('Server with id $id not found'); - return; - } - - final serverNotifier = ref.read(individualServerNotifierProvider(id).notifier); - serverNotifier.closeConnection(); - - final newManualDisconnected = Set.from(state.manualDisconnectedIds)..add(id); - state = state.copyWith(manualDisconnectedIds: newManualDisconnected); - - // Remove SSH session when server is manually closed - final sessionId = 'ssh_$id'; - TermSessionManager.remove(sessionId); - } - - void addServer(Spi spi) { - final newServers = Map.from(state.servers); - newServers[spi.id] = spi; - - final newOrder = List.from(state.serverOrder)..add(spi.id); - final newTags = _calculateTags(newServers); - - state = state.copyWith(servers: newServers, serverOrder: newOrder, tags: newTags); - - Stores.server.put(spi); - Stores.setting.serverOrder.put(newOrder); - refresh(spi: spi); - bakSync.sync(milliDelay: 1000); - } - - void delServer(String id) { - final newServers = Map.from(state.servers); - newServers.remove(id); - - final newOrder = List.from(state.serverOrder)..remove(id); - final newTags = _calculateTags(newServers); - - state = state.copyWith(servers: newServers, serverOrder: newOrder, tags: newTags); - - Stores.setting.serverOrder.put(newOrder); - Stores.server.delete(id); - - // Remove SSH session when server is deleted - final sessionId = 'ssh_$id'; - TermSessionManager.remove(sessionId); - - bakSync.sync(milliDelay: 1000); - } - - void deleteAll() { - // Remove all SSH sessions before clearing servers - for (final id in state.servers.keys) { - final sessionId = 'ssh_$id'; - TermSessionManager.remove(sessionId); - } - - state = const ServersState(); - - Stores.setting.serverOrder.put([]); - Stores.server.clear(); - bakSync.sync(milliDelay: 1000); - } - - Future updateServer(Spi old, Spi newSpi) async { - if (old != newSpi) { - Stores.server.update(old, newSpi); - - final newServers = Map.from(state.servers); - final newOrder = List.from(state.serverOrder); - - if (newSpi.id != old.id) { - newServers[newSpi.id] = newSpi; - newServers.remove(old.id); - newOrder.update(old.id, newSpi.id); - Stores.setting.serverOrder.put(newOrder); - - // Update SSH session ID when server ID changes - final oldSessionId = 'ssh_${old.id}'; - TermSessionManager.remove(oldSessionId); - // Session will be re-added when reconnecting if necessary - } else { - newServers[old.id] = newSpi; - // Update SPI in the corresponding IndividualServerNotifier - final serverNotifier = ref.read(individualServerNotifierProvider(old.id).notifier); - serverNotifier.updateSpi(newSpi); - } - - final newTags = _calculateTags(newServers); - state = state.copyWith(servers: newServers, serverOrder: newOrder, tags: newTags); - - // Only reconnect if neccessary - if (newSpi.shouldReconnect(old)) { - // Use [newSpi.id] instead of [old.id] because [old.id] may be changed - TryLimiter.reset(newSpi.id); - refresh(spi: newSpi); - } - } - bakSync.sync(milliDelay: 1000); - } + String get id => spi.id; } - diff --git a/lib/data/provider/server/single.freezed.dart b/lib/data/provider/server/single.freezed.dart new file mode 100644 index 00000000..a617c2f0 --- /dev/null +++ b/lib/data/provider/server/single.freezed.dart @@ -0,0 +1,301 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'single.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$ServerState { + + Spi get spi; ServerStatus get status; ServerConn get conn; SSHClient? get client; Future? get updateFuture; +/// Create a copy of ServerState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ServerStateCopyWith get copyWith => _$ServerStateCopyWithImpl(this as ServerState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ServerState&&(identical(other.spi, spi) || other.spi == spi)&&(identical(other.status, status) || other.status == status)&&(identical(other.conn, conn) || other.conn == conn)&&(identical(other.client, client) || other.client == client)&&(identical(other.updateFuture, updateFuture) || other.updateFuture == updateFuture)); +} + + +@override +int get hashCode => Object.hash(runtimeType,spi,status,conn,client,updateFuture); + +@override +String toString() { + return 'ServerState(spi: $spi, status: $status, conn: $conn, client: $client, updateFuture: $updateFuture)'; +} + + +} + +/// @nodoc +abstract mixin class $ServerStateCopyWith<$Res> { + factory $ServerStateCopyWith(ServerState value, $Res Function(ServerState) _then) = _$ServerStateCopyWithImpl; +@useResult +$Res call({ + Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture +}); + + +$SpiCopyWith<$Res> get spi; + +} +/// @nodoc +class _$ServerStateCopyWithImpl<$Res> + implements $ServerStateCopyWith<$Res> { + _$ServerStateCopyWithImpl(this._self, this._then); + + final ServerState _self; + final $Res Function(ServerState) _then; + +/// Create a copy of ServerState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? spi = null,Object? status = null,Object? conn = null,Object? client = freezed,Object? updateFuture = freezed,}) { + return _then(_self.copyWith( +spi: null == spi ? _self.spi : spi // ignore: cast_nullable_to_non_nullable +as Spi,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as ServerStatus,conn: null == conn ? _self.conn : conn // ignore: cast_nullable_to_non_nullable +as ServerConn,client: freezed == client ? _self.client : client // ignore: cast_nullable_to_non_nullable +as SSHClient?,updateFuture: freezed == updateFuture ? _self.updateFuture : updateFuture // ignore: cast_nullable_to_non_nullable +as Future?, + )); +} +/// Create a copy of ServerState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SpiCopyWith<$Res> get spi { + + return $SpiCopyWith<$Res>(_self.spi, (value) { + return _then(_self.copyWith(spi: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [ServerState]. +extension ServerStatePatterns on ServerState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ServerState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ServerState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ServerState value) $default,){ +final _that = this; +switch (_that) { +case _ServerState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ServerState value)? $default,){ +final _that = this; +switch (_that) { +case _ServerState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ServerState() when $default != null: +return $default(_that.spi,_that.status,_that.conn,_that.client,_that.updateFuture);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture) $default,) {final _that = this; +switch (_that) { +case _ServerState(): +return $default(_that.spi,_that.status,_that.conn,_that.client,_that.updateFuture);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture)? $default,) {final _that = this; +switch (_that) { +case _ServerState() when $default != null: +return $default(_that.spi,_that.status,_that.conn,_that.client,_that.updateFuture);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _ServerState implements ServerState { + const _ServerState({required this.spi, required this.status, this.conn = ServerConn.disconnected, this.client, this.updateFuture}); + + +@override final Spi spi; +@override final ServerStatus status; +@override@JsonKey() final ServerConn conn; +@override final SSHClient? client; +@override final Future? updateFuture; + +/// Create a copy of ServerState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ServerStateCopyWith<_ServerState> get copyWith => __$ServerStateCopyWithImpl<_ServerState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ServerState&&(identical(other.spi, spi) || other.spi == spi)&&(identical(other.status, status) || other.status == status)&&(identical(other.conn, conn) || other.conn == conn)&&(identical(other.client, client) || other.client == client)&&(identical(other.updateFuture, updateFuture) || other.updateFuture == updateFuture)); +} + + +@override +int get hashCode => Object.hash(runtimeType,spi,status,conn,client,updateFuture); + +@override +String toString() { + return 'ServerState(spi: $spi, status: $status, conn: $conn, client: $client, updateFuture: $updateFuture)'; +} + + +} + +/// @nodoc +abstract mixin class _$ServerStateCopyWith<$Res> implements $ServerStateCopyWith<$Res> { + factory _$ServerStateCopyWith(_ServerState value, $Res Function(_ServerState) _then) = __$ServerStateCopyWithImpl; +@override @useResult +$Res call({ + Spi spi, ServerStatus status, ServerConn conn, SSHClient? client, Future? updateFuture +}); + + +@override $SpiCopyWith<$Res> get spi; + +} +/// @nodoc +class __$ServerStateCopyWithImpl<$Res> + implements _$ServerStateCopyWith<$Res> { + __$ServerStateCopyWithImpl(this._self, this._then); + + final _ServerState _self; + final $Res Function(_ServerState) _then; + +/// Create a copy of ServerState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? spi = null,Object? status = null,Object? conn = null,Object? client = freezed,Object? updateFuture = freezed,}) { + return _then(_ServerState( +spi: null == spi ? _self.spi : spi // ignore: cast_nullable_to_non_nullable +as Spi,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as ServerStatus,conn: null == conn ? _self.conn : conn // ignore: cast_nullable_to_non_nullable +as ServerConn,client: freezed == client ? _self.client : client // ignore: cast_nullable_to_non_nullable +as SSHClient?,updateFuture: freezed == updateFuture ? _self.updateFuture : updateFuture // ignore: cast_nullable_to_non_nullable +as Future?, + )); +} + +/// Create a copy of ServerState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$SpiCopyWith<$Res> get spi { + + return $SpiCopyWith<$Res>(_self.spi, (value) { + return _then(_self.copyWith(spi: value)); + }); +} +} + +// dart format on diff --git a/lib/data/provider/server.g.dart b/lib/data/provider/server/single.g.dart similarity index 50% rename from lib/data/provider/server.g.dart rename to lib/data/provider/server/single.g.dart index 3baae147..eb069983 100644 --- a/lib/data/provider/server.g.dart +++ b/lib/data/provider/server/single.g.dart @@ -1,13 +1,12 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'server.dart'; +part of 'single.dart'; // ************************************************************************** // RiverpodGenerator // ************************************************************************** -String _$individualServerNotifierHash() => - r'e3d74fb95ca994cd8419b1deab743e8b3e21bee2'; +String _$serverNotifierHash() => r'5625b0a4762c28efdbc124809c03b84a51d213b1'; /// Copied from Dart SDK class _SystemHash { @@ -30,30 +29,30 @@ class _SystemHash { } } -abstract class _$IndividualServerNotifier +abstract class _$ServerNotifier extends BuildlessAutoDisposeNotifier { late final String serverId; ServerState build(String serverId); } -/// See also [IndividualServerNotifier]. -@ProviderFor(IndividualServerNotifier) -const individualServerNotifierProvider = IndividualServerNotifierFamily(); +/// See also [ServerNotifier]. +@ProviderFor(ServerNotifier) +const serverNotifierProvider = ServerNotifierFamily(); -/// See also [IndividualServerNotifier]. -class IndividualServerNotifierFamily extends Family { - /// See also [IndividualServerNotifier]. - const IndividualServerNotifierFamily(); +/// See also [ServerNotifier]. +class ServerNotifierFamily extends Family { + /// See also [ServerNotifier]. + const ServerNotifierFamily(); - /// See also [IndividualServerNotifier]. - IndividualServerNotifierProvider call(String serverId) { - return IndividualServerNotifierProvider(serverId); + /// See also [ServerNotifier]. + ServerNotifierProvider call(String serverId) { + return ServerNotifierProvider(serverId); } @override - IndividualServerNotifierProvider getProviderOverride( - covariant IndividualServerNotifierProvider provider, + ServerNotifierProvider getProviderOverride( + covariant ServerNotifierProvider provider, ) { return call(provider.serverId); } @@ -70,29 +69,28 @@ class IndividualServerNotifierFamily extends Family { _allTransitiveDependencies; @override - String? get name => r'individualServerNotifierProvider'; + String? get name => r'serverNotifierProvider'; } -/// See also [IndividualServerNotifier]. -class IndividualServerNotifierProvider - extends - AutoDisposeNotifierProviderImpl { - /// See also [IndividualServerNotifier]. - IndividualServerNotifierProvider(String serverId) +/// See also [ServerNotifier]. +class ServerNotifierProvider + extends AutoDisposeNotifierProviderImpl { + /// See also [ServerNotifier]. + ServerNotifierProvider(String serverId) : this._internal( - () => IndividualServerNotifier()..serverId = serverId, - from: individualServerNotifierProvider, - name: r'individualServerNotifierProvider', + () => ServerNotifier()..serverId = serverId, + from: serverNotifierProvider, + name: r'serverNotifierProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') ? null - : _$individualServerNotifierHash, - dependencies: IndividualServerNotifierFamily._dependencies, + : _$serverNotifierHash, + dependencies: ServerNotifierFamily._dependencies, allTransitiveDependencies: - IndividualServerNotifierFamily._allTransitiveDependencies, + ServerNotifierFamily._allTransitiveDependencies, serverId: serverId, ); - IndividualServerNotifierProvider._internal( + ServerNotifierProvider._internal( super._createNotifier, { required super.name, required super.dependencies, @@ -105,15 +103,15 @@ class IndividualServerNotifierProvider final String serverId; @override - ServerState runNotifierBuild(covariant IndividualServerNotifier notifier) { + ServerState runNotifierBuild(covariant ServerNotifier notifier) { return notifier.build(serverId); } @override - Override overrideWith(IndividualServerNotifier Function() create) { + Override overrideWith(ServerNotifier Function() create) { return ProviderOverride( origin: this, - override: IndividualServerNotifierProvider._internal( + override: ServerNotifierProvider._internal( () => create()..serverId = serverId, from: from, name: null, @@ -126,15 +124,14 @@ class IndividualServerNotifierProvider } @override - AutoDisposeNotifierProviderElement + AutoDisposeNotifierProviderElement createElement() { - return _IndividualServerNotifierProviderElement(this); + return _ServerNotifierProviderElement(this); } @override bool operator ==(Object other) { - return other is IndividualServerNotifierProvider && - other.serverId == serverId; + return other is ServerNotifierProvider && other.serverId == serverId; } @override @@ -148,40 +145,19 @@ class IndividualServerNotifierProvider @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element -mixin IndividualServerNotifierRef - on AutoDisposeNotifierProviderRef { +mixin ServerNotifierRef on AutoDisposeNotifierProviderRef { /// The parameter `serverId` of this provider. String get serverId; } -class _IndividualServerNotifierProviderElement - extends - AutoDisposeNotifierProviderElement< - IndividualServerNotifier, - ServerState - > - with IndividualServerNotifierRef { - _IndividualServerNotifierProviderElement(super.provider); +class _ServerNotifierProviderElement + extends AutoDisposeNotifierProviderElement + with ServerNotifierRef { + _ServerNotifierProviderElement(super.provider); @override - String get serverId => (origin as IndividualServerNotifierProvider).serverId; + String get serverId => (origin as ServerNotifierProvider).serverId; } -String _$serverNotifierHash() => r'8e2bc3aef3c56263f88df3c2bb1ba88b6cf83c8f'; - -/// See also [ServerNotifier]. -@ProviderFor(ServerNotifier) -final serverNotifierProvider = - NotifierProvider.internal( - ServerNotifier.new, - name: r'serverNotifierProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$serverNotifierHash, - dependencies: null, - allTransitiveDependencies: null, - ); - -typedef _$ServerNotifier = Notifier; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/data/provider/systemd.dart b/lib/data/provider/systemd.dart index abd64438..5fbb97d4 100644 --- a/lib/data/provider/systemd.dart +++ b/lib/data/provider/systemd.dart @@ -5,7 +5,7 @@ import 'package:server_box/core/extension/ssh_client.dart'; import 'package:server_box/data/model/app/scripts/script_consts.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/systemd.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; part 'systemd.freezed.dart'; part 'systemd.g.dart'; @@ -25,7 +25,7 @@ class SystemdNotifier extends _$SystemdNotifier { @override SystemdState build(Spi spi) { - final si = ref.read(individualServerNotifierProvider(spi.id)); + final si = ref.read(serverNotifierProvider(spi.id)); _si = si; // Async initialization Future.microtask(() => getUnits()); diff --git a/lib/data/provider/systemd.g.dart b/lib/data/provider/systemd.g.dart index c9c0495f..ef4157c7 100644 --- a/lib/data/provider/systemd.g.dart +++ b/lib/data/provider/systemd.g.dart @@ -6,7 +6,7 @@ part of 'systemd.dart'; // RiverpodGenerator // ************************************************************************** -String _$systemdNotifierHash() => r'617fb7637fbc5c5100e5b522d246984f22b44cca'; +String _$systemdNotifierHash() => r'98466bd176518545be49cae52f8dbe12af3a88a6'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/view/page/container/container.dart b/lib/view/page/container/container.dart index 8f9a950b..ef284d60 100644 --- a/lib/view/page/container/container.dart +++ b/lib/view/page/container/container.dart @@ -13,7 +13,7 @@ import 'package:server_box/data/model/container/image.dart'; import 'package:server_box/data/model/container/ps.dart'; import 'package:server_box/data/model/container/type.dart'; import 'package:server_box/data/provider/container.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/ssh/page/page.dart'; @@ -43,7 +43,7 @@ class _ContainerPageState extends ConsumerState { @override void initState() { super.initState(); - final serverState = ref.read(individualServerNotifierProvider(widget.args.spi.id)); + final serverState = ref.read(serverNotifierProvider(widget.args.spi.id)); _provider = containerNotifierProvider( serverState.client, widget.args.spi.user, diff --git a/lib/view/page/home.dart b/lib/view/page/home.dart index c9ca7b22..20d82900 100644 --- a/lib/view/page/home.dart +++ b/lib/view/page/home.dart @@ -5,7 +5,7 @@ import 'package:responsive_framework/responsive_framework.dart'; import 'package:server_box/core/chan.dart'; import 'package:server_box/core/sync.dart'; import 'package:server_box/data/model/app/tab.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/url.dart'; @@ -31,8 +31,8 @@ class _HomePageState extends ConsumerState bool _shouldAuth = false; DateTime? _pausedTime; - late final _notifier = ref.read(serverNotifierProvider.notifier); - late final _provider = ref.read(serverNotifierProvider); + late final _notifier = ref.read(serversNotifierProvider.notifier); + late final _provider = ref.read(serversNotifierProvider); @override void dispose() { diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart index e72df5ed..9d43cf44 100644 --- a/lib/view/page/ping.dart +++ b/lib/view/page/ping.dart @@ -5,7 +5,8 @@ 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/ping_result.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/all.dart'; +import 'package:server_box/data/provider/server/single.dart'; /// Only permit ipv4 / ipv6 / domain chars final targetReg = RegExp(r'[a-zA-Z0-9\.-_:]+'); @@ -130,7 +131,7 @@ class _PingPageState extends ConsumerState with AutomaticKeepAliveClie return; } - if (ref.read(serverNotifierProvider).serverOrder.isEmpty) { + if (ref.read(serversNotifierProvider).serverOrder.isEmpty) { context.showSnackBar(l10n.pingNoServer); return; } @@ -142,8 +143,8 @@ class _PingPageState extends ConsumerState with AutomaticKeepAliveClie } await Future.wait( - ref.read(serverNotifierProvider).servers.values.map((spi) async { - final serverState = ref.read(individualServerNotifierProvider(spi.id)); + ref.read(serversNotifierProvider).servers.values.map((spi) async { + final serverState = ref.read(serverNotifierProvider(spi.id)); if (serverState.client == null) { return; } diff --git a/lib/view/page/process.dart b/lib/view/page/process.dart index 338d5582..592346de 100644 --- a/lib/view/page/process.dart +++ b/lib/view/page/process.dart @@ -8,7 +8,7 @@ import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/route.dart'; import 'package:server_box/data/model/app/scripts/shell_func.dart'; import 'package:server_box/data/model/server/proc.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; import 'package:server_box/data/res/store.dart'; class ProcessPage extends ConsumerStatefulWidget { @@ -37,7 +37,7 @@ class _ProcessPageState extends ConsumerState { ProcSortMode _procSortMode = ProcSortMode.cpu; List _sortModes = List.from(ProcSortMode.values); - late final _provider = individualServerNotifierProvider(widget.args.spi.id); + late final _provider = serverNotifierProvider(widget.args.spi.id); @override void dispose() { diff --git a/lib/view/page/server/detail/view.dart b/lib/view/page/server/detail/view.dart index a66a5e3f..856f24fb 100644 --- a/lib/view/page/server/detail/view.dart +++ b/lib/view/page/server/detail/view.dart @@ -21,7 +21,7 @@ import 'package:server_box/data/model/server/sensors.dart'; import 'package:server_box/data/model/server/server.dart' as server_model; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/system.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/pve.dart'; import 'package:server_box/view/page/server/edit.dart'; @@ -86,7 +86,7 @@ class _ServerDetailPageState extends ConsumerState with Single @override Widget build(BuildContext context) { - final serverState = ref.watch(individualServerNotifierProvider(widget.args.spi.id)); + final serverState = ref.watch(serverNotifierProvider(widget.args.spi.id)); if (serverState.client == null) { return Scaffold( appBar: CustomAppBar(), diff --git a/lib/view/page/server/edit.dart b/lib/view/page/server/edit.dart index 13c8ff2a..439d9e95 100644 --- a/lib/view/page/server/edit.dart +++ b/lib/view/page/server/edit.dart @@ -17,7 +17,7 @@ import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/system.dart'; import 'package:server_box/data/model/server/wol_cfg.dart'; import 'package:server_box/data/provider/private_key.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/store/server.dart'; import 'package:server_box/view/page/private_key/edit.dart'; @@ -172,7 +172,7 @@ class _ServerEditPageState extends ConsumerState with AfterLayou hint: 'root', suggestion: false, ), - TagTile(tags: _tags, allTags: ref.watch(serverNotifierProvider).tags).cardx, + TagTile(tags: _tags, allTags: ref.watch(serversNotifierProvider).tags).cardx, ListTile( title: Text(l10n.autoConnect), trailing: _autoConnect.listenVal( @@ -492,7 +492,7 @@ class _ServerEditPageState extends ConsumerState with AfterLayou Widget _buildJumpServer() { const padding = EdgeInsets.only(left: 13, right: 13, bottom: 7); final srvs = ref - .watch(serverNotifierProvider) + .watch(serversNotifierProvider) .servers .values .where((e) => e.jumpId == null) @@ -587,7 +587,7 @@ class _ServerEditPageState extends ConsumerState with AfterLayou actions: Btn.ok( onTap: () async { context.pop(); - ref.read(serverNotifierProvider.notifier).delServer(spi!.id); + ref.read(serversNotifierProvider.notifier).delServer(spi!.id); context.pop(true); }, red: true, @@ -683,7 +683,7 @@ extension _Actions on _ServerEditPageState { if (shouldImport == true) { for (final server in resolved) { - ref.read(serverNotifierProvider.notifier).addServer(server); + ref.read(serversNotifierProvider.notifier).addServer(server); } context.showSnackBar(l10n.sshConfigImported('${resolved.length}')); } @@ -802,9 +802,9 @@ extension _Actions on _ServerEditPageState { context.showSnackBar('${l10n.sameIdServerExist}: ${spi.id}'); return; } - ref.read(serverNotifierProvider.notifier).addServer(spi); + ref.read(serversNotifierProvider.notifier).addServer(spi); } else { - ref.read(serverNotifierProvider.notifier).updateServer(this.spi!, spi); + ref.read(serversNotifierProvider.notifier).updateServer(this.spi!, spi); } context.pop(); @@ -860,7 +860,7 @@ extension _Utils on _ServerEditPageState { // Import without asking again since user already gave permission for (final server in resolved) { - ref.read(serverNotifierProvider.notifier).addServer(server); + ref.read(serversNotifierProvider.notifier).addServer(server); } context.showSnackBar(l10n.sshConfigImported('${resolved.length}')); } diff --git a/lib/view/page/server/tab/content.dart b/lib/view/page/server/tab/content.dart index a9651988..8feb8c2b 100644 --- a/lib/view/page/server/tab/content.dart +++ b/lib/view/page/server/tab/content.dart @@ -30,16 +30,16 @@ extension on _ServerPageState { const Icon(Icons.refresh, size: 21, color: Colors.grey), () { TryLimiter.reset(s.spi.id); - ref.read(serverNotifierProvider.notifier).refresh(spi: s.spi); + ref.read(serversNotifierProvider.notifier).refresh(spi: s.spi); }, ), ServerConn.disconnected => ( const Icon(MingCute.link_3_line, size: 19, color: Colors.grey), - () => ref.read(serverNotifierProvider.notifier).refresh(spi: s.spi), + () => ref.read(serversNotifierProvider.notifier).refresh(spi: s.spi), ), ServerConn.finished => ( const Icon(MingCute.unlink_2_line, size: 17, color: Colors.grey), - () => ref.read(serverNotifierProvider.notifier).closeServer(id: s.spi.id), + () => ref.read(serversNotifierProvider.notifier).closeServer(id: s.spi.id), ), }; @@ -106,7 +106,7 @@ ${ss.err?.message ?? 'null'} Widget _buildNet(ServerStatus ss, String id) { final cardNoti = _getCardNoti(id); final type = cardNoti.value.net ?? Stores.setting.netViewType.fetch(); - final device = ref.watch(serverNotifierProvider).servers[id]?.custom?.netDev; + final device = ref.watch(serversNotifierProvider).servers[id]?.custom?.netDev; final (a, b) = type.build(ss, dev: device); return AnimatedSwitcher( duration: const Duration(milliseconds: 377), diff --git a/lib/view/page/server/tab/landscape.dart b/lib/view/page/server/tab/landscape.dart index 7f33bcfc..b0a91189 100644 --- a/lib/view/page/server/tab/landscape.dart +++ b/lib/view/page/server/tab/landscape.dart @@ -26,7 +26,7 @@ extension on _ServerPageState { } Widget _buildLandscapeBody() { - final serverState = ref.watch(serverNotifierProvider); + final serverState = ref.watch(serversNotifierProvider); final order = serverState.serverOrder; if (order.isEmpty) { @@ -37,7 +37,7 @@ extension on _ServerPageState { itemCount: order.length, itemBuilder: (_, idx) { final id = order[idx]; - final srv = ref.watch(individualServerNotifierProvider(id)); + final srv = ref.watch(serverNotifierProvider(id)); final title = _buildServerCardTitle(srv); final List children = [title, _buildNormalCard(srv.status, srv.spi)]; diff --git a/lib/view/page/server/tab/tab.dart b/lib/view/page/server/tab/tab.dart index ba372111..34cf09c8 100644 --- a/lib/view/page/server/tab/tab.dart +++ b/lib/view/page/server/tab/tab.dart @@ -17,7 +17,8 @@ import 'package:server_box/data/model/app/scripts/shell_func.dart'; import 'package:server_box/data/model/server/server.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/try_limiter.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/all.dart'; +import 'package:server_box/data/provider/server/single.dart'; import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/server/detail/view.dart'; @@ -73,7 +74,7 @@ class _ServerPageState extends ConsumerState @override void initState() { super.initState(); - _tags = ValueNotifier(ref.read(serverNotifierProvider).tags); + _tags = ValueNotifier(ref.read(serversNotifierProvider).tags); _startAvoidJitterTimer(); } @@ -88,7 +89,7 @@ class _ServerPageState extends ConsumerState Widget build(BuildContext context) { super.build(context); // Listen to provider changes and update the ValueNotifier - ref.listen(serverNotifierProvider, (previous, next) { + ref.listen(serversNotifierProvider, (previous, next) { _tags.value = next.tags; }); return OrientationBuilder( @@ -132,7 +133,7 @@ class _ServerPageState extends ConsumerState Widget _buildPortrait() { // final isMobile = ResponsiveBreakpoints.of(context).isMobile; - final serverState = ref.watch(serverNotifierProvider); + final serverState = ref.watch(serversNotifierProvider); return _tag.listenVal((val) { final filtered = _filterServers(serverState.serverOrder); final child = _buildScaffold(_buildBodySmall(filtered: filtered)); @@ -182,7 +183,7 @@ class _ServerPageState extends ConsumerState // Last item is just spacing if (index == lens) return SizedBox(height: 77); - final individualState = ref.watch(individualServerNotifierProvider(serversInThisColumn[index])); + final individualState = ref.watch(serverNotifierProvider(serversInThisColumn[index])); return _buildEachServerCard(individualState); }, @@ -338,8 +339,8 @@ class _ServerPageState extends ConsumerState @override Future afterFirstLayout(BuildContext context) async { - ref.read(serverNotifierProvider.notifier).refresh(); - ref.read(serverNotifierProvider.notifier).startAutoRefresh(); + ref.read(serversNotifierProvider.notifier).refresh(); + ref.read(serversNotifierProvider.notifier).startAutoRefresh(); } static const _kCardHeightMin = 23.0; diff --git a/lib/view/page/server/tab/utils.dart b/lib/view/page/server/tab/utils.dart index a8733420..05f69fc4 100644 --- a/lib/view/page/server/tab/utils.dart +++ b/lib/view/page/server/tab/utils.dart @@ -98,7 +98,7 @@ extension _Utils on _ServerPageState { final tag = _tag.value; if (tag == TagSwitcher.kDefaultTag) return order; return order.where((e) { - final tags = ref.read(serverNotifierProvider).servers[e]?.tags; + final tags = ref.read(serversNotifierProvider).servers[e]?.tags; if (tags == null) return false; return tags.contains(tag); }).toList(); diff --git a/lib/view/page/setting/entries/server.dart b/lib/view/page/setting/entries/server.dart index d2601a35..f032990c 100644 --- a/lib/view/page/setting/entries/server.dart +++ b/lib/view/page/setting/entries/server.dart @@ -46,7 +46,7 @@ extension _Server on _AppSettingsPageState { onTap: () async { final keys = Stores.server.keys(); final names = Map.fromEntries( - keys.map((e) => MapEntry(e, ref.read(serverNotifierProvider).servers[e]?.name ?? e)), + keys.map((e) => MapEntry(e, ref.read(serversNotifierProvider).servers[e]?.name ?? e)), ); final deleteKeys = await context.showPickDialog( clearable: true, diff --git a/lib/view/page/setting/entry.dart b/lib/view/page/setting/entry.dart index 4cdf8067..e75f5558 100644 --- a/lib/view/page/setting/entry.dart +++ b/lib/view/page/setting/entry.dart @@ -8,7 +8,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:icons_plus/icons_plus.dart'; import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/data/model/app/net_view.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/res/github_id.dart'; import 'package:server_box/data/res/store.dart'; diff --git a/lib/view/page/setting/seq/srv_seq.dart b/lib/view/page/setting/seq/srv_seq.dart index 85fdd4bd..f3768004 100644 --- a/lib/view/page/setting/seq/srv_seq.dart +++ b/lib/view/page/setting/seq/srv_seq.dart @@ -4,7 +4,7 @@ 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.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/data/res/store.dart'; class ServerOrderPage extends ConsumerStatefulWidget { @@ -42,7 +42,7 @@ class _ServerOrderPageState extends ConsumerState { } Widget _buildBody() { - final serverState = ref.watch(serverNotifierProvider); + final serverState = ref.watch(serversNotifierProvider); final order = serverState.serverOrder; if (order.isEmpty) { @@ -77,7 +77,7 @@ class _ServerOrderPageState extends ConsumerState { } Widget _buildCardTile(int index) { - final serverState = ref.watch(serverNotifierProvider); + final serverState = ref.watch(serversNotifierProvider); final order = serverState.serverOrder; final id = order[index]; final spi = serverState.servers[id]; diff --git a/lib/view/page/snippet/edit.dart b/lib/view/page/snippet/edit.dart index 43bdf75b..2165770c 100644 --- a/lib/view/page/snippet/edit.dart +++ b/lib/view/page/snippet/edit.dart @@ -4,7 +4,7 @@ import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/data/model/server/snippet.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/data/provider/snippet.dart'; final class SnippetEditPageArgs { @@ -157,7 +157,7 @@ class _SnippetEditPageState extends ConsumerState with AfterLay builder: (vals) { final subtitle = vals.isEmpty ? null - : vals.map((e) => ref.read(serverNotifierProvider).servers[e]?.name ?? e).join(', '); + : vals.map((e) => ref.read(serversNotifierProvider).servers[e]?.name ?? e).join(', '); return ListTile( leading: const Padding( padding: EdgeInsets.only(left: 5), @@ -169,12 +169,13 @@ class _SnippetEditPageState extends ConsumerState with AfterLay ? null : Text(subtitle, maxLines: 1, style: UIs.textGrey, overflow: TextOverflow.ellipsis), onTap: () async { - vals.removeWhere((e) => !ref.read(serverNotifierProvider).serverOrder.contains(e)); + // Create a filtered copy for the dialog, don't modify the original + final validServerIds = vals.where((e) => ref.read(serversNotifierProvider).serverOrder.contains(e)).toList(); final serverIds = await context.showPickDialog( title: l10n.autoRun, - items: ref.read(serverNotifierProvider).serverOrder, - display: (e) => ref.read(serverNotifierProvider).servers[e]?.name ?? e, - initial: vals, + items: ref.read(serversNotifierProvider).serverOrder, + display: (e) => ref.read(serversNotifierProvider).servers[e]?.name ?? e, + initial: validServerIds, clearable: true, ); if (serverIds != null) { diff --git a/lib/view/page/ssh/page/page.dart b/lib/view/page/ssh/page/page.dart index 871b18b7..02862c0b 100644 --- a/lib/view/page/ssh/page/page.dart +++ b/lib/view/page/ssh/page/page.dart @@ -16,7 +16,7 @@ import 'package:server_box/core/utils/ssh_auth.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/snippet.dart'; import 'package:server_box/data/model/ssh/virtual_key.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; import 'package:server_box/data/provider/snippet.dart'; import 'package:server_box/data/provider/virtual_keyboard.dart'; import 'package:server_box/data/res/store.dart'; @@ -118,7 +118,7 @@ class SSHPageState extends ConsumerState _setupDiscontinuityTimer(); // Initialize client from provider - final serverState = ref.read(individualServerNotifierProvider(widget.args.spi.id)); + final serverState = ref.read(serverNotifierProvider(widget.args.spi.id)); _client = serverState.client; if (++_sshConnCount == 1) { diff --git a/lib/view/page/ssh/tab.dart b/lib/view/page/ssh/tab.dart index 6a940ec3..70d19621 100644 --- a/lib/view/page/ssh/tab.dart +++ b/lib/view/page/ssh/tab.dart @@ -7,7 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:icons_plus/icons_plus.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.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/view/page/server/edit.dart'; import 'package:server_box/view/page/ssh/page/page.dart'; @@ -249,7 +249,7 @@ class _AddPage extends ConsumerWidget { const viewPadding = 7.0; final viewWidth = context.windowSize.width - 2 * viewPadding; - final serverState = ref.watch(serverNotifierProvider); + final serverState = ref.watch(serversNotifierProvider); final itemCount = serverState.servers.length; const itemPadding = 1.0; const itemWidth = 150.0; diff --git a/lib/view/page/storage/local.dart b/lib/view/page/storage/local.dart index 015bf544..824a5738 100644 --- a/lib/view/page/storage/local.dart +++ b/lib/view/page/storage/local.dart @@ -7,7 +7,7 @@ import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/data/model/app/path_with_prefix.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/sftp/worker.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/all.dart'; import 'package:server_box/data/provider/sftp.dart'; import 'package:server_box/data/res/misc.dart'; import 'package:server_box/data/store/setting.dart'; @@ -359,7 +359,7 @@ extension _OnTapFile on _LocalFilePageState { final spi = await context.showPickSingleDialog( title: libL10n.select, - items: ref.read(serverNotifierProvider).servers.values.toList(), + items: ref.read(serversNotifierProvider).servers.values.toList(), display: (e) => e.name, ); if (spi == null) return; diff --git a/lib/view/page/storage/sftp.dart b/lib/view/page/storage/sftp.dart index c4ed448b..ff8a9552 100644 --- a/lib/view/page/storage/sftp.dart +++ b/lib/view/page/storage/sftp.dart @@ -12,7 +12,7 @@ import 'package:server_box/core/utils/comparator.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/sftp/browser_status.dart'; import 'package:server_box/data/model/sftp/worker.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; import 'package:server_box/data/provider/sftp.dart'; import 'package:server_box/data/res/misc.dart'; import 'package:server_box/data/res/store.dart'; @@ -50,7 +50,7 @@ class _SftpPageState extends ConsumerState with AfterLayoutMixin { @override void initState() { super.initState(); - final serverState = ref.read(individualServerNotifierProvider(widget.args.spi.id)); + final serverState = ref.read(serverNotifierProvider(widget.args.spi.id)); _client = serverState.client!; _status = SftpBrowserStatus(_client); } diff --git a/lib/view/widget/server_func_btns.dart b/lib/view/widget/server_func_btns.dart index b7a7529a..dd3257d8 100644 --- a/lib/view/widget/server_func_btns.dart +++ b/lib/view/widget/server_func_btns.dart @@ -10,7 +10,7 @@ import 'package:server_box/data/model/app/menu/base.dart'; import 'package:server_box/data/model/app/menu/server_func.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/snippet.dart'; -import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/provider/server/single.dart'; import 'package:server_box/data/provider/snippet.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/container/container.dart'; @@ -273,7 +273,7 @@ void _gotoSSH(Spi spi, BuildContext context) async { } bool _checkClient(BuildContext context, String id, WidgetRef ref) { - final serverState = ref.read(individualServerNotifierProvider(id)); + final serverState = ref.read(serverNotifierProvider(id)); if (serverState.client == null) { context.showSnackBar(l10n.waitConnection); return false;