mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-18 15:54:35 +01:00
refactors (#539)
This commit is contained in:
@@ -10,8 +10,8 @@ import 'package:server_box/core/utils/sync/webdav.dart';
|
||||
import 'package:server_box/data/model/app/backup.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/snippet.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
|
||||
@@ -266,7 +266,7 @@ class BackupPage extends StatelessWidget {
|
||||
actions: Btn.ok(
|
||||
onTap: () {
|
||||
for (final snippet in snippets) {
|
||||
Pros.snippet.add(snippet);
|
||||
SnippetProvider.add(snippet);
|
||||
}
|
||||
context.pop();
|
||||
context.pop();
|
||||
@@ -441,7 +441,7 @@ class BackupPage extends StatelessWidget {
|
||||
void _onBulkImportServers(BuildContext context) async {
|
||||
final data = await context.showImportDialog(
|
||||
title: l10n.server,
|
||||
modelDef: ServerPrivateInfo.example.toJson(),
|
||||
modelDef: Spix.example.toJson(),
|
||||
);
|
||||
if (data == null) return;
|
||||
final text = String.fromCharCodes(data);
|
||||
@@ -450,7 +450,7 @@ class BackupPage extends StatelessWidget {
|
||||
final (spis, err) = await context.showLoadingDialog(
|
||||
fn: () => Computer.shared.start((val) {
|
||||
final list = json.decode(val) as List;
|
||||
return list.map((e) => ServerPrivateInfo.fromJson(e)).toList();
|
||||
return list.map((e) => Spi.fromJson(e)).toList();
|
||||
}, text.trim()),
|
||||
);
|
||||
if (err != null || spis == null) return;
|
||||
|
||||
@@ -17,7 +17,7 @@ import 'package:server_box/data/provider/container.dart';
|
||||
import 'package:server_box/view/widget/two_line_text.dart';
|
||||
|
||||
class ContainerPage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
final Spi spi;
|
||||
const ContainerPage({required this.spi, super.key});
|
||||
|
||||
@override
|
||||
@@ -27,7 +27,7 @@ class ContainerPage extends StatefulWidget {
|
||||
class _ContainerPageState extends State<ContainerPage> {
|
||||
final _textController = TextEditingController();
|
||||
late final _container = ContainerProvider(
|
||||
client: widget.spi.server?.client,
|
||||
client: widget.spi.server?.value.client,
|
||||
userName: widget.spi.user,
|
||||
hostId: widget.spi.id,
|
||||
context: context,
|
||||
|
||||
@@ -9,10 +9,10 @@ import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/route.dart';
|
||||
import 'package:server_box/data/model/app/tab.dart';
|
||||
import 'package:server_box/data/provider/app.dart';
|
||||
import 'package:server_box/data/provider/server.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/misc.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:server_box/data/res/url.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
@@ -65,7 +65,7 @@ class _HomePageState extends State<HomePage>
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
Pros.server.closeServer();
|
||||
ServerProvider.closeServer();
|
||||
_pageController.dispose();
|
||||
WakelockPlus.disable();
|
||||
}
|
||||
@@ -78,8 +78,8 @@ class _HomePageState extends State<HomePage>
|
||||
switch (state) {
|
||||
case AppLifecycleState.resumed:
|
||||
if (_shouldAuth) _goAuth();
|
||||
if (!Pros.server.isAutoRefreshOn) {
|
||||
Pros.server.startAutoRefresh();
|
||||
if (!ServerProvider.isAutoRefreshOn) {
|
||||
ServerProvider.startAutoRefresh();
|
||||
}
|
||||
HomeWidgetMC.update();
|
||||
break;
|
||||
@@ -93,7 +93,7 @@ class _HomePageState extends State<HomePage>
|
||||
// }
|
||||
} else {
|
||||
//Pros.server.setDisconnected();
|
||||
Pros.server.stopAutoRefresh();
|
||||
ServerProvider.stopAutoRefresh();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -120,7 +120,7 @@ class _HomePageState extends State<HomePage>
|
||||
icon: const Icon(Icons.refresh),
|
||||
tooltip: 'Refresh',
|
||||
onPressed: () async {
|
||||
await Pros.server.refresh();
|
||||
await ServerProvider.refresh();
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -333,8 +333,7 @@ ${GithubIds.participants.map((e) => '[$e](${e.url})').join(' ')}
|
||||
);
|
||||
}
|
||||
HomeWidgetMC.update();
|
||||
await Pros.server.load();
|
||||
await Pros.server.refresh();
|
||||
await ServerProvider.refresh();
|
||||
}
|
||||
|
||||
// Future<void> _reqNotiPerm() async {
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/data/model/server/server.dart';
|
||||
import 'package:server_box/data/provider/server.dart';
|
||||
import 'package:server_box/data/res/build_data.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:server_box/data/res/url.dart';
|
||||
|
||||
final class WearHome extends StatefulWidget {
|
||||
const WearHome({super.key});
|
||||
|
||||
@override
|
||||
State<WearHome> createState() => _WearHomeState();
|
||||
}
|
||||
|
||||
final class _WearHomeState extends State<WearHome> with AfterLayoutMixin {
|
||||
late final _pageCtrl =
|
||||
PageController(initialPage: Pros.server.servers.isNotEmpty ? 1 : 0);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _buildBody();
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return Consumer<ServerProvider>(builder: (_, pro, __) {
|
||||
if (pro.servers.isEmpty) {
|
||||
return const Center(child: Text('No server'));
|
||||
}
|
||||
return PageView.builder(
|
||||
controller: _pageCtrl,
|
||||
itemCount: pro.servers.length + 1,
|
||||
itemBuilder: (_, index) {
|
||||
if (index == 0) return _buildInit();
|
||||
|
||||
final id = pro.serverOrder[index];
|
||||
final server = Pros.server.pick(id: id);
|
||||
if (server == null) return UIs.placeholder;
|
||||
return _buildEachSever(server);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildInit() {
|
||||
return Center(
|
||||
child: Column(
|
||||
children: [
|
||||
IconButton(onPressed: () {}, icon: const Icon(Icons.add)),
|
||||
UIs.height7,
|
||||
Text(libL10n.restore)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildEachSever(Server srv) {
|
||||
final mem = () {
|
||||
final total = srv.status.mem.total;
|
||||
final used = srv.status.mem.total - srv.status.mem.avail;
|
||||
return '${used.bytes2Str} / ${total.bytes2Str}';
|
||||
}();
|
||||
final disk = () {
|
||||
final total = srv.status.diskUsage?.size.kb2Str;
|
||||
final used = srv.status.diskUsage?.used.kb2Str;
|
||||
return '$used / $total';
|
||||
}();
|
||||
final net = '↓ ${srv.status.netSpeed.cachedRealVals.speedIn}'
|
||||
'↑ ${srv.status.netSpeed.cachedRealVals.speedOut}';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(7),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(srv.spi.name, style: UIs.text15Bold),
|
||||
UIs.height7,
|
||||
KvRow(k: 'CPU', v: '${srv.status.cpu.usedPercent()}%'),
|
||||
KvRow(k: 'Mem', v: mem),
|
||||
KvRow(k: 'Disk', v: disk),
|
||||
KvRow(k: 'Net', v: net)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> afterFirstLayout(BuildContext context) async {
|
||||
if (Stores.setting.autoCheckAppUpdate.fetch()) {
|
||||
AppUpdateIface.doUpdate(
|
||||
build: BuildData.build,
|
||||
url: Urls.updateCfg,
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
await Pros.server.load();
|
||||
await Pros.server.refresh();
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import 'package:server_box/core/route.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
|
||||
class IPerfPage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
final Spi spi;
|
||||
const IPerfPage({super.key, required this.spi});
|
||||
|
||||
@override
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:async';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/provider/server.dart';
|
||||
|
||||
import 'package:server_box/data/model/server/ping_result.dart';
|
||||
|
||||
@@ -150,7 +150,7 @@ class _PingPageState extends State<PingPage>
|
||||
return;
|
||||
}
|
||||
|
||||
if (Pros.server.serverOrder.isEmpty) {
|
||||
if (ServerProvider.serverOrder.value.isEmpty) {
|
||||
context.showSnackBar(l10n.pingNoServer);
|
||||
return;
|
||||
}
|
||||
@@ -161,7 +161,8 @@ class _PingPageState extends State<PingPage>
|
||||
return;
|
||||
}
|
||||
|
||||
await Future.wait(Pros.server.servers.map((e) async {
|
||||
await Future.wait(ServerProvider.servers.values.map((v) async {
|
||||
final e = v.value;
|
||||
if (e.client == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/provider/private_key.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
|
||||
import 'package:server_box/core/utils/server.dart';
|
||||
import 'package:server_box/data/model/server/private_key_info.dart';
|
||||
@@ -89,7 +89,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
||||
)),
|
||||
actions: Btn.ok(
|
||||
onTap: () {
|
||||
Pros.key.delete(widget.pki!);
|
||||
PrivateKeyProvider.delete(widget.pki!);
|
||||
context.pop();
|
||||
context.pop();
|
||||
},
|
||||
@@ -204,9 +204,9 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
||||
final decrypted = await Computer.shared.start(decyptPem, [key, pwd]);
|
||||
final pki = PrivateKeyInfo(id: name, key: decrypted);
|
||||
if (widget.pki != null) {
|
||||
Pros.key.update(widget.pki!, pki);
|
||||
PrivateKeyProvider.update(widget.pki!, pki);
|
||||
} else {
|
||||
Pros.key.add(pki);
|
||||
PrivateKeyProvider.add(pki);
|
||||
}
|
||||
} catch (e) {
|
||||
context.showSnackBar(e.toString());
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
@@ -35,16 +34,16 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return Consumer<PrivateKeyProvider>(
|
||||
builder: (_, key, __) {
|
||||
if (key.pkis.isEmpty) {
|
||||
return PrivateKeyProvider.pkis.listenVal(
|
||||
(pkis) {
|
||||
if (pkis.isEmpty) {
|
||||
return Center(child: Text(libL10n.empty));
|
||||
}
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(13),
|
||||
itemCount: key.pkis.length,
|
||||
itemCount: pkis.length,
|
||||
itemBuilder: (context, idx) {
|
||||
final item = key.pkis[idx];
|
||||
final item = pkis[idx];
|
||||
return CardX(
|
||||
child: ListTile(
|
||||
leading: Text(
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/view/widget/two_line_text.dart';
|
||||
|
||||
class ProcessPage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
final Spi spi;
|
||||
const ProcessPage({super.key, required this.spi});
|
||||
|
||||
@override
|
||||
@@ -37,7 +37,7 @@ class _ProcessPageState extends State<ProcessPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_client = widget.spi.server?.client;
|
||||
_client = widget.spi.server?.value.client;
|
||||
final duration =
|
||||
Duration(seconds: Stores.setting.serverStatusUpdateInterval.fetch());
|
||||
_timer = Timer.periodic(duration, (_) => _refresh());
|
||||
|
||||
@@ -11,7 +11,7 @@ import 'package:server_box/view/widget/percent_circle.dart';
|
||||
import 'package:server_box/view/widget/two_line_text.dart';
|
||||
|
||||
final class PvePage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
final Spi spi;
|
||||
|
||||
const PvePage({
|
||||
super.key,
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/app/server_detail_card.dart';
|
||||
import 'package:server_box/data/model/app/shell_func.dart';
|
||||
@@ -22,14 +21,13 @@ import 'package:server_box/view/widget/server_func_btns.dart';
|
||||
|
||||
import 'package:server_box/core/route.dart';
|
||||
import 'package:server_box/data/model/server/server.dart';
|
||||
import 'package:server_box/data/provider/server.dart';
|
||||
|
||||
part 'misc.dart';
|
||||
|
||||
class ServerDetailPage extends StatefulWidget {
|
||||
const ServerDetailPage({super.key, required this.spi});
|
||||
|
||||
final ServerPrivateInfo spi;
|
||||
final Spi spi;
|
||||
|
||||
@override
|
||||
State<ServerDetailPage> createState() => _ServerDetailPageState();
|
||||
@@ -79,16 +77,14 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<ServerProvider>(builder: (_, provider, __) {
|
||||
final s = widget.spi.server;
|
||||
if (s == null) {
|
||||
return Scaffold(
|
||||
appBar: const CustomAppBar(),
|
||||
body: Center(child: Text(libL10n.empty)),
|
||||
);
|
||||
}
|
||||
return _buildMainPage(s);
|
||||
});
|
||||
final s = widget.spi.server;
|
||||
if (s == null) {
|
||||
return Scaffold(
|
||||
appBar: const CustomAppBar(),
|
||||
body: Center(child: Text(libL10n.empty)),
|
||||
);
|
||||
}
|
||||
return s.listenVal(_buildMainPage);
|
||||
}
|
||||
|
||||
Widget _buildMainPage(Server si) {
|
||||
@@ -96,12 +92,12 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
final logo = _buildLogo(si);
|
||||
final children = [
|
||||
logo,
|
||||
if (buildFuncs) ServerFuncBtns(spi: widget.spi),
|
||||
if (buildFuncs) ServerFuncBtns(spi: si.spi),
|
||||
];
|
||||
for (final card in _cardsOrder) {
|
||||
final buildFunc = _cardBuildMap[card];
|
||||
if (buildFunc != null) {
|
||||
children.add(buildFunc(si.status));
|
||||
children.add(buildFunc(si));
|
||||
}
|
||||
}
|
||||
return Scaffold(
|
||||
@@ -122,8 +118,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
title: Text(si.spi.name),
|
||||
actions: [
|
||||
ShareBtn(
|
||||
data: widget.spi.toJsonString(),
|
||||
tip: widget.spi.name,
|
||||
data: si.spi.toJsonString(),
|
||||
tip: si.spi.name,
|
||||
tip2: '${libL10n.share} ${l10n.server} ~ ServerBox',
|
||||
),
|
||||
IconButton(
|
||||
@@ -160,7 +156,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAbout(ServerStatus ss) {
|
||||
Widget _buildAbout(Server si) {
|
||||
final ss = si.status;
|
||||
return CardX(
|
||||
child: ExpandTile(
|
||||
leading: const Icon(MingCute.information_fill, size: 20),
|
||||
@@ -188,7 +185,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCPUView(ServerStatus ss) {
|
||||
Widget _buildCPUView(Server si) {
|
||||
final ss = si.status;
|
||||
final percent = ss.cpu.usedPercent(coreIdx: 0).toInt();
|
||||
final details = [
|
||||
_buildDetailPercent(ss.cpu.user, 'user'),
|
||||
@@ -352,7 +350,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMemView(ServerStatus ss) {
|
||||
Widget _buildMemView(Server si) {
|
||||
final ss = si.status;
|
||||
final free = ss.mem.free / ss.mem.total * 100;
|
||||
final avail = ss.mem.availPercent * 100;
|
||||
final used = ss.mem.usedPercent * 100;
|
||||
@@ -399,7 +398,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSwapView(ServerStatus ss) {
|
||||
Widget _buildSwapView(Server si) {
|
||||
final ss = si.status;
|
||||
if (ss.swap.total == 0) return UIs.placeholder;
|
||||
final used = ss.swap.usedPercent * 100;
|
||||
final cached = ss.swap.cached / ss.swap.total * 100;
|
||||
@@ -434,7 +434,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildGpuView(ServerStatus ss) {
|
||||
Widget _buildGpuView(Server si) {
|
||||
final ss = si.status;
|
||||
if (ss.nvidia == null || ss.nvidia?.isEmpty == true) return UIs.placeholder;
|
||||
final children = ss.nvidia?.map((e) => _buildGpuItem(e)).toList() ?? [];
|
||||
return CardX(
|
||||
@@ -544,7 +545,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDiskView(ServerStatus ss) {
|
||||
Widget _buildDiskView(Server si) {
|
||||
final ss = si.status;
|
||||
final children = List.generate(
|
||||
ss.disk.length, (idx) => _buildDiskItem(ss.disk[idx], ss));
|
||||
return CardX(
|
||||
@@ -608,7 +610,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNetView(ServerStatus ss) {
|
||||
Widget _buildNetView(Server si) {
|
||||
final ss = si.status;
|
||||
final ns = ss.netSpeed;
|
||||
final children = <Widget>[];
|
||||
final devices = ns.devices;
|
||||
@@ -691,14 +694,15 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTemperature(ServerStatus ss) {
|
||||
Widget _buildTemperature(Server si) {
|
||||
final ss = si.status;
|
||||
if (ss.temps.isEmpty) {
|
||||
return UIs.placeholder;
|
||||
}
|
||||
return CardX(
|
||||
child: ExpandTile(
|
||||
title: Text(l10n.temperature),
|
||||
leading: const Icon(Icons.ac_unit, size: 17),
|
||||
leading: const Icon(Icons.ac_unit, size: 20),
|
||||
initiallyExpanded: _getInitExpand(ss.temps.devices.length),
|
||||
childrenPadding: const EdgeInsets.only(bottom: 7),
|
||||
children: ss.temps.devices
|
||||
@@ -726,7 +730,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBatteries(ServerStatus ss) {
|
||||
Widget _buildBatteries(Server si) {
|
||||
final ss = si.status;
|
||||
if (ss.batteries.isEmpty) {
|
||||
return UIs.placeholder;
|
||||
}
|
||||
@@ -767,7 +772,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSensors(ServerStatus ss) {
|
||||
Widget _buildSensors(Server si) {
|
||||
final ss = si.status;
|
||||
if (ss.sensors.isEmpty) return UIs.placeholder;
|
||||
return CardX(
|
||||
child: ExpandTile(
|
||||
@@ -830,20 +836,21 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPve(_) {
|
||||
final addr = widget.spi.custom?.pveAddr;
|
||||
if (addr == null) return UIs.placeholder;
|
||||
Widget _buildPve(Server si) {
|
||||
final addr = si.spi.custom?.pveAddr;
|
||||
if (addr == null || addr.isEmpty) return UIs.placeholder;
|
||||
return CardX(
|
||||
child: ListTile(
|
||||
title: const Text('PVE'),
|
||||
leading: const Icon(FontAwesome.server_solid, size: 17),
|
||||
trailing: const Icon(Icons.chevron_right),
|
||||
onTap: () => AppRoutes.pve(spi: widget.spi).go(context),
|
||||
onTap: () => AppRoutes.pve(spi: si.spi).go(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCustom(ServerStatus ss) {
|
||||
Widget _buildCustom(Server si) {
|
||||
final ss = si.status;
|
||||
if (ss.customCmds.isEmpty) return UIs.placeholder;
|
||||
return CardX(
|
||||
child: ExpandTile(
|
||||
|
||||
@@ -3,11 +3,10 @@ import 'dart:convert';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/server/custom.dart';
|
||||
import 'package:server_box/data/model/server/wol_cfg.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/provider/server.dart';
|
||||
|
||||
import 'package:server_box/core/route.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
@@ -16,7 +15,7 @@ import 'package:server_box/data/provider/private_key.dart';
|
||||
class ServerEditPage extends StatefulWidget {
|
||||
const ServerEditPage({super.key, this.spi});
|
||||
|
||||
final ServerPrivateInfo? spi;
|
||||
final Spi? spi;
|
||||
|
||||
@override
|
||||
State<ServerEditPage> createState() => _ServerEditPageState();
|
||||
@@ -148,7 +147,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
hint: 'root',
|
||||
suggestion: false,
|
||||
),
|
||||
TagTile(tags: _tags, allTags: Pros.server.tags.value).cardx,
|
||||
TagTile(tags: _tags, allTags: ServerProvider.tags.value).cardx,
|
||||
ListTile(
|
||||
title: Text(l10n.autoConnect),
|
||||
trailing: ListenableBuilder(
|
||||
@@ -219,10 +218,10 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
|
||||
Widget _buildKeyAuth() {
|
||||
const padding = EdgeInsets.only(left: 23, right: 13);
|
||||
return Consumer<PrivateKeyProvider>(
|
||||
builder: (_, key, __) {
|
||||
final tiles = List<Widget>.generate(key.pkis.length, (index) {
|
||||
final e = key.pkis[index];
|
||||
return PrivateKeyProvider.pkis.listenVal(
|
||||
(pkis) {
|
||||
final tiles = List<Widget>.generate(pkis.length, (index) {
|
||||
final e = pkis[index];
|
||||
return ListTile(
|
||||
contentPadding: padding,
|
||||
leading: Text(
|
||||
@@ -289,7 +288,6 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
return ExpandTile(
|
||||
title: Text(l10n.more),
|
||||
children: [
|
||||
UIs.height7,
|
||||
Input(
|
||||
controller: _logoUrlCtrl,
|
||||
type: TextInputType.url,
|
||||
@@ -300,13 +298,9 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
),
|
||||
_buildAltUrl(),
|
||||
_buildEnvs(),
|
||||
UIs.height7,
|
||||
..._buildPVEs(),
|
||||
UIs.height7,
|
||||
..._buildCustomCmds(),
|
||||
UIs.height7,
|
||||
Text(l10n.temperature, style: UIs.text13Grey),
|
||||
UIs.height7,
|
||||
CenterGreyTitle(l10n.temperature),
|
||||
Input(
|
||||
controller: _preferTempDevCtrl,
|
||||
type: TextInputType.text,
|
||||
@@ -336,26 +330,14 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
List<Widget> _buildPVEs() {
|
||||
const addr = 'https://127.0.0.1:8006';
|
||||
return [
|
||||
const Text('PVE', style: UIs.text13Grey),
|
||||
UIs.height7,
|
||||
Autocomplete<String>(
|
||||
optionsBuilder: (val) {
|
||||
final v = val.text;
|
||||
if (v.startsWith(addr.substring(0, v.length))) {
|
||||
return [addr];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
onSelected: (val) => _pveAddrCtrl.text = val,
|
||||
fieldViewBuilder: (_, ctrl, node, __) => Input(
|
||||
controller: ctrl,
|
||||
type: TextInputType.url,
|
||||
icon: MingCute.web_line,
|
||||
node: node,
|
||||
label: 'URL',
|
||||
hint: addr,
|
||||
suggestion: false,
|
||||
),
|
||||
const CenterGreyTitle('PVE'),
|
||||
Input(
|
||||
controller: _pveAddrCtrl,
|
||||
type: TextInputType.url,
|
||||
icon: MingCute.web_line,
|
||||
label: 'URL',
|
||||
hint: addr,
|
||||
suggestion: false,
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(MingCute.certificate_line),
|
||||
@@ -376,8 +358,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
|
||||
List<Widget> _buildCustomCmds() {
|
||||
return [
|
||||
Text(l10n.customCmd, style: UIs.text13Grey),
|
||||
UIs.height7,
|
||||
CenterGreyTitle(l10n.customCmd),
|
||||
_customCmds.listenVal(
|
||||
(vals) {
|
||||
return ListTile(
|
||||
@@ -455,9 +436,10 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
return ListenableBuilder(
|
||||
listenable: _jumpServer,
|
||||
builder: (_, __) {
|
||||
final children = Pros.server.servers
|
||||
.where((element) => element.spi.jumpId == null)
|
||||
.where((element) => element.spi.id != widget.spi?.id)
|
||||
final children = ServerProvider.servers.values
|
||||
.map((e) => e.value)
|
||||
.where((e) => e.spi.jumpId == null)
|
||||
.where((e) => e.spi.id != widget.spi?.id)
|
||||
.map(
|
||||
(e) => ListTile(
|
||||
title: Text(e.spi.name),
|
||||
@@ -552,7 +534,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
}
|
||||
}
|
||||
|
||||
final spi = ServerPrivateInfo(
|
||||
final spi = Spi(
|
||||
name: _nameController.text.isEmpty
|
||||
? _ipController.text
|
||||
: _nameController.text,
|
||||
@@ -561,7 +543,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
user: _usernameController.text,
|
||||
pwd: _passwordController.text.selfIfNotNullEmpty,
|
||||
keyId: _keyIdx.value != null
|
||||
? Pros.key.pkis.elementAt(_keyIdx.value!).id
|
||||
? PrivateKeyProvider.pkis.value.elementAt(_keyIdx.value!).id
|
||||
: null,
|
||||
tags: _tags.value.isEmpty ? null : _tags.value.toList(),
|
||||
alterUrl: _altUrlController.text.selfIfNotNullEmpty,
|
||||
@@ -573,9 +555,9 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
);
|
||||
|
||||
if (widget.spi == null) {
|
||||
Pros.server.addServer(spi);
|
||||
ServerProvider.addServer(spi);
|
||||
} else {
|
||||
Pros.server.updateServer(widget.spi!, spi);
|
||||
ServerProvider.updateServer(widget.spi!, spi);
|
||||
}
|
||||
|
||||
context.pop();
|
||||
@@ -589,7 +571,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
}
|
||||
}
|
||||
|
||||
void _initWithSpi(ServerPrivateInfo spi) {
|
||||
void _initWithSpi(Spi spi) {
|
||||
_nameController.text = spi.name;
|
||||
_ipController.text = spi.ip;
|
||||
_portController.text = spi.port.toString();
|
||||
@@ -597,7 +579,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
if (spi.keyId == null) {
|
||||
_passwordController.text = spi.pwd ?? '';
|
||||
} else {
|
||||
_keyIdx.value = Pros.key.pkis.indexWhere(
|
||||
_keyIdx.value = PrivateKeyProvider.pkis.value.indexWhere(
|
||||
(e) => e.id == widget.spi!.keyId,
|
||||
);
|
||||
}
|
||||
@@ -656,7 +638,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
final code = codes?.firstOrNull?.rawValue;
|
||||
if (code == null) return;
|
||||
try {
|
||||
final spi = ServerPrivateInfo.fromJson(json.decode(code));
|
||||
final spi = Spi.fromJson(json.decode(code));
|
||||
_initWithSpi(spi);
|
||||
} catch (e, s) {
|
||||
context.showErrDialog(e, s);
|
||||
@@ -680,7 +662,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
actions: Btn.ok(
|
||||
onTap: () async {
|
||||
context.pop();
|
||||
Pros.server.delServer(widget.spi!.id);
|
||||
ServerProvider.delServer(widget.spi!.id);
|
||||
context.pop(true);
|
||||
},
|
||||
red: true,
|
||||
|
||||
@@ -4,12 +4,10 @@ import 'dart:math' as math;
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/extension/ssh_client.dart';
|
||||
import 'package:server_box/data/model/app/shell_func.dart';
|
||||
import 'package:server_box/data/model/server/try_limiter.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:server_box/view/widget/percent_circle.dart';
|
||||
|
||||
@@ -86,7 +84,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
|
||||
Widget _buildPortrait() {
|
||||
return Scaffold(
|
||||
appBar: _buildTagsSwitcher(Pros.server),
|
||||
appBar: _buildTagsSwitcher(),
|
||||
body: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => _autoHideKey.currentState?.show(),
|
||||
@@ -138,74 +136,74 @@ class _ServerPageState extends State<ServerPage>
|
||||
}
|
||||
|
||||
Widget _buildLandscapeBody() {
|
||||
return Consumer<ServerProvider>(builder: (_, pro, __) {
|
||||
if (pro.serverOrder.isEmpty) {
|
||||
return ServerProvider.serverOrder.listenVal((order) {
|
||||
if (order.isEmpty) {
|
||||
return Center(
|
||||
child: Text(libL10n.empty, textAlign: TextAlign.center),
|
||||
);
|
||||
}
|
||||
|
||||
return PageView.builder(
|
||||
itemCount: pro.serverOrder.length,
|
||||
itemCount: order.length,
|
||||
itemBuilder: (_, idx) {
|
||||
final id = pro.serverOrder[idx];
|
||||
final srv = pro.pick(id: id);
|
||||
final id = order[idx];
|
||||
final srv = ServerProvider.pick(id: id);
|
||||
if (srv == null) return UIs.placeholder;
|
||||
|
||||
final title = _buildServerCardTitle(srv);
|
||||
final List<Widget> children = [
|
||||
title,
|
||||
..._buildNormalCard(srv.status, srv.spi).joinWith(SizedBox(
|
||||
height: _media.size.height / 10,
|
||||
))
|
||||
];
|
||||
return srv.listenVal((srv) {
|
||||
final title = _buildServerCardTitle(srv);
|
||||
final List<Widget> children = [
|
||||
title,
|
||||
..._buildNormalCard(srv.status, srv.spi).joinWith(SizedBox(
|
||||
height: _media.size.height / 10,
|
||||
))
|
||||
];
|
||||
|
||||
return Padding(
|
||||
padding: _media.padding,
|
||||
child: ListenableBuilder(
|
||||
listenable: _getCardNoti(id),
|
||||
builder: (_, __) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: children,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
return Padding(
|
||||
padding: _media.padding,
|
||||
child: ListenableBuilder(
|
||||
listenable: _getCardNoti(id),
|
||||
builder: (_, __) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: children,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
final child = Consumer<ServerProvider>(
|
||||
builder: (_, pro, __) {
|
||||
if (!pro.tags.value.contains(_tag)) {
|
||||
return ServerProvider.serverOrder.listenVal(
|
||||
(order) {
|
||||
if (!ServerProvider.tags.value.contains(_tag)) {
|
||||
_tag = null;
|
||||
}
|
||||
if (pro.serverOrder.isEmpty) {
|
||||
if (order.isEmpty) {
|
||||
return Center(
|
||||
child: Text(libL10n.empty, textAlign: TextAlign.center),
|
||||
);
|
||||
}
|
||||
|
||||
final filtered = _filterServers(pro);
|
||||
final filtered = _filterServers(order);
|
||||
if (_useDoubleColumn &&
|
||||
Stores.setting.doubleColumnServersPage.fetch()) {
|
||||
return _buildBodyMedium(pro: pro, filtered: filtered);
|
||||
return _buildBodyMedium(filtered);
|
||||
}
|
||||
return _buildBodySmall(pro: pro, filtered: filtered);
|
||||
return _buildBodySmall(filtered: filtered);
|
||||
},
|
||||
);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
TagSwitcher _buildTagsSwitcher(ServerProvider provider) {
|
||||
TagSwitcher _buildTagsSwitcher() {
|
||||
return TagSwitcher(
|
||||
tags: provider.tags,
|
||||
tags: ServerProvider.tags,
|
||||
width: _media.size.width,
|
||||
onTagChanged: (p0) => setState(() {
|
||||
_tag = p0;
|
||||
@@ -215,7 +213,6 @@ class _ServerPageState extends State<ServerPage>
|
||||
}
|
||||
|
||||
Widget _buildBodySmall({
|
||||
required ServerProvider pro,
|
||||
required List<String> filtered,
|
||||
EdgeInsets? padding = const EdgeInsets.fromLTRB(7, 0, 7, 7),
|
||||
}) {
|
||||
@@ -227,15 +224,14 @@ class _ServerPageState extends State<ServerPage>
|
||||
itemBuilder: (_, index) {
|
||||
// Issue #130
|
||||
if (index == count - 1) return UIs.height77;
|
||||
return _buildEachServerCard(pro.pick(id: filtered[index]));
|
||||
final vnode = ServerProvider.pick(id: filtered[index]);
|
||||
if (vnode == null) return UIs.placeholder;
|
||||
return vnode.listenVal(_buildEachServerCard);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBodyMedium({
|
||||
required ServerProvider pro,
|
||||
required List<String> filtered,
|
||||
}) {
|
||||
Widget _buildBodyMedium(List<String> filtered) {
|
||||
final mid = (filtered.length / 2).ceil();
|
||||
final filteredLeft = filtered.sublist(0, mid);
|
||||
final filteredRight = filtered.sublist(mid);
|
||||
@@ -243,14 +239,12 @@ class _ServerPageState extends State<ServerPage>
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildBodySmall(
|
||||
pro: pro,
|
||||
filtered: filteredLeft,
|
||||
padding: const EdgeInsets.only(left: 7),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _buildBodySmall(
|
||||
pro: pro,
|
||||
filtered: filteredRight,
|
||||
padding: const EdgeInsets.only(right: 7),
|
||||
),
|
||||
@@ -416,7 +410,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
];
|
||||
}
|
||||
|
||||
List<Widget> _buildNormalCard(ServerStatus ss, ServerPrivateInfo spi) {
|
||||
List<Widget> _buildNormalCard(ServerStatus ss, Spi spi) {
|
||||
return [
|
||||
UIs.height13,
|
||||
Row(
|
||||
@@ -491,7 +485,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
),
|
||||
() {
|
||||
TryLimiter.reset(s.spi.id);
|
||||
Pros.server.refresh(spi: s.spi);
|
||||
ServerProvider.refresh(spi: s.spi);
|
||||
},
|
||||
),
|
||||
ServerConn.disconnected => (
|
||||
@@ -500,7 +494,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
size: 19,
|
||||
color: Colors.grey,
|
||||
),
|
||||
() => Pros.server.refresh(spi: s.spi)
|
||||
() => ServerProvider.refresh(spi: s.spi)
|
||||
),
|
||||
ServerConn.finished => (
|
||||
const Icon(
|
||||
@@ -508,7 +502,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
size: 17,
|
||||
color: Colors.grey,
|
||||
),
|
||||
() => Pros.server.closeServer(id: s.spi.id),
|
||||
() => ServerProvider.closeServer(id: s.spi.id),
|
||||
),
|
||||
_ when Stores.setting.serverTabUseOldUI.fetch() => (
|
||||
ServerFuncBtnsTopRight(spi: s.spi),
|
||||
@@ -653,14 +647,14 @@ ${ss.err?.message ?? 'null'}
|
||||
|
||||
@override
|
||||
Future<void> afterFirstLayout(BuildContext context) async {
|
||||
await Pros.server.load();
|
||||
Pros.server.startAutoRefresh();
|
||||
ServerProvider.refresh();
|
||||
ServerProvider.startAutoRefresh();
|
||||
}
|
||||
|
||||
List<String> _filterServers(ServerProvider pro) => pro.serverOrder
|
||||
.where((e) => pro.serverOrder.contains(e))
|
||||
List<String> _filterServers(List<String> order) => order
|
||||
.where((e) =>
|
||||
_tag == null || (pro.pick(id: e)?.spi.tags?.contains(_tag) ?? false))
|
||||
_tag == null ||
|
||||
(ServerProvider.pick(id: e)?.value.spi.tags?.contains(_tag) ?? false))
|
||||
.toList();
|
||||
|
||||
static const _kCardHeightMin = 23.0;
|
||||
@@ -747,7 +741,7 @@ class _CardStatus {
|
||||
}
|
||||
|
||||
extension _ServerX on Server {
|
||||
String? getTopRightStr(ServerPrivateInfo spi) {
|
||||
String? getTopRightStr(Spi spi) {
|
||||
switch (conn) {
|
||||
case ServerConn.disconnected:
|
||||
return null;
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:ui';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/provider/server.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
class ServerOrderPage extends StatefulWidget {
|
||||
@@ -45,24 +45,28 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
if (Pros.server.serverOrder.isEmpty) {
|
||||
return Center(child: Text(libL10n.empty));
|
||||
}
|
||||
return ReorderableListView.builder(
|
||||
footer: const SizedBox(height: 77),
|
||||
onReorder: (oldIndex, newIndex) => setState(() {
|
||||
Pros.server.serverOrder.move(
|
||||
oldIndex,
|
||||
newIndex,
|
||||
property: Stores.setting.serverOrder,
|
||||
);
|
||||
}),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
|
||||
buildDefaultDragHandles: false,
|
||||
itemBuilder: (_, idx) => _buildItem(idx),
|
||||
itemCount: Pros.server.serverOrder.length,
|
||||
proxyDecorator: _proxyDecorator,
|
||||
);
|
||||
final orderNode = ServerProvider.serverOrder;
|
||||
return orderNode.listenVal((order) {
|
||||
if (order.isEmpty) {
|
||||
return Center(child: Text(libL10n.empty));
|
||||
}
|
||||
return ReorderableListView.builder(
|
||||
footer: const SizedBox(height: 77),
|
||||
onReorder: (oldIndex, newIndex) => setState(() {
|
||||
orderNode.value.move(
|
||||
oldIndex,
|
||||
newIndex,
|
||||
property: Stores.setting.serverOrder,
|
||||
);
|
||||
orderNode.notify();
|
||||
}),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
|
||||
buildDefaultDragHandles: false,
|
||||
itemBuilder: (_, idx) => _buildItem(idx),
|
||||
itemCount: order.length,
|
||||
proxyDecorator: _proxyDecorator,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildItem(int index) {
|
||||
@@ -74,8 +78,8 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
|
||||
}
|
||||
|
||||
Widget _buildCardTile(int index) {
|
||||
final id = Pros.server.serverOrder[index];
|
||||
final spi = Pros.server.pick(id: id)?.spi;
|
||||
final id = ServerProvider.serverOrder.value[index];
|
||||
final spi = ServerProvider.pick(id: id)?.value.spi;
|
||||
if (spi == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/server/snippet.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/provider/server.dart';
|
||||
import 'package:server_box/data/provider/snippet.dart';
|
||||
|
||||
class SnippetEditPage extends StatefulWidget {
|
||||
const SnippetEditPage({super.key, this.snippet});
|
||||
@@ -55,7 +56,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
)),
|
||||
actions: Btn.ok(
|
||||
onTap: () {
|
||||
Pros.snippet.del(widget.snippet!);
|
||||
SnippetProvider.del(widget.snippet!);
|
||||
context.pop();
|
||||
context.pop();
|
||||
},
|
||||
@@ -89,9 +90,9 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
autoRunOn: _autoRunOn.value.isEmpty ? null : _autoRunOn.value,
|
||||
);
|
||||
if (widget.snippet != null) {
|
||||
Pros.snippet.update(widget.snippet!, snippet);
|
||||
SnippetProvider.update(widget.snippet!, snippet);
|
||||
} else {
|
||||
Pros.snippet.add(snippet);
|
||||
SnippetProvider.add(snippet);
|
||||
}
|
||||
context.pop();
|
||||
},
|
||||
@@ -120,7 +121,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
icon: Icons.note,
|
||||
suggestion: true,
|
||||
),
|
||||
TagTile(tags: _tags, allTags: Pros.snippet.tags.value).cardx,
|
||||
TagTile(tags: _tags, allTags: SnippetProvider.tags.value).cardx,
|
||||
Input(
|
||||
controller: _scriptController,
|
||||
node: _scriptNode,
|
||||
@@ -145,7 +146,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
final subtitle = vals.isEmpty
|
||||
? null
|
||||
: vals
|
||||
.map((e) => Pros.server.pick(id: e)?.spi.name ?? e)
|
||||
.map((e) => ServerProvider.pick(id: e)?.value.spi.name ?? e)
|
||||
.join(', ');
|
||||
return ListTile(
|
||||
leading: const Padding(
|
||||
@@ -163,11 +164,12 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onTap: () async {
|
||||
vals.removeWhere((e) => !Pros.server.serverOrder.contains(e));
|
||||
vals.removeWhere(
|
||||
(e) => !ServerProvider.serverOrder.value.contains(e));
|
||||
final serverIds = await context.showPickDialog(
|
||||
title: l10n.autoRun,
|
||||
items: Pros.server.serverOrder,
|
||||
name: (e) => Pros.server.pick(id: e)?.spi.name ?? e,
|
||||
items: ServerProvider.serverOrder.value,
|
||||
name: (e) => ServerProvider.pick(id: e)?.value.spi.name ?? e,
|
||||
initial: vals,
|
||||
clearable: true,
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
import 'package:server_box/data/model/server/snippet.dart';
|
||||
@@ -38,13 +37,13 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return Consumer<SnippetProvider>(
|
||||
builder: (_, provider, __) {
|
||||
if (provider.snippets.isEmpty) {
|
||||
return SnippetProvider.snippets.listenVal(
|
||||
(snippets) {
|
||||
if (snippets.isEmpty) {
|
||||
return Center(child: Text(libL10n.empty));
|
||||
}
|
||||
|
||||
final filtered = provider.snippets
|
||||
final filtered = snippets
|
||||
.where((e) => _tag == null || (e.tags?.contains(_tag) ?? false))
|
||||
.toList();
|
||||
|
||||
@@ -52,7 +51,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 11),
|
||||
itemCount: filtered.length,
|
||||
onReorder: (oldIdx, newIdx) => setState(() {
|
||||
provider.snippets.moveByItem(
|
||||
snippets.moveByItem(
|
||||
oldIdx,
|
||||
newIdx,
|
||||
filtered: filtered,
|
||||
@@ -62,7 +61,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
);
|
||||
}),
|
||||
header: TagSwitcher(
|
||||
tags: provider.tags,
|
||||
tags: SnippetProvider.tags,
|
||||
onTagChanged: (tag) => setState(() => _tag = tag),
|
||||
initTag: _tag,
|
||||
width: _media.size.width,
|
||||
|
||||
@@ -11,8 +11,8 @@ import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/utils/ssh_auth.dart';
|
||||
import 'package:server_box/core/utils/server.dart';
|
||||
import 'package:server_box/data/model/server/snippet.dart';
|
||||
import 'package:server_box/data/provider/snippet.dart';
|
||||
import 'package:server_box/data/provider/virtual_keyboard.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
import 'package:xterm/core.dart';
|
||||
@@ -26,7 +26,7 @@ import 'package:server_box/data/res/terminal.dart';
|
||||
const _echoPWD = 'echo \$PWD';
|
||||
|
||||
class SSHPage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
final Spi spi;
|
||||
final String? initCmd;
|
||||
final Snippet? initSnippet;
|
||||
final bool notFromTab;
|
||||
@@ -68,7 +68,7 @@ class SSHPageState extends State<SSHPage>
|
||||
|
||||
bool _isDark = false;
|
||||
Timer? _virtKeyLongPressTimer;
|
||||
late SSHClient? _client = widget.spi.server?.client;
|
||||
late SSHClient? _client = widget.spi.server?.value.client;
|
||||
Timer? _discontinuityTimer;
|
||||
|
||||
@override
|
||||
@@ -298,10 +298,10 @@ class SSHPageState extends State<SSHPage>
|
||||
case VirtualKeyFunc.snippet:
|
||||
final snippets = await context.showPickWithTagDialog<Snippet>(
|
||||
title: l10n.snippet,
|
||||
tags: Pros.snippet.tags,
|
||||
tags: SnippetProvider.tags,
|
||||
itemsBuilder: (e) {
|
||||
if (e == null) return Pros.snippet.snippets;
|
||||
return Pros.snippet.snippets
|
||||
if (e == null) return SnippetProvider.snippets.value;
|
||||
return SnippetProvider.snippets.value
|
||||
.where((element) => element.tags?.contains(e) ?? false)
|
||||
.toList();
|
||||
},
|
||||
@@ -417,7 +417,7 @@ class SSHPageState extends State<SSHPage>
|
||||
|
||||
_initService();
|
||||
|
||||
for (final snippet in Pros.snippet.snippets) {
|
||||
for (final snippet in SnippetProvider.snippets.value) {
|
||||
if (snippet.autoRunOn?.contains(widget.spi.id) == true) {
|
||||
snippet.runInTerm(_terminal, widget.spi);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,10 @@ import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/route.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/res/provider.dart';
|
||||
import 'package:server_box/view/page/ssh/page.dart';
|
||||
|
||||
class SSHTabPage extends StatefulWidget {
|
||||
@@ -86,8 +84,8 @@ class _SSHTabPageState extends State<SSHTabPage>
|
||||
Widget _buildAddPage() {
|
||||
return Center(
|
||||
key: const Key('sshTabAddServer'),
|
||||
child: Consumer<ServerProvider>(builder: (_, pro, __) {
|
||||
if (pro.serverOrder.isEmpty) {
|
||||
child: ServerProvider.serverOrder.listenVal((order) {
|
||||
if (order.isEmpty) {
|
||||
return Center(
|
||||
child: Text(libL10n.empty, textAlign: TextAlign.center),
|
||||
);
|
||||
@@ -98,7 +96,7 @@ class _SSHTabPageState extends State<SSHTabPage>
|
||||
padding: const EdgeInsets.all(7),
|
||||
cacheExtent: 50,
|
||||
itemBuilder: (context, idx) {
|
||||
final spi = Pros.server.pick(id: pro.serverOrder[idx])?.spi;
|
||||
final spi = ServerProvider.pick(id: order[idx])?.value.spi;
|
||||
if (spi == null) return UIs.placeholder;
|
||||
return CardX(
|
||||
child: InkWell(
|
||||
@@ -117,7 +115,7 @@ class _SSHTabPageState extends State<SSHTabPage>
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: pro.servers.length,
|
||||
itemCount: ServerProvider.servers.length,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
childAspectRatio: 3 * (ratio / (9 / 16)),
|
||||
@@ -147,7 +145,7 @@ class _SSHTabPageState extends State<SSHTabPage>
|
||||
);
|
||||
}
|
||||
|
||||
void _onTapInitCard(ServerPrivateInfo spi) async {
|
||||
void _onTapInitCard(Spi spi) async {
|
||||
final name = () {
|
||||
final reg = RegExp('${spi.name}\\((\\d+)\\)');
|
||||
final idxs = _tabMap.keys
|
||||
|
||||
@@ -5,8 +5,9 @@ import 'package:flutter/material.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/model/sftp/worker.dart';
|
||||
import 'package:server_box/data/provider/server.dart';
|
||||
import 'package:server_box/data/provider/sftp.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/view/widget/omit_start_text.dart';
|
||||
|
||||
import 'package:server_box/core/route.dart';
|
||||
@@ -282,10 +283,10 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
||||
onTap: () async {
|
||||
context.pop();
|
||||
|
||||
final spi = await context.showPickSingleDialog<ServerPrivateInfo>(
|
||||
final spi = await context.showPickSingleDialog<Spi>(
|
||||
title: libL10n.select,
|
||||
items: Pros.server.serverOrder
|
||||
.map((e) => Pros.server.pick(id: e)?.spi)
|
||||
items: ServerProvider.serverOrder.value
|
||||
.map((e) => ServerProvider.pick(id: e)?.value.spi)
|
||||
.toList(),
|
||||
name: (e) => e.name,
|
||||
);
|
||||
@@ -299,7 +300,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
||||
return;
|
||||
}
|
||||
|
||||
Pros.sftp.add(SftpReq(
|
||||
SftpProvider.add(SftpReq(
|
||||
spi,
|
||||
'$remotePath/$fileName',
|
||||
file.absolute.path,
|
||||
|
||||
@@ -11,8 +11,8 @@ 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/sftp.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:server_box/view/widget/omit_start_text.dart';
|
||||
import 'package:server_box/view/widget/two_line_text.dart';
|
||||
@@ -21,7 +21,7 @@ import 'package:server_box/view/widget/unix_perm.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
|
||||
class SftpPage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
final Spi spi;
|
||||
final String? initPath;
|
||||
final bool isSelect;
|
||||
|
||||
@@ -38,7 +38,7 @@ class SftpPage extends StatefulWidget {
|
||||
|
||||
class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
late final _status = SftpBrowserStatus(_client);
|
||||
late final _client = widget.spi.server!.client!;
|
||||
late final _client = widget.spi.server!.value.client!;
|
||||
final _sortOption = _SortOption().vn;
|
||||
|
||||
@override
|
||||
@@ -303,7 +303,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
localPath,
|
||||
SftpReqType.download,
|
||||
);
|
||||
Pros.sftp.add(req, completer: completer);
|
||||
SftpProvider.add(req, completer: completer);
|
||||
final (suc, err) = await context.showLoadingDialog(
|
||||
fn: () => completer.future,
|
||||
);
|
||||
@@ -311,7 +311,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
|
||||
final result = await AppRoutes.editor(path: localPath).go<bool>(context);
|
||||
if (result != null && result) {
|
||||
Pros.sftp.add(SftpReq(
|
||||
SftpProvider.add(SftpReq(
|
||||
req.spi,
|
||||
remotePath,
|
||||
localPath,
|
||||
@@ -335,7 +335,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
context.pop();
|
||||
final remotePath = _getRemotePath(name);
|
||||
|
||||
Pros.sftp.add(
|
||||
SftpProvider.add(
|
||||
SftpReq(
|
||||
widget.spi,
|
||||
remotePath,
|
||||
@@ -659,12 +659,13 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
}
|
||||
|
||||
showSearch(
|
||||
context: context,
|
||||
delegate: SearchPage(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
|
||||
future: (q) => find(q).toList(),
|
||||
builder: (ctx, e) => _buildItem(e, beforeTap: () => ctx.pop()),
|
||||
));
|
||||
context: context,
|
||||
delegate: SearchPage(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
|
||||
future: (q) => find(q).toList(),
|
||||
builder: (ctx, e) => _buildItem(e, beforeTap: ctx.pop),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.search),
|
||||
);
|
||||
@@ -701,7 +702,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
final fileName = path.split(Platform.pathSeparator).lastOrNull;
|
||||
final remotePath = '$remoteDir/$fileName';
|
||||
Loggers.app.info('SFTP upload local: $path, remote: $remotePath');
|
||||
Pros.sftp.add(
|
||||
SftpProvider.add(
|
||||
SftpReq(widget.spi, remotePath, path, SftpReqType.upload),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/route.dart';
|
||||
import 'package:server_box/data/model/sftp/worker.dart';
|
||||
import 'package:server_box/data/provider/sftp.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
|
||||
class SftpMissionPage extends StatefulWidget {
|
||||
const SftpMissionPage({super.key});
|
||||
@@ -26,16 +24,15 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return Consumer<SftpProvider>(builder: (__, pro, _) {
|
||||
if (pro.status.isEmpty) {
|
||||
return SftpProvider.status.listenVal((status) {
|
||||
if (status.isEmpty) {
|
||||
return Center(child: Text(libL10n.empty));
|
||||
}
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(11),
|
||||
itemCount: pro.status.length,
|
||||
itemCount: status.length,
|
||||
itemBuilder: (context, index) {
|
||||
final status = pro.status[index];
|
||||
return _buildItem(status);
|
||||
return _buildItem(status[index]);
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -165,7 +162,7 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
||||
)),
|
||||
actions: Btn.ok(
|
||||
onTap: () {
|
||||
Pros.sftp.cancel(id);
|
||||
SftpProvider.cancel(id);
|
||||
context.pop();
|
||||
},
|
||||
).toList,
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:server_box/data/model/server/systemd.dart';
|
||||
import 'package:server_box/data/provider/systemd.dart';
|
||||
|
||||
final class SystemdPageArgs {
|
||||
final ServerPrivateInfo spi;
|
||||
final Spi spi;
|
||||
|
||||
const SystemdPageArgs({
|
||||
required this.spi,
|
||||
@@ -102,7 +102,7 @@ final class _SystemdPageState extends State<SystemdPage> {
|
||||
return PopupMenu(
|
||||
items: unit.availableFuncs.map(_buildUnitFuncBtn).toList(),
|
||||
onSelected: (val) async {
|
||||
final cmd = unit.getCmd(func: val, isRoot: _pro.isRoot);
|
||||
final cmd = unit.getCmd(func: val, isRoot: widget.args.spi.isRoot);
|
||||
final sure = await context.showRoundDialog(
|
||||
title: libL10n.attention,
|
||||
child: SimpleMarkdown(data: '```shell\n$cmd\n```'),
|
||||
|
||||
Reference in New Issue
Block a user