feat: custom server logo

This commit is contained in:
lollipopkit
2024-05-09 17:08:37 +08:00
parent 91a9d5aab5
commit 4d2a944310
10 changed files with 140 additions and 56 deletions

View File

@@ -16,6 +16,8 @@ final class ServerCustom {
final Map<String, String>? cmds; final Map<String, String>? cmds;
@HiveField(4) @HiveField(4)
final String? preferTempDev; final String? preferTempDev;
@HiveField(5)
final String? logoUrl;
const ServerCustom({ const ServerCustom({
//this.temperature, //this.temperature,
@@ -23,6 +25,7 @@ final class ServerCustom {
this.pveIgnoreCert = false, this.pveIgnoreCert = false,
this.cmds, this.cmds,
this.preferTempDev, this.preferTempDev,
this.logoUrl,
}); });
static ServerCustom fromJson(Map<String, dynamic> json) { static ServerCustom fromJson(Map<String, dynamic> json) {
@@ -31,12 +34,14 @@ final class ServerCustom {
final pveIgnoreCert = json["pveIgnoreCert"] as bool; final pveIgnoreCert = json["pveIgnoreCert"] as bool;
final cmds = json["cmds"] as Map<String, dynamic>?; final cmds = json["cmds"] as Map<String, dynamic>?;
final preferTempDev = json["preferTempDev"] as String?; final preferTempDev = json["preferTempDev"] as String?;
final logoUrl = json["logoUrl"] as String?;
return ServerCustom( return ServerCustom(
//temperature: temperature, //temperature: temperature,
pveAddr: pveAddr, pveAddr: pveAddr,
pveIgnoreCert: pveIgnoreCert, pveIgnoreCert: pveIgnoreCert,
cmds: cmds?.cast<String, String>(), cmds: cmds?.cast<String, String>(),
preferTempDev: preferTempDev, preferTempDev: preferTempDev,
logoUrl: logoUrl,
); );
} }
@@ -56,6 +61,9 @@ final class ServerCustom {
if (preferTempDev != null) { if (preferTempDev != null) {
json["preferTempDev"] = preferTempDev; json["preferTempDev"] = preferTempDev;
} }
if (logoUrl != null) {
json["logoUrl"] = logoUrl;
}
return json; return json;
} }
@@ -71,9 +79,16 @@ final class ServerCustom {
other.pveAddr == pveAddr && other.pveAddr == pveAddr &&
other.pveIgnoreCert == pveIgnoreCert && other.pveIgnoreCert == pveIgnoreCert &&
other.cmds == cmds && other.cmds == cmds &&
other.preferTempDev == preferTempDev; other.preferTempDev == preferTempDev &&
other.logoUrl == logoUrl;
} }
@override @override
int get hashCode => toString().hashCode; int get hashCode =>
//temperature.hashCode ^
pveAddr.hashCode ^
pveIgnoreCert.hashCode ^
cmds.hashCode ^
preferTempDev.hashCode ^
logoUrl.hashCode;
} }

View File

@@ -21,13 +21,14 @@ class ServerCustomAdapter extends TypeAdapter<ServerCustom> {
pveIgnoreCert: fields[2] == null ? false : fields[2] as bool, pveIgnoreCert: fields[2] == null ? false : fields[2] as bool,
cmds: (fields[3] as Map?)?.cast<String, String>(), cmds: (fields[3] as Map?)?.cast<String, String>(),
preferTempDev: fields[4] as String?, preferTempDev: fields[4] as String?,
logoUrl: fields[5] as String?,
); );
} }
@override @override
void write(BinaryWriter writer, ServerCustom obj) { void write(BinaryWriter writer, ServerCustom obj) {
writer writer
..writeByte(4) ..writeByte(5)
..writeByte(1) ..writeByte(1)
..write(obj.pveAddr) ..write(obj.pveAddr)
..writeByte(2) ..writeByte(2)
@@ -35,7 +36,9 @@ class ServerCustomAdapter extends TypeAdapter<ServerCustom> {
..writeByte(3) ..writeByte(3)
..write(obj.cmds) ..write(obj.cmds)
..writeByte(4) ..writeByte(4)
..write(obj.preferTempDev); ..write(obj.preferTempDev)
..writeByte(5)
..write(obj.logoUrl);
} }
@override @override

View File

@@ -22,12 +22,12 @@ class Server implements TagPickable {
ServerPrivateInfo spi; ServerPrivateInfo spi;
ServerStatus status; ServerStatus status;
SSHClient? client; SSHClient? client;
ServerState state; ServerConn conn;
Server( Server(
this.spi, this.spi,
this.status, this.status,
this.state, { this.conn, {
this.client, this.client,
}); });
@@ -39,9 +39,9 @@ class Server implements TagPickable {
@override @override
String get tagName => spi.id; String get tagName => spi.id;
bool get needGenClient => state < ServerState.connecting; bool get needGenClient => conn < ServerConn.connecting;
bool get canViewDetails => state == ServerState.finished; bool get canViewDetails => conn == ServerConn.finished;
String get id => spi.id; String get id => spi.id;
} }
@@ -80,7 +80,7 @@ class ServerStatus {
}); });
} }
enum ServerState { enum ServerConn {
failed, failed,
disconnected, disconnected,
connecting, connecting,
@@ -94,5 +94,5 @@ enum ServerState {
/// Status parsing finished /// Status parsing finished
finished; finished;
operator <(ServerState other) => index < other.index; operator <(ServerConn other) => index < other.index;
} }

View File

@@ -2,10 +2,10 @@ part of 'server.dart';
extension ServerX on Server { extension ServerX on Server {
String getTopRightStr(ServerPrivateInfo spi) { String getTopRightStr(ServerPrivateInfo spi) {
switch (state) { switch (conn) {
case ServerState.disconnected: case ServerConn.disconnected:
return l10n.disconnected; return l10n.disconnected;
case ServerState.finished: case ServerConn.finished:
// Highest priority of temperature display // Highest priority of temperature display
final cmdTemp = () { final cmdTemp = () {
final val = status.customCmds['server_card_top_right']; final val = status.customCmds['server_card_top_right'];
@@ -46,13 +46,13 @@ extension ServerX on Server {
final str = items.where((e) => e != null && e.isNotEmpty).join(' | '); final str = items.where((e) => e != null && e.isNotEmpty).join(' | ');
if (str.isEmpty) return l10n.noResult; if (str.isEmpty) return l10n.noResult;
return str; return str;
case ServerState.loading: case ServerConn.loading:
return l10n.serverTabLoading; return l10n.serverTabLoading;
case ServerState.connected: case ServerConn.connected:
return l10n.connected; return l10n.connected;
case ServerState.connecting: case ServerConn.connecting:
return l10n.serverTabConnecting; return l10n.serverTabConnecting;
case ServerState.failed: case ServerConn.failed:
return status.err ?? l10n.serverTabFailed; return status.err ?? l10n.serverTabFailed;
} }
} }

View File

@@ -52,7 +52,7 @@ class ServerProvider extends ChangeNotifier {
/// Issues #258 /// Issues #258
/// If not [shouldReconnect], then keep the old state. /// If not [shouldReconnect], then keep the old state.
if (originServer != null && !originServer.spi.shouldReconnect(spi)) { if (originServer != null && !originServer.spi.shouldReconnect(spi)) {
newServer.state = originServer.state; newServer.conn = originServer.conn;
} }
_servers[spi.id] = newServer; _servers[spi.id] = newServer;
} }
@@ -115,7 +115,7 @@ class ServerProvider extends ChangeNotifier {
} }
Server genServer(ServerPrivateInfo spi) { Server genServer(ServerPrivateInfo spi) {
return Server(spi, InitStatus.status, ServerState.disconnected); return Server(spi, InitStatus.status, ServerConn.disconnected);
} }
/// if [spi] is specificed then only refresh this server /// if [spi] is specificed then only refresh this server
@@ -134,7 +134,7 @@ class ServerProvider extends ChangeNotifier {
Future<void> _connectFn(Server s, bool onlyFailed) async { Future<void> _connectFn(Server s, bool onlyFailed) async {
if (onlyFailed) { if (onlyFailed) {
if (s.state != ServerState.failed) return; if (s.conn != ServerConn.failed) return;
TryLimiter.reset(s.spi.id); TryLimiter.reset(s.spi.id);
} }
@@ -144,7 +144,7 @@ class ServerProvider extends ChangeNotifier {
/// If no this, the server will only refresh once by clicking refresh button. /// If no this, the server will only refresh once by clicking refresh button.
/// ///
/// If [spi.autoConnect] is true, then refresh. /// If [spi.autoConnect] is true, then refresh.
if (!(s.spi.autoConnect ?? true) && s.state == ServerState.disconnected) { if (!(s.spi.autoConnect ?? true) && s.conn == ServerConn.disconnected) {
return; return;
} }
return await _getData(s.spi); return await _getData(s.spi);
@@ -174,7 +174,7 @@ class ServerProvider extends ChangeNotifier {
void setDisconnected() { void setDisconnected() {
for (final s in _servers.values) { for (final s in _servers.values) {
s.state = ServerState.disconnected; s.conn = ServerConn.disconnected;
} }
//TryLimiter.clear(); //TryLimiter.clear();
notifyListeners(); notifyListeners();
@@ -251,8 +251,8 @@ class ServerProvider extends ChangeNotifier {
} }
} }
void _setServerState(Server s, ServerState ss) { void _setServerState(Server s, ServerConn ss) {
s.state = ss; s.conn = ss;
notifyListeners(); notifyListeners();
} }
@@ -263,8 +263,8 @@ class ServerProvider extends ChangeNotifier {
if (s == null) return; if (s == null) return;
if (!TryLimiter.canTry(sid)) { if (!TryLimiter.canTry(sid)) {
if (s.state != ServerState.failed) { if (s.conn != ServerConn.failed) {
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
} }
return; return;
} }
@@ -272,7 +272,7 @@ class ServerProvider extends ChangeNotifier {
s.status.err = null; s.status.err = null;
if (s.needGenClient || (s.client?.isClosed ?? true)) { if (s.needGenClient || (s.client?.isClosed ?? true)) {
_setServerState(s, ServerState.connecting); _setServerState(s, ServerConn.connecting);
try { try {
final time1 = DateTime.now(); final time1 = DateTime.now();
@@ -291,14 +291,14 @@ class ServerProvider extends ChangeNotifier {
} catch (e) { } catch (e) {
TryLimiter.inc(sid); TryLimiter.inc(sid);
s.status.err = e.toString(); s.status.err = e.toString();
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
/// In order to keep privacy, print [spi.name] instead of [spi.id] /// In order to keep privacy, print [spi.name] instead of [spi.id]
Loggers.app.warning('Connect to ${spi.name} failed', e); Loggers.app.warning('Connect to ${spi.name} failed', e);
return; return;
} }
_setServerState(s, ServerState.connected); _setServerState(s, ServerConn.connected);
// Write script to server // Write script to server
// by ssh // by ssh
@@ -314,12 +314,12 @@ class ServerProvider extends ChangeNotifier {
} on SSHAuthAbortError catch (e) { } on SSHAuthAbortError catch (e) {
TryLimiter.inc(sid); TryLimiter.inc(sid);
s.status.err = e.toString(); s.status.err = e.toString();
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
return; return;
} on SSHAuthFailError catch (e) { } on SSHAuthFailError catch (e) {
TryLimiter.inc(sid); TryLimiter.inc(sid);
s.status.err = e.toString(); s.status.err = e.toString();
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
return; return;
} catch (e) { } catch (e) {
Loggers.app.warning('Write script to ${spi.name} by shell', e); Loggers.app.warning('Write script to ${spi.name} by shell', e);
@@ -347,7 +347,7 @@ class ServerProvider extends ChangeNotifier {
} catch (e) { } catch (e) {
TryLimiter.inc(sid); TryLimiter.inc(sid);
s.status.err = e.toString(); s.status.err = e.toString();
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
Loggers.app.warning('Write script to ${spi.name} by sftp', e); Loggers.app.warning('Write script to ${spi.name} by sftp', e);
return; return;
} finally { } finally {
@@ -356,13 +356,13 @@ class ServerProvider extends ChangeNotifier {
} }
} }
if (s.state == ServerState.connecting) return; if (s.conn == ServerConn.connecting) return;
/// Keep [finished] state, or the UI will be refreshed to [loading] state /// Keep [finished] state, or the UI will be refreshed to [loading] state
/// instead of the '$Temp | $Uptime'. /// instead of the '$Temp | $Uptime'.
/// eg: '32C | 7 days' /// eg: '32C | 7 days'
if (s.state != ServerState.finished) { if (s.conn != ServerConn.finished) {
_setServerState(s, ServerState.loading); _setServerState(s, ServerConn.loading);
} }
List<String>? segments; List<String>? segments;
@@ -374,19 +374,19 @@ class ServerProvider extends ChangeNotifier {
if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) { if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) {
if (Stores.setting.keepStatusWhenErr.fetch()) { if (Stores.setting.keepStatusWhenErr.fetch()) {
// Keep previous server status when err occurs // Keep previous server status when err occurs
if (s.state != ServerState.failed && s.status.more.isNotEmpty) { if (s.conn != ServerConn.failed && s.status.more.isNotEmpty) {
return; return;
} }
} }
TryLimiter.inc(sid); TryLimiter.inc(sid);
s.status.err = 'Seperate segments failed, raw:\n$raw'; s.status.err = 'Seperate segments failed, raw:\n$raw';
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
return; return;
} }
} catch (e) { } catch (e) {
TryLimiter.inc(sid); TryLimiter.inc(sid);
s.status.err = e.toString(); s.status.err = e.toString();
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
Loggers.app.warning('Get status from ${spi.name} failed', e); Loggers.app.warning('Get status from ${spi.name} failed', e);
return; return;
} }
@@ -399,7 +399,7 @@ class ServerProvider extends ChangeNotifier {
final actual = segments.length; final actual = segments.length;
final err = 'Segments: expect $expected, got $actual, raw:\n\n$raw'; final err = 'Segments: expect $expected, got $actual, raw:\n\n$raw';
s.status.err = err; s.status.err = err;
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
return; return;
} }
s.status.system = systemType; s.status.system = systemType;
@@ -419,13 +419,13 @@ class ServerProvider extends ChangeNotifier {
} catch (e, trace) { } catch (e, trace) {
TryLimiter.inc(sid); TryLimiter.inc(sid);
s.status.err = 'Parse failed: $e\n\n$raw'; s.status.err = 'Parse failed: $e\n\n$raw';
_setServerState(s, ServerState.failed); _setServerState(s, ServerConn.failed);
Loggers.parse.warning('Server status', e, trace); Loggers.parse.warning('Server status', e, trace);
return; return;
} }
/// Call this every time for setting [Server.isBusy] to false /// Call this every time for setting [Server.isBusy] to false
_setServerState(s, ServerState.finished); _setServerState(s, ServerConn.finished);
// reset try times only after prepared successfully // reset try times only after prepared successfully
TryLimiter.reset(sid); TryLimiter.reset(sid);
} }

View File

@@ -1,3 +1,4 @@
import 'package:extended_image/extended_image.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:icons_plus/icons_plus.dart'; import 'package:icons_plus/icons_plus.dart';
@@ -11,6 +12,7 @@ import 'package:toolbox/data/model/app/shell_func.dart';
import 'package:toolbox/data/model/server/battery.dart'; import 'package:toolbox/data/model/server/battery.dart';
import 'package:toolbox/data/model/server/cpu.dart'; import 'package:toolbox/data/model/server/cpu.dart';
import 'package:toolbox/data/model/server/disk.dart'; import 'package:toolbox/data/model/server/disk.dart';
import 'package:toolbox/data/model/server/dist.dart';
import 'package:toolbox/data/model/server/net_speed.dart'; import 'package:toolbox/data/model/server/net_speed.dart';
import 'package:toolbox/data/model/server/nvdia.dart'; import 'package:toolbox/data/model/server/nvdia.dart';
import 'package:toolbox/data/model/server/sensors.dart'; import 'package:toolbox/data/model/server/sensors.dart';
@@ -100,6 +102,13 @@ class _ServerDetailPageState extends State<ServerDetailPage>
Widget _buildMainPage(Server si) { Widget _buildMainPage(Server si) {
final buildFuncs = !Stores.setting.moveOutServerTabFuncBtns.fetch(); final buildFuncs = !Stores.setting.moveOutServerTabFuncBtns.fetch();
final logoUrl = si.spi.custom?.logoUrl;
final listLen = () {
var len = _cardsOrder.length;
if (buildFuncs) len++;
if (logoUrl != null) len++;
return len;
}();
return Scaffold( return Scaffold(
appBar: CustomAppBar( appBar: CustomAppBar(
title: Text(si.spi.name, style: UIs.text18), title: Text(si.spi.name, style: UIs.text18),
@@ -121,11 +130,15 @@ class _ServerDetailPageState extends State<ServerDetailPage>
right: 13, right: 13,
bottom: _media.padding.bottom + 77, bottom: _media.padding.bottom + 77,
), ),
itemCount: buildFuncs ? _cardsOrder.length + 1 : _cardsOrder.length, itemCount: listLen,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index == 0 && buildFuncs) { if (index == 0 && logoUrl != null) {
return _buildLogo(logoUrl, si.status.more[StatusCmdType.sys]?.dist);
}
if (index == 1 && buildFuncs) {
return ServerFuncBtns(spi: widget.spi); return ServerFuncBtns(spi: widget.spi);
} }
if (logoUrl != null) index--;
if (buildFuncs) index--; if (buildFuncs) index--;
return _cardBuildMap[_cardsOrder[index]]?.call(si.status); return _cardBuildMap[_cardsOrder[index]]?.call(si.status);
}, },
@@ -133,6 +146,20 @@ class _ServerDetailPageState extends State<ServerDetailPage>
); );
} }
Widget _buildLogo(String logoUrl, Dist? dist) {
if (dist != null) {
logoUrl = logoUrl.replaceFirst('{DIST}', dist.name);
}
return Padding(
padding: const EdgeInsets.symmetric(vertical: 13),
child: ExtendedImage.network(
logoUrl,
cache: true,
height: _media.size.height * 0.2,
),
);
}
Widget _buildAbout(ServerStatus ss) { Widget _buildAbout(ServerStatus ss) {
return CardX( return CardX(
child: ExpandTile( child: ExpandTile(

View File

@@ -43,6 +43,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
final _pveAddrCtrl = TextEditingController(); final _pveAddrCtrl = TextEditingController();
final _customCmdCtrl = TextEditingController(); final _customCmdCtrl = TextEditingController();
final _preferTempDevCtrl = TextEditingController(); final _preferTempDevCtrl = TextEditingController();
final _logoUrlCtrl = TextEditingController();
final _nameFocus = FocusNode(); final _nameFocus = FocusNode();
final _ipFocus = FocusNode(); final _ipFocus = FocusNode();
@@ -96,6 +97,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
} }
} catch (_) {} } catch (_) {}
_preferTempDevCtrl.text = custom.preferTempDev ?? ''; _preferTempDevCtrl.text = custom.preferTempDev ?? '';
_logoUrlCtrl.text = custom.logoUrl ?? '';
} }
} }
} }
@@ -117,6 +119,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
_pveAddrCtrl.dispose(); _pveAddrCtrl.dispose();
_customCmdCtrl.dispose(); _customCmdCtrl.dispose();
_preferTempDevCtrl.dispose(); _preferTempDevCtrl.dispose();
_logoUrlCtrl.dispose();
} }
@override @override
@@ -367,6 +370,16 @@ class _ServerEditPageState extends State<ServerEditPage> {
return ExpandTile( return ExpandTile(
title: Text(l10n.more), title: Text(l10n.more),
children: [ children: [
const Text('Logo', style: UIs.text13Grey),
UIs.height7,
Input(
controller: _logoUrlCtrl,
type: TextInputType.url,
icon: Icons.image,
label: 'Url',
hint: 'https://example.com/logo.png',
),
UIs.height7,
const Text('PVE', style: UIs.text13Grey), const Text('PVE', style: UIs.text13Grey),
UIs.height7, UIs.height7,
Input( Input(
@@ -528,6 +541,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
pveIgnoreCert: _pveIgnoreCert.value, pveIgnoreCert: _pveIgnoreCert.value,
cmds: customCmds, cmds: customCmds,
preferTempDev: _preferTempDevCtrl.text.selfIfNotNullEmpty, preferTempDev: _preferTempDevCtrl.text.selfIfNotNullEmpty,
logoUrl: _logoUrlCtrl.text.selfIfNotNullEmpty,
); );
final spi = ServerPrivateInfo( final spi = ServerPrivateInfo(

View File

@@ -281,7 +281,7 @@ class _ServerPageState extends State<ServerPage>
} }
}, },
onLongPress: () { onLongPress: () {
if (srv.state == ServerState.finished) { if (srv.conn == ServerConn.finished) {
final id = srv.spi.id; final id = srv.spi.id;
final cardStatus = _getCardNoti(id); final cardStatus = _getCardNoti(id);
cardStatus.value = cardStatus.value.copyWith( cardStatus.value = cardStatus.value.copyWith(
@@ -319,7 +319,7 @@ class _ServerPageState extends State<ServerPage>
listenable: cardStatus, listenable: cardStatus,
builder: (_, __) { builder: (_, __) {
final List<Widget> children = [title]; final List<Widget> children = [title];
if (srv.state == ServerState.finished) { if (srv.conn == ServerConn.finished) {
if (cardStatus.value.flip) { if (cardStatus.value.flip) {
children.addAll(_buildFlippedCard(srv)); children.addAll(_buildFlippedCard(srv));
} else { } else {
@@ -330,7 +330,7 @@ class _ServerPageState extends State<ServerPage>
return AnimatedContainer( return AnimatedContainer(
duration: const Duration(milliseconds: 377), duration: const Duration(milliseconds: 377),
curve: Curves.fastEaseInToSlowEaseOut, curve: Curves.fastEaseInToSlowEaseOut,
height: _calcCardHeight(srv.state, cardStatus.value.flip), height: _calcCardHeight(srv.conn, cardStatus.value.flip),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
@@ -461,10 +461,10 @@ class _ServerPageState extends State<ServerPage>
} }
Widget _buildTopRightWidget(Server s) { Widget _buildTopRightWidget(Server s) {
return switch (s.state) { return switch (s.conn) {
ServerState.connecting || ServerConn.connecting ||
ServerState.loading || ServerConn.loading ||
ServerState.connected => ServerConn.connected =>
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 7), padding: const EdgeInsets.symmetric(horizontal: 7),
child: SizedBox( child: SizedBox(
@@ -476,7 +476,7 @@ class _ServerPageState extends State<ServerPage>
), ),
), ),
), ),
ServerState.failed => InkWell( ServerConn.failed => InkWell(
onTap: () { onTap: () {
TryLimiter.reset(s.spi.id); TryLimiter.reset(s.spi.id);
Pros.server.refresh(spi: s.spi); Pros.server.refresh(spi: s.spi);
@@ -490,7 +490,7 @@ class _ServerPageState extends State<ServerPage>
), ),
), ),
), ),
ServerState.disconnected when !(s.spi.autoConnect ?? true) => InkWell( ServerConn.disconnected when !(s.spi.autoConnect ?? true) => InkWell(
onTap: () => Pros.server.refresh(spi: s.spi), onTap: () => Pros.server.refresh(spi: s.spi),
child: const Padding( child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 7), padding: EdgeInsets.symmetric(horizontal: 7),
@@ -508,7 +508,7 @@ class _ServerPageState extends State<ServerPage>
} }
Widget _buildTopRightText(Server s) { Widget _buildTopRightText(Server s) {
final hasErr = s.state == ServerState.failed && s.status.err != null; final hasErr = s.conn == ServerConn.failed && s.status.err != null;
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
if (!hasErr) return; if (!hasErr) return;
@@ -636,9 +636,9 @@ class _ServerPageState extends State<ServerPage>
_tag == null || (pro.pick(id: e)?.spi.tags?.contains(_tag) ?? false)) _tag == null || (pro.pick(id: e)?.spi.tags?.contains(_tag) ?? false))
.toList(); .toList();
double? _calcCardHeight(ServerState cs, bool flip) { double? _calcCardHeight(ServerConn cs, bool flip) {
if (_textFactorDouble != 1.0) return null; if (_textFactorDouble != 1.0) return null;
if (cs != ServerState.finished) { if (cs != ServerConn.finished) {
return 23.0; return 23.0;
} }
if (flip) { if (flip) {

View File

@@ -308,6 +308,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.5" version: "2.0.5"
extended_image:
dependency: "direct main"
description:
name: extended_image
sha256: d7f091d068fcac7246c4b22a84b8dac59a62e04d29a5c172710c696e67a22f94
url: "https://pub.dev"
source: hosted
version: "8.2.0"
extended_image_library:
dependency: transitive
description:
name: extended_image_library
sha256: c9caee8fe9b6547bd41c960c4f2d1ef8e34321804de6a1777f1d614a24247ad6
url: "https://pub.dev"
source: hosted
version: "4.0.4"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@@ -544,6 +560,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.2.1"
http_client_helper:
dependency: transitive
description:
name: http_client_helper
sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:

View File

@@ -77,6 +77,7 @@ dependencies:
permission_handler: ^11.3.1 permission_handler: ^11.3.1
fl_chart: ^0.67.0 fl_chart: ^0.67.0
wakelock_plus: ^1.2.4 wakelock_plus: ^1.2.4
extended_image: ^8.2.0
dev_dependencies: dev_dependencies:
flutter_native_splash: ^2.1.6 flutter_native_splash: ^2.1.6