fix: cloud sync (#769)

This commit is contained in:
lollipopkit🏳️‍⚧️
2025-06-04 00:11:31 +08:00
committed by GitHub
parent 9547d92ac5
commit 0c1ada0067
70 changed files with 2348 additions and 1906 deletions

View File

@@ -20,7 +20,7 @@ jobs:
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.27.3" flutter-version: "3.32.1"
- uses: actions/setup-java@v4 - uses: actions/setup-java@v4
with: with:
distribution: "zulu" distribution: "zulu"
@@ -108,7 +108,7 @@ jobs:
# uses: subosito/flutter-action@v2 # uses: subosito/flutter-action@v2
# with: # with:
# channel: 'stable' # channel: 'stable'
# flutter-version: '3.22.2' # flutter-version: '3.32.1'
# - name: Build # - name: Build
# run: dart run fl_build -p ios,mac # run: dart run fl_build -p ios,mac
# - name: Create Release # - name: Create Release

View File

@@ -12,17 +12,17 @@ extension SftpFileX on SftpFileMode {
UnixPerm toUnixPerm() { UnixPerm toUnixPerm() {
return UnixPerm( return UnixPerm(
user: RWX( user: UnixPermOp(
r: userRead, r: userRead,
w: userWrite, w: userWrite,
x: userExecute, x: userExecute,
), ),
group: RWX( group: UnixPermOp(
r: groupRead, r: groupRead,
w: groupWrite, w: groupWrite,
x: groupExecute, x: groupExecute,
), ),
other: RWX( other: UnixPermOp(
r: otherRead, r: otherRead,
w: otherWrite, w: otherWrite,
x: otherExecute, x: otherExecute,

View File

@@ -1,7 +1,8 @@
import 'dart:io'; import 'dart:io';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/app/backup.dart'; import 'package:server_box/data/model/app/bak/backup2.dart';
import 'package:server_box/data/model/app/bak/utils.dart';
const bakSync = BakSyncer._(); const bakSync = BakSyncer._();
@@ -11,12 +12,12 @@ final class BakSyncer extends SyncIface {
const BakSyncer._() : super(); const BakSyncer._() : super();
@override @override
Future<void> saveToFile() => Backup.backup(); Future<void> saveToFile() => BackupV2.backup();
@override @override
Future<Backup> fromFile(String path) async { Future<Mergeable> fromFile(String path) async {
final content = await File(path).readAsString(); final content = await File(path).readAsString();
return Backup.fromJsonString(content); return MergeableUtils.fromJsonString(content).$1;
} }
@override @override

View File

@@ -1,37 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'backup.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Backup _$BackupFromJson(Map<String, dynamic> json) => Backup(
version: (json['version'] as num).toInt(),
date: json['date'] as String,
spis: (json['spis'] as List<dynamic>)
.map((e) => Spi.fromJson(e as Map<String, dynamic>))
.toList(),
snippets: (json['snippets'] as List<dynamic>)
.map((e) => Snippet.fromJson(e as Map<String, dynamic>))
.toList(),
keys: (json['keys'] as List<dynamic>)
.map((e) => PrivateKeyInfo.fromJson(e as Map<String, dynamic>))
.toList(),
container: json['container'] as Map<String, dynamic>,
history: json['history'] as Map<String, dynamic>,
settings: json['settings'] as Map<String, dynamic>?,
lastModTime: (json['lastModTime'] as num?)?.toInt(),
);
Map<String, dynamic> _$BackupToJson(Backup instance) => <String, dynamic>{
'version': instance.version,
'date': instance.date,
'spis': instance.spis,
'snippets': instance.snippets,
'keys': instance.keys,
'container': instance.container,
'history': instance.history,
'lastModTime': instance.lastModTime,
'settings': instance.settings,
};

View File

@@ -46,7 +46,7 @@ class Backup implements Mergeable {
Map<String, dynamic> toJson() => _$BackupToJson(this); Map<String, dynamic> toJson() => _$BackupToJson(this);
static Future<Backup> loadFromStore() async { static Future<Backup> loadFromStore() async {
final lastModTime = Stores.lastModTime?.millisecondsSinceEpoch; final lastModTime = Stores.lastModTime;
return Backup( return Backup(
version: backupFormatVersion, version: backupFormatVersion,
date: DateTime.now().toString().split('.').firstOrNull ?? '', date: DateTime.now().toString().split('.').firstOrNull ?? '',
@@ -70,7 +70,7 @@ class Backup implements Mergeable {
@override @override
Future<void> merge({bool force = false}) async { Future<void> merge({bool force = false}) async {
final curTime = Stores.lastModTime?.millisecondsSinceEpoch ?? 0; final curTime = Stores.lastModTime;
final bakTime = lastModTime ?? 0; final bakTime = lastModTime ?? 0;
final shouldRestore = force || curTime < bakTime; final shouldRestore = force || curTime < bakTime;
if (!shouldRestore) { if (!shouldRestore) {
@@ -234,3 +234,4 @@ String _diyDecrypt(String raw) {
rethrow; rethrow;
} }
} }

View File

@@ -0,0 +1,37 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'backup.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Backup _$BackupFromJson(Map<String, dynamic> json) => Backup(
version: (json['version'] as num).toInt(),
date: json['date'] as String,
spis: (json['spis'] as List<dynamic>)
.map((e) => Spi.fromJson(e as Map<String, dynamic>))
.toList(),
snippets: (json['snippets'] as List<dynamic>)
.map((e) => Snippet.fromJson(e as Map<String, dynamic>))
.toList(),
keys: (json['keys'] as List<dynamic>)
.map((e) => PrivateKeyInfo.fromJson(e as Map<String, dynamic>))
.toList(),
container: json['container'] as Map<String, dynamic>,
history: json['history'] as Map<String, dynamic>,
settings: json['settings'] as Map<String, dynamic>?,
lastModTime: (json['lastModTime'] as num?)?.toInt(),
);
Map<String, dynamic> _$BackupToJson(Backup instance) => <String, dynamic>{
'version': instance.version,
'date': instance.date,
'spis': instance.spis,
'snippets': instance.snippets,
'keys': instance.keys,
'container': instance.container,
'history': instance.history,
'lastModTime': instance.lastModTime,
'settings': instance.settings,
};

View File

@@ -0,0 +1,89 @@
import 'dart:convert';
import 'dart:io';
import 'package:fl_lib/fl_lib.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:logging/logging.dart';
import 'package:server_box/data/res/misc.dart';
import 'package:server_box/data/res/store.dart';
part 'backup2.freezed.dart';
part 'backup2.g.dart';
final _loggerV2 = Logger('BackupV2');
@freezed
abstract class BackupV2 with _$BackupV2 implements Mergeable {
const BackupV2._();
/// Construct a backup with the latest format (v2).
///
/// All `Map<String, dynamic>` are:
/// ```json
/// {
/// "key1": Model{},
/// "_lastModTime": {
/// "key1": 1234567890,
/// },
/// }
/// ```
const factory BackupV2({
required int version,
required int date,
required Map<String, Object?> spis,
required Map<String, Object?> snippets,
required Map<String, Object?> keys,
required Map<String, Object?> container,
required Map<String, Object?> history,
required Map<String, Object?> settings,
}) = _BackupV2;
factory BackupV2.fromJson(Map<String, dynamic> json) => _$BackupV2FromJson(json);
@override
Future<void> merge({bool force = false}) async {
_loggerV2.info('Merging...');
// Merge each store
await Mergeable.mergeStore(backupData: spis, store: Stores.server, force: force);
await Mergeable.mergeStore(backupData: snippets, store: Stores.snippet, force: force);
await Mergeable.mergeStore(backupData: keys, store: Stores.key, force: force);
await Mergeable.mergeStore(backupData: container, store: Stores.container, force: force);
await Mergeable.mergeStore(backupData: history, store: Stores.history, force: force);
await Mergeable.mergeStore(backupData: settings, store: Stores.setting, force: force);
// Reload providers and notify listeners
Provider.reload();
RNodes.app.notify();
_loggerV2.info('Merge completed');
}
static const formatVer = 2;
static Future<BackupV2> loadFromStore() async {
return BackupV2(
version: formatVer,
date: DateTimeX.timestamp,
spis: Stores.server.getAllMap(includeInternalKeys: true),
snippets: Stores.snippet.getAllMap(includeInternalKeys: true),
keys: Stores.key.getAllMap(includeInternalKeys: true),
container: Stores.container.getAllMap(includeInternalKeys: true),
history: Stores.history.getAllMap(includeInternalKeys: true),
settings: Stores.setting.getAllMap(includeInternalKeys: true),
);
}
static Future<String> backup([String? name]) async {
final bak = await BackupV2.loadFromStore();
final result = json.encode(bak.toJson());
final path = Paths.doc.joinPath(name ?? Miscs.bakFileName);
await File(path).writeAsString(result);
return path;
}
factory BackupV2.fromJsonString(String jsonString) {
final map = json.decode(jsonString) as Map<String, dynamic>;
return BackupV2.fromJson(map);
}
}

View File

@@ -0,0 +1,372 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'backup2.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
BackupV2 _$BackupV2FromJson(Map<String, dynamic> json) {
return _BackupV2.fromJson(json);
}
/// @nodoc
mixin _$BackupV2 {
int get version => throw _privateConstructorUsedError;
int get date => throw _privateConstructorUsedError;
Map<String, Object?> get spis => throw _privateConstructorUsedError;
Map<String, Object?> get snippets => throw _privateConstructorUsedError;
Map<String, Object?> get keys => throw _privateConstructorUsedError;
Map<String, Object?> get container => throw _privateConstructorUsedError;
Map<String, Object?> get history => throw _privateConstructorUsedError;
Map<String, Object?> get settings => throw _privateConstructorUsedError;
/// Serializes this BackupV2 to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of BackupV2
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$BackupV2CopyWith<BackupV2> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $BackupV2CopyWith<$Res> {
factory $BackupV2CopyWith(BackupV2 value, $Res Function(BackupV2) then) =
_$BackupV2CopyWithImpl<$Res, BackupV2>;
@useResult
$Res call({
int version,
int date,
Map<String, Object?> spis,
Map<String, Object?> snippets,
Map<String, Object?> keys,
Map<String, Object?> container,
Map<String, Object?> history,
Map<String, Object?> settings,
});
}
/// @nodoc
class _$BackupV2CopyWithImpl<$Res, $Val extends BackupV2>
implements $BackupV2CopyWith<$Res> {
_$BackupV2CopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of BackupV2
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? version = null,
Object? date = null,
Object? spis = null,
Object? snippets = null,
Object? keys = null,
Object? container = null,
Object? history = null,
Object? settings = null,
}) {
return _then(
_value.copyWith(
version: null == version
? _value.version
: version // ignore: cast_nullable_to_non_nullable
as int,
date: null == date
? _value.date
: date // ignore: cast_nullable_to_non_nullable
as int,
spis: null == spis
? _value.spis
: spis // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
snippets: null == snippets
? _value.snippets
: snippets // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
keys: null == keys
? _value.keys
: keys // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
container: null == container
? _value.container
: container // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
history: null == history
? _value.history
: history // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
settings: null == settings
? _value.settings
: settings // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$BackupV2ImplCopyWith<$Res>
implements $BackupV2CopyWith<$Res> {
factory _$$BackupV2ImplCopyWith(
_$BackupV2Impl value,
$Res Function(_$BackupV2Impl) then,
) = __$$BackupV2ImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
int version,
int date,
Map<String, Object?> spis,
Map<String, Object?> snippets,
Map<String, Object?> keys,
Map<String, Object?> container,
Map<String, Object?> history,
Map<String, Object?> settings,
});
}
/// @nodoc
class __$$BackupV2ImplCopyWithImpl<$Res>
extends _$BackupV2CopyWithImpl<$Res, _$BackupV2Impl>
implements _$$BackupV2ImplCopyWith<$Res> {
__$$BackupV2ImplCopyWithImpl(
_$BackupV2Impl _value,
$Res Function(_$BackupV2Impl) _then,
) : super(_value, _then);
/// Create a copy of BackupV2
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? version = null,
Object? date = null,
Object? spis = null,
Object? snippets = null,
Object? keys = null,
Object? container = null,
Object? history = null,
Object? settings = null,
}) {
return _then(
_$BackupV2Impl(
version: null == version
? _value.version
: version // ignore: cast_nullable_to_non_nullable
as int,
date: null == date
? _value.date
: date // ignore: cast_nullable_to_non_nullable
as int,
spis: null == spis
? _value._spis
: spis // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
snippets: null == snippets
? _value._snippets
: snippets // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
keys: null == keys
? _value._keys
: keys // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
container: null == container
? _value._container
: container // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
history: null == history
? _value._history
: history // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
settings: null == settings
? _value._settings
: settings // ignore: cast_nullable_to_non_nullable
as Map<String, Object?>,
),
);
}
}
/// @nodoc
@JsonSerializable()
class _$BackupV2Impl extends _BackupV2 {
const _$BackupV2Impl({
required this.version,
required this.date,
required final Map<String, Object?> spis,
required final Map<String, Object?> snippets,
required final Map<String, Object?> keys,
required final Map<String, Object?> container,
required final Map<String, Object?> history,
required final Map<String, Object?> settings,
}) : _spis = spis,
_snippets = snippets,
_keys = keys,
_container = container,
_history = history,
_settings = settings,
super._();
factory _$BackupV2Impl.fromJson(Map<String, dynamic> json) =>
_$$BackupV2ImplFromJson(json);
@override
final int version;
@override
final int date;
final Map<String, Object?> _spis;
@override
Map<String, Object?> get spis {
if (_spis is EqualUnmodifiableMapView) return _spis;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_spis);
}
final Map<String, Object?> _snippets;
@override
Map<String, Object?> get snippets {
if (_snippets is EqualUnmodifiableMapView) return _snippets;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_snippets);
}
final Map<String, Object?> _keys;
@override
Map<String, Object?> get keys {
if (_keys is EqualUnmodifiableMapView) return _keys;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_keys);
}
final Map<String, Object?> _container;
@override
Map<String, Object?> get container {
if (_container is EqualUnmodifiableMapView) return _container;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_container);
}
final Map<String, Object?> _history;
@override
Map<String, Object?> get history {
if (_history is EqualUnmodifiableMapView) return _history;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_history);
}
final Map<String, Object?> _settings;
@override
Map<String, Object?> get settings {
if (_settings is EqualUnmodifiableMapView) return _settings;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_settings);
}
@override
String toString() {
return 'BackupV2(version: $version, date: $date, spis: $spis, snippets: $snippets, keys: $keys, container: $container, history: $history, settings: $settings)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$BackupV2Impl &&
(identical(other.version, version) || other.version == version) &&
(identical(other.date, date) || other.date == date) &&
const DeepCollectionEquality().equals(other._spis, _spis) &&
const DeepCollectionEquality().equals(other._snippets, _snippets) &&
const DeepCollectionEquality().equals(other._keys, _keys) &&
const DeepCollectionEquality().equals(
other._container,
_container,
) &&
const DeepCollectionEquality().equals(other._history, _history) &&
const DeepCollectionEquality().equals(other._settings, _settings));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
version,
date,
const DeepCollectionEquality().hash(_spis),
const DeepCollectionEquality().hash(_snippets),
const DeepCollectionEquality().hash(_keys),
const DeepCollectionEquality().hash(_container),
const DeepCollectionEquality().hash(_history),
const DeepCollectionEquality().hash(_settings),
);
/// Create a copy of BackupV2
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$BackupV2ImplCopyWith<_$BackupV2Impl> get copyWith =>
__$$BackupV2ImplCopyWithImpl<_$BackupV2Impl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$BackupV2ImplToJson(this);
}
}
abstract class _BackupV2 extends BackupV2 {
const factory _BackupV2({
required final int version,
required final int date,
required final Map<String, Object?> spis,
required final Map<String, Object?> snippets,
required final Map<String, Object?> keys,
required final Map<String, Object?> container,
required final Map<String, Object?> history,
required final Map<String, Object?> settings,
}) = _$BackupV2Impl;
const _BackupV2._() : super._();
factory _BackupV2.fromJson(Map<String, dynamic> json) =
_$BackupV2Impl.fromJson;
@override
int get version;
@override
int get date;
@override
Map<String, Object?> get spis;
@override
Map<String, Object?> get snippets;
@override
Map<String, Object?> get keys;
@override
Map<String, Object?> get container;
@override
Map<String, Object?> get history;
@override
Map<String, Object?> get settings;
/// Create a copy of BackupV2
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$BackupV2ImplCopyWith<_$BackupV2Impl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'backup2.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$BackupV2Impl _$$BackupV2ImplFromJson(Map<String, dynamic> json) =>
_$BackupV2Impl(
version: (json['version'] as num).toInt(),
date: (json['date'] as num).toInt(),
spis: json['spis'] as Map<String, dynamic>,
snippets: json['snippets'] as Map<String, dynamic>,
keys: json['keys'] as Map<String, dynamic>,
container: json['container'] as Map<String, dynamic>,
history: json['history'] as Map<String, dynamic>,
settings: json['settings'] as Map<String, dynamic>,
);
Map<String, dynamic> _$$BackupV2ImplToJson(_$BackupV2Impl instance) =>
<String, dynamic>{
'version': instance.version,
'date': instance.date,
'spis': instance.spis,
'snippets': instance.snippets,
'keys': instance.keys,
'container': instance.container,
'history': instance.history,
'settings': instance.settings,
};

View File

@@ -0,0 +1,15 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/app/bak/backup.dart';
import 'package:server_box/data/model/app/bak/backup2.dart';
abstract final class MergeableUtils {
static (Mergeable, String) fromJsonString(String json) {
try {
final bak = BackupV2.fromJsonString(json);
return (bak, DateTime.fromMillisecondsSinceEpoch(bak.date).hms());
} catch (e) {
final bak = Backup.fromJsonString(json);
return (bak, bak.date);
}
}
}

View File

@@ -1,26 +1,5 @@
import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/context/locale.dart';
import 'package:fl_lib/fl_lib.dart';
enum ErrFrom {
unknown,
apt,
docker,
sftp,
ssh,
status,
icloud,
webdav,
;
}
abstract class Err<T> {
final ErrFrom from;
final T type;
final String? message;
String? get solution;
Err({required this.from, required this.type, this.message});
}
enum SSHErrType { enum SSHErrType {
unknown, unknown,
@@ -35,7 +14,7 @@ enum SSHErrType {
} }
class SSHErr extends Err<SSHErrType> { class SSHErr extends Err<SSHErrType> {
SSHErr({required super.type, super.message}) : super(from: ErrFrom.ssh); SSHErr({required super.type, super.message});
@override @override
String? get solution => switch (type) { String? get solution => switch (type) {
@@ -45,11 +24,6 @@ class SSHErr extends Err<SSHErrType> {
SSHErrType.noPrivateKey => l10n.noPrivateKeyTip, SSHErrType.noPrivateKey => l10n.noPrivateKeyTip,
_ => null, _ => null,
}; };
@override
String toString() {
return 'SSHErr<$type>: $message';
}
} }
enum ContainerErrType { enum ContainerErrType {
@@ -65,16 +39,10 @@ enum ContainerErrType {
} }
class ContainerErr extends Err<ContainerErrType> { class ContainerErr extends Err<ContainerErrType> {
ContainerErr({required super.type, super.message}) ContainerErr({required super.type, super.message});
: super(from: ErrFrom.docker);
@override @override
String? get solution => null; String? get solution => null;
@override
String toString() {
return 'ContainerErr<$type>: $message';
}
} }
enum ICloudErrType { enum ICloudErrType {
@@ -84,15 +52,10 @@ enum ICloudErrType {
} }
class ICloudErr extends Err<ICloudErrType> { class ICloudErr extends Err<ICloudErrType> {
ICloudErr({required super.type, super.message}) : super(from: ErrFrom.icloud); ICloudErr({required super.type, super.message});
@override @override
String? get solution => null; String? get solution => null;
@override
String toString() {
return 'ICloudErr<$type>: $message';
}
} }
enum WebdavErrType { enum WebdavErrType {
@@ -102,15 +65,10 @@ enum WebdavErrType {
} }
class WebdavErr extends Err<WebdavErrType> { class WebdavErr extends Err<WebdavErrType> {
WebdavErr({required super.type, super.message}) : super(from: ErrFrom.webdav); WebdavErr({required super.type, super.message});
@override @override
String? get solution => null; String? get solution => null;
@override
String toString() {
return 'WebdavErr<$type>: $message';
}
} }
enum PveErrType { enum PveErrType {
@@ -121,13 +79,8 @@ enum PveErrType {
} }
class PveErr extends Err<PveErrType> { class PveErr extends Err<PveErrType> {
PveErr({required super.type, super.message}) : super(from: ErrFrom.status); PveErr({required super.type, super.message});
@override @override
String? get solution => null; String? get solution => null;
@override
String toString() {
return 'PveErr<$type>: $message';
}
} }

View File

@@ -1,36 +1,23 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:icons_plus/icons_plus.dart'; import 'package:icons_plus/icons_plus.dart';
import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/store.dart';
part 'server_func.g.dart';
@HiveType(typeId: 6)
enum ServerFuncBtn { enum ServerFuncBtn {
@HiveField(0) terminal(),
terminal._(), sftp(),
@HiveField(1) container(),
sftp._(), process(),
@HiveField(2) //pkg(),
container._(), snippet(),
@HiveField(3) iperf(),
process._(), // pve(),
//@HiveField(4) systemd(1058),
//pkg,
@HiveField(5)
snippet._(),
@HiveField(6)
iperf._(),
// @HiveField(7)
// pve,
@HiveField(8)
systemd._(1058),
; ;
final int? addedVersion; final int? addedVersion;
const ServerFuncBtn._([this.addedVersion]); const ServerFuncBtn([this.addedVersion]);
static void autoAddNewFuncs(int cur) { static void autoAddNewFuncs(int cur) {
if (cur >= systemd.addedVersion!) { if (cur >= systemd.addedVersion!) {

View File

@@ -1,71 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'server_func.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class ServerFuncBtnAdapter extends TypeAdapter<ServerFuncBtn> {
@override
final int typeId = 6;
@override
ServerFuncBtn read(BinaryReader reader) {
switch (reader.readByte()) {
case 0:
return ServerFuncBtn.terminal;
case 1:
return ServerFuncBtn.sftp;
case 2:
return ServerFuncBtn.container;
case 3:
return ServerFuncBtn.process;
case 5:
return ServerFuncBtn.snippet;
case 6:
return ServerFuncBtn.iperf;
case 8:
return ServerFuncBtn.systemd;
default:
return ServerFuncBtn.terminal;
}
}
@override
void write(BinaryWriter writer, ServerFuncBtn obj) {
switch (obj) {
case ServerFuncBtn.terminal:
writer.writeByte(0);
break;
case ServerFuncBtn.sftp:
writer.writeByte(1);
break;
case ServerFuncBtn.container:
writer.writeByte(2);
break;
case ServerFuncBtn.process:
writer.writeByte(3);
break;
case ServerFuncBtn.snippet:
writer.writeByte(5);
break;
case ServerFuncBtn.iperf:
writer.writeByte(6);
break;
case ServerFuncBtn.systemd:
writer.writeByte(8);
break;
}
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ServerFuncBtnAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -1,17 +1,10 @@
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/model/server/server.dart'; import 'package:server_box/data/model/server/server.dart';
part 'net_view.g.dart';
@HiveType(typeId: 5)
enum NetViewType { enum NetViewType {
@HiveField(0)
conn, conn,
@HiveField(1)
speed, speed,
@HiveField(2)
traffic; traffic;
NetViewType get next => switch (this) { NetViewType get next => switch (this) {

View File

@@ -1,51 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'net_view.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class NetViewTypeAdapter extends TypeAdapter<NetViewType> {
@override
final int typeId = 5;
@override
NetViewType read(BinaryReader reader) {
switch (reader.readByte()) {
case 0:
return NetViewType.conn;
case 1:
return NetViewType.speed;
case 2:
return NetViewType.traffic;
default:
return NetViewType.conn;
}
}
@override
void write(BinaryWriter writer, NetViewType obj) {
switch (obj) {
case NetViewType.conn:
writer.writeByte(0);
break;
case NetViewType.speed:
writer.writeByte(1);
break;
case NetViewType.traffic:
writer.writeByte(2);
break;
}
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is NetViewTypeAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -1,24 +0,0 @@
import 'dart:async';
class SyncResult<T, E> {
final List<T> up;
final List<T> down;
final Map<T, E> err;
const SyncResult({
required this.up,
required this.down,
required this.err,
});
@override
String toString() {
return 'SyncResult{up: $up, down: $down, err: $err}';
}
}
abstract class SyncIface<T> {
/// Merge [other] into [this], return [this] after merge.
/// Data in [other] has higher priority than [this].
FutureOr<void> sync(T other);
}

View File

@@ -1,32 +1,27 @@
import 'package:hive_flutter/adapters.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
part 'custom.g.dart'; part 'custom.g.dart';
@JsonSerializable() @JsonSerializable(includeIfNull: false)
@HiveType(typeId: 7)
final class ServerCustom { final class ServerCustom {
// @HiveField(0) // @HiveField(0)
// final String? temperature; // final String? temperature;
@HiveField(1)
final String? pveAddr; final String? pveAddr;
@HiveField(2, defaultValue: false)
final bool pveIgnoreCert; final bool pveIgnoreCert;
/// {"title": "cmd"} /// {"title": "cmd"}
@HiveField(3)
final Map<String, String>? cmds; final Map<String, String>? cmds;
@HiveField(4)
final String? preferTempDev; final String? preferTempDev;
@HiveField(5)
final String? logoUrl; final String? logoUrl;
/// The device name of the network interface displayed in the home server card. /// The device name of the network interface displayed in the home server card.
@HiveField(6)
final String? netDev; final String? netDev;
/// The directory where the script is stored. /// The directory where the script is stored.
@HiveField(7)
final String? scriptDir; final String? scriptDir;
const ServerCustom({ const ServerCustom({
@@ -40,8 +35,7 @@ final class ServerCustom {
this.scriptDir, this.scriptDir,
}); });
factory ServerCustom.fromJson(Map<String, dynamic> json) => factory ServerCustom.fromJson(Map<String, dynamic> json) => _$ServerCustomFromJson(json);
_$ServerCustomFromJson(json);
Map<String, dynamic> toJson() => _$ServerCustomToJson(this); Map<String, dynamic> toJson() => _$ServerCustomToJson(this);

View File

@@ -2,62 +2,6 @@
part of 'custom.dart'; part of 'custom.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class ServerCustomAdapter extends TypeAdapter<ServerCustom> {
@override
final int typeId = 7;
@override
ServerCustom read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return ServerCustom(
pveAddr: fields[1] as String?,
pveIgnoreCert: fields[2] == null ? false : fields[2] as bool,
cmds: (fields[3] as Map?)?.cast<String, String>(),
preferTempDev: fields[4] as String?,
logoUrl: fields[5] as String?,
netDev: fields[6] as String?,
scriptDir: fields[7] as String?,
);
}
@override
void write(BinaryWriter writer, ServerCustom obj) {
writer
..writeByte(7)
..writeByte(1)
..write(obj.pveAddr)
..writeByte(2)
..write(obj.pveIgnoreCert)
..writeByte(3)
..write(obj.cmds)
..writeByte(4)
..write(obj.preferTempDev)
..writeByte(5)
..write(obj.logoUrl)
..writeByte(6)
..write(obj.netDev)
..writeByte(7)
..write(obj.scriptDir);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ServerCustomAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// ************************************************************************** // **************************************************************************
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
@@ -72,15 +16,15 @@ ServerCustom _$ServerCustomFromJson(Map<String, dynamic> json) => ServerCustom(
logoUrl: json['logoUrl'] as String?, logoUrl: json['logoUrl'] as String?,
netDev: json['netDev'] as String?, netDev: json['netDev'] as String?,
scriptDir: json['scriptDir'] as String?, scriptDir: json['scriptDir'] as String?,
); );
Map<String, dynamic> _$ServerCustomToJson(ServerCustom instance) => Map<String, dynamic> _$ServerCustomToJson(ServerCustom instance) =>
<String, dynamic>{ <String, dynamic>{
'pveAddr': instance.pveAddr, if (instance.pveAddr case final value?) 'pveAddr': value,
'pveIgnoreCert': instance.pveIgnoreCert, 'pveIgnoreCert': instance.pveIgnoreCert,
'cmds': instance.cmds, if (instance.cmds case final value?) 'cmds': value,
'preferTempDev': instance.preferTempDev, if (instance.preferTempDev case final value?) 'preferTempDev': value,
'logoUrl': instance.logoUrl, if (instance.logoUrl case final value?) 'logoUrl': value,
'netDev': instance.netDev, if (instance.netDev case final value?) 'netDev': value,
'scriptDir': instance.scriptDir, if (instance.scriptDir case final value?) 'scriptDir': value,
}; };

View File

@@ -1,15 +1,11 @@
import 'package:hive_flutter/hive_flutter.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
part 'private_key_info.g.dart'; part 'private_key_info.g.dart';
@JsonSerializable() @JsonSerializable()
@HiveType(typeId: 1)
class PrivateKeyInfo { class PrivateKeyInfo {
@HiveField(0)
final String id; final String id;
@JsonKey(name: 'private_key') @JsonKey(name: 'private_key')
@HiveField(1)
final String key; final String key;
const PrivateKeyInfo({ const PrivateKeyInfo({
@@ -17,8 +13,7 @@ class PrivateKeyInfo {
required this.key, required this.key,
}); });
factory PrivateKeyInfo.fromJson(Map<String, dynamic> json) => factory PrivateKeyInfo.fromJson(Map<String, dynamic> json) => _$PrivateKeyInfoFromJson(json);
_$PrivateKeyInfoFromJson(json);
Map<String, dynamic> toJson() => _$PrivateKeyInfoToJson(this); Map<String, dynamic> toJson() => _$PrivateKeyInfoToJson(this);

View File

@@ -2,47 +2,6 @@
part of 'private_key_info.dart'; part of 'private_key_info.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class PrivateKeyInfoAdapter extends TypeAdapter<PrivateKeyInfo> {
@override
final int typeId = 1;
@override
PrivateKeyInfo read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return PrivateKeyInfo(
id: fields[0] as String,
key: fields[1] as String,
);
}
@override
void write(BinaryWriter writer, PrivateKeyInfo obj) {
writer
..writeByte(2)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.key);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is PrivateKeyInfoAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// ************************************************************************** // **************************************************************************
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
@@ -54,7 +13,4 @@ PrivateKeyInfo _$PrivateKeyInfoFromJson(Map<String, dynamic> json) =>
); );
Map<String, dynamic> _$PrivateKeyInfoToJson(PrivateKeyInfo instance) => Map<String, dynamic> _$PrivateKeyInfoToJson(PrivateKeyInfo instance) =>
<String, dynamic>{ <String, dynamic>{'id': instance.id, 'private_key': instance.key};
'id': instance.id,
'private_key': instance.key,
};

View File

@@ -1,5 +1,5 @@
import 'package:dartssh2/dartssh2.dart'; import 'package:dartssh2/dartssh2.dart';
import 'package:server_box/data/model/app/error.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/app/shell_func.dart'; import 'package:server_box/data/model/app/shell_func.dart';
import 'package:server_box/data/model/server/battery.dart'; import 'package:server_box/data/model/server/battery.dart';
import 'package:server_box/data/model/server/conn.dart'; import 'package:server_box/data/model/server/conn.dart';

View File

@@ -2,7 +2,7 @@ import 'dart:convert';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_ce_flutter/hive_flutter.dart';
import 'package:server_box/data/model/server/custom.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.dart';
import 'package:server_box/data/model/server/wol_cfg.dart'; import 'package:server_box/data/model/server/wol_cfg.dart';
@@ -20,31 +20,31 @@ part 'server_private_info.freezed.dart';
/// Some params named as `spi` in the codebase which is the abbreviation of `ServerPrivateInfo`. /// Some params named as `spi` in the codebase which is the abbreviation of `ServerPrivateInfo`.
/// ///
/// Nowaday, more fields are added to this class, and it's renamed to `Spi`. /// Nowaday, more fields are added to this class, and it's renamed to `Spi`.
@freezed @Freezed(fromJson: false)
@HiveType(typeId: 3) @JsonSerializable(includeIfNull: false)
class Spi with _$Spi { class Spi with _$Spi {
const Spi._(); const Spi._();
const factory Spi({ const factory Spi({
@HiveField(0) required String name, required String name,
@HiveField(1) required String ip, required String ip,
@HiveField(2) required int port, required int port,
@HiveField(3) required String user, required String user,
@HiveField(4) String? pwd, String? pwd,
/// [id] of private key /// [id] of private key
@JsonKey(name: 'pubKeyId') @HiveField(5) String? keyId, @JsonKey(name: 'pubKeyId') String? keyId,
@HiveField(6) List<String>? tags, List<String>? tags,
@HiveField(7) String? alterUrl, String? alterUrl,
@HiveField(8, defaultValue: true) @Default(true) bool autoConnect, @Default(true) @JsonKey(defaultValue: true) bool autoConnect,
/// [id] of the jump server /// [id] of the jump server
@HiveField(9) String? jumpId, String? jumpId,
@HiveField(10) ServerCustom? custom, ServerCustom? custom,
@HiveField(11) WakeOnLanCfg? wolCfg, WakeOnLanCfg? wolCfg,
/// It only applies to SSH terminal. /// It only applies to SSH terminal.
@HiveField(12) Map<String, String>? envs, Map<String, String>? envs,
@JsonKey(fromJson: Spi.parseId) @HiveField(13, defaultValue: '') required String id, @JsonKey(fromJson: Spi.parseId) @HiveField(13, defaultValue: '') required String id,
}) = _Spi; }) = _Spi;

View File

@@ -12,46 +12,31 @@ part of 'server_private_info.dart';
T _$identity<T>(T value) => value; T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError( final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
Spi _$SpiFromJson(Map<String, dynamic> json) {
return _Spi.fromJson(json);
}
/// @nodoc /// @nodoc
mixin _$Spi { mixin _$Spi {
@HiveField(0)
String get name => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError;
@HiveField(1)
String get ip => throw _privateConstructorUsedError; String get ip => throw _privateConstructorUsedError;
@HiveField(2)
int get port => throw _privateConstructorUsedError; int get port => throw _privateConstructorUsedError;
@HiveField(3)
String get user => throw _privateConstructorUsedError; String get user => throw _privateConstructorUsedError;
@HiveField(4)
String? get pwd => throw _privateConstructorUsedError; String? get pwd => throw _privateConstructorUsedError;
/// [id] of private key /// [id] of private key
@JsonKey(name: 'pubKeyId') @JsonKey(name: 'pubKeyId')
@HiveField(5)
String? get keyId => throw _privateConstructorUsedError; String? get keyId => throw _privateConstructorUsedError;
@HiveField(6)
List<String>? get tags => throw _privateConstructorUsedError; List<String>? get tags => throw _privateConstructorUsedError;
@HiveField(7)
String? get alterUrl => throw _privateConstructorUsedError; String? get alterUrl => throw _privateConstructorUsedError;
@HiveField(8, defaultValue: true) @JsonKey(defaultValue: true)
bool get autoConnect => throw _privateConstructorUsedError; bool get autoConnect => throw _privateConstructorUsedError;
/// [id] of the jump server /// [id] of the jump server
@HiveField(9)
String? get jumpId => throw _privateConstructorUsedError; String? get jumpId => throw _privateConstructorUsedError;
@HiveField(10)
ServerCustom? get custom => throw _privateConstructorUsedError; ServerCustom? get custom => throw _privateConstructorUsedError;
@HiveField(11)
WakeOnLanCfg? get wolCfg => throw _privateConstructorUsedError; WakeOnLanCfg? get wolCfg => throw _privateConstructorUsedError;
/// It only applies to SSH terminal. /// It only applies to SSH terminal.
@HiveField(12)
Map<String, String>? get envs => throw _privateConstructorUsedError; Map<String, String>? get envs => throw _privateConstructorUsedError;
@JsonKey(fromJson: Spi.parseId) @JsonKey(fromJson: Spi.parseId)
@HiveField(13, defaultValue: '') @HiveField(13, defaultValue: '')
@@ -71,23 +56,22 @@ abstract class $SpiCopyWith<$Res> {
factory $SpiCopyWith(Spi value, $Res Function(Spi) then) = factory $SpiCopyWith(Spi value, $Res Function(Spi) then) =
_$SpiCopyWithImpl<$Res, Spi>; _$SpiCopyWithImpl<$Res, Spi>;
@useResult @useResult
$Res call( $Res call({
{@HiveField(0) String name, String name,
@HiveField(1) String ip, String ip,
@HiveField(2) int port, int port,
@HiveField(3) String user, String user,
@HiveField(4) String? pwd, String? pwd,
@JsonKey(name: 'pubKeyId') @HiveField(5) String? keyId, @JsonKey(name: 'pubKeyId') String? keyId,
@HiveField(6) List<String>? tags, List<String>? tags,
@HiveField(7) String? alterUrl, String? alterUrl,
@HiveField(8, defaultValue: true) bool autoConnect, @JsonKey(defaultValue: true) bool autoConnect,
@HiveField(9) String? jumpId, String? jumpId,
@HiveField(10) ServerCustom? custom, ServerCustom? custom,
@HiveField(11) WakeOnLanCfg? wolCfg, WakeOnLanCfg? wolCfg,
@HiveField(12) Map<String, String>? envs, Map<String, String>? envs,
@JsonKey(fromJson: Spi.parseId) @JsonKey(fromJson: Spi.parseId) @HiveField(13, defaultValue: '') String id,
@HiveField(13, defaultValue: '') });
String id});
} }
/// @nodoc /// @nodoc
@@ -119,7 +103,8 @@ class _$SpiCopyWithImpl<$Res, $Val extends Spi> implements $SpiCopyWith<$Res> {
Object? envs = freezed, Object? envs = freezed,
Object? id = null, Object? id = null,
}) { }) {
return _then(_value.copyWith( return _then(
_value.copyWith(
name: null == name name: null == name
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
@@ -176,7 +161,9 @@ class _$SpiCopyWithImpl<$Res, $Val extends Spi> implements $SpiCopyWith<$Res> {
? _value.id ? _value.id
: id // ignore: cast_nullable_to_non_nullable : id // ignore: cast_nullable_to_non_nullable
as String, as String,
) as $Val); )
as $Val,
);
} }
} }
@@ -186,23 +173,22 @@ abstract class _$$SpiImplCopyWith<$Res> implements $SpiCopyWith<$Res> {
__$$SpiImplCopyWithImpl<$Res>; __$$SpiImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call( $Res call({
{@HiveField(0) String name, String name,
@HiveField(1) String ip, String ip,
@HiveField(2) int port, int port,
@HiveField(3) String user, String user,
@HiveField(4) String? pwd, String? pwd,
@JsonKey(name: 'pubKeyId') @HiveField(5) String? keyId, @JsonKey(name: 'pubKeyId') String? keyId,
@HiveField(6) List<String>? tags, List<String>? tags,
@HiveField(7) String? alterUrl, String? alterUrl,
@HiveField(8, defaultValue: true) bool autoConnect, @JsonKey(defaultValue: true) bool autoConnect,
@HiveField(9) String? jumpId, String? jumpId,
@HiveField(10) ServerCustom? custom, ServerCustom? custom,
@HiveField(11) WakeOnLanCfg? wolCfg, WakeOnLanCfg? wolCfg,
@HiveField(12) Map<String, String>? envs, Map<String, String>? envs,
@JsonKey(fromJson: Spi.parseId) @JsonKey(fromJson: Spi.parseId) @HiveField(13, defaultValue: '') String id,
@HiveField(13, defaultValue: '') });
String id});
} }
/// @nodoc /// @nodoc
@@ -231,7 +217,8 @@ class __$$SpiImplCopyWithImpl<$Res> extends _$SpiCopyWithImpl<$Res, _$SpiImpl>
Object? envs = freezed, Object? envs = freezed,
Object? id = null, Object? id = null,
}) { }) {
return _then(_$SpiImpl( return _then(
_$SpiImpl(
name: null == name name: null == name
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
@@ -288,61 +275,52 @@ class __$$SpiImplCopyWithImpl<$Res> extends _$SpiCopyWithImpl<$Res, _$SpiImpl>
? _value.id ? _value.id
: id // ignore: cast_nullable_to_non_nullable : id // ignore: cast_nullable_to_non_nullable
as String, as String,
)); ),
);
} }
} }
/// @nodoc /// @nodoc
@JsonSerializable() @JsonSerializable(createFactory: false)
class _$SpiImpl extends _Spi { class _$SpiImpl extends _Spi {
const _$SpiImpl( const _$SpiImpl({
{@HiveField(0) required this.name, required this.name,
@HiveField(1) required this.ip, required this.ip,
@HiveField(2) required this.port, required this.port,
@HiveField(3) required this.user, required this.user,
@HiveField(4) this.pwd, this.pwd,
@JsonKey(name: 'pubKeyId') @HiveField(5) this.keyId, @JsonKey(name: 'pubKeyId') this.keyId,
@HiveField(6) final List<String>? tags, final List<String>? tags,
@HiveField(7) this.alterUrl, this.alterUrl,
@HiveField(8, defaultValue: true) this.autoConnect = true, @JsonKey(defaultValue: true) this.autoConnect = true,
@HiveField(9) this.jumpId, this.jumpId,
@HiveField(10) this.custom, this.custom,
@HiveField(11) this.wolCfg, this.wolCfg,
@HiveField(12) final Map<String, String>? envs, final Map<String, String>? envs,
@JsonKey(fromJson: Spi.parseId) @JsonKey(fromJson: Spi.parseId)
@HiveField(13, defaultValue: '') @HiveField(13, defaultValue: '')
required this.id}) required this.id,
: _tags = tags, }) : _tags = tags,
_envs = envs, _envs = envs,
super._(); super._();
factory _$SpiImpl.fromJson(Map<String, dynamic> json) =>
_$$SpiImplFromJson(json);
@override @override
@HiveField(0)
final String name; final String name;
@override @override
@HiveField(1)
final String ip; final String ip;
@override @override
@HiveField(2)
final int port; final int port;
@override @override
@HiveField(3)
final String user; final String user;
@override @override
@HiveField(4)
final String? pwd; final String? pwd;
/// [id] of private key /// [id] of private key
@override @override
@JsonKey(name: 'pubKeyId') @JsonKey(name: 'pubKeyId')
@HiveField(5)
final String? keyId; final String? keyId;
final List<String>? _tags; final List<String>? _tags;
@override @override
@HiveField(6)
List<String>? get tags { List<String>? get tags {
final value = _tags; final value = _tags;
if (value == null) return null; if (value == null) return null;
@@ -352,22 +330,17 @@ class _$SpiImpl extends _Spi {
} }
@override @override
@HiveField(7)
final String? alterUrl; final String? alterUrl;
@override @override
@JsonKey() @JsonKey(defaultValue: true)
@HiveField(8, defaultValue: true)
final bool autoConnect; final bool autoConnect;
/// [id] of the jump server /// [id] of the jump server
@override @override
@HiveField(9)
final String? jumpId; final String? jumpId;
@override @override
@HiveField(10)
final ServerCustom? custom; final ServerCustom? custom;
@override @override
@HiveField(11)
final WakeOnLanCfg? wolCfg; final WakeOnLanCfg? wolCfg;
/// It only applies to SSH terminal. /// It only applies to SSH terminal.
@@ -375,7 +348,6 @@ class _$SpiImpl extends _Spi {
/// It only applies to SSH terminal. /// It only applies to SSH terminal.
@override @override
@HiveField(12)
Map<String, String>? get envs { Map<String, String>? get envs {
final value = _envs; final value = _envs;
if (value == null) return null; if (value == null) return null;
@@ -429,7 +401,8 @@ class _$SpiImpl extends _Spi {
custom, custom,
wolCfg, wolCfg,
const DeepCollectionEquality().hash(_envs), const DeepCollectionEquality().hash(_envs),
id); id,
);
/// Create a copy of Spi /// Create a copy of Spi
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -441,79 +414,64 @@ class _$SpiImpl extends _Spi {
@override @override
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return _$$SpiImplToJson( return _$$SpiImplToJson(this);
this,
);
} }
} }
abstract class _Spi extends Spi { abstract class _Spi extends Spi {
const factory _Spi( const factory _Spi({
{@HiveField(0) required final String name, required final String name,
@HiveField(1) required final String ip, required final String ip,
@HiveField(2) required final int port, required final int port,
@HiveField(3) required final String user, required final String user,
@HiveField(4) final String? pwd, final String? pwd,
@JsonKey(name: 'pubKeyId') @HiveField(5) final String? keyId, @JsonKey(name: 'pubKeyId') final String? keyId,
@HiveField(6) final List<String>? tags, final List<String>? tags,
@HiveField(7) final String? alterUrl, final String? alterUrl,
@HiveField(8, defaultValue: true) final bool autoConnect, @JsonKey(defaultValue: true) final bool autoConnect,
@HiveField(9) final String? jumpId, final String? jumpId,
@HiveField(10) final ServerCustom? custom, final ServerCustom? custom,
@HiveField(11) final WakeOnLanCfg? wolCfg, final WakeOnLanCfg? wolCfg,
@HiveField(12) final Map<String, String>? envs, final Map<String, String>? envs,
@JsonKey(fromJson: Spi.parseId) @JsonKey(fromJson: Spi.parseId)
@HiveField(13, defaultValue: '') @HiveField(13, defaultValue: '')
required final String id}) = _$SpiImpl; required final String id,
}) = _$SpiImpl;
const _Spi._() : super._(); const _Spi._() : super._();
factory _Spi.fromJson(Map<String, dynamic> json) = _$SpiImpl.fromJson;
@override @override
@HiveField(0)
String get name; String get name;
@override @override
@HiveField(1)
String get ip; String get ip;
@override @override
@HiveField(2)
int get port; int get port;
@override @override
@HiveField(3)
String get user; String get user;
@override @override
@HiveField(4)
String? get pwd; String? get pwd;
/// [id] of private key /// [id] of private key
@override @override
@JsonKey(name: 'pubKeyId') @JsonKey(name: 'pubKeyId')
@HiveField(5)
String? get keyId; String? get keyId;
@override @override
@HiveField(6)
List<String>? get tags; List<String>? get tags;
@override @override
@HiveField(7)
String? get alterUrl; String? get alterUrl;
@override @override
@HiveField(8, defaultValue: true) @JsonKey(defaultValue: true)
bool get autoConnect; bool get autoConnect;
/// [id] of the jump server /// [id] of the jump server
@override @override
@HiveField(9)
String? get jumpId; String? get jumpId;
@override @override
@HiveField(10)
ServerCustom? get custom; ServerCustom? get custom;
@override @override
@HiveField(11)
WakeOnLanCfg? get wolCfg; WakeOnLanCfg? get wolCfg;
/// It only applies to SSH terminal. /// It only applies to SSH terminal.
@override @override
@HiveField(12)
Map<String, String>? get envs; Map<String, String>? get envs;
@override @override
@JsonKey(fromJson: Spi.parseId) @JsonKey(fromJson: Spi.parseId)

View File

@@ -2,88 +2,11 @@
part of 'server_private_info.dart'; part of 'server_private_info.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class SpiAdapter extends TypeAdapter<Spi> {
@override
final int typeId = 3;
@override
Spi read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Spi(
name: fields[0] as String,
ip: fields[1] as String,
port: fields[2] as int,
user: fields[3] as String,
pwd: fields[4] as String?,
keyId: fields[5] as String?,
tags: (fields[6] as List?)?.cast<String>(),
alterUrl: fields[7] as String?,
autoConnect: fields[8] == null ? true : fields[8] as bool,
jumpId: fields[9] as String?,
custom: fields[10] as ServerCustom?,
wolCfg: fields[11] as WakeOnLanCfg?,
envs: (fields[12] as Map?)?.cast<String, String>(),
id: fields[13] == null ? '' : fields[13] as String,
);
}
@override
void write(BinaryWriter writer, Spi obj) {
writer
..writeByte(14)
..writeByte(0)
..write(obj.name)
..writeByte(1)
..write(obj.ip)
..writeByte(2)
..write(obj.port)
..writeByte(3)
..write(obj.user)
..writeByte(4)
..write(obj.pwd)
..writeByte(5)
..write(obj.keyId)
..writeByte(6)
..write(obj.tags)
..writeByte(7)
..write(obj.alterUrl)
..writeByte(8)
..write(obj.autoConnect)
..writeByte(9)
..write(obj.jumpId)
..writeByte(10)
..write(obj.custom)
..writeByte(11)
..write(obj.wolCfg)
..writeByte(12)
..write(obj.envs)
..writeByte(13)
..write(obj.id);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SpiAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// ************************************************************************** // **************************************************************************
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
_$SpiImpl _$$SpiImplFromJson(Map<String, dynamic> json) => _$SpiImpl( Spi _$SpiFromJson(Map<String, dynamic> json) => Spi(
name: json['name'] as String, name: json['name'] as String,
ip: json['ip'] as String, ip: json['ip'] as String,
port: (json['port'] as num).toInt(), port: (json['port'] as num).toInt(),
@@ -104,7 +27,24 @@ _$SpiImpl _$$SpiImplFromJson(Map<String, dynamic> json) => _$SpiImpl(
(k, e) => MapEntry(k, e as String), (k, e) => MapEntry(k, e as String),
), ),
id: Spi.parseId(json['id']), id: Spi.parseId(json['id']),
); );
Map<String, dynamic> _$SpiToJson(Spi instance) => <String, dynamic>{
'name': instance.name,
'ip': instance.ip,
'port': instance.port,
'user': instance.user,
if (instance.pwd case final value?) 'pwd': value,
if (instance.keyId case final value?) 'pubKeyId': value,
if (instance.tags case final value?) 'tags': value,
if (instance.alterUrl case final value?) 'alterUrl': value,
'autoConnect': instance.autoConnect,
if (instance.jumpId case final value?) 'jumpId': value,
if (instance.custom case final value?) 'custom': value,
if (instance.wolCfg case final value?) 'wolCfg': value,
if (instance.envs case final value?) 'envs': value,
'id': instance.id,
};
Map<String, dynamic> _$$SpiImplToJson(_$SpiImpl instance) => <String, dynamic>{ Map<String, dynamic> _$$SpiImplToJson(_$SpiImpl instance) => <String, dynamic>{
'name': instance.name, 'name': instance.name,
@@ -121,4 +61,4 @@ Map<String, dynamic> _$$SpiImplToJson(_$SpiImpl instance) => <String, dynamic>{
'wolCfg': instance.wolCfg, 'wolCfg': instance.wolCfg,
'envs': instance.envs, 'envs': instance.envs,
'id': instance.id, 'id': instance.id,
}; };

View File

@@ -2,7 +2,6 @@ import 'dart:async';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:xterm/core.dart'; import 'package:xterm/core.dart';
@@ -10,16 +9,15 @@ part 'snippet.g.dart';
part 'snippet.freezed.dart'; part 'snippet.freezed.dart';
@freezed @freezed
@HiveType(typeId: 2)
class Snippet with _$Snippet { class Snippet with _$Snippet {
const factory Snippet({ const factory Snippet({
@HiveField(0) required String name, required String name,
@HiveField(1) required String script, required String script,
@HiveField(2) List<String>? tags, List<String>? tags,
@HiveField(3) String? note, String? note,
/// List of server id that this snippet should be auto run on /// List of server id that this snippet should be auto run on
@HiveField(4) List<String>? autoRunOn, List<String>? autoRunOn,
}) = _Snippet; }) = _Snippet;
factory Snippet.fromJson(Map<String, dynamic> json) => _$SnippetFromJson(json); factory Snippet.fromJson(Map<String, dynamic> json) => _$SnippetFromJson(json);

View File

@@ -12,7 +12,8 @@ part of 'snippet.dart';
T _$identity<T>(T value) => value; T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError( final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
Snippet _$SnippetFromJson(Map<String, dynamic> json) { Snippet _$SnippetFromJson(Map<String, dynamic> json) {
return _Snippet.fromJson(json); return _Snippet.fromJson(json);
@@ -20,17 +21,12 @@ Snippet _$SnippetFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$Snippet { mixin _$Snippet {
@HiveField(0)
String get name => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError;
@HiveField(1)
String get script => throw _privateConstructorUsedError; String get script => throw _privateConstructorUsedError;
@HiveField(2)
List<String>? get tags => throw _privateConstructorUsedError; List<String>? get tags => throw _privateConstructorUsedError;
@HiveField(3)
String? get note => throw _privateConstructorUsedError; String? get note => throw _privateConstructorUsedError;
/// List of server id that this snippet should be auto run on /// List of server id that this snippet should be auto run on
@HiveField(4)
List<String>? get autoRunOn => throw _privateConstructorUsedError; List<String>? get autoRunOn => throw _privateConstructorUsedError;
/// Serializes this Snippet to a JSON map. /// Serializes this Snippet to a JSON map.
@@ -47,12 +43,13 @@ abstract class $SnippetCopyWith<$Res> {
factory $SnippetCopyWith(Snippet value, $Res Function(Snippet) then) = factory $SnippetCopyWith(Snippet value, $Res Function(Snippet) then) =
_$SnippetCopyWithImpl<$Res, Snippet>; _$SnippetCopyWithImpl<$Res, Snippet>;
@useResult @useResult
$Res call( $Res call({
{@HiveField(0) String name, String name,
@HiveField(1) String script, String script,
@HiveField(2) List<String>? tags, List<String>? tags,
@HiveField(3) String? note, String? note,
@HiveField(4) List<String>? autoRunOn}); List<String>? autoRunOn,
});
} }
/// @nodoc /// @nodoc
@@ -76,7 +73,8 @@ class _$SnippetCopyWithImpl<$Res, $Val extends Snippet>
Object? note = freezed, Object? note = freezed,
Object? autoRunOn = freezed, Object? autoRunOn = freezed,
}) { }) {
return _then(_value.copyWith( return _then(
_value.copyWith(
name: null == name name: null == name
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
@@ -97,23 +95,27 @@ class _$SnippetCopyWithImpl<$Res, $Val extends Snippet>
? _value.autoRunOn ? _value.autoRunOn
: autoRunOn // ignore: cast_nullable_to_non_nullable : autoRunOn // ignore: cast_nullable_to_non_nullable
as List<String>?, as List<String>?,
) as $Val); )
as $Val,
);
} }
} }
/// @nodoc /// @nodoc
abstract class _$$SnippetImplCopyWith<$Res> implements $SnippetCopyWith<$Res> { abstract class _$$SnippetImplCopyWith<$Res> implements $SnippetCopyWith<$Res> {
factory _$$SnippetImplCopyWith( factory _$$SnippetImplCopyWith(
_$SnippetImpl value, $Res Function(_$SnippetImpl) then) = _$SnippetImpl value,
__$$SnippetImplCopyWithImpl<$Res>; $Res Function(_$SnippetImpl) then,
) = __$$SnippetImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call( $Res call({
{@HiveField(0) String name, String name,
@HiveField(1) String script, String script,
@HiveField(2) List<String>? tags, List<String>? tags,
@HiveField(3) String? note, String? note,
@HiveField(4) List<String>? autoRunOn}); List<String>? autoRunOn,
});
} }
/// @nodoc /// @nodoc
@@ -121,8 +123,9 @@ class __$$SnippetImplCopyWithImpl<$Res>
extends _$SnippetCopyWithImpl<$Res, _$SnippetImpl> extends _$SnippetCopyWithImpl<$Res, _$SnippetImpl>
implements _$$SnippetImplCopyWith<$Res> { implements _$$SnippetImplCopyWith<$Res> {
__$$SnippetImplCopyWithImpl( __$$SnippetImplCopyWithImpl(
_$SnippetImpl _value, $Res Function(_$SnippetImpl) _then) _$SnippetImpl _value,
: super(_value, _then); $Res Function(_$SnippetImpl) _then,
) : super(_value, _then);
/// Create a copy of Snippet /// Create a copy of Snippet
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -135,7 +138,8 @@ class __$$SnippetImplCopyWithImpl<$Res>
Object? note = freezed, Object? note = freezed,
Object? autoRunOn = freezed, Object? autoRunOn = freezed,
}) { }) {
return _then(_$SnippetImpl( return _then(
_$SnippetImpl(
name: null == name name: null == name
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
@@ -156,34 +160,32 @@ class __$$SnippetImplCopyWithImpl<$Res>
? _value._autoRunOn ? _value._autoRunOn
: autoRunOn // ignore: cast_nullable_to_non_nullable : autoRunOn // ignore: cast_nullable_to_non_nullable
as List<String>?, as List<String>?,
)); ),
);
} }
} }
/// @nodoc /// @nodoc
@JsonSerializable() @JsonSerializable()
class _$SnippetImpl implements _Snippet { class _$SnippetImpl implements _Snippet {
const _$SnippetImpl( const _$SnippetImpl({
{@HiveField(0) required this.name, required this.name,
@HiveField(1) required this.script, required this.script,
@HiveField(2) final List<String>? tags, final List<String>? tags,
@HiveField(3) this.note, this.note,
@HiveField(4) final List<String>? autoRunOn}) final List<String>? autoRunOn,
: _tags = tags, }) : _tags = tags,
_autoRunOn = autoRunOn; _autoRunOn = autoRunOn;
factory _$SnippetImpl.fromJson(Map<String, dynamic> json) => factory _$SnippetImpl.fromJson(Map<String, dynamic> json) =>
_$$SnippetImplFromJson(json); _$$SnippetImplFromJson(json);
@override @override
@HiveField(0)
final String name; final String name;
@override @override
@HiveField(1)
final String script; final String script;
final List<String>? _tags; final List<String>? _tags;
@override @override
@HiveField(2)
List<String>? get tags { List<String>? get tags {
final value = _tags; final value = _tags;
if (value == null) return null; if (value == null) return null;
@@ -193,7 +195,6 @@ class _$SnippetImpl implements _Snippet {
} }
@override @override
@HiveField(3)
final String? note; final String? note;
/// List of server id that this snippet should be auto run on /// List of server id that this snippet should be auto run on
@@ -201,7 +202,6 @@ class _$SnippetImpl implements _Snippet {
/// List of server id that this snippet should be auto run on /// List of server id that this snippet should be auto run on
@override @override
@HiveField(4)
List<String>? get autoRunOn { List<String>? get autoRunOn {
final value = _autoRunOn; final value = _autoRunOn;
if (value == null) return null; if (value == null) return null;
@@ -224,8 +224,10 @@ class _$SnippetImpl implements _Snippet {
(identical(other.script, script) || other.script == script) && (identical(other.script, script) || other.script == script) &&
const DeepCollectionEquality().equals(other._tags, _tags) && const DeepCollectionEquality().equals(other._tags, _tags) &&
(identical(other.note, note) || other.note == note) && (identical(other.note, note) || other.note == note) &&
const DeepCollectionEquality() const DeepCollectionEquality().equals(
.equals(other._autoRunOn, _autoRunOn)); other._autoRunOn,
_autoRunOn,
));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@@ -236,7 +238,8 @@ class _$SnippetImpl implements _Snippet {
script, script,
const DeepCollectionEquality().hash(_tags), const DeepCollectionEquality().hash(_tags),
note, note,
const DeepCollectionEquality().hash(_autoRunOn)); const DeepCollectionEquality().hash(_autoRunOn),
);
/// Create a copy of Snippet /// Create a copy of Snippet
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@@ -248,38 +251,32 @@ class _$SnippetImpl implements _Snippet {
@override @override
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return _$$SnippetImplToJson( return _$$SnippetImplToJson(this);
this,
);
} }
} }
abstract class _Snippet implements Snippet { abstract class _Snippet implements Snippet {
const factory _Snippet( const factory _Snippet({
{@HiveField(0) required final String name, required final String name,
@HiveField(1) required final String script, required final String script,
@HiveField(2) final List<String>? tags, final List<String>? tags,
@HiveField(3) final String? note, final String? note,
@HiveField(4) final List<String>? autoRunOn}) = _$SnippetImpl; final List<String>? autoRunOn,
}) = _$SnippetImpl;
factory _Snippet.fromJson(Map<String, dynamic> json) = _$SnippetImpl.fromJson; factory _Snippet.fromJson(Map<String, dynamic> json) = _$SnippetImpl.fromJson;
@override @override
@HiveField(0)
String get name; String get name;
@override @override
@HiveField(1)
String get script; String get script;
@override @override
@HiveField(2)
List<String>? get tags; List<String>? get tags;
@override @override
@HiveField(3)
String? get note; String? get note;
/// List of server id that this snippet should be auto run on /// List of server id that this snippet should be auto run on
@override @override
@HiveField(4)
List<String>? get autoRunOn; List<String>? get autoRunOn;
/// Create a copy of Snippet /// Create a copy of Snippet

View File

@@ -2,56 +2,6 @@
part of 'snippet.dart'; part of 'snippet.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class SnippetAdapter extends TypeAdapter<Snippet> {
@override
final int typeId = 2;
@override
Snippet read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Snippet(
name: fields[0] as String,
script: fields[1] as String,
tags: (fields[2] as List?)?.cast<String>(),
note: fields[3] as String?,
autoRunOn: (fields[4] as List?)?.cast<String>(),
);
}
@override
void write(BinaryWriter writer, Snippet obj) {
writer
..writeByte(5)
..writeByte(0)
..write(obj.name)
..writeByte(1)
..write(obj.script)
..writeByte(2)
..write(obj.tags)
..writeByte(3)
..write(obj.note)
..writeByte(4)
..write(obj.autoRunOn);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SnippetAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// ************************************************************************** // **************************************************************************
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************

View File

@@ -1,19 +1,14 @@
import 'dart:io'; import 'dart:io';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:wake_on_lan/wake_on_lan.dart'; import 'package:wake_on_lan/wake_on_lan.dart';
part 'wol_cfg.g.dart'; part 'wol_cfg.g.dart';
@JsonSerializable() @JsonSerializable(includeIfNull: false)
@HiveType(typeId: 8)
final class WakeOnLanCfg { final class WakeOnLanCfg {
@HiveField(0)
final String mac; final String mac;
@HiveField(1)
final String ip; final String ip;
@HiveField(2)
final String? pwd; final String? pwd;
const WakeOnLanCfg({ const WakeOnLanCfg({
@@ -26,18 +21,12 @@ final class WakeOnLanCfg {
final macValidation = MACAddress.validate(mac); final macValidation = MACAddress.validate(mac);
final ipValidation = IPAddress.validate( final ipValidation = IPAddress.validate(
ip, ip,
type: ip.contains(':') type: ip.contains(':') ? InternetAddressType.IPv6 : InternetAddressType.IPv4,
? InternetAddressType.IPv6
: InternetAddressType.IPv4,
); );
final pwdValidation = pwd != null final pwdValidation = pwd != null ? SecureONPassword.validate(pwd) : (state: true, error: null);
? SecureONPassword.validate(pwd)
: (state: true, error: null);
final valid = final valid = macValidation.state && ipValidation.state && pwdValidation.state;
macValidation.state && ipValidation.state && pwdValidation.state; final err = macValidation.error ?? ipValidation.error ?? pwdValidation.error;
final err =
macValidation.error ?? ipValidation.error ?? pwdValidation.error;
return (err, valid); return (err, valid);
} }
@@ -56,8 +45,7 @@ final class WakeOnLanCfg {
); );
} }
factory WakeOnLanCfg.fromJson(Map<String, dynamic> json) => factory WakeOnLanCfg.fromJson(Map<String, dynamic> json) => _$WakeOnLanCfgFromJson(json);
_$WakeOnLanCfgFromJson(json);
Map<String, dynamic> toJson() => _$WakeOnLanCfgToJson(this); Map<String, dynamic> toJson() => _$WakeOnLanCfgToJson(this);
} }

View File

@@ -2,50 +2,6 @@
part of 'wol_cfg.dart'; part of 'wol_cfg.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class WakeOnLanCfgAdapter extends TypeAdapter<WakeOnLanCfg> {
@override
final int typeId = 8;
@override
WakeOnLanCfg read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return WakeOnLanCfg(
mac: fields[0] as String,
ip: fields[1] as String,
pwd: fields[2] as String?,
);
}
@override
void write(BinaryWriter writer, WakeOnLanCfg obj) {
writer
..writeByte(3)
..writeByte(0)
..write(obj.mac)
..writeByte(1)
..write(obj.ip)
..writeByte(2)
..write(obj.pwd);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is WakeOnLanCfgAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// ************************************************************************** // **************************************************************************
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
@@ -54,11 +10,11 @@ WakeOnLanCfg _$WakeOnLanCfgFromJson(Map<String, dynamic> json) => WakeOnLanCfg(
mac: json['mac'] as String, mac: json['mac'] as String,
ip: json['ip'] as String, ip: json['ip'] as String,
pwd: json['pwd'] as String?, pwd: json['pwd'] as String?,
); );
Map<String, dynamic> _$WakeOnLanCfgToJson(WakeOnLanCfg instance) => Map<String, dynamic> _$WakeOnLanCfgToJson(WakeOnLanCfg instance) =>
<String, dynamic>{ <String, dynamic>{
'mac': instance.mac, 'mac': instance.mac,
'ip': instance.ip, 'ip': instance.ip,
'pwd': instance.pwd, if (instance.pwd case final value?) 'pwd': value,
}; };

View File

@@ -1,103 +1,55 @@
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/store.dart';
import 'package:xterm/core.dart'; import 'package:xterm/core.dart';
part 'virtual_key.g.dart';
enum VirtualKeyFunc { toggleIME, backspace, clipboard, snippet, file } enum VirtualKeyFunc { toggleIME, backspace, clipboard, snippet, file }
@HiveType(typeId: 4)
enum VirtKey { enum VirtKey {
@HiveField(0)
esc, esc,
@HiveField(1)
alt, alt,
@HiveField(2)
home, home,
@HiveField(3)
up, up,
@HiveField(4)
end, end,
@HiveField(5)
sftp, sftp,
@HiveField(6)
snippet, snippet,
@HiveField(7)
tab, tab,
@HiveField(8)
ctrl, ctrl,
@HiveField(9)
left, left,
@HiveField(10)
down, down,
@HiveField(11)
right, right,
@HiveField(12)
clipboard, clipboard,
@HiveField(13)
ime, ime,
@HiveField(14)
pgup, pgup,
@HiveField(15)
pgdn, pgdn,
@HiveField(16)
slash, slash,
@HiveField(17)
backSlash, backSlash,
@HiveField(18)
underscore, underscore,
@HiveField(19)
plus, plus,
@HiveField(20)
equal, equal,
@HiveField(21)
minus, minus,
@HiveField(22)
parenLeft, parenLeft,
@HiveField(23)
parenRight, parenRight,
@HiveField(24)
bracketLeft, bracketLeft,
@HiveField(25)
bracketRight, bracketRight,
@HiveField(26)
braceLeft, braceLeft,
@HiveField(27)
braceRight, braceRight,
@HiveField(28)
chevronLeft, chevronLeft,
@HiveField(29)
chevronRight, chevronRight,
@HiveField(30)
colon, colon,
@HiveField(31)
semicolon, semicolon,
@HiveField(32)
f1, f1,
@HiveField(33)
f2, f2,
@HiveField(34)
f3, f3,
@HiveField(35)
f4, f4,
@HiveField(36)
f5, f5,
@HiveField(37)
f6, f6,
@HiveField(38)
f7, f7,
@HiveField(39)
f8, f8,
@HiveField(40)
f9, f9,
@HiveField(41)
f10, f10,
@HiveField(42)
f11, f11,
@HiveField(43)
f12; f12;
} }

View File

@@ -1,256 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'virtual_key.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class VirtKeyAdapter extends TypeAdapter<VirtKey> {
@override
final int typeId = 4;
@override
VirtKey read(BinaryReader reader) {
switch (reader.readByte()) {
case 0:
return VirtKey.esc;
case 1:
return VirtKey.alt;
case 2:
return VirtKey.home;
case 3:
return VirtKey.up;
case 4:
return VirtKey.end;
case 5:
return VirtKey.sftp;
case 6:
return VirtKey.snippet;
case 7:
return VirtKey.tab;
case 8:
return VirtKey.ctrl;
case 9:
return VirtKey.left;
case 10:
return VirtKey.down;
case 11:
return VirtKey.right;
case 12:
return VirtKey.clipboard;
case 13:
return VirtKey.ime;
case 14:
return VirtKey.pgup;
case 15:
return VirtKey.pgdn;
case 16:
return VirtKey.slash;
case 17:
return VirtKey.backSlash;
case 18:
return VirtKey.underscore;
case 19:
return VirtKey.plus;
case 20:
return VirtKey.equal;
case 21:
return VirtKey.minus;
case 22:
return VirtKey.parenLeft;
case 23:
return VirtKey.parenRight;
case 24:
return VirtKey.bracketLeft;
case 25:
return VirtKey.bracketRight;
case 26:
return VirtKey.braceLeft;
case 27:
return VirtKey.braceRight;
case 28:
return VirtKey.chevronLeft;
case 29:
return VirtKey.chevronRight;
case 30:
return VirtKey.colon;
case 31:
return VirtKey.semicolon;
case 32:
return VirtKey.f1;
case 33:
return VirtKey.f2;
case 34:
return VirtKey.f3;
case 35:
return VirtKey.f4;
case 36:
return VirtKey.f5;
case 37:
return VirtKey.f6;
case 38:
return VirtKey.f7;
case 39:
return VirtKey.f8;
case 40:
return VirtKey.f9;
case 41:
return VirtKey.f10;
case 42:
return VirtKey.f11;
case 43:
return VirtKey.f12;
default:
return VirtKey.esc;
}
}
@override
void write(BinaryWriter writer, VirtKey obj) {
switch (obj) {
case VirtKey.esc:
writer.writeByte(0);
break;
case VirtKey.alt:
writer.writeByte(1);
break;
case VirtKey.home:
writer.writeByte(2);
break;
case VirtKey.up:
writer.writeByte(3);
break;
case VirtKey.end:
writer.writeByte(4);
break;
case VirtKey.sftp:
writer.writeByte(5);
break;
case VirtKey.snippet:
writer.writeByte(6);
break;
case VirtKey.tab:
writer.writeByte(7);
break;
case VirtKey.ctrl:
writer.writeByte(8);
break;
case VirtKey.left:
writer.writeByte(9);
break;
case VirtKey.down:
writer.writeByte(10);
break;
case VirtKey.right:
writer.writeByte(11);
break;
case VirtKey.clipboard:
writer.writeByte(12);
break;
case VirtKey.ime:
writer.writeByte(13);
break;
case VirtKey.pgup:
writer.writeByte(14);
break;
case VirtKey.pgdn:
writer.writeByte(15);
break;
case VirtKey.slash:
writer.writeByte(16);
break;
case VirtKey.backSlash:
writer.writeByte(17);
break;
case VirtKey.underscore:
writer.writeByte(18);
break;
case VirtKey.plus:
writer.writeByte(19);
break;
case VirtKey.equal:
writer.writeByte(20);
break;
case VirtKey.minus:
writer.writeByte(21);
break;
case VirtKey.parenLeft:
writer.writeByte(22);
break;
case VirtKey.parenRight:
writer.writeByte(23);
break;
case VirtKey.bracketLeft:
writer.writeByte(24);
break;
case VirtKey.bracketRight:
writer.writeByte(25);
break;
case VirtKey.braceLeft:
writer.writeByte(26);
break;
case VirtKey.braceRight:
writer.writeByte(27);
break;
case VirtKey.chevronLeft:
writer.writeByte(28);
break;
case VirtKey.chevronRight:
writer.writeByte(29);
break;
case VirtKey.colon:
writer.writeByte(30);
break;
case VirtKey.semicolon:
writer.writeByte(31);
break;
case VirtKey.f1:
writer.writeByte(32);
break;
case VirtKey.f2:
writer.writeByte(33);
break;
case VirtKey.f3:
writer.writeByte(34);
break;
case VirtKey.f4:
writer.writeByte(35);
break;
case VirtKey.f5:
writer.writeByte(36);
break;
case VirtKey.f6:
writer.writeByte(37);
break;
case VirtKey.f7:
writer.writeByte(38);
break;
case VirtKey.f8:
writer.writeByte(39);
break;
case VirtKey.f9:
writer.writeByte(40);
break;
case VirtKey.f10:
writer.writeByte(41);
break;
case VirtKey.f11:
writer.writeByte(42);
break;
case VirtKey.f12:
writer.writeByte(43);
break;
}
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is VirtKeyAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -12,7 +12,8 @@ part of 'app.dart';
T _$identity<T>(T value) => value; T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError( final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
/// @nodoc /// @nodoc
mixin _$AppState { mixin _$AppState {
@@ -47,15 +48,16 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({Object? desktopMode = null}) {
Object? desktopMode = null, return _then(
}) { _value.copyWith(
return _then(_value.copyWith(
desktopMode: null == desktopMode desktopMode: null == desktopMode
? _value.desktopMode ? _value.desktopMode
: desktopMode // ignore: cast_nullable_to_non_nullable : desktopMode // ignore: cast_nullable_to_non_nullable
as bool, as bool,
) as $Val); )
as $Val,
);
} }
} }
@@ -63,8 +65,9 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
abstract class _$$AppStateImplCopyWith<$Res> abstract class _$$AppStateImplCopyWith<$Res>
implements $AppStateCopyWith<$Res> { implements $AppStateCopyWith<$Res> {
factory _$$AppStateImplCopyWith( factory _$$AppStateImplCopyWith(
_$AppStateImpl value, $Res Function(_$AppStateImpl) then) = _$AppStateImpl value,
__$$AppStateImplCopyWithImpl<$Res>; $Res Function(_$AppStateImpl) then,
) = __$$AppStateImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({bool desktopMode}); $Res call({bool desktopMode});
@@ -75,22 +78,23 @@ class __$$AppStateImplCopyWithImpl<$Res>
extends _$AppStateCopyWithImpl<$Res, _$AppStateImpl> extends _$AppStateCopyWithImpl<$Res, _$AppStateImpl>
implements _$$AppStateImplCopyWith<$Res> { implements _$$AppStateImplCopyWith<$Res> {
__$$AppStateImplCopyWithImpl( __$$AppStateImplCopyWithImpl(
_$AppStateImpl _value, $Res Function(_$AppStateImpl) _then) _$AppStateImpl _value,
: super(_value, _then); $Res Function(_$AppStateImpl) _then,
) : super(_value, _then);
/// Create a copy of AppState /// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({Object? desktopMode = null}) {
Object? desktopMode = null, return _then(
}) { _$AppStateImpl(
return _then(_$AppStateImpl(
desktopMode: null == desktopMode desktopMode: null == desktopMode
? _value.desktopMode ? _value.desktopMode
: desktopMode // ignore: cast_nullable_to_non_nullable : desktopMode // ignore: cast_nullable_to_non_nullable
as bool, as bool,
)); ),
);
} }
} }

View File

@@ -13,8 +13,9 @@ String _$appProviderHash() => r'8378ec9d0a9c8d99cc05805047cd2d52ac4dbb56';
final appProviderProvider = NotifierProvider<AppProvider, AppState>.internal( final appProviderProvider = NotifierProvider<AppProvider, AppState>.internal(
AppProvider.new, AppProvider.new,
name: r'appProviderProvider', name: r'appProviderProvider',
debugGetCreateSourceHash: debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
const bool.fromEnvironment('dart.vm.product') ? null : _$appProviderHash, ? null
: _$appProviderHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );

View File

@@ -49,8 +49,7 @@ class ServerProvider extends Provider {
/// #258 /// #258
/// If not [shouldReconnect], then keep the old state. /// If not [shouldReconnect], then keep the old state.
if (originServer != null && if (originServer != null && !originServer.value.spi.shouldReconnect(spi)) {
!originServer.value.spi.shouldReconnect(spi)) {
newServer.conn = originServer.value.conn; newServer.conn = originServer.value.conn;
} }
servers[spi.id] = newServer.vn; servers[spi.id] = newServer.vn;
@@ -174,12 +173,16 @@ class ServerProvider extends Provider {
static void _closeOneServer(String id) { static void _closeOneServer(String id) {
final s = servers[id]; final s = servers[id];
final item = s?.value; if (s == null) {
item?.client?.close(); Loggers.app.warning('Server with id $id not found');
item?.client = null; return;
item?.conn = ServerConn.disconnected; }
final item = s.value;
item.client?.close();
item.client = null;
item.conn = ServerConn.disconnected;
_manualDisconnectedIds.add(id); _manualDisconnectedIds.add(id);
s?.notify(); s.notify();
} }
static void addServer(Spi spi) { static void addServer(Spi spi) {

View File

@@ -28,17 +28,22 @@ abstract final class Stores {
await Future.wait(_allBackup.map((store) => store.init())); await Future.wait(_allBackup.map((store) => store.init()));
} }
static DateTime? get lastModTime { static int get lastModTime {
DateTime? lastModTime; var lastModTime = 0;
for (final store in _allBackup) { for (final store in _allBackup) {
final last = store.lastUpdateTs; final last = store.lastUpdateTs;
if (last == null) { if (last == null) {
continue; continue;
} }
if (lastModTime == null) { var lastModTimeTs = 0;
lastModTime = last; for (final item in last.entries) {
} else if (last.isAfter(lastModTime)) { final ts = item.value;
lastModTime = last; if (ts > lastModTimeTs) {
lastModTimeTs = ts;
}
}
if (lastModTimeTs > lastModTime) {
lastModTime = lastModTimeTs;
} }
} }
return lastModTime; return lastModTime;

View File

@@ -14,8 +14,7 @@ class ContainerStore extends HiveStore {
} }
void put(String id, String host) { void put(String id, String host) {
box.put(id, host); set(id, host);
updateLastUpdateTs();
} }
ContainerType getType([String id = '']) { ContainerType getType([String id = '']) {
@@ -36,10 +35,11 @@ class ContainerStore extends HiveStore {
void setType(ContainerType type, [String id = '']) { void setType(ContainerType type, [String id = '']) {
if (type == defaultType) { if (type == defaultType) {
box.delete(_keyConfig + id); // box.delete(_keyConfig + id);
remove(_keyConfig + id);
} else { } else {
box.put(_keyConfig + id, type.toString()); // box.put(_keyConfig + id, type.toString());
set(_keyConfig + id, type.toString());
} }
updateLastUpdateTs();
} }
} }

View File

@@ -1,5 +1,5 @@
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_ce_flutter/hive_flutter.dart';
/// index from 0 -> n : latest -> oldest /// index from 0 -> n : latest -> oldest
class _ListHistory { class _ListHistory {

View File

@@ -12,11 +12,27 @@ class PrivateKeyStore extends HiveStore {
} }
List<PrivateKeyInfo> fetch() { List<PrivateKeyInfo> fetch() {
final keys = box.keys;
final ps = <PrivateKeyInfo>[]; final ps = <PrivateKeyInfo>[];
for (final key in keys) { for (final key in keys()) {
final s = box.get(key); final s = get<PrivateKeyInfo>(
if (s != null && s is PrivateKeyInfo) { key,
fromObj: (val) {
if (val is PrivateKeyInfo) return val;
if (val is Map<dynamic, dynamic>) {
final map = val.toStrDynMap;
if (map == null) return null;
try {
final pki = PrivateKeyInfo.fromJson(map as Map<String, dynamic>);
put(pki);
return pki;
} catch (e) {
dprint('Parsing PrivateKeyInfo from JSON', e);
}
}
return null;
},
);
if (s != null) {
ps.add(s); ps.add(s);
} }
} }

View File

@@ -17,8 +17,25 @@ class ServerStore extends HiveStore {
List<Spi> fetch() { List<Spi> fetch() {
final List<Spi> ss = []; final List<Spi> ss = [];
for (final id in keys()) { for (final id in keys()) {
final s = box.get(id); final s = get<Spi>(
if (s != null && s is Spi) { id,
fromObj: (val) {
if (val is Spi) return val;
if (val is Map<dynamic, dynamic>) {
final map = val.toStrDynMap;
if (map == null) return null;
try {
final spi = Spi.fromJson(map as Map<String, dynamic>);
put(spi);
return spi;
} catch (e) {
dprint('Parsing Spi from JSON', e);
}
}
return null;
},
);
if (s != null) {
ss.add(s); ss.add(s);
} }
} }

View File

@@ -13,12 +13,6 @@ class SettingStore extends HiveStore {
static final instance = SettingStore._(); static final instance = SettingStore._();
// ------BEGIN------
//
// These settings are not displayed in the settings page
// You can edit them in the settings json editor (by long press the settings
// item in the drawer of the home page)
/// Discussion #146 /// Discussion #146
late final serverTabUseOldUI = propertyDefault('serverTabUseOldUI', false); late final serverTabUseOldUI = propertyDefault('serverTabUseOldUI', false);
@@ -37,8 +31,6 @@ class SettingStore extends HiveStore {
false, false,
); );
// ------END------
/// Bigger for bigger font size /// Bigger for bigger font size
/// 1.0 means 100% /// 1.0 means 100%
/// Warning: This may cause some UI issues /// Warning: This may cause some UI issues
@@ -65,14 +57,14 @@ class SettingStore extends HiveStore {
late final bgRun = propertyDefault('bgRun', isAndroid); late final bgRun = propertyDefault('bgRun', isAndroid);
// Server order // Server order
late final serverOrder = propertyDefault<List<String>>('serverOrder', []); late final serverOrder = listProperty<String>('serverOrder');
late final snippetOrder = propertyDefault<List<String>>('snippetOrder', []); late final snippetOrder = listProperty<String>('snippetOrder');
// Server details page cards order // Server details page cards order
late final detailCardOrder = propertyDefault( late final detailCardOrder = listProperty(
'detailCardOrder', 'detailCardOrder',
ServerDetailCards.values.map((e) => e.name).toList(), defaultValue: ServerDetailCards.values.map((e) => e.name).toList(),
); );
// SSH term font size // SSH term font size
@@ -82,16 +74,14 @@ class SettingStore extends HiveStore {
late final locale = propertyDefault('locale', ''); late final locale = propertyDefault('locale', '');
// SSH virtual key (ctrl | alt) auto turn off // SSH virtual key (ctrl | alt) auto turn off
late final sshVirtualKeyAutoOff = late final sshVirtualKeyAutoOff = propertyDefault('sshVirtualKeyAutoOff', true);
propertyDefault('sshVirtualKeyAutoOff', true);
late final editorFontSize = propertyDefault('editorFontSize', 12.5); late final editorFontSize = propertyDefault('editorFontSize', 12.5);
// Editor theme // Editor theme
late final editorTheme = propertyDefault('editorTheme', Defaults.editorTheme); late final editorTheme = propertyDefault('editorTheme', Defaults.editorTheme);
late final editorDarkTheme = late final editorDarkTheme = propertyDefault('editorDarkTheme', Defaults.editorDarkTheme);
propertyDefault('editorDarkTheme', Defaults.editorDarkTheme);
late final fullScreen = propertyDefault('fullScreen', false); late final fullScreen = propertyDefault('fullScreen', false);
@@ -107,31 +97,34 @@ class SettingStore extends HiveStore {
// TextInputType.text.index, // TextInputType.text.index,
// ); // );
late final sshVirtKeys = propertyDefault( late final sshVirtKeys = listProperty<int>(
'sshVirtKeys', 'sshVirtKeys',
VirtKeyX.defaultOrder.map((e) => e.index).toList(), defaultValue: VirtKeyX.defaultOrder.map((e) => e.index).toList(),
fromObj: (val) => List<int>.from(val as List),
); );
late final netViewType = propertyDefault('netViewType', NetViewType.speed); late final netViewType = propertyDefault(
'netViewType',
NetViewType.speed,
fromObj: (val) => NetViewType.values.firstWhereOrNull((e) => e.name == val),
toObj: (type) => type?.name,
);
// Only valid on iOS // Only valid on iOS
late final autoUpdateHomeWidget = late final autoUpdateHomeWidget = propertyDefault('autoUpdateHomeWidget', isIOS);
propertyDefault('autoUpdateHomeWidget', isIOS);
late final autoCheckAppUpdate = propertyDefault('autoCheckAppUpdate', true); late final autoCheckAppUpdate = propertyDefault('autoCheckAppUpdate', true);
/// Display server tab function buttons on the bottom of each server card if [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 /// Otherwise, display them on the top of server detail page
late final moveServerFuncs = late final moveServerFuncs = propertyDefault('moveOutServerTabFuncBtns', false);
propertyDefault('moveOutServerTabFuncBtns', false);
/// Whether use `rm -r` to delete directory on SFTP /// Whether use `rm -r` to delete directory on SFTP
late final sftpRmrDir = propertyDefault('sftpRmrDir', false); late final sftpRmrDir = propertyDefault('sftpRmrDir', false);
/// Whether use system's primary color as the app's primary color /// Whether use system's primary color as the app's primary color
late final useSystemPrimaryColor = late final useSystemPrimaryColor = propertyDefault('useSystemPrimaryColor', false);
propertyDefault('useSystemPrimaryColor', false);
/// Only valid on iOS / Android / Windows /// Only valid on iOS / Android / Windows
late final useBioAuth = propertyDefault('useBioAuth', false); late final useBioAuth = propertyDefault('useBioAuth', false);
@@ -143,8 +136,7 @@ class SettingStore extends HiveStore {
late final sftpOpenLastPath = propertyDefault('sftpOpenLastPath', true); late final sftpOpenLastPath = propertyDefault('sftpOpenLastPath', true);
/// Show folders first in SFTP file browser /// Show folders first in SFTP file browser
late final sftpShowFoldersFirst = late final sftpShowFoldersFirst = propertyDefault('sftpShowFoldersFirst', true);
propertyDefault('sftpShowFoldersFirst', true);
/// Show tip of suspend /// Show tip of suspend
late final showSuspendTip = propertyDefault('showSuspendTip', true); late final showSuspendTip = propertyDefault('showSuspendTip', true);
@@ -152,9 +144,9 @@ class SettingStore extends HiveStore {
/// Whether collapse UI items by default /// Whether collapse UI items by default
late final collapseUIDefault = propertyDefault('collapseUIDefault', true); late final collapseUIDefault = propertyDefault('collapseUIDefault', true);
late final serverFuncBtns = propertyDefault( late final serverFuncBtns = listProperty(
'serverBtns', 'serverBtns',
ServerFuncBtn.defaultIdxs, defaultValue: ServerFuncBtn.defaultIdxs,
); );
/// Docker is more popular than podman, set to `false` to use docker /// Docker is more popular than podman, set to `false` to use docker
@@ -170,8 +162,7 @@ class SettingStore extends HiveStore {
late final containerParseStat = propertyDefault('containerParseStat', true); late final containerParseStat = propertyDefault('containerParseStat', true);
/// Auto refresh container status /// Auto refresh container status
late final contaienrAutoRefresh = late final contaienrAutoRefresh = propertyDefault('contaienrAutoRefresh', true);
propertyDefault('contaienrAutoRefresh', true);
/// Use double column servers page on Desktop /// Use double column servers page on Desktop
late final doubleColumnServersPage = propertyDefault( late final doubleColumnServersPage = propertyDefault(
@@ -229,9 +220,8 @@ class SettingStore extends HiveStore {
/// Record the position and size of the window. /// Record the position and size of the window.
late final windowState = property<WindowState>( late final windowState = property<WindowState>(
'windowState', 'windowState',
fromStr: (jsonStr) => fromObj: (raw) => WindowState.fromJson(jsonDecode(raw as String) as Map<String, dynamic>),
WindowState.fromJson(jsonDecode(jsonStr) as Map<String, dynamic>), toObj: (state) => state == null ? null : jsonEncode(state.toJson()),
toStr: (state) => state == null ? null : jsonEncode(state.toJson()),
); );
late final introVer = propertyDefault('introVer', 0); late final introVer = propertyDefault('introVer', 0);
@@ -248,15 +238,9 @@ class SettingStore extends HiveStore {
/// Close the editor after saving /// Close the editor after saving
late final closeAfterSave = propertyDefault('closeAfterSave', false); late final closeAfterSave = propertyDefault('closeAfterSave', false);
// Never show these settings for users
//
// ------BEGIN------
/// Version of store db /// Version of store db
late final storeVersion = propertyDefault('storeVersion', 0); late final storeVersion = propertyDefault('storeVersion', 0);
/// Have notified user for notificaiton permission or not /// Have notified user for notificaiton permission or not
late final noNotiPerm = propertyDefault('noNotiPerm', false); late final noNotiPerm = propertyDefault('noNotiPerm', false);
// ------END------
} }

View File

@@ -14,8 +14,25 @@ class SnippetStore extends HiveStore {
List<Snippet> fetch() { List<Snippet> fetch() {
final ss = <Snippet>{}; final ss = <Snippet>{};
for (final key in keys()) { for (final key in keys()) {
final s = box.get(key); final s = get<Snippet>(
if (s != null && s is Snippet) { key,
fromObj: (val) {
if (val is Snippet) return val;
if (val is Map<dynamic, dynamic>) {
final map = val.toStrDynMap;
if (map == null) return null;
try {
final snippet = Snippet.fromJson(map as Map<String, dynamic>);
put(snippet);
return snippet;
} catch (e) {
dprint('Parsing Snippet from JSON', e);
}
}
return null;
},
);
if (s != null) {
ss.add(s); ss.add(s);
} }
} }

View File

@@ -116,7 +116,7 @@ abstract class AppLocalizations {
Locale('tr'), Locale('tr'),
Locale('uk'), Locale('uk'),
Locale('zh'), Locale('zh'),
Locale('zh', 'TW') Locale('zh', 'TW'),
]; ];
/// No description provided for @aboutThanks. /// No description provided for @aboutThanks.
@@ -370,7 +370,9 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'{runningCount} running, {stoppedCount} container stopped.'** /// **'{runningCount} running, {stoppedCount} container stopped.'**
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount); Object runningCount,
Object stoppedCount,
);
/// No description provided for @dockerStatusRunningFmt. /// No description provided for @dockerStatusRunningFmt.
/// ///
@@ -1499,7 +1501,7 @@ class _AppLocalizationsDelegate
'ru', 'ru',
'tr', 'tr',
'uk', 'uk',
'zh' 'zh',
].contains(locale.languageCode); ].contains(locale.languageCode);
@override @override
@@ -1551,5 +1553,6 @@ AppLocalizations lookupAppLocalizations(Locale locale) {
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue ' 'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration ' 'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.'); 'that was used.',
);
} }

View File

@@ -149,7 +149,9 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount aktiv, $stoppedCount container gestoppt.'; return '$runningCount aktiv, $stoppedCount container gestoppt.';
} }

View File

@@ -148,7 +148,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount running, $stoppedCount container stopped.'; return '$runningCount running, $stoppedCount container stopped.';
} }

View File

@@ -149,7 +149,9 @@ class AppLocalizationsEs extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount en ejecución, $stoppedCount detenidos'; return '$runningCount en ejecución, $stoppedCount detenidos';
} }

View File

@@ -149,7 +149,9 @@ class AppLocalizationsFr extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount en cours d\'exécution, $stoppedCount conteneur arrêté.'; return '$runningCount en cours d\'exécution, $stoppedCount conteneur arrêté.';
} }

View File

@@ -148,7 +148,9 @@ class AppLocalizationsId extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount running, $stoppedCount container stopped.'; return '$runningCount running, $stoppedCount container stopped.';
} }

View File

@@ -142,7 +142,9 @@ class AppLocalizationsJa extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount個が実行中$stoppedCount個が停止中'; return '$runningCount個が実行中$stoppedCount個が停止中';
} }

View File

@@ -148,7 +148,9 @@ class AppLocalizationsNl extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount actief, $stoppedCount container gestopt.'; return '$runningCount actief, $stoppedCount container gestopt.';
} }

View File

@@ -148,7 +148,9 @@ class AppLocalizationsPt extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount em execução, $stoppedCount parados'; return '$runningCount em execução, $stoppedCount parados';
} }

View File

@@ -148,7 +148,9 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount запущено, $stoppedCount остановлено'; return '$runningCount запущено, $stoppedCount остановлено';
} }

View File

@@ -147,7 +147,9 @@ class AppLocalizationsTr extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount çalışıyor, $stoppedCount konteyner durdurulmuş.'; return '$runningCount çalışıyor, $stoppedCount konteyner durdurulmuş.';
} }

View File

@@ -149,7 +149,9 @@ class AppLocalizationsUk extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount запущено, $stoppedCount контейнерів зупинено.'; return '$runningCount запущено, $stoppedCount контейнерів зупинено.';
} }

View File

@@ -141,7 +141,9 @@ class AppLocalizationsZh extends AppLocalizations {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount 个正在运行, $stoppedCount 个已停止'; return '$runningCount 个正在运行, $stoppedCount 个已停止';
} }
@@ -858,7 +860,9 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override @override
String dockerStatusRunningAndStoppedFmt( String dockerStatusRunningAndStoppedFmt(
Object runningCount, Object stoppedCount) { Object runningCount,
Object stoppedCount,
) {
return '$runningCount 個正在運行, $stoppedCount 個已停止'; return '$runningCount 個正在運行, $stoppedCount 個已停止';
} }

View File

@@ -0,0 +1,21 @@
import 'package:hive_ce/hive.dart';
import 'package:server_box/data/model/app/menu/server_func.dart';
import 'package:server_box/data/model/app/net_view.dart';
import 'package:server_box/data/model/server/custom.dart';
import 'package:server_box/data/model/server/private_key_info.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/model/server/snippet.dart';
import 'package:server_box/data/model/server/wol_cfg.dart';
import 'package:server_box/data/model/ssh/virtual_key.dart';
@GenerateAdapters([
AdapterSpec<PrivateKeyInfo>(),
AdapterSpec<Snippet>(),
AdapterSpec<Spi>(),
AdapterSpec<VirtKey>(),
AdapterSpec<NetViewType>(),
AdapterSpec<ServerFuncBtn>(),
AdapterSpec<ServerCustom>(),
AdapterSpec<WakeOnLanCfg>(),
])
part 'hive_adapters.g.dart';

View File

@@ -0,0 +1,555 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'hive_adapters.dart';
// **************************************************************************
// AdaptersGenerator
// **************************************************************************
class PrivateKeyInfoAdapter extends TypeAdapter<PrivateKeyInfo> {
@override
final typeId = 1;
@override
PrivateKeyInfo read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return PrivateKeyInfo(id: fields[0] as String, key: fields[1] as String);
}
@override
void write(BinaryWriter writer, PrivateKeyInfo obj) {
writer
..writeByte(2)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.key);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is PrivateKeyInfoAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class SnippetAdapter extends TypeAdapter<Snippet> {
@override
final typeId = 2;
@override
Snippet read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Snippet(
name: fields[0] as String,
script: fields[1] as String,
tags: (fields[2] as List?)?.cast<String>(),
note: fields[3] as String?,
autoRunOn: (fields[4] as List?)?.cast<String>(),
);
}
@override
void write(BinaryWriter writer, Snippet obj) {
writer
..writeByte(5)
..writeByte(0)
..write(obj.name)
..writeByte(1)
..write(obj.script)
..writeByte(2)
..write(obj.tags)
..writeByte(3)
..write(obj.note)
..writeByte(4)
..write(obj.autoRunOn);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SnippetAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class SpiAdapter extends TypeAdapter<Spi> {
@override
final typeId = 3;
@override
Spi read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Spi(
name: fields[0] as String,
ip: fields[1] as String,
port: (fields[2] as num).toInt(),
user: fields[3] as String,
pwd: fields[4] as String?,
keyId: fields[5] as String?,
tags: (fields[6] as List?)?.cast<String>(),
alterUrl: fields[7] as String?,
autoConnect: fields[8] == null ? true : fields[8] as bool,
jumpId: fields[9] as String?,
custom: fields[10] as ServerCustom?,
wolCfg: fields[11] as WakeOnLanCfg?,
envs: (fields[12] as Map?)?.cast<String, String>(),
id: fields[13] == null ? '' : fields[13] as String,
);
}
@override
void write(BinaryWriter writer, Spi obj) {
writer
..writeByte(14)
..writeByte(0)
..write(obj.name)
..writeByte(1)
..write(obj.ip)
..writeByte(2)
..write(obj.port)
..writeByte(3)
..write(obj.user)
..writeByte(4)
..write(obj.pwd)
..writeByte(5)
..write(obj.keyId)
..writeByte(6)
..write(obj.tags)
..writeByte(7)
..write(obj.alterUrl)
..writeByte(8)
..write(obj.autoConnect)
..writeByte(9)
..write(obj.jumpId)
..writeByte(10)
..write(obj.custom)
..writeByte(11)
..write(obj.wolCfg)
..writeByte(12)
..write(obj.envs)
..writeByte(13)
..write(obj.id);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SpiAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class VirtKeyAdapter extends TypeAdapter<VirtKey> {
@override
final typeId = 4;
@override
VirtKey read(BinaryReader reader) {
switch (reader.readByte()) {
case 0:
return VirtKey.esc;
case 1:
return VirtKey.alt;
case 2:
return VirtKey.home;
case 3:
return VirtKey.up;
case 4:
return VirtKey.end;
case 5:
return VirtKey.sftp;
case 6:
return VirtKey.snippet;
case 7:
return VirtKey.tab;
case 8:
return VirtKey.ctrl;
case 9:
return VirtKey.left;
case 10:
return VirtKey.down;
case 11:
return VirtKey.right;
case 12:
return VirtKey.clipboard;
case 13:
return VirtKey.ime;
case 14:
return VirtKey.pgup;
case 15:
return VirtKey.pgdn;
case 16:
return VirtKey.slash;
case 17:
return VirtKey.backSlash;
case 18:
return VirtKey.underscore;
case 19:
return VirtKey.plus;
case 20:
return VirtKey.equal;
case 21:
return VirtKey.minus;
case 22:
return VirtKey.parenLeft;
case 23:
return VirtKey.parenRight;
case 24:
return VirtKey.bracketLeft;
case 25:
return VirtKey.bracketRight;
case 26:
return VirtKey.braceLeft;
case 27:
return VirtKey.braceRight;
case 28:
return VirtKey.chevronLeft;
case 29:
return VirtKey.chevronRight;
case 30:
return VirtKey.colon;
case 31:
return VirtKey.semicolon;
case 32:
return VirtKey.f1;
case 33:
return VirtKey.f2;
case 34:
return VirtKey.f3;
case 35:
return VirtKey.f4;
case 36:
return VirtKey.f5;
case 37:
return VirtKey.f6;
case 38:
return VirtKey.f7;
case 39:
return VirtKey.f8;
case 40:
return VirtKey.f9;
case 41:
return VirtKey.f10;
case 42:
return VirtKey.f11;
case 43:
return VirtKey.f12;
default:
return VirtKey.esc;
}
}
@override
void write(BinaryWriter writer, VirtKey obj) {
switch (obj) {
case VirtKey.esc:
writer.writeByte(0);
case VirtKey.alt:
writer.writeByte(1);
case VirtKey.home:
writer.writeByte(2);
case VirtKey.up:
writer.writeByte(3);
case VirtKey.end:
writer.writeByte(4);
case VirtKey.sftp:
writer.writeByte(5);
case VirtKey.snippet:
writer.writeByte(6);
case VirtKey.tab:
writer.writeByte(7);
case VirtKey.ctrl:
writer.writeByte(8);
case VirtKey.left:
writer.writeByte(9);
case VirtKey.down:
writer.writeByte(10);
case VirtKey.right:
writer.writeByte(11);
case VirtKey.clipboard:
writer.writeByte(12);
case VirtKey.ime:
writer.writeByte(13);
case VirtKey.pgup:
writer.writeByte(14);
case VirtKey.pgdn:
writer.writeByte(15);
case VirtKey.slash:
writer.writeByte(16);
case VirtKey.backSlash:
writer.writeByte(17);
case VirtKey.underscore:
writer.writeByte(18);
case VirtKey.plus:
writer.writeByte(19);
case VirtKey.equal:
writer.writeByte(20);
case VirtKey.minus:
writer.writeByte(21);
case VirtKey.parenLeft:
writer.writeByte(22);
case VirtKey.parenRight:
writer.writeByte(23);
case VirtKey.bracketLeft:
writer.writeByte(24);
case VirtKey.bracketRight:
writer.writeByte(25);
case VirtKey.braceLeft:
writer.writeByte(26);
case VirtKey.braceRight:
writer.writeByte(27);
case VirtKey.chevronLeft:
writer.writeByte(28);
case VirtKey.chevronRight:
writer.writeByte(29);
case VirtKey.colon:
writer.writeByte(30);
case VirtKey.semicolon:
writer.writeByte(31);
case VirtKey.f1:
writer.writeByte(32);
case VirtKey.f2:
writer.writeByte(33);
case VirtKey.f3:
writer.writeByte(34);
case VirtKey.f4:
writer.writeByte(35);
case VirtKey.f5:
writer.writeByte(36);
case VirtKey.f6:
writer.writeByte(37);
case VirtKey.f7:
writer.writeByte(38);
case VirtKey.f8:
writer.writeByte(39);
case VirtKey.f9:
writer.writeByte(40);
case VirtKey.f10:
writer.writeByte(41);
case VirtKey.f11:
writer.writeByte(42);
case VirtKey.f12:
writer.writeByte(43);
}
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is VirtKeyAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class NetViewTypeAdapter extends TypeAdapter<NetViewType> {
@override
final typeId = 5;
@override
NetViewType read(BinaryReader reader) {
switch (reader.readByte()) {
case 0:
return NetViewType.conn;
case 1:
return NetViewType.speed;
case 2:
return NetViewType.traffic;
default:
return NetViewType.conn;
}
}
@override
void write(BinaryWriter writer, NetViewType obj) {
switch (obj) {
case NetViewType.conn:
writer.writeByte(0);
case NetViewType.speed:
writer.writeByte(1);
case NetViewType.traffic:
writer.writeByte(2);
}
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is NetViewTypeAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class ServerFuncBtnAdapter extends TypeAdapter<ServerFuncBtn> {
@override
final typeId = 6;
@override
ServerFuncBtn read(BinaryReader reader) {
switch (reader.readByte()) {
case 0:
return ServerFuncBtn.terminal;
case 1:
return ServerFuncBtn.sftp;
case 2:
return ServerFuncBtn.container;
case 3:
return ServerFuncBtn.process;
case 5:
return ServerFuncBtn.snippet;
case 6:
return ServerFuncBtn.iperf;
case 8:
return ServerFuncBtn.systemd;
default:
return ServerFuncBtn.terminal;
}
}
@override
void write(BinaryWriter writer, ServerFuncBtn obj) {
switch (obj) {
case ServerFuncBtn.terminal:
writer.writeByte(0);
case ServerFuncBtn.sftp:
writer.writeByte(1);
case ServerFuncBtn.container:
writer.writeByte(2);
case ServerFuncBtn.process:
writer.writeByte(3);
case ServerFuncBtn.snippet:
writer.writeByte(5);
case ServerFuncBtn.iperf:
writer.writeByte(6);
case ServerFuncBtn.systemd:
writer.writeByte(8);
}
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ServerFuncBtnAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class ServerCustomAdapter extends TypeAdapter<ServerCustom> {
@override
final typeId = 7;
@override
ServerCustom read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return ServerCustom(
pveAddr: fields[1] as String?,
pveIgnoreCert: fields[2] == null ? false : fields[2] as bool,
cmds: (fields[3] as Map?)?.cast<String, String>(),
preferTempDev: fields[4] as String?,
logoUrl: fields[5] as String?,
netDev: fields[6] as String?,
scriptDir: fields[7] as String?,
);
}
@override
void write(BinaryWriter writer, ServerCustom obj) {
writer
..writeByte(7)
..writeByte(1)
..write(obj.pveAddr)
..writeByte(2)
..write(obj.pveIgnoreCert)
..writeByte(3)
..write(obj.cmds)
..writeByte(4)
..write(obj.preferTempDev)
..writeByte(5)
..write(obj.logoUrl)
..writeByte(6)
..write(obj.netDev)
..writeByte(7)
..write(obj.scriptDir);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ServerCustomAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class WakeOnLanCfgAdapter extends TypeAdapter<WakeOnLanCfg> {
@override
final typeId = 8;
@override
WakeOnLanCfg read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return WakeOnLanCfg(
mac: fields[0] as String,
ip: fields[1] as String,
pwd: fields[2] as String?,
);
}
@override
void write(BinaryWriter writer, WakeOnLanCfg obj) {
writer
..writeByte(3)
..writeByte(0)
..write(obj.mac)
..writeByte(1)
..write(obj.ip)
..writeByte(2)
..write(obj.pwd);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is WakeOnLanCfgAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,207 @@
# Generated by Hive CE
# Manual modifications may be necessary for certain migrations
# Check in to version control
nextTypeId: 9
types:
PrivateKeyInfo:
typeId: 1
nextIndex: 2
fields:
id:
index: 0
key:
index: 1
Snippet:
typeId: 2
nextIndex: 5
fields:
name:
index: 0
script:
index: 1
tags:
index: 2
note:
index: 3
autoRunOn:
index: 4
Spi:
typeId: 3
nextIndex: 14
fields:
name:
index: 0
ip:
index: 1
port:
index: 2
user:
index: 3
pwd:
index: 4
keyId:
index: 5
tags:
index: 6
alterUrl:
index: 7
autoConnect:
index: 8
jumpId:
index: 9
custom:
index: 10
wolCfg:
index: 11
envs:
index: 12
id:
index: 13
VirtKey:
typeId: 4
nextIndex: 44
fields:
esc:
index: 0
alt:
index: 1
home:
index: 2
up:
index: 3
end:
index: 4
sftp:
index: 5
snippet:
index: 6
tab:
index: 7
ctrl:
index: 8
left:
index: 9
down:
index: 10
right:
index: 11
clipboard:
index: 12
ime:
index: 13
pgup:
index: 14
pgdn:
index: 15
slash:
index: 16
backSlash:
index: 17
underscore:
index: 18
plus:
index: 19
equal:
index: 20
minus:
index: 21
parenLeft:
index: 22
parenRight:
index: 23
bracketLeft:
index: 24
bracketRight:
index: 25
braceLeft:
index: 26
braceRight:
index: 27
chevronLeft:
index: 28
chevronRight:
index: 29
colon:
index: 30
semicolon:
index: 31
f1:
index: 32
f2:
index: 33
f3:
index: 34
f4:
index: 35
f5:
index: 36
f6:
index: 37
f7:
index: 38
f8:
index: 39
f9:
index: 40
f10:
index: 41
f11:
index: 42
f12:
index: 43
NetViewType:
typeId: 5
nextIndex: 3
fields:
conn:
index: 0
speed:
index: 1
traffic:
index: 2
ServerFuncBtn:
typeId: 6
nextIndex: 9
fields:
terminal:
index: 0
sftp:
index: 1
container:
index: 2
process:
index: 3
snippet:
index: 5
iperf:
index: 6
systemd:
index: 8
ServerCustom:
typeId: 7
nextIndex: 8
fields:
pveAddr:
index: 1
pveIgnoreCert:
index: 2
cmds:
index: 3
preferTempDev:
index: 4
logoUrl:
index: 5
netDev:
index: 6
scriptDir:
index: 7
WakeOnLanCfg:
typeId: 8
nextIndex: 3
fields:
mac:
index: 0
ip:
index: 1
pwd:
index: 2

View File

@@ -0,0 +1,32 @@
// Generated by Hive CE
// Do not modify
// Check in to version control
import 'package:hive_ce/hive.dart';
import 'package:server_box/hive/hive_adapters.dart';
extension HiveRegistrar on HiveInterface {
void registerAdapters() {
registerAdapter(NetViewTypeAdapter());
registerAdapter(PrivateKeyInfoAdapter());
registerAdapter(ServerCustomAdapter());
registerAdapter(ServerFuncBtnAdapter());
registerAdapter(SnippetAdapter());
registerAdapter(SpiAdapter());
registerAdapter(VirtKeyAdapter());
registerAdapter(WakeOnLanCfgAdapter());
}
}
extension IsolatedHiveRegistrar on IsolatedHiveInterface {
void registerAdapters() {
registerAdapter(NetViewTypeAdapter());
registerAdapter(PrivateKeyInfoAdapter());
registerAdapter(ServerCustomAdapter());
registerAdapter(ServerFuncBtnAdapter());
registerAdapter(SnippetAdapter());
registerAdapter(SpiAdapter());
registerAdapter(VirtKeyAdapter());
registerAdapter(WakeOnLanCfgAdapter());
}
}

View File

@@ -6,19 +6,12 @@ import 'package:computer/computer.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_ce_flutter/hive_flutter.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:server_box/app.dart'; import 'package:server_box/app.dart';
import 'package:server_box/core/sync.dart'; import 'package:server_box/core/sync.dart';
import 'package:server_box/data/model/app/menu/server_func.dart'; import 'package:server_box/data/model/app/menu/server_func.dart';
import 'package:server_box/data/model/app/net_view.dart';
import 'package:server_box/data/model/app/server_detail_card.dart'; import 'package:server_box/data/model/app/server_detail_card.dart';
import 'package:server_box/data/model/server/custom.dart';
import 'package:server_box/data/model/server/private_key_info.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/model/server/snippet.dart';
import 'package:server_box/data/model/server/wol_cfg.dart';
import 'package:server_box/data/model/ssh/virtual_key.dart';
import 'package:server_box/data/provider/private_key.dart'; import 'package:server_box/data/provider/private_key.dart';
import 'package:server_box/data/provider/server.dart'; import 'package:server_box/data/provider/server.dart';
import 'package:server_box/data/provider/sftp.dart'; import 'package:server_box/data/provider/sftp.dart';
@@ -26,6 +19,7 @@ import 'package:server_box/data/provider/snippet.dart';
import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/res/build_data.dart';
import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/store.dart';
import 'package:server_box/data/store/server.dart'; import 'package:server_box/data/store/server.dart';
import 'package:server_box/hive/hive_registrar.g.dart';
Future<void> main() async { Future<void> main() async {
_runInZone(() async { _runInZone(() async {
@@ -41,37 +35,24 @@ void _runInZone(void Function() body) {
}, },
); );
runZonedGuarded( runZonedGuarded(body, (e, s) => print('[ZONE] $e\n$s'), zoneSpecification: zoneSpec);
body,
(e, s) => print('[ZONE] $e\n$s'),
zoneSpecification: zoneSpec,
);
} }
Future<void> _initApp() async { Future<void> _initApp() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await Paths.init(BuildData.name, bakName: 'srvbox_bak.json');
await _initData(); await _initData();
_setupDebug(); _setupDebug();
await _initWindow(); await _initWindow();
FontUtils.loadFrom(Stores.setting.fontPath.fetch());
_doPlatformRelated(); _doPlatformRelated();
} }
Future<void> _initData() async { Future<void> _initData() async {
await Hive.initFlutter(); await Paths.init(BuildData.name, bakName: 'srvbox_bak.json');
// Ordered by typeId await Hive.initFlutter();
Hive.registerAdapter(PrivateKeyInfoAdapter()); // 1 Hive.registerAdapters();
Hive.registerAdapter(SnippetAdapter()); // 2
Hive.registerAdapter(SpiAdapter()); // 3
Hive.registerAdapter(VirtKeyAdapter()); // 4
Hive.registerAdapter(NetViewTypeAdapter()); // 5
Hive.registerAdapter(ServerFuncBtnAdapter()); // 6
Hive.registerAdapter(ServerCustomAdapter()); // 7
Hive.registerAdapter(WakeOnLanCfgAdapter()); // 8
await PrefStore.shared.init(); // Call this before accessing any store await PrefStore.shared.init(); // Call this before accessing any store
await Stores.init(); await Stores.init();
@@ -87,13 +68,15 @@ Future<void> _initData() async {
SftpProvider.instance.load(); SftpProvider.instance.load();
if (Stores.setting.betaTest.fetch()) AppUpdate.chan = AppUpdateChan.beta; if (Stores.setting.betaTest.fetch()) AppUpdate.chan = AppUpdateChan.beta;
FontUtils.loadFrom(Stores.setting.fontPath.fetch());
} }
void _setupDebug() { void _setupDebug() {
Logger.root.level = Level.ALL; Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) { Logger.root.onRecord.listen((record) {
DebugProvider.addLog(record); DebugProvider.addLog(record);
print(record); lprint(record);
if (record.error != null) print(record.error); if (record.error != null) print(record.error);
if (record.stackTrace != null) print(record.stackTrace); if (record.stackTrace != null) print(record.stackTrace);
}); });
@@ -106,8 +89,7 @@ void _doPlatformRelated() async {
} }
final serversCount = Stores.server.keys().length; final serversCount = Stores.server.keys().length;
// Plus 1 to avoid 0. Computer.shared.turnOn(workersCount: (serversCount / 3).round() + 1); // Plus 1 to avoid 0.
Computer.shared.turnOn(workersCount: (serversCount / 3).round() + 1);
bakSync.sync(); bakSync.sync();
} }
@@ -135,7 +117,7 @@ Future<void> _initWindow() async {
final hideTitleBar = Stores.setting.hideTitleBar.fetch(); final hideTitleBar = Stores.setting.hideTitleBar.fetch();
await SystemUIs.initDesktopWindow( await SystemUIs.initDesktopWindow(
hideTitleBar: hideTitleBar, hideTitleBar: hideTitleBar,
size: windowState?.size, size: windowState?.size ?? Size(947, 487),
position: windowState?.position, position: windowState?.position,
listener: WindowStateListener(windowStateProp), listener: WindowStateListener(windowStateProp),
); );

View File

@@ -6,7 +6,8 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/core/sync.dart'; import 'package:server_box/core/sync.dart';
import 'package:server_box/data/model/app/backup.dart'; import 'package:server_box/data/model/app/bak/backup2.dart';
import 'package:server_box/data/model/app/bak/utils.dart';
import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/model/server/snippet.dart'; import 'package:server_box/data/model/server/snippet.dart';
import 'package:server_box/data/provider/snippet.dart'; import 'package:server_box/data/provider/snippet.dart';
@@ -27,14 +28,11 @@ class BackupPage extends StatefulWidget {
); );
} }
final class _BackupPageState extends State<BackupPage> final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveClientMixin {
with AutomaticKeepAliveClientMixin {
final icloudLoading = false.vn;
final webdavLoading = false.vn; final webdavLoading = false.vn;
@override @override
void dispose() { void dispose() {
icloudLoading.dispose();
webdavLoading.dispose(); webdavLoading.dispose();
super.dispose(); super.dispose();
} }
@@ -89,7 +87,7 @@ final class _BackupPageState extends State<BackupPage>
title: Text(libL10n.backup), title: Text(libL10n.backup),
trailing: const Icon(Icons.save), trailing: const Icon(Icons.save),
onTap: () async { onTap: () async {
final path = await Backup.backup(); final path = await BackupV2.backup();
await Pfs.sharePaths(paths: [path]); await Pfs.sharePaths(paths: [path]);
}, },
), ),
@@ -110,19 +108,15 @@ final class _BackupPageState extends State<BackupPage>
title: const Text('iCloud'), title: const Text('iCloud'),
trailing: StoreSwitch( trailing: StoreSwitch(
prop: PrefProps.icloudSync, prop: PrefProps.icloudSync,
validator: (p0) { validator: (p0) async {
if (p0 && PrefProps.webdavSync.get()) { if (p0 && PrefProps.webdavSync.get()) {
context.showSnackBar(l10n.autoBackupConflict); context.showSnackBar(l10n.autoBackupConflict);
return false; return false;
} }
return true; if (p0) {
},
callback: (val) async {
if (val) {
icloudLoading.value = true;
await bakSync.sync(rs: icloud); await bakSync.sync(rs: icloud);
icloudLoading.value = false;
} }
return true;
}, },
), ),
), ),
@@ -145,7 +139,11 @@ final class _BackupPageState extends State<BackupPage>
title: Text(libL10n.auto), title: Text(libL10n.auto),
trailing: StoreSwitch( trailing: StoreSwitch(
prop: PrefProps.webdavSync, prop: PrefProps.webdavSync,
validator: (p0) { validator: (p0) async {
if (p0 && PrefProps.icloudSync.get()) {
context.showSnackBar(l10n.autoBackupConflict);
return false;
}
if (p0) { if (p0) {
final url = PrefProps.webdavUrl.get(); final url = PrefProps.webdavUrl.get();
final user = PrefProps.webdavUser.get(); final user = PrefProps.webdavUser.get();
@@ -162,28 +160,20 @@ final class _BackupPageState extends State<BackupPage>
context.showSnackBar(l10n.webdavSettingEmpty); context.showSnackBar(l10n.webdavSettingEmpty);
return false; return false;
} }
}
if (PrefProps.icloudSync.get()) {
context.showSnackBar(l10n.autoBackupConflict);
return false;
}
return true;
},
callback: (val) async {
if (val) {
webdavLoading.value = true; webdavLoading.value = true;
await bakSync.sync(rs: Webdav.shared); await bakSync.sync(rs: Webdav.shared);
webdavLoading.value = false; webdavLoading.value = false;
} }
return true;
}, },
), ),
), ),
ListTile( ListTile(
title: Text(l10n.manual), title: Text(l10n.manual),
trailing: ListenableBuilder( trailing: webdavLoading.listenVal(
listenable: webdavLoading, (loading) {
builder: (_, __) { if (loading) return SizedLoading.small;
if (webdavLoading.value) return SizedLoading.small;
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -217,7 +207,7 @@ final class _BackupPageState extends State<BackupPage>
title: Text(libL10n.backup), title: Text(libL10n.backup),
trailing: const Icon(Icons.save), trailing: const Icon(Icons.save),
onTap: () async { onTap: () async {
final path = await Backup.backup(); final path = await BackupV2.backup();
Pfs.copy(await File(path).readAsString()); Pfs.copy(await File(path).readAsString());
context.showSnackBar(libL10n.success); context.showSnackBar(libL10n.success);
}, },
@@ -310,22 +300,18 @@ final class _BackupPageState extends State<BackupPage>
try { try {
final (backup, err) = await context.showLoadingDialog( final (backup, err) = await context.showLoadingDialog(
fn: () => Computer.shared.start(Backup.fromJsonString, text.trim()), fn: () => Computer.shared.start(MergeableUtils.fromJsonString, text.trim()),
); );
if (err != null || backup == null) return; if (err != null || backup == null) return;
if (backupFormatVersion != backup.version) {
context.showSnackBar(l10n.backupVersionNotMatch);
return;
}
await context.showRoundDialog( await context.showRoundDialog(
title: libL10n.restore, title: libL10n.restore,
child: Text(libL10n.askContinue( child: Text(libL10n.askContinue(
'${libL10n.restore} ${libL10n.backup}(${backup.date})', '${libL10n.restore} ${libL10n.backup}(${backup.$2})',
)), )),
actions: Btn.ok( actions: Btn.ok(
onTap: () async { onTap: () async {
await backup.merge(force: true); await backup.$1.merge(force: true);
context.pop(); context.pop();
}, },
).toList, ).toList,
@@ -350,7 +336,7 @@ final class _BackupPageState extends State<BackupPage>
await Webdav.shared.download(relativePath: fileName); await Webdav.shared.download(relativePath: fileName);
final dlFile = await File('${Paths.doc}/$fileName').readAsString(); final dlFile = await File('${Paths.doc}/$fileName').readAsString();
final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile); final dlBak = await Computer.shared.start(BackupV2.fromJsonString, dlFile);
await dlBak.merge(force: true); await dlBak.merge(force: true);
} catch (e, s) { } catch (e, s) {
context.showErrDialog(e, s, libL10n.restore); context.showErrDialog(e, s, libL10n.restore);
@@ -365,7 +351,7 @@ final class _BackupPageState extends State<BackupPage>
final date = DateTime.now().ymdhms(ymdSep: '-', hmsSep: '-', sep: '-'); final date = DateTime.now().ymdhms(ymdSep: '-', hmsSep: '-', sep: '-');
final bakName = '$date-${Miscs.bakFileName}'; final bakName = '$date-${Miscs.bakFileName}';
try { try {
await Backup.backup(bakName); await BackupV2.backup(bakName);
await Webdav.shared.upload(relativePath: bakName); await Webdav.shared.upload(relativePath: bakName);
Loggers.app.info('Upload webdav backup success'); Loggers.app.info('Upload webdav backup success');
} catch (e, s) { } catch (e, s) {
@@ -421,8 +407,7 @@ final class _BackupPageState extends State<BackupPage>
await Webdav.test(url_, user_, pwd_); await Webdav.test(url_, user_, pwd_);
context.showSnackBar(libL10n.success); context.showSnackBar(libL10n.success);
Webdav.shared.client = Webdav.shared.client = WebdavClient.basicAuth(url: url_, user: user_, pwd: pwd_);
WebdavClient.basicAuth(url: url_, user: user_, pwd: pwd_);
PrefProps.webdavUrl.set(url_); PrefProps.webdavUrl.set(url_);
PrefProps.webdavUser.set(user_); PrefProps.webdavUser.set(user_);
PrefProps.webdavPwd.set(pwd_); PrefProps.webdavPwd.set(pwd_);
@@ -441,23 +426,18 @@ final class _BackupPageState extends State<BackupPage>
try { try {
final (backup, err) = await context.showLoadingDialog( final (backup, err) = await context.showLoadingDialog(
fn: () => Computer.shared.start(Backup.fromJsonString, text.trim()), fn: () => Computer.shared.start(MergeableUtils.fromJsonString, text.trim()),
); );
if (err != null || backup == null) return; if (err != null || backup == null) return;
if (backupFormatVersion != backup.version) {
context.showSnackBar(l10n.backupVersionNotMatch);
return;
}
await context.showRoundDialog( await context.showRoundDialog(
title: libL10n.restore, title: libL10n.restore,
child: Text(libL10n.askContinue( child: Text(libL10n.askContinue(
'${libL10n.restore} ${libL10n.backup}(${backup.date})', '${libL10n.restore} ${libL10n.backup}(${backup.$2})',
)), )),
actions: Btn.ok( actions: Btn.ok(
onTap: () async { onTap: () async {
await backup.merge(force: true); await backup.$1.merge(force: true);
context.pop(); context.pop();
}, },
).toList, ).toList,

View File

@@ -7,8 +7,10 @@ extension on _ServerPageState {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
ConstrainedBox( LayoutBuilder(
constraints: BoxConstraints(maxWidth: _media.size.width / 2.3), builder: (_, cons) {
return ConstrainedBox(
constraints: BoxConstraints(maxWidth: cons.maxWidth / 2.3),
child: Hero( child: Hero(
tag: 'home_card_title_${s.spi.id}', tag: 'home_card_title_${s.spi.id}',
transitionOnUserGestures: true, transitionOnUserGestures: true,
@@ -16,20 +18,16 @@ extension on _ServerPageState {
color: Colors.transparent, color: Colors.transparent,
child: Text( child: Text(
s.spi.name, s.spi.name,
style: UIs.text13Bold.copyWith( style: UIs.text13Bold.copyWith(color: context.isDark ? Colors.white : Colors.black),
color: context.isDark ? Colors.white : Colors.black,
),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), ),
), ),
);
},
), ),
const Icon( const Icon(Icons.keyboard_arrow_right, size: 17, color: Colors.grey),
Icons.keyboard_arrow_right,
size: 17,
color: Colors.grey,
),
const Spacer(), const Spacer(),
_buildTopRightText(s), _buildTopRightText(s),
_buildTopRightWidget(s), _buildTopRightWidget(s),
@@ -60,7 +58,7 @@ extension on _ServerPageState {
), ),
ServerConn.disconnected => ( ServerConn.disconnected => (
const Icon(MingCute.link_3_line, size: 19, color: Colors.grey), const Icon(MingCute.link_3_line, size: 19, color: Colors.grey),
() => ServerProvider.refresh(spi: s.spi) () => ServerProvider.refresh(spi: s.spi),
), ),
ServerConn.finished => ( ServerConn.finished => (
const Icon(MingCute.unlink_2_line, size: 17, color: Colors.grey), const Icon(MingCute.unlink_2_line, size: 17, color: Colors.grey),
@@ -73,11 +71,7 @@ extension on _ServerPageState {
? child ? child
: SizedBox(height: _ServerPageState._kCardHeightMin, width: 27, child: child); : SizedBox(height: _ServerPageState._kCardHeightMin, width: 27, child: child);
if (onTap == null) return wrapped.paddingOnly(left: 10); if (onTap == null) return wrapped.paddingOnly(left: 10);
return InkWell( return InkWell(borderRadius: BorderRadius.circular(7), onTap: onTap, child: wrapped).paddingOnly(left: 5);
borderRadius: BorderRadius.circular(7),
onTap: onTap,
child: wrapped,
).paddingOnly(left: 5);
} }
Widget _buildTopRightText(Server s) { Widget _buildTopRightText(Server s) {
@@ -94,7 +88,8 @@ extension on _ServerPageState {
} }
void _showFailReason(ServerStatus ss) { void _showFailReason(ServerStatus ss) {
final md = ''' final md =
'''
${ss.err?.solution ?? l10n.unknown} ${ss.err?.solution ?? l10n.unknown}
```sh ```sh
@@ -103,12 +98,7 @@ ${ss.err?.message ?? 'null'}
context.showRoundDialog( context.showRoundDialog(
title: libL10n.error, title: libL10n.error,
child: SingleChildScrollView(child: SimpleMarkdown(data: md)), child: SingleChildScrollView(child: SimpleMarkdown(data: md)),
actions: [ actions: [TextButton(onPressed: () => Pfs.copy(md), child: Text(libL10n.copy))],
TextButton(
onPressed: () => Pfs.copy(md),
child: Text(libL10n.copy),
)
],
); );
} }
@@ -156,13 +146,7 @@ ${ss.err?.message ?? 'null'}
); );
} }
Widget _buildIOData( Widget _buildIOData(String up, String down, {void Function()? onTap, Key? key, int maxLines = 2}) {
String up,
String down, {
void Function()? onTap,
Key? key,
int maxLines = 2
}) {
final child = Column( final child = Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@@ -181,7 +165,7 @@ ${ss.err?.message ?? 'null'}
textAlign: TextAlign.center, textAlign: TextAlign.center,
textScaler: _textFactor, textScaler: _textFactor,
maxLines: maxLines, maxLines: maxLines,
) ),
], ],
); );
if (onTap == null) return child; if (onTap == null) return child;

View File

@@ -28,9 +28,7 @@ extension on _ServerPageState {
Widget _buildLandscapeBody() { Widget _buildLandscapeBody() {
return ServerProvider.serverOrder.listenVal((order) { return ServerProvider.serverOrder.listenVal((order) {
if (order.isEmpty) { if (order.isEmpty) {
return Center( return Center(child: Text(libL10n.empty, textAlign: TextAlign.center));
child: Text(libL10n.empty, textAlign: TextAlign.center),
);
} }
return PageView.builder( return PageView.builder(
@@ -42,14 +40,9 @@ extension on _ServerPageState {
return srv.listenVal((srv) { return srv.listenVal((srv) {
final title = _buildServerCardTitle(srv); final title = _buildServerCardTitle(srv);
final List<Widget> children = [ final List<Widget> children = [title, _buildNormalCard(srv.status, srv.spi)];
title,
_buildNormalCard(srv.status, srv.spi),
];
return Padding( return ListenableBuilder(
padding: _media.padding,
child: ListenableBuilder(
listenable: _getCardNoti(id), listenable: _getCardNoti(id),
builder: (_, __) { builder: (_, __) {
return Column( return Column(
@@ -59,7 +52,6 @@ extension on _ServerPageState {
children: children, children: children,
); );
}, },
),
); );
}); });
}, },

View File

@@ -37,18 +37,13 @@ class ServerPage extends StatefulWidget {
@override @override
State<ServerPage> createState() => _ServerPageState(); State<ServerPage> createState() => _ServerPageState();
static const route = AppRouteNoArg( static const route = AppRouteNoArg(page: ServerPage.new, path: '/servers');
page: ServerPage.new,
path: '/servers',
);
} }
const _cardPad = 74.0; const _cardPad = 74.0;
const _cardPadSingle = 13.0; const _cardPadSingle = 13.0;
class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMixin, AfterLayoutMixin { class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
late MediaQueryData _media;
late double _textFactorDouble; late double _textFactorDouble;
double _offset = 1; double _offset = 1;
late TextScaler _textFactor; late TextScaler _textFactor;
@@ -80,7 +75,6 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
_media = MediaQuery.of(context);
_updateOffset(); _updateOffset();
_updateTextScaler(); _updateTextScaler();
} }
@@ -88,7 +82,8 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
return OrientationBuilder(builder: (_, orientation) { return OrientationBuilder(
builder: (_, orientation) {
if (orientation == Orientation.landscape) { if (orientation == Orientation.landscape) {
final useFullScreen = Stores.setting.fullScreen.fetch(); final useFullScreen = Stores.setting.fullScreen.fetch();
// Only enter landscape mode when the screen is wide enough and the // Only enter landscape mode when the screen is wide enough and the
@@ -96,16 +91,13 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
if (useFullScreen) return _buildLandscape(); if (useFullScreen) return _buildLandscape();
} }
return _buildPortrait(); return _buildPortrait();
}); },
);
} }
Widget _buildScaffold(Widget child) { Widget _buildScaffold(Widget child) {
return Scaffold( return Scaffold(
appBar: _TopBar( appBar: _TopBar(tags: ServerProvider.tags, onTagChanged: (p0) => _tag.value = p0, initTag: _tag.value),
tags: ServerProvider.tags,
onTagChanged: (p0) => _tag.value = p0,
initTag: _tag.value,
),
body: GestureDetector( body: GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () => _autoHideCtrl.show(), onTap: () => _autoHideCtrl.show(),
@@ -134,10 +126,8 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
Widget _buildPortrait() { Widget _buildPortrait() {
// final isMobile = ResponsiveBreakpoints.of(context).isMobile; // final isMobile = ResponsiveBreakpoints.of(context).isMobile;
return ServerProvider.serverOrder.listenVal( return ServerProvider.serverOrder.listenVal((order) {
(order) { return _tag.listenVal((val) {
return _tag.listenVal(
(val) {
final filtered = _filterServers(order); final filtered = _filterServers(order);
final child = _buildScaffold(_buildBodySmall(filtered: filtered)); final child = _buildScaffold(_buildBodySmall(filtered: filtered));
// if (isMobile) { // if (isMobile) {
@@ -151,10 +141,8 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
// initialRight: Center(child: CircularProgressIndicator()), // initialRight: Center(child: CircularProgressIndicator()),
// leftBuilder: (_, __) => child, // leftBuilder: (_, __) => child,
// ); // );
}, });
); });
},
);
} }
Widget _buildBodySmall({ Widget _buildBodySmall({
@@ -165,34 +153,38 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
return Center(child: Text(libL10n.empty, textAlign: TextAlign.center)); return Center(child: Text(libL10n.empty, textAlign: TextAlign.center));
} }
return LayoutBuilder(
builder: (_, cons) {
// Calculate number of columns based on available width // Calculate number of columns based on available width
final columnsCount = math.max(1, (_media.size.width / UIs.columnWidth).floor()); final columnsCount = math.max(1, (cons.maxWidth / UIs.columnWidth).floor());
// Calculate number of rows needed
final rowCount = (filtered.length + columnsCount - 1) ~/ columnsCount;
return ListView.builder(
controller: _scrollController,
padding: padding,
itemCount: rowCount + 1, // +1 for the bottom space
itemBuilder: (_, rowIndex) {
// Bottom space
if (rowIndex == rowCount) return UIs.height77;
// Create a row of server cards
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(columnsCount, (colIndex) { children: List.generate(columnsCount, (colIndex) {
final index = rowIndex * columnsCount + colIndex; // Calculate which servers belong in this column
if (index >= filtered.length) return Expanded(child: Container()); final serversInThisColumn = <String>[];
for (int i = colIndex; i < filtered.length; i += columnsCount) {
final vnode = ServerProvider.pick(id: filtered[index]); serversInThisColumn.add(filtered[i]);
if (vnode == null) return Expanded(child: UIs.placeholder); }
final lens = serversInThisColumn.length;
return Expanded( return Expanded(
child: Padding( child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 4.0), controller: colIndex == 0 ? _scrollController : null,
padding: padding,
itemCount: lens + 1, // Add 1 for bottom spacing
itemBuilder: (context, index) {
// 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;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 0),
child: vnode.listenVal(_buildEachServerCard), child: vnode.listenVal(_buildEachServerCard),
);
},
), ),
); );
}), }),
@@ -227,13 +219,12 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
/// The child's width mat not equal to 1/4 of the screen width, /// The child's width mat not equal to 1/4 of the screen width,
/// so we need to wrap it with a SizedBox. /// so we need to wrap it with a SizedBox.
Widget _wrapWithSizedbox(Widget child, double maxWidth, [bool circle = false]) { Widget _wrapWithSizedbox(Widget child, double maxWidth, [bool circle = false]) {
return LayoutBuilder(builder: (_, cons) { return LayoutBuilder(
builder: (_, cons) {
final width = (maxWidth - _cardPad) / 4; final width = (maxWidth - _cardPad) / 4;
return SizedBox( return SizedBox(width: width, child: child);
width: width, },
child: child,
); );
});
} }
Widget _buildRealServerCard(Server srv) { Widget _buildRealServerCard(Server srv) {
@@ -300,12 +291,13 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
icon: const Icon(Icons.edit, color: color), icon: const Icon(Icons.edit, color: color),
text: libL10n.edit, text: libL10n.edit,
textStyle: textStyle, textStyle: textStyle,
) ),
]; ];
return Padding( return Padding(
padding: const EdgeInsets.only(top: 9), padding: const EdgeInsets.only(top: 9),
child: LayoutBuilder(builder: (_, cons) { child: LayoutBuilder(
builder: (_, cons) {
final width = (cons.maxWidth - _cardPad) / children.length; final width = (cons.maxWidth - _cardPad) / children.length;
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
@@ -314,12 +306,14 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
return SizedBox(width: width, child: e); return SizedBox(width: width, child: e);
}).toList(), }).toList(),
); );
}), },
),
); );
} }
Widget _buildNormalCard(ServerStatus ss, Spi spi) { Widget _buildNormalCard(ServerStatus ss, Spi spi) {
return LayoutBuilder(builder: (_, cons) { return LayoutBuilder(
builder: (_, cons) {
final maxWidth = cons.maxWidth; final maxWidth = cons.maxWidth;
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -329,11 +323,7 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
_wrapWithSizedbox(PercentCircle(percent: ss.cpu.usedPercent()), maxWidth, true), _wrapWithSizedbox(PercentCircle(percent: ss.cpu.usedPercent()), maxWidth, true),
_wrapWithSizedbox( _wrapWithSizedbox(PercentCircle(percent: ss.mem.usedPercent * 100), maxWidth, true),
PercentCircle(percent: ss.mem.usedPercent * 100),
maxWidth,
true,
),
_wrapWithSizedbox(_buildNet(ss, spi.id), maxWidth), _wrapWithSizedbox(_buildNet(ss, spi.id), maxWidth),
_wrapWithSizedbox(_buildDisk(ss, spi.id), maxWidth), _wrapWithSizedbox(_buildDisk(ss, spi.id), maxWidth),
], ],
@@ -342,13 +332,11 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
if (Stores.setting.moveServerFuncs.fetch() && if (Stores.setting.moveServerFuncs.fetch() &&
// Discussion #146 // Discussion #146
!Stores.setting.serverTabUseOldUI.fetch()) !Stores.setting.serverTabUseOldUI.fetch())
SizedBox( SizedBox(height: 27, child: ServerFuncBtns(spi: spi)),
height: 27,
child: ServerFuncBtns(spi: spi),
),
], ],
); );
}); },
);
} }
@override @override

View File

@@ -164,7 +164,7 @@ extension _Utils on _ServerPageState {
void _updateOffset() { void _updateOffset() {
if (!Stores.setting.fullScreenJitter.fetch()) return; if (!Stores.setting.fullScreenJitter.fetch()) return;
final x = _media.size.height * 0.03; final x = MediaQuery.sizeOf(context).height * 0.03;
final r = math.Random().nextDouble(); final r = math.Random().nextDouble();
final n = math.Random().nextBool() ? 1 : -1; final n = math.Random().nextBool() ? 1 : -1;
_offset = x * r * n; _offset = x * r * n;

View File

@@ -2,6 +2,7 @@ import 'dart:ui';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/provider/server.dart'; import 'package:server_box/data/provider/server.dart';
import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/store.dart';
@@ -35,17 +36,13 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
final double scale = lerpDouble(1, 1.02, animValue)!; final double scale = lerpDouble(1, 1.02, animValue)!;
return Transform.scale( return Transform.scale(
scale: scale, scale: scale,
// Create a Card based on the color and the content of the dragged one
// and set its elevation to the animated value.
child: Card( child: Card(
elevation: elevation, elevation: elevation,
// color: cards[index].color, child: child,
// child: cards[index].child,
child: _buildCardTile(index),
), ),
); );
}, },
// child: child, child: _buildCardTile(index),
); );
} }
@@ -57,28 +54,34 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
} }
return ReorderableListView.builder( return ReorderableListView.builder(
footer: const SizedBox(height: 77), footer: const SizedBox(height: 77),
onReorder: (oldIndex, newIndex) => setState(() { onReorder: (oldIndex, newIndex) {
setState(() {
orders.value.move( orders.value.move(
oldIndex, oldIndex,
newIndex, newIndex,
property: Stores.setting.serverOrder, property: Stores.setting.serverOrder,
); );
orders.notify(); });
}), },
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3), padding: const EdgeInsets.all(8),
buildDefaultDragHandles: false, buildDefaultDragHandles: false,
itemBuilder: (_, idx) => _buildItem(idx), itemBuilder: (_, idx) => _buildItem(idx, order[idx]),
itemCount: order.length, itemCount: order.length,
proxyDecorator: _proxyDecorator, proxyDecorator: _proxyDecorator,
); );
}); });
} }
Widget _buildItem(int index) { Widget _buildItem(int index, String id) {
return ReorderableDelayedDragStartListener( return ReorderableDelayedDragStartListener(
key: ValueKey('$index'), key: ValueKey('server_item_$id'),
index: index, index: index,
child: CardX(child: _buildCardTile(index)), child: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: CardX(
child: _buildCardTile(index),
),
),
); );
} }
@@ -90,9 +93,14 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
} }
return ListTile( return ListTile(
title: Text(spi.name), title: Text(
subtitle: Text(spi.id, style: UIs.textGrey), spi.name,
style: const TextStyle(fontWeight: FontWeight.w500),
),
subtitle: Text(spi.oldId, style: UIs.textGrey),
leading: CircleAvatar( leading: CircleAvatar(
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.onPrimary,
child: Text(spi.name[0]), child: Text(spi.name[0]),
), ),
trailing: ReorderableDragStartListener( trailing: ReorderableDragStartListener(

View File

@@ -52,7 +52,7 @@ class ServerFuncBtns extends StatelessWidget {
if (btns.isEmpty) return UIs.placeholder; if (btns.isEmpty) return UIs.placeholder;
return SizedBox( return SizedBox(
height: 74, height: 77,
child: ListView.builder( child: ListView.builder(
itemCount: btns.length, itemCount: btns.length,
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,

View File

@@ -1,19 +1,19 @@
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
final class RWX { final class UnixPermOp {
final bool r; final bool r;
final bool w; final bool w;
final bool x; final bool x;
const RWX({ const UnixPermOp({
required this.r, required this.r,
required this.w, required this.w,
required this.x, required this.x,
}); });
RWX copyWith({bool? r, bool? w, bool? x}) { UnixPermOp copyWith({bool? r, bool? w, bool? x}) {
return RWX(r: r ?? this.r, w: w ?? this.w, x: x ?? this.x); return UnixPermOp(r: r ?? this.r, w: w ?? this.w, x: x ?? this.x);
} }
int get value { int get value {
@@ -37,9 +37,9 @@ enum UnixPermScope {
} }
final class UnixPerm { final class UnixPerm {
final RWX user; final UnixPermOp user;
final RWX group; final UnixPermOp group;
final RWX other; final UnixPermOp other;
const UnixPerm({ const UnixPerm({
required this.user, required this.user,
@@ -47,7 +47,7 @@ final class UnixPerm {
required this.other, required this.other,
}); });
UnixPerm copyWith({RWX? user, RWX? group, RWX? other}) { UnixPerm copyWith({UnixPermOp? user, UnixPermOp? group, UnixPermOp? other}) {
return UnixPerm( return UnixPerm(
user: user ?? this.user, user: user ?? this.user,
group: group ?? this.group, group: group ?? this.group,
@@ -55,7 +55,7 @@ final class UnixPerm {
); );
} }
UnixPerm copyWithScope(UnixPermScope scope, RWX rwx) { UnixPerm copyWithScope(UnixPermScope scope, UnixPermOp rwx) {
switch (scope) { switch (scope) {
case UnixPermScope.user: case UnixPermScope.user:
return copyWith(user: rwx); return copyWith(user: rwx);
@@ -72,9 +72,9 @@ final class UnixPerm {
} }
static UnixPerm get empty => const UnixPerm( static UnixPerm get empty => const UnixPerm(
user: RWX(r: false, w: false, x: false), user: UnixPermOp(r: false, w: false, x: false),
group: RWX(r: false, w: false, x: false), group: UnixPermOp(r: false, w: false, x: false),
other: RWX(r: false, w: false, x: false), other: UnixPermOp(r: false, w: false, x: false),
); );
} }
@@ -110,7 +110,7 @@ final class _UnixPermEditorState extends State<UnixPermEditor> {
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
Text('Read'), Text('Read'),
Text('Write'), Text('Writ'), // Keep it short to fit UI
Text('Exec'), Text('Exec'),
], ],
).paddingOnly(left: 13), ).paddingOnly(left: 13),
@@ -122,7 +122,7 @@ final class _UnixPermEditorState extends State<UnixPermEditor> {
); );
} }
Widget _buildRow(UnixPermScope scope, RWX rwx) { Widget _buildRow(UnixPermScope scope, UnixPermOp rwx) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [

View File

@@ -27,7 +27,7 @@ PODS:
- FlutterMacOS - FlutterMacOS
- wakelock_plus (0.0.1): - wakelock_plus (0.0.1):
- FlutterMacOS - FlutterMacOS
- window_manager (0.2.0): - window_manager (0.5.0):
- FlutterMacOS - FlutterMacOS
DEPENDENCIES: DEPENDENCIES:
@@ -90,7 +90,7 @@ SPEC CHECKSUMS:
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497 wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497
window_manager: 1d01fa7ac65a6e6f83b965471b1a7fdd3f06166c window_manager: b729e31d38fb04905235df9ea896128991cad99e
PODFILE CHECKSUM: 8cdf29216ea1ab6b9743188287968d22b4579c1d PODFILE CHECKSUM: 8cdf29216ea1ab6b9743188287968d22b4579c1d

View File

@@ -5,31 +5,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" sha256: dc27559385e905ad30838356c5f5d574014ba39872d732111cd07ac0beff4c57
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "76.0.0" version: "80.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.3"
analyzer: analyzer:
dependency: transitive dependency: "direct dev"
description: description:
name: analyzer name: analyzer
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" sha256: "192d1c5b944e7e53b24b5586db760db934b177d4147c42fbca8c8c5f1eb8d11e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.11.0" version: "7.3.0"
analyzer_plugin: analyzer_plugin:
dependency: transitive dependency: transitive
description: description:
name: analyzer_plugin name: analyzer_plugin
sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161" sha256: b3075265c5ab222f8b3188342dcb50b476286394a40323e85d1fa725035d40a4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.11.3" version: "0.13.0"
animations: animations:
dependency: transitive dependency: transitive
description: description:
@@ -178,10 +173,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
sha256: ea90e81dc4a25a043d9bee692d20ed6d1c4a1662a28c03a96417446c093ed6b4 sha256: "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.9.5" version: "8.10.1"
camera: camera:
dependency: transitive dependency: transitive
description: description:
@@ -194,10 +189,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: camera_android_camerax name: camera_android_camerax
sha256: f0dcbce91623f75030840609de9b64d0d73f86df279c6e9588c1501245a05eb2 sha256: "0bd3d1645df00af2540a22df13ba466ac5fb2838a09bce4089cecdb1712a9e94"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.15+2" version: "0.6.18"
camera_avfoundation: camera_avfoundation:
dependency: transitive dependency: transitive
description: description:
@@ -254,14 +249,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.3.2"
ci:
dependency: transitive
description:
name: ci
sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13"
url: "https://pub.dev"
source: hosted
version: "0.1.0"
circle_chart: circle_chart:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -271,14 +258,6 @@ packages:
url: "https://github.com/lollipopkit/circle_chart" url: "https://github.com/lollipopkit/circle_chart"
source: git source: git
version: "0.0.3" version: "0.0.3"
cli_util:
dependency: transitive
description:
name: cli_util
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
url: "https://pub.dev"
source: hosted
version: "0.4.2"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@@ -344,46 +323,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "1.0.2"
custom_lint:
dependency: "direct dev"
description:
name: custom_lint
sha256: "3486c470bb93313a9417f926c7dd694a2e349220992d7b9d14534dc49c15bba9"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
custom_lint_builder:
dependency: transitive
description:
name: custom_lint_builder
sha256: "42cdc41994eeeddab0d7a722c7093ec52bd0761921eeb2cbdbf33d192a234759"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
custom_lint_core: custom_lint_core:
dependency: transitive dependency: transitive
description: description:
name: custom_lint_core name: custom_lint_core
sha256: "02450c3e45e2a6e8b26c4d16687596ab3c4644dd5792e3313aa9ceba5a49b7f5" sha256: "31110af3dde9d29fb10828ca33f1dce24d2798477b167675543ce3d208dee8be"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.0" version: "0.7.5"
custom_lint_visitor: custom_lint_visitor:
dependency: transitive dependency: transitive
description: description:
name: custom_lint_visitor name: custom_lint_visitor
sha256: bfe9b7a09c4775a587b58d10ebb871d4fe618237639b1e84d5ec62d7dfef25f9 sha256: "36282d85714af494ee2d7da8c8913630aa6694da99f104fb2ed4afcf8fc857d8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0+6.11.0" version: "1.0.0+7.3.0"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820" sha256: "5b236382b47ee411741447c1f1e111459c941ea1b3f2b540dde54c210a3662af"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.8" version: "3.1.0"
dartssh2: dartssh2:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -517,9 +480,11 @@ packages:
fl_lib: fl_lib:
dependency: "direct main" dependency: "direct main"
description: description:
path: "../fl_lib" path: "."
relative: true ref: "v1.0.313"
source: path resolved-ref: "234dc4cd1f4c7bbcdb12834dc674f65c243dd8e4"
url: "https://github.com/lppcg/fl_lib"
source: git
version: "0.0.1" version: "0.0.1"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
@@ -559,10 +524,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_markdown name: flutter_markdown
sha256: "634622a3a826d67cb05c0e3e576d1812c430fa98404e95b60b131775c73d76ec" sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.7" version: "0.7.7+1"
flutter_markdown_latex: flutter_markdown_latex:
dependency: transitive dependency: transitive
description: description:
@@ -576,7 +541,7 @@ packages:
description: description:
path: "." path: "."
ref: HEAD ref: HEAD
resolved-ref: "127cf24e01bff00a4e25a4820295a871020f7a94" resolved-ref: "2f270aee06d3ca02ca6d108420921472fd10e5cb"
url: "https://github.com/simpleclub/flutter_math" url: "https://github.com/simpleclub/flutter_math"
source: git source: git
version: "0.7.4" version: "0.7.4"
@@ -626,10 +591,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: freezed name: freezed
sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e" sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.7" version: "2.5.8"
freezed_annotation: freezed_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -678,38 +643,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.0" version: "0.7.0"
hive: hive_ce:
dependency: transitive dependency: transitive
description: description:
name: hive name: hive_ce
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" sha256: "708bb39050998707c5d422752159f91944d3c81ab42d80e1bd0ee37d8e130658"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.3" version: "2.11.3"
hive_flutter: hive_ce_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
name: hive_flutter name: hive_ce_flutter
sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc sha256: a0989670652eab097b47544f1e5a4456e861b1b01b050098ea0b80a5fabe9909
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "2.3.1"
hive_generator: hive_ce_generator:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: hive_generator name: hive_ce_generator
sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" sha256: "609678c10ebee7503505a0007050af40a0a4f498b1fb7def3220df341e573a89"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "1.9.2"
hotreloader:
dependency: transitive
description:
name: hotreloader
sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b
url: "https://pub.dev"
source: hosted
version: "4.3.0"
html: html:
dependency: transitive dependency: transitive
description: description:
@@ -722,10 +679,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: http name: http
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.4.0"
http_client_helper: http_client_helper:
dependency: transitive dependency: transitive
description: description:
@@ -790,6 +747,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.5" version: "1.0.5"
isolate_channel:
dependency: transitive
description:
name: isolate_channel
sha256: f3d36f783b301e6b312c3450eeb2656b0e7d1db81331af2a151d9083a3f6b18d
url: "https://pub.dev"
source: hosted
version: "0.2.2+1"
isolate_contactor: isolate_contactor:
dependency: transitive dependency: transitive
description: description:
@@ -826,10 +791,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: json_serializable name: json_serializable
sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c sha256: c50ef5fc083d5b5e12eef489503ba3bf5ccc899e487d691584699b4bdefeea8c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.9.0" version: "6.9.5"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
@@ -918,14 +883,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
macros:
dependency: transitive
description:
name: macros
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
url: "https://pub.dev"
source: hosted
version: "0.1.3-main.0"
markdown: markdown:
dependency: transitive dependency: transitive
description: description:
@@ -1147,10 +1104,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: provider name: provider
sha256: "489024f942069c2920c844ee18bb3d467c69e48955a4f32d1677f71be103e310" sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.4" version: "6.1.5"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
@@ -1235,10 +1192,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: riverpod_analyzer_utils name: riverpod_analyzer_utils
sha256: c6b8222b2b483cb87ae77ad147d6408f400c64f060df7a225b127f4afef4f8c8 sha256: "837a6dc33f490706c7f4632c516bcd10804ee4d9ccc8046124ca56388715fdf3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.8" version: "0.5.9"
riverpod_annotation: riverpod_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -1251,26 +1208,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: riverpod_generator name: riverpod_generator
sha256: "63546d70952015f0981361636bf8f356d9cfd9d7f6f0815e3c07789a41233188" sha256: "120d3310f687f43e7011bb213b90a436f1bbc300f0e4b251a72c39bccb017a4f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.3" version: "2.6.4"
riverpod_lint:
dependency: "direct dev"
description:
name: riverpod_lint
sha256: "83e4caa337a9840469b7b9bd8c2351ce85abad80f570d84146911b32086fbd99"
url: "https://pub.dev"
source: hosted
version: "2.6.3"
rxdart:
dependency: transitive
description:
name: rxdart
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
url: "https://pub.dev"
source: hosted
version: "0.28.0"
screen_retriever: screen_retriever:
dependency: transitive dependency: transitive
description: description:
@@ -1416,10 +1357,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_gen name: source_gen
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.0" version: "2.0.0"
source_helper: source_helper:
dependency: transitive dependency: transitive
description: description:
@@ -1624,10 +1565,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vector_graphics_compiler name: vector_graphics_compiler
sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" sha256: "557a315b7d2a6dbb0aaaff84d857967ce6bdc96a63dc6ee2a57ce5a6ee5d3331"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.16" version: "1.1.17"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@@ -1697,10 +1638,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: web_socket name: web_socket
sha256: bfe6f435f6ec49cb6c01da1e275ae4228719e59a6b067048c51e72d9d63bcc4b sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.1"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
@@ -1721,18 +1662,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: dc6ecaa00a7c708e5b4d10ee7bec8c270e9276dfcab1783f57e9962d7884305f sha256: "329edf97fdd893e0f1e3b9e88d6a0e627128cc17cc316a8d67fda8f1451178ba"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.12.0" version: "5.13.0"
window_manager: window_manager:
dependency: transitive dependency: transitive
description: description:
name: window_manager name: window_manager
sha256: "732896e1416297c63c9e3fb95aea72d0355f61390263982a47fd519169dc5059" sha256: "51d50168ab267d344b975b15390426b1243600d436770d3f13de67e55b05ec16"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.4.3" version: "0.5.0"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
@@ -1766,6 +1707,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
yaml_writer:
dependency: transitive
description:
name: yaml_writer
sha256: "69651cd7238411179ac32079937d4aa9a2970150d6b2ae2c6fe6de09402a5dc5"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
zmodem: zmodem:
dependency: transitive dependency: transitive
description: description:
@@ -1783,5 +1732,5 @@ packages:
source: hosted source: hosted
version: "1.1.2" version: "1.1.2"
sdks: sdks:
dart: ">=3.7.0 <4.0.0" dart: ">=3.8.0 <4.0.0"
flutter: ">=3.29.0" flutter: ">=3.32.1"

View File

@@ -4,14 +4,15 @@ publish_to: "none"
version: 1.0.1128+1128 version: 1.0.1128+1128
environment: environment:
sdk: ">=3.0.0" sdk: ">=3.8.0"
flutter: ">=3.32.1"
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
hive_flutter: ^1.1.0 hive_ce_flutter: ^2.3.1
dio: ^5.2.1 dio: ^5.2.1
easy_isolate: ^1.3.0 easy_isolate: ^1.3.0
intl: ^0.20.2 intl: ^0.20.2
@@ -61,7 +62,7 @@ dependencies:
fl_lib: fl_lib:
git: git:
url: https://github.com/lppcg/fl_lib url: https://github.com/lppcg/fl_lib
ref: v1.0.300 ref: v1.0.313
dependency_overrides: dependency_overrides:
# webdav_client_plus: # webdav_client_plus:
@@ -70,24 +71,23 @@ dependency_overrides:
# path: ../dartssh2 # path: ../dartssh2
# xterm: # xterm:
# path: ../xterm.dart # path: ../xterm.dart
fl_lib: # fl_lib:
path: ../fl_lib # path: ../fl_lib
# fl_build: # fl_build:
# path: ../fl_build # path: ../fl_build
flutter_math_fork: flutter_math_fork: # Refer to https://github.com/simpleclub/flutter_math/issues/110
git: git:
url: https://github.com/simpleclub/flutter_math url: https://github.com/simpleclub/flutter_math
dev_dependencies: dev_dependencies:
analyzer: ^7.3.0
flutter_native_splash: ^2.1.6 flutter_native_splash: ^2.1.6
hive_generator: ^2.0.0 hive_ce_generator: ^1.9.2
build_runner: ^2.4.15 build_runner: ^2.4.15
flutter_lints: ^5.0.0 flutter_lints: ^5.0.0
json_serializable: ^6.8.0 json_serializable: ^6.8.0
freezed: ^2.5.7 freezed: ^2.5.7
riverpod_generator: ^2.6.3 riverpod_generator: ^2.6.3
custom_lint: ^0.7.0
riverpod_lint: ^2.6.3
flutter_test: flutter_test:
sdk: flutter sdk: flutter
fl_build: fl_build: