optimization: desktop UI (#747)

This commit is contained in:
lollipopkit🏳️‍⚧️
2025-05-13 04:57:37 +08:00
committed by GitHub
parent e520929411
commit 8627ff823f
52 changed files with 2459 additions and 1990 deletions

View File

@@ -1,7 +1,7 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/view/page/server/tab.dart';
import 'package:server_box/view/page/server/tab/tab.dart';
// import 'package:server_box/view/page/setting/entry.dart';
import 'package:server_box/view/page/snippet/list.dart';
import 'package:server_box/view/page/ssh/tab.dart';

View File

@@ -1,5 +1,6 @@
import 'dart:convert';
import 'package:equatable/equatable.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:json_annotation/json_annotation.dart';
@@ -20,7 +21,7 @@ part 'server_private_info.g.dart';
/// Nowaday, more fields are added to this class, and it's renamed to `Spi`.
@JsonSerializable()
@HiveType(typeId: 3)
class Spi {
class Spi with EquatableMixin {
@HiveField(0)
final String name;
@HiveField(1)
@@ -81,6 +82,10 @@ class Spi {
@override
String toString() => id;
@override
List<Object?> get props =>
[name, ip, port, user, pwd, keyId, tags, alterUrl, autoConnect, jumpId, custom, wolCfg, envs];
}
extension Spix on Spi {

View File

@@ -1,5 +1,6 @@
import 'dart:async';
import 'package:equatable/equatable.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:json_annotation/json_annotation.dart';
@@ -10,7 +11,7 @@ part 'snippet.g.dart';
@JsonSerializable()
@HiveType(typeId: 2)
class Snippet {
class Snippet with EquatableMixin {
@HiveField(0)
final String name;
@HiveField(1)
@@ -32,11 +33,21 @@ class Snippet {
this.autoRunOn,
});
factory Snippet.fromJson(Map<String, dynamic> json) =>
_$SnippetFromJson(json);
factory Snippet.fromJson(Map<String, dynamic> json) => _$SnippetFromJson(json);
Map<String, dynamic> toJson() => _$SnippetToJson(this);
@override
List<Object?> get props => [
name,
script,
tags,
note,
autoRunOn,
];
}
extension SnippetX on Snippet {
static final fmtFinder = RegExp(r'\$\{[^{}]+\}');
String fmtWithSpi(Spi spi) {

View File

@@ -1,7 +1,27 @@
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
final class AppProvider {
const AppProvider._();
part 'app.g.dart';
part 'app.freezed.dart';
static BuildContext? ctx;
@freezed
class AppState with _$AppState {
const factory AppState({
@Default(false) bool desktopMode,
}) = _AppState;
}
@Riverpod(keepAlive: true)
class AppProvider extends _$AppProvider {
static BuildContext? ctx;
@override
AppState build() {
return const AppState();
}
void setDesktop(bool desktopMode) {
state = state.copyWith(desktopMode: desktopMode);
}
}

View File

@@ -0,0 +1,144 @@
// 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 'app.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');
/// @nodoc
mixin _$AppState {
bool get desktopMode => throw _privateConstructorUsedError;
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$AppStateCopyWith<AppState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $AppStateCopyWith<$Res> {
factory $AppStateCopyWith(AppState value, $Res Function(AppState) then) =
_$AppStateCopyWithImpl<$Res, AppState>;
@useResult
$Res call({bool desktopMode});
}
/// @nodoc
class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
implements $AppStateCopyWith<$Res> {
_$AppStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? desktopMode = null,
}) {
return _then(_value.copyWith(
desktopMode: null == desktopMode
? _value.desktopMode
: desktopMode // ignore: cast_nullable_to_non_nullable
as bool,
) as $Val);
}
}
/// @nodoc
abstract class _$$AppStateImplCopyWith<$Res>
implements $AppStateCopyWith<$Res> {
factory _$$AppStateImplCopyWith(
_$AppStateImpl value, $Res Function(_$AppStateImpl) then) =
__$$AppStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({bool desktopMode});
}
/// @nodoc
class __$$AppStateImplCopyWithImpl<$Res>
extends _$AppStateCopyWithImpl<$Res, _$AppStateImpl>
implements _$$AppStateImplCopyWith<$Res> {
__$$AppStateImplCopyWithImpl(
_$AppStateImpl _value, $Res Function(_$AppStateImpl) _then)
: super(_value, _then);
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? desktopMode = null,
}) {
return _then(_$AppStateImpl(
desktopMode: null == desktopMode
? _value.desktopMode
: desktopMode // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
/// @nodoc
class _$AppStateImpl implements _AppState {
const _$AppStateImpl({this.desktopMode = false});
@override
@JsonKey()
final bool desktopMode;
@override
String toString() {
return 'AppState(desktopMode: $desktopMode)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$AppStateImpl &&
(identical(other.desktopMode, desktopMode) ||
other.desktopMode == desktopMode));
}
@override
int get hashCode => Object.hash(runtimeType, desktopMode);
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$AppStateImplCopyWith<_$AppStateImpl> get copyWith =>
__$$AppStateImplCopyWithImpl<_$AppStateImpl>(this, _$identity);
}
abstract class _AppState implements AppState {
const factory _AppState({final bool desktopMode}) = _$AppStateImpl;
@override
bool get desktopMode;
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$AppStateImplCopyWith<_$AppStateImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,24 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'app.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$appProviderHash() => r'8378ec9d0a9c8d99cc05805047cd2d52ac4dbb56';
/// See also [AppProvider].
@ProviderFor(AppProvider)
final appProviderProvider = NotifierProvider<AppProvider, AppState>.internal(
AppProvider.new,
name: r'appProviderProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') ? null : _$appProviderHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$AppProvider = Notifier<AppState>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

View File

@@ -14,15 +14,14 @@ class SnippetStore extends HiveStore {
}
List<Snippet> fetch() {
final keys = box.keys;
final ss = <Snippet>[];
for (final key in keys) {
final ss = <Snippet>{};
for (final key in keys()) {
final s = box.get(key);
if (s != null && s is Snippet) {
ss.add(s);
}
}
return ss;
return ss.toList();
}
void delete(Snippet s) {