opt.: migrate to new fl_lib (#649)

Fixes #648
This commit is contained in:
lollipopkit🏳️‍⚧️
2024-12-02 21:06:44 +08:00
committed by GitHub
parent b882baeafa
commit ddd32e82d4
50 changed files with 10858 additions and 225 deletions

View File

@@ -46,19 +46,24 @@ class Backup implements Mergeable {
Map<String, dynamic> toJson() => _$BackupToJson(this);
Backup.loadFromStore()
: version = backupFormatVersion,
date = DateTime.now().toString().split('.').firstOrNull ?? '',
spis = Stores.server.fetch(),
snippets = Stores.snippet.fetch(),
keys = Stores.key.fetch(),
container = Stores.container.box.toJson(),
lastModTime = Stores.lastModTime,
history = Stores.history.box.toJson(),
settings = Stores.setting.box.toJson();
static Future<Backup> loadFromStore() async {
final lastModTime = Stores.lastModTime?.millisecondsSinceEpoch;
return Backup(
version: backupFormatVersion,
date: DateTime.now().toString().split('.').firstOrNull ?? '',
spis: Stores.server.fetch(),
snippets: Stores.snippet.fetch(),
keys: Stores.key.fetch(),
container: await Stores.container.getAllMap(),
lastModTime: lastModTime,
history: await Stores.history.getAllMap(),
settings: await Stores.setting.getAllMap(),
);
}
static Future<String> backup([String? name]) async {
final result = _diyEncrypt(json.encode(Backup.loadFromStore().toJson()));
final bak = await Backup.loadFromStore();
final result = _diyEncrypt(json.encode(bak.toJson()));
final path = Paths.doc.joinPath(name ?? Miscs.bakFileName);
await File(path).writeAsString(result);
return path;
@@ -66,7 +71,7 @@ class Backup implements Mergeable {
@override
Future<void> merge({bool force = false}) async {
final curTime = Stores.lastModTime ?? 0;
final curTime = Stores.lastModTime?.millisecondsSinceEpoch ?? 0;
final bakTime = lastModTime ?? 0;
final shouldRestore = force || curTime < bakTime;
if (!shouldRestore) {

View File

@@ -36,7 +36,7 @@ class _AbsolutePath {
_path = newPath;
return;
}
_path = _path.joinPath(newPath, seperator: _sep);
_path = _path.joinPath(newPath, separator: _sep);
}
bool undo() {

View File

@@ -21,7 +21,7 @@ class SftpReq {
}
if (spi.jumpId != null) {
jumpSpi = Stores.server.box.get(spi.jumpId);
jumpPrivateKey = Stores.key.get(jumpSpi?.keyId)?.key;
jumpPrivateKey = Stores.key.fetchOne(jumpSpi?.keyId)?.key;
}
}
}

View File

@@ -3,6 +3,6 @@
abstract class BuildData {
static const String name = "ServerBox";
static const int build = 1104;
static const int script = 58;
static const int build = 1110;
static const int script = 59;
}

View File

@@ -16,7 +16,7 @@ abstract final class Stores {
static final history = HistoryStore.instance;
/// All stores that need backup
static final List<PersistentStore> _allBackup = [
static final List<HiveStore> _allBackup = [
SettingStore.instance,
ServerStore.instance,
ContainerStore.instance,
@@ -30,11 +30,16 @@ abstract final class Stores {
await NoBackupStore.instance.init();
}
static int? get lastModTime {
int? lastModTime = 0;
static DateTime? get lastModTime {
DateTime? lastModTime;
for (final store in _allBackup) {
final last = store.box.lastModified ?? 0;
if (last > (lastModTime ?? 0)) {
final last = store.lastUpdateTs;
if (last == null) {
continue;
}
if (lastModTime == null) {
lastModTime = last;
} else if (last.isAfter(lastModTime)) {
lastModTime = last;
}
}

View File

@@ -4,7 +4,7 @@ import 'package:server_box/data/res/store.dart';
const _keyConfig = 'providerConfig';
class ContainerStore extends PersistentStore {
class ContainerStore extends HiveStore {
ContainerStore._() : super('docker');
static final instance = ContainerStore._();
@@ -15,7 +15,7 @@ class ContainerStore extends PersistentStore {
void put(String id, String host) {
box.put(id, host);
box.updateLastModified();
updateLastUpdateTs();
}
ContainerType getType([String id = '']) {
@@ -30,7 +30,7 @@ class ContainerStore extends PersistentStore {
}
ContainerType get defaultType {
if (Stores.setting.usePodman.fetch()) return ContainerType.podman;
if (Stores.setting.usePodman.get()) return ContainerType.podman;
return ContainerType.docker;
}
@@ -40,6 +40,6 @@ class ContainerStore extends PersistentStore {
} else {
box.put(_keyConfig + id, type.toString());
}
box.updateLastModified();
updateLastUpdateTs();
}
}

View File

@@ -18,7 +18,6 @@ class _ListHistory {
_history.remove(path);
_history.insert(0, path);
_box.put(_name, _history);
_box.updateLastModified();
}
List get all => _history;
@@ -39,13 +38,12 @@ class _MapHistory {
void put(String id, String val) {
_history[id] = val;
_box.put(_name, _history);
_box.updateLastModified();
}
String? fetch(String id) => _history[id];
}
class HistoryStore extends PersistentStore {
class HistoryStore extends HiveStore {
HistoryStore._() : super('history');
static final instance = HistoryStore._();
@@ -58,5 +56,6 @@ class HistoryStore extends PersistentStore {
late final sshCmds = _ListHistory(box: box, name: 'sshCmds');
/// Notify users that this app will write script to server to works properly
late final writeScriptTipShown = property('writeScriptTipShown', false);
late final writeScriptTipShown =
propertyDefault('writeScriptTipShown', false);
}

View File

@@ -1,49 +1,72 @@
// ignore_for_file: non_constant_identifier_names
import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/res/build_data.dart';
import 'package:server_box/data/res/store.dart';
final class NoBackupStore extends PersistentStore {
final class NoBackupStore extends HiveStore {
NoBackupStore._() : super('no_backup');
static final instance = NoBackupStore._();
/// Only valid on iOS and macOS
late final icloudSync = property('icloudSync', false);
late final _icloudSync = propertyDefault('icloudSync', false);
/// Webdav sync
late final webdavSync = property('webdavSync', false);
late final webdavUrl = property('webdavUrl', '');
late final webdavUser = property('webdavUser', '');
late final webdavPwd = property('webdavPwd', '');
late final webdavSync = propertyDefault('webdavSync', false);
late final webdavUrl = propertyDefault('webdavUrl', '');
late final webdavUser = propertyDefault('webdavUser', '');
late final webdavPwd = propertyDefault('webdavPwd', '');
void migrate() {
if (BuildData.build > 1076) return;
void migrate(int lastVer) {
if (lastVer > 1104) return;
// Settings store -> NoBackup store
final settings = Stores.setting;
final icloudSync_ = settings.box.get('icloudSync');
if (icloudSync_ is bool) {
icloudSync.put(icloudSync_);
_icloudSync.set(icloudSync_);
settings.box.delete('icloudSync');
}
final webdavSync_ = settings.box.get('webdavSync');
if (webdavSync_ is bool) {
webdavSync.put(webdavSync_);
webdavSync.set(webdavSync_);
settings.box.delete('webdavSync');
}
final webdavUrl_ = settings.box.get('webdavUrl');
if (webdavUrl_ is String) {
webdavUrl.put(webdavUrl_);
webdavUrl.set(webdavUrl_);
settings.box.delete('webdavUrl');
}
final webdavUser_ = settings.box.get('webdavUser');
if (webdavUser_ is String) {
webdavUser.put(webdavUser_);
webdavUser.set(webdavUser_);
settings.box.delete('webdavUser');
}
final webdavPwd_ = settings.box.get('webdavPwd');
if (webdavPwd_ is String) {
webdavPwd.put(webdavPwd_);
webdavPwd.set(webdavPwd_);
settings.box.delete('webdavPwd');
}
// NoBackup store -> Pref store
final icloudSync__ = _icloudSync.get();
PrefProps.icloudSync.set(icloudSync__);
_icloudSync.remove();
final webdavSync__ = webdavSync.get();
PrefProps.webdavSync.set(webdavSync__);
webdavSync.remove();
final webdavUrl__ = webdavUrl.get();
PrefProps.webdavUrl.set(webdavUrl__);
webdavUrl.remove();
final webdavUser__ = webdavUser.get();
PrefProps.webdavUser.set(webdavUser__);
webdavUser.remove();
final webdavPwd__ = webdavPwd.get();
PrefProps.webdavPwd.set(webdavPwd__);
webdavPwd.remove();
}
}

View File

@@ -2,14 +2,13 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/server/private_key_info.dart';
class PrivateKeyStore extends PersistentStore {
class PrivateKeyStore extends HiveStore {
PrivateKeyStore._() : super('key');
static final instance = PrivateKeyStore._();
void put(PrivateKeyInfo info) {
box.put(info.id, info);
box.updateLastModified();
set(info.id, info);
}
List<PrivateKeyInfo> fetch() {
@@ -24,13 +23,12 @@ class PrivateKeyStore extends PersistentStore {
return ps;
}
PrivateKeyInfo? get(String? id) {
PrivateKeyInfo? fetchOne(String? id) {
if (id == null) return null;
return box.get(id);
}
void delete(PrivateKeyInfo s) {
box.delete(s.id);
box.updateLastModified();
remove(s.id);
}
}

View File

@@ -2,14 +2,15 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
class ServerStore extends PersistentStore {
class ServerStore extends HiveStore {
ServerStore._() : super('server');
static final instance = ServerStore._();
void put(Spi info) {
box.put(info.id, info);
box.updateLastModified();
// box.put(info.id, info);
// box.updateLastModified();
set(info.id, info);
}
List<Spi> fetch() {
@@ -25,13 +26,11 @@ class ServerStore extends PersistentStore {
}
void delete(String id) {
box.delete(id);
box.updateLastModified();
remove(id);
}
void deleteAll() {
box.clear();
box.updateLastModified();
clear();
}
void update(Spi old, Spi newInfo) {

View File

@@ -6,7 +6,7 @@ import 'package:server_box/data/model/ssh/virtual_key.dart';
import 'package:server_box/data/model/app/net_view.dart';
import 'package:server_box/data/res/default.dart';
class SettingStore extends PersistentStore {
class SettingStore extends HiveStore {
SettingStore._() : super('setting');
static final instance = SettingStore._();
@@ -18,19 +18,19 @@ class SettingStore extends PersistentStore {
// item in the drawer of the home page)
/// Discussion #146
late final serverTabUseOldUI = property('serverTabUseOldUI', false);
late final serverTabUseOldUI = propertyDefault('serverTabUseOldUI', false);
/// Time out for server connect and more...
late final timeout = property('timeOut', 5);
late final timeout = propertyDefault('timeOut', 5);
/// Record history of SFTP path and etc.
late final recordHistory = property('recordHistory', true);
late final recordHistory = propertyDefault('recordHistory', true);
/// Lanch page idx
// late final launchPage = property('launchPage', Defaults.launchPageIdx);
/// Disk view: amount / IO
late final serverTabPreferDiskAmount = property(
late final serverTabPreferDiskAmount = propertyDefault(
'serverTabPreferDiskAmount',
false,
);
@@ -40,59 +40,60 @@ class SettingStore extends PersistentStore {
/// Bigger for bigger font size
/// 1.0 means 100%
/// Warning: This may cause some UI issues
late final textFactor = property('textFactor', 1.0);
late final textFactor = propertyDefault('textFactor', 1.0);
/// The seed of color scheme
late final colorSeed = property('primaryColor', 4287106639);
late final colorSeed = propertyDefault('primaryColor', 4287106639);
late final serverStatusUpdateInterval = property(
late final serverStatusUpdateInterval = propertyDefault(
'serverStatusUpdateInterval',
Defaults.updateInterval,
);
// Max retry count when connect to server
late final maxRetryCount = property('maxRetryCount', 2);
late final maxRetryCount = propertyDefault('maxRetryCount', 2);
// Night mode: 0 -> auto, 1 -> light, 2 -> dark, 3 -> AMOLED, 4 -> AUTO-AMOLED
late final themeMode = property('themeMode', 0);
late final themeMode = propertyDefault('themeMode', 0);
// Font file path
late final fontPath = property('fontPath', '');
late final fontPath = propertyDefault('fontPath', '');
// Backgroud running (Android)
late final bgRun = property('bgRun', isAndroid);
late final bgRun = propertyDefault('bgRun', isAndroid);
// Server order
late final serverOrder = listProperty<String>('serverOrder', []);
late final serverOrder = propertyDefault<List<String>>('serverOrder', []);
late final snippetOrder = listProperty<String>('snippetOrder', []);
late final snippetOrder = propertyDefault<List<String>>('snippetOrder', []);
// Server details page cards order
late final detailCardOrder = listProperty(
late final detailCardOrder = propertyDefault(
'detailCardOrder',
ServerDetailCards.values.map((e) => e.name).toList(),
);
// SSH term font size
late final termFontSize = property('termFontSize', 13.0);
late final termFontSize = propertyDefault('termFontSize', 13.0);
// Locale
late final locale = property('locale', '');
late final locale = propertyDefault('locale', '');
// SSH virtual key (ctrl | alt) auto turn off
late final sshVirtualKeyAutoOff = property('sshVirtualKeyAutoOff', true);
late final sshVirtualKeyAutoOff =
propertyDefault('sshVirtualKeyAutoOff', true);
late final editorFontSize = property('editorFontSize', 12.5);
late final editorFontSize = propertyDefault('editorFontSize', 12.5);
// Editor theme
late final editorTheme = property('editorTheme', Defaults.editorTheme);
late final editorTheme = propertyDefault('editorTheme', Defaults.editorTheme);
late final editorDarkTheme =
property('editorDarkTheme', Defaults.editorDarkTheme);
propertyDefault('editorDarkTheme', Defaults.editorDarkTheme);
late final fullScreen = property('fullScreen', false);
late final fullScreen = propertyDefault('fullScreen', false);
late final fullScreenJitter = property('fullScreenJitter', true);
late final fullScreenJitter = propertyDefault('fullScreenJitter', true);
// late final fullScreenRotateQuarter = property(
// 'fullScreenRotateQuarter',
@@ -104,140 +105,145 @@ class SettingStore extends PersistentStore {
// TextInputType.text.index,
// );
late final sshVirtKeys = listProperty(
late final sshVirtKeys = propertyDefault(
'sshVirtKeys',
VirtKeyX.defaultOrder.map((e) => e.index).toList(),
);
late final netViewType = property('netViewType', NetViewType.speed);
late final netViewType = propertyDefault('netViewType', NetViewType.speed);
// Only valid on iOS
late final autoUpdateHomeWidget = property('autoUpdateHomeWidget', isIOS);
late final autoUpdateHomeWidget =
propertyDefault('autoUpdateHomeWidget', isIOS);
late final autoCheckAppUpdate = property('autoCheckAppUpdate', true);
late final autoCheckAppUpdate = propertyDefault('autoCheckAppUpdate', true);
/// Display server tab function buttons on the bottom of each server card if [true]
///
/// Otherwise, display them on the top of server detail page
late final moveServerFuncs = property('moveOutServerTabFuncBtns', false);
late final moveServerFuncs =
propertyDefault('moveOutServerTabFuncBtns', false);
/// Whether use `rm -r` to delete directory on SFTP
late final sftpRmrDir = property('sftpRmrDir', false);
late final sftpRmrDir = propertyDefault('sftpRmrDir', false);
/// Whether use system's primary color as the app's primary color
late final useSystemPrimaryColor = property('useSystemPrimaryColor', false);
late final useSystemPrimaryColor =
propertyDefault('useSystemPrimaryColor', false);
/// Only valid on iOS / Android / Windows
late final useBioAuth = property('useBioAuth', false);
late final useBioAuth = propertyDefault('useBioAuth', false);
/// The performance of highlight is bad
late final editorHighlight = property('editorHighlight', true);
late final editorHighlight = propertyDefault('editorHighlight', true);
/// Open SFTP with last viewed path
late final sftpOpenLastPath = property('sftpOpenLastPath', true);
late final sftpOpenLastPath = propertyDefault('sftpOpenLastPath', true);
/// Show folders first in SFTP file browser
late final sftpShowFoldersFirst = property('sftpShowFoldersFirst', true);
late final sftpShowFoldersFirst =
propertyDefault('sftpShowFoldersFirst', true);
/// Show tip of suspend
late final showSuspendTip = property('showSuspendTip', true);
late final showSuspendTip = propertyDefault('showSuspendTip', true);
/// Whether collapse UI items by default
late final collapseUIDefault = property('collapseUIDefault', true);
late final collapseUIDefault = propertyDefault('collapseUIDefault', true);
late final serverFuncBtns = listProperty(
late final serverFuncBtns = propertyDefault(
'serverBtns',
ServerFuncBtn.defaultIdxs,
);
/// Docker is more popular than podman, set to `false` to use docker
late final usePodman = property('usePodman', false);
late final usePodman = propertyDefault('usePodman', false);
/// Try to use `sudo` to run docker command
late final containerTrySudo = property('containerTrySudo', true);
late final containerTrySudo = propertyDefault('containerTrySudo', true);
/// Keep previous server status when err occurs
late final keepStatusWhenErr = property('keepStatusWhenErr', false);
late final keepStatusWhenErr = propertyDefault('keepStatusWhenErr', false);
/// Parse container stat
late final containerParseStat = property('containerParseStat', true);
late final containerParseStat = propertyDefault('containerParseStat', true);
/// Auto refresh container status
late final contaienrAutoRefresh = property('contaienrAutoRefresh', true);
late final contaienrAutoRefresh =
propertyDefault('contaienrAutoRefresh', true);
/// Use double column servers page on Desktop
late final doubleColumnServersPage = property(
late final doubleColumnServersPage = propertyDefault(
'doubleColumnServersPage',
true,
);
/// Ignore local network device (eg: br-xxx, ovs-system...)
/// when building traffic view on server tab
//late final ignoreLocalNet = property('ignoreLocalNet', true);
//late final ignoreLocalNet = propertyDefault('ignoreLocalNet', true);
/// Remerber pwd in memory
/// Used for [DialogX.showPwdDialog]
late final rememberPwdInMem = property('rememberPwdInMem', true);
late final rememberPwdInMem = propertyDefault('rememberPwdInMem', true);
/// SSH Term Theme
/// 0: follow app theme, 1: light, 2: dark
late final termTheme = property('termTheme', 0);
late final termTheme = propertyDefault('termTheme', 0);
/// Compatiablity for Chinese Android.
/// Set it to true, if you use Safe Keyboard on Chinese Android
// late final cnKeyboardComp = property('cnKeyboardComp', false);
// late final cnKeyboardComp = propertyDefault('cnKeyboardComp', false);
late final lastVer = property('lastVer', 0);
late final lastVer = propertyDefault('lastVer', 0);
/// Use CupertinoPageRoute for all routes
late final cupertinoRoute = property('cupertinoRoute', isIOS);
late final cupertinoRoute = propertyDefault('cupertinoRoute', isIOS);
/// Hide title bar on desktop
late final hideTitleBar = property('hideTitleBar', isDesktop);
late final hideTitleBar = propertyDefault('hideTitleBar', isDesktop);
/// Display CPU view as progress, also called as old CPU view
late final cpuViewAsProgress = property('cpuViewAsProgress', false);
late final cpuViewAsProgress = propertyDefault('cpuViewAsProgress', false);
late final displayCpuIndex = property('displayCpuIndex', true);
late final displayCpuIndex = propertyDefault('displayCpuIndex', true);
late final editorSoftWrap = property('editorSoftWrap', isIOS);
late final editorSoftWrap = propertyDefault('editorSoftWrap', isIOS);
late final sshTermHelpShown = property('sshTermHelpShown', false);
late final sshTermHelpShown = propertyDefault('sshTermHelpShown', false);
late final horizonVirtKey = property('horizonVirtKey', false);
late final horizonVirtKey = propertyDefault('horizonVirtKey', false);
/// general wake lock
late final generalWakeLock = property('generalWakeLock', false);
late final generalWakeLock = propertyDefault('generalWakeLock', false);
/// ssh page
late final sshWakeLock = property('sshWakeLock', true);
late final sshWakeLock = propertyDefault('sshWakeLock', true);
/// fmt: https://example.com/{DIST}-{BRIGHT}.png
late final serverLogoUrl = property('serverLogoUrl', '');
late final serverLogoUrl = propertyDefault('serverLogoUrl', '');
late final betaTest = property('betaTest', false);
late final betaTest = propertyDefault('betaTest', false);
/// If it's empty, skip change window size.
/// Format: {width}x{height}
late final windowSize = property('windowSize', '');
late final windowSize = propertyDefault('windowSize', '');
late final introVer = property('introVer', 0);
late final introVer = propertyDefault('introVer', 0);
late final letterCache = property('letterCache', false);
late final letterCache = propertyDefault('letterCache', false);
/// Set it to `$EDITOR`, `vim` and etc. to use remote system editor in SSH terminal.
/// Set it empty to use local editor GUI.
late final sftpEditor = property('sftpEditor', '');
late final sftpEditor = propertyDefault('sftpEditor', '');
// Never show these settings for users
//
// ------BEGIN------
/// Version of store db
late final storeVersion = property('storeVersion', 0);
late final storeVersion = propertyDefault('storeVersion', 0);
/// Have notified user for notificaiton permission or not
late final noNotiPerm = property('noNotiPerm', false);
late final noNotiPerm = propertyDefault('noNotiPerm', false);
// ------END------
}

View File

@@ -2,14 +2,15 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/server/snippet.dart';
class SnippetStore extends PersistentStore {
class SnippetStore extends HiveStore {
SnippetStore._() : super('snippet');
static final instance = SnippetStore._();
void put(Snippet snippet) {
box.put(snippet.name, snippet);
box.updateLastModified();
// box.put(snippet.name, snippet);
// box.updateLastModified();
set(snippet.name, snippet);
}
List<Snippet> fetch() {
@@ -25,7 +26,8 @@ class SnippetStore extends PersistentStore {
}
void delete(Snippet s) {
box.delete(s.name);
box.updateLastModified();
// box.delete(s.name);
// box.updateLastModified();
remove(s.name);
}
}