mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-05 00:30:19 +08:00
opt ui
opt video keyboard event opt code Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -10,6 +10,7 @@ import 'package:PiliPlus/utils/accounts/account.dart';
|
||||
import 'package:PiliPlus/utils/app_sign.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||
@@ -312,13 +313,19 @@ class AccountManager extends Interceptor {
|
||||
case DioExceptionType.sendTimeout:
|
||||
return '发送请求超时,请检查网络设置';
|
||||
case DioExceptionType.unknown:
|
||||
final String res =
|
||||
(await Connectivity().checkConnectivity()).first.title;
|
||||
return '$res网络异常 ${error.error}';
|
||||
String desc;
|
||||
try {
|
||||
desc = Utils.isMobile
|
||||
? (await Connectivity().checkConnectivity()).first.desc
|
||||
: '';
|
||||
} catch (_) {
|
||||
desc = '';
|
||||
}
|
||||
return '$desc网络异常 ${error.error}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension _ConnectivityResultExt on ConnectivityResult {
|
||||
String get title => const ['蓝牙', 'Wi-Fi', '局域', '流量', '无', '代理', '其他'][index];
|
||||
String get desc => const ['蓝牙', 'Wi-Fi', '局域', '流量', '无', '代理', '其他'][index];
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/http/init.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/global_data.dart';
|
||||
import 'package:PiliPlus/utils/permission_handler.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
@@ -12,7 +14,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:intl/intl.dart' show DateFormat;
|
||||
import 'package:live_photo_maker/live_photo_maker.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:saver_gallery/saver_gallery.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
@@ -106,7 +107,7 @@ class ImageUtils {
|
||||
required int height,
|
||||
}) async {
|
||||
try {
|
||||
if (!await checkPermissionDependOnSdkInt(context)) {
|
||||
if (Utils.isMobile && !await checkPermissionDependOnSdkInt(context)) {
|
||||
return false;
|
||||
}
|
||||
if (!silentDownImg) SmartDialog.showLoading(msg: '正在下载');
|
||||
@@ -165,7 +166,9 @@ class ImageUtils {
|
||||
BuildContext context,
|
||||
List<String> imgList,
|
||||
) async {
|
||||
if (!await checkPermissionDependOnSdkInt(context)) return false;
|
||||
if (Utils.isMobile && !await checkPermissionDependOnSdkInt(context)) {
|
||||
return false;
|
||||
}
|
||||
CancelToken? cancelToken;
|
||||
if (!silentDownImg) {
|
||||
cancelToken = CancelToken();
|
||||
@@ -193,7 +196,7 @@ class ImageUtils {
|
||||
await SaverGallery.saveFile(
|
||||
filePath: filePath,
|
||||
fileName: name,
|
||||
androidRelativePath: "Pictures/PiliPlus",
|
||||
androidRelativePath: "Pictures/${Constants.appName}",
|
||||
skipIfExists: false,
|
||||
).whenComplete(File(filePath).tryDel);
|
||||
}
|
||||
@@ -271,7 +274,7 @@ class ImageUtils {
|
||||
result = await SaverGallery.saveImage(
|
||||
bytes,
|
||||
fileName: fileName,
|
||||
androidRelativePath: "Pictures/PiliPlus",
|
||||
androidRelativePath: "Pictures/${Constants.appName}",
|
||||
skipIfExists: false,
|
||||
);
|
||||
SmartDialog.dismiss();
|
||||
@@ -313,7 +316,7 @@ class ImageUtils {
|
||||
result = await SaverGallery.saveFile(
|
||||
filePath: filePath,
|
||||
fileName: fileName,
|
||||
androidRelativePath: "Pictures/PiliPlus",
|
||||
androidRelativePath: "Pictures/${Constants.appName}",
|
||||
skipIfExists: false,
|
||||
).whenComplete(file.tryDel);
|
||||
} else {
|
||||
|
||||
201
lib/utils/permission_handler.dart
Normal file
201
lib/utils/permission_handler.dart
Normal file
@@ -0,0 +1,201 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart';
|
||||
|
||||
export 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'
|
||||
show
|
||||
Permission,
|
||||
PermissionStatus,
|
||||
PermissionStatusGetters,
|
||||
PermissionWithService,
|
||||
FuturePermissionStatusGetters,
|
||||
ServiceStatus,
|
||||
ServiceStatusGetters,
|
||||
FutureServiceStatusGetters;
|
||||
|
||||
PermissionHandlerPlatform get _handler => PermissionHandlerPlatform.instance;
|
||||
|
||||
/// Opens the app settings page.
|
||||
///
|
||||
/// Returns [true] if the app settings page could be opened, otherwise [false].
|
||||
Future<bool> openAppSettings() => _handler.openAppSettings();
|
||||
|
||||
/// Actions that can be executed on a permission.
|
||||
extension PermissionActions on Permission {
|
||||
/// Callback for when permission is denied.
|
||||
static FutureOr<void>? Function()? _onDenied;
|
||||
|
||||
/// Callback for when permission is granted.
|
||||
static FutureOr<void>? Function()? _onGranted;
|
||||
|
||||
/// Callback for when permission is permanently denied.
|
||||
static FutureOr<void>? Function()? _onPermanentlyDenied;
|
||||
|
||||
/// Callback for when permission is restricted.
|
||||
static FutureOr<void>? Function()? _onRestricted;
|
||||
|
||||
/// Callback for when permission is limited.
|
||||
static FutureOr<void>? Function()? _onLimited;
|
||||
|
||||
/// Callback for when permission is Provisional.
|
||||
static FutureOr<void>? Function()? _onProvisional;
|
||||
|
||||
/// Method to set a callback for when permission is denied.
|
||||
Permission onDeniedCallback(FutureOr<void>? Function()? callback) {
|
||||
_onDenied = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Method to set a callback for when permission is granted.
|
||||
Permission onGrantedCallback(FutureOr<void>? Function()? callback) {
|
||||
_onGranted = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Method to set a callback for when permission is permanently denied.
|
||||
Permission onPermanentlyDeniedCallback(FutureOr<void>? Function()? callback) {
|
||||
_onPermanentlyDenied = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Method to set a callback for when permission is restricted.
|
||||
Permission onRestrictedCallback(FutureOr<void>? Function()? callback) {
|
||||
_onRestricted = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Method to set a callback for when permission is limited.
|
||||
Permission onLimitedCallback(FutureOr<void>? Function()? callback) {
|
||||
_onLimited = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Method to set a callback for when permission is provisional.
|
||||
Permission onProvisionalCallback(FutureOr<void>? Function()? callback) {
|
||||
_onProvisional = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Checks the current status of the given [Permission].
|
||||
///
|
||||
/// Notes about specific permissions:
|
||||
/// - **[Permission.bluetooth]**
|
||||
/// - iOS 13.0 only:
|
||||
/// - The method will **always** return [PermissionStatus.denied],
|
||||
/// regardless of the actual status. For the actual permission state,
|
||||
/// use [Permission.bluetooth.request]. Note that this will show a
|
||||
/// permission dialog if the permission was not yet requested.
|
||||
Future<PermissionStatus> get status => _handler.checkPermissionStatus(this);
|
||||
|
||||
/// If you should show a rationale for requesting permission.
|
||||
///
|
||||
/// This is only implemented on Android, calling this on iOS always returns
|
||||
/// [false].
|
||||
Future<bool> get shouldShowRequestRationale async {
|
||||
if (defaultTargetPlatform != TargetPlatform.android) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _handler.shouldShowRequestPermissionRationale(this);
|
||||
}
|
||||
|
||||
/// Request the user for access to this [Permission], if access hasn't already
|
||||
/// been grant access before.
|
||||
///
|
||||
/// Returns the new [PermissionStatus].
|
||||
Future<PermissionStatus> request() async {
|
||||
final permissionStatus =
|
||||
(await [this].request())[this] ?? PermissionStatus.denied;
|
||||
|
||||
if (permissionStatus.isDenied) {
|
||||
_onDenied?.call();
|
||||
} else if (permissionStatus.isGranted) {
|
||||
_onGranted?.call();
|
||||
} else if (permissionStatus.isPermanentlyDenied) {
|
||||
_onPermanentlyDenied?.call();
|
||||
} else if (permissionStatus.isRestricted) {
|
||||
_onRestricted?.call();
|
||||
} else if (permissionStatus.isLimited) {
|
||||
_onLimited?.call();
|
||||
} else if (permissionStatus.isProvisional) {
|
||||
_onProvisional?.call();
|
||||
}
|
||||
|
||||
return permissionStatus;
|
||||
}
|
||||
}
|
||||
|
||||
/// Shortcuts for checking the [status] of a [Permission].
|
||||
extension PermissionCheckShortcuts on Permission {
|
||||
/// If the user granted this permission.
|
||||
Future<bool> get isGranted => status.isGranted;
|
||||
|
||||
/// If the user denied this permission.
|
||||
Future<bool> get isDenied => status.isDenied;
|
||||
|
||||
/// If the OS denied this permission. The user cannot change the status,
|
||||
/// possibly due to active restrictions such as parental controls being in
|
||||
/// place.
|
||||
/// *Only supported on iOS.*
|
||||
Future<bool> get isRestricted => status.isRestricted;
|
||||
|
||||
/// User has authorized this application for limited access.
|
||||
/// *Only supported on iOS.(iOS14+ for photos, ios18+ for contacts)*
|
||||
Future<bool> get isLimited => status.isLimited;
|
||||
|
||||
/// Returns `true` when permissions are denied permanently.
|
||||
///
|
||||
/// When permissions are denied permanently, no new permission dialog will
|
||||
/// be showed to the user. Consuming Apps should redirect the user to the
|
||||
/// App settings to change permissions.
|
||||
Future<bool> get isPermanentlyDenied => status.isPermanentlyDenied;
|
||||
|
||||
/// If the application is provisionally authorized to post noninterruptive user notifications.
|
||||
/// *Only supported on iOS.*
|
||||
Future<bool> get isProvisional => status.isProvisional;
|
||||
}
|
||||
|
||||
/// Actions that apply only to permissions that have an associated service.
|
||||
extension ServicePermissionActions on PermissionWithService {
|
||||
/// Checks the current status of the service associated with the given
|
||||
/// [Permission].
|
||||
///
|
||||
/// Notes about specific permissions:
|
||||
/// - **[Permission.phone]**
|
||||
/// - Android:
|
||||
/// - The method will return [ServiceStatus.notApplicable] when:
|
||||
/// - the device lacks the TELEPHONY feature
|
||||
/// - TelephonyManager.getPhoneType() returns PHONE_TYPE_NONE
|
||||
/// - when no Intents can be resolved to handle the `tel:` scheme
|
||||
/// - The method will return [ServiceStatus.disabled] when:
|
||||
/// - the SIM card is missing
|
||||
/// - iOS:
|
||||
/// - The method will return [ServiceStatus.notApplicable] when:
|
||||
/// - the native code can not find a handler for the `tel:` scheme
|
||||
/// - The method will return [ServiceStatus.disabled] when:
|
||||
/// - the mobile network code (MNC) is either 0 or 65535. See
|
||||
/// https://stackoverflow.com/a/11595365 for details
|
||||
/// - **PLEASE NOTE that this is still not a perfect indication** of the
|
||||
/// device's capability to place & connect phone calls as it also depends
|
||||
/// on the network condition.
|
||||
/// - **[Permission.bluetooth]**
|
||||
/// - iOS:
|
||||
/// - The method will **always** return [ServiceStatus.disabled] when the
|
||||
/// Bluetooth permission was denied by the user. It is impossible to
|
||||
/// obtain the actual Bluetooth service status without having the
|
||||
/// Bluetooth permission granted.
|
||||
/// - The method will prompt the user for Bluetooth permission if the
|
||||
/// permission was not yet requested.
|
||||
Future<ServiceStatus> get serviceStatus => _handler.checkServiceStatus(this);
|
||||
}
|
||||
|
||||
/// Actions that can be taken on a [List] of [Permission]s.
|
||||
extension PermissionListActions on List<Permission> {
|
||||
/// Requests the user for access to these permissions, if they haven't already
|
||||
/// been granted before.
|
||||
///
|
||||
/// Returns a [Map] containing the status per requested [Permission].
|
||||
Future<Map<Permission, PermissionStatus>> request() =>
|
||||
_handler.requestPermissions(this);
|
||||
}
|
||||
@@ -135,7 +135,8 @@ class SettingBoxKey {
|
||||
showFsScreenshotBtn = 'showFsScreenshotBtn',
|
||||
showFsLockBtn = 'showFsLockBtn',
|
||||
silentDownImg = 'silentDownImg',
|
||||
showMemberShop = 'showMemberShop';
|
||||
showMemberShop = 'showMemberShop',
|
||||
minimizeOnExit = 'minimizeOnExit';
|
||||
|
||||
static const String subtitlePreferenceV2 = 'subtitlePreferenceV2',
|
||||
enableDragSubtitle = 'enableDragSubtitle',
|
||||
|
||||
@@ -809,4 +809,7 @@ abstract class Pref {
|
||||
|
||||
static bool get showSuperChat =>
|
||||
_setting.get(SettingBoxKey.showSuperChat, defaultValue: true);
|
||||
|
||||
static bool get minimizeOnExit =>
|
||||
_setting.get(SettingBoxKey.minimizeOnExit, defaultValue: true);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:PiliPlus/build_config.dart';
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/http/api.dart';
|
||||
import 'package:PiliPlus/http/init.dart';
|
||||
import 'package:PiliPlus/http/ua_type.dart';
|
||||
@@ -61,7 +62,7 @@ class Update {
|
||||
Text('${res.data[0]['body']}'),
|
||||
TextButton(
|
||||
onPressed: () => PageUtils.launchURL(
|
||||
'https://github.com/bggRGjQaUbCoE/PiliPlus/commits/main',
|
||||
'${Constants.sourceCodeUrl}/commits/main',
|
||||
),
|
||||
child: Text(
|
||||
"点此查看完整更新(即commit)内容",
|
||||
@@ -134,9 +135,7 @@ class Update {
|
||||
download('ios');
|
||||
}
|
||||
} catch (_) {
|
||||
PageUtils.launchURL(
|
||||
'https://github.com/bggRGjQaUbCoE/PiliPlus/releases/latest',
|
||||
);
|
||||
PageUtils.launchURL('${Constants.sourceCodeUrl}/releases/latest');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ 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';
|
||||
@@ -14,13 +16,24 @@ import 'package:share_plus/share_plus.dart';
|
||||
class Utils {
|
||||
static final Random random = Random();
|
||||
|
||||
static const channel = MethodChannel("PiliPlus");
|
||||
static const channel = MethodChannel(Constants.appName);
|
||||
|
||||
static final bool isMobile = Platform.isAndroid || Platform.isIOS;
|
||||
|
||||
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));
|
||||
|
||||
@@ -59,6 +72,10 @@ class Utils {
|
||||
}
|
||||
|
||||
static Future<void> shareText(String text) async {
|
||||
if (Utils.isDesktop) {
|
||||
copyText(text);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await SharePlus.instance.share(
|
||||
ShareParams(
|
||||
|
||||
Reference in New Issue
Block a user