Files
PiliPlus/lib/utils/utils.dart
My-Responsitories 37fb63c3b1 tweaks (#1252)
* opt: cache

* opt: MediaListPanel

* feat: nested replyreply panel

* tweaks

* opt: abstract class

* opt: PageStorageKey

* opt: contextExt

* opt: EpisodePanel

* opt

* opt: context instead GlobalKey

* feat: jump to reply

* refa: reply_reply

* fix: jump

* fix: index

* update

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* opt: keepalive

* reapply: nested replyreply

* mod: spacing

* opt: CommonSlidePageState

* fix drag bottomsheet

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* opt reply jump

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* opt reply2reply

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* tweaks

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* tweaks

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* reapply: jumpToReply

* fix: padding

* fix: anim

* fix some panels

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* opt: implements Scaffold

* opt: remove keepalive

* revert: GlobalKey

* tweaks

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

---------

Co-authored-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-09-15 18:45:28 +08:00

159 lines
4.2 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:PiliPlus/common/constants.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/services.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
abstract class Utils {
static final Random random = Random();
static const channel = MethodChannel(Constants.appName);
@pragma("vm:platform-const")
static final bool isMobile = Platform.isAndroid || Platform.isIOS;
@pragma("vm:platform-const")
static final bool isDesktop =
Platform.isWindows || Platform.isMacOS || Platform.isLinux;
static Future<bool> get isWiFi async {
try {
return Utils.isMobile &&
(await Connectivity().checkConnectivity()).contains(
ConnectivityResult.wifi,
);
} catch (_) {
return true;
}
}
static Color parseColor(String color) =>
Color(int.parse(color.replaceFirst('#', 'FF'), radix: 16));
static int? _sdkInt;
static Future<int> get sdkInt async {
return _sdkInt ??= (await DeviceInfoPlugin().androidInfo).version.sdkInt;
}
static bool? _isIpad;
static Future<bool> get isIpad async {
if (!Platform.isIOS) return false;
return _isIpad ??= (await DeviceInfoPlugin().iosInfo).model
.toLowerCase()
.contains('ipad');
}
static String? _tempDir;
static Future<String> get temporaryDirectory async {
return _tempDir ??= (await getTemporaryDirectory()).path;
}
static Future<Rect?> get sharePositionOrigin async {
if (await isIpad) {
final size = Get.size;
return Rect.fromLTWH(
0,
0,
size.width,
size.height / 2,
);
}
return null;
}
static Future<void> shareText(String text) async {
if (Utils.isDesktop) {
copyText(text);
return;
}
try {
await SharePlus.instance.share(
ShareParams(
text: text,
sharePositionOrigin: await sharePositionOrigin,
),
);
} catch (e) {
SmartDialog.showToast(e.toString());
}
}
static String buildShadersAbsolutePath(
String baseDirectory,
List<String> shaders,
) {
return shaders
.map((shader) => path.join(baseDirectory, shader))
.join(Platform.isWindows ? ';' : ':');
}
static final numericRegex = RegExp(r'^[\d\.]+$');
static bool isStringNumeric(String str) {
return numericRegex.hasMatch(str);
}
static String generateRandomString(int length) {
const characters = '0123456789abcdefghijklmnopqrstuvwxyz';
return String.fromCharCodes(
Iterable.generate(
length,
(_) => characters.codeUnitAt(random.nextInt(characters.length)),
),
);
}
static void copyText(
String text, {
bool needToast = true,
String? toastText,
}) {
Clipboard.setData(ClipboardData(text: text));
if (needToast) {
SmartDialog.showToast(toastText ?? '已复制');
}
}
static String makeHeroTag(v) {
return v.toString() + random.nextInt(9999).toString();
}
static int findClosestNumber(int target, List<int> numbers) {
List<int> filterNums = numbers.where((number) => number <= target).toList();
return filterNums.isNotEmpty
? filterNums.reduce((a, b) => a > b ? a : b)
: numbers.reduce((a, b) => a > b ? b : a);
}
static List<int> generateRandomBytes(int minLength, int maxLength) {
return List<int>.generate(
minLength + random.nextInt(maxLength - minLength + 1),
(_) => 0x26 + random.nextInt(0x59), // dm_img_str不能有`%`
);
}
static String base64EncodeRandomString(int minLength, int maxLength) {
final randomBytes = generateRandomBytes(minLength, maxLength);
final randomBase64 = base64.encode(randomBytes);
return randomBase64.substring(0, randomBase64.length - 2);
}
static String getFileName(String uri, {bool fileExt = true}) {
final i0 = uri.lastIndexOf('/') + 1;
final i1 = fileExt ? uri.length : uri.lastIndexOf('.');
return uri.substring(i0, i1);
}
}