mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt: Shares
This commit is contained in:
@@ -81,7 +81,7 @@ Platform | Support | Sign
|
|||||||
- In order to push server status to your portable device without opening ServerBox app (Such as **message push** and **home widget**), you need to install [ServerBoxMonitor](https://github.com/lollipopkit/server_box_monitor) on your servers, and config it correctly. See [wiki](https://github.com/lollipopkit/server_box_monitor/wiki) for more details.
|
- In order to push server status to your portable device without opening ServerBox app (Such as **message push** and **home widget**), you need to install [ServerBoxMonitor](https://github.com/lollipopkit/server_box_monitor) on your servers, and config it correctly. See [wiki](https://github.com/lollipopkit/server_box_monitor/wiki) for more details.
|
||||||
- **Common issues** can be found in [app wiki](https://github.com/lollipopkit/flutter_server_box/wiki).
|
- **Common issues** can be found in [app wiki](https://github.com/lollipopkit/flutter_server_box/wiki).
|
||||||
- If you have **any question or feature request**, please open a [discussion](https://github.com/lollipopkit/flutter_server_box/discussions/new/choose).
|
- If you have **any question or feature request**, please open a [discussion](https://github.com/lollipopkit/flutter_server_box/discussions/new/choose).
|
||||||
- If ServerBox app has **any bug**, please open an [issue](https://github.com/lollipopkit/flutter_server_box/issues/new).
|
- If ServerBox app has **any bug**, please open an [issue](https://github.com/lollipopkit/flutter_server_box/issues/new) with **screenshots of ENTIRE LOG page** (at top right of home page).
|
||||||
|
|
||||||
|
|
||||||
## 🧱 Contribution
|
## 🧱 Contribution
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
- 为了可以在不使用 ServerBox app 时获取服务器状态(例如:桌面小部件、推送服务),你需要在你的服务器上安装 [ServerBoxMonitor](https://github.com/lollipopkit/server_box_monitor),并且正确配置,详情可见 [wiki](https://github.com/lollipopkit/server_box_monitor/wiki/%E4%B8%BB%E9%A1%B5)。
|
- 为了可以在不使用 ServerBox app 时获取服务器状态(例如:桌面小部件、推送服务),你需要在你的服务器上安装 [ServerBoxMonitor](https://github.com/lollipopkit/server_box_monitor),并且正确配置,详情可见 [wiki](https://github.com/lollipopkit/server_box_monitor/wiki/%E4%B8%BB%E9%A1%B5)。
|
||||||
- **常见问题**可以在 [app wiki](https://github.com/lollipopkit/flutter_server_box/wiki/主页) 查看。
|
- **常见问题**可以在 [app wiki](https://github.com/lollipopkit/flutter_server_box/wiki/主页) 查看。
|
||||||
- 如果你有**任何问题或者功能请求**,请在 [讨论](https://github.com/lollipopkit/flutter_server_box/discussions/new/choose) 中交流。
|
- 如果你有**任何问题或者功能请求**,请在 [讨论](https://github.com/lollipopkit/flutter_server_box/discussions/new/choose) 中交流。
|
||||||
- 如果 ServerBox app 有**任何 bug**,请在 [问题](https://github.com/lollipopkit/flutter_server_box/issues/new) 中反馈。
|
- 如果 ServerBox app 有**任何 bug**,请在 [问题](https://github.com/lollipopkit/flutter_server_box/issues/new) 中反馈,并且附带**完整的 Log 页截图**(点主界面右上角按钮进入)。
|
||||||
|
|
||||||
|
|
||||||
## 🧱 贡献
|
## 🧱 贡献
|
||||||
|
|||||||
@@ -1,34 +1,8 @@
|
|||||||
import 'dart:io';
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:plain_notification_token/plain_notification_token.dart';
|
import 'package:plain_notification_token/plain_notification_token.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/locale.dart';
|
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
|
|
||||||
Future<bool> shareFiles(List<String> filePaths) async {
|
|
||||||
for (final filePath in filePaths) {
|
|
||||||
if (!await File(filePath).exists()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var text = '';
|
|
||||||
if (filePaths.length == 1) {
|
|
||||||
text = filePaths.first.split('/').last;
|
|
||||||
} else {
|
|
||||||
text = '${filePaths.length} ${l10n.files}';
|
|
||||||
}
|
|
||||||
Pros.app.moveBg = false;
|
|
||||||
// ignore: deprecated_member_use
|
|
||||||
await Share.shareFiles(filePaths, subject: text);
|
|
||||||
Pros.app.moveBg = true;
|
|
||||||
return filePaths.isNotEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy2Clipboard(String text) {
|
|
||||||
Clipboard.setData(ClipboardData(text: text));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> pickOneFile() async {
|
Future<String?> pickOneFile() async {
|
||||||
Pros.app.moveBg = false;
|
Pros.app.moveBg = false;
|
||||||
|
|||||||
45
lib/core/utils/share.dart
Normal file
45
lib/core/utils/share.dart
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
|
|
||||||
|
class Shares {
|
||||||
|
const Shares._();
|
||||||
|
|
||||||
|
static Future<bool> files(List<String> filePaths) async {
|
||||||
|
for (final filePath in filePaths) {
|
||||||
|
if (!await File(filePath).exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var text = '';
|
||||||
|
if (filePaths.length == 1) {
|
||||||
|
text = filePaths.first.split('/').last;
|
||||||
|
} else {
|
||||||
|
text = '${filePaths.length} ${l10n.files}';
|
||||||
|
}
|
||||||
|
Pros.app.moveBg = false;
|
||||||
|
// ignore: deprecated_member_use
|
||||||
|
await Share.shareFiles(filePaths, subject: text);
|
||||||
|
Pros.app.moveBg = true;
|
||||||
|
return filePaths.isNotEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<bool> text(String text) async {
|
||||||
|
Pros.app.moveBg = false;
|
||||||
|
await Share.share(text);
|
||||||
|
Pros.app.moveBg = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy(String text) {
|
||||||
|
Clipboard.setData(ClipboardData(text: text));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<String?> paste([String type = 'text/plain']) async {
|
||||||
|
final data = await Clipboard.getData(type);
|
||||||
|
return data?.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,9 +63,11 @@ class Backup {
|
|||||||
dockerHosts = Stores.docker.fetchAll(),
|
dockerHosts = Stores.docker.fetchAll(),
|
||||||
settings = Stores.setting.toJson();
|
settings = Stores.setting.toJson();
|
||||||
|
|
||||||
static Future<void> backup() async {
|
static Future<String> backup() async {
|
||||||
final result = _diyEncrtpt(json.encode(Backup.loadFromStore()));
|
final result = _diyEncrtpt(json.encode(Backup.loadFromStore()));
|
||||||
await File(await Paths.bak).writeAsString(result);
|
final path = await Paths.bak;
|
||||||
|
await File(path).writeAsString(result);
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> restore() async {
|
Future<void> restore() async {
|
||||||
|
|||||||
@@ -308,14 +308,13 @@ class ServerProvider extends ChangeNotifier {
|
|||||||
try {
|
try {
|
||||||
Loggers.app.warning('Using SFTP to write script to ${spi.name}');
|
Loggers.app.warning('Using SFTP to write script to ${spi.name}');
|
||||||
file.writeAsString(ShellFunc.allScript);
|
file.writeAsString(ShellFunc.allScript);
|
||||||
final sftp = Pros.sftp;
|
|
||||||
final completer = Completer();
|
final completer = Completer();
|
||||||
final reqId = sftp.add(
|
final reqId = Pros.sftp.add(
|
||||||
SftpReq(spi, installShellPath, localPath, SftpReqType.upload),
|
SftpReq(spi, installShellPath, localPath, SftpReqType.upload),
|
||||||
completer: completer,
|
completer: completer,
|
||||||
);
|
);
|
||||||
await completer.future;
|
await completer.future;
|
||||||
final err = sftp.get(reqId)?.error;
|
final err = Pros.sftp.get(reqId)?.error;
|
||||||
if (err != null) {
|
if (err != null) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import 'package:toolbox/core/extension/context/snackbar.dart';
|
|||||||
import 'package:toolbox/core/persistant_store.dart';
|
import 'package:toolbox/core/persistant_store.dart';
|
||||||
import 'package:toolbox/core/utils/icloud.dart';
|
import 'package:toolbox/core/utils/icloud.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
import 'package:toolbox/data/model/app/backup.dart';
|
import 'package:toolbox/data/model/app/backup.dart';
|
||||||
import 'package:toolbox/data/res/logger.dart';
|
import 'package:toolbox/data/res/logger.dart';
|
||||||
import 'package:toolbox/data/res/path.dart';
|
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
import 'package:toolbox/data/res/rebuild.dart';
|
import 'package:toolbox/data/res/rebuild.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
@@ -20,7 +20,6 @@ import 'package:toolbox/view/widget/expand_tile.dart';
|
|||||||
import 'package:toolbox/view/widget/cardx.dart';
|
import 'package:toolbox/view/widget/cardx.dart';
|
||||||
import 'package:toolbox/view/widget/store_switch.dart';
|
import 'package:toolbox/view/widget/store_switch.dart';
|
||||||
import 'package:toolbox/view/widget/value_notifier.dart';
|
import 'package:toolbox/view/widget/value_notifier.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
import '../../core/utils/misc.dart';
|
import '../../core/utils/misc.dart';
|
||||||
import '../../data/res/ui.dart';
|
import '../../data/res/ui.dart';
|
||||||
@@ -149,17 +148,14 @@ class BackupPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onBackup() async {
|
Future<void> _onBackup() async {
|
||||||
await Backup.backup();
|
final path = await Backup.backup();
|
||||||
final path = await Paths.bak;
|
|
||||||
|
|
||||||
/// Issue #188
|
/// Issue #188
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
await launchUrl(
|
await Shares.text(await File(path).readAsString());
|
||||||
File(path).uri,
|
|
||||||
mode: LaunchMode.externalNonBrowserApplication,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
await shareFiles([path]);
|
await Shares.files([path]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'package:toolbox/core/extension/context/dialog.dart';
|
|||||||
import 'package:toolbox/core/extension/context/locale.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/uint8list.dart';
|
import 'package:toolbox/core/extension/uint8list.dart';
|
||||||
import 'package:toolbox/core/utils/misc.dart';
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
import 'package:toolbox/view/widget/value_notifier.dart';
|
import 'package:toolbox/view/widget/value_notifier.dart';
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ class _PingPageState extends State<PingPage>
|
|||||||
child: Text(e.toString()),
|
child: Text(e.toString()),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => copy2Clipboard(e.toString()),
|
onPressed: () => Shares.copy(e.toString()),
|
||||||
child: Text(l10n.copy),
|
child: Text(l10n.copy),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import 'package:toolbox/core/extension/context/dialog.dart';
|
|||||||
import 'package:toolbox/core/extension/context/locale.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/uint8list.dart';
|
import 'package:toolbox/core/extension/uint8list.dart';
|
||||||
import 'package:toolbox/core/utils/misc.dart';
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
|
|
||||||
import '../../data/model/app/shell_func.dart';
|
import '../../data/model/app/shell_func.dart';
|
||||||
@@ -111,7 +111,7 @@ class _ProcessPageState extends State<ProcessPage> {
|
|||||||
child: SingleChildScrollView(child: Text(_result.error!)),
|
child: SingleChildScrollView(child: Text(_result.error!)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => copy2Clipboard(_result.error!),
|
onPressed: () => Shares.copy(_result.error!),
|
||||||
child: Text(l10n.copy),
|
child: Text(l10n.copy),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import 'package:toolbox/core/extension/context/locale.dart';
|
|||||||
import 'package:toolbox/core/extension/media_queryx.dart';
|
import 'package:toolbox/core/extension/media_queryx.dart';
|
||||||
import 'package:toolbox/core/extension/ssh_client.dart';
|
import 'package:toolbox/core/extension/ssh_client.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
|
|
||||||
import '../../../core/route.dart';
|
import '../../../core/route.dart';
|
||||||
import '../../../core/utils/misc.dart';
|
|
||||||
import '../../../data/model/app/net_view.dart';
|
import '../../../data/model/app/net_view.dart';
|
||||||
import '../../../data/model/server/disk.dart';
|
import '../../../data/model/server/disk.dart';
|
||||||
import '../../../data/model/server/server.dart';
|
import '../../../data/model/server/server.dart';
|
||||||
@@ -412,7 +412,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => copy2Clipboard(ss.failedInfo!),
|
onPressed: () => Shares.copy(ss.failedInfo!),
|
||||||
child: Text(l10n.copy),
|
child: Text(l10n.copy),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:toolbox/core/extension/context/snackbar.dart';
|
|||||||
import 'package:toolbox/core/route.dart';
|
import 'package:toolbox/core/route.dart';
|
||||||
import 'package:toolbox/core/utils/misc.dart';
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
import 'package:toolbox/core/utils/platform/auth.dart';
|
import 'package:toolbox/core/utils/platform/auth.dart';
|
||||||
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
import 'package:toolbox/data/res/logger.dart';
|
import 'package:toolbox/data/res/logger.dart';
|
||||||
import 'package:toolbox/data/res/misc.dart';
|
import 'package:toolbox/data/res/misc.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
@@ -58,7 +59,7 @@ class _IOSSettingsPageState extends State<IOSSettingsPage> {
|
|||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_pushToken.value != null) {
|
if (_pushToken.value != null) {
|
||||||
copy2Clipboard(_pushToken.value!);
|
Shares.copy(_pushToken.value!);
|
||||||
context.showSnackBar(l10n.success);
|
context.showSnackBar(l10n.success);
|
||||||
} else {
|
} else {
|
||||||
context.showSnackBar(l10n.getPushTokenFailed);
|
context.showSnackBar(l10n.getPushTokenFailed);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:toolbox/core/extension/context/dialog.dart';
|
|||||||
import 'package:toolbox/core/extension/context/locale.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
import 'package:toolbox/data/model/server/snippet.dart';
|
import 'package:toolbox/data/model/server/snippet.dart';
|
||||||
import 'package:toolbox/data/provider/virtual_keyboard.dart';
|
import 'package:toolbox/data/provider/virtual_keyboard.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
@@ -249,7 +250,7 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
case VirtualKeyFunc.clipboard:
|
case VirtualKeyFunc.clipboard:
|
||||||
final selected = terminalSelected;
|
final selected = terminalSelected;
|
||||||
if (selected != null) {
|
if (selected != null) {
|
||||||
copy2Clipboard(selected);
|
Shares.copy(selected);
|
||||||
} else {
|
} else {
|
||||||
_paste();
|
_paste();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:toolbox/core/extension/context/common.dart';
|
|||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
import 'package:toolbox/core/extension/context/locale.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||||
import 'package:toolbox/data/model/sftp/req.dart';
|
import 'package:toolbox/data/model/sftp/req.dart';
|
||||||
import 'package:toolbox/data/res/misc.dart';
|
import 'package:toolbox/data/res/misc.dart';
|
||||||
@@ -303,7 +304,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
leading: const Icon(Icons.open_in_new),
|
leading: const Icon(Icons.open_in_new),
|
||||||
title: Text(l10n.open),
|
title: Text(l10n.open),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
shareFiles([file.absolute.path]);
|
Shares.files([file.absolute.path]);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import 'package:toolbox/core/extension/context/locale.dart';
|
|||||||
import 'package:toolbox/core/extension/datetime.dart';
|
import 'package:toolbox/core/extension/datetime.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
import 'package:toolbox/core/route.dart';
|
import 'package:toolbox/core/route.dart';
|
||||||
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
|
|
||||||
import '../../../core/extension/numx.dart';
|
import '../../../core/extension/numx.dart';
|
||||||
import '../../../core/utils/misc.dart';
|
|
||||||
import '../../../data/model/sftp/req.dart';
|
import '../../../data/model/sftp/req.dart';
|
||||||
import '../../../data/provider/sftp.dart';
|
import '../../../data/provider/sftp.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
@@ -72,7 +72,7 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Icons.file_open)),
|
icon: const Icon(Icons.file_open)),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => shareFiles([status.req.localPath]),
|
onPressed: () => Shares.files([status.req.localPath]),
|
||||||
icon: const Icon(Icons.open_in_new),
|
icon: const Icon(Icons.open_in_new),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user