* 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>
This commit is contained in:
My-Responsitories
2025-09-15 18:45:28 +08:00
committed by GitHub
parent b9a55ccbce
commit 37fb63c3b1
75 changed files with 6300 additions and 1140 deletions

View File

@@ -5,7 +5,7 @@ import 'package:PiliPlus/utils/accounts/account.dart';
import 'package:PiliPlus/utils/login_utils.dart';
import 'package:hive/hive.dart';
class Accounts {
abstract class Accounts {
static late final Box<LoginAccount> account;
static final Map<AccountType, Account> accountMode = {};
static Account get main => accountMode[AccountType.main]!;

View File

@@ -19,7 +19,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class PiliScheme {
abstract class PiliScheme {
static late AppLinks appLinks;
static StreamSubscription? listener;
static final uriDigitRegExp = RegExp(r'/(\d+)');

View File

@@ -3,7 +3,7 @@ import 'dart:convert';
import 'package:PiliPlus/common/constants.dart';
import 'package:crypto/crypto.dart';
class AppSign {
abstract class AppSign {
static void appSign(
Map<String, dynamic> params, [
String appkey = Constants.appKey,

View File

@@ -8,24 +8,24 @@ extension ContextExtensions on BuildContext {
/// The same of [MediaQuery.of(context).size.height]
/// Note: updates when you rezise your screen (like on a browser or
/// desktop window)
double get height => mediaQuerySize.height;
double get height => MediaQuery.heightOf(this);
/// The same of [MediaQuery.of(context).size.width]
/// Note: updates when you rezise your screen (like on a browser or
/// desktop window)
double get width => mediaQuerySize.width;
double get width => MediaQuery.widthOf(this);
/// similar to [MediaQuery.of(context).padding]
ThemeData get theme => Theme.of(this);
/// Check if dark mode theme is enable
bool get isDarkMode => (theme.brightness == Brightness.dark);
bool get isDarkMode => (Theme.brightnessOf(this) == Brightness.dark);
/// give access to Theme.of(context).iconTheme.color
Color? get iconColor => theme.iconTheme.color;
Color? get iconColor => IconTheme.of(this).color;
/// similar to [MediaQuery.of(context).padding]
TextTheme get textTheme => Theme.of(this).textTheme;
TextTheme get textTheme => TextTheme.of(this);
/// similar to [MediaQuery.of(context).padding]
EdgeInsets get mediaQueryPadding => MediaQuery.viewPaddingOf(this);

View File

@@ -1,14 +1,14 @@
import 'package:canvas_danmaku/models/danmaku_content_item.dart';
import 'package:flutter/material.dart';
class DmUtils {
abstract class DmUtils {
static Color decimalToColor(int decimalColor) {
// 16777215 表示白色
int red = (decimalColor >> 16) & 0xFF;
int green = (decimalColor >> 8) & 0xFF;
int blue = decimalColor & 0xFF;
return Color.fromARGB(255, red, green, blue);
return Color.fromRGBO(red, green, blue, 1);
}
static DanmakuItemType getPosition(int mode) {

View File

@@ -1,6 +1,6 @@
import 'package:intl/intl.dart' show DateFormat;
class DateFormatUtils {
abstract class DateFormatUtils {
static final shortFormat = DateFormat('MM-dd');
static final longFormat = DateFormat('yyyy-MM-dd');
static final _shortFormatD = DateFormat('MM-dd HH:mm');

View File

@@ -1,6 +1,6 @@
import 'dart:math' show pow;
class DurationUtils {
abstract class DurationUtils {
static String formatDuration(num? seconds) {
if (seconds == null || seconds == 0) {
return '00:00';

View File

@@ -1,6 +1,6 @@
import 'package:html/parser.dart' show parse;
class Em {
abstract class Em {
static final _exp = RegExp('<[^>]*>([^<]*)</[^>]*>');
static String regCate(String origin) {

View File

@@ -11,7 +11,7 @@ import 'package:PiliPlus/utils/app_scheme.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';
import 'package:get/get.dart' hide ContextExtensionss;
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
extension ImageExtension on num? {
@@ -29,14 +29,19 @@ extension IntExt on int? {
}
extension ScrollControllerExt on ScrollController {
void animToTop() {
void animToTop() => animTo(0);
void animTo(
double offset, {
Duration duration = const Duration(milliseconds: 500),
}) {
if (!hasClients) return;
if (offset >= Get.mediaQuery.size.height * 7) {
jumpTo(0);
if ((offset - this.offset).abs() >= position.viewportDimension * 7) {
jumpTo(offset);
} else {
animateTo(
0,
duration: const Duration(milliseconds: 500),
offset,
duration: duration,
curve: Curves.easeInOut,
);
}
@@ -227,9 +232,9 @@ extension ThreeDotItemTypeExt on ThreeDotItemType {
}
extension FileExt on File {
void tryDel({bool recursive = false}) {
Future<void> tryDel({bool recursive = false}) async {
try {
delete(recursive: recursive);
await delete(recursive: recursive);
} catch (_) {}
}
}

View File

@@ -1,4 +1,4 @@
class FavUtils {
abstract class FavUtils {
static bool isDefaultFav(int? attr) {
if (attr == null) {
return false;

View File

@@ -16,7 +16,7 @@ mixin GridMixin<T extends StatefulWidget> on State<T> {
);
}
class Grid {
abstract class Grid {
static final double smallCardWidth = Pref.smallCardWidth;
static SliverGridDelegateWithExtentAndRatio videoCardHDelegate(

View File

@@ -5,7 +5,7 @@ import 'dart:convert';
import 'package:PiliPlus/utils/utils.dart';
import 'package:uuid/v4.dart';
class IdUtils {
abstract class IdUtils {
static const XOR_CODE = 23442827791579;
static const MASK_CODE = 2251799813685247;
static const MAX_AID = 1 << 51;

View File

@@ -17,7 +17,7 @@ import 'package:live_photo_maker/live_photo_maker.dart';
import 'package:saver_gallery/saver_gallery.dart';
import 'package:share_plus/share_plus.dart';
class ImageUtils {
abstract class ImageUtils {
static String get time =>
DateFormat('yyyy-MM-dd_HH-mm-ss').format(DateTime.now());
static bool silentDownImg = Pref.silentDownImg;

View File

@@ -25,7 +25,7 @@ import 'package:flutter_inappwebview/flutter_inappwebview.dart' as web;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class LoginUtils {
abstract class LoginUtils {
static final random = Random();
static FutureOr setWebCookie([Account? account]) {

View File

@@ -1,7 +1,7 @@
import 'package:flutter/foundation.dart' show kDebugMode, debugPrint;
import 'package:get/get_utils/get_utils.dart';
class NumUtils {
abstract class NumUtils {
static final _numRegExp = RegExp(r'([\d\.]+)([千万亿])?');
static int _getUnit(String? unit) {

View File

@@ -2,6 +2,7 @@ import 'dart:math';
import 'package:PiliPlus/common/widgets/interactiveviewer_gallery/hero_dialog_route.dart';
import 'package:PiliPlus/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart';
import 'package:PiliPlus/common/widgets/marquee.dart';
import 'package:PiliPlus/grpc/im.dart';
import 'package:PiliPlus/http/dynamics.dart';
import 'package:PiliPlus/http/search.dart';
@@ -34,7 +35,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart' hide ContextExtensionss;
import 'package:url_launcher/url_launcher.dart';
class PageUtils {
abstract class PageUtils {
static final RouteObserver<PageRoute> routeObserver =
RouteObserver<PageRoute>();
@@ -44,7 +45,7 @@ class PageUtils {
ValueChanged<int>? onDismissed,
int? quality,
}) {
return Navigator.of(Get.context!).push(
return Get.key.currentState!.push<void>(
HeroDialogRoute(
builder: (context) => InteractiveviewerGallery(
sources: imgList,
@@ -558,23 +559,23 @@ class PageUtils {
}
}
static void onHorizontalPreview(
GlobalKey<ScaffoldState> key,
static void onHorizontalPreviewState(
ScaffoldState state,
TickerProvider vsync,
List<String> imgList,
List<SourceModel> imgList,
int index,
) {
final ctr = AnimationController(
vsync: vsync,
duration: const Duration(milliseconds: 200),
)..forward();
key.currentState?.showBottomSheet(
state.showBottomSheet(
constraints: const BoxConstraints(),
(context) {
return FadeTransition(
opacity: Tween<double>(begin: 0, end: 1).animate(ctr),
child: InteractiveviewerGallery(
sources: imgList.map((url) => SourceModel(url: url)).toList(),
sources: imgList,
initIndex: index,
onClose: (value) async {
if (!value) {
@@ -594,12 +595,30 @@ class PageUtils {
);
},
enableDrag: false,
elevation: 0,
elevation: 0.0,
backgroundColor: Colors.transparent,
sheetAnimationStyle: const AnimationStyle(duration: Duration.zero),
);
}
static void onHorizontalPreview(
BuildContext context,
List<SourceModel> imgList,
int index,
) {
final scaffoldState = Scaffold.maybeOf(context);
if (scaffoldState != null) {
onHorizontalPreviewState(
scaffoldState,
ContextSingleTicker(scaffoldState.context),
imgList,
index,
);
} else {
imageView(imgList: imgList, initialPage: index);
}
}
static void inAppWebview(
String url, {
bool off = false,

View File

@@ -35,7 +35,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart' hide ContextExtensionss;
import 'package:gt3_flutter_plugin/gt3_flutter_plugin.dart';
class RequestUtils {
abstract class RequestUtils {
static Future<void> syncHistoryStatus() async {
final account = Accounts.history;
if (!account.isLogin) {

View File

@@ -1,6 +1,6 @@
// ignore_for_file: constant_identifier_names
class SettingBoxKey {
abstract class SettingBoxKey {
static const String btmProgressBehavior = 'btmProgressBehavior',
defaultVideoSpeed = 'defaultVideoSpeed',
autoUpgradeEnable = 'autoUpgradeEnable',
@@ -210,7 +210,7 @@ class SettingBoxKey {
reduceLuxColor = 'reduceLuxColor';
}
class LocalCacheKey {
abstract class LocalCacheKey {
static const String historyPause = 'historyPause',
blackMids = 'blackMids',
danmakuFilterRules = 'danmakuFilterRules',
@@ -219,7 +219,7 @@ class LocalCacheKey {
buvid = 'buvid';
}
class VideoBoxKey {
abstract class VideoBoxKey {
static const String videoFit = 'videoFit',
videoBrightness = 'videoBrightness',
videoSpeed = 'videoSpeed',

View File

@@ -5,7 +5,7 @@ import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:flex_seed_scheme/flex_seed_scheme.dart';
import 'package:flutter/material.dart';
class ThemeUtils {
abstract class ThemeUtils {
static ThemeData getThemeData({
required ColorScheme colorScheme,
required bool isDynamic,

View File

@@ -15,7 +15,7 @@ import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
class Update {
abstract class Update {
// 检查更新
static Future<void> checkUpdate([bool isAuto = true]) async {
if (kDebugMode) return;

View File

@@ -8,7 +8,7 @@ import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
class UrlUtils {
abstract class UrlUtils {
// 302重定向路由截取
static Future<String?> parseRedirectUrl(
String url, [

View File

@@ -13,13 +13,15 @@ import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
class Utils {
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;

View File

@@ -4,7 +4,7 @@ import 'package:PiliPlus/models_new/live/live_room_play_info/codec.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
class VideoUtils {
abstract class VideoUtils {
static String cdnService = Pref.defaultCDNService;
static bool disableAudioCDN = Pref.disableAudioCDN;

View File

@@ -56,7 +56,8 @@ mixin DynMixin {
itemCount: 10,
);
}
return SliverList.builder(
return SliverPrototypeExtentList.builder(
prototypeItem: const DynamicCardSkeleton(),
itemBuilder: (_, _) => const DynamicCardSkeleton(),
itemCount: 10,
);

View File

@@ -13,7 +13,7 @@ import 'package:crypto/crypto.dart';
import 'package:hive/hive.dart';
import 'package:synchronized/synchronized.dart';
class WbiSign {
abstract class WbiSign {
static Box localCache = GStorage.localCache;
static final Lock lock = Lock();
static final RegExp chrFilter = RegExp(r"[!\'\(\)\*]");