mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-21 03:15:14 +08:00
@@ -8,9 +8,9 @@ import 'package:PiliPlus/models/common/account_type.dart';
|
||||
import 'package:PiliPlus/utils/accounts.dart';
|
||||
import 'package:PiliPlus/utils/accounts/account.dart';
|
||||
import 'package:PiliPlus/utils/app_sign.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/string_ext.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.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;
|
||||
@@ -363,7 +363,7 @@ class AccountManager extends Interceptor {
|
||||
case DioExceptionType.unknown:
|
||||
String desc;
|
||||
try {
|
||||
desc = Utils.isMobile
|
||||
desc = PlatformUtils.isMobile
|
||||
? (await Connectivity().checkConnectivity()).first.desc
|
||||
: '';
|
||||
} catch (_) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:PiliPlus/models/common/account_type.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
||||
class AccountTypeAdapter extends TypeAdapter<AccountType> {
|
||||
|
||||
@@ -14,7 +14,7 @@ import 'package:PiliPlus/pages/live/view.dart';
|
||||
import 'package:PiliPlus/pages/rank/view.dart';
|
||||
import 'package:PiliPlus/pages/subscription_detail/view.dart';
|
||||
import 'package:PiliPlus/pages/video/reply_reply/view.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
|
||||
import 'package:PiliPlus/utils/id_utils.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/request_utils.dart';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
abstract class CacheManager {
|
||||
@@ -14,7 +14,7 @@ abstract class CacheManager {
|
||||
]) async {
|
||||
try {
|
||||
final Directory tempDirectory = await getTemporaryDirectory();
|
||||
if (Utils.isDesktop) {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
final dir = Directory('${tempDirectory.path}/libCachedImageData');
|
||||
if (dir.existsSync()) {
|
||||
return await getTotalSizeOfFilesInDir(dir, maxSize);
|
||||
@@ -62,7 +62,7 @@ abstract class CacheManager {
|
||||
static Future<void> clearLibraryCache() async {
|
||||
try {
|
||||
final Directory tempDirectory = await getTemporaryDirectory();
|
||||
if (Utils.isDesktop) {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
final dir = Directory('${tempDirectory.path}/libCachedImageData');
|
||||
if (dir.existsSync()) {
|
||||
await dir.delete(recursive: true);
|
||||
|
||||
@@ -1,291 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
||||
import 'package:PiliPlus/grpc/bilibili/app/im/v1.pb.dart' show ThreeDotItem;
|
||||
import 'package:PiliPlus/grpc/bilibili/app/im/v1.pbenum.dart'
|
||||
show IMSettingType, ThreeDotItemType;
|
||||
import 'package:PiliPlus/pages/common/common_whisper_controller.dart';
|
||||
import 'package:PiliPlus/pages/contact/view.dart';
|
||||
import 'package:PiliPlus/pages/whisper_settings/view.dart';
|
||||
import 'package:floating/floating.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart' hide ContextExtensionss;
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
extension ImageExtension on num {
|
||||
int? cacheSize(BuildContext context) {
|
||||
if (this == 0) {
|
||||
return null;
|
||||
}
|
||||
return (this * MediaQuery.devicePixelRatioOf(context)).round();
|
||||
}
|
||||
}
|
||||
|
||||
extension IntExt on int? {
|
||||
int? operator +(int other) => this == null ? null : this! + other;
|
||||
int? operator -(int other) => this == null ? null : this! - other;
|
||||
}
|
||||
|
||||
extension ScrollControllerExt on ScrollController {
|
||||
void animToTop() => animTo(0);
|
||||
|
||||
void animTo(
|
||||
double offset, {
|
||||
Duration duration = const Duration(milliseconds: 500),
|
||||
}) {
|
||||
if (!hasClients) return;
|
||||
if ((offset - this.offset).abs() >= position.viewportDimension * 7) {
|
||||
jumpTo(offset);
|
||||
} else {
|
||||
animateTo(
|
||||
offset,
|
||||
duration: duration,
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void jumpToTop() {
|
||||
if (!hasClients) return;
|
||||
jumpTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
extension IterableExt<T> on Iterable<T>? {
|
||||
bool get isNullOrEmpty => this == null || this!.isEmpty;
|
||||
}
|
||||
|
||||
extension NonNullIterableExt<T> on Iterable<T> {
|
||||
T? reduceOrNull(T Function(T value, T element) combine) {
|
||||
Iterator<T> iterator = this.iterator;
|
||||
if (!iterator.moveNext()) {
|
||||
return null;
|
||||
}
|
||||
T value = iterator.current;
|
||||
while (iterator.moveNext()) {
|
||||
value = combine(value, iterator.current);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
extension MapExt<K, V> on Map<K, V> {
|
||||
Map<RK, RV> fromCast<RK, RV>() {
|
||||
return Map<RK, RV>.from(this);
|
||||
}
|
||||
}
|
||||
|
||||
extension ListExt<T> on List<T> {
|
||||
T? getOrNull(int index) {
|
||||
if (index < 0 || index >= length) {
|
||||
return null;
|
||||
}
|
||||
return this[index];
|
||||
}
|
||||
|
||||
bool removeFirstWhere(bool Function(T) test) {
|
||||
final index = indexWhere(test);
|
||||
if (index != -1) {
|
||||
removeAt(index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
List<R> fromCast<R>() {
|
||||
return List<R>.from(this);
|
||||
}
|
||||
|
||||
T findClosestTarget(
|
||||
bool Function(T) test,
|
||||
T Function(T, T) combine,
|
||||
) {
|
||||
return where(test).reduceOrNull(combine) ?? reduce(combine);
|
||||
}
|
||||
}
|
||||
|
||||
final _regExp = RegExp("^(http:)?//", caseSensitive: false);
|
||||
|
||||
extension StringExt on String? {
|
||||
String get http2https => this?.replaceFirst(_regExp, "https://") ?? '';
|
||||
|
||||
bool get isNullOrEmpty => this == null || this!.isEmpty;
|
||||
}
|
||||
|
||||
extension ColorSchemeExt on ColorScheme {
|
||||
Color get vipColor =>
|
||||
brightness.isLight ? const Color(0xFFFF6699) : const Color(0xFFD44E7D);
|
||||
|
||||
Color get freeColor =>
|
||||
brightness.isLight ? const Color(0xFFFF7F24) : const Color(0xFFD66011);
|
||||
|
||||
bool get isLight => brightness.isLight;
|
||||
|
||||
bool get isDark => brightness.isDark;
|
||||
}
|
||||
|
||||
extension Unique<E, Id> on List<E> {
|
||||
List<E> unique([Id Function(E element)? id, bool inplace = true]) {
|
||||
final ids = <Id>{};
|
||||
return (inplace ? this : List<E>.from(this))
|
||||
..retainWhere((x) => ids.add(id != null ? id(x) : x as Id));
|
||||
}
|
||||
}
|
||||
|
||||
extension ColorExtension on Color {
|
||||
Color darken([double amount = .5]) {
|
||||
assert(amount >= 0 && amount <= 1, 'Amount must be between 0 and 1');
|
||||
return Color.lerp(this, Colors.black, amount)!;
|
||||
}
|
||||
}
|
||||
|
||||
extension BrightnessExt on Brightness {
|
||||
Brightness get reverse => isLight ? Brightness.dark : Brightness.light;
|
||||
|
||||
bool get isLight => this == Brightness.light;
|
||||
|
||||
bool get isDark => this == Brightness.dark;
|
||||
}
|
||||
|
||||
extension RationalExt on Rational {
|
||||
/// Checks whether given [Rational] instance fits into Android requirements
|
||||
/// or not.
|
||||
///
|
||||
/// Android docs specified boundaries as inclusive.
|
||||
bool get fitsInAndroidRequirements {
|
||||
final aspectRatio = numerator / denominator;
|
||||
const min = 1 / 2.39;
|
||||
const max = 2.39;
|
||||
return (min <= aspectRatio) && (aspectRatio <= max);
|
||||
}
|
||||
}
|
||||
|
||||
extension ThreeDotItemTypeExt on ThreeDotItemType {
|
||||
Icon get icon => switch (this) {
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_MSG_SETTING => const Icon(
|
||||
Icons.settings,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_READ_ALL => const Icon(
|
||||
Icons.cleaning_services,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_CLEAR_LIST => const Icon(
|
||||
Icons.delete_forever_outlined,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_UP_HELPER => const Icon(
|
||||
Icons.live_tv,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_CONTACTS => const Icon(
|
||||
Icons.account_box_outlined,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_FANS_GROUP_HELPER => const Icon(
|
||||
Icons.notifications_none,
|
||||
size: 20,
|
||||
),
|
||||
_ => const Icon(MdiIcons.circleMedium, size: 20),
|
||||
};
|
||||
|
||||
void action({
|
||||
required BuildContext context,
|
||||
required CommonWhisperController controller,
|
||||
required ThreeDotItem item,
|
||||
}) {
|
||||
switch (this) {
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_READ_ALL:
|
||||
showConfirmDialog(
|
||||
context: context,
|
||||
title: '一键已读',
|
||||
content: '是否清除全部新消息提醒?',
|
||||
onConfirm: controller.onClearUnread,
|
||||
);
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_CLEAR_LIST:
|
||||
showConfirmDialog(
|
||||
context: context,
|
||||
title: '清空列表',
|
||||
content: '清空后所有消息将被删除,无法恢复',
|
||||
onConfirm: controller.onDeleteList,
|
||||
);
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_MSG_SETTING:
|
||||
Get.to(
|
||||
const WhisperSettingsPage(
|
||||
imSettingType: IMSettingType.SETTING_TYPE_NEED_ALL,
|
||||
),
|
||||
);
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_UP_HELPER:
|
||||
dynamic talkerId = RegExp(r'/(\d{3,})').firstMatch(item.url)?.group(1);
|
||||
if (talkerId != null) {
|
||||
talkerId = int.parse(talkerId);
|
||||
Get.toNamed(
|
||||
'/whisperDetail',
|
||||
arguments: {
|
||||
'talkerId': talkerId,
|
||||
'name': item.title,
|
||||
'face': switch (talkerId) {
|
||||
844424930131966 =>
|
||||
'https://message.biliimg.com/bfs/im/489a63efadfb202366c2f88853d2217b5ddc7a13.png',
|
||||
844424930131964 =>
|
||||
'https://i0.hdslb.com/bfs/im_new/58eda511672db078466e7ab8db22a95c1503684976.png',
|
||||
_ => item.icon,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_CONTACTS:
|
||||
Get.to(const ContactPage(isFromSelect: false));
|
||||
default:
|
||||
SmartDialog.showToast('TODO: $name');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FileExt on File {
|
||||
Future<void> tryDel({bool recursive = false}) async {
|
||||
try {
|
||||
await delete(recursive: recursive);
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
extension DirectoryExt on Directory {
|
||||
Future<void> tryDel({bool recursive = false}) async {
|
||||
try {
|
||||
await delete(recursive: recursive);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
Future<bool> lengthGte(int length) async {
|
||||
int count = 0;
|
||||
await for (var _ in list()) {
|
||||
if (++count == length) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
extension SizeExt on Size {
|
||||
bool get isPortrait => width < 600 || height >= width;
|
||||
}
|
||||
|
||||
extension GetExt on GetInterface {
|
||||
S putOrFind<S>(InstanceBuilderCallback<S> dep, {String? tag}) =>
|
||||
GetInstance().putOrFind(dep, tag: tag);
|
||||
}
|
||||
|
||||
extension WidgetExt on Widget {
|
||||
Widget constraintWidth({
|
||||
BoxConstraints constraints = const BoxConstraints(maxWidth: 625),
|
||||
}) {
|
||||
return Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ConstrainedBox(
|
||||
constraints: constraints,
|
||||
child: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
14
lib/utils/extension/extension.dart
Normal file
14
lib/utils/extension/extension.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:floating/floating.dart';
|
||||
|
||||
extension RationalExt on Rational {
|
||||
/// Checks whether given [Rational] instance fits into Android requirements
|
||||
/// or not.
|
||||
///
|
||||
/// Android docs specified boundaries as inclusive.
|
||||
bool get fitsInAndroidRequirements {
|
||||
final aspectRatio = numerator / denominator;
|
||||
const min = 1 / 2.39;
|
||||
const max = 2.39;
|
||||
return (min <= aspectRatio) && (aspectRatio <= max);
|
||||
}
|
||||
}
|
||||
25
lib/utils/extension/file_ext.dart
Normal file
25
lib/utils/extension/file_ext.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
import 'dart:io';
|
||||
|
||||
extension FileExt on File {
|
||||
Future<void> tryDel({bool recursive = false}) async {
|
||||
try {
|
||||
await delete(recursive: recursive);
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
extension DirectoryExt on Directory {
|
||||
Future<void> tryDel({bool recursive = false}) async {
|
||||
try {
|
||||
await delete(recursive: recursive);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
Future<bool> lengthGte(int length) async {
|
||||
int count = 0;
|
||||
await for (var _ in list()) {
|
||||
if (++count == length) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
6
lib/utils/extension/get_ext.dart
Normal file
6
lib/utils/extension/get_ext.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
extension GetExt on GetInterface {
|
||||
S putOrFind<S>(InstanceBuilderCallback<S> dep, {String? tag}) =>
|
||||
GetInstance().putOrFind(dep, tag: tag);
|
||||
}
|
||||
46
lib/utils/extension/iterable_ext.dart
Normal file
46
lib/utils/extension/iterable_ext.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
extension NullableIterableExt<T> on Iterable<T>? {
|
||||
bool get isNullOrEmpty => this == null || this!.isEmpty;
|
||||
}
|
||||
|
||||
extension IterableExt<T> on Iterable<T> {
|
||||
T? reduceOrNull(T Function(T value, T element) combine) {
|
||||
Iterator<T> iterator = this.iterator;
|
||||
if (!iterator.moveNext()) {
|
||||
return null;
|
||||
}
|
||||
T value = iterator.current;
|
||||
while (iterator.moveNext()) {
|
||||
value = combine(value, iterator.current);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
extension ListExt<T> on List<T> {
|
||||
T? getOrNull(int index) {
|
||||
if (index < 0 || index >= length) {
|
||||
return null;
|
||||
}
|
||||
return this[index];
|
||||
}
|
||||
|
||||
bool removeFirstWhere(bool Function(T) test) {
|
||||
final index = indexWhere(test);
|
||||
if (index != -1) {
|
||||
removeAt(index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
List<R> fromCast<R>() {
|
||||
return List<R>.from(this);
|
||||
}
|
||||
|
||||
T findClosestTarget(
|
||||
bool Function(T) test,
|
||||
T Function(T, T) combine,
|
||||
) {
|
||||
return where(test).reduceOrNull(combine) ?? reduce(combine);
|
||||
}
|
||||
}
|
||||
5
lib/utils/extension/map_ext.dart
Normal file
5
lib/utils/extension/map_ext.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
extension MapExt<K, V> on Map<K, V> {
|
||||
Map<RK, RV> fromCast<RK, RV>() {
|
||||
return Map<RK, RV>.from(this);
|
||||
}
|
||||
}
|
||||
15
lib/utils/extension/num_ext.dart
Normal file
15
lib/utils/extension/num_ext.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
extension ImageExtension on num {
|
||||
int? cacheSize(BuildContext context) {
|
||||
if (this == 0) {
|
||||
return null;
|
||||
}
|
||||
return (this * MediaQuery.devicePixelRatioOf(context)).round();
|
||||
}
|
||||
}
|
||||
|
||||
extension IntExt on int? {
|
||||
int? operator +(int other) => this == null ? null : this! + other;
|
||||
int? operator -(int other) => this == null ? null : this! - other;
|
||||
}
|
||||
26
lib/utils/extension/scroll_controller_ext.dart
Normal file
26
lib/utils/extension/scroll_controller_ext.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
extension ScrollControllerExt on ScrollController {
|
||||
void animToTop() => animTo(0);
|
||||
|
||||
void animTo(
|
||||
double offset, {
|
||||
Duration duration = const Duration(milliseconds: 500),
|
||||
}) {
|
||||
if (!hasClients) return;
|
||||
if ((offset - this.offset).abs() >= position.viewportDimension * 7) {
|
||||
jumpTo(offset);
|
||||
} else {
|
||||
animateTo(
|
||||
offset,
|
||||
duration: duration,
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void jumpToTop() {
|
||||
if (!hasClients) return;
|
||||
jumpTo(0);
|
||||
}
|
||||
}
|
||||
5
lib/utils/extension/size_ext.dart
Normal file
5
lib/utils/extension/size_ext.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
import 'dart:ui' show Size;
|
||||
|
||||
extension SizeExt on Size {
|
||||
bool get isPortrait => width < 600 || height >= width;
|
||||
}
|
||||
7
lib/utils/extension/string_ext.dart
Normal file
7
lib/utils/extension/string_ext.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
final _regExp = RegExp("^(http:)?//", caseSensitive: false);
|
||||
|
||||
extension StringExt on String? {
|
||||
String get http2https => this?.replaceFirst(_regExp, "https://") ?? '';
|
||||
|
||||
bool get isNullOrEmpty => this == null || this!.isEmpty;
|
||||
}
|
||||
28
lib/utils/extension/theme_ext.dart
Normal file
28
lib/utils/extension/theme_ext.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension ColorSchemeExt on ColorScheme {
|
||||
Color get vipColor =>
|
||||
brightness.isLight ? const Color(0xFFFF6699) : const Color(0xFFD44E7D);
|
||||
|
||||
Color get freeColor =>
|
||||
brightness.isLight ? const Color(0xFFFF7F24) : const Color(0xFFD66011);
|
||||
|
||||
bool get isLight => brightness.isLight;
|
||||
|
||||
bool get isDark => brightness.isDark;
|
||||
}
|
||||
|
||||
extension ColorExtension on Color {
|
||||
Color darken([double amount = .5]) {
|
||||
assert(amount >= 0 && amount <= 1, 'Amount must be between 0 and 1');
|
||||
return Color.lerp(this, Colors.black, amount)!;
|
||||
}
|
||||
}
|
||||
|
||||
extension BrightnessExt on Brightness {
|
||||
Brightness get reverse => isLight ? Brightness.dark : Brightness.light;
|
||||
|
||||
bool get isLight => this == Brightness.light;
|
||||
|
||||
bool get isDark => this == Brightness.dark;
|
||||
}
|
||||
92
lib/utils/extension/three_dot_ext.dart
Normal file
92
lib/utils/extension/three_dot_ext.dart
Normal file
@@ -0,0 +1,92 @@
|
||||
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
||||
import 'package:PiliPlus/grpc/bilibili/app/im/v1.pb.dart'
|
||||
show ThreeDotItem, ThreeDotItemType, IMSettingType;
|
||||
import 'package:PiliPlus/pages/common/common_whisper_controller.dart';
|
||||
import 'package:PiliPlus/pages/contact/view.dart';
|
||||
import 'package:PiliPlus/pages/whisper_settings/view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
extension ThreeDotItemTypeExt on ThreeDotItemType {
|
||||
Icon get icon => switch (this) {
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_MSG_SETTING => const Icon(
|
||||
Icons.settings,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_READ_ALL => const Icon(
|
||||
Icons.cleaning_services,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_CLEAR_LIST => const Icon(
|
||||
Icons.delete_forever_outlined,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_UP_HELPER => const Icon(
|
||||
Icons.live_tv,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_CONTACTS => const Icon(
|
||||
Icons.account_box_outlined,
|
||||
size: 20,
|
||||
),
|
||||
ThreeDotItemType.THREE_DOT_ITEM_TYPE_FANS_GROUP_HELPER => const Icon(
|
||||
Icons.notifications_none,
|
||||
size: 20,
|
||||
),
|
||||
_ => const Icon(MdiIcons.circleMedium, size: 20),
|
||||
};
|
||||
|
||||
void action({
|
||||
required BuildContext context,
|
||||
required CommonWhisperController controller,
|
||||
required ThreeDotItem item,
|
||||
}) {
|
||||
switch (this) {
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_READ_ALL:
|
||||
showConfirmDialog(
|
||||
context: context,
|
||||
title: '一键已读',
|
||||
content: '是否清除全部新消息提醒?',
|
||||
onConfirm: controller.onClearUnread,
|
||||
);
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_CLEAR_LIST:
|
||||
showConfirmDialog(
|
||||
context: context,
|
||||
title: '清空列表',
|
||||
content: '清空后所有消息将被删除,无法恢复',
|
||||
onConfirm: controller.onDeleteList,
|
||||
);
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_MSG_SETTING:
|
||||
Get.to(
|
||||
const WhisperSettingsPage(
|
||||
imSettingType: IMSettingType.SETTING_TYPE_NEED_ALL,
|
||||
),
|
||||
);
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_UP_HELPER:
|
||||
dynamic talkerId = RegExp(r'/(\d{3,})').firstMatch(item.url)?.group(1);
|
||||
if (talkerId != null) {
|
||||
talkerId = int.parse(talkerId);
|
||||
Get.toNamed(
|
||||
'/whisperDetail',
|
||||
arguments: {
|
||||
'talkerId': talkerId,
|
||||
'name': item.title,
|
||||
'face': switch (talkerId) {
|
||||
844424930131966 =>
|
||||
'https://message.biliimg.com/bfs/im/489a63efadfb202366c2f88853d2217b5ddc7a13.png',
|
||||
844424930131964 =>
|
||||
'https://i0.hdslb.com/bfs/im_new/58eda511672db078466e7ab8db22a95c1503684976.png',
|
||||
_ => item.icon,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
case ThreeDotItemType.THREE_DOT_ITEM_TYPE_CONTACTS:
|
||||
Get.to(const ContactPage(isFromSelect: false));
|
||||
default:
|
||||
SmartDialog.showToast('TODO: $name');
|
||||
}
|
||||
}
|
||||
}
|
||||
15
lib/utils/extension/widget_ext.dart
Normal file
15
lib/utils/extension/widget_ext.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
extension WidgetExt on Widget {
|
||||
Widget constraintWidth({
|
||||
BoxConstraints constraints = const BoxConstraints(maxWidth: 625),
|
||||
}) {
|
||||
return Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ConstrainedBox(
|
||||
constraints: constraints,
|
||||
child: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,12 @@ 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/extension/file_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/string_ext.dart';
|
||||
import 'package:PiliPlus/utils/global_data.dart';
|
||||
import 'package:PiliPlus/utils/path_utils.dart';
|
||||
import 'package:PiliPlus/utils/permission_handler.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
@@ -109,7 +111,8 @@ abstract class ImageUtils {
|
||||
required int height,
|
||||
}) async {
|
||||
try {
|
||||
if (Utils.isMobile && !await checkPermissionDependOnSdkInt(context)) {
|
||||
if (PlatformUtils.isMobile &&
|
||||
!await checkPermissionDependOnSdkInt(context)) {
|
||||
return false;
|
||||
}
|
||||
if (!silentDownImg) SmartDialog.showLoading(msg: '正在下载');
|
||||
@@ -168,7 +171,8 @@ abstract class ImageUtils {
|
||||
List<String> imgList, [
|
||||
CacheManager? manager,
|
||||
]) async {
|
||||
if (Utils.isMobile && !await checkPermissionDependOnSdkInt(context)) {
|
||||
if (PlatformUtils.isMobile &&
|
||||
!await checkPermissionDependOnSdkInt(context)) {
|
||||
return false;
|
||||
}
|
||||
CancelToken? cancelToken;
|
||||
@@ -211,7 +215,7 @@ abstract class ImageUtils {
|
||||
}
|
||||
});
|
||||
final result = await Future.wait(futures, eagerError: true);
|
||||
if (Utils.isMobile) {
|
||||
if (PlatformUtils.isMobile) {
|
||||
final delList = <String>[];
|
||||
final saveList = <SaveFileData>[];
|
||||
for (var i in result) {
|
||||
@@ -292,7 +296,7 @@ abstract class ImageUtils {
|
||||
}) async {
|
||||
SaveResult? result;
|
||||
fileName += '.$ext';
|
||||
if (Utils.isMobile) {
|
||||
if (PlatformUtils.isMobile) {
|
||||
SmartDialog.showLoading(msg: '正在保存');
|
||||
result = await SaverGallery.saveImage(
|
||||
bytes,
|
||||
@@ -336,7 +340,7 @@ abstract class ImageUtils {
|
||||
return;
|
||||
}
|
||||
SaveResult? result;
|
||||
if (Utils.isMobile) {
|
||||
if (PlatformUtils.isMobile) {
|
||||
result = await SaverGallery.saveFile(
|
||||
filePath: filePath,
|
||||
fileName: fileName,
|
||||
|
||||
@@ -18,8 +18,9 @@ import 'package:PiliPlus/pages/share/view.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/menu_row.dart';
|
||||
import 'package:PiliPlus/services/shutdown_timer_service.dart';
|
||||
import 'package:PiliPlus/utils/app_scheme.dart';
|
||||
import 'package:PiliPlus/utils/context_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/context_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/string_ext.dart';
|
||||
import 'package:PiliPlus/utils/feed_back.dart';
|
||||
import 'package:PiliPlus/utils/global_data.dart';
|
||||
import 'package:PiliPlus/utils/id_utils.dart';
|
||||
@@ -423,10 +424,7 @@ abstract class PageUtils {
|
||||
}
|
||||
}
|
||||
// redirectUrl from jumpUrl
|
||||
if (await UrlUtils.parseRedirectUrl(
|
||||
archive.jumpUrl.http2https,
|
||||
false,
|
||||
)
|
||||
if (await UrlUtils.parseRedirectUrl(archive.jumpUrl.http2https, false)
|
||||
case final redirectUrl?) {
|
||||
if (viewPgcFromUri(redirectUrl)) {
|
||||
return;
|
||||
|
||||
10
lib/utils/platform_utils.dart
Normal file
10
lib/utils/platform_utils.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
abstract final class PlatformUtils {
|
||||
@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;
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import 'package:PiliPlus/models/common/reply/reply_sort_type.dart';
|
||||
import 'package:PiliPlus/models_new/reply/data.dart';
|
||||
import 'package:PiliPlus/utils/accounts.dart';
|
||||
import 'package:PiliPlus/utils/accounts/account.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
|
||||
import 'package:PiliPlus/utils/id_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||
|
||||
@@ -24,9 +24,10 @@ import 'package:PiliPlus/pages/group_panel/view.dart';
|
||||
import 'package:PiliPlus/pages/later/controller.dart';
|
||||
import 'package:PiliPlus/pages/login/geetest/geetest_webview_dialog.dart';
|
||||
import 'package:PiliPlus/utils/accounts.dart';
|
||||
import 'package:PiliPlus/utils/context_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/context_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/string_ext.dart';
|
||||
import 'package:PiliPlus/utils/feed_back.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/storage_key.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
@@ -542,7 +543,7 @@ abstract final class RequestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
if (Utils.isDesktop) {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
final json = await Get.dialog<Map<String, dynamic>>(
|
||||
GeetestWebviewDialog(gt!, challenge!),
|
||||
);
|
||||
|
||||
@@ -24,13 +24,13 @@ import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/fullscreen_mode.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/hwdec_type.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart';
|
||||
import 'package:PiliPlus/utils/context_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/context_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
|
||||
import 'package:PiliPlus/utils/global_data.dart';
|
||||
import 'package:PiliPlus/utils/login_utils.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/storage_key.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart' hide ContextExtensionss;
|
||||
import 'package:hive/hive.dart';
|
||||
@@ -277,7 +277,7 @@ abstract class Pref {
|
||||
|
||||
static double get refreshDisplacement => _setting.get(
|
||||
SettingBoxKey.refreshDisplacement,
|
||||
defaultValue: Utils.isMobile ? 20.0 : 40.0,
|
||||
defaultValue: PlatformUtils.isMobile ? 20.0 : 40.0,
|
||||
);
|
||||
|
||||
static String get blockUserID {
|
||||
@@ -878,7 +878,7 @@ abstract class Pref {
|
||||
|
||||
static bool get showBatteryLevel => _setting.get(
|
||||
SettingBoxKey.showBatteryLevel,
|
||||
defaultValue: Utils.isMobile,
|
||||
defaultValue: PlatformUtils.isMobile,
|
||||
);
|
||||
|
||||
static FollowOrderType get followOrderType =>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/main.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:PiliPlus/http/api.dart';
|
||||
import 'package:PiliPlus/http/init.dart';
|
||||
import 'package:PiliPlus/http/ua_type.dart';
|
||||
import 'package:PiliPlus/utils/accounts/account.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/extension/string_ext.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/storage_key.dart';
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'dart:io';
|
||||
import 'dart:math' show Random;
|
||||
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:catcher_2/catcher_2.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
@@ -18,13 +19,6 @@ abstract class Utils {
|
||||
|
||||
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 const jsonEncoder = JsonEncoder.withIndent(' ');
|
||||
|
||||
static Future<void> saveBytes2File({
|
||||
@@ -38,13 +32,13 @@ abstract class Utils {
|
||||
allowedExtensions: allowedExtensions,
|
||||
type: type,
|
||||
fileName: name,
|
||||
bytes: Utils.isDesktop ? null : bytes,
|
||||
bytes: PlatformUtils.isDesktop ? null : bytes,
|
||||
);
|
||||
if (path == null) {
|
||||
SmartDialog.showToast("取消保存");
|
||||
return;
|
||||
}
|
||||
if (Utils.isDesktop) {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
await File(path).writeAsBytes(bytes);
|
||||
}
|
||||
SmartDialog.showToast("已保存");
|
||||
@@ -62,7 +56,7 @@ abstract class Utils {
|
||||
|
||||
static Future<bool> get isWiFi async {
|
||||
try {
|
||||
return Utils.isMobile &&
|
||||
return PlatformUtils.isMobile &&
|
||||
(await Connectivity().checkConnectivity()).contains(
|
||||
ConnectivityResult.wifi,
|
||||
);
|
||||
@@ -96,7 +90,7 @@ abstract class Utils {
|
||||
}
|
||||
|
||||
static Future<void> shareText(String text) async {
|
||||
if (Utils.isDesktop) {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
copyText(text);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user