mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
opt.: servers list -> map
This commit is contained in:
@@ -2,8 +2,8 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:toolbox/core/build_mode.dart';
|
|
||||||
|
|
||||||
|
import '../../core/build_mode.dart';
|
||||||
import '../../core/extension/uint8list.dart';
|
import '../../core/extension/uint8list.dart';
|
||||||
import '../../core/provider_base.dart';
|
import '../../core/provider_base.dart';
|
||||||
import '../../core/utils/server.dart';
|
import '../../core/utils/server.dart';
|
||||||
@@ -18,9 +18,11 @@ import '../res/status.dart';
|
|||||||
import '../store/server.dart';
|
import '../store/server.dart';
|
||||||
import '../store/setting.dart';
|
import '../store/setting.dart';
|
||||||
|
|
||||||
|
typedef ServersMap = Map<String, Server>;
|
||||||
|
|
||||||
class ServerProvider extends BusyProvider {
|
class ServerProvider extends BusyProvider {
|
||||||
List<Server> _servers = [];
|
final ServersMap _servers = {};
|
||||||
List<Server> get servers => _servers;
|
ServersMap get servers => _servers;
|
||||||
final _limiter = TryLimiter();
|
final _limiter = TryLimiter();
|
||||||
|
|
||||||
Timer? _timer;
|
Timer? _timer;
|
||||||
@@ -30,7 +32,9 @@ class ServerProvider extends BusyProvider {
|
|||||||
Future<void> loadLocalData() async {
|
Future<void> loadLocalData() async {
|
||||||
setBusyState(true);
|
setBusyState(true);
|
||||||
final infos = locator<ServerStore>().fetch();
|
final infos = locator<ServerStore>().fetch();
|
||||||
_servers = List.generate(infos.length, (index) => genServer(infos[index]));
|
for (final info in infos) {
|
||||||
|
_servers[info.id] = genServer(info);
|
||||||
|
}
|
||||||
setBusyState(false);
|
setBusyState(false);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@@ -45,13 +49,14 @@ class ServerProvider extends BusyProvider {
|
|||||||
await _getData(spi);
|
await _getData(spi);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await Future.wait(_servers.map((s) async {
|
final futures = _servers.values.map((s) async {
|
||||||
if (onlyFailed) {
|
if (onlyFailed) {
|
||||||
if (s.state != ServerState.failed) return;
|
if (s.state != ServerState.failed) return;
|
||||||
_limiter.resetTryTimes(s.spi.id);
|
_limiter.resetTryTimes(s.spi.id);
|
||||||
}
|
}
|
||||||
await _getData(s.spi);
|
return await _getData(s.spi);
|
||||||
}));
|
});
|
||||||
|
await Future.wait(futures);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> startAutoRefresh() async {
|
Future<void> startAutoRefresh() async {
|
||||||
@@ -71,72 +76,62 @@ class ServerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get isAutoRefreshOn => _timer != null;
|
||||||
|
|
||||||
void setDisconnected() {
|
void setDisconnected() {
|
||||||
for (var i = 0; i < _servers.length; i++) {
|
for (final s in _servers.values) {
|
||||||
_servers[i].state = ServerState.disconnected;
|
s.state = ServerState.disconnected;
|
||||||
}
|
}
|
||||||
_limiter.clear();
|
_limiter.clear();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeServer({ServerPrivateInfo? spi}) {
|
void closeServer({String? id}) {
|
||||||
if (spi == null) {
|
if (id == null) {
|
||||||
for (var i = 0; i < _servers.length; i++) {
|
for (final s in _servers.values) {
|
||||||
_servers[i].client?.close();
|
_closeOneServer(s.spi.id);
|
||||||
_servers[i].client = null;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final idx = getServerIdx(spi.id);
|
_closeOneServer(id);
|
||||||
_servers[idx].client?.close();
|
}
|
||||||
_servers[idx].client = null;
|
|
||||||
|
void _closeOneServer(String id) {
|
||||||
|
_servers[id]?.client?.close();
|
||||||
|
_servers[id]?.client = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addServer(ServerPrivateInfo spi) {
|
void addServer(ServerPrivateInfo spi) {
|
||||||
_servers.add(genServer(spi));
|
_servers[spi.id] = genServer(spi);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
locator<ServerStore>().put(spi);
|
locator<ServerStore>().put(spi);
|
||||||
refreshData(spi: spi);
|
refreshData(spi: spi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delServer(String id) {
|
void delServer(String id) {
|
||||||
final idx = getServerIdx(id);
|
_servers.remove(id);
|
||||||
_servers[idx].client?.close();
|
|
||||||
_servers.removeAt(idx);
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
locator<ServerStore>().delete(id);
|
locator<ServerStore>().delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateServer(
|
Future<void> updateServer(
|
||||||
ServerPrivateInfo old, ServerPrivateInfo newSpi) async {
|
ServerPrivateInfo old, ServerPrivateInfo newSpi) async {
|
||||||
final idx = _servers.indexWhere((e) => e.spi.id == old.id);
|
_servers.remove(old.id);
|
||||||
if (idx < 0) {
|
|
||||||
throw RangeError.index(idx, _servers);
|
|
||||||
}
|
|
||||||
_servers[idx].spi = newSpi;
|
|
||||||
locator<ServerStore>().update(old, newSpi);
|
locator<ServerStore>().update(old, newSpi);
|
||||||
_servers[idx].client = await genClient(newSpi);
|
_servers[newSpi.id] = genServer(newSpi);
|
||||||
|
_servers[newSpi.id]?.client = await genClient(newSpi);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
refreshData(spi: newSpi);
|
refreshData(spi: newSpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getServerIdx(String id) {
|
|
||||||
final idx = _servers.indexWhere((s) => s.spi.id == id);
|
|
||||||
if (idx < 0) {
|
|
||||||
throw Exception('Server not found: $id');
|
|
||||||
}
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
Server getServer(String id) => _servers[getServerIdx(id)];
|
|
||||||
|
|
||||||
Future<void> _getData(ServerPrivateInfo spi) async {
|
Future<void> _getData(ServerPrivateInfo spi) async {
|
||||||
final sid = spi.id;
|
final sid = spi.id;
|
||||||
final s = getServer(sid);
|
final s = _servers[sid];
|
||||||
|
if (s == null) return;
|
||||||
|
|
||||||
|
try {
|
||||||
final state = s.state;
|
final state = s.state;
|
||||||
if (!state.shouldConnect) {
|
if (state.shouldConnect) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!_limiter.shouldTry(sid)) {
|
if (!_limiter.shouldTry(sid)) {
|
||||||
s.state = ServerState.failed;
|
s.state = ServerState.failed;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -145,7 +140,6 @@ class ServerProvider extends BusyProvider {
|
|||||||
s.state = ServerState.connecting;
|
s.state = ServerState.connecting;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
try {
|
|
||||||
// try to connect
|
// try to connect
|
||||||
final time1 = DateTime.now();
|
final time1 = DateTime.now();
|
||||||
s.client = await genClient(spi);
|
s.client = await genClient(spi);
|
||||||
@@ -156,7 +150,6 @@ class ServerProvider extends BusyProvider {
|
|||||||
// after connected
|
// after connected
|
||||||
s.state = ServerState.connected;
|
s.state = ServerState.connected;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
// write script to server
|
// write script to server
|
||||||
final writeResult = await s.client!.run(installShellCmd).string;
|
final writeResult = await s.client!.run(installShellCmd).string;
|
||||||
|
|
||||||
@@ -164,9 +157,10 @@ class ServerProvider extends BusyProvider {
|
|||||||
if (writeResult.isNotEmpty) {
|
if (writeResult.isNotEmpty) {
|
||||||
throw Exception(writeResult);
|
throw Exception(writeResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset try times if connected successfully
|
// reset try times if connected successfully
|
||||||
_limiter.resetTryTimes(sid);
|
_limiter.resetTryTimes(sid);
|
||||||
|
}
|
||||||
|
|
||||||
if (s.client == null) return;
|
if (s.client == null) return;
|
||||||
// run script to get server status
|
// run script to get server status
|
||||||
final raw = await s.client!.run("sh $shellPath").string;
|
final raw = await s.client!.run("sh $shellPath").string;
|
||||||
@@ -181,6 +175,7 @@ class ServerProvider extends BusyProvider {
|
|||||||
// remove first empty segment
|
// remove first empty segment
|
||||||
// for `export xxx` in shell script
|
// for `export xxx` in shell script
|
||||||
segments.removeAt(0);
|
segments.removeAt(0);
|
||||||
|
|
||||||
final req = ServerStatusUpdateReq(s.status, segments);
|
final req = ServerStatusUpdateReq(s.status, segments);
|
||||||
s.status = await compute(getStatus, req);
|
s.status = await compute(getStatus, req);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -196,7 +191,7 @@ class ServerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> runSnippet(String id, Snippet snippet) async {
|
Future<String?> runSnippet(String id, Snippet snippet) async {
|
||||||
final client = getServer(id).client;
|
final client = _servers[id]?.client;
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final client = locator<ServerProvider>().getServer(widget.spi.id).client;
|
final client = locator<ServerProvider>().servers[widget.spi.id]?.client;
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
showSnackBar(context, Text(_s.noClient));
|
showSnackBar(context, Text(_s.noClient));
|
||||||
context.pop();
|
context.pop();
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AppLifecycleState.resumed:
|
case AppLifecycleState.resumed:
|
||||||
if (isIOS) {
|
if (!_serverProvider.isAutoRefreshOn) {
|
||||||
_serverProvider.startAutoRefresh();
|
_serverProvider.startAutoRefresh();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ class _PingPageState extends State<PingPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Future.wait(_serverProvider.servers.map((e) async {
|
await Future.wait(_serverProvider.servers.values.map((e) async {
|
||||||
if (e.client == null) {
|
if (e.client == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ class _PkgManagePageState extends State<PkgManagePage>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final si = locator<ServerProvider>().getServer(widget.spi.id);
|
final si = locator<ServerProvider>().servers[widget.spi.id];
|
||||||
if (si.client == null) {
|
if (si == null || si.client == null) {
|
||||||
showSnackBar(context, Text(_s.waitConnection));
|
showSnackBar(context, Text(_s.waitConnection));
|
||||||
context.pop();
|
context.pop();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -40,9 +40,15 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<ServerProvider>(builder: (_, provider, __) {
|
return Consumer<ServerProvider>(builder: (_, provider, __) {
|
||||||
return _buildMainPage(
|
final s = provider.servers[widget.id];
|
||||||
provider.getServer(widget.id),
|
if (s == null) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: Text(_s.noClient),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
return _buildMainPage(s);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
final keys = pro.servers.keys.toList();
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
padding: const EdgeInsets.all(7),
|
padding: const EdgeInsets.all(7),
|
||||||
controller: ScrollController(),
|
controller: ScrollController(),
|
||||||
@@ -83,9 +84,9 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
if (idx == pro.servers.length) {
|
if (idx == pro.servers.length) {
|
||||||
return SizedBox(height: _media.padding.bottom);
|
return SizedBox(height: _media.padding.bottom);
|
||||||
}
|
}
|
||||||
return _buildEachServerCard(pro.servers[idx]);
|
return _buildEachServerCard(pro.servers[keys[idx]]);
|
||||||
},
|
},
|
||||||
itemCount: pro.servers.length + 1,
|
itemCount: pro.servers.length,
|
||||||
separatorBuilder: (_, __) => const SizedBox(
|
separatorBuilder: (_, __) => const SizedBox(
|
||||||
height: 3,
|
height: 3,
|
||||||
),
|
),
|
||||||
@@ -105,7 +106,10 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEachServerCard(Server si) {
|
Widget _buildEachServerCard(Server? si) {
|
||||||
|
if (si == null) {
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
InkWell(
|
InkWell(
|
||||||
onLongPress: () => AppRoute(
|
onLongPress: () => AppRoute(
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final serverProvider = locator<ServerProvider>();
|
final serverProvider = locator<ServerProvider>();
|
||||||
_si = serverProvider.getServer(widget.spi.id);
|
_si = serverProvider.servers[widget.spi.id];
|
||||||
_client = _si?.client;
|
_client = _si?.client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user