mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
feat: custom server logo
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
24
pubspec.lock
24
pubspec.lock
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user