migrate: riverpod + freezed (#870)
This commit is contained in:
@@ -3,8 +3,10 @@ import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
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/core/extension/server.dart';
|
||||
import 'package:server_box/core/route.dart';
|
||||
import 'package:server_box/data/model/app/scripts/cmd_types.dart';
|
||||
import 'package:server_box/data/model/app/server_detail_card.dart';
|
||||
@@ -16,28 +18,28 @@ import 'package:server_box/data/model/server/disk_smart.dart';
|
||||
import 'package:server_box/data/model/server/net_speed.dart';
|
||||
import 'package:server_box/data/model/server/nvdia.dart';
|
||||
import 'package:server_box/data/model/server/sensors.dart';
|
||||
import 'package:server_box/data/model/server/server.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/res/store.dart';
|
||||
import 'package:server_box/view/page/pve.dart';
|
||||
import 'package:server_box/view/page/server/edit.dart';
|
||||
import 'package:server_box/view/page/server/logo.dart';
|
||||
import 'package:server_box/view/widget/server_func_btns.dart';
|
||||
|
||||
part 'misc.dart';
|
||||
|
||||
class ServerDetailPage extends StatefulWidget {
|
||||
class ServerDetailPage extends ConsumerStatefulWidget {
|
||||
final SpiRequiredArgs args;
|
||||
const ServerDetailPage({super.key, required this.args});
|
||||
|
||||
@override
|
||||
State<ServerDetailPage> createState() => _ServerDetailPageState();
|
||||
ConsumerState<ServerDetailPage> createState() => _ServerDetailPageState();
|
||||
|
||||
static const route = AppRouteArg(page: ServerDetailPage.new, path: '/servers/detail');
|
||||
}
|
||||
|
||||
class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerProviderStateMixin {
|
||||
class _ServerDetailPageState extends ConsumerState<ServerDetailPage> with SingleTickerProviderStateMixin {
|
||||
late final _cardBuildMap = Map.fromIterables(ServerDetailCards.names, [
|
||||
_buildAbout,
|
||||
_buildCPUView,
|
||||
@@ -84,17 +86,17 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = widget.args.spi.server;
|
||||
if (s == null) {
|
||||
final serverState = ref.watch(individualServerNotifierProvider(widget.args.spi.id));
|
||||
if (serverState.client == null) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(),
|
||||
body: Center(child: Text(libL10n.empty)),
|
||||
);
|
||||
}
|
||||
return s.listenVal(_buildMainPage);
|
||||
return _buildMainPage(serverState);
|
||||
}
|
||||
|
||||
Widget _buildMainPage(Server si) {
|
||||
Widget _buildMainPage(ServerState si) {
|
||||
final buildFuncs = !Stores.setting.moveServerFuncs.fetch();
|
||||
final logo = _buildLogo(si);
|
||||
final children = <Widget>[if (logo != null) logo, if (buildFuncs) ServerFuncBtns(spi: si.spi)];
|
||||
@@ -111,7 +113,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
CustomAppBar _buildAppBar(Server si) {
|
||||
CustomAppBar _buildAppBar(ServerState si) {
|
||||
return CustomAppBar(
|
||||
title: Text(
|
||||
si.spi.name,
|
||||
@@ -132,7 +134,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildLogo(Server si) {
|
||||
Widget? _buildLogo(ServerState si) {
|
||||
final logoUrl = si.getLogoUrl(context);
|
||||
|
||||
return Padding(
|
||||
@@ -153,7 +155,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildAbout(Server si) {
|
||||
Widget? _buildAbout(ServerState si) {
|
||||
final ss = si.status;
|
||||
return ExpandTile(
|
||||
key: ValueKey(ss.more.hashCode), // Use hashCode to avoid perf issue
|
||||
@@ -178,7 +180,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
).cardx;
|
||||
}
|
||||
|
||||
Widget? _buildCPUView(Server si) {
|
||||
Widget? _buildCPUView(ServerState si) {
|
||||
final ss = si.status;
|
||||
final percent = ss.cpu.usedPercent(coreIdx: 0).toInt();
|
||||
final details = [
|
||||
@@ -305,7 +307,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
return children;
|
||||
}
|
||||
|
||||
Widget _buildCPUChart(ServerStatus ss) {
|
||||
Widget _buildCPUChart(server_model.ServerStatus ss) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 13),
|
||||
child: LayoutBuilder(
|
||||
@@ -335,7 +337,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildMemView(Server si) {
|
||||
Widget? _buildMemView(ServerState si) {
|
||||
final ss = si.status;
|
||||
final free = ss.mem.free / ss.mem.total * 100;
|
||||
final avail = ss.mem.availPercent * 100;
|
||||
@@ -376,7 +378,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
).cardx;
|
||||
}
|
||||
|
||||
Widget? _buildSwapView(Server si) {
|
||||
Widget? _buildSwapView(ServerState si) {
|
||||
final ss = si.status;
|
||||
if (ss.swap.total == 0) return null;
|
||||
|
||||
@@ -408,7 +410,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
).cardx;
|
||||
}
|
||||
|
||||
Widget? _buildGpuView(Server si) {
|
||||
Widget? _buildGpuView(ServerState si) {
|
||||
final ss = si.status;
|
||||
final hasNvidia = ss.nvidia != null && ss.nvidia!.isNotEmpty;
|
||||
final hasAmd = ss.amd != null && ss.amd!.isNotEmpty;
|
||||
@@ -532,7 +534,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildDiskView(Server si) {
|
||||
Widget? _buildDiskView(ServerState si) {
|
||||
final ss = si.status;
|
||||
final children = <Widget>[];
|
||||
|
||||
@@ -553,7 +555,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
).cardx;
|
||||
}
|
||||
|
||||
Widget _buildDiskItemWithHierarchy(Disk disk, ServerStatus ss, int depth) {
|
||||
Widget _buildDiskItemWithHierarchy(Disk disk, server_model.ServerStatus ss, int depth) {
|
||||
// Create a list to hold this disk and its children
|
||||
final items = <Widget>[];
|
||||
|
||||
@@ -570,7 +572,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
return Column(children: items);
|
||||
}
|
||||
|
||||
Widget _buildDiskItem(Disk disk, ServerStatus ss, int depth) {
|
||||
Widget _buildDiskItem(Disk disk, server_model.ServerStatus ss, int depth) {
|
||||
final (read, write) = ss.diskIO.getSpeed(disk.path);
|
||||
final text = () {
|
||||
final use = '${l10n.used} ${disk.used.kb2Str} / ${disk.size.kb2Str}';
|
||||
@@ -625,7 +627,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildDiskSmart(Server si) {
|
||||
Widget? _buildDiskSmart(ServerState si) {
|
||||
final smarts = si.status.diskSmart;
|
||||
if (smarts.isEmpty) return null;
|
||||
return CardX(
|
||||
@@ -770,7 +772,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildNetView(Server si) {
|
||||
Widget? _buildNetView(ServerState si) {
|
||||
final ss = si.status;
|
||||
final ns = ss.netSpeed;
|
||||
final children = <Widget>[];
|
||||
@@ -847,7 +849,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildTemperature(Server si) {
|
||||
Widget? _buildTemperature(ServerState si) {
|
||||
final ss = si.status;
|
||||
if (ss.temps.isEmpty) return null;
|
||||
|
||||
@@ -879,7 +881,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildBatteries(Server si) {
|
||||
Widget? _buildBatteries(ServerState si) {
|
||||
final ss = si.status;
|
||||
if (ss.batteries.isEmpty) return null;
|
||||
|
||||
@@ -914,7 +916,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildSensors(Server si) {
|
||||
Widget? _buildSensors(ServerState si) {
|
||||
final ss = si.status;
|
||||
if (ss.sensors.isEmpty) return UIs.placeholder;
|
||||
return CardX(
|
||||
@@ -967,7 +969,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildPve(Server si) {
|
||||
Widget? _buildPve(ServerState si) {
|
||||
final addr = si.spi.custom?.pveAddr;
|
||||
if (addr == null || addr.isEmpty) return null;
|
||||
return CardX(
|
||||
@@ -980,7 +982,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
|
||||
);
|
||||
}
|
||||
|
||||
Widget? _buildCustomCmd(Server si) {
|
||||
Widget? _buildCustomCmd(ServerState si) {
|
||||
final ss = si.status;
|
||||
if (ss.customCmds.isEmpty) return null;
|
||||
return CardX(
|
||||
|
||||
@@ -3,12 +3,12 @@ import 'dart:convert';
|
||||
import 'package:choice/choice.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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/core/route.dart';
|
||||
import 'package:server_box/data/model/app/scripts/cmd_types.dart';
|
||||
import 'package:server_box/data/model/server/custom.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/system.dart';
|
||||
import 'package:server_box/data/model/server/wol_cfg.dart';
|
||||
@@ -17,7 +17,7 @@ import 'package:server_box/data/provider/server.dart';
|
||||
import 'package:server_box/data/store/server.dart';
|
||||
import 'package:server_box/view/page/private_key/edit.dart';
|
||||
|
||||
class ServerEditPage extends StatefulWidget {
|
||||
class ServerEditPage extends ConsumerStatefulWidget {
|
||||
final SpiRequiredArgs? args;
|
||||
|
||||
const ServerEditPage({super.key, this.args});
|
||||
@@ -25,10 +25,10 @@ class ServerEditPage extends StatefulWidget {
|
||||
static const route = AppRoute<bool, SpiRequiredArgs>(page: ServerEditPage.new, path: '/servers/edit');
|
||||
|
||||
@override
|
||||
State<ServerEditPage> createState() => _ServerEditPageState();
|
||||
ConsumerState<ServerEditPage> createState() => _ServerEditPageState();
|
||||
}
|
||||
|
||||
class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
class _ServerEditPageState extends ConsumerState<ServerEditPage> with AfterLayoutMixin {
|
||||
late final spi = widget.args?.spi;
|
||||
final _nameController = TextEditingController();
|
||||
final _ipController = TextEditingController();
|
||||
@@ -167,7 +167,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
hint: 'root',
|
||||
suggestion: false,
|
||||
),
|
||||
TagTile(tags: _tags, allTags: ServerProvider.tags.value).cardx,
|
||||
TagTile(tags: _tags, allTags: ref.watch(serverNotifierProvider).tags).cardx,
|
||||
ListTile(
|
||||
title: Text(l10n.autoConnect),
|
||||
trailing: _autoConnect.listenVal(
|
||||
@@ -227,12 +227,14 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
}
|
||||
|
||||
Widget _buildKeyAuth() {
|
||||
return PrivateKeyProvider.pkis.listenVal((pkis) {
|
||||
final tiles = List<Widget>.generate(pkis.length, (index) {
|
||||
final e = pkis[index];
|
||||
return ListTile(
|
||||
contentPadding: const EdgeInsets.only(left: 10, right: 15),
|
||||
leading: Radio<int>(value: index),
|
||||
final privateKeyState = ref.watch(privateKeyNotifierProvider);
|
||||
final pkis = privateKeyState.keys;
|
||||
|
||||
final tiles = List<Widget>.generate(pkis.length, (index) {
|
||||
final e = pkis[index];
|
||||
return ListTile(
|
||||
contentPadding: const EdgeInsets.only(left: 10, right: 15),
|
||||
leading: Radio<int>(value: index),
|
||||
title: Text(e.id, textAlign: TextAlign.start),
|
||||
subtitle: Text(e.type ?? l10n.unknown, textAlign: TextAlign.start, style: UIs.textGrey),
|
||||
trailing: Btn.icon(
|
||||
@@ -254,7 +256,6 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
onChanged: (val) => _keyIdx.value = val,
|
||||
child: _keyIdx.listenVal((_) => Column(children: tiles)).cardx,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildEnvs() {
|
||||
@@ -485,27 +486,26 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
|
||||
Widget _buildJumpServer() {
|
||||
const padding = EdgeInsets.only(left: 13, right: 13, bottom: 7);
|
||||
final srvs = ServerProvider.servers.values
|
||||
.map((e) => e.value)
|
||||
.where((e) => e.spi.jumpId == null)
|
||||
.where((e) => e.spi.id != spi?.id)
|
||||
final srvs = ref.watch(serverNotifierProvider).servers.values
|
||||
.where((e) => e.jumpId == null)
|
||||
.where((e) => e.id != spi?.id)
|
||||
.toList();
|
||||
final choice = _jumpServer.listenVal((val) {
|
||||
final srv = srvs.firstWhereOrNull((e) => e.id == _jumpServer.value);
|
||||
return Choice<Server>(
|
||||
return Choice<Spi>(
|
||||
multiple: false,
|
||||
clearable: true,
|
||||
value: srv != null ? [srv] : [],
|
||||
builder: (state, _) => Wrap(
|
||||
children: List<Widget>.generate(srvs.length, (index) {
|
||||
final item = srvs[index];
|
||||
return ChoiceChipX<Server>(
|
||||
label: item.spi.name,
|
||||
return ChoiceChipX<Spi>(
|
||||
label: item.name,
|
||||
state: state,
|
||||
value: item,
|
||||
onSelected: (srv, on) {
|
||||
if (on) {
|
||||
_jumpServer.value = srv.spi.id;
|
||||
_jumpServer.value = srv.id;
|
||||
} else {
|
||||
_jumpServer.value = null;
|
||||
}
|
||||
@@ -569,7 +569,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
actions: Btn.ok(
|
||||
onTap: () async {
|
||||
context.pop();
|
||||
ServerProvider.delServer(spi!.id);
|
||||
ref.read(serverNotifierProvider.notifier).delServer(spi!.id);
|
||||
context.pop(true);
|
||||
},
|
||||
red: true,
|
||||
@@ -705,7 +705,7 @@ extension on _ServerEditPageState {
|
||||
port: int.parse(_portController.text),
|
||||
user: _usernameController.text,
|
||||
pwd: _passwordController.text.selfNotEmptyOrNull,
|
||||
keyId: _keyIdx.value != null ? PrivateKeyProvider.pkis.value.elementAt(_keyIdx.value!).id : null,
|
||||
keyId: _keyIdx.value != null ? ref.read(privateKeyNotifierProvider).keys.elementAt(_keyIdx.value!).id : null,
|
||||
tags: _tags.value.isEmpty ? null : _tags.value.toList(),
|
||||
alterUrl: _altUrlController.text.selfNotEmptyOrNull,
|
||||
autoConnect: _autoConnect.value,
|
||||
@@ -724,9 +724,9 @@ extension on _ServerEditPageState {
|
||||
context.showSnackBar('${l10n.sameIdServerExist}: ${spi.id}');
|
||||
return;
|
||||
}
|
||||
ServerProvider.addServer(spi);
|
||||
ref.read(serverNotifierProvider.notifier).addServer(spi);
|
||||
} else {
|
||||
ServerProvider.updateServer(this.spi!, spi);
|
||||
ref.read(serverNotifierProvider.notifier).updateServer(this.spi!, spi);
|
||||
}
|
||||
|
||||
context.pop();
|
||||
@@ -740,7 +740,7 @@ extension on _ServerEditPageState {
|
||||
if (spi.keyId == null) {
|
||||
_passwordController.text = spi.pwd ?? '';
|
||||
} else {
|
||||
_keyIdx.value = PrivateKeyProvider.pkis.value.indexWhere((e) => e.id == spi.keyId);
|
||||
_keyIdx.value = ref.read(privateKeyNotifierProvider).keys.indexWhere((e) => e.id == spi.keyId);
|
||||
}
|
||||
|
||||
/// List in dart is passed by pointer, so you need to copy it here
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
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/model/server/server.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
extension LogoExt on Server {
|
||||
String? getLogoUrl(BuildContext context) {
|
||||
var logoUrl = spi.custom?.logoUrl ?? Stores.setting.serverLogoUrl.fetch().selfNotEmptyOrNull;
|
||||
if (logoUrl == null) {
|
||||
return null;
|
||||
}
|
||||
final dist = status.more[StatusCmdType.sys]?.dist;
|
||||
if (dist != null) {
|
||||
logoUrl = logoUrl.replaceFirst('{DIST}', dist.name);
|
||||
}
|
||||
logoUrl = logoUrl.replaceFirst('{BRIGHT}', context.isDark ? 'dark' : 'light');
|
||||
return logoUrl;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
part of 'tab.dart';
|
||||
|
||||
extension on _ServerPageState {
|
||||
Widget _buildServerCardTitle(Server s) {
|
||||
Widget _buildServerCardTitle(ServerState s) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 7, right: 13),
|
||||
child: Row(
|
||||
@@ -17,12 +17,12 @@ extension on _ServerPageState {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTopRightWidget(Server s) {
|
||||
Widget _buildTopRightWidget(ServerState s) {
|
||||
final (child, onTap) = switch (s.conn) {
|
||||
ServerConn.connecting || ServerConn.loading || ServerConn.connected => (
|
||||
SizedBox.square(
|
||||
dimension: _ServerPageState._kCardHeightMin,
|
||||
child: SizedLoading(_ServerPageState._kCardHeightMin, strokeWidth: 3, padding: 3),
|
||||
child: SizedLoading(_ServerPageState._kCardHeightMin, padding: 3),
|
||||
),
|
||||
null,
|
||||
),
|
||||
@@ -30,16 +30,16 @@ extension on _ServerPageState {
|
||||
const Icon(Icons.refresh, size: 21, color: Colors.grey),
|
||||
() {
|
||||
TryLimiter.reset(s.spi.id);
|
||||
ServerProvider.refresh(spi: s.spi);
|
||||
ref.read(serverNotifierProvider.notifier).refresh(spi: s.spi);
|
||||
},
|
||||
),
|
||||
ServerConn.disconnected => (
|
||||
const Icon(MingCute.link_3_line, size: 19, color: Colors.grey),
|
||||
() => ServerProvider.refresh(spi: s.spi),
|
||||
() => ref.read(serverNotifierProvider.notifier).refresh(spi: s.spi),
|
||||
),
|
||||
ServerConn.finished => (
|
||||
const Icon(MingCute.unlink_2_line, size: 17, color: Colors.grey),
|
||||
() => ServerProvider.closeServer(id: s.spi.id),
|
||||
() => ref.read(serverNotifierProvider.notifier).closeServer(id: s.spi.id),
|
||||
),
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ extension on _ServerPageState {
|
||||
return InkWell(borderRadius: BorderRadius.circular(7), onTap: onTap, child: wrapped).paddingOnly(left: 5);
|
||||
}
|
||||
|
||||
Widget _buildTopRightText(Server s) {
|
||||
Widget _buildTopRightText(ServerState s) {
|
||||
final hasErr = s.status.err != null;
|
||||
final str = s._getTopRightStr(s.spi);
|
||||
if (str == null) return UIs.placeholder;
|
||||
@@ -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 = ServerProvider.pick(id: id)?.value.spi.custom?.netDev;
|
||||
final device = ref.watch(serverNotifierProvider).servers[id]?.custom?.netDev;
|
||||
final (a, b) = type.build(ss, dev: device);
|
||||
return AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 377),
|
||||
|
||||
@@ -26,33 +26,31 @@ extension on _ServerPageState {
|
||||
}
|
||||
|
||||
Widget _buildLandscapeBody() {
|
||||
return ServerProvider.serverOrder.listenVal((order) {
|
||||
if (order.isEmpty) {
|
||||
return Center(child: Text(libL10n.empty, textAlign: TextAlign.center));
|
||||
}
|
||||
final serverState = ref.watch(serverNotifierProvider);
|
||||
final order = serverState.serverOrder;
|
||||
|
||||
if (order.isEmpty) {
|
||||
return Center(child: Text(libL10n.empty, textAlign: TextAlign.center));
|
||||
}
|
||||
|
||||
return PageView.builder(
|
||||
itemCount: order.length,
|
||||
itemBuilder: (_, idx) {
|
||||
final id = order[idx];
|
||||
final srv = ServerProvider.pick(id: id);
|
||||
if (srv == null) return UIs.placeholder;
|
||||
return PageView.builder(
|
||||
itemCount: order.length,
|
||||
itemBuilder: (_, idx) {
|
||||
final id = order[idx];
|
||||
final srv = ref.watch(individualServerNotifierProvider(id));
|
||||
|
||||
return srv.listenVal((srv) {
|
||||
final title = _buildServerCardTitle(srv);
|
||||
final List<Widget> children = [title, _buildNormalCard(srv.status, srv.spi)];
|
||||
final title = _buildServerCardTitle(srv);
|
||||
final List<Widget> children = [title, _buildNormalCard(srv.status, srv.spi)];
|
||||
|
||||
return _getCardNoti(id).listenVal((_) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: children,
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
return _getCardNoti(id).listenVal((_) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: children,
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'dart:math' as math;
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
import 'package:responsive_framework/responsive_framework.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
@@ -31,11 +32,11 @@ part 'landscape.dart';
|
||||
part 'top_bar.dart';
|
||||
part 'utils.dart';
|
||||
|
||||
class ServerPage extends StatefulWidget {
|
||||
class ServerPage extends ConsumerStatefulWidget {
|
||||
const ServerPage({super.key});
|
||||
|
||||
@override
|
||||
State<ServerPage> createState() => _ServerPageState();
|
||||
ConsumerState<ServerPage> createState() => _ServerPageState();
|
||||
|
||||
static const route = AppRouteNoArg(page: ServerPage.new, path: '/servers');
|
||||
}
|
||||
@@ -43,12 +44,14 @@ class ServerPage extends StatefulWidget {
|
||||
const _cardPad = 74.0;
|
||||
const _cardPadSingle = 13.0;
|
||||
|
||||
class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
|
||||
class _ServerPageState extends ConsumerState<ServerPage>
|
||||
with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
|
||||
late double _textFactorDouble;
|
||||
double _offset = 1;
|
||||
late TextScaler _textFactor;
|
||||
|
||||
final _cardsStatus = <String, _CardNotifier>{};
|
||||
late final ValueNotifier<Set<String>> _tags;
|
||||
|
||||
Timer? _timer;
|
||||
|
||||
@@ -64,11 +67,13 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
_scrollController.dispose();
|
||||
_autoHideCtrl.dispose();
|
||||
_tag.dispose();
|
||||
_tags.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tags = ValueNotifier(ref.read(serverNotifierProvider).tags);
|
||||
_startAvoidJitterTimer();
|
||||
}
|
||||
|
||||
@@ -78,9 +83,14 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
_updateOffset();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
// Listen to provider changes and update the ValueNotifier
|
||||
ref.listen(serverNotifierProvider, (previous, next) {
|
||||
_tags.value = next.tags;
|
||||
});
|
||||
return OrientationBuilder(
|
||||
builder: (_, orientation) {
|
||||
if (orientation == Orientation.landscape) {
|
||||
@@ -96,7 +106,7 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
|
||||
Widget _buildScaffold(Widget child) {
|
||||
return Scaffold(
|
||||
appBar: _TopBar(tags: ServerProvider.tags, onTagChanged: (p0) => _tag.value = p0, initTag: _tag.value),
|
||||
appBar: _TopBar(tags: _tags, onTagChanged: (p0) => _tag.value = p0, initTag: _tag.value),
|
||||
body: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: _autoHideCtrl.show,
|
||||
@@ -122,22 +132,21 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
|
||||
Widget _buildPortrait() {
|
||||
// final isMobile = ResponsiveBreakpoints.of(context).isMobile;
|
||||
return ServerProvider.serverOrder.listenVal((order) {
|
||||
return _tag.listenVal((val) {
|
||||
final filtered = _filterServers(order);
|
||||
final child = _buildScaffold(_buildBodySmall(filtered: filtered));
|
||||
// if (isMobile) {
|
||||
return child;
|
||||
// }
|
||||
final serverState = ref.watch(serverNotifierProvider);
|
||||
return _tag.listenVal((val) {
|
||||
final filtered = _filterServers(serverState.serverOrder);
|
||||
final child = _buildScaffold(_buildBodySmall(filtered: filtered));
|
||||
// if (isMobile) {
|
||||
return child;
|
||||
// }
|
||||
|
||||
// return SplitView(
|
||||
// controller: _splitViewCtrl,
|
||||
// leftWeight: 1,
|
||||
// rightWeight: 1.3,
|
||||
// initialRight: Center(child: CircularProgressIndicator()),
|
||||
// leftBuilder: (_, __) => child,
|
||||
// );
|
||||
});
|
||||
// return SplitView(
|
||||
// controller: _splitViewCtrl,
|
||||
// leftWeight: 1,
|
||||
// rightWeight: 1.3,
|
||||
// initialRight: Center(child: CircularProgressIndicator()),
|
||||
// leftBuilder: (_, __) => child,
|
||||
// );
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,10 +182,9 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
// Last item is just spacing
|
||||
if (index == lens) return SizedBox(height: 77);
|
||||
|
||||
final vnode = ServerProvider.pick(id: serversInThisColumn[index]);
|
||||
if (vnode == null) return UIs.placeholder;
|
||||
final individualState = ref.watch(individualServerNotifierProvider(serversInThisColumn[index]));
|
||||
|
||||
return vnode.listenVal(_buildEachServerCard);
|
||||
return _buildEachServerCard(individualState);
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -186,9 +194,7 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildEachServerCard(Server? srv) {
|
||||
if (srv == null) return UIs.placeholder;
|
||||
|
||||
Widget _buildEachServerCard(ServerState srv) {
|
||||
return CardX(
|
||||
key: Key(srv.spi.id + _tag.value),
|
||||
child: InkWell(
|
||||
@@ -218,7 +224,7 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRealServerCard(Server srv) {
|
||||
Widget _buildRealServerCard(ServerState srv) {
|
||||
final id = srv.spi.id;
|
||||
final cardStatus = _getCardNoti(id);
|
||||
final title = _buildServerCardTitle(srv);
|
||||
@@ -255,7 +261,7 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildFlippedCard(Server srv) {
|
||||
Widget _buildFlippedCard(ServerState srv) {
|
||||
const color = Colors.grey;
|
||||
const textStyle = TextStyle(fontSize: 13, color: color);
|
||||
final children = [
|
||||
@@ -332,8 +338,8 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
|
||||
|
||||
@override
|
||||
Future<void> afterFirstLayout(BuildContext context) async {
|
||||
ServerProvider.refresh();
|
||||
ServerProvider.startAutoRefresh();
|
||||
ref.read(serverNotifierProvider.notifier).refresh();
|
||||
ref.read(serverNotifierProvider.notifier).startAutoRefresh();
|
||||
}
|
||||
|
||||
static const _kCardHeightMin = 23.0;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
part of 'tab.dart';
|
||||
|
||||
extension _Actions on _ServerPageState {
|
||||
void _onTapCard(Server srv) {
|
||||
void _onTapCard(ServerState srv) {
|
||||
if (srv.canViewDetails) {
|
||||
// _splitViewCtrl.replace(ServerDetailPage(
|
||||
// key: ValueKey(srv.spi.id),
|
||||
@@ -19,7 +19,7 @@ extension _Actions on _ServerPageState {
|
||||
}
|
||||
}
|
||||
|
||||
void _onLongPressCard(Server srv) {
|
||||
void _onLongPressCard(ServerState srv) {
|
||||
if (srv.conn == ServerConn.finished) {
|
||||
final id = srv.spi.id;
|
||||
final cardStatus = _getCardNoti(id);
|
||||
@@ -42,7 +42,7 @@ extension _Actions on _ServerPageState {
|
||||
}
|
||||
|
||||
extension _Operation on _ServerPageState {
|
||||
void _onTapSuspend(Server srv) {
|
||||
void _onTapSuspend(ServerState srv) {
|
||||
_askFor(
|
||||
func: () async {
|
||||
if (Stores.setting.showSuspendTip.fetch()) {
|
||||
@@ -50,7 +50,7 @@ extension _Operation on _ServerPageState {
|
||||
Stores.setting.showSuspendTip.put(false);
|
||||
}
|
||||
srv.client?.execWithPwd(
|
||||
ShellFunc.suspend.exec(srv.spi.id, systemType: srv.status.system),
|
||||
ShellFunc.suspend.exec(srv.spi.id, systemType: srv.status.system, customDir: null),
|
||||
context: context,
|
||||
id: srv.id,
|
||||
);
|
||||
@@ -60,10 +60,10 @@ extension _Operation on _ServerPageState {
|
||||
);
|
||||
}
|
||||
|
||||
void _onTapShutdown(Server srv) {
|
||||
void _onTapShutdown(ServerState srv) {
|
||||
_askFor(
|
||||
func: () => srv.client?.execWithPwd(
|
||||
ShellFunc.shutdown.exec(srv.spi.id, systemType: srv.status.system),
|
||||
ShellFunc.shutdown.exec(srv.spi.id, systemType: srv.status.system, customDir: null),
|
||||
context: context,
|
||||
id: srv.id,
|
||||
),
|
||||
@@ -72,10 +72,10 @@ extension _Operation on _ServerPageState {
|
||||
);
|
||||
}
|
||||
|
||||
void _onTapReboot(Server srv) {
|
||||
void _onTapReboot(ServerState srv) {
|
||||
_askFor(
|
||||
func: () => srv.client?.execWithPwd(
|
||||
ShellFunc.reboot.exec(srv.spi.id, systemType: srv.status.system),
|
||||
ShellFunc.reboot.exec(srv.spi.id, systemType: srv.status.system, customDir: null),
|
||||
context: context,
|
||||
id: srv.id,
|
||||
),
|
||||
@@ -84,7 +84,7 @@ extension _Operation on _ServerPageState {
|
||||
);
|
||||
}
|
||||
|
||||
void _onTapEdit(Server srv) {
|
||||
void _onTapEdit(ServerState srv) {
|
||||
if (srv.canViewDetails) {
|
||||
ServerDetailPage.route.go(context, SpiRequiredArgs(srv.spi));
|
||||
} else {
|
||||
@@ -98,7 +98,7 @@ extension _Utils on _ServerPageState {
|
||||
final tag = _tag.value;
|
||||
if (tag == TagSwitcher.kDefaultTag) return order;
|
||||
return order.where((e) {
|
||||
final tags = ServerProvider.pick(id: e)?.value.spi.tags;
|
||||
final tags = ref.read(serverNotifierProvider).servers[e]?.tags;
|
||||
if (tags == null) return false;
|
||||
return tags.contains(tag);
|
||||
}).toList();
|
||||
@@ -160,7 +160,7 @@ extension _Utils on _ServerPageState {
|
||||
}
|
||||
}
|
||||
|
||||
extension _ServerX on Server {
|
||||
extension _ServerX on ServerState {
|
||||
String? _getTopRightStr(Spi spi) {
|
||||
if (status.err != null) {
|
||||
return l10n.viewErr;
|
||||
|
||||
Reference in New Issue
Block a user