opt.: file view (#249)

This commit is contained in:
lollipopkit
2024-01-16 11:42:30 +08:00
parent 9eeacb3bdd
commit ee96f2696e
18 changed files with 212 additions and 33 deletions

View File

@@ -1348,6 +1348,12 @@ abstract class S {
/// **'Shutdown'**
String get shutdown;
/// No description provided for @size.
///
/// In en, this message translates to:
/// **'Size'**
String get size;
/// No description provided for @snippet.
///
/// In en, this message translates to:
@@ -1474,6 +1480,12 @@ abstract class S {
/// **'Theme mode'**
String get themeMode;
/// No description provided for @time.
///
/// In en, this message translates to:
/// **'Time'**
String get time;
/// No description provided for @times.
///
/// In en, this message translates to:

View File

@@ -654,6 +654,9 @@ class SDe extends S {
@override
String get shutdown => 'Abschaltung';
@override
String get size => 'Größe';
@override
String get snippet => 'Snippet';
@@ -721,6 +724,9 @@ class SDe extends S {
@override
String get themeMode => 'Themen-Modus';
@override
String get time => 'Zeit';
@override
String get times => 'x';

View File

@@ -654,6 +654,9 @@ class SEn extends S {
@override
String get shutdown => 'Shutdown';
@override
String get size => 'Size';
@override
String get snippet => 'Snippet';
@@ -721,6 +724,9 @@ class SEn extends S {
@override
String get themeMode => 'Theme mode';
@override
String get time => 'Time';
@override
String get times => 'Times';

View File

@@ -654,6 +654,9 @@ class SFr extends S {
@override
String get shutdown => 'Éteindre';
@override
String get size => 'Taille';
@override
String get snippet => 'Extrait';
@@ -721,6 +724,9 @@ class SFr extends S {
@override
String get themeMode => 'Mode du thème';
@override
String get time => 'L\'heure';
@override
String get times => 'Fois';

View File

@@ -654,6 +654,9 @@ class SId extends S {
@override
String get shutdown => 'Matikan';
@override
String get size => 'Ukuran';
@override
String get snippet => 'Snippet';
@@ -721,6 +724,9 @@ class SId extends S {
@override
String get themeMode => 'Mode tema';
@override
String get time => 'Waktu';
@override
String get times => 'Waktu';

View File

@@ -654,6 +654,9 @@ class SZh extends S {
@override
String get shutdown => '关机';
@override
String get size => '大小';
@override
String get snippet => '代码片段';
@@ -721,6 +724,9 @@ class SZh extends S {
@override
String get themeMode => '主题模式';
@override
String get time => '时间';
@override
String get times => '';
@@ -1476,6 +1482,9 @@ class SZhTw extends SZh {
@override
String get shutdown => '关机';
@override
String get size => '大小';
@override
String get snippet => '程式片段';
@@ -1543,6 +1552,9 @@ class SZhTw extends SZh {
@override
String get themeMode => '主題模式';
@override
String get time => '時間';
@override
String get times => '';

View File

@@ -586,7 +586,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -596,7 +596,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -720,7 +720,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -730,7 +730,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -748,7 +748,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -758,7 +758,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -779,7 +779,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -792,7 +792,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
@@ -818,7 +818,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -831,7 +831,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -854,7 +854,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -867,7 +867,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -890,7 +890,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -902,7 +902,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
@@ -931,7 +931,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -943,7 +943,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;
@@ -969,7 +969,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 703;
CURRENT_PROJECT_VERSION = 704;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -981,7 +981,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.703;
MARKETING_VERSION = 1.0.704;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;

View File

@@ -1,6 +1,6 @@
import 'package:dartssh2/dartssh2.dart';
extension SftpFile on SftpFileMode {
extension SftpFileX on SftpFileMode {
String get str {
final user = _getRoleMode(userRead, userWrite, userExecute);
final group = _getRoleMode(groupRead, groupWrite, groupExecute);

View File

@@ -2,9 +2,9 @@
class BuildData {
static const String name = "ServerBox";
static const int build = 703;
static const int build = 704;
static const String engine = "3.16.7";
static const String buildAt = "2024-01-14 19:40:49";
static const int modifications = 6;
static const String buildAt = "2024-01-15 18:40:44";
static const int modifications = 3;
static const int script = 34;
}

View File

@@ -208,6 +208,7 @@
"sftpSSHConnected": "SFTP Verbunden",
"showDistLogo": "Distributionslogo anzeigen",
"shutdown": "Abschaltung",
"size": "Größe",
"snippet": "Snippet",
"speed": "Tempo",
"spentTime": "Benötigte Zeit: {time}",
@@ -229,6 +230,7 @@
"textScalerTip": "1.0 => 100% (Originalgröße), funktioniert nur auf der Serverseite Teil der Schrift, nicht empfohlen zu ändern.",
"theme": "Themen",
"themeMode": "Themen-Modus",
"time": "Zeit",
"times": "x",
"traffic": "Durchflussmenge",
"ttl": "ttl",

View File

@@ -208,6 +208,7 @@
"sftpSSHConnected": "SFTP Connected",
"showDistLogo": "Show distribution logo",
"shutdown": "Shutdown",
"size": "Size",
"snippet": "Snippet",
"speed": "Speed",
"spentTime": "Spent time: {time}",
@@ -229,6 +230,7 @@
"textScalerTip": "1.0 => 100% (original size), only works on server page part of the font, not recommended to change.",
"theme": "Theme",
"themeMode": "Theme mode",
"time": "Time",
"times": "Times",
"traffic": "Traffic",
"ttl": "ttl",

View File

@@ -208,6 +208,7 @@
"sftpSSHConnected": "SFTP connecté",
"showDistLogo": "Afficher le logo de la distribution",
"shutdown": "Éteindre",
"size": "Taille",
"snippet": "Extrait",
"speed": "Vitesse",
"spentTime": "Temps écoulé : {time}",
@@ -229,6 +230,7 @@
"textScalerTip": "1.0 => 100% (taille d'origine), fonctionne uniquement sur la partie police de caractères de la page du serveur, il n'est pas recommandé de la modifier.",
"theme": "Thème",
"themeMode": "Mode du thème",
"time": "L'heure",
"times": "Fois",
"traffic": "Trafic",
"ttl": "ttl",

View File

@@ -208,6 +208,7 @@
"sftpSSHConnected": "Sftp terhubung",
"showDistLogo": "Tampilkan logo distribusi",
"shutdown": "Matikan",
"size": "Ukuran",
"snippet": "Snippet",
"speed": "Kecepatan",
"spentTime": "Menghabiskan waktu: {time}",
@@ -229,6 +230,7 @@
"textScalerTip": "1.0 => 100% (ukuran asli), hanya berfungsi pada bagian halaman server font, tidak disarankan untuk diubah.",
"theme": " Tema",
"themeMode": "Mode tema",
"time": "Waktu",
"times": "Waktu",
"traffic": "Lalu lintas",
"ttl": "ttl",

View File

@@ -208,6 +208,7 @@
"sftpSSHConnected": "SFTP 已连接...",
"showDistLogo": "显示发行版 Logo",
"shutdown": "关机",
"size": "大小",
"snippet": "代码片段",
"speed": "速度",
"spentTime": "耗时: {time}",
@@ -229,6 +230,7 @@
"textScalerTip": "1.0 => 100%(原大小),仅作用于服务器页面部分字体,不建议修改。",
"theme": "主题",
"themeMode": "主题模式",
"time": "时间",
"times": "次",
"traffic": "流量",
"ttl": "缓存时间",

View File

@@ -208,6 +208,7 @@
"sftpSSHConnected": "SFTP 已連接...",
"showDistLogo": "顯示發行版 Logo",
"shutdown": "关机",
"size": "大小",
"snippet": "程式片段",
"speed": "速度",
"spentTime": "耗時: {time}",
@@ -229,6 +230,7 @@
"textScalerTip": "1.0 => 100%(原大小),僅作用於伺服器頁面部分字體,不建議修改。",
"theme": "主題",
"themeMode": "主題模式",
"time": "時間",
"times": "次",
"traffic": "流量",
"ttl": "緩存時間",

View File

@@ -132,7 +132,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
() => delScripts = !delScripts,
),
controlAffinity: ListTileControlAffinity.leading,
subtitle: Text(l10n.deleteScripts),
title: Text(l10n.deleteScripts),
tileColor: Colors.transparent,
contentPadding: EdgeInsets.zero,
)
@@ -142,13 +142,15 @@ class _ServerEditPageState extends State<ServerEditPage> {
actions: [
TextButton(
onPressed: () async {
context.pop();
if (delScripts) {
context.showLoadingDialog();
const cmd =
'rm ${ShellFunc.srvBoxDir}/mobile_v*.sh';
await widget.spi?.server?.client?.run(cmd);
context.pop();
}
Pros.server.delServer(widget.spi!.id);
context.pop();
context.pop(true);
},
child: Text(l10n.ok, style: UIs.textRed),

View File

@@ -39,6 +39,8 @@ class LocalStoragePage extends StatefulWidget {
class _LocalStoragePageState extends State<LocalStoragePage> {
LocalPath? _path;
final _sortType = ValueNotifier(_SortType.name);
@override
void initState() {
super.initState();
@@ -73,12 +75,44 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
IconButton(
icon: const Icon(Icons.downloading),
onPressed: () => AppRoute.sftpMission().go(context),
)
),
ValueListenableBuilder<_SortType>(
valueListenable: _sortType,
builder: (context, value, child) {
return PopupMenuButton<_SortType>(
icon: const Icon(Icons.sort),
itemBuilder: (context) {
return [
PopupMenuItem(
value: _SortType.name,
child: Text(l10n.name),
),
PopupMenuItem(
value: _SortType.size,
child: Text(l10n.size),
),
PopupMenuItem(
value: _SortType.time,
child: Text(l10n.time),
),
];
},
onSelected: (value) {
_sortType.value = value;
},
);
},
),
],
),
body: FadeIn(
key: UniqueKey(),
child: _buildBody(),
child: ValueListenableBuilder(
valueListenable: _sortType,
builder: (_, val, __) {
return _buildBody();
},
),
),
bottomNavigationBar: SafeArea(child: _buildPath()),
);
@@ -129,7 +163,8 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
);
}
final dir = Directory(_path!.path);
final files = dir.listSync();
final tempFiles = dir.listSync();
final files = _sortType.value.sort(tempFiles);
return ListView.builder(
itemCount: files.length,
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 7),
@@ -142,7 +177,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
return CardX(
child: ListTile(
leading: isDir
? const Icon(Icons.folder)
? const Icon(Icons.folder_open)
: const Icon(Icons.insert_drive_file),
title: Text(fileName),
subtitle: isDir
@@ -350,3 +385,26 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
);
}
}
enum _SortType {
name,
size,
time,
;
List<FileSystemEntity> sort(List<FileSystemEntity> files) {
switch (this) {
case _SortType.name:
files.sort((a, b) => a.path.compareTo(b.path));
break;
case _SortType.size:
files.sort((a, b) => a.statSync().size.compareTo(b.statSync().size));
break;
case _SortType.time:
files.sort(
(a, b) => a.statSync().modified.compareTo(b.statSync().modified));
break;
}
return files;
}
}

View File

@@ -50,6 +50,8 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
final _status = SftpBrowserStatus();
late final _client = widget.spi.server?.client;
final _sortType = ValueNotifier(_SortType.name);
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -67,6 +69,33 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
icon: const Icon(Icons.downloading),
onPressed: () => AppRoute.sftpMission().go(context),
),
ValueListenableBuilder<_SortType>(
valueListenable: _sortType,
builder: (context, value, child) {
return PopupMenuButton<_SortType>(
icon: const Icon(Icons.sort),
itemBuilder: (context) {
return [
PopupMenuItem(
value: _SortType.name,
child: Text(l10n.name),
),
PopupMenuItem(
value: _SortType.size,
child: Text(l10n.size),
),
PopupMenuItem(
value: _SortType.time,
child: Text(l10n.time),
),
];
},
onSelected: (value) {
_sortType.value = value;
},
);
},
),
],
),
body: _buildFileView(),
@@ -244,10 +273,16 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
return RefreshIndicator(
child: FadeIn(
key: Key(widget.spi.name + _status.path!.path),
child: ListView.builder(
itemCount: _status.files!.length,
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
itemBuilder: (_, index) => _buildItem(_status.files![index]),
child: ValueListenableBuilder(
valueListenable: _sortType,
builder: (_, sortType, __) {
final files = sortType.sort(_status.files!);
return ListView.builder(
itemCount: files.length,
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
itemBuilder: (_, index) => _buildItem(files[index]),
);
},
),
),
onRefresh: () => _listDir(),
@@ -263,7 +298,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
);
return CardX(
child: ListTile(
leading: Icon(isDir ? Icons.folder : Icons.insert_drive_file),
leading: Icon(isDir ? Icons.folder_outlined : Icons.insert_drive_file),
title: Text(file.filename),
trailing: trailing,
subtitle: isDir
@@ -755,3 +790,27 @@ String _getTime(int? unixMill) {
.toString()
.replaceFirst('.000', '');
}
enum _SortType {
name,
time,
size,
;
List<SftpName> sort(List<SftpName> files) {
switch (this) {
case _SortType.name:
files.sort((a, b) => a.filename.compareTo(b.filename));
break;
case _SortType.time:
files.sort(
(a, b) => (a.attr.modifyTime ?? 0).compareTo(b.attr.modifyTime ?? 0),
);
break;
case _SortType.size:
files.sort((a, b) => (a.attr.size ?? 0).compareTo(b.attr.size ?? 0));
break;
}
return files;
}
}