mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt.: migrate fl_lib
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract final class Funcs {
|
||||
static const int _defaultDurationTime = 377;
|
||||
static const String _defaultThrottleId = 'default';
|
||||
static final Map<String, int> startTimeMap = <String, int>{
|
||||
_defaultThrottleId: 0
|
||||
};
|
||||
|
||||
static void throttle(
|
||||
VoidCallback? func, {
|
||||
String id = _defaultThrottleId,
|
||||
int duration = _defaultDurationTime,
|
||||
Function? continueClick,
|
||||
}) {
|
||||
final currentTime = DateTime.now().millisecondsSinceEpoch;
|
||||
if (currentTime - (startTimeMap[id] ?? 0) > duration) {
|
||||
func?.call();
|
||||
startTimeMap[id] = DateTime.now().millisecondsSinceEpoch;
|
||||
} else {
|
||||
continueClick?.call();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,6 @@
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:plain_notification_token/plain_notification_token.dart';
|
||||
import 'package:toolbox/core/utils/platform/base.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
|
||||
Future<String?> pickOneFile() async {
|
||||
Pros.app.moveBg = false;
|
||||
final result = await FilePicker.platform.pickFiles(type: FileType.any);
|
||||
Pros.app.moveBg = true;
|
||||
return result?.files.single.path;
|
||||
}
|
||||
|
||||
Future<String?> getToken() async {
|
||||
if (isIOS) {
|
||||
@@ -29,22 +21,3 @@ String? getFileName(String? path) {
|
||||
}
|
||||
return path.split('/').last;
|
||||
}
|
||||
|
||||
/// Join two path with `/`
|
||||
String pathJoin(String path1, String path2) {
|
||||
return path1 + (path1.endsWith('/') ? '' : '/') + path2;
|
||||
}
|
||||
|
||||
/// Check if a url is a file url (ends with a file extension)
|
||||
bool isFileUrl(String url) => url.split('/').last.contains('.');
|
||||
|
||||
int get timeStamp => DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
bool isBaseType(Object? obj) {
|
||||
return obj is String ||
|
||||
obj is int ||
|
||||
obj is double ||
|
||||
obj is bool ||
|
||||
obj is List ||
|
||||
obj is Map;
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:local_auth_android/local_auth_android.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:local_auth_ios/types/auth_messages_ios.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/core/utils/platform/base.dart';
|
||||
import 'package:local_auth/error_codes.dart' as errs;
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
|
||||
abstract final class BioAuth {
|
||||
static final _auth = LocalAuthentication();
|
||||
|
||||
static final isPlatformSupported = isAndroid || isIOS || isWindows;
|
||||
|
||||
static bool _isAuthing = false;
|
||||
|
||||
static Future<bool> get isAvail async {
|
||||
if (!isPlatformSupported) return false;
|
||||
if (!await _auth.canCheckBiometrics) {
|
||||
return false;
|
||||
}
|
||||
final biometrics = await _auth.getAvailableBiometrics();
|
||||
|
||||
/// [biometrics] on Android and Windows is returned with error
|
||||
/// Handle it specially
|
||||
if (isAndroid || isWindows) return biometrics.isNotEmpty;
|
||||
return biometrics.contains(BiometricType.face) ||
|
||||
biometrics.contains(BiometricType.fingerprint);
|
||||
}
|
||||
|
||||
static Future<void> go([int count = 0]) async {
|
||||
if (Stores.setting.useBioAuth.fetch()) {
|
||||
if (!_isAuthing) {
|
||||
_isAuthing = true;
|
||||
final val = await goWithResult();
|
||||
_isAuthing = false;
|
||||
switch (val) {
|
||||
case AuthResult.success:
|
||||
break;
|
||||
case AuthResult.fail:
|
||||
case AuthResult.cancel:
|
||||
go(count + 1);
|
||||
break;
|
||||
case AuthResult.notAvail:
|
||||
Stores.setting.useBioAuth.put(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Future<AuthResult> goWithResult() async {
|
||||
if (!await isAvail) return AuthResult.notAvail;
|
||||
try {
|
||||
await _auth.stopAuthentication();
|
||||
final reuslt = await _auth.authenticate(
|
||||
localizedReason: l10n.authRequired,
|
||||
options: const AuthenticationOptions(
|
||||
biometricOnly: true,
|
||||
stickyAuth: true,
|
||||
),
|
||||
authMessages: [
|
||||
AndroidAuthMessages(
|
||||
biometricHint: l10n.bioAuth,
|
||||
biometricNotRecognized: l10n.failed,
|
||||
biometricRequiredTitle: l10n.authRequired,
|
||||
biometricSuccess: l10n.success,
|
||||
cancelButton: l10n.cancel,
|
||||
),
|
||||
IOSAuthMessages(
|
||||
lockOut: l10n.authRequired,
|
||||
cancelButton: l10n.ok,
|
||||
),
|
||||
]);
|
||||
if (reuslt) {
|
||||
return AuthResult.success;
|
||||
}
|
||||
return AuthResult.fail;
|
||||
} on PlatformException catch (e) {
|
||||
switch (e.code) {
|
||||
case errs.notEnrolled:
|
||||
return AuthResult.notAvail;
|
||||
case errs.lockedOut:
|
||||
case errs.permanentlyLockedOut:
|
||||
exit(0);
|
||||
}
|
||||
return AuthResult.cancel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum AuthResult {
|
||||
success,
|
||||
// Not match
|
||||
fail,
|
||||
// User cancel
|
||||
cancel,
|
||||
// Device doesn't support biometrics
|
||||
notAvail,
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:toolbox/core/extension/stringx.dart';
|
||||
|
||||
enum OS {
|
||||
android,
|
||||
ios,
|
||||
linux,
|
||||
macos,
|
||||
windows,
|
||||
web,
|
||||
fuchsia,
|
||||
unknown;
|
||||
|
||||
static final type = () {
|
||||
if (kIsWeb) {
|
||||
return OS.web;
|
||||
}
|
||||
if (Platform.isAndroid) {
|
||||
return OS.android;
|
||||
}
|
||||
if (Platform.isIOS) {
|
||||
return OS.ios;
|
||||
}
|
||||
if (Platform.isLinux) {
|
||||
return OS.linux;
|
||||
}
|
||||
if (Platform.isMacOS) {
|
||||
return OS.macos;
|
||||
}
|
||||
if (Platform.isWindows) {
|
||||
return OS.windows;
|
||||
}
|
||||
if (Platform.isFuchsia) {
|
||||
return OS.fuchsia;
|
||||
}
|
||||
return OS.unknown;
|
||||
}();
|
||||
|
||||
@override
|
||||
String toString() => switch (this) {
|
||||
OS.macos => 'macOS',
|
||||
OS.ios => 'iOS',
|
||||
final val => val.name.upperFirst,
|
||||
};
|
||||
}
|
||||
|
||||
final isAndroid = OS.type == OS.android;
|
||||
final isIOS = OS.type == OS.ios;
|
||||
final isLinux = OS.type == OS.linux;
|
||||
final isMacOS = OS.type == OS.macos;
|
||||
final isWindows = OS.type == OS.windows;
|
||||
final isWeb = OS.type == OS.web;
|
||||
final isMobile = OS.type == OS.ios || OS.type == OS.android;
|
||||
final isDesktop =
|
||||
OS.type == OS.linux || OS.type == OS.macos || OS.type == OS.windows;
|
||||
@@ -1,26 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:toolbox/core/utils/platform/base.dart';
|
||||
|
||||
final _pathSep = Platform.pathSeparator;
|
||||
String get pathSeparator => _pathSep;
|
||||
|
||||
/// Available only on desktop,
|
||||
/// return null on mobile
|
||||
String? getHomeDir() {
|
||||
final envVars = Platform.environment;
|
||||
if (isMacOS || isLinux) {
|
||||
return envVars['HOME'];
|
||||
} else if (isWindows) {
|
||||
return envVars['UserProfile'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Join two paths with platform specific separator
|
||||
String joinPath(String path1, String path2) {
|
||||
if (isWindows) {
|
||||
return path1 + (path1.endsWith('\\') ? '' : '\\') + path2;
|
||||
}
|
||||
return path1 + (path1.endsWith('/') ? '' : '/') + path2;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
abstract final class PermUtils {
|
||||
static Future<bool> request(Permission permission) async {
|
||||
final status = await permission.status;
|
||||
if (status.isGranted) {
|
||||
return true;
|
||||
} else {
|
||||
final result = await permission.request();
|
||||
return result.isGranted;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
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';
|
||||
|
||||
abstract final class 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;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
@@ -14,6 +14,7 @@ abstract final class KeybordInteractive {
|
||||
try {
|
||||
final res = await (ctx ?? Pros.app.ctx)?.showPwdDialog(
|
||||
title: '2FA ${l10n.pwd}',
|
||||
id: spi.id,
|
||||
label: spi.id,
|
||||
);
|
||||
return res == null ? null : [res];
|
||||
|
||||
@@ -2,13 +2,13 @@ import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:computer/computer.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:icloud_storage/icloud_storage.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:toolbox/data/model/app/backup.dart';
|
||||
import 'package:toolbox/data/model/app/sync.dart';
|
||||
|
||||
import '../../../data/model/app/error.dart';
|
||||
import '../../../data/res/path.dart';
|
||||
|
||||
abstract final class ICloud {
|
||||
static const _containerId = 'iCloud.tech.lolli.serverbox';
|
||||
@@ -31,7 +31,7 @@ abstract final class ICloud {
|
||||
try {
|
||||
await ICloudStorage.upload(
|
||||
containerId: _containerId,
|
||||
filePath: localPath ?? '${await Paths.doc}/$relativePath',
|
||||
filePath: localPath ?? '${Paths.doc}/$relativePath',
|
||||
destinationRelativePath: relativePath,
|
||||
onProgress: (stream) {
|
||||
stream.listen(
|
||||
@@ -85,7 +85,7 @@ abstract final class ICloud {
|
||||
await ICloudStorage.download(
|
||||
containerId: _containerId,
|
||||
relativePath: relativePath,
|
||||
destinationFilePath: localPath ?? '${await Paths.doc}/$relativePath',
|
||||
destinationFilePath: localPath ?? '${Paths.doc}/$relativePath',
|
||||
onProgress: (stream) {
|
||||
stream.listen(
|
||||
null,
|
||||
@@ -139,7 +139,7 @@ abstract final class ICloud {
|
||||
}
|
||||
}));
|
||||
|
||||
final docPath = await Paths.doc;
|
||||
final docPath = Paths.doc;
|
||||
|
||||
/// compare files in iCloud and local
|
||||
missions.addAll(allFiles.map((file) async {
|
||||
@@ -205,7 +205,7 @@ abstract final class ICloud {
|
||||
return;
|
||||
}
|
||||
|
||||
final dlFile = await File(await Paths.bak).readAsString();
|
||||
final dlFile = await File(Paths.bakPath).readAsString();
|
||||
final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile);
|
||||
await dlBak.restore();
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:computer/computer.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:toolbox/data/model/app/backup.dart';
|
||||
import 'package:toolbox/data/model/app/error.dart';
|
||||
import 'package:toolbox/data/res/path.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:webdav_client/webdav_client.dart';
|
||||
|
||||
@@ -37,7 +37,7 @@ abstract final class Webdav {
|
||||
}) async {
|
||||
try {
|
||||
await _client.writeFile(
|
||||
localPath ?? '${await Paths.doc}/$relativePath',
|
||||
localPath ?? '${Paths.doc}/$relativePath',
|
||||
_prefix + relativePath,
|
||||
);
|
||||
} catch (e, s) {
|
||||
@@ -64,7 +64,7 @@ abstract final class Webdav {
|
||||
try {
|
||||
await _client.readFile(
|
||||
_prefix + relativePath,
|
||||
localPath ?? '${await Paths.doc}/$relativePath',
|
||||
localPath ?? '${Paths.doc}/$relativePath',
|
||||
);
|
||||
} catch (e) {
|
||||
_logger.warning('Download $relativePath failed');
|
||||
@@ -104,7 +104,7 @@ abstract final class Webdav {
|
||||
}
|
||||
|
||||
try {
|
||||
final dlFile = await File(await Paths.bak).readAsString();
|
||||
final dlFile = await File(Paths.bakPath).readAsString();
|
||||
final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile);
|
||||
await dlBak.restore();
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:toolbox/core/utils/platform/base.dart';
|
||||
import 'package:toolbox/core/utils/misc.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import 'misc.dart';
|
||||
import '../extension/uint8list.dart';
|
||||
|
||||
Future<bool> openUrl(String url) async {
|
||||
return await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user