diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index f30099746..5460d9942 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -62,8 +62,8 @@ jobs: - name: flutter build apk run: | - chmod +x lib/scripts/build.sh - lib/scripts/build.sh + chmod +x lib/scripts/build.dart + dart lib/scripts/build.dart flutter build apk --release --split-per-abi - name: 上传 diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index 5c5909566..67ebdb960 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -39,8 +39,8 @@ jobs: - name: Build iOS run: | - chmod +x lib/scripts/build.sh - lib/scripts/build.sh + chmod +x lib/scripts/build.dart + dart lib/scripts/build.dart flutter build ios --release --no-codesign ln -sf ./build/ios/iphoneos Payload zip -r9 ios-release-no-sign.ipa Payload/runner.app diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml new file mode 100644 index 000000000..f0f372c87 --- /dev/null +++ b/.github/workflows/win.yml @@ -0,0 +1,49 @@ +name: Build for Windows + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + paths-ignore: + - '**.md' + workflow_dispatch: + inputs: + branch: + required: false + default: 'main' + +jobs: + build-windows-app: + name: Release Windows + runs-on: windows-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.branch }} + fetch-depth: 0 + + - name: Setup flutter + uses: subosito/flutter-action@v2 + with: + channel: stable + flutter-version-file: pubspec.yaml + + - name: Build Windows + run: | + dart lib/scripts/build.dart + flutter build windows --release + + - name: Prepare Upload + run: | + mkdir -p Release/PiliPlus-Win + mv build/windows/x64/runner/Release/* Release/PiliPlus-Win/ + + - name: Upload windows release + uses: actions/upload-artifact@v4 + with: + name: windows-release + path: Release \ No newline at end of file diff --git a/android/.gitignore b/android/.gitignore index 6f568019d..0a357b9e3 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -11,3 +11,6 @@ GeneratedPluginRegistrant.java key.properties **/*.keystore **/*.jks + +/build +/.kotlin diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index aed3f941d..18e5aed95 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -24,8 +24,7 @@ android { defaultConfig { applicationId = "com.example.piliplus" -// minSdk = flutter.minSdkVersion - minSdkVersion(23) + minSdk = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName diff --git a/android/build.gradle.kts b/android/build.gradle.kts index eaa8e9780..be844ccc8 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -34,8 +34,8 @@ subprojects { } project.tasks.withType().configureEach { - kotlinOptions { - jvmTarget = "17" + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index ac3b47926..3cdc9e0d6 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://downloads.gradle.org/distributions/gradle-8.13-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index fb605bc84..53113ce1a 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -19,8 +19,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.9.1" apply false - id("org.jetbrains.kotlin.android") version "2.1.0" apply false + id("com.android.application") version "8.12.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.0" apply false } include(":app") diff --git a/lib/common/widgets/color_palette.dart b/lib/common/widgets/color_palette.dart index 2be1b2bae..8cf5ff8ec 100644 --- a/lib/common/widgets/color_palette.dart +++ b/lib/common/widgets/color_palette.dart @@ -19,7 +19,6 @@ class ColorPalette extends StatelessWidget { final primary = Color(Hct.from(hct.hue, 20.0, 90.0).toInt()); final tertiary = Color(Hct.from(hct.hue + 50, 20.0, 85.0).toInt()); final primaryContainer = Color(Hct.from(hct.hue, 30.0, 50.0).toInt()); - final checkbox = Color(Hct.from(hct.hue, 30.0, 40.0).toInt()); Widget coloredBox(Color color) => Expanded( child: ColoredBox( color: color, @@ -51,7 +50,7 @@ class ColorPalette extends StatelessWidget { width: 23, height: 23, decoration: BoxDecoration( - color: checkbox, + color: Color(Hct.from(hct.hue, 30.0, 40.0).toInt()), shape: BoxShape.circle, ), child: Icon( diff --git a/lib/common/widgets/image/image_save.dart b/lib/common/widgets/image/image_save.dart index d9d77fdd7..b6a46f94a 100644 --- a/lib/common/widgets/image/image_save.dart +++ b/lib/common/widgets/image/image_save.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/http/user.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -111,14 +111,14 @@ void imageSaveDialog({ tooltip: '分享', onPressed: () { SmartDialog.dismiss(); - ImageUtil.onShareImg(cover!); + ImageUtils.onShareImg(cover!); }, icon: Icons.share, ), iconBtn( tooltip: '保存封面图', onPressed: () async { - bool saveStatus = await ImageUtil.downloadImg( + bool saveStatus = await ImageUtils.downloadImg( context, [cover!], ); diff --git a/lib/common/widgets/image/network_img_layer.dart b/lib/common/widgets/image/network_img_layer.dart index 878ab396a..3111e3467 100644 --- a/lib/common/widgets/image/network_img_layer.dart +++ b/lib/common/widgets/image/network_img_layer.dart @@ -1,7 +1,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; @@ -83,7 +83,7 @@ class NetworkImgLayer extends StatelessWidget { memCacheHeight = height.cacheSize(context); } return CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(src, quality), + imageUrl: ImageUtils.thumbnailUrl(src, quality), width: width, height: height, memCacheWidth: memCacheWidth, diff --git a/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart b/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart index e0188dcf4..b867a83ec 100644 --- a/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart +++ b/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart @@ -5,7 +5,8 @@ import 'package:PiliPlus/common/widgets/interactiveviewer_gallery/interactive_vi import 'package:PiliPlus/common/widgets/interactiveviewer_gallery/interactive_viewer_boundary.dart'; import 'package:PiliPlus/models/common/image_preview_type.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; +import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; @@ -224,7 +225,7 @@ class _InteractiveviewerGalleryState extends State String _getActualUrl(String url) { return _quality != 100 - ? ImageUtil.thumbnailUrl(url, _quality) + ? ImageUtils.thumbnailUrl(url, _quality) : url.http2https; } @@ -351,7 +352,7 @@ class _InteractiveviewerGalleryState extends State final item = widget.sources[currentIndex.value]; return [ PopupMenuItem( - onTap: () => ImageUtil.onShareImg(item.url), + onTap: () => ImageUtils.onShareImg(item.url), child: const Text("分享图片"), ), PopupMenuItem( @@ -359,15 +360,20 @@ class _InteractiveviewerGalleryState extends State child: const Text("复制链接"), ), PopupMenuItem( - onTap: () => ImageUtil.downloadImg( + onTap: () => ImageUtils.downloadImg( this.context, [item.url], ), child: const Text("保存图片"), ), - if (widget.sources.length > 1) + if (Utils.isDesktop) PopupMenuItem( - onTap: () => ImageUtil.downloadImg( + onTap: () => PageUtils.launchURL(item.url), + child: const Text("网页打开"), + ) + else if (widget.sources.length > 1) + PopupMenuItem( + onTap: () => ImageUtils.downloadImg( this.context, widget.sources.map((item) => item.url).toList(), ), @@ -376,7 +382,7 @@ class _InteractiveviewerGalleryState extends State if (item.sourceType == SourceType.livePhoto) PopupMenuItem( onTap: () { - ImageUtil.downloadLivePhoto( + ImageUtils.downloadLivePhoto( context: this.context, url: item.url, liveUrl: item.liveUrl!, @@ -417,7 +423,7 @@ class _InteractiveviewerGalleryState extends State return CachedNetworkImage( fadeInDuration: Duration.zero, fadeOutDuration: Duration.zero, - imageUrl: ImageUtil.thumbnailUrl(item.url, widget.quality), + imageUrl: ImageUtils.thumbnailUrl(item.url, widget.quality), ); }, ), @@ -497,7 +503,7 @@ class _InteractiveviewerGalleryState extends State ListTile( onTap: () { Get.back(); - ImageUtil.onShareImg(item.url); + ImageUtils.onShareImg(item.url); }, dense: true, title: const Text('分享', style: TextStyle(fontSize: 14)), @@ -513,7 +519,7 @@ class _InteractiveviewerGalleryState extends State ListTile( onTap: () { Get.back(); - ImageUtil.downloadImg( + ImageUtils.downloadImg( this.context, [item.url], ); @@ -521,11 +527,20 @@ class _InteractiveviewerGalleryState extends State dense: true, title: const Text('保存图片', style: TextStyle(fontSize: 14)), ), - if (widget.sources.length > 1) + if (Utils.isDesktop) ListTile( onTap: () { Get.back(); - ImageUtil.downloadImg( + PageUtils.launchURL(item.url); + }, + dense: true, + title: const Text('网页打开', style: TextStyle(fontSize: 14)), + ) + else if (widget.sources.length > 1) + ListTile( + onTap: () { + Get.back(); + ImageUtils.downloadImg( this.context, widget.sources.map((item) => item.url).toList(), ); @@ -537,7 +552,7 @@ class _InteractiveviewerGalleryState extends State ListTile( onTap: () { Get.back(); - ImageUtil.downloadLivePhoto( + ImageUtils.downloadLivePhoto( context: this.context, url: item.url, liveUrl: item.liveUrl!, diff --git a/lib/common/widgets/pendant_avatar.dart b/lib/common/widgets/pendant_avatar.dart index 5c0fba0a4..9384cfd15 100644 --- a/lib/common/widgets/pendant_avatar.dart +++ b/lib/common/widgets/pendant_avatar.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/avatar_badge_type.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:cached_network_image/cached_network_image.dart'; @@ -64,7 +64,7 @@ class PendantAvatar extends StatelessWidget { child: CachedNetworkImage( width: size * 1.75, height: size * 1.75, - imageUrl: ImageUtil.thumbnailUrl(garbPendantImage), + imageUrl: ImageUtils.thumbnailUrl(garbPendantImage), ), ), ), diff --git a/lib/common/widgets/stat/stat.dart b/lib/common/widgets/stat/stat.dart index b87606fd3..580c6e97f 100644 --- a/lib/common/widgets/stat/stat.dart +++ b/lib/common/widgets/stat/stat.dart @@ -1,5 +1,5 @@ import 'package:PiliPlus/models/common/stat_type.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:flutter/material.dart'; class StatWidget extends StatelessWidget { @@ -32,7 +32,7 @@ class StatWidget extends StatelessWidget { color: color, ), Text( - NumUtil.numFormat(value), + NumUtils.numFormat(value), style: TextStyle(fontSize: 12, color: color), ), ], diff --git a/lib/common/widgets/video_card/video_card_h.dart b/lib/common/widgets/video_card/video_card_h.dart index 15149f3be..087a1e644 100644 --- a/lib/common/widgets/video_card/video_card_h.dart +++ b/lib/common/widgets/video_card/video_card_h.dart @@ -11,8 +11,8 @@ import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models/model_hot_video_item.dart'; import 'package:PiliPlus/models/model_video.dart'; import 'package:PiliPlus/models/search/result.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -158,7 +158,7 @@ class VideoCardH extends StatelessWidget { PBadge( text: progress == -1 ? '已看完' - : '${DurationUtil.formatDuration(progress)}/${DurationUtil.formatDuration(videoItem.duration)}', + : '${DurationUtils.formatDuration(progress)}/${DurationUtils.formatDuration(videoItem.duration)}', right: 6, bottom: 8, type: PBadgeType.gray, @@ -175,7 +175,7 @@ class VideoCardH extends StatelessWidget { ), ] else if (videoItem.duration > 0) PBadge( - text: DurationUtil.formatDuration( + text: DurationUtils.formatDuration( videoItem.duration, ), right: 6.0, @@ -210,7 +210,7 @@ class VideoCardH extends StatelessWidget { Widget content(BuildContext context) { final theme = Theme.of(context); - String pubdate = DateUtil.dateFormat(videoItem.pubdate!); + String pubdate = DateFormatUtils.dateFormat(videoItem.pubdate!); if (pubdate != '') pubdate += ' '; return Expanded( child: Column( diff --git a/lib/common/widgets/video_card/video_card_v.dart b/lib/common/widgets/video_card/video_card_v.dart index 76a085fa3..2607b5fa1 100644 --- a/lib/common/widgets/video_card/video_card_v.dart +++ b/lib/common/widgets/video_card/video_card_v.dart @@ -9,8 +9,8 @@ import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models/model_rec_video_item.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -103,7 +103,7 @@ class VideoCardV extends StatelessWidget { right: 7, size: PBadgeSize.small, type: PBadgeType.gray, - text: DurationUtil.formatDuration( + text: DurationUtils.formatDuration( videoItem.duration, ), ), @@ -233,7 +233,7 @@ class VideoCardV extends StatelessWidget { fontSize: theme.textTheme.labelSmall!.fontSize, color: theme.colorScheme.outline.withValues(alpha: 0.8), ), - text: DateUtil.dateFormat( + text: DateFormatUtils.dateFormat( videoItem.pubdate, short: shortFormat, long: longFormat, diff --git a/lib/main.dart b/lib/main.dart index 3a7d778e1..1c635121c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,24 +10,26 @@ import 'package:PiliPlus/services/logger.dart'; import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; import 'package:PiliPlus/utils/cache_manage.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/request_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/theme_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:catcher_2/catcher_2.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:flex_seed_scheme/flex_seed_scheme.dart'; -import 'package:flutter/foundation.dart' show kDebugMode; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; -import 'package:media_kit/media_kit.dart'; // Provides [Player], [Media], [Playlist] etc. +import 'package:media_kit/media_kit.dart'; +import 'package:window_manager/window_manager.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -38,36 +40,62 @@ void main() async { await Future.wait([ CacheManage.autoClearCache(), - if (Pref.horizontalScreen) + if (Utils.isMobile) ...[ SystemChrome.setPreferredOrientations( - //支持竖屏与横屏 [ DeviceOrientation.portraitUp, - // DeviceOrientation.portraitDown, - DeviceOrientation.landscapeLeft, - DeviceOrientation.landscapeRight, + if (Pref.horizontalScreen) ...[ + DeviceOrientation.landscapeLeft, + DeviceOrientation.landscapeRight, + ], ], - ) - else - SystemChrome.setPreferredOrientations( - //支持竖屏 - [DeviceOrientation.portraitUp], ), - setupServiceLocator(), + setupServiceLocator(), + ], ]); Request(); Request.setCookie(); + RequestUtils.syncHistoryStatus(); + PiliScheme.init(); SmartDialog.config.toast = SmartConfigToast( displayType: SmartToastType.onlyRefresh, ); + if (Utils.isMobile) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + systemNavigationBarColor: Colors.transparent, + systemNavigationBarDividerColor: Colors.transparent, + statusBarColor: Colors.transparent, + systemNavigationBarContrastEnforced: false, + ), + ); + } else if (Utils.isDesktop) { + await windowManager.ensureInitialized(); + WindowOptions windowOptions = WindowOptions( + minimumSize: const Size(400, 720), + size: const Size(1180, 720), + center: true, + skipTaskbar: false, + titleBarStyle: Platform.isMacOS + ? TitleBarStyle.hidden + : TitleBarStyle.normal, + title: 'PiliPlus', + ); + windowManager.waitUntilReadyToShow(windowOptions, () async { + await windowManager.show(); + await windowManager.focus(); + }); + } + if (Pref.enableLog) { // 异常捕获 logo记录 String buildConfig = '''\n -Build Time: ${DateUtil.format(BuildConfig.buildTime, format: DateUtil.longFormatDs)} +Build Time: ${DateFormatUtils.format(BuildConfig.buildTime, format: DateFormatUtils.longFormatDs)} Commit Hash: ${BuildConfig.commitHash}'''; final Catcher2Options debugConfig = Catcher2Options( SilentReportMode(), @@ -107,19 +135,6 @@ Commit Hash: ${BuildConfig.commitHash}'''; } else { runApp(const MyApp()); } - - // 小白条、导航栏沉浸 - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - SystemChrome.setSystemUIOverlayStyle( - const SystemUiOverlayStyle( - systemNavigationBarColor: Colors.transparent, - systemNavigationBarDividerColor: Colors.transparent, - statusBarColor: Colors.transparent, - systemNavigationBarContrastEnforced: false, - ), - ); - RequestUtils.syncHistoryStatus(); - PiliScheme.init(); } class MyApp extends StatelessWidget { @@ -219,6 +234,7 @@ class MyApp extends StatelessWidget { FlutterSmartDialog.observer, PageUtils.routeObserver, ], + scrollBehavior: const ScrollBehavior().copyWith(scrollbars: false), ); }), ); @@ -234,8 +250,7 @@ class _CustomHttpOverrides extends HttpOverrides { // ..maxConnectionsPerHost = 32 ..idleTimeout = const Duration(seconds: 15); if (badCertificateCallback) { - client.badCertificateCallback = - (X509Certificate cert, String host, int port) => true; + client.badCertificateCallback = (cert, host, port) => true; } return client; } diff --git a/lib/models/home/rcmd/result.dart b/lib/models/home/rcmd/result.dart index 13004f488..be2205806 100644 --- a/lib/models/home/rcmd/result.dart +++ b/lib/models/home/rcmd/result.dart @@ -1,7 +1,7 @@ import 'package:PiliPlus/models/model_rec_video_item.dart'; import 'package:PiliPlus/models/model_video.dart'; import 'package:PiliPlus/utils/id_utils.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; class RecVideoItemAppModel extends BaseRecVideoItemModel { int? get id => aid; @@ -26,7 +26,7 @@ class RecVideoItemAppModel extends BaseRecVideoItemModel { // json['top_rcmd_reason']; if (rcmdReason != null && rcmdReason!.contains('赞')) { // 有时能在推荐原因里获得点赞数 - (stat as RcmdStat).like = NumUtil.parseNum(rcmdReason!); + (stat as RcmdStat).like = NumUtils.parseNum(rcmdReason!); } // 由于app端api并不会直接返回与owner的关注状态 // 所以借用推荐原因是否为“已关注”、“新关注”判别关注状态,从而与web端接口等效 @@ -53,8 +53,8 @@ class RecVideoItemAppModel extends BaseRecVideoItemModel { class RcmdStat extends BaseStat { RcmdStat.fromJson(Map json) { - view = NumUtil.parseNum(json["cover_left_text_1"] ?? ''); - danmu = NumUtil.parseNum(json["cover_left_text_2"] ?? ''); + view = NumUtils.parseNum(json["cover_left_text_1"] ?? ''); + danmu = NumUtils.parseNum(json["cover_left_text_2"] ?? ''); } } diff --git a/lib/models/search/result.dart b/lib/models/search/result.dart index aaaa5c199..72fc2cd58 100644 --- a/lib/models/search/result.dart +++ b/lib/models/search/result.dart @@ -1,7 +1,7 @@ import 'package:PiliPlus/models/model_avatar.dart'; import 'package:PiliPlus/models/model_owner.dart'; import 'package:PiliPlus/models/model_video.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/em.dart'; import 'package:PiliPlus/utils/extension.dart'; @@ -85,7 +85,7 @@ class SearchVideoItemModel extends BaseVideoItemModel { cover = (json['pic'] as String?)?.http2https; pubdate = json['pubdate']; ctime = json['senddate']; - duration = DurationUtil.parseDuration(json['duration']); + duration = DurationUtils.parseDuration(json['duration']); owner = SearchOwner.fromJson(json); stat = SearchStat.fromJson(json); isUnionVideo = json['is_union_video']; diff --git a/lib/models_new/member/search_archive/vlist.dart b/lib/models_new/member/search_archive/vlist.dart index 58f060a18..2d67c43cc 100644 --- a/lib/models_new/member/search_archive/vlist.dart +++ b/lib/models_new/member/search_archive/vlist.dart @@ -1,5 +1,5 @@ import 'package:PiliPlus/models/model_video.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; class VListItemModel extends BaseVideoItemModel { int? comment; @@ -21,7 +21,7 @@ class VListItemModel extends BaseVideoItemModel { review = json['review']; pubdate = json['created']; if (json['length'] != null) { - duration = DurationUtil.parseDuration(json['length']); + duration = DurationUtils.parseDuration(json['length']); } aid = json['aid']; bvid = json['bvid']; diff --git a/lib/pages/about/view.dart b/lib/pages/about/view.dart index c97573e16..78299a3ea 100644 --- a/lib/pages/about/view.dart +++ b/lib/pages/about/view.dart @@ -11,14 +11,13 @@ import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts/account.dart'; import 'package:PiliPlus/utils/cache_manage.dart'; import 'package:PiliPlus/utils/context_ext.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/login_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/update.dart'; import 'package:PiliPlus/utils/utils.dart'; -import 'package:dio/dio.dart' show Headers; -import 'package:document_file_save_plus/document_file_save_plus_platform_interface.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart' hide ListTile; import 'package:flutter/services.dart' show Clipboard, ClipboardData; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -30,7 +29,6 @@ import 'package:re_highlight/languages/json.dart'; import 'package:re_highlight/re_highlight.dart'; import 'package:re_highlight/styles/github-dark.dart'; import 'package:re_highlight/styles/github.dart'; -import 'package:share_plus/share_plus.dart'; class AboutPage extends StatefulWidget { const AboutPage({super.key, this.showAppBar = true}); @@ -161,7 +159,7 @@ class _AboutPageState extends State { ListTile( title: Text( ''' -Build Time: ${DateUtil.format(BuildConfig.buildTime, format: DateUtil.longFormatDs)} +Build Time: ${DateFormatUtils.format(BuildConfig.buildTime, format: DateFormatUtils.longFormatDs)} Commit Hash: ${BuildConfig.commitHash}''', style: const TextStyle(fontSize: 14), ), @@ -248,7 +246,9 @@ Commit Hash: ${BuildConfig.commitHash}''', onTap: () => showInportExportDialog( context, title: '登录信息', - toJson: () => jsonEncode(Accounts.account.toMap()), + toJson: () => const JsonEncoder.withIndent( + ' ', + ).convert(Accounts.account.toMap()), fromJson: (json) async { final res = json.map( (key, value) => MapEntry(key, LoginAccount.fromJson(value)), @@ -349,27 +349,22 @@ Future showInportExportDialog( 'piliplus_${label}_${context.isTablet ? 'pad' : 'phone'}_' '${DateFormat('yyyyMMddHHmmss').format(DateTime.now())}.json'; try { - DocumentFileSavePlusPlatform.instance.saveMultipleFiles( - dataList: [res], - fileNameList: [name], - mimeTypeList: const [Headers.jsonContentType], + final path = await FilePicker.platform.saveFile( + allowedExtensions: ['json'], + type: FileType.custom, + fileName: name, + bytes: Utils.isDesktop ? null : res, ); - if (Platform.isAndroid) { - SmartDialog.showToast('已保存'); + if (path == null) { + SmartDialog.showToast("取消保存"); + return; } + if (Utils.isDesktop) { + await File(path).writeAsBytes(res); + } + SmartDialog.showToast("已保存"); } catch (e) { - SharePlus.instance.share( - ShareParams( - files: [ - XFile.fromData( - res, - name: name, - mimeType: Headers.jsonContentType, - ), - ], - sharePositionOrigin: await Utils.sharePositionOrigin, - ), - ); + SmartDialog.showToast("保存失败: $e"); } }, ), diff --git a/lib/pages/article/view.dart b/lib/pages/article/view.dart index a26a11ccc..d6726de62 100644 --- a/lib/pages/article/view.dart +++ b/lib/pages/article/view.dart @@ -20,11 +20,11 @@ import 'package:PiliPlus/pages/article/widgets/opus_content.dart'; import 'package:PiliPlus/pages/common/dyn/common_dyn_page.dart'; import 'package:PiliPlus/pages/dynamics_repost/view.dart'; import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/image_util.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; @@ -295,7 +295,7 @@ class _ArticlePageState extends CommonDynPageState { fit: pic.isLongPic == true ? BoxFit.cover : null, - imageUrl: ImageUtil.thumbnailUrl( + imageUrl: ImageUtils.thumbnailUrl( pic.url, 60, ), @@ -371,7 +371,7 @@ class _ArticlePageState extends CommonDynPageState { ), if (pubTime != null) Text( - DateUtil.format(pubTime), + DateFormatUtils.format(pubTime), style: TextStyle( color: theme.colorScheme.outline, fontSize: @@ -596,7 +596,7 @@ class _ArticlePageState extends CommonDynPageState { ), style: btnStyle, label: Text( - stat?.count != null ? NumUtil.numFormat(stat!.count) : text, + stat?.count != null ? NumUtils.numFormat(stat!.count) : text, style: TextStyle(color: color), ), ); diff --git a/lib/pages/article/widgets/article_ops.dart b/lib/pages/article/widgets/article_ops.dart index 2ce624840..c3c1e459b 100644 --- a/lib/pages/article/widgets/article_ops.dart +++ b/lib/pages/article/widgets/article_ops.dart @@ -3,7 +3,7 @@ import 'package:PiliPlus/models_new/article/article_view/ops.dart'; import 'package:PiliPlus/pages/dynamics/widgets/vote.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -57,7 +57,7 @@ class ArticleOpus extends StatelessWidget { child: ClipRRect( borderRadius: StyleString.mdRadius, child: CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(card.url, 60), + imageUrl: ImageUtils.thumbnailUrl(card.url, 60), ), ), ); diff --git a/lib/pages/article/widgets/html_render.dart b/lib/pages/article/widgets/html_render.dart index 89274cea6..6810c70cd 100644 --- a/lib/pages/article/widgets/html_render.dart +++ b/lib/pages/article/widgets/html_render.dart @@ -1,5 +1,5 @@ import 'package:PiliPlus/models/common/image_preview_type.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/foundation.dart' show kDebugMode; @@ -42,7 +42,7 @@ Widget htmlRender({ return CachedNetworkImage( width: maxWidth, height: height != null ? double.parse(height) : null, - imageUrl: ImageUtil.thumbnailUrl(imgUrl), + imageUrl: ImageUtils.thumbnailUrl(imgUrl), fit: BoxFit.contain, ); } @@ -63,7 +63,7 @@ Widget htmlRender({ child: CachedNetworkImage( width: size, height: size, - imageUrl: ImageUtil.thumbnailUrl(imgUrl, 60), + imageUrl: ImageUtils.thumbnailUrl(imgUrl, 60), fadeInDuration: const Duration(milliseconds: 120), fadeOutDuration: const Duration(milliseconds: 120), placeholder: (context, url) => diff --git a/lib/pages/article/widgets/opus_content.dart b/lib/pages/article/widgets/opus_content.dart index 3c856f68a..a54bdca25 100644 --- a/lib/pages/article/widgets/opus_content.dart +++ b/lib/pages/article/widgets/opus_content.dart @@ -12,7 +12,7 @@ import 'package:PiliPlus/pages/dynamics/widgets/vote.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/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_svg_image/cached_network_svg_image.dart'; @@ -196,7 +196,7 @@ class OpusContent extends StatelessWidget { child: CachedNetworkImage( width: width, height: height, - imageUrl: ImageUtil.thumbnailUrl(pic.url!, 60), + imageUrl: ImageUtils.thumbnailUrl(pic.url!, 60), fadeInDuration: const Duration(milliseconds: 120), fadeOutDuration: const Duration(milliseconds: 120), placeholder: (context, url) => @@ -224,7 +224,7 @@ class OpusContent extends StatelessWidget { width: maxWidth, fit: BoxFit.contain, height: element.line!.pic!.height?.toDouble(), - imageUrl: ImageUtil.thumbnailUrl(element.line!.pic!.url!), + imageUrl: ImageUtils.thumbnailUrl(element.line!.pic!.url!), ); case 5 when (element.list != null): return SelectableText.rich( @@ -642,7 +642,7 @@ Widget moduleBlockedItem( image: DecorationImage( fit: BoxFit.fill, image: CachedNetworkImageProvider( - ImageUtil.thumbnailUrl( + ImageUtils.thumbnailUrl( isDarkMode ? moduleBlocked.bgImg!.imgDark : moduleBlocked.bgImg!.imgDay, @@ -656,7 +656,7 @@ Widget moduleBlockedItem( return CachedNetworkImage( width: width, fit: BoxFit.contain, - imageUrl: ImageUtil.thumbnailUrl( + imageUrl: ImageUtils.thumbnailUrl( isDarkMode ? moduleBlocked.icon!.imgDark : moduleBlocked.icon!.imgDay, ), ); diff --git a/lib/pages/article_list/view.dart b/lib/pages/article_list/view.dart index 3d76ab3a4..b7351d8d5 100644 --- a/lib/pages/article_list/view.dart +++ b/lib/pages/article_list/view.dart @@ -8,9 +8,9 @@ import 'package:PiliPlus/models_new/article/article_list/article.dart'; import 'package:PiliPlus/models_new/article/article_list/list.dart'; import 'package:PiliPlus/pages/article_list/controller.dart'; import 'package:PiliPlus/pages/article_list/widgets/item.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -158,12 +158,12 @@ class _ArticleListPageState extends State with GridMixin { TextSpan( children: [ TextSpan( - text: '${NumUtil.numFormat(item.articlesCount)}篇专栏', + text: '${NumUtils.numFormat(item.articlesCount)}篇专栏', ), divider, - TextSpan(text: '${NumUtil.numFormat(item.words)}个字'), + TextSpan(text: '${NumUtils.numFormat(item.words)}个字'), divider, - TextSpan(text: '${NumUtil.numFormat(item.read)}次阅读'), + TextSpan(text: '${NumUtils.numFormat(item.read)}次阅读'), ], style: style, ), @@ -172,7 +172,7 @@ class _ArticleListPageState extends State with GridMixin { TextSpan( children: [ TextSpan( - text: '${DateUtil.dateFormat(item.updateTime)}更新', + text: '${DateFormatUtils.dateFormat(item.updateTime)}更新', ), divider, TextSpan(text: '文集号: ${item.id}'), diff --git a/lib/pages/blacklist/view.dart b/lib/pages/blacklist/view.dart index c6f92d380..549e47d3b 100644 --- a/lib/pages/blacklist/view.dart +++ b/lib/pages/blacklist/view.dart @@ -6,7 +6,7 @@ import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models_new/blacklist/list.dart'; import 'package:PiliPlus/pages/blacklist/controller.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/global_data.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:flutter/material.dart'; @@ -98,7 +98,7 @@ class _BlackListPageState extends State { style: const TextStyle(fontSize: 14), ), subtitle: Text( - '添加时间: ${DateUtil.format(item.mtime, format: DateUtil.longFormatDs)}', + '添加时间: ${DateFormatUtils.format(item.mtime, format: DateFormatUtils.longFormatDs)}', maxLines: 1, style: style, overflow: TextOverflow.ellipsis, diff --git a/lib/pages/common/dyn/common_dyn_page.dart b/lib/pages/common/dyn/common_dyn_page.dart index cae4a1dfe..795aab3bb 100644 --- a/lib/pages/common/dyn/common_dyn_page.dart +++ b/lib/pages/common/dyn/common_dyn_page.dart @@ -12,7 +12,7 @@ import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPlus/pages/video/reply_reply/view.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/feed_back.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; @@ -124,7 +124,7 @@ abstract class CommonDynPageState extends State () { final count = controller.count.value; return Text( - '${count == -1 ? 0 : NumUtil.numFormat(count)}条回复', + '${count == -1 ? 0 : NumUtils.numFormat(count)}条回复', ); }, ), diff --git a/lib/pages/common/publish/common_publish_page.dart b/lib/pages/common/publish/common_publish_page.dart index 81bb57ae3..ca364d959 100644 --- a/lib/pages/common/publish/common_publish_page.dart +++ b/lib/pages/common/publish/common_publish_page.dart @@ -99,8 +99,6 @@ abstract class CommonPublishPageState void updatePanelType(PanelType type) { final isSwitchToKeyboard = PanelType.keyboard == type; - final isSwitchToEmojiPanel = - PanelType.emoji == type || PanelType.more == type; bool isUpdated = false; switch (type) { case PanelType.keyboard: @@ -119,9 +117,9 @@ abstract class CommonPublishPageState ? ChatBottomPanelType.keyboard : ChatBottomPanelType.other, data: type, - forceHandleFocus: isSwitchToEmojiPanel + forceHandleFocus: isSwitchToKeyboard ? ChatBottomHandleFocus.requestFocus - : ChatBottomHandleFocus.none, + : ChatBottomHandleFocus.unfocus, ); } diff --git a/lib/pages/common/publish/common_rich_text_pub_page.dart b/lib/pages/common/publish/common_rich_text_pub_page.dart index df678005a..e54481e50 100644 --- a/lib/pages/common/publish/common_rich_text_pub_page.dart +++ b/lib/pages/common/publish/common_rich_text_pub_page.dart @@ -16,6 +16,7 @@ import 'package:PiliPlus/pages/dynamics_mention/view.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:dio/dio.dart' show CancelToken; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; @@ -62,7 +63,7 @@ abstract class CommonRichTextPubPageState @override void dispose() { for (var i in pathList) { - File(i).delSync(); + File(i).tryDel(); } super.dispose(); } @@ -115,18 +116,19 @@ abstract class CommonRichTextPubPageState ), ), ), - Positioned( - top: 34, - right: 5, - child: iconButton( - context: context, - icon: Icons.edit, - onPressed: () => onCropImage(index), - size: 24, - iconSize: 14, - bgColor: color, + if (Utils.isMobile) + Positioned( + top: 34, + right: 5, + child: iconButton( + context: context, + icon: Icons.edit, + onPressed: () => onCropImage(index), + size: 24, + iconSize: 14, + bgColor: color, + ), ), - ), Positioned( top: 5, right: 5, diff --git a/lib/pages/dynamics/widgets/action_panel.dart b/lib/pages/dynamics/widgets/action_panel.dart index fde13c07e..ae73f4c61 100644 --- a/lib/pages/dynamics/widgets/action_panel.dart +++ b/lib/pages/dynamics/widgets/action_panel.dart @@ -1,7 +1,7 @@ import 'package:PiliPlus/common/widgets/dyn/text_button.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/pages/dynamics_repost/view.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/request_utils.dart'; import 'package:flutter/material.dart' hide TextButton; @@ -55,7 +55,7 @@ class ActionPanel extends StatelessWidget { ), style: btnStyle, label: Text( - forward.count != null ? NumUtil.numFormat(forward.count) : '转发', + forward.count != null ? NumUtils.numFormat(forward.count) : '转发', ), ), ), @@ -70,7 +70,7 @@ class ActionPanel extends StatelessWidget { ), style: btnStyle, label: Text( - comment.count != null ? NumUtil.numFormat(comment.count) : '评论', + comment.count != null ? NumUtils.numFormat(comment.count) : '评论', ), ), ), @@ -96,7 +96,7 @@ class ActionPanel extends StatelessWidget { return ScaleTransition(scale: animation, child: child); }, child: Text( - like.count != null ? NumUtil.numFormat(like.count) : '点赞', + like.count != null ? NumUtils.numFormat(like.count) : '点赞', key: ValueKey(like.count?.toString() ?? '点赞'), style: TextStyle(color: like.status! ? primary : outline), ), diff --git a/lib/pages/dynamics/widgets/additional_panel.dart b/lib/pages/dynamics/widgets/additional_panel.dart index a0e2e300a..48d70bd9a 100644 --- a/lib/pages/dynamics/widgets/additional_panel.dart +++ b/lib/pages/dynamics/widgets/additional_panel.dart @@ -6,7 +6,7 @@ import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/models_new/dynamic/dyn_reserve/data.dart'; import 'package:PiliPlus/pages/dynamics/widgets/vote.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:flutter/foundation.dart' show kDebugMode; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart' hide InkWell; @@ -446,7 +446,7 @@ Widget addWidget( overflow: TextOverflow.ellipsis, ), Text( - '${NumUtil.numFormat(vote.joinNum)}人参与', + '${NumUtils.numFormat(vote.joinNum)}人参与', maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( diff --git a/lib/pages/dynamics/widgets/author_panel.dart b/lib/pages/dynamics/widgets/author_panel.dart index ccfe72e05..2e0b11475 100644 --- a/lib/pages/dynamics/widgets/author_panel.dart +++ b/lib/pages/dynamics/widgets/author_panel.dart @@ -12,7 +12,7 @@ import 'package:PiliPlus/pages/dynamics/controller.dart'; import 'package:PiliPlus/pages/save_panel/view.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/context_ext.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/page_utils.dart'; @@ -63,11 +63,11 @@ class AuthorPanel extends StatelessWidget { final moduleAuthor = item.modules.moduleAuthor!; final pubTime = moduleAuthor.pubTs != null ? isSave - ? DateUtil.format( + ? DateFormatUtils.format( moduleAuthor.pubTs, - format: DateUtil.longFormatDs, + format: DateFormatUtils.longFormatDs, ) - : DateUtil.dateFormat(moduleAuthor.pubTs) + : DateFormatUtils.dateFormat(moduleAuthor.pubTs) : moduleAuthor.pubTime; return Stack( clipBehavior: Clip.none, diff --git a/lib/pages/dynamics/widgets/forward_panel.dart b/lib/pages/dynamics/widgets/forward_panel.dart index e83bdad43..09cbb2e92 100644 --- a/lib/pages/dynamics/widgets/forward_panel.dart +++ b/lib/pages/dynamics/widgets/forward_panel.dart @@ -3,7 +3,7 @@ import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/pages/dynamics/widgets/dyn_content.dart'; import 'package:PiliPlus/pages/dynamics/widgets/module_panel.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart' hide InkWell; import 'package:get/get.dart'; @@ -123,8 +123,11 @@ Widget _forwardAuthor({ const SizedBox(width: 6), Text( isSave - ? DateUtil.format(moduleAuthor.pubTs, format: DateUtil.longFormatDs) - : DateUtil.dateFormat(moduleAuthor.pubTs), + ? DateFormatUtils.format( + moduleAuthor.pubTs, + format: DateFormatUtils.longFormatDs, + ) + : DateFormatUtils.dateFormat(moduleAuthor.pubTs), style: TextStyle( color: theme.colorScheme.outline, fontSize: theme.textTheme.labelSmall!.fontSize, diff --git a/lib/pages/dynamics/widgets/video_panel.dart b/lib/pages/dynamics/widgets/video_panel.dart index bc79f2063..f7d437599 100644 --- a/lib/pages/dynamics/widgets/video_panel.dart +++ b/lib/pages/dynamics/widgets/video_panel.dart @@ -4,7 +4,7 @@ import 'package:PiliPlus/common/widgets/badge.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:flutter/material.dart'; Widget videoSeasonWidget( @@ -112,11 +112,11 @@ Widget videoSeasonWidget( ], if (video.stat case final stat?) ...[ Text( - '${NumUtil.numFormat(stat.play)}次围观', + '${NumUtils.numFormat(stat.play)}次围观', ), const SizedBox(width: 6), Text( - '${NumUtil.numFormat(stat.danmu)}条弹幕', + '${NumUtils.numFormat(stat.danmu)}条弹幕', ), ], const Spacer(), diff --git a/lib/pages/dynamics/widgets/vote.dart b/lib/pages/dynamics/widgets/vote.dart index 099aab9d7..0d51ddf14 100644 --- a/lib/pages/dynamics/widgets/vote.dart +++ b/lib/pages/dynamics/widgets/vote.dart @@ -4,8 +4,8 @@ import 'package:PiliPlus/common/widgets/dialog/report.dart'; import 'package:PiliPlus/http/dynamics.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/dynamics/vote_model.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart' hide ContextExtensionss; @@ -119,13 +119,13 @@ class _VotePanelState extends State { runSpacing: 5, children: [ Text( - '至 ${DateUtil.format(_voteInfo.endTime, format: DateUtil.longFormatDs)}', + '至 ${DateFormatUtils.format(_voteInfo.endTime, format: DateFormatUtils.longFormatDs)}', ), Text.rich( TextSpan( children: [ TextSpan( - text: NumUtil.numFormat(_voteInfo.joinNum), + text: NumUtils.numFormat(_voteInfo.joinNum), style: TextStyle(color: theme.colorScheme.primary), ), const TextSpan(text: '人参与'), diff --git a/lib/pages/dynamics_create/view.dart b/lib/pages/dynamics_create/view.dart index 996ce7f04..f1f3f0481 100644 --- a/lib/pages/dynamics_create/view.dart +++ b/lib/pages/dynamics_create/view.dart @@ -25,7 +25,7 @@ import 'package:PiliPlus/pages/emote/controller.dart'; import 'package:PiliPlus/pages/emote/view.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/context_ext.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/grid.dart'; import 'package:PiliPlus/utils/request_utils.dart'; import 'package:flutter/foundation.dart' show kDebugMode; @@ -524,7 +524,7 @@ class _CreateDynPanelState extends CommonRichTextPubPageState { visualDensity: VisualDensity.compact, ), onPressed: () => _publishTime.value = null, - label: Text(DateUtil.longFormatD.format(_publishTime.value!)), + label: Text(DateFormatUtils.longFormatD.format(_publishTime.value!)), icon: const Icon(Icons.clear, size: 20), iconAlignment: IconAlignment.end, ); @@ -792,7 +792,7 @@ class _CreateDynPanelState extends CommonRichTextPubPageState { children: [ Text('直播预约: ${reserveCard.title}'), Text( - '${DateUtil.longFormatD.format( + '${DateFormatUtils.longFormatD.format( DateTime.fromMillisecondsSinceEpoch(reserveCard.livePlanStartTime! * 1000), )} 直播', ), diff --git a/lib/pages/dynamics_create_reserve/view.dart b/lib/pages/dynamics_create_reserve/view.dart index d7f8a92e8..b01a2055e 100644 --- a/lib/pages/dynamics_create_reserve/view.dart +++ b/lib/pages/dynamics_create_reserve/view.dart @@ -1,5 +1,5 @@ import 'package:PiliPlus/pages/dynamics_create_reserve/controller.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' @@ -127,7 +127,7 @@ class _CreateReservePageState extends State { padding: const EdgeInsets.symmetric(vertical: 4), child: Obx( () => Text( - DateUtil.longFormatD.format(_controller.date.value), + DateFormatUtils.longFormatD.format(_controller.date.value), ), ), ), diff --git a/lib/pages/dynamics_create_vote/view.dart b/lib/pages/dynamics_create_vote/view.dart index 71acf83fd..faffefad8 100644 --- a/lib/pages/dynamics_create_vote/view.dart +++ b/lib/pages/dynamics_create_vote/view.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/dynamics/vote_model.dart'; import 'package:PiliPlus/pages/dynamics_create_vote/controller.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; @@ -244,7 +244,7 @@ class _CreateVotePageState extends State { padding: const EdgeInsets.symmetric(vertical: 4), child: Obx( () => Text( - DateUtil.longFormatD.format(_controller.endtime.value), + DateFormatUtils.longFormatD.format(_controller.endtime.value), ), ), ), diff --git a/lib/pages/dynamics_detail/view.dart b/lib/pages/dynamics_detail/view.dart index 085e500ae..dbe026d8a 100644 --- a/lib/pages/dynamics_detail/view.dart +++ b/lib/pages/dynamics_detail/view.dart @@ -11,7 +11,7 @@ import 'package:PiliPlus/pages/dynamics_detail/controller.dart'; import 'package:PiliPlus/pages/dynamics_repost/view.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/request_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -235,7 +235,7 @@ class _DynamicDetailPageState extends CommonDynPageState { ), style: btnStyle, label: Text( - stat?.count != null ? NumUtil.numFormat(stat!.count) : text, + stat?.count != null ? NumUtils.numFormat(stat!.count) : text, style: TextStyle(color: color), ), ); diff --git a/lib/pages/dynamics_mention/widgets/item.dart b/lib/pages/dynamics_mention/widgets/item.dart index 8039edbad..61d515de0 100644 --- a/lib/pages/dynamics_mention/widgets/item.dart +++ b/lib/pages/dynamics_mention/widgets/item.dart @@ -1,7 +1,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models_new/dynamic/dyn_mention/item.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:flutter/material.dart'; class DynMentionItem extends StatelessWidget { @@ -34,7 +34,7 @@ class DynMentionItem extends StatelessWidget { style: const TextStyle(fontSize: 14), ), subtitle: Text( - '${NumUtil.numFormat(item.fans)}粉丝', + '${NumUtils.numFormat(item.fans)}粉丝', style: TextStyle(color: Theme.of(context).colorScheme.outline), ), trailing: Checkbox( diff --git a/lib/pages/dynamics_select_topic/widgets/item.dart b/lib/pages/dynamics_select_topic/widgets/item.dart index 2545b091c..3df4ccf5b 100644 --- a/lib/pages/dynamics_select_topic/widgets/item.dart +++ b/lib/pages/dynamics_select_topic/widgets/item.dart @@ -1,6 +1,6 @@ import 'package:PiliPlus/common/widgets/custom_icon.dart'; import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/topic_item.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:flutter/material.dart'; class DynTopicItem extends StatelessWidget { @@ -43,7 +43,7 @@ class DynTopicItem extends StatelessWidget { subtitle: Padding( padding: const EdgeInsets.only(left: 23), child: Text( - '${NumUtil.numFormat(item.view)}浏览 · ${NumUtil.numFormat(item.discuss)}讨论', + '${NumUtils.numFormat(item.view)}浏览 · ${NumUtils.numFormat(item.discuss)}讨论', style: TextStyle(color: Theme.of(context).colorScheme.outline), ), ), diff --git a/lib/pages/dynamics_topic/view.dart b/lib/pages/dynamics_topic/view.dart index 4cab8241c..043aa3b53 100644 --- a/lib/pages/dynamics_topic/view.dart +++ b/lib/pages/dynamics_topic/view.dart @@ -13,7 +13,7 @@ import 'package:PiliPlus/pages/dynamics/widgets/dynamic_panel.dart'; import 'package:PiliPlus/pages/dynamics_create/view.dart'; import 'package:PiliPlus/pages/dynamics_topic/controller.dart'; import 'package:PiliPlus/utils/global_data.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:PiliPlus/utils/waterfall.dart'; @@ -231,7 +231,7 @@ class _DynTopicPageState extends State with DynMixin { Row( children: [ Text( - '${NumUtil.numFormat(response.topicItem!.view)}浏览 · ${NumUtil.numFormat(response.topicItem!.discuss)}讨论', + '${NumUtils.numFormat(response.topicItem!.view)}浏览 · ${NumUtils.numFormat(response.topicItem!.discuss)}讨论', style: TextStyle( fontSize: 13, color: theme.colorScheme.outline, @@ -261,7 +261,7 @@ class _DynTopicPageState extends State with DynMixin { ? const Icon(FontAwesomeIcons.solidThumbsUp, size: 13) : const Icon(FontAwesomeIcons.thumbsUp, size: 13), label: Text( - NumUtil.numFormat(response.topicItem!.like), + NumUtils.numFormat(response.topicItem!.like), style: const TextStyle(fontSize: 13), textScaler: TextScaler.noScaling, ), @@ -290,7 +290,7 @@ class _DynTopicPageState extends State with DynMixin { ? const Icon(FontAwesomeIcons.solidStar, size: 13) : const Icon(FontAwesomeIcons.star, size: 13), label: Text( - NumUtil.numFormat(response.topicItem!.fav), + NumUtils.numFormat(response.topicItem!.fav), style: const TextStyle(fontSize: 13), textScaler: TextScaler.noScaling, ), diff --git a/lib/pages/episode_panel/view.dart b/lib/pages/episode_panel/view.dart index 2c7b39436..8bf61e2b0 100644 --- a/lib/pages/episode_panel/view.dart +++ b/lib/pages/episode_panel/view.dart @@ -25,8 +25,8 @@ import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/widgets/page.dart'; import 'package:PiliPlus/utils/accounts.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:flutter/foundation.dart' show kDebugMode; @@ -412,7 +412,7 @@ class _EpisodePanelState extends CommonCollapseSlidePageState { ), if (duration != null && duration > 0) PBadge( - text: DurationUtil.formatDuration(duration), + text: DurationUtils.formatDuration(duration), right: 6.0, bottom: 6.0, type: PBadgeType.gray, @@ -466,7 +466,7 @@ class _EpisodePanelState extends CommonCollapseSlidePageState { ), if (pubdate != null) Text( - DateUtil.format(pubdate), + DateFormatUtils.format(pubdate), maxLines: 1, style: TextStyle( fontSize: 12, diff --git a/lib/pages/fav/video/widgets/item.dart b/lib/pages/fav/video/widgets/item.dart index 1efa915e7..188c136b1 100644 --- a/lib/pages/fav/video/widgets/item.dart +++ b/lib/pages/fav/video/widgets/item.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/fav/fav_folder/list.dart'; -import 'package:PiliPlus/utils/fav_util.dart'; +import 'package:PiliPlus/utils/fav_utils.dart'; import 'package:flutter/material.dart'; class FavVideoItem extends StatelessWidget { @@ -96,7 +96,7 @@ class FavVideoItem extends StatelessWidget { ), const Spacer(), Text( - FavUtil.isPublicFavText(item.attr), + FavUtils.isPublicFavText(item.attr), style: TextStyle( fontSize: fontSize, color: color, diff --git a/lib/pages/fav_create/view.dart b/lib/pages/fav_create/view.dart index e19827945..a2d854d77 100644 --- a/lib/pages/fav_create/view.dart +++ b/lib/pages/fav_create/view.dart @@ -2,8 +2,8 @@ import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/http/fav.dart'; import 'package:PiliPlus/http/msg.dart'; import 'package:PiliPlus/models_new/fav/fav_folder/list.dart'; -import 'package:PiliPlus/utils/fav_util.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/fav_utils.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; @@ -46,7 +46,7 @@ class _CreateFavPageState extends State { FavFolderInfo data = res['data']; _titleController.text = data.title; _introController.text = data.intro ?? ''; - _isPublic = FavUtil.isPublicFav(data.attr); + _isPublic = FavUtils.isPublicFav(data.attr); _cover = data.cover; _attr = data.attr; } else { @@ -176,7 +176,7 @@ class _CreateFavPageState extends State { Widget _buildBody(ThemeData theme) => SingleChildScrollView( child: Column( children: [ - if (_attr == null || !FavUtil.isDefaultFav(_attr!)) ...[ + if (_attr == null || !FavUtils.isDefaultFav(_attr!)) ...[ Builder( builder: (context) { return ListTile( @@ -251,7 +251,7 @@ class _CreateFavPageState extends State { Radius.circular(6), ), child: CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(_cover!), + imageUrl: ImageUtils.thumbnailUrl(_cover!), height: 55, width: 88, fit: BoxFit.cover, @@ -298,11 +298,11 @@ class _CreateFavPageState extends State { ), title: TextField( autofocus: true, - readOnly: _attr != null && FavUtil.isDefaultFav(_attr!), + readOnly: _attr != null && FavUtils.isDefaultFav(_attr!), controller: _titleController, style: TextStyle( fontSize: 14, - color: _attr != null && FavUtil.isDefaultFav(_attr!) + color: _attr != null && FavUtils.isDefaultFav(_attr!) ? theme.colorScheme.outline : null, ), @@ -325,7 +325,7 @@ class _CreateFavPageState extends State { ), ), const SizedBox(height: 16), - if (_attr == null || !FavUtil.isDefaultFav(_attr!)) ...[ + if (_attr == null || !FavUtils.isDefaultFav(_attr!)) ...[ ListTile( tileColor: theme.colorScheme.onInverseSurface, title: Row( diff --git a/lib/pages/fav_detail/view.dart b/lib/pages/fav_detail/view.dart index 3781004fe..3a0b3a78f 100644 --- a/lib/pages/fav_detail/view.dart +++ b/lib/pages/fav_detail/view.dart @@ -12,7 +12,7 @@ import 'package:PiliPlus/models_new/fav/fav_folder/list.dart'; import 'package:PiliPlus/pages/dynamics_repost/view.dart'; import 'package:PiliPlus/pages/fav_detail/controller.dart'; import 'package:PiliPlus/pages/fav_detail/widget/fav_video_card.dart'; -import 'package:PiliPlus/utils/fav_util.dart'; +import 'package:PiliPlus/utils/fav_utils.dart'; import 'package:PiliPlus/utils/grid.dart'; import 'package:PiliPlus/utils/request_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -161,7 +161,7 @@ class _FavDetailPageState extends State with GridMixin { ), Obx(() { final attr = _favDetailController.folderInfo.value.attr; - return attr == -1 || !FavUtil.isPublicFav(attr) + return attr == -1 || !FavUtils.isPublicFav(attr) ? const SizedBox.shrink() : IconButton( iconSize: 22, @@ -221,7 +221,7 @@ class _FavDetailPageState extends State with GridMixin { _favDetailController.onFav(folderInfo.favState == 1), child: Text('${folderInfo.favState == 1 ? '取消' : ''}收藏'), ), - if (FavUtil.isPublicFav(folderInfo.attr)) + if (FavUtils.isPublicFav(folderInfo.attr)) PopupMenuItem( onTap: () => showModalBottomSheet( context: context, @@ -242,7 +242,7 @@ class _FavDetailPageState extends State with GridMixin { onTap: _favDetailController.cleanFav, child: const Text('清除失效内容'), ), - if (!FavUtil.isDefaultFav(folderInfo.attr)) ...[ + if (!FavUtils.isDefaultFav(folderInfo.attr)) ...[ const PopupMenuDivider(height: 12), PopupMenuItem( onTap: () => showConfirmDialog( @@ -434,7 +434,7 @@ class _FavDetailPageState extends State with GridMixin { ], Text( '共${folderInfo.mediaCount}条视频 · ' - '${FavUtil.isPublicFavText(folderInfo.attr)}', + '${FavUtils.isPublicFavText(folderInfo.attr)}', style: style, ), ], diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index 3f4aaf4f0..48d140990 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -9,8 +9,8 @@ import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/fav/fav_detail/media.dart'; import 'package:PiliPlus/pages/fav_detail/controller.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -95,7 +95,7 @@ class FavVideoCardH extends StatelessWidget { height: maxHeight, ), PBadge( - text: DurationUtil.formatDuration(item.duration), + text: DurationUtils.formatDuration(item.duration), right: 6.0, bottom: 6.0, type: PBadgeType.gray, @@ -158,7 +158,7 @@ class FavVideoCardH extends StatelessWidget { ), const Spacer(), Text( - '${DateUtil.dateFormat(item.favTime)} ${item.upper?.name}', + '${DateFormatUtils.dateFormat(item.favTime)} ${item.upper?.name}', maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( diff --git a/lib/pages/fav_panel/view.dart b/lib/pages/fav_panel/view.dart index 06b63eb00..e3fb05444 100644 --- a/lib/pages/fav_panel/view.dart +++ b/lib/pages/fav_panel/view.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models_new/fav/fav_folder/list.dart'; import 'package:PiliPlus/pages/common/common_intro_controller.dart'; -import 'package:PiliPlus/utils/fav_util.dart'; +import 'package:PiliPlus/utils/fav_utils.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -64,13 +64,13 @@ class _FavPanelState extends State { return ListTile( onTap: onTap, dense: true, - leading: FavUtil.isPublicFav(item.attr) + leading: FavUtils.isPublicFav(item.attr) ? const Icon(Icons.folder_outlined) : const Icon(Icons.lock_outline), minLeadingWidth: 0, title: Text(item.title), subtitle: Text( - '${item.mediaCount}个内容 . ${FavUtil.isPublicFavText(item.attr)}', + '${item.mediaCount}个内容 . ${FavUtils.isPublicFavText(item.attr)}', ), trailing: Transform.scale( scale: 0.9, diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index 3d162ad0c..f5a4ac350 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -8,8 +8,8 @@ import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models_new/history/list.dart'; import 'package:PiliPlus/pages/common/multi_select/base.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -124,7 +124,7 @@ class HistoryItem extends StatelessWidget { PBadge( text: item.progress == -1 ? '已看完' - : '${DurationUtil.formatDuration(item.progress)}/${DurationUtil.formatDuration(item.duration)}', + : '${DurationUtils.formatDuration(item.progress)}/${DurationUtils.formatDuration(item.duration)}', right: 6.0, bottom: 8.0, type: PBadgeType.gray, @@ -283,7 +283,7 @@ class HistoryItem extends StatelessWidget { ), ), Text( - DateUtil.chatFormat(item.viewAt!, isHistory: true), + DateFormatUtils.chatFormat(item.viewAt!, isHistory: true), style: TextStyle( fontSize: theme.textTheme.labelMedium!.fontSize, color: theme.colorScheme.outline, diff --git a/lib/pages/hot/view.dart b/lib/pages/hot/view.dart index 58084aca2..7b1d94f17 100644 --- a/lib/pages/hot/view.dart +++ b/lib/pages/hot/view.dart @@ -10,7 +10,7 @@ import 'package:PiliPlus/pages/home/controller.dart'; import 'package:PiliPlus/pages/hot/controller.dart'; import 'package:PiliPlus/pages/rank/view.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -44,7 +44,7 @@ class _HotPageState extends CommonPageState CachedNetworkImage( width: 35, height: 35, - imageUrl: ImageUtil.thumbnailUrl(iconUrl), + imageUrl: ImageUtils.thumbnailUrl(iconUrl), ), const SizedBox(height: 4), Text( diff --git a/lib/pages/later/widgets/video_card_h_later.dart b/lib/pages/later/widgets/video_card_h_later.dart index eefc008e6..0aa60fe09 100644 --- a/lib/pages/later/widgets/video_card_h_later.dart +++ b/lib/pages/later/widgets/video_card_h_later.dart @@ -11,7 +11,7 @@ import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/models_new/later/list.dart'; import 'package:PiliPlus/pages/later/controller.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -130,7 +130,7 @@ class VideoCardHLater extends StatelessWidget { PBadge( text: progress == -1 ? '已看完' - : '${DurationUtil.formatDuration(progress)}/${DurationUtil.formatDuration(videoItem.duration)}', + : '${DurationUtils.formatDuration(progress)}/${DurationUtils.formatDuration(videoItem.duration)}', right: 6, bottom: 8, type: PBadgeType.gray, @@ -147,7 +147,7 @@ class VideoCardHLater extends StatelessWidget { ), ] else if (videoItem.duration! > 0) PBadge( - text: DurationUtil.formatDuration( + text: DurationUtils.formatDuration( videoItem.duration, ), right: 6.0, diff --git a/lib/pages/live/widgets/live_item_app.dart b/lib/pages/live/widgets/live_item_app.dart index f232de644..2b6e135e3 100644 --- a/lib/pages/live/widgets/live_item_app.dart +++ b/lib/pages/live/widgets/live_item_app.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/live/live_feed_index/card_data_list_item.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -129,7 +129,7 @@ class LiveCardVApp extends StatelessWidget { ), if (item.watchedShow?.textSmall != null) Text( - '${NumUtil.numFormat(item.watchedShow!.textSmall)}围观', + '${NumUtils.numFormat(item.watchedShow!.textSmall)}围观', style: const TextStyle(fontSize: 11, color: Colors.white), ), ], diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index cd94053eb..3e823b06d 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -174,7 +174,7 @@ class LiveRoomController extends GetxController { if (res['status']) { RoomInfoH5Data data = res['data']; roomInfoH5.value = data; - videoPlayerServiceHandler.onVideoDetailChange(data, roomId, heroTag); + videoPlayerServiceHandler?.onVideoDetailChange(data, roomId, heroTag); } else { if (res['msg'] != null) { _showDialog(res['msg']); diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index a2c62a826..e177dc46a 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -20,7 +20,7 @@ import 'package:PiliPlus/plugin/pl_player/models/play_status.dart'; import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart'; import 'package:PiliPlus/plugin/pl_player/view.dart'; import 'package:PiliPlus/services/service_locator.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; @@ -34,7 +34,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show SystemUiOverlayStyle; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart' hide ContextExtensionss; -import 'package:screen_brightness/screen_brightness.dart'; +import 'package:screen_brightness_platform_interface/screen_brightness_platform_interface.dart'; class LiveRoomPage extends StatefulWidget { const LiveRoomPage({super.key}); @@ -138,9 +138,11 @@ class _LiveRoomPageState extends State @override void dispose() { - videoPlayerServiceHandler.onVideoDetailDispose(heroTag); + videoPlayerServiceHandler?.onVideoDetailDispose(heroTag); WidgetsBinding.instance.removeObserver(this); - ScreenBrightness.instance.resetApplicationScreenBrightness(); + if (Utils.isMobile) { + ScreenBrightnessPlatform.instance.resetApplicationScreenBrightness(); + } PlPlayerController.setPlayCallBack(null); plPlayerController ..removeStatusLister(playerListener) @@ -539,7 +541,7 @@ class _LiveRoomPageState extends State if (text.isNotEmpty) { text += ' '; } - final duration = DurationUtil.formatDurationBetween( + final duration = DurationUtils.formatDurationBetween( liveTime * 1000, DateTime.now().millisecondsSinceEpoch, ); diff --git a/lib/pages/live_search/widgets/live_search_room.dart b/lib/pages/live_search/widgets/live_search_room.dart index 248e249c4..9bef3b7cd 100644 --- a/lib/pages/live_search/widgets/live_search_room.dart +++ b/lib/pages/live_search/widgets/live_search_room.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/live/live_search/room_item.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -100,7 +100,7 @@ class LiveCardVSearch extends StatelessWidget { ), if (item.watchedShow?.textSmall != null) Text( - '${NumUtil.numFormat(item.watchedShow!.textSmall)}围观', + '${NumUtils.numFormat(item.watchedShow!.textSmall)}围观', style: const TextStyle(fontSize: 11, color: Colors.white), ), ], diff --git a/lib/pages/live_search/widgets/live_search_user.dart b/lib/pages/live_search/widgets/live_search_user.dart index 82a27f84b..4d992a4f7 100644 --- a/lib/pages/live_search/widgets/live_search_user.dart +++ b/lib/pages/live_search/widgets/live_search_user.dart @@ -1,7 +1,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models_new/live/live_search/user_item.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -55,7 +55,7 @@ class LiveSearchUserItem extends StatelessWidget { ), const SizedBox(height: 2), Text( - '分区: ${item.areaName ?? ''} 关注数: ${NumUtil.numFormat(item.fansNum ?? 0)}', + '分区: ${item.areaName ?? ''} 关注数: ${NumUtils.numFormat(item.fansNum ?? 0)}', style: style, ), ], diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index c790fcb45..e2f10d658 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -3,7 +3,7 @@ import 'dart:ui'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/pages/login/controller.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -11,7 +11,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart' hide ContextExtensionss; import 'package:pretty_qr_code/pretty_qr_code.dart'; -import 'package:saver_gallery/saver_gallery.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @@ -62,21 +61,8 @@ class _LoginPageState extends State { ); Uint8List pngBytes = byteData!.buffer.asUint8List(); SmartDialog.dismiss(); - SmartDialog.showLoading(msg: '正在保存至图库'); - String picName = "PiliPlus_loginQRCode_${ImageUtil.time}"; - final SaveResult result = await SaverGallery.saveImage( - Uint8List.fromList(pngBytes), - fileName: picName, - extension: 'png', - androidRelativePath: "Pictures/PiliPlus", - skipIfExists: false, - ); - SmartDialog.dismiss(); - if (result.isSuccess) { - await SmartDialog.showToast('「$picName」已保存 '); - } else { - await SmartDialog.showToast('保存失败,${result.errorMessage}'); - } + String picName = "PiliPlus_loginQRCode_${ImageUtils.time}"; + ImageUtils.saveByteImg(bytes: pngBytes, fileName: picName); }, icon: const Icon(Icons.save), label: const Text('保存至相册'), diff --git a/lib/pages/match_info/view.dart b/lib/pages/match_info/view.dart index 28751a468..3018febaa 100644 --- a/lib/pages/match_info/view.dart +++ b/lib/pages/match_info/view.dart @@ -14,7 +14,7 @@ import 'package:PiliPlus/pages/common/dyn/common_dyn_page.dart'; import 'package:PiliPlus/pages/match_info/controller.dart'; import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPlus/pages/video/reply_reply/view.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:easy_debounce/easy_throttle.dart'; @@ -156,14 +156,14 @@ class _MatchInfoPageState extends CommonDynPageState { ) else if (data.contestStatus == 3) Text( - '${DateUtil.dateFormat(data.stime)}${data.contestStatus == 3 ? ' 已结束' : ''}', + '${DateFormatUtils.dateFormat(data.stime)}${data.contestStatus == 3 ? ' 已结束' : ''}', style: TextStyle( color: theme.colorScheme.outline, ), ) else if (data.contestStatus == 1) Text( - DateUtil.format( + DateFormatUtils.format( data.stime, format: DateFormat('yy-MM-dd HH:mm'), ), diff --git a/lib/pages/member/widget/user_info_card.dart b/lib/pages/member/widget/user_info_card.dart index 19722d00d..9de204605 100644 --- a/lib/pages/member/widget/user_info_card.dart +++ b/lib/pages/member/widget/user_info_card.dart @@ -12,8 +12,8 @@ import 'package:PiliPlus/models_new/space/space/pr_info.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/context_ext.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; @@ -66,7 +66,7 @@ class UserInfoCard extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Text( - NumUtil.numFormat(count), + NumUtils.numFormat(count), style: const TextStyle(fontSize: 14), ), Text( @@ -95,7 +95,7 @@ class UserInfoCard extends StatelessWidget { child: GestureDetector( onTap: () => PageUtils.imageView(imgList: [SourceModel(url: imgUrl)]), child: CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(imgUrl), + imageUrl: ImageUtils.thumbnailUrl(imgUrl), width: double.infinity, height: 135, imageBuilder: (context, imageProvider) => DecoratedBox( @@ -172,7 +172,7 @@ class UserInfoCard extends StatelessWidget { ), if (card.nameplate?.imageSmall?.isNotEmpty == true) CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(card.nameplate!.imageSmall!), + imageUrl: ImageUtils.thumbnailUrl(card.nameplate!.imageSmall!), height: 20, placeholder: (context, url) { return const SizedBox.shrink(); @@ -489,13 +489,13 @@ class UserInfoCard extends StatelessWidget { children: [ if (!isLight && prInfo.iconNight?.isNotEmpty == true) ...[ CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(card.prInfo!.iconNight!), + imageUrl: ImageUtils.thumbnailUrl(card.prInfo!.iconNight!), height: 20, ), const SizedBox(width: 16), ] else if (prInfo.icon?.isNotEmpty == true) ...[ CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(card.prInfo!.icon!), + imageUrl: ImageUtils.thumbnailUrl(card.prInfo!.icon!), height: 20, ), const SizedBox(width: 16), diff --git a/lib/pages/member_audio/widgets/item.dart b/lib/pages/member_audio/widgets/item.dart index 20406d892..39c92e3d0 100644 --- a/lib/pages/member_audio/widgets/item.dart +++ b/lib/pages/member_audio/widgets/item.dart @@ -5,7 +5,7 @@ import 'package:PiliPlus/common/widgets/stat/stat.dart'; import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/space/space_audio/item.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -72,7 +72,7 @@ class MemberAudioItem extends StatelessWidget { ), const SizedBox(height: 6), Text( - DateUtil.dateFormat( + DateFormatUtils.dateFormat( hasStat ? item.ctime! ~/ 1000 : item.ctime!, ), style: TextStyle( diff --git a/lib/pages/member_cheese/widgets/item.dart b/lib/pages/member_cheese/widgets/item.dart index 24796ee37..3408f8463 100644 --- a/lib/pages/member_cheese/widgets/item.dart +++ b/lib/pages/member_cheese/widgets/item.dart @@ -4,7 +4,7 @@ import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/space/space_cheese/item.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -43,7 +43,7 @@ class MemberCheeseItem extends StatelessWidget { if (item.ctime != null) ...[ const Spacer(), Text( - '收藏于${DateUtil.dateFormat(int.parse(item.ctime!))}', + '收藏于${DateFormatUtils.dateFormat(int.parse(item.ctime!))}', style: TextStyle( fontSize: 12, color: theme.colorScheme.outline, diff --git a/lib/pages/member_coin_arc/widgets/item.dart b/lib/pages/member_coin_arc/widgets/item.dart index 4de158eb8..82ee3b2bb 100644 --- a/lib/pages/member_coin_arc/widgets/item.dart +++ b/lib/pages/member_coin_arc/widgets/item.dart @@ -8,8 +8,8 @@ import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/member/coin_like_arc/item.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -86,7 +86,7 @@ class MemberCoinLikeItem extends StatelessWidget { bottom: 6, right: 6, type: PBadgeType.gray, - text: DurationUtil.formatDuration(item.duration), + text: DurationUtils.formatDuration(item.duration), ), ], ); @@ -118,7 +118,7 @@ class MemberCoinLikeItem extends StatelessWidget { ), const Spacer(), Text( - DateUtil.dateFormat( + DateFormatUtils.dateFormat( item.ctime, short: VideoCardV.shortFormat, long: VideoCardV.longFormat, diff --git a/lib/pages/member_favorite/widget/item.dart b/lib/pages/member_favorite/widget/item.dart index 6bc55cd7a..4b8dc8de6 100644 --- a/lib/pages/member_favorite/widget/item.dart +++ b/lib/pages/member_favorite/widget/item.dart @@ -4,8 +4,8 @@ import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/space/space_fav/list.dart'; import 'package:PiliPlus/pages/subscription_detail/view.dart'; -import 'package:PiliPlus/utils/fav_util.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/fav_utils.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -92,11 +92,11 @@ class MemberFavItem extends StatelessWidget { const Spacer(), Text( item.type == 0 - ? '${item.mediaCount}个内容 · ${FavUtil.isPublicFavText(item.attr)}' + ? '${item.mediaCount}个内容 · ${FavUtils.isPublicFavText(item.attr)}' : item.type == 11 ? '${item.mediaCount}个内容 · ${item.upper?.name}' : item.type == 21 - ? '创建者: ${item.upper?.name}\n${item.mediaCount}个视频 · ${NumUtil.numFormat(item.viewCount)}播放' + ? '创建者: ${item.upper?.name}\n${item.mediaCount}个视频 · ${NumUtils.numFormat(item.viewCount)}播放' : '${item.mediaCount}个内容', style: TextStyle( fontSize: 12, diff --git a/lib/pages/member_home/widgets/video_card_v_member_home.dart b/lib/pages/member_home/widgets/video_card_v_member_home.dart index a5f077038..b71f4182d 100644 --- a/lib/pages/member_home/widgets/video_card_v_member_home.dart +++ b/lib/pages/member_home/widgets/video_card_v_member_home.dart @@ -6,7 +6,7 @@ import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models_new/space/space_archive/item.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -96,7 +96,9 @@ class VideoCardVMemberHome extends StatelessWidget { right: 7, size: PBadgeSize.small, type: PBadgeType.gray, - text: DurationUtil.formatDuration(videoItem.duration), + text: DurationUtils.formatDuration( + videoItem.duration, + ), ), if (videoItem.badges?.isNotEmpty == true) PBadge( diff --git a/lib/pages/member_profile/view.dart b/lib/pages/member_profile/view.dart index 4d2939c50..2d2c3569e 100644 --- a/lib/pages/member_profile/view.dart +++ b/lib/pages/member_profile/view.dart @@ -10,9 +10,9 @@ import 'package:PiliPlus/pages/mine/controller.dart'; import 'package:PiliPlus/services/account_service.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/app_sign.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; @@ -141,7 +141,7 @@ class _EditProfilePageState extends State { child: CachedNetworkImage( width: 55, height: 55, - imageUrl: ImageUtil.thumbnailUrl(response.face), + imageUrl: ImageUtils.thumbnailUrl(response.face), ), ), ), @@ -195,7 +195,7 @@ class _EditProfilePageState extends State { if (res != null) { _update( type: ProfileType.birthday, - datum: DateUtil.longFormat.format(res), + datum: DateFormatUtils.longFormat.format(res), ); } }), diff --git a/lib/pages/member_season_series/widget/season_series_card.dart b/lib/pages/member_season_series/widget/season_series_card.dart index 10389ce47..db9a81486 100644 --- a/lib/pages/member_season_series/widget/season_series_card.dart +++ b/lib/pages/member_season_series/widget/season_series_card.dart @@ -3,7 +3,7 @@ import 'package:PiliPlus/common/widgets/badge.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/space/space_season_series/season.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:flutter/material.dart'; class SeasonSeriesCard extends StatelessWidget { @@ -86,7 +86,7 @@ class SeasonSeriesCard extends StatelessWidget { ), const Spacer(), Text( - DateUtil.dateFormat(item.meta!.ptime), + DateFormatUtils.dateFormat(item.meta!.ptime), maxLines: 1, style: TextStyle( fontSize: 12, diff --git a/lib/pages/member_video/widgets/video_card_h_member_video.dart b/lib/pages/member_video/widgets/video_card_h_member_video.dart index 8969023e2..c403d4043 100644 --- a/lib/pages/member_video/widgets/video_card_h_member_video.dart +++ b/lib/pages/member_video/widgets/video_card_h_member_video.dart @@ -8,8 +8,8 @@ import 'package:PiliPlus/common/widgets/video_popup_menu.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/space/space_archive/item.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -156,16 +156,17 @@ class VideoCardHMemberVideo extends StatelessWidget { .history! .duration ? '已看完' - : '${DurationUtil.formatDuration(videoItem.history!.progress)}/${DurationUtil.formatDuration(videoItem.history!.duration)}', + : '${DurationUtils.formatDuration(videoItem.history!.progress)}/${DurationUtils.formatDuration(videoItem.history!.duration)}', right: 6.0, bottom: 6.0, type: PBadgeType.gray, ); } catch (_) { return PBadge( - text: DurationUtil.formatDuration( - videoItem.duration, - ), + text: + DurationUtils.formatDuration( + videoItem.duration, + ), right: 6.0, bottom: 6.0, type: PBadgeType.gray, @@ -175,7 +176,7 @@ class VideoCardHMemberVideo extends StatelessWidget { ), ] else if (videoItem.duration > 0) PBadge( - text: DurationUtil.formatDuration( + text: DurationUtils.formatDuration( videoItem.duration, ), right: 6.0, @@ -234,7 +235,7 @@ class VideoCardHMemberVideo extends StatelessWidget { ), Text( videoItem.season != null - ? DateUtil.dateFormat(videoItem.season!.mtime) + ? DateFormatUtils.dateFormat(videoItem.season!.mtime) : videoItem.publishTimeText ?? '', maxLines: 1, style: TextStyle( diff --git a/lib/pages/mine/widgets/item.dart b/lib/pages/mine/widgets/item.dart index fce2a600c..b3b318f2c 100644 --- a/lib/pages/mine/widgets/item.dart +++ b/lib/pages/mine/widgets/item.dart @@ -1,6 +1,6 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models_new/fav/fav_folder/list.dart'; -import 'package:PiliPlus/utils/fav_util.dart'; +import 'package:PiliPlus/utils/fav_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -66,7 +66,7 @@ class FavFolderItem extends StatelessWidget { maxLines: 1, ), Text( - ' 共${item.mediaCount}条视频 · ${FavUtil.isPublicFavText(item.attr)}', + ' 共${item.mediaCount}条视频 · ${FavUtils.isPublicFavText(item.attr)}', style: theme.textTheme.labelSmall!.copyWith( color: theme.colorScheme.outline, ), diff --git a/lib/pages/msg_feed_top/at_me/view.dart b/lib/pages/msg_feed_top/at_me/view.dart index e5e63362f..04295a36d 100644 --- a/lib/pages/msg_feed_top/at_me/view.dart +++ b/lib/pages/msg_feed_top/at_me/view.dart @@ -11,7 +11,7 @@ import 'package:PiliPlus/models_new/msg/msg_at/item.dart'; import 'package:PiliPlus/pages/msg_feed_top/at_me/controller.dart'; import 'package:PiliPlus/pages/whisper_settings/view.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -149,7 +149,7 @@ class _AtMePageState extends State { ], const SizedBox(height: 4), Text( - DateUtil.dateFormat(item.atTime), + DateFormatUtils.dateFormat(item.atTime), style: theme.textTheme.bodyMedium!.copyWith( fontSize: 13, color: theme.colorScheme.outline, diff --git a/lib/pages/msg_feed_top/like_detail/view.dart b/lib/pages/msg_feed_top/like_detail/view.dart index a3e3c6c21..1210612f7 100644 --- a/lib/pages/msg_feed_top/like_detail/view.dart +++ b/lib/pages/msg_feed_top/like_detail/view.dart @@ -8,7 +8,7 @@ import 'package:PiliPlus/models_new/msg/msg_like_detail/card.dart'; import 'package:PiliPlus/models_new/msg/msg_like_detail/item.dart'; import 'package:PiliPlus/pages/msg_feed_top/like_detail/controller.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -141,7 +141,7 @@ class _LikeDetailPageState extends State { overflow: TextOverflow.ellipsis, ), subtitle: Text( - DateUtil.dateFormat(item.likeTime), + DateFormatUtils.dateFormat(item.likeTime), style: theme.textTheme.bodyMedium!.copyWith( fontSize: 13, color: theme.colorScheme.outline, diff --git a/lib/pages/msg_feed_top/like_me/view.dart b/lib/pages/msg_feed_top/like_me/view.dart index ba0ee9a77..2e469afd1 100644 --- a/lib/pages/msg_feed_top/like_me/view.dart +++ b/lib/pages/msg_feed_top/like_me/view.dart @@ -12,7 +12,7 @@ import 'package:PiliPlus/models_new/msg/msg_like/item.dart'; import 'package:PiliPlus/pages/msg_feed_top/like_me/controller.dart'; import 'package:PiliPlus/pages/whisper_settings/view.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -312,7 +312,7 @@ class _LikeMePageState extends State { ], const SizedBox(height: 4), Text( - DateUtil.dateFormat(item.likeTime), + DateFormatUtils.dateFormat(item.likeTime), style: theme.textTheme.bodyMedium!.copyWith( fontSize: 13, color: theme.colorScheme.outline, diff --git a/lib/pages/msg_feed_top/reply_me/view.dart b/lib/pages/msg_feed_top/reply_me/view.dart index dc618b6c8..5aa325750 100644 --- a/lib/pages/msg_feed_top/reply_me/view.dart +++ b/lib/pages/msg_feed_top/reply_me/view.dart @@ -11,7 +11,7 @@ import 'package:PiliPlus/models_new/msg/msg_reply/item.dart'; import 'package:PiliPlus/pages/msg_feed_top/reply_me/controller.dart'; import 'package:PiliPlus/pages/whisper_settings/view.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -179,7 +179,7 @@ class _ReplyMePageState extends State { ), ), Text( - DateUtil.dateFormat(item.replyTime), + DateFormatUtils.dateFormat(item.replyTime), style: theme.textTheme.bodyMedium!.copyWith( fontSize: 13, color: theme.colorScheme.outline, diff --git a/lib/pages/music/view.dart b/lib/pages/music/view.dart index 5b5ad3ef7..614e02364 100644 --- a/lib/pages/music/view.dart +++ b/lib/pages/music/view.dart @@ -15,10 +15,10 @@ import 'package:PiliPlus/pages/common/dyn/common_dyn_page.dart'; import 'package:PiliPlus/pages/music/controller.dart'; import 'package:PiliPlus/pages/music/video/view.dart'; import 'package:PiliPlus/utils/accounts.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:fl_chart/fl_chart.dart'; @@ -224,7 +224,7 @@ class _MusicDetailPageState extends CommonDynPageState { foregroundColor: outline, ), label: Text( - count != null ? NumUtil.numFormat(count) : text, + count != null ? NumUtils.numFormat(count) : text, style: TextStyle(color: color), ), ); @@ -385,7 +385,7 @@ class _MusicDetailPageState extends CommonDynPageState { final child = Column( mainAxisSize: MainAxisSize.min, children: [ - Text(NumUtil.numFormat(rank)), + Text(NumUtils.numFormat(rank)), Text( name, style: theme.textTheme.bodySmall!.copyWith(color: outline), @@ -625,7 +625,7 @@ class _MusicDetailPageState extends CommonDynPageState { space: 8 * sqrt2, meta: meta, child: Text( - DateUtil.shortFormat.format( + DateFormatUtils.shortFormat.format( DateTime.fromMillisecondsSinceEpoch( heat[index.toInt()].date * 1000, ), diff --git a/lib/pages/music/widget/music_video_card_h.dart b/lib/pages/music/widget/music_video_card_h.dart index 376b70b1d..f3ab4b0bd 100644 --- a/lib/pages/music/widget/music_video_card_h.dart +++ b/lib/pages/music/widget/music_video_card_h.dart @@ -8,7 +8,7 @@ import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/music/bgm_recommend_list.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -65,7 +65,9 @@ class MusicVideoCardH extends StatelessWidget { height: maxHeight, ), PBadge( - text: DurationUtil.formatDuration(videoItem.duration), + text: DurationUtils.formatDuration( + videoItem.duration, + ), right: 6.0, bottom: 6.0, type: PBadgeType.gray, diff --git a/lib/pages/pgc_review/child/view.dart b/lib/pages/pgc_review/child/view.dart index 053ce55f1..d4ea42a81 100644 --- a/lib/pages/pgc_review/child/view.dart +++ b/lib/pages/pgc_review/child/view.dart @@ -13,7 +13,7 @@ import 'package:PiliPlus/pages/pgc_review/child/controller.dart'; import 'package:PiliPlus/pages/pgc_review/post/view.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; @@ -351,7 +351,7 @@ class _PgcReviewChildPageState extends State color: isLike ? primary : color, ), Text( - NumUtil.numFormat(item.stat?.likes ?? 0), + NumUtils.numFormat(item.stat?.likes ?? 0), style: TextStyle( color: isLike ? primary : color, fontSize: 12, @@ -390,7 +390,7 @@ class _PgcReviewChildPageState extends State return count == null ? const SizedBox.shrink() : Text( - '${NumUtil.numFormat(count)}条点评', + '${NumUtils.numFormat(count)}条点评', style: const TextStyle(fontSize: 13), ); }, diff --git a/lib/pages/save_panel/view.dart b/lib/pages/save_panel/view.dart index 42a944159..d5d843b38 100644 --- a/lib/pages/save_panel/view.dart +++ b/lib/pages/save_panel/view.dart @@ -13,8 +13,8 @@ import 'package:PiliPlus/pages/video/introduction/pgc/controller.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart'; import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPlus/utils/context_ext.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/foundation.dart' show kDebugMode; import 'package:flutter/material.dart'; @@ -23,7 +23,6 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart' hide ContextExtensionss; import 'package:intl/intl.dart' show DateFormat; import 'package:pretty_qr_code/pretty_qr_code.dart'; -import 'package:saver_gallery/saver_gallery.dart'; import 'package:share_plus/share_plus.dart'; class SavePanel extends StatefulWidget { @@ -79,7 +78,7 @@ class _SavePanelState extends State { _CoverType coverType = _CoverType.def16_9; String? title; int? pubdate; - DateFormat dateFormat = DateUtil.longFormatDs; + DateFormat dateFormat = DateFormatUtils.longFormatDs; String? uname; String uri = ''; @@ -193,7 +192,7 @@ class _SavePanelState extends State { )?.millisecondsSinceEpoch; if (time != null) { pubdate = time ~/ 1000; - dateFormat = DateUtil.longFormat; + dateFormat = DateFormatUtils.longFormat; } } } @@ -273,7 +272,7 @@ class _SavePanelState extends State { Future _onSaveOrSharePic([bool isShare = false]) async { if (!isShare) { - if (mounted && !await ImageUtil.checkPermissionDependOnSdkInt(context)) { + if (mounted && !await ImageUtils.checkPermissionDependOnSdkInt(context)) { return; } } @@ -303,18 +302,14 @@ class _SavePanelState extends State { ), ); } else { - final result = await SaverGallery.saveImage( - pngBytes, - fileName: '$picName.png', - androidRelativePath: "Pictures/PiliPlus", - skipIfExists: false, + final result = await ImageUtils.saveByteImg( + bytes: pngBytes, + fileName: picName, ); - SmartDialog.dismiss(); - if (result.isSuccess) { - Get.back(); - SmartDialog.showToast('保存成功'); - } else if (result.errorMessage?.isNotEmpty == true) { - SmartDialog.showToast(result.errorMessage!); + if (result != null) { + if (result.isSuccess) { + Get.back(); + } } } } catch (e) { @@ -420,7 +415,7 @@ class _SavePanelState extends State { if (pubdate != null) ...[ const Spacer(), Text( - DateUtil.format( + DateFormatUtils.format( pubdate, format: dateFormat, ), @@ -473,7 +468,7 @@ class _SavePanelState extends State { ), ), Text( - DateUtil.longFormatDs + DateFormatUtils.longFormatDs .format( DateTime.now(), ), diff --git a/lib/pages/search/widgets/hot_keyword.dart b/lib/pages/search/widgets/hot_keyword.dart index 56c6f9185..86a46dc1c 100644 --- a/lib/pages/search/widgets/hot_keyword.dart +++ b/lib/pages/search/widgets/hot_keyword.dart @@ -1,6 +1,6 @@ import 'package:PiliPlus/models_new/search/search_trending/list.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; @@ -55,7 +55,7 @@ class HotKeyword extends StatelessWidget { Padding( padding: const EdgeInsets.only(left: 4), child: CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(i.icon!), + imageUrl: ImageUtils.thumbnailUrl(i.icon!), height: 15, ), ) diff --git a/lib/pages/search_panel/article/widgets/item.dart b/lib/pages/search_panel/article/widgets/item.dart index dbadcfdfc..471e6df8b 100644 --- a/lib/pages/search_panel/article/widgets/item.dart +++ b/lib/pages/search_panel/article/widgets/item.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/search/result.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -80,7 +80,7 @@ class SearchArticleItem extends StatelessWidget { ), const Spacer(), Text( - DateUtil.dateFormat(item.pubTime), + DateFormatUtils.dateFormat(item.pubTime), style: textStyle, ), Row( diff --git a/lib/pages/search_panel/pgc/widgets/item.dart b/lib/pages/search_panel/pgc/widgets/item.dart index cc7fab003..a8ceb4cb4 100644 --- a/lib/pages/search_panel/pgc/widgets/item.dart +++ b/lib/pages/search_panel/pgc/widgets/item.dart @@ -3,7 +3,7 @@ import 'package:PiliPlus/common/widgets/badge.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/search/result.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -84,7 +84,7 @@ class SearchPgcItem extends StatelessWidget { const Text('·'), const SizedBox(width: 3), Text( - DateUtil.dateFormat(item.pubtime), + DateFormatUtils.dateFormat(item.pubtime), style: style, ), ], diff --git a/lib/pages/search_panel/user/widgets/item.dart b/lib/pages/search_panel/user/widgets/item.dart index 68df91cd4..ce1d530e9 100644 --- a/lib/pages/search_panel/user/widgets/item.dart +++ b/lib/pages/search_panel/user/widgets/item.dart @@ -1,6 +1,6 @@ import 'package:PiliPlus/common/widgets/pendant_avatar.dart'; import 'package:PiliPlus/models/search/result.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -56,7 +56,7 @@ class SearchUserItem extends StatelessWidget { ], ), Text( - '粉丝:${NumUtil.numFormat(item.fans)} 视频:${NumUtil.numFormat(item.videos)}', + '粉丝:${NumUtils.numFormat(item.fans)} 视频:${NumUtils.numFormat(item.videos)}', style: style, ), if (item.officialVerify?.desc?.isNotEmpty == true) diff --git a/lib/pages/search_panel/video/controller.dart b/lib/pages/search_panel/video/controller.dart index c422205ff..c72d8181d 100644 --- a/lib/pages/search_panel/video/controller.dart +++ b/lib/pages/search_panel/video/controller.dart @@ -8,7 +8,7 @@ import 'package:PiliPlus/pages/search/widgets/search_text.dart'; import 'package:PiliPlus/pages/search_panel/controller.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; import 'package:PiliPlus/utils/context_ext.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -98,7 +98,7 @@ class SearchVideoController pubTimeType == null && (isFirst ? customPubBeginDate : customPubEndDate); return SearchText( - text: DateUtil.longFormat.format( + text: DateFormatUtils.longFormat.format( isFirst ? pubBeginDate : pubEndDate, ), textAlign: TextAlign.center, diff --git a/lib/pages/search_trending/view.dart b/lib/pages/search_trending/view.dart index 13e9e4380..ca8e1cbe0 100644 --- a/lib/pages/search_trending/view.dart +++ b/lib/pages/search_trending/view.dart @@ -9,7 +9,7 @@ import 'package:PiliPlus/models_new/search/search_trending/list.dart'; import 'package:PiliPlus/pages/search_trending/controller.dart'; import 'package:PiliPlus/utils/context_ext.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart' hide ListTile; @@ -203,7 +203,7 @@ class _SearchTrendingPageState extends State { if (item.icon?.isNotEmpty == true) ...[ const SizedBox(width: 4), CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(item.icon!), + imageUrl: ImageUtils.thumbnailUrl(item.icon!), height: 16, ), ] else if (item.showLiveIcon == true) ...[ diff --git a/lib/pages/setting/models/extra_settings.dart b/lib/pages/setting/models/extra_settings.dart index 1077a469b..a876ad84b 100644 --- a/lib/pages/setting/models/extra_settings.dart +++ b/lib/pages/setting/models/extra_settings.dart @@ -25,7 +25,7 @@ import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/cache_manage.dart'; import 'package:PiliPlus/utils/feed_back.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; @@ -739,7 +739,7 @@ List get extraSettings => [ leading: const Icon(Icons.download_for_offline_outlined), setKey: SettingBoxKey.silentDownImg, defaultVal: false, - onChanged: (value) => ImageUtil.silentDownImg = value, + onChanged: (value) => ImageUtils.silentDownImg = value, ), SettingsModel( settingsType: SettingsType.sw1tch, @@ -961,7 +961,7 @@ List get extraSettings => [ settingsType: SettingsType.normal, title: '动态展示', setKey: SettingBoxKey.defaultDynamicType, - leading: const Icon(Icons.dynamic_feed_outlined), + leading: const Icon(Icons.dynamic_feed_rounded), getSubtitle: () => '当前优先展示「${DynamicsTabType.values[Pref.defaultDynamicType].label}」', onTap: (setState) async { @@ -1162,7 +1162,7 @@ List get extraSettings => [ settingsType: SettingsType.sw1tch, title: '检查更新', subtitle: '每次启动时检查是否需要更新', - leading: const Icon(Icons.system_update_alt_outlined), + leading: const Icon(Icons.system_update_alt), setKey: SettingBoxKey.autoUpdate, defaultVal: true, onChanged: (val) { diff --git a/lib/pages/setting/models/play_settings.dart b/lib/pages/setting/models/play_settings.dart index 556258e1f..be087727f 100644 --- a/lib/pages/setting/models/play_settings.dart +++ b/lib/pages/setting/models/play_settings.dart @@ -13,6 +13,7 @@ import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -194,7 +195,7 @@ List get playSettings => [ setKey: SettingBoxKey.autoPiP, defaultVal: false, onChanged: (val) { - if (val && !videoPlayerServiceHandler.enableBackgroundPlay) { + if (val && !videoPlayerServiceHandler!.enableBackgroundPlay) { SmartDialog.showToast('建议开启后台音频服务'); } }, @@ -212,7 +213,7 @@ List get playSettings => [ settingsType: SettingsType.sw1tch, title: '全屏手势反向', subtitle: '默认播放器中部向上滑动进入全屏,向下退出\n开启后向下全屏,向上退出', - leading: Icon(Icons.swap_vert_outlined), + leading: Icon(Icons.swap_vert), setKey: SettingBoxKey.fullScreenGestureReverse, defaultVal: false, ), @@ -281,17 +282,18 @@ List get playSettings => [ } }, ), - SettingsModel( - settingsType: SettingsType.sw1tch, - title: '后台音频服务', - subtitle: '避免画中画没有播放暂停功能', - leading: const Icon(Icons.volume_up_outlined), - setKey: SettingBoxKey.enableBackgroundPlay, - defaultVal: true, - onChanged: (value) { - videoPlayerServiceHandler.enableBackgroundPlay = value; - }, - ), + if (Utils.isMobile) + SettingsModel( + settingsType: SettingsType.sw1tch, + title: '后台音频服务', + subtitle: '避免画中画没有播放暂停功能', + leading: const Icon(Icons.volume_up_outlined), + setKey: SettingBoxKey.enableBackgroundPlay, + defaultVal: true, + onChanged: (value) { + videoPlayerServiceHandler!.enableBackgroundPlay = value; + }, + ), const SettingsModel( settingsType: SettingsType.sw1tch, title: '播放器设置仅对当前生效', diff --git a/lib/pages/subscription_detail/view.dart b/lib/pages/subscription_detail/view.dart index c03206e9f..3eaf6317e 100644 --- a/lib/pages/subscription_detail/view.dart +++ b/lib/pages/subscription_detail/view.dart @@ -7,7 +7,7 @@ import 'package:PiliPlus/models_new/sub/sub_detail/media.dart'; import 'package:PiliPlus/pages/subscription_detail/controller.dart'; import 'package:PiliPlus/pages/subscription_detail/widget/sub_video_card.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -192,7 +192,7 @@ class _SubDetailPageState extends State with GridMixin { Text('共${info.mediaCount}条视频', style: style), const SizedBox(height: 4), Text( - '${NumUtil.numFormat(info.viewCount ?? info.cntInfo?.play)}次播放', + '${NumUtils.numFormat(info.viewCount ?? info.cntInfo?.play)}次播放', style: style, ), ], diff --git a/lib/pages/subscription_detail/widget/sub_video_card.dart b/lib/pages/subscription_detail/widget/sub_video_card.dart index 62f0d428c..ab3ac06c0 100644 --- a/lib/pages/subscription_detail/widget/sub_video_card.dart +++ b/lib/pages/subscription_detail/widget/sub_video_card.dart @@ -7,8 +7,8 @@ import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/sub/sub_detail/media.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -67,7 +67,9 @@ class SubVideoCardH extends StatelessWidget { height: maxHeight, ), PBadge( - text: DurationUtil.formatDuration(videoItem.duration), + text: DurationUtils.formatDuration( + videoItem.duration, + ), right: 6.0, bottom: 6.0, type: PBadgeType.gray, @@ -103,7 +105,7 @@ class SubVideoCardH extends StatelessWidget { ), ), Text( - DateUtil.dateFormat(videoItem.pubtime), + DateFormatUtils.dateFormat(videoItem.pubtime), style: TextStyle( fontSize: 12, color: Theme.of(context).colorScheme.outline, diff --git a/lib/pages/video/ai_conclusion/view.dart b/lib/pages/video/ai_conclusion/view.dart index 1363ac589..999681957 100644 --- a/lib/pages/video/ai_conclusion/view.dart +++ b/lib/pages/video/ai_conclusion/view.dart @@ -1,7 +1,7 @@ import 'package:PiliPlus/models_new/video/video_ai_conclusion/model_result.dart'; import 'package:PiliPlus/pages/common/slide/common_collapse_slide_page.dart'; import 'package:PiliPlus/pages/video/controller.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -122,7 +122,7 @@ class _AiDetailState extends CommonCollapseSlidePageState { ), children: [ TextSpan( - text: DurationUtil.formatDuration( + text: DurationUtils.formatDuration( item.timestamp, ), style: TextStyle( diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index ebda35535..74af3f980 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -43,7 +43,7 @@ import 'package:PiliPlus/plugin/pl_player/models/data_source.dart'; import 'package:PiliPlus/plugin/pl_player/models/heart_beat_type.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_status.dart'; import 'package:PiliPlus/utils/accounts.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; @@ -143,10 +143,10 @@ class VideoDetailController extends GetxController ..addListener(scrollListener); late bool isExpanding = false; late bool isCollapsing = false; - AnimationController? _animationController; + AnimationController? animController; AnimationController get animationController => - _animationController ??= AnimationController( + animController ??= AnimationController( vsync: this, duration: const Duration(milliseconds: 200), ); @@ -612,7 +612,7 @@ class VideoDetailController extends GetxController ), contentPadding: const EdgeInsets.only(left: 16, right: 8), subtitle: Text( - '${DurationUtil.formatDuration(item.segment.first / 1000)} 至 ${DurationUtil.formatDuration(item.segment.second / 1000)}', + '${DurationUtils.formatDuration(item.segment.first / 1000)} 至 ${DurationUtils.formatDuration(item.segment.second / 1000)}', style: const TextStyle(fontSize: 13), ), trailing: Row( @@ -1511,6 +1511,7 @@ class VideoDetailController extends GetxController if (idx == 0) { if (preference == SubtitlePrefType.on || (preference == SubtitlePrefType.auto && + Utils.isMobile && (await FlutterVolumeController.getVolume() ?? 0) <= 0)) { idx = 1; } @@ -1563,7 +1564,7 @@ class VideoDetailController extends GetxController scrollCtr ..removeListener(scrollListener) ..dispose(); - _animationController?.dispose(); + animController?.dispose(); super.onClose(); } diff --git a/lib/pages/video/introduction/pgc/controller.dart b/lib/pages/video/introduction/pgc/controller.dart index 9b94d6f91..77d5dd40a 100644 --- a/lib/pages/video/introduction/pgc/controller.dart +++ b/lib/pages/video/introduction/pgc/controller.dart @@ -483,7 +483,7 @@ class PgcIntroController extends CommonIntroController { videoDetail ..value.title = episode.showTitle ..refresh(); - videoPlayerServiceHandler.onVideoDetailChange( + videoPlayerServiceHandler?.onVideoDetailChange( episode, cid.value, heroTag, diff --git a/lib/pages/video/introduction/pgc/view.dart b/lib/pages/video/introduction/pgc/view.dart index bb4aa1fcf..64d87fe70 100644 --- a/lib/pages/video/introduction/pgc/view.dart +++ b/lib/pages/video/introduction/pgc/view.dart @@ -15,7 +15,7 @@ import 'package:PiliPlus/pages/video/introduction/pgc/controller.dart'; import 'package:PiliPlus/pages/video/introduction/pgc/widgets/pgc_panel.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_item.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/widgets/triple_state.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -418,7 +418,7 @@ class _PgcIntroPageState extends TripleState selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), selectStatus: introController.hasLike.value, semanticsLabel: '点赞', - text: NumUtil.numFormat(item.stat!.like), + text: NumUtils.numFormat(item.stat!.like), onStartTriple: onStartTriple, onCancelTriple: onCancelTriple, ), @@ -431,7 +431,7 @@ class _PgcIntroPageState extends TripleState onTap: introController.actionCoinVideo, selectStatus: introController.hasCoin, semanticsLabel: '投币', - text: NumUtil.numFormat(item.stat!.coin), + text: NumUtils.numFormat(item.stat!.coin), ), ), Obx( @@ -446,7 +446,7 @@ class _PgcIntroPageState extends TripleState ), selectStatus: introController.hasFav.value, semanticsLabel: '收藏', - text: NumUtil.numFormat(item.stat!.favorite), + text: NumUtils.numFormat(item.stat!.favorite), ), ), Obx( @@ -465,7 +465,7 @@ class _PgcIntroPageState extends TripleState onTap: () => introController.actionShareVideo(context), selectStatus: false, semanticsLabel: '转发', - text: NumUtil.numFormat(item.stat!.share), + text: NumUtils.numFormat(item.stat!.share), ), ], ), diff --git a/lib/pages/video/introduction/ugc/controller.dart b/lib/pages/video/introduction/ugc/controller.dart index 5a8e289aa..a29514ef8 100644 --- a/lib/pages/video/introduction/ugc/controller.dart +++ b/lib/pages/video/introduction/ugc/controller.dart @@ -92,7 +92,7 @@ class UgcIntroController extends CommonIntroController with ReloadMixin { var res = await VideoHttp.videoIntro(bvid: bvid); if (res.isSuccess) { VideoDetailData data = res.data; - videoPlayerServiceHandler.onVideoDetailChange(data, cid.value, heroTag); + videoPlayerServiceHandler?.onVideoDetailChange(data, cid.value, heroTag); if (videoDetail.value.ugcSeason?.id == data.ugcSeason?.id) { // keep reversed season data.ugcSeason = videoDetail.value.ugcSeason; @@ -532,7 +532,7 @@ class UgcIntroController extends CommonIntroController with ReloadMixin { } else { if (episode is Part) { final videoDetail = this.videoDetail.value; - videoPlayerServiceHandler.onVideoDetailChange( + videoPlayerServiceHandler?.onVideoDetailChange( episode, cid, heroTag, diff --git a/lib/pages/video/introduction/ugc/view.dart b/lib/pages/video/introduction/ugc/view.dart index 984d03687..d972bcf74 100644 --- a/lib/pages/video/introduction/ugc/view.dart +++ b/lib/pages/video/introduction/ugc/view.dart @@ -17,11 +17,11 @@ import 'package:PiliPlus/pages/video/introduction/ugc/widgets/page.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/widgets/season.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/widgets/triple_state.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/id_utils.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/request_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -517,7 +517,7 @@ class _UgcIntroPanelState extends TripleState selectStatus: introController.hasLike.value, semanticsLabel: '点赞', text: !isLoading - ? NumUtil.numFormat(videoDetail.stat!.like) + ? NumUtils.numFormat(videoDetail.stat!.like) : null, onStartTriple: onStartTriple, onCancelTriple: onCancelTriple, @@ -544,7 +544,7 @@ class _UgcIntroPanelState extends TripleState selectStatus: introController.hasCoin, semanticsLabel: '投币', text: !isLoading - ? NumUtil.numFormat(videoDetail.stat!.coin) + ? NumUtils.numFormat(videoDetail.stat!.coin) : null, ), ), @@ -561,7 +561,7 @@ class _UgcIntroPanelState extends TripleState selectStatus: introController.hasFav.value, semanticsLabel: '收藏', text: !isLoading - ? NumUtil.numFormat(videoDetail.stat!.favorite) + ? NumUtils.numFormat(videoDetail.stat!.favorite) : null, ), ), @@ -582,7 +582,7 @@ class _UgcIntroPanelState extends TripleState selectStatus: false, semanticsLabel: '分享', text: !isLoading - ? NumUtil.numFormat(videoDetail.stat!.share!) + ? NumUtils.numFormat(videoDetail.stat!.share!) : null, ), ], @@ -835,7 +835,7 @@ class _UgcIntroPanelState extends TripleState ), const SizedBox(height: 0), Text( - '${NumUtil.numFormat(userStat.follower)}粉丝 ${'${NumUtil.numFormat(userStat.archiveCount)}视频'}', + '${NumUtils.numFormat(userStat.follower)}粉丝 ${'${NumUtils.numFormat(userStat.archiveCount)}视频'}', style: TextStyle( fontSize: 12, color: theme.colorScheme.outline, @@ -863,7 +863,7 @@ class _UgcIntroPanelState extends TripleState color: theme.colorScheme.outline, ), Text( - DateUtil.format(videoDetail.pubdate), + DateFormatUtils.format(videoDetail.pubdate), style: TextStyle( fontSize: 12, color: theme.colorScheme.outline, diff --git a/lib/pages/video/medialist/view.dart b/lib/pages/video/medialist/view.dart index 7c9de88d3..b31867a3b 100644 --- a/lib/pages/video/medialist/view.dart +++ b/lib/pages/video/medialist/view.dart @@ -10,7 +10,7 @@ import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/media_list/media_list.dart'; import 'package:PiliPlus/models_new/video/video_detail/episode.dart'; import 'package:PiliPlus/pages/common/slide/common_collapse_slide_page.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:flutter/material.dart' hide RefreshCallback; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -202,7 +202,7 @@ class _MediaListPanelState }, ), PBadge( - text: DurationUtil.formatDuration( + text: DurationUtils.formatDuration( item.duration, ), right: 6.0, diff --git a/lib/pages/video/member/view.dart b/lib/pages/video/member/view.dart index 9e8da659b..64233d794 100644 --- a/lib/pages/video/member/view.dart +++ b/lib/pages/video/member/view.dart @@ -17,7 +17,7 @@ import 'package:PiliPlus/pages/video/member/controller.dart'; import 'package:PiliPlus/services/account_service.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/request_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -265,12 +265,12 @@ class _HorizontalMemberPageState extends State title: const ['粉丝', '关注', '获赞'][index ~/ 2], num: index == 0 ? _controller.userStat['follower'] != null - ? NumUtil.numFormat(_controller.userStat['follower']) + ? NumUtils.numFormat(_controller.userStat['follower']) : '' : index == 2 ? _controller.userStat['following'] ?? '' : _controller.userStat['likes'] != null - ? NumUtil.numFormat(_controller.userStat['likes']) + ? NumUtils.numFormat(_controller.userStat['likes']) : '', onTap: () { if (index == 0) { diff --git a/lib/pages/video/post_panel/view.dart b/lib/pages/video/post_panel/view.dart index 356fa8b74..eb4f0497e 100644 --- a/lib/pages/video/post_panel/view.dart +++ b/lib/pages/video/post_panel/view.dart @@ -14,7 +14,7 @@ import 'package:PiliPlus/pages/common/slide/common_collapse_slide_page.dart'; import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/pages/video/post_panel/popup_menu_text.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:dio/dio.dart'; @@ -62,7 +62,7 @@ class PostPanel extends CommonCollapseSlidePage { }) { Widget segment(bool isFirst) => Builder( builder: (context) { - String value = DurationUtil.formatDuration( + String value = DurationUtils.formatDuration( isFirst ? item.segment.first : item.segment.second, ); return Row( diff --git a/lib/pages/video/reply/widgets/reply_item_grpc.dart b/lib/pages/video/reply/widgets/reply_item_grpc.dart index a17b5d00e..3649d7820 100644 --- a/lib/pages/video/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/reply/widgets/reply_item_grpc.dart @@ -19,11 +19,11 @@ import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/pages/video/reply/widgets/zan_grpc.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/context_ext.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/feed_back.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/url_utils.dart'; @@ -238,11 +238,13 @@ class ReplyItemGrpc extends StatelessWidget { children: [ Text( replyLevel == 0 - ? DateUtil.format( + ? DateFormatUtils.format( replyItem.ctime.toInt(), - format: DateUtil.longFormatDs, + format: DateFormatUtils.longFormatDs, ) - : DateUtil.dateFormat(replyItem.ctime.toInt()), + : DateFormatUtils.dateFormat( + replyItem.ctime.toInt(), + ), style: TextStyle( fontSize: theme.textTheme.labelSmall!.fontSize, color: theme.colorScheme.outline, @@ -616,7 +618,7 @@ class ReplyItemGrpc extends StatelessWidget { if (!isCv && url.hasPrefixIcon()) WidgetSpan( child: CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(url.prefixIcon), + imageUrl: ImageUtils.thumbnailUrl(url.prefixIcon), height: 19, color: theme.colorScheme.primary, placeholder: (context, url) { @@ -727,7 +729,7 @@ class ReplyItemGrpc extends StatelessWidget { tag: getTag?.call() ?? Get.arguments['heroTag'], ); isValid = - DurationUtil.parseDuration(matchStr) * 1000 <= + DurationUtils.parseDuration(matchStr) * 1000 <= ctr.data.timeLength!; } catch (e) { if (kDebugMode) debugPrint('failed to validate: $e'); @@ -748,7 +750,7 @@ class ReplyItemGrpc extends StatelessWidget { tag: Get.arguments['heroTag'], ).plPlayerController.seekTo( Duration( - seconds: DurationUtil.parseDuration(matchStr), + seconds: DurationUtils.parseDuration(matchStr), ), isSeek: false, ); diff --git a/lib/pages/video/reply/widgets/zan_grpc.dart b/lib/pages/video/reply/widgets/zan_grpc.dart index d762f333a..715bea665 100644 --- a/lib/pages/video/reply/widgets/zan_grpc.dart +++ b/lib/pages/video/reply/widgets/zan_grpc.dart @@ -2,7 +2,7 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' show ReplyInfo; import 'package:PiliPlus/http/reply.dart'; import 'package:PiliPlus/utils/feed_back.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:fixnum/fixnum.dart' as $fixnum; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -160,7 +160,7 @@ class ZanButtonGrpc extends StatelessWidget { semanticLabel: isLike ? '已赞' : '点赞', ), Text( - NumUtil.numFormat(replyItem.like.toInt()), + NumUtils.numFormat(replyItem.like.toInt()), style: TextStyle( color: isLike ? primary : outline, fontSize: theme.textTheme.labelSmall!.fontSize, diff --git a/lib/pages/video/reply_new/view.dart b/lib/pages/video/reply_new/view.dart index 6687bc22e..be8c65af1 100644 --- a/lib/pages/video/reply_new/view.dart +++ b/lib/pages/video/reply_new/view.dart @@ -18,7 +18,7 @@ import 'package:PiliPlus/pages/emote/view.dart'; import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/pages/video/reply_search_item/view.dart'; import 'package:PiliPlus/utils/context_ext.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/grid.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -347,7 +347,7 @@ class _ReplyPageState extends CommonRichTextPubPageState { tag: heroTag, ); onInsertText( - ' ${DurationUtil.formatDuration((plPlayerController.playedTime ?? Duration.zero).inSeconds)} ', + ' ${DurationUtils.formatDuration((plPlayerController.playedTime ?? Duration.zero).inSeconds)} ', RichTextType.common, ); } catch (e) { diff --git a/lib/pages/video/reply_reply/view.dart b/lib/pages/video/reply_reply/view.dart index 6a75d0886..a35c9ffff 100644 --- a/lib/pages/video/reply_reply/view.dart +++ b/lib/pages/video/reply_reply/view.dart @@ -8,7 +8,7 @@ import 'package:PiliPlus/pages/common/slide/common_slide_page.dart'; import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPlus/pages/video/reply_reply/controller.dart'; import 'package:PiliPlus/utils/context_ext.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -248,7 +248,7 @@ class _VideoReplyReplyPanelState final count = _controller.count.value; return count != -1 ? Text( - '相关回复共${NumUtil.numFormat(count)}条', + '相关回复共${NumUtils.numFormat(count)}条', style: const TextStyle(fontSize: 13), ) : const SizedBox.shrink(); diff --git a/lib/pages/video/reply_search_item/child/widgets/item.dart b/lib/pages/video/reply_search_item/child/widgets/item.dart index 8d6764c7d..758f7c4ec 100644 --- a/lib/pages/video/reply_search_item/child/widgets/item.dart +++ b/lib/pages/video/reply_search_item/child/widgets/item.dart @@ -6,7 +6,7 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' show SearchItem, SearchItemVideoSubType; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/reply/reply_search_type.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -84,7 +84,7 @@ class ReplySearchItem extends StatelessWidget { PBadge( right: 6, bottom: 6, - text: DurationUtil.formatDuration(duration), + text: DurationUtils.formatDuration(duration), type: PBadgeType.gray, ), ], diff --git a/lib/pages/video/send_danmaku/view.dart b/lib/pages/video/send_danmaku/view.dart index 53103d4a0..56d63ed05 100644 --- a/lib/pages/video/send_danmaku/view.dart +++ b/lib/pages/video/send_danmaku/view.dart @@ -329,23 +329,24 @@ class _SendDanmakuPanelState extends CommonTextPubPageState { child: Row( children: [ Obx( - () => iconButton( - context: context, - tooltip: '弹幕样式', - onPressed: () { - updatePanelType( - panelType.value == PanelType.keyboard - ? PanelType.emoji - : PanelType.keyboard, - ); - }, - bgColor: Colors.transparent, - iconSize: 24, - icon: Icons.text_format, - iconColor: panelType.value == PanelType.emoji - ? themeData.colorScheme.primary - : themeData.colorScheme.onSurfaceVariant, - ), + () { + final isEmoji = panelType.value == PanelType.emoji; + return iconButton( + context: context, + tooltip: '弹幕样式', + onPressed: () { + updatePanelType( + isEmoji ? PanelType.keyboard : PanelType.emoji, + ); + }, + bgColor: Colors.transparent, + iconSize: 24, + icon: Icons.text_format, + iconColor: isEmoji + ? themeData.colorScheme.primary + : themeData.colorScheme.onSurfaceVariant, + ); + }, ), const SizedBox(width: 12), Expanded( diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index e76fc713b..966742e5b 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -46,11 +46,12 @@ import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/services/shutdown_timer_service.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; -import 'package:PiliPlus/utils/num_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; +import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:auto_orientation/auto_orientation.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; @@ -63,7 +64,7 @@ import 'package:flutter/services.dart' import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart' hide ContextExtensionss; -import 'package:screen_brightness/screen_brightness.dart'; +import 'package:screen_brightness_platform_interface/screen_brightness_platform_interface.dart'; class VideoDetailPageV extends StatefulWidget { const VideoDetailPageV({super.key}); @@ -159,8 +160,6 @@ class _VideoDetailPageVState extends State }); } - videoDetailController.animationController.addListener(animListener); - WidgetsBinding.instance.addObserver(this); } @@ -327,29 +326,36 @@ class _VideoDetailPageVState extends State @override void dispose() { + plPlayerController + ?..removeStatusLister(playerListener) + ..removePositionListener(positionListener); + videoDetailController ..skipTimer?.cancel() - ..skipTimer = null; + ..skipTimer = null + ..positionSubscription?.cancel() + ..cid.close() + ..animController?.removeListener(animListener); + + Get.delete( + tag: videoDetailController.heroTag, + ); try { - Get.delete( - tag: videoDetailController.heroTag, - ); - videoDetailController.animationController.removeListener(animListener); if (videoDetailController.showReply) { videoDetailController.scrollKey.currentState?.innerController .removeListener(innerScrollListener); } } catch (_) {} - WidgetsBinding.instance.removeObserver(this); if (!Get.previousRoute.startsWith('/video')) { - ScreenBrightness.instance.resetApplicationScreenBrightness(); + if (Utils.isMobile) { + ScreenBrightnessPlatform.instance.resetApplicationScreenBrightness(); + } PlPlayerController.setPlayCallBack(null); } - videoDetailController - ..positionSubscription?.cancel() - ..cid.close(); + + _introScrollController?.dispose(); if (videoDetailController.isUgc) { ugcIntroController ..canelTimer() @@ -362,20 +368,17 @@ class _VideoDetailPageVState extends State } shutdownTimerService.handleWaitingFinished(); if (videoDetailController.plPlayerController.backToHome != true) { - videoPlayerServiceHandler.onVideoDetailDispose(heroTag); + videoPlayerServiceHandler?.onVideoDetailDispose(heroTag); } if (plPlayerController != null) { videoDetailController.makeHeartBeat(); - plPlayerController! - ..removeStatusLister(playerListener) - ..removePositionListener(positionListener) - ..dispose(); + plPlayerController!.dispose(); } else { PlPlayerController.updatePlayCount(); } PageUtils.routeObserver.unsubscribe(this); + WidgetsBinding.instance.removeObserver(this); showStatusBar(); - _introScrollController?.dispose(); super.dispose(); } @@ -388,7 +391,9 @@ class _VideoDetailPageVState extends State WidgetsBinding.instance.removeObserver(this); - ScreenBrightness.instance.resetApplicationScreenBrightness(); + if (Utils.isMobile) { + ScreenBrightnessPlatform.instance.resetApplicationScreenBrightness(); + } videoDetailController.positionSubscription?.cancel(); @@ -430,20 +435,20 @@ class _VideoDetailPageVState extends State introController.startTimer(); - if (mounted) { + if (Utils.isMobile && mounted) { if (videoDetailController.brightness != null) { plPlayerController?.setCurrBrightness( videoDetailController.brightness!, ); if (videoDetailController.brightness != -1.0) { - ScreenBrightness.instance.setApplicationScreenBrightness( + ScreenBrightnessPlatform.instance.setApplicationScreenBrightness( videoDetailController.brightness!, ); } else { - ScreenBrightness.instance.resetApplicationScreenBrightness(); + ScreenBrightnessPlatform.instance.resetApplicationScreenBrightness(); } } else { - ScreenBrightness.instance.resetApplicationScreenBrightness(); + ScreenBrightnessPlatform.instance.resetApplicationScreenBrightness(); } } super.didPopNext(); @@ -558,6 +563,9 @@ class _VideoDetailPageVState extends State } Widget get childWhenDisabled { + videoDetailController.animationController + ..removeListener(animListener) + ..addListener(animListener); if (mounted && isShowing && !isFullScreen) { if (isPortrait) { if (!videoDetailController.imageStatus) { @@ -807,7 +815,7 @@ class _VideoDetailPageVState extends State ); break; case 'savePic': - ImageUtil.downloadImg( + ImageUtils.downloadImg( context, [ videoDetailController @@ -1378,7 +1386,7 @@ class _VideoDetailPageVState extends State videoDetailController.showNoteList(context); break; case 'savePic': - ImageUtil.downloadImg( + ImageUtils.downloadImg( context, [videoDetailController.cover.value], ); @@ -1575,7 +1583,7 @@ class _VideoDetailPageVState extends State return Obx(() { final count = _videoReplyController.count.value; return Tab( - text: '评论${count == -1 ? '' : ' ${NumUtil.numFormat(count)}'}', + text: '评论${count == -1 ? '' : ' ${NumUtils.numFormat(count)}'}', ); }); } else { diff --git a/lib/pages/video/view_point/view.dart b/lib/pages/video/view_point/view.dart index 8490b703b..801db6803 100644 --- a/lib/pages/video/view_point/view.dart +++ b/lib/pages/video/view_point/view.dart @@ -5,7 +5,7 @@ import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart'; import 'package:PiliPlus/pages/common/slide/common_collapse_slide_page.dart'; import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -166,8 +166,8 @@ class _ViewPointsPageState : null, ), Text( - '${segment.from != null ? DurationUtil.formatDuration(segment.from) : ''} - ' - '${segment.to != null ? DurationUtil.formatDuration(segment.to) : ''}', + '${segment.from != null ? DurationUtils.formatDuration(segment.from) : ''} - ' + '${segment.to != null ? DurationUtils.formatDuration(segment.to) : ''}', style: TextStyle(color: theme.colorScheme.outline), ), ], diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index 7063d1e2d..474e2c7e9 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:io'; import 'dart:math'; +import 'dart:typed_data'; import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/custom_icon.dart'; @@ -26,7 +27,7 @@ import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart'; import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/extension.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; @@ -35,7 +36,7 @@ import 'package:PiliPlus/utils/video_utils.dart'; import 'package:canvas_danmaku/canvas_danmaku.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:dio/dio.dart'; -import 'package:document_file_save_plus/document_file_save_plus_platform_interface.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:floating/floating.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -45,7 +46,6 @@ import 'package:hive/hive.dart'; import 'package:intl/intl.dart' show DateFormat; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:media_kit/media_kit.dart'; -import 'package:share_plus/share_plus.dart'; class HeaderControl extends StatefulWidget { const HeaderControl({ @@ -159,7 +159,7 @@ class HeaderControlState extends TripleState { dense: true, onTap: () { Get.back(); - ImageUtil.downloadImg( + ImageUtils.downloadImg( context, [widget.videoDetailCtr.cover.value], ); @@ -893,33 +893,23 @@ class HeaderControlState extends TripleState { options: Options(responseType: ResponseType.bytes), ); if (res.statusCode == 200) { + final Uint8List bytes = res.data; final name = '${introController.videoDetail.value.title}-${videoDetailCtr.bvid}-${videoDetailCtr.cid.value}-${item.lanDoc}.json'; - try { - DocumentFileSavePlusPlatform.instance - .saveMultipleFiles( - dataList: [res.data], - fileNameList: [name], - mimeTypeList: [Headers.jsonContentType], - ); - if (Platform.isAndroid) { - SmartDialog.showToast('已保存'); - } - } catch (e) { - SharePlus.instance.share( - ShareParams( - files: [ - XFile.fromData( - res.data, - name: name, - mimeType: Headers.jsonContentType, - ), - ], - sharePositionOrigin: - await Utils.sharePositionOrigin, - ), - ); + final path = await FilePicker.platform.saveFile( + allowedExtensions: ['json'], + type: FileType.custom, + fileName: name, + bytes: Utils.isDesktop ? null : bytes, + ); + if (path == null) { + SmartDialog.showToast("取消保存"); + return; } + if (Utils.isDesktop) { + await File(path).writeAsBytes(bytes); + } + SmartDialog.showToast("已保存"); } } catch (e) { SmartDialog.showToast(e.toString()); @@ -2083,7 +2073,7 @@ class HeaderControlState extends TripleState { bool canUsePiP = await Floating().isPipAvailable; plPlayerController.hiddenControls(false); if (canUsePiP) { - if (!videoPlayerServiceHandler.enableBackgroundPlay && + if (!videoPlayerServiceHandler!.enableBackgroundPlay && mounted) { final theme = Theme.of(context); ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/pages/webview/view.dart b/lib/pages/webview/view.dart index f745fb434..6d29a21c6 100644 --- a/lib/pages/webview/view.dart +++ b/lib/pages/webview/view.dart @@ -60,6 +60,17 @@ class _WebviewPageState extends State { @override Widget build(BuildContext context) { + if (Platform.isWindows) { + return Scaffold( + appBar: AppBar(), + body: Center( + child: TextButton( + onPressed: () => PageUtils.launchURL(_url), + child: const Text('unsupported'), + ), + ), + ); + } return Scaffold( appBar: widget.url != null ? null diff --git a/lib/pages/whisper/widgets/item.dart b/lib/pages/whisper/widgets/item.dart index abcce5568..c90e692a3 100644 --- a/lib/pages/whisper/widgets/item.dart +++ b/lib/pages/whisper/widgets/item.dart @@ -7,7 +7,7 @@ import 'package:PiliPlus/grpc/bilibili/app/im/v1.pb.dart' show Session, SessionId, SessionPageType, SessionType, UnreadStyle; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/pages/whisper_secondary/view.dart'; -import 'package:PiliPlus/utils/date_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:fixnum/fixnum.dart'; import 'package:flutter/material.dart'; @@ -234,7 +234,7 @@ class WhisperSessionItem extends StatelessWidget { ), if (item.hasTimestamp()) Text( - DateUtil.dateFormat((item.timestamp ~/ 1000000).toInt()), + DateFormatUtils.dateFormat((item.timestamp ~/ 1000000).toInt()), style: TextStyle( fontSize: 12, color: theme.colorScheme.outline, diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index b04dc9fb5..b721b8526 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -11,10 +11,10 @@ import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/image_preview_type.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; -import 'package:PiliPlus/utils/date_util.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart'; -import 'package:PiliPlus/utils/image_util.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/gestures.dart'; @@ -70,7 +70,7 @@ class ChatItem extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 6, bottom: 18), child: Text( - DateUtil.chatFormat(item.timestamp.toInt()), + DateFormatUtils.chatFormat(item.timestamp.toInt()), textAlign: TextAlign.center, style: TextStyle(color: theme.colorScheme.outline), ), @@ -451,7 +451,7 @@ class ChatItem extends StatelessWidget { type: PBadgeType.gray, text: content['times'] == 0 ? '--:--' - : DurationUtil.formatDuration(content['times']), + : DurationUtils.formatDuration(content['times']), ), ], ), @@ -772,7 +772,7 @@ class ChatItem extends StatelessWidget { child: GestureDetector( onTap: url == null ? null : () => PiliScheme.routePushFromUrl(url), child: CachedNetworkImage( - imageUrl: ImageUtil.thumbnailUrl(content['pic_url']), + imageUrl: ImageUtils.thumbnailUrl(content['pic_url']), ), ), ), diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 6ee45ec4c..43f3345d5 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -51,7 +51,6 @@ import 'package:media_kit/media_kit.dart'; import 'package:media_kit_video/media_kit_video.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; -import 'package:screen_brightness/screen_brightness.dart'; import 'package:universal_platform/universal_platform.dart'; class PlPlayerController { @@ -465,11 +464,8 @@ class PlPlayerController { return _instance?.volume.value; } - static Future setVolumeIfExists( - double volumeNew, { - bool videoPlayerVolume = false, - }) async { - await _instance?.setVolume(volumeNew, videoPlayerVolume: videoPlayerVolume); + static Future setVolumeIfExists(double volumeNew) async { + await _instance?.setVolume(volumeNew); } Box video = GStorage.video; @@ -897,7 +893,7 @@ class PlPlayerController { } else { playerStatus.status.value = PlayerStatus.paused; } - videoPlayerServiceHandler.onStatusChange( + videoPlayerServiceHandler?.onStatusChange( playerStatus.status.value, isBuffering.value, isLive, @@ -947,7 +943,7 @@ class PlPlayerController { }), videoPlayerController!.stream.buffering.listen((bool event) { isBuffering.value = event; - videoPlayerServiceHandler.onStatusChange( + videoPlayerServiceHandler?.onStatusChange( playerStatus.status.value, event, isLive, @@ -1012,20 +1008,22 @@ class PlPlayerController { // } // }), // 媒体通知监听 - onPlayerStatusChanged.listen((PlayerStatus event) { - videoPlayerServiceHandler.onStatusChange( - event, - isBuffering.value, - isLive, - ); - }), - onPositionChanged.listen((Duration event) { - EasyThrottle.throttle( - 'mediaServicePosition', - const Duration(seconds: 1), - () => videoPlayerServiceHandler.onPositionChange(event), - ); - }), + if (videoPlayerServiceHandler != null) ...[ + onPlayerStatusChanged.listen((PlayerStatus event) { + videoPlayerServiceHandler!.onStatusChange( + event, + isBuffering.value, + isLive, + ); + }), + onPositionChanged.listen((Duration event) { + EasyThrottle.throttle( + 'mediaServicePosition', + const Duration(seconds: 1), + () => videoPlayerServiceHandler!.onPositionChange(event), + ); + }), + ], }; } @@ -1138,7 +1136,7 @@ class PlPlayerController { playerStatus.status.value = PlayerStatus.playing; // screenManager.setOverlays(false); - audioSessionHandler.setActive(true); + audioSessionHandler?.setActive(true); } /// 暂停播放 @@ -1148,7 +1146,7 @@ class PlPlayerController { // 主动暂停时让出音频焦点 if (!isInterrupt) { - audioSessionHandler.setActive(false); + audioSessionHandler?.setActive(false); } } @@ -1208,31 +1206,15 @@ class PlPlayerController { hideTaskControls(); } - /// 音量 - Future getCurrentVolume() async { - // mac try...catch + Future setVolume(double volume) async { + this.volume.value = volume; try { - _currentVolume.value = (await FlutterVolumeController.getVolume())!; - } catch (_) {} - } - - Future setVolume( - double volumeNew, { - bool videoPlayerVolume = false, - }) async { - if (volumeNew < 0.0) { - volumeNew = 0.0; - } else if (volumeNew > 1.0) { - volumeNew = 1.0; - } - if (volume.value == volumeNew) { - return; - } - volume.value = volumeNew; - - try { - FlutterVolumeController.updateShowSystemUI(false); - await FlutterVolumeController.setVolume(volumeNew); + if (Utils.isDesktop) { + _videoPlayerController!.setVolume(volume * 100); + } else { + FlutterVolumeController.updateShowSystemUI(false); + await FlutterVolumeController.setVolume(volume); + } } catch (err) { if (kDebugMode) debugPrint(err.toString()); } @@ -1246,30 +1228,10 @@ class PlPlayerController { }); } - /// 亮度 - Future getCurrentBrightness() async { - try { - _currentBrightness.value = await ScreenBrightness.instance.application; - } catch (e) { - throw 'Failed to get current brightness'; - //return 0; - } - } - void setCurrBrightness(double brightness) { _currentBrightness.value = brightness; } - Future setBrightness(double brightness) async { - try { - this.brightness.value = brightness; - ScreenBrightness.instance.setApplicationScreenBrightness(brightness); - // setVideoBrightness(); - } catch (e) { - throw 'Failed to set brightness'; - } - } - /// Toggle Change the videofit accordingly void toggleVideoFit(VideoFitType value) { _videoFit.value = value; @@ -1303,7 +1265,7 @@ class PlPlayerController { /// 设置后台播放 Future setBackgroundPlay(bool val) async { - videoPlayerServiceHandler.enableBackgroundPlay = val; + videoPlayerServiceHandler?.enableBackgroundPlay = val; if (!tempPlayerConf) { setting.put(SettingBoxKey.enableBackgroundPlay, val); } @@ -1387,10 +1349,11 @@ class PlPlayerController { return; } late final size = Get.size; - if (mode == FullScreenMode.vertical || - (mode == FullScreenMode.auto && isVertical) || - (mode == FullScreenMode.ratio && - (isVertical || size.height / size.width < 1.25))) { + if (Utils.isMobile && + (mode == FullScreenMode.vertical || + (mode == FullScreenMode.auto && isVertical) || + (mode == FullScreenMode.ratio && + (isVertical || size.height / size.width < 1.25)))) { await verticalScreenForTwoSeconds(); } else { await landScape(); @@ -1561,7 +1524,7 @@ class PlPlayerController { _videoPlayerController = null; } _instance = null; - videoPlayerServiceHandler.clear(); + videoPlayerServiceHandler?.clear(); } catch (err) { if (kDebugMode) debugPrint(err.toString()); } diff --git a/lib/plugin/pl_player/utils/fullscreen.dart b/lib/plugin/pl_player/utils/fullscreen.dart index 9054a4262..aacc44d0a 100644 --- a/lib/plugin/pl_player/utils/fullscreen.dart +++ b/lib/plugin/pl_player/utils/fullscreen.dart @@ -13,9 +13,9 @@ Future landScape() async { try { if (kIsWeb) { await document.documentElement?.requestFullscreen(); - } else if (Platform.isAndroid || Platform.isIOS) { + } else if (Utils.isMobile) { await AutoOrientation.landscapeAutoMode(forceSensor: true); - } else if (Platform.isMacOS || Platform.isWindows || Platform.isLinux) { + } else if (Utils.isDesktop) { await const MethodChannel( 'com.alexmercerind/media_kit_video', ).invokeMethod( @@ -86,7 +86,7 @@ Future showStatusBar() async { try { if (kIsWeb) { document.exitFullscreen(); - } else if (Platform.isAndroid || Platform.isIOS) { + } else if (Utils.isMobile) { if (Platform.isAndroid && (await Utils.sdkInt < 29)) { mode = SystemUiMode.manual; } @@ -94,7 +94,7 @@ Future showStatusBar() async { mode, overlays: SystemUiOverlay.values, ); - } else if (Platform.isMacOS || Platform.isWindows || Platform.isLinux) { + } else if (Utils.isDesktop) { await const MethodChannel( 'com.alexmercerind/media_kit_video', ).invokeMethod( diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index e7cc05b6d..a27419767 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -40,9 +40,9 @@ import 'package:PiliPlus/plugin/pl_player/widgets/common_btn.dart'; import 'package:PiliPlus/plugin/pl_player/widgets/forward_seek.dart'; import 'package:PiliPlus/plugin/pl_player/widgets/mpv_convert_webp.dart'; import 'package:PiliPlus/plugin/pl_player/widgets/play_pause_btn.dart'; -import 'package:PiliPlus/utils/duration_util.dart'; -import 'package:PiliPlus/utils/extension.dart'; +import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart'; +import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -61,8 +61,7 @@ import 'package:get/get.dart' hide ContextExtensionss; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:media_kit/media_kit.dart'; import 'package:media_kit_video/media_kit_video.dart'; -import 'package:saver_gallery/saver_gallery.dart'; -import 'package:screen_brightness/screen_brightness.dart'; +import 'package:screen_brightness_platform_interface/screen_brightness_platform_interface.dart'; class PLVideoPlayer extends StatefulWidget { const PLVideoPlayer({ @@ -123,7 +122,6 @@ class _PLVideoPlayerState extends State final RxBool _brightnessIndicator = false.obs; Timer? _brightnessTimer; - final RxDouble _volumeValue = 0.0.obs; final RxBool _volumeIndicator = false.obs; Timer? _volumeTimer; @@ -207,49 +205,52 @@ class _PLVideoPlayerState extends State duration: const Duration(milliseconds: 100), ); videoController = plPlayerController.videoController!; - Future.microtask(() async { - try { - FlutterVolumeController.updateShowSystemUI(true); - _volumeValue.value = (await FlutterVolumeController.getVolume())!; - FlutterVolumeController.addListener((double value) { - if (mounted && !_volumeInterceptEventStream.value) { - _volumeValue.value = value; - if (Platform.isIOS && !FlutterVolumeController.showSystemUI) { - _volumeIndicator.value = true; - _volumeTimer?.cancel(); - _volumeTimer = Timer(const Duration(milliseconds: 800), () { + + if (Utils.isMobile) { + Future.microtask(() async { + try { + FlutterVolumeController.updateShowSystemUI(true); + plPlayerController.volume.value = + (await FlutterVolumeController.getVolume())!; + FlutterVolumeController.addListener((double value) { + if (mounted && !_volumeInterceptEventStream.value) { + plPlayerController.volume.value = value; + if (Platform.isIOS && !FlutterVolumeController.showSystemUI) { + _volumeIndicator.value = true; + _volumeTimer?.cancel(); + _volumeTimer = Timer(const Duration(milliseconds: 800), () { + if (mounted) { + _volumeIndicator.value = false; + } + }); + } + } + }); + } catch (_) {} + }); + + Future.microtask(() async { + try { + _brightnessValue.value = + await ScreenBrightnessPlatform.instance.application; + _listener = ScreenBrightnessPlatform + .instance + .onApplicationScreenBrightnessChanged + .listen((double value) { if (mounted) { - _volumeIndicator.value = false; + _brightnessValue.value = value; } }); - } - } - }); - } catch (_) {} - }); - - Future.microtask(() async { - try { - _brightnessValue.value = await ScreenBrightness.instance.application; - _listener = ScreenBrightness - .instance - .onApplicationScreenBrightnessChanged - .listen((double value) { - if (mounted) { - _brightnessValue.value = value; - } - }); - } catch (_) {} - }); + } catch (_) {} + }); + } } Future setVolume(double value) async { - try { - FlutterVolumeController.updateShowSystemUI(false); - await FlutterVolumeController.setVolume(value); - } catch (_) {} - - _volumeValue.value = value; + if (plPlayerController.volume.value == value) { + return; + } + plPlayerController.setVolume(value); _volumeIndicator.value = true; _volumeInterceptEventStream.value = true; _volumeTimer?.cancel(); @@ -263,7 +264,9 @@ class _PLVideoPlayerState extends State Future setBrightness(double value) async { try { - await ScreenBrightness.instance.setApplicationScreenBrightness(value); + await ScreenBrightnessPlatform.instance.setApplicationScreenBrightness( + value, + ); } catch (_) {} _brightnessIndicator.value = true; _brightnessTimer?.cancel(); @@ -281,7 +284,9 @@ class _PLVideoPlayerState extends State _listener?.cancel(); _controlsListener?.cancel(); animationController.dispose(); - FlutterVolumeController.removeListener(); + if (Utils.isMobile) { + FlutterVolumeController.removeListener(); + } transformationController.dispose(); super.dispose(); } @@ -347,7 +352,7 @@ class _PLVideoPlayerState extends State // 播放时间 Obx( () => Text( - DurationUtil.formatDuration( + DurationUtils.formatDuration( plPlayerController.positionSeconds.value, ), style: const TextStyle( @@ -360,7 +365,7 @@ class _PLVideoPlayerState extends State ), Obx( () => Text( - DurationUtil.formatDuration( + DurationUtils.formatDuration( plPlayerController.durationSeconds.value.inSeconds, ), style: const TextStyle( @@ -847,7 +852,8 @@ class _PLVideoPlayerState extends State final double tapPosition = details.localFocalPoint.dx; final double sectionWidth = maxWidth / 3; if (tapPosition < sectionWidth) { - if (!plPlayerController.enableSlideVolumeBrightness) { + if (Utils.isDesktop || + !plPlayerController.enableSlideVolumeBrightness) { return; } // 左边区域 @@ -975,9 +981,12 @@ class _PLVideoPlayerState extends State 'setVolume', const Duration(milliseconds: 20), () { - final double volume = _volumeValue.value - delta.dy / level; - final double result = volume.clamp(0.0, 1.0); - setVolume(result); + final double volume = clampDouble( + plPlayerController.volume.value - delta.dy / level, + 0.0, + 1.0, + ); + setVolume(volume); }, ); } @@ -1025,7 +1034,7 @@ class _PLVideoPlayerState extends State final double sectionWidth = maxWidth / 3; late GestureType gestureType; if (tapPosition < sectionWidth) { - if (!plPlayerController.enableSlideVolumeBrightness) { + if (Utils.isDesktop || !plPlayerController.enableSlideVolumeBrightness) { return; } // 左边区域 @@ -1089,9 +1098,12 @@ class _PLVideoPlayerState extends State 'setVolume', const Duration(milliseconds: 20), () { - final double volume = _volumeValue.value - details.delta.dy / level; - final double result = volume.clamp(0.0, 1.0); - setVolume(result); + final double volume = clampDouble( + plPlayerController.volume.value - details.delta.dy / level, + 0.0, + 1.0, + ); + setVolume(volume); }, ); } @@ -1298,7 +1310,7 @@ class _PLVideoPlayerState extends State children: [ Obx(() { return Text( - DurationUtil.formatDuration( + DurationUtils.formatDuration( plPlayerController .sliderTempPosition .value @@ -1311,7 +1323,7 @@ class _PLVideoPlayerState extends State Obx( () { return Text( - DurationUtil.formatDuration( + DurationUtils.formatDuration( plPlayerController .durationSeconds .value @@ -1336,44 +1348,47 @@ class _PLVideoPlayerState extends State child: Align( alignment: Alignment.center, child: Obx( - () => AnimatedOpacity( - curve: Curves.easeInOut, - opacity: _volumeIndicator.value ? 1.0 : 0.0, - duration: const Duration(milliseconds: 150), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 5, - ), - decoration: const BoxDecoration( - color: Color(0x88000000), - borderRadius: BorderRadius.all(Radius.circular(64)), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - _volumeValue.value == 0.0 - ? Icons.volume_off - : _volumeValue.value < 0.5 - ? Icons.volume_down - : Icons.volume_up, - color: Colors.white, - size: 20.0, - ), - const SizedBox(width: 2.0), - Text( - '${(_volumeValue.value * 100.0).round()}%', - style: const TextStyle( - fontSize: 13.0, + () { + final volume = plPlayerController.volume.value; + return AnimatedOpacity( + curve: Curves.easeInOut, + opacity: _volumeIndicator.value ? 1.0 : 0.0, + duration: const Duration(milliseconds: 150), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 5, + ), + decoration: const BoxDecoration( + color: Color(0x88000000), + borderRadius: BorderRadius.all(Radius.circular(64)), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + volume == 0.0 + ? Icons.volume_off + : volume < 0.5 + ? Icons.volume_down + : Icons.volume_up, color: Colors.white, + size: 20.0, ), - ), - ], + const SizedBox(width: 2.0), + Text( + '${(volume * 100.0).round()}%', + style: const TextStyle( + fontSize: 13.0, + color: Colors.white, + ), + ), + ], + ), ), - ), - ), + ); + }, ), ), ), @@ -1728,29 +1743,13 @@ class _PLVideoPlayerState extends State //移除圆角 shape: const RoundedRectangleBorder(), content: GestureDetector( - onTap: () async { + onTap: () { Get.back(); - - String name = DateTime.now() - .toString(); - final SaveResult result = - await SaverGallery.saveImage( - value, - fileName: name, - androidRelativePath: - "Pictures/Screenshots", - skipIfExists: false, - ); - - if (result.isSuccess) { - SmartDialog.showToast( - '$name.png已保存到相册/截图', - ); - } else { - SmartDialog.showToast( - '保存失败,${result.errorMessage}', - ); - } + ImageUtils.saveByteImg( + bytes: value, + fileName: + 'screenshot_${ImageUtils.time}', + ); }, child: ConstrainedBox( constraints: BoxConstraints( @@ -2047,18 +2046,15 @@ class _PLVideoPlayerState extends State mpv.dispose(); } if (await future) { - await SaverGallery.saveFile( + await ImageUtils.saveFileImg( filePath: file, - fileName: name, - androidRelativePath: 'Pictures/Screenshots', - skipIfExists: false, + fileName: '$name.webp', + needToast: true, ); - SmartDialog.showToast('$name已保存到相册/截图'); } else { SmartDialog.showToast('转码出现错误或已取消'); } progress.close(); - File(file).delSync(); if (isPlay) ctr.play(); }, ); @@ -2233,7 +2229,7 @@ Future _getImg(String url) async { options: Options(responseType: ResponseType.bytes), ); if (res.statusCode == 200) { - final data = res.data; + final Uint8List data = res.data; cacheManager.putFile(cacheKey, data, fileExtension: 'jpg'); return _loadImg(data); } diff --git a/lib/scripts/build.dart b/lib/scripts/build.dart new file mode 100644 index 000000000..ed87c4011 --- /dev/null +++ b/lib/scripts/build.dart @@ -0,0 +1,49 @@ +import 'dart:io'; + +void main() async { + if (Platform.isWindows) { + updateVersion(); + } + + final buildTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; + String commitHash = ''; + try { + final result = await Process.run('git', ['rev-parse', 'HEAD']); + commitHash = result.stdout.toString().trim(); + } catch (_) {} + final content = + ''' +class BuildConfig { + static const int buildTime = $buildTime; + static const String commitHash = '$commitHash'; +} +'''; + final file = File('lib/build_config.dart'); + await file.writeAsString(content); +} + +Future updateVersion() async { + final file = File('pubspec.yaml'); + final lines = await file.readAsLines(); + + final versionLineIndex = lines.indexWhere( + (line) => line.trim().startsWith('version:'), + ); + if (versionLineIndex == -1) { + exit(1); + } + + final versionName = lines[versionLineIndex] + .split('+')[0] + .replaceAll('version:', '') + .trim(); + final commitCount = await Process.run('git', [ + 'rev-list', + '--count', + 'HEAD', + ]); + final buildNumber = commitCount.stdout.toString().trim(); + + lines[versionLineIndex] = 'version: $versionName+$buildNumber'; + await file.writeAsString(lines.join('\n')); +} diff --git a/lib/scripts/build.sh b/lib/scripts/build.sh deleted file mode 100644 index 6946cbbb5..000000000 --- a/lib/scripts/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -build_time=$(date +%s) -commit_hash=$(git rev-parse HEAD) - -cat < lib/build_config.dart -class BuildConfig { - static const int buildTime = $build_time; - static const String commitHash = '$commit_hash'; -} -EOL diff --git a/lib/services/service_locator.dart b/lib/services/service_locator.dart index beaa798e1..8cf81e5dc 100644 --- a/lib/services/service_locator.dart +++ b/lib/services/service_locator.dart @@ -1,8 +1,8 @@ import 'package:PiliPlus/services/audio_handler.dart'; import 'package:PiliPlus/services/audio_session.dart'; -late VideoPlayerServiceHandler videoPlayerServiceHandler; -late AudioSessionHandler audioSessionHandler; +VideoPlayerServiceHandler? videoPlayerServiceHandler; +AudioSessionHandler? audioSessionHandler; Future setupServiceLocator() async { final audio = await initAudioService(); diff --git a/lib/utils/cache_manage.dart b/lib/utils/cache_manage.dart index 93d392af4..3d2811897 100644 --- a/lib/utils/cache_manage.dart +++ b/lib/utils/cache_manage.dart @@ -3,55 +3,61 @@ import 'dart:io'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:path_provider/path_provider.dart'; abstract class CacheManage { // 获取缓存目录 - static Future loadApplicationCache() async { + static Future loadApplicationCache() async { /// clear all of image in memory // clearMemoryImageCache(); /// get ImageCache // var res = getMemoryImageCache(); // 缓存大小 - double cacheSize = 0; // cached_network_image directory Directory tempDirectory = await getTemporaryDirectory(); + if (Utils.isDesktop) { + final dir = Directory('${tempDirectory.path}/libCachedImageData'); + if (dir.existsSync()) { + return await getTotalSizeOfFilesInDir(dir); + } else { + return 0; + } + } // get_storage directory Directory docDirectory = await getApplicationDocumentsDirectory(); + int cacheSize = 0; // 获取缓存大小 if (tempDirectory.existsSync()) { - double value = await getTotalSizeOfFilesInDir(tempDirectory); - cacheSize += value; + cacheSize += await getTotalSizeOfFilesInDir(tempDirectory); } /// 获取缓存大小 dioCache if (docDirectory.existsSync()) { - double value = 0; String dioCacheFileName = '${docDirectory.path}${Platform.pathSeparator}DioCache.db'; var dioCacheFile = File(dioCacheFileName); if (dioCacheFile.existsSync()) { - value = await getTotalSizeOfFilesInDir(dioCacheFile); + cacheSize += await getTotalSizeOfFilesInDir(dioCacheFile); } - cacheSize += value; } return cacheSize; } // 循环计算文件的大小(递归) - static Future getTotalSizeOfFilesInDir( + static Future getTotalSizeOfFilesInDir( final FileSystemEntity file, ) async { if (file is File) { int length = await file.length(); - return double.parse(length.toString()); + return int.parse(length.toString()); } if (file is Directory) { final List children = file.listSync(); - double total = 0; + int total = 0; for (final FileSystemEntity child in children) { total += await getTotalSizeOfFilesInDir(child); } @@ -87,10 +93,17 @@ abstract class CacheManage { // 清除 Library/Caches 目录及文件缓存 static Future clearLibraryCache() async { - var appDocDir = await getTemporaryDirectory(); - if (appDocDir.existsSync()) { + var tempDirectory = await getTemporaryDirectory(); + if (Utils.isDesktop) { + final dir = Directory('${tempDirectory.path}/libCachedImageData'); + if (dir.existsSync()) { + await dir.delete(recursive: true); + } + return; + } + if (tempDirectory.existsSync()) { // await appDocDir.delete(recursive: true); - final List children = appDocDir.listSync( + final List children = tempDirectory.listSync( recursive: false, ); for (final FileSystemEntity file in children) { diff --git a/lib/utils/date_util.dart b/lib/utils/date_utils.dart similarity index 97% rename from lib/utils/date_util.dart rename to lib/utils/date_utils.dart index 4d2c33f4c..f24556949 100644 --- a/lib/utils/date_util.dart +++ b/lib/utils/date_utils.dart @@ -1,6 +1,6 @@ import 'package:intl/intl.dart' show DateFormat; -class DateUtil { +class DateFormatUtils { static final shortFormat = DateFormat('MM-dd'); static final longFormat = DateFormat('yyyy-MM-dd'); static final _shortFormatD = DateFormat('MM-dd HH:mm'); @@ -38,7 +38,7 @@ class DateUtil { } final DateFormat sdf = now.year == date.year ? short ?? shortFormat - : long ?? DateUtil.longFormat; + : long ?? DateFormatUtils.longFormat; return sdf.format(date); } diff --git a/lib/utils/duration_util.dart b/lib/utils/duration_utils.dart similarity index 98% rename from lib/utils/duration_util.dart rename to lib/utils/duration_utils.dart index 065eaeb76..cdcdcbfc4 100644 --- a/lib/utils/duration_util.dart +++ b/lib/utils/duration_utils.dart @@ -1,6 +1,6 @@ import 'dart:math' show pow; -class DurationUtil { +class DurationUtils { static String formatDuration(num? seconds) { if (seconds == null || seconds == 0) { return '00:00'; diff --git a/lib/utils/extension.dart b/lib/utils/extension.dart index 5ae32c2c1..79898c974 100644 --- a/lib/utils/extension.dart +++ b/lib/utils/extension.dart @@ -227,9 +227,9 @@ extension ThreeDotItemTypeExt on ThreeDotItemType { } extension FileExt on File { - void delSync({bool recursive = false}) { + void tryDel({bool recursive = false}) { try { - deleteSync(recursive: recursive); + delete(recursive: recursive); } catch (_) {} } } diff --git a/lib/utils/fav_util.dart b/lib/utils/fav_utils.dart similarity index 95% rename from lib/utils/fav_util.dart rename to lib/utils/fav_utils.dart index 8e43467e3..de09c6dac 100644 --- a/lib/utils/fav_util.dart +++ b/lib/utils/fav_utils.dart @@ -1,4 +1,4 @@ -class FavUtil { +class FavUtils { static bool isDefaultFav(int? attr) { if (attr == null) { return false; diff --git a/lib/utils/image_util.dart b/lib/utils/image_utils.dart similarity index 74% rename from lib/utils/image_util.dart rename to lib/utils/image_utils.dart index 2ac3de097..d79657ac5 100644 --- a/lib/utils/image_util.dart +++ b/lib/utils/image_utils.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'dart:typed_data'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/utils/extension.dart'; @@ -6,6 +7,7 @@ import 'package:PiliPlus/utils/global_data.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:dio/dio.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:intl/intl.dart' show DateFormat; @@ -14,7 +16,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:saver_gallery/saver_gallery.dart'; import 'package:share_plus/share_plus.dart'; -class ImageUtil { +class ImageUtils { static String get time => DateFormat('yyyy-MM-dd_HH-mm-ss').format(DateTime.now()); static bool silentDownImg = Pref.silentDownImg; @@ -35,7 +37,7 @@ class ImageUtil { sharePositionOrigin: await Utils.sharePositionOrigin, ), ) - .whenComplete(() => File(path).delSync()); + .whenComplete(File(path).tryDel); } } catch (e) { SmartDialog.showToast(e.toString()); @@ -131,8 +133,8 @@ class ImageUtil { height: height, ).whenComplete( () { - File(videoPath).delSync(); - File(imagePath).delSync(); + File(videoPath).tryDel(); + File(imagePath).tryDel(); }, ); if (success) { @@ -143,18 +145,12 @@ class ImageUtil { } } else { if (!silentDownImg) SmartDialog.showLoading(msg: '正在保存'); - final SaveResult result = await SaverGallery.saveFile( + await saveFileImg( filePath: videoPath, fileName: videoName, - androidRelativePath: "Pictures/PiliPlus", - skipIfExists: false, - ).whenComplete(() => File(videoPath).delSync()); - if (result.isSuccess) { - SmartDialog.showToast(' 已保存 '); - } else { - SmartDialog.showToast('保存失败,${result.errorMessage}'); - return false; - } + type: FileType.video, + needToast: true, + ); } return true; } catch (err) { @@ -199,7 +195,7 @@ class ImageUtil { fileName: name, androidRelativePath: "Pictures/PiliPlus", skipIfExists: false, - ).whenComplete(() => File(filePath).delSync()); + ).whenComplete(File(filePath).tryDel); } } return ( @@ -212,13 +208,10 @@ class ImageUtil { if (!isAndroid) { for (var res in result) { if (res.statusCode == 200) { - await SaverGallery.saveFile( + await saveFileImg( filePath: res.filePath, fileName: res.name, - androidRelativePath: "Pictures/PiliPlus", - skipIfExists: false, ); - File(res.filePath).delSync(); } } } @@ -265,4 +258,83 @@ class ImageUtil { } return src.http2https; } + + static Future saveByteImg({ + required Uint8List bytes, + required String fileName, + String ext = 'png', + }) async { + SaveResult? result; + fileName += '.$ext'; + if (Utils.isMobile) { + SmartDialog.showLoading(msg: '正在保存'); + result = await SaverGallery.saveImage( + bytes, + fileName: fileName, + androidRelativePath: "Pictures/PiliPlus", + skipIfExists: false, + ); + SmartDialog.dismiss(); + if (result.isSuccess) { + SmartDialog.showToast(' 已保存 '); + } else { + SmartDialog.showToast('保存失败,${result.errorMessage}'); + } + } else { + SmartDialog.dismiss(); + final savePath = await FilePicker.platform.saveFile( + type: FileType.image, + fileName: fileName, + ); + if (savePath == null) { + SmartDialog.showToast("取消保存"); + return null; + } + await File(savePath).writeAsBytes(bytes); + SmartDialog.showToast(' 已保存 '); + result = SaveResult(true, null); + } + return result; + } + + static Future saveFileImg({ + required String filePath, + required String fileName, + FileType type = FileType.image, + bool needToast = false, + }) async { + final file = File(filePath); + if (!file.existsSync()) { + SmartDialog.showToast("文件不存在"); + return; + } + SaveResult? result; + if (Utils.isMobile) { + result = await SaverGallery.saveFile( + filePath: filePath, + fileName: fileName, + androidRelativePath: "Pictures/PiliPlus", + skipIfExists: false, + ).whenComplete(file.tryDel); + } else { + final savePath = await FilePicker.platform.saveFile( + type: type, + fileName: fileName, + ); + if (savePath == null) { + SmartDialog.showToast("取消保存"); + return; + } + await file.copy(savePath); + file.tryDel(); + result = SaveResult(true, null); + } + if (needToast) { + if (result.isSuccess) { + SmartDialog.showToast(' 已保存 '); + } else { + SmartDialog.showToast('保存失败,${result.errorMessage}'); + } + } + } } diff --git a/lib/utils/login_utils.dart b/lib/utils/login_utils.dart index 9714b6573..2bcb6551c 100644 --- a/lib/utils/login_utils.dart +++ b/lib/utils/login_utils.dart @@ -1,3 +1,5 @@ +import 'dart:async' show FutureOr; +import 'dart:io' show Platform; import 'dart:math'; import 'package:PiliPlus/grpc/grpc_req.dart'; @@ -16,6 +18,7 @@ import 'package:PiliPlus/pages/pgc/controller.dart'; import 'package:PiliPlus/services/account_service.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts/account.dart'; +import 'package:PiliPlus/utils/request_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart' as web; @@ -25,7 +28,10 @@ import 'package:get/get.dart'; class LoginUtils { static final random = Random(); - static Future setWebCookie([Account? account]) async { + static FutureOr setWebCookie([Account? account]) { + if (Platform.isWindows) { + return null; + } final cookies = (account ?? Accounts.main).cookieJar.toList(); final webManager = web.CookieManager(); return Future.wait( @@ -47,6 +53,7 @@ class LoginUtils { final account = Accounts.main; GrpcReq.updateHeaders(account.accessKey); setWebCookie(account); + RequestUtils.syncHistoryStatus(); final result = await UserHttp.userInfo(); if (result.isSuccess) { final UserInfoData data = result.data; diff --git a/lib/utils/num_util.dart b/lib/utils/num_utils.dart similarity index 98% rename from lib/utils/num_util.dart rename to lib/utils/num_utils.dart index 4811f139f..a05a705df 100644 --- a/lib/utils/num_util.dart +++ b/lib/utils/num_utils.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart' show kDebugMode, debugPrint; import 'package:get/get_utils/get_utils.dart'; -class NumUtil { +class NumUtils { static final _numRegExp = RegExp(r'([\d\.]+)([千万亿])?'); static int _getUnit(String? unit) { diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 9b29f10fb..5e6a29156 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -54,7 +54,7 @@ abstract class GStorage { } static String exportAllSettings() { - return jsonEncode({ + return const JsonEncoder.withIndent(' ').convert({ setting.name: setting.toMap(), video.name: video.toMap(), }); diff --git a/lib/utils/theme_utils.dart b/lib/utils/theme_utils.dart index 8c6bd03ed..d85e1336f 100644 --- a/lib/utils/theme_utils.dart +++ b/lib/utils/theme_utils.dart @@ -50,7 +50,7 @@ class ThemeUtils { titleSpacing: 0, centerTitle: false, scrolledUnderElevation: 0, - backgroundColor: isDynamic ? null : colorScheme.surface, + backgroundColor: colorScheme.surface, titleTextStyle: TextStyle( fontSize: 16, color: colorScheme.onSurface, diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 4ae44511d..53f76baf5 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -16,6 +16,11 @@ class Utils { static const channel = MethodChannel("PiliPlus"); + static final bool isMobile = Platform.isAndroid || Platform.isIOS; + + static final bool isDesktop = + Platform.isWindows || Platform.isMacOS || Platform.isLinux; + static Color parseColor(String color) => Color(int.parse(color.replaceFirst('#', 'FF'), radix: 16)); @@ -70,7 +75,9 @@ class Utils { String baseDirectory, List shaders, ) { - return shaders.map((shader) => path.join(baseDirectory, shader)).join(':'); + return shaders + .map((shader) => path.join(baseDirectory, shader)) + .join(Platform.isWindows ? ';' : ':'); } static final numericRegex = RegExp(r'^[\d\.]+$'); diff --git a/pubspec.lock b/pubspec.lock index 0a7d084cc..522187a8b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -214,10 +214,10 @@ packages: dependency: transitive description: name: built_value - sha256: "1b3b173f3379c8f941446267868548b6fc67e9134d81f4842eb98bb729451359" + sha256: a30f0a0e38671e89a492c44d005b5545b830a961575bbd8336d42869ff71066d url: "https://pub.dev" source: hosted - version: "8.11.2" + version: "8.12.0" cached_network_image: dependency: "direct main" description: @@ -312,10 +312,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + sha256: "11654819532ba94c34de52ff5feb52bd81cba1de00ef2ed622fd50295f9d4243" url: "https://pub.dev" source: hosted - version: "4.10.1" + version: "4.11.0" collection: dependency: "direct main" description: @@ -328,10 +328,10 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec + sha256: "33bae12a398f841c6cda09d1064212957265869104c478e5ad51e2fb26c3973c" url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "7.0.0" connectivity_plus_platform_interface: dependency: transitive description: @@ -452,14 +452,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - document_file_save_plus: - dependency: "direct main" - description: - name: document_file_save_plus - sha256: ff05c6a3b072377566e8e92666db38eb277786f90c0ac267ea47dc22725c1df3 - url: "https://pub.dev" - source: hosted - version: "2.0.0" dynamic_color: dependency: "direct main" description: @@ -541,6 +533,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: f2d9f173c2c14635cc0e9b14c143c49ef30b4934e8d1d274d6206fcb0086a06f + url: "https://pub.dev" + source: hosted + version: "10.3.3" file_selector_linux: dependency: transitive description: @@ -638,10 +638,11 @@ packages: flutter_inappwebview: dependency: "direct main" description: - name: flutter_inappwebview - sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5" - url: "https://pub.dev" - source: hosted + path: flutter_inappwebview + ref: "version_6.1.5" + resolved-ref: bef2e3cb123ad4f6533a6371594ea3e21f36eeb2 + url: "https://github.com/bggRGjQaUbCoE/flutter_inappwebview.git" + source: git version: "6.1.5" flutter_inappwebview_android: dependency: transitive @@ -683,22 +684,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0+1" - flutter_inappwebview_web: - dependency: transitive - description: - name: flutter_inappwebview_web - sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - flutter_inappwebview_windows: - dependency: transitive - description: - name: flutter_inappwebview_windows - sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055" - url: "https://pub.dev" - source: hosted - version: "0.6.0" flutter_launcher_icons: dependency: "direct dev" description: @@ -959,10 +944,10 @@ packages: dependency: transitive description: name: image_picker_android - sha256: "28f3987ca0ec702d346eae1d90eda59603a2101b52f1e234ded62cff1d5cfa6e" + sha256: a45bef33deb24839a51fb85a4d9e504ead2b1ad1c4779d02d09bf6a8857cdd52 url: "https://pub.dev" source: hosted - version: "0.8.13+1" + version: "0.8.13+2" image_picker_for_web: dependency: transitive description: @@ -1047,10 +1032,10 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "11.0.1" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: @@ -1210,7 +1195,7 @@ packages: description: path: media_kit_video ref: "version_1.2.5" - resolved-ref: c4655bfb4bf81b6bb450d252184da20e2fbba292 + resolved-ref: "484d040a05133343eb01752ce48bfe545219a80a" url: "https://github.com/bggRGjQaUbCoE/media-kit.git" source: git version: "1.2.5" @@ -1502,16 +1487,8 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.1" - screen_brightness: - dependency: "direct main" - description: - name: screen_brightness - sha256: "5f70754028f169f059fdc61112a19dcbee152f8b293c42c848317854d650cba3" - url: "https://pub.dev" - source: hosted - version: "2.1.7" screen_brightness_android: - dependency: transitive + dependency: "direct overridden" description: name: screen_brightness_android sha256: d34f5321abd03bc3474f4c381f53d189117eba0b039eac1916aa92cca5fd0a96 @@ -1519,45 +1496,61 @@ packages: source: hosted version: "2.1.3" screen_brightness_ios: - dependency: transitive + dependency: "direct overridden" description: name: screen_brightness_ios sha256: "2493953340ecfe8f4f13f61db50ce72533a55b0bbd58ba1402893feecf3727f5" url: "https://pub.dev" source: hosted version: "2.1.2" - screen_brightness_macos: - dependency: transitive - description: - name: screen_brightness_macos - sha256: "4edf330ad21078686d8bfaf89413325fbaf571dcebe1e89254d675a3f288b5b9" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - screen_brightness_ohos: - dependency: transitive - description: - name: screen_brightness_ohos - sha256: a93a263dcd39b5c56e589eb495bcd001ce65cdd96ff12ab1350683559d5c5bb7 - url: "https://pub.dev" - source: hosted - version: "2.1.2" screen_brightness_platform_interface: - dependency: transitive + dependency: "direct main" description: name: screen_brightness_platform_interface sha256: "737bd47b57746bc4291cab1b8a5843ee881af499514881b0247ec77447ee769c" url: "https://pub.dev" source: hosted version: "2.1.0" - screen_brightness_windows: + screen_retriever: dependency: transitive description: - name: screen_brightness_windows - sha256: d3518bf0f5d7a884cee2c14449ae0b36803802866de09f7ef74077874b6b2448 + name: screen_retriever + sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "0.2.0" + screen_retriever_linux: + dependency: transitive + description: + name: screen_retriever_linux + sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_macos: + dependency: transitive + description: + name: screen_retriever_macos + sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_platform_interface: + dependency: transitive + description: + name: screen_retriever_platform_interface + sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_windows: + dependency: transitive + description: + name: screen_retriever_windows + sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" + url: "https://pub.dev" + source: hosted + version: "0.2.0" scrollable_positioned_list: dependency: "direct main" description: @@ -1578,10 +1571,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: d7dc0630a923883c6328ca31b89aa682bacbf2f8304162d29f7c6aaff03a27a1 + sha256: "3424e9d5c22fd7f7590254ba09465febd6f8827c8b19a44350de4ac31d92d3a6" url: "https://pub.dev" source: hosted - version: "11.1.0" + version: "12.0.0" share_plus_platform_interface: dependency: transitive description: @@ -1855,10 +1848,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "69ee86740f2847b9a4ba6cffa74ed12ce500bbe2b07f3dc1e643439da60637b7" + sha256: "07cffecb7d68cbc6437cd803d5f11a86fe06736735c3dfe46ff73bcb0f958eed" url: "https://pub.dev" source: hosted - version: "6.3.18" + version: "6.3.21" url_launcher_ios: dependency: transitive description: @@ -1967,18 +1960,18 @@ packages: dependency: "direct main" description: name: wakelock_plus - sha256: a474e314c3e8fb5adef1f9ae2d247e57467ad557fa7483a2b895bc1b421c5678 + sha256: "61713aa82b7f85c21c9f4cd0a148abd75f38a74ec645fcb1e446f882c82fd09b" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" wakelock_plus_platform_interface: dependency: transitive description: name: wakelock_plus_platform_interface - sha256: e10444072e50dbc4999d7316fd303f7ea53d31c824aa5eb05d7ccbdd98985207 + sha256: "036deb14cd62f558ca3b73006d52ce049fabcdcb2eddfe0bf0fe4e8a943b5cf2" url: "https://pub.dev" source: hosted - version: "1.2.3" + version: "1.3.0" watcher: dependency: transitive description: @@ -2044,6 +2037,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + window_manager: + dependency: "direct main" + description: + name: window_manager + sha256: "7eb6d6c4164ec08e1bf978d6e733f3cebe792e2a23fb07cbca25c2872bfdbdcd" + url: "https://pub.dev" + source: hosted + version: "0.5.1" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 696028e6d..37fc915c2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -45,7 +45,7 @@ dependencies: # 网络 dio: ^5.7.0 cookie_jar: ^4.0.8 - connectivity_plus: ^6.1.1 + connectivity_plus: ^7.0.0 dio_http2_adapter: ^2.5.3 # 图片 @@ -67,12 +67,17 @@ dependencies: # 权限 permission_handler: ^12.0.0+1 # 分享 - share_plus: ^11.0.0 + share_plus: ^12.0.0 # cookie 管理 # webview_cookie_manager: ^2.0.6 # 浏览器 # webview_flutter: ^4.10.0 - flutter_inappwebview: ^6.1.5 + # flutter_inappwebview: ^6.1.5 + flutter_inappwebview: + git: + url: https://github.com/bggRGjQaUbCoE/flutter_inappwebview.git + path: flutter_inappwebview + ref: version_6.1.5 # 解决sliver滑动不同步 # extended_nested_scroll_view: ^6.2.1 extended_nested_scroll_view: @@ -187,7 +192,7 @@ dependencies: live_photo_maker: ^0.0.6 fl_chart: ^1.0.0 synchronized: ^3.3.0 - document_file_save_plus: ^2.0.0 + # document_file_save_plus: ^2.0.0 # webdav_client: ^1.2.2 webdav_client: git: @@ -202,12 +207,14 @@ dependencies: crclib: ^3.0.0 web_socket_channel: ^3.0.3 image: ^4.5.4 + window_manager: ^0.5.1 + file_picker: ^10.3.3 vector_math: any fixnum: any json_annotation: any stream_transform: any - screen_brightness: any + screen_brightness_platform_interface: any mime: any universal_platform: any path: any @@ -217,7 +224,10 @@ dependencies: http2: any dependency_overrides: - screen_brightness: ^2.1.7 + # screen_brightness: ^2.1. + screen_brightness_ios: ^2.1.2 + screen_brightness_android: ^2.1.3 + screen_brightness_platform_interface: ^2.1.0 path: ^1.9.1 mime: ^2.0.0 rxdart: ^0.28.0 diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt index 930d2071a..903f4899d 100644 --- a/windows/flutter/CMakeLists.txt +++ b/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index b25e363ef..955ee3038 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -31,6 +31,11 @@ bool FlutterWindow::OnCreate() { this->Show(); }); + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20caf..aae59560b 100644 Binary files a/windows/runner/resources/app_icon.ico and b/windows/runner/resources/app_icon.ico differ