diff --git a/lib/common/widgets/progress_bar/segment_progress_bar.dart b/lib/common/widgets/progress_bar/segment_progress_bar.dart index aec95d8a5..875822dc4 100644 --- a/lib/common/widgets/progress_bar/segment_progress_bar.dart +++ b/lib/common/widgets/progress_bar/segment_progress_bar.dart @@ -17,7 +17,9 @@ import 'dart:ui' as ui; -import 'package:flutter/foundation.dart' show listEquals, kDebugMode; +import 'package:PiliPlus/utils/extension/iterable_ext.dart'; +import 'package:collection/collection.dart'; +import 'package:flutter/foundation.dart' show listEquals; import 'package:flutter/gestures.dart' show TapGestureRecognizer; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart' show BoxHitTestEntry; @@ -223,6 +225,8 @@ class RenderViewPointProgressBar final canvas = context.canvas; final paint = Paint()..style = PaintingStyle.fill; + assert(segments.isSortedBy((i) => i.end)); + canvas.drawRect( Rect.fromLTRB(0, 0, size.width, _barHeight), paint..color = Colors.grey[600]!.withValues(alpha: 0.45), @@ -305,19 +309,16 @@ class RenderViewPointProgressBar } } + @pragma('vm:notify-debugger-on-exception') void _onTapUp(TapUpDetails details) { try { final seg = details.localPosition.dx / size.width; - final item = _segments - .where((item) => item.end >= seg) - .reduce((a, b) => a.end < b.end ? a : b); + final item = _segments[_segments.lowerBoundByKey((i) => i.end, seg)]; if (item.from case final from?) { _onSeek?.call(Duration(seconds: from)); } // if (kDebugMode) debugPrint('${item.title},,${item.from}'); - } catch (e) { - if (kDebugMode) rethrow; - } + } catch (_) {} } } diff --git a/lib/http/search.dart b/lib/http/search.dart index cbcf752ca..c458050eb 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -10,7 +10,6 @@ import 'package:PiliPlus/models_new/dynamic/dyn_topic_pub_search/data.dart'; import 'package:PiliPlus/models_new/pgc/pgc_info_model/result.dart'; import 'package:PiliPlus/models_new/search/search_rcmd/data.dart'; import 'package:PiliPlus/models_new/search/search_trending/data.dart'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/request_utils.dart'; import 'package:PiliPlus/utils/wbi_sign.dart'; import 'package:dio/dio.dart'; @@ -183,7 +182,8 @@ abstract final class SearchHttp { if (res.data['code'] == 0) { if (res.data['data'] case List list) { return part != null - ? (list.getOrNull(part - 1)?['cid'] ?? list.firstOrNull?['cid']) + ? (list.elementAtOrNull(part - 1)?['cid'] ?? + list.firstOrNull?['cid']) : list.firstOrNull?['cid']; } else { return null; diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart index 4301e8cab..b75f8a71c 100644 --- a/lib/pages/dynamics/controller.dart +++ b/lib/pages/dynamics/controller.dart @@ -10,7 +10,6 @@ import 'package:PiliPlus/pages/common/common_controller.dart'; import 'package:PiliPlus/pages/dynamics_tab/controller.dart'; import 'package:PiliPlus/services/account_service.dart'; import 'package:PiliPlus/utils/accounts.dart'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart'; import 'package:PiliPlus/utils/extension/string_ext.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; @@ -33,7 +32,7 @@ class DynamicsController extends GetxController LoadingState.loading().obs; late int _upPage = 1; late bool _upEnd = false; - List? _cacheUpList; + Set? _cacheUpList; late final _showAllUp = Pref.dynamicsShowAllFollowedUp; late bool showLiveUp = Pref.expandDynLivePanel; @@ -150,7 +149,7 @@ class DynamicsController extends GetxController final first = res.first; if (first case final Success i) { final data = i.response; - final second = res.getOrNull(1); + final second = res.elementAtOrNull(1); if (second case final Success j) { final data1 = j.response; final list1 = data1.list; @@ -161,8 +160,7 @@ class DynamicsController extends GetxController } final list = data.upList; - _cacheUpList = List.from(list); - list.addAll(list1..removeWhere(list.contains)); + list.addAll(list1..removeWhere((_cacheUpList = list.toSet()).contains)); } if (!_showAllUp) { if (data.hasMore == false || data.offset.isNullOrEmpty) { diff --git a/lib/pages/fav_sort/view.dart b/lib/pages/fav_sort/view.dart index e3ff614cc..cc61cddf7 100644 --- a/lib/pages/fav_sort/view.dart +++ b/lib/pages/fav_sort/view.dart @@ -3,7 +3,6 @@ import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models_new/fav/fav_detail/media.dart'; import 'package:PiliPlus/pages/fav_detail/controller.dart'; import 'package:PiliPlus/pages/fav_detail/widget/fav_video_card.dart'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -84,7 +83,7 @@ class _FavSortPageState extends State { } final oldItem = sortList[oldIndex]; - final newItem = sortList.getOrNull( + final newItem = sortList.elementAtOrNull( oldIndex > newIndex ? newIndex - 1 : newIndex, ); sort.add( diff --git a/lib/pages/member_profile/view.dart b/lib/pages/member_profile/view.dart index 7a3f7a146..ef508c5b2 100644 --- a/lib/pages/member_profile/view.dart +++ b/lib/pages/member_profile/view.dart @@ -15,7 +15,6 @@ import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/app_sign.dart'; import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/extension/file_ext.dart'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/extension/theme_ext.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/platform_utils.dart'; @@ -483,7 +482,7 @@ class _EditProfilePageState extends State { if (pickedFile != null && mounted) { String? mimeType = lookupMimeType( pickedFile.path, - )?.split('/').getOrNull(1); + )?.split('/').elementAtOrNull(1); if (mimeType == 'gif') { SmartDialog.showToast('不能选GIF'); return; diff --git a/lib/pages/whisper/widgets/item.dart b/lib/pages/whisper/widgets/item.dart index 048dc23b8..e22e101bd 100644 --- a/lib/pages/whisper/widgets/item.dart +++ b/lib/pages/whisper/widgets/item.dart @@ -9,7 +9,6 @@ import 'package:PiliPlus/grpc/bilibili/app/im/v1.pb.dart' import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/pages/whisper_secondary/view.dart'; import 'package:PiliPlus/utils/date_utils.dart'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/extension/num_ext.dart'; import 'package:PiliPlus/utils/extension/theme_ext.dart'; import 'package:PiliPlus/utils/page_utils.dart'; @@ -190,7 +189,7 @@ class WhisperSessionItem extends StatelessWidget { leading: Builder( builder: (context) { final pendant = item.sessionInfo.avatar.fallbackLayers.layers - .getOrNull(1) + .elementAtOrNull(1) ?.resource; final official = item .sessionInfo diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index 70bc69310..4afe1230d 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -16,7 +16,6 @@ import 'package:PiliPlus/pages/whisper_detail/controller.dart'; import 'package:PiliPlus/pages/whisper_detail/widget/chat_item.dart'; import 'package:PiliPlus/pages/whisper_link_setting/view.dart'; import 'package:PiliPlus/utils/extension/file_ext.dart'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/extension/num_ext.dart'; import 'package:PiliPlus/utils/extension/widget_ext.dart'; import 'package:PiliPlus/utils/feed_back.dart'; @@ -360,7 +359,9 @@ class _WhisperDetailPageState ); if (result case Success(:final response)) { final mimeType = - lookupMimeType(path)?.split('/').getOrNull(1) ?? + lookupMimeType( + path, + )?.split('/').elementAtOrNull(1) ?? 'jpg'; final picMsg = { 'url': response.imageUrl, diff --git a/lib/utils/accounts/account_type_adapter.dart b/lib/utils/accounts/account_type_adapter.dart index 328af3479..abe1b8aa4 100644 --- a/lib/utils/accounts/account_type_adapter.dart +++ b/lib/utils/accounts/account_type_adapter.dart @@ -1,5 +1,4 @@ import 'package:PiliPlus/models/common/account_type.dart'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:hive/hive.dart'; class AccountTypeAdapter extends TypeAdapter { @@ -8,7 +7,7 @@ class AccountTypeAdapter extends TypeAdapter { @override AccountType read(BinaryReader reader) => - AccountType.values.getOrNull(reader.readByte()) ?? AccountType.main; + AccountType.values.elementAtOrNull(reader.readByte()) ?? AccountType.main; @override void write(BinaryWriter writer, AccountType obj) { diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index 4758a0ea9..174a045d0 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -14,7 +14,6 @@ import 'package:PiliPlus/pages/live/view.dart'; import 'package:PiliPlus/pages/rank/view.dart'; import 'package:PiliPlus/pages/subscription_detail/view.dart'; import 'package:PiliPlus/pages/video/reply_reply/view.dart'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/request_utils.dart'; @@ -579,7 +578,7 @@ abstract final class PiliScheme { } final first = pathSegments.first; final String? area = const ['mobile', 'h5', 'v'].contains(first) - ? pathSegments.getOrNull(1) + ? pathSegments.elementAtOrNull(1) : first; // if (kDebugMode) debugPrint('area: $area'); switch (area) { diff --git a/lib/utils/cache_manager.dart b/lib/utils/cache_manager.dart index a8e327b1b..4dc29623c 100644 --- a/lib/utils/cache_manager.dart +++ b/lib/utils/cache_manager.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/platform_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:path_provider/path_provider.dart'; @@ -55,7 +54,7 @@ abstract final class CacheManager { value = value / 1024; } String size = value.toStringAsFixed(2); - return size + (unitArr.getOrNull(index) ?? ''); + return size + (unitArr.elementAtOrNull(index) ?? ''); } // 清除 Library/Caches 目录及文件缓存 diff --git a/lib/utils/extension/iterable_ext.dart b/lib/utils/extension/iterable_ext.dart index 08d35c167..d30844ac0 100644 --- a/lib/utils/extension/iterable_ext.dart +++ b/lib/utils/extension/iterable_ext.dart @@ -24,13 +24,6 @@ extension IterableExt on Iterable { } extension ListExt on List { - T? getOrNull(int index) { - if (index < 0 || index >= length) { - return null; - } - return this[index]; - } - bool removeFirstWhere(bool Function(T) test) { final index = indexWhere(test); if (index != -1) { @@ -50,4 +43,27 @@ extension ListExt on List { ) { return where(test).reduceOrNull(combine) ?? reduce(combine); } + + /// from [algorithms.lowerBoundBy]. + int lowerBoundByKey>( + K Function(T element) keyOf, + K key, [ + int start = 0, + int? end, + ]) { + end = RangeError.checkValidRange(start, end, length); + var min = start; + var max = end; + while (min < max) { + var mid = min + ((max - min) >> 1); + var element = this[mid]; + var comp = keyOf(element).compareTo(key); + if (comp < 0) { + min = mid + 1; + } else { + max = mid; + } + } + return min; + } } diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index c66079204..26abf286a 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -461,7 +461,7 @@ abstract final class Pref { SuperResolutionType? superResolutionType; final index = _setting.get(SettingBoxKey.superResolutionType); if (index != null) { - superResolutionType = SuperResolutionType.values.getOrNull(index); + superResolutionType = SuperResolutionType.values.elementAtOrNull(index); } return superResolutionType ?? SuperResolutionType.disable; }