diff --git a/lib/common/widgets/list_tile.dart b/lib/common/widgets/list_tile.dart index 22056f15b..6a31467c7 100644 --- a/lib/common/widgets/list_tile.dart +++ b/lib/common/widgets/list_tile.dart @@ -316,6 +316,7 @@ class ListTile extends StatelessWidget { /// Requires one of its ancestors to be a [Material] widget. const ListTile({ super.key, + this.safeArea = false, this.leading, this.title, this.subtitle, @@ -335,6 +336,7 @@ class ListTile extends StatelessWidget { this.enabled = true, this.onTap, this.onLongPress, + this.onSecondaryTap, this.onFocusChange, this.mouseCursor, this.selected = false, @@ -355,6 +357,8 @@ class ListTile extends StatelessWidget { this.statesController, }) : assert(isThreeLine != true || subtitle != null); + final bool safeArea; + /// A widget to display before the title. /// /// Typically an [Icon] or a [CircleAvatar] widget. @@ -563,6 +567,8 @@ class ListTile extends StatelessWidget { /// Inoperative if [enabled] is false. final GestureLongPressCallback? onLongPress; + final GestureTapCallback? onSecondaryTap; + /// {@macro flutter.material.inkwell.onFocusChange} final ValueChanged? onFocusChange; @@ -922,10 +928,64 @@ class ListTile extends StatelessWidget { ? ListTileTitleAlignment.threeLine : ListTileTitleAlignment.titleHeight); + Widget child = IconTheme.merge( + data: iconThemeData, + child: IconButtonTheme( + data: iconButtonThemeData, + child: _ListTile( + leading: leadingIcon, + title: titleText, + subtitle: subtitleText, + trailing: trailingIcon, + isDense: _isDenseLayout(theme, tileTheme), + visualDensity: + visualDensity ?? tileTheme.visualDensity ?? theme.visualDensity, + isThreeLine: + isThreeLine ?? + tileTheme.isThreeLine ?? + theme.listTileTheme.isThreeLine ?? + false, + textDirection: textDirection, + titleBaselineType: + titleStyle.textBaseline ?? defaults.titleTextStyle!.textBaseline!, + subtitleBaselineType: + subtitleStyle?.textBaseline ?? + defaults.subtitleTextStyle!.textBaseline!, + horizontalTitleGap: + horizontalTitleGap ?? tileTheme.horizontalTitleGap ?? 16, + minVerticalPadding: + minVerticalPadding ?? + tileTheme.minVerticalPadding ?? + defaults.minVerticalPadding!, + minLeadingWidth: + minLeadingWidth ?? + tileTheme.minLeadingWidth ?? + defaults.minLeadingWidth!, + minTileHeight: minTileHeight ?? tileTheme.minTileHeight, + titleAlignment: effectiveTitleAlignment, + ), + ), + ); + + if (safeArea) { + child = SafeArea( + top: false, + bottom: false, + minimum: resolvedContentPadding, + child: child, + ); + } else { + child = Padding( + padding: resolvedContentPadding, + child: child, + ); + } + return InkWell( customBorder: shape ?? tileTheme.shape, onTap: enabled ? onTap : null, onLongPress: enabled ? onLongPress : null, + onSecondaryTap: enabled ? onSecondaryTap : null, onFocusChange: onFocusChange, mouseCursor: effectiveMouseCursor, canRequestFocus: enabled, @@ -947,50 +1007,7 @@ class ListTile extends StatelessWidget { shape: shape ?? tileTheme.shape ?? const Border(), color: _tileBackgroundColor(theme, tileTheme, defaults), ), - child: Padding( - padding: resolvedContentPadding, - child: IconTheme.merge( - data: iconThemeData, - child: IconButtonTheme( - data: iconButtonThemeData, - child: _ListTile( - leading: leadingIcon, - title: titleText, - subtitle: subtitleText, - trailing: trailingIcon, - isDense: _isDenseLayout(theme, tileTheme), - visualDensity: - visualDensity ?? - tileTheme.visualDensity ?? - theme.visualDensity, - isThreeLine: - isThreeLine ?? - tileTheme.isThreeLine ?? - theme.listTileTheme.isThreeLine ?? - false, - textDirection: textDirection, - titleBaselineType: - titleStyle.textBaseline ?? - defaults.titleTextStyle!.textBaseline!, - subtitleBaselineType: - subtitleStyle?.textBaseline ?? - defaults.subtitleTextStyle!.textBaseline!, - horizontalTitleGap: - horizontalTitleGap ?? tileTheme.horizontalTitleGap ?? 16, - minVerticalPadding: - minVerticalPadding ?? - tileTheme.minVerticalPadding ?? - defaults.minVerticalPadding!, - minLeadingWidth: - minLeadingWidth ?? - tileTheme.minLeadingWidth ?? - defaults.minLeadingWidth!, - minTileHeight: minTileHeight ?? tileTheme.minTileHeight, - titleAlignment: effectiveTitleAlignment, - ), - ), - ), - ), + child: child, ), ), ); diff --git a/lib/pages/about/view.dart b/lib/pages/about/view.dart index f841bef87..f0887debd 100644 --- a/lib/pages/about/view.dart +++ b/lib/pages/about/view.dart @@ -138,6 +138,9 @@ class _AboutPageState extends State { ListTile( onTap: () => Update.checkUpdate(false), onLongPress: () => Utils.copyText(currentVersion), + onSecondaryTap: Utils.isMobile + ? null + : () => Utils.copyText(currentVersion), title: const Text('当前版本'), leading: const Icon(Icons.commit_outlined), trailing: Text( @@ -157,6 +160,9 @@ Commit Hash: ${BuildConfig.commitHash}''', '${Constants.sourceCodeUrl}/commit/${BuildConfig.commitHash}', ), onLongPress: () => Utils.copyText(BuildConfig.commitHash), + onSecondaryTap: Utils.isMobile + ? null + : () => Utils.copyText(BuildConfig.commitHash), ), Divider( thickness: 1, @@ -194,6 +200,7 @@ Commit Hash: ${BuildConfig.commitHash}''', ListTile( onTap: () => Get.toNamed('/logs'), onLongPress: LoggerUtils.clearLogs, + onSecondaryTap: Utils.isMobile ? null : LoggerUtils.clearLogs, leading: const Icon(Icons.bug_report_outlined), title: const Text('错误日志'), subtitle: Text('长按清除日志', style: subTitleStyle), diff --git a/lib/pages/episode_panel/view.dart b/lib/pages/episode_panel/view.dart index 3873f4966..172b10714 100644 --- a/lib/pages/episode_panel/view.dart +++ b/lib/pages/episode_panel/view.dart @@ -29,6 +29,7 @@ import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart' hide TabBarView; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -414,6 +415,12 @@ class _EpisodePanelState extends State } late final Color primary = theme.colorScheme.primary; + void onLongPress() { + if (cover?.isNotEmpty == true) { + imageSaveDialog(title: title, cover: cover, bvid: bvid); + } + } + return Padding( padding: const EdgeInsets.only(bottom: 2), child: SizedBox( @@ -450,11 +457,8 @@ class _EpisodePanelState extends State } }); }, - onLongPress: () { - if (cover?.isNotEmpty == true) { - imageSaveDialog(title: title, cover: cover, bvid: bvid); - } - }, + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index 48d140990..91b120a8e 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -12,6 +12,7 @@ import 'package:PiliPlus/pages/fav_detail/controller.dart'; import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -35,6 +36,21 @@ class FavVideoCardH extends StatelessWidget { final isOwner = !isSort && ctr!.isOwner; late final enableMultiSelect = ctr?.enableMultiSelect.value ?? false; final theme = Theme.of(context); + + final onLongPress = isSort || enableMultiSelect + ? null + : isOwner && !enableMultiSelect + ? () { + ctr! + ..enableMultiSelect.value = true + ..onSelect(item); + } + : () => imageSaveDialog( + title: item.title, + cover: item.cover, + bvid: item.bvid, + ); + return Material( type: MaterialType.transparency, child: InkWell( @@ -59,19 +75,8 @@ class FavVideoCardH extends StatelessWidget { ctr!.onViewFav(item, index); }, - onLongPress: isSort || enableMultiSelect - ? null - : isOwner && !enableMultiSelect - ? () { - ctr! - ..enableMultiSelect.value = true - ..onSelect(item); - } - : () => imageSaveDialog( - title: item.title, - cover: item.cover, - bvid: item.bvid, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index f5a4ac350..7080fa14e 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -12,6 +12,7 @@ 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'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -37,6 +38,13 @@ class HistoryItem extends StatelessWidget { String bvid = item.history.bvid ?? IdUtils.av2bv(aid); final business = item.history.business; final enableMultiSelect = ctr.enableMultiSelect.value; + + final onLongPress = enableMultiSelect + ? null + : () => ctr + ..enableMultiSelect.value = true + ..onSelect(item); + return Material( type: MaterialType.transparency, child: InkWell( @@ -88,11 +96,8 @@ class HistoryItem extends StatelessWidget { } } }, - onLongPress: enableMultiSelect - ? null - : () => ctr - ..enableMultiSelect.value = true - ..onSelect(item), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Stack( clipBehavior: Clip.none, children: [ diff --git a/lib/pages/later/widgets/video_card_h_later.dart b/lib/pages/later/widgets/video_card_h_later.dart index 0aa60fe09..8307e913a 100644 --- a/lib/pages/later/widgets/video_card_h_later.dart +++ b/lib/pages/later/widgets/video_card_h_later.dart @@ -13,6 +13,7 @@ import 'package:PiliPlus/models_new/later/list.dart'; import 'package:PiliPlus/pages/later/controller.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -41,14 +42,18 @@ class VideoCardHLater extends StatelessWidget { } final theme = Theme.of(context); final enableMultiSelect = ctr.enableMultiSelect.value; + + final onLongPress = enableMultiSelect + ? null + : () => ctr + ..enableMultiSelect.value = true + ..onSelect(videoItem); + return Material( type: MaterialType.transparency, child: InkWell( - onLongPress: enableMultiSelect - ? null - : () => ctr - ..enableMultiSelect.value = true - ..onSelect(videoItem), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, onTap: enableMultiSelect ? () => ctr.onSelect(videoItem) : () async { diff --git a/lib/pages/live/widgets/live_item_app.dart b/lib/pages/live/widgets/live_item_app.dart index 2b6e135e3..056410336 100644 --- a/lib/pages/live/widgets/live_item_app.dart +++ b/lib/pages/live/widgets/live_item_app.dart @@ -4,6 +4,7 @@ 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_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -17,14 +18,16 @@ class LiveCardVApp extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Card( clipBehavior: Clip.hardEdge, child: InkWell( onTap: () => PageUtils.toLiveRoom(item.roomid), - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Column( children: [ AspectRatio( diff --git a/lib/pages/live_follow/widgets/live_item_follow.dart b/lib/pages/live_follow/widgets/live_item_follow.dart index b84b93999..b61d70f3d 100644 --- a/lib/pages/live_follow/widgets/live_item_follow.dart +++ b/lib/pages/live_follow/widgets/live_item_follow.dart @@ -3,6 +3,7 @@ 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_follow/item.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -16,14 +17,16 @@ class LiveCardVFollow extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: liveItem.title, + cover: liveItem.roomCover, + ); return Card( clipBehavior: Clip.hardEdge, child: InkWell( onTap: () => PageUtils.toLiveRoom(liveItem.roomid), - onLongPress: () => imageSaveDialog( - title: liveItem.title, - cover: liveItem.roomCover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Column( children: [ AspectRatio( diff --git a/lib/pages/live_search/widgets/live_search_room.dart b/lib/pages/live_search/widgets/live_search_room.dart index 9bef3b7cd..fb56a9e6a 100644 --- a/lib/pages/live_search/widgets/live_search_room.dart +++ b/lib/pages/live_search/widgets/live_search_room.dart @@ -4,6 +4,7 @@ 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_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -17,14 +18,16 @@ class LiveCardVSearch extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Card( clipBehavior: Clip.hardEdge, child: InkWell( onTap: () => PageUtils.toLiveRoom(item.roomid), - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/member_article/widget/item.dart b/lib/pages/member_article/widget/item.dart index 64191242f..46db260a9 100644 --- a/lib/pages/member_article/widget/item.dart +++ b/lib/pages/member_article/widget/item.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/stat/stat.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/space/space_article/item.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; class MemberArticleItem extends StatelessWidget { @@ -16,6 +17,10 @@ class MemberArticleItem extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); final outline = theme.colorScheme.outline; + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.originImageUrls?.firstOrNull, + ); return Material( type: MaterialType.transparency, child: InkWell( @@ -24,10 +29,8 @@ class MemberArticleItem extends StatelessWidget { PiliScheme.routePushFromUrl(item.uri!); } }, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.originImageUrls?.firstOrNull, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/member_audio/widgets/item.dart b/lib/pages/member_audio/widgets/item.dart index 6d2094310..3f85e2168 100644 --- a/lib/pages/member_audio/widgets/item.dart +++ b/lib/pages/member_audio/widgets/item.dart @@ -7,6 +7,7 @@ import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/space/space_audio/item.dart'; import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -19,6 +20,7 @@ class MemberAudioItem extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); final hasStat = item.statistic != null; + void onLongPress() => imageSaveDialog(title: item.title, cover: item.cover); return Material( type: MaterialType.transparency, child: InkWell( @@ -35,8 +37,8 @@ class MemberAudioItem extends StatelessWidget { SmartDialog.showToast('没有MV'); return; }, - onLongPress: () => - imageSaveDialog(title: item.title, cover: item.cover), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/member_cheese/widgets/item.dart b/lib/pages/member_cheese/widgets/item.dart index 3408f8463..4f34aeae1 100644 --- a/lib/pages/member_cheese/widgets/item.dart +++ b/lib/pages/member_cheese/widgets/item.dart @@ -6,6 +6,7 @@ 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_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; class MemberCheeseItem extends StatelessWidget { @@ -72,12 +73,13 @@ class MemberCheeseItem extends StatelessWidget { ], ); } + void onLongPress() => imageSaveDialog(title: item.title, cover: item.cover); return Material( type: MaterialType.transparency, child: InkWell( onTap: () => PageUtils.viewPugv(seasonId: item.seasonId), - onLongPress: () => - imageSaveDialog(title: item.title, cover: item.cover), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/member_coin_arc/widgets/item.dart b/lib/pages/member_coin_arc/widgets/item.dart index 82ee3b2bb..06b92bbf1 100644 --- a/lib/pages/member_coin_arc/widgets/item.dart +++ b/lib/pages/member_coin_arc/widgets/item.dart @@ -11,6 +11,7 @@ import 'package:PiliPlus/models_new/member/coin_like_arc/item.dart'; import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; class MemberCoinLikeItem extends StatelessWidget { @@ -23,6 +24,11 @@ class MemberCoinLikeItem extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + aid: item.param, + ); return Card( clipBehavior: Clip.hardEdge, child: InkWell( @@ -46,11 +52,8 @@ class MemberCoinLikeItem extends StatelessWidget { } } }, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - aid: item.param, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/member_comic/widgets/item.dart b/lib/pages/member_comic/widgets/item.dart index 1655d83da..c20687083 100644 --- a/lib/pages/member_comic/widgets/item.dart +++ b/lib/pages/member_comic/widgets/item.dart @@ -2,6 +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/space/space_archive/item.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -17,6 +18,7 @@ class MemberComicItem extends StatelessWidget { fontSize: 13, color: theme.colorScheme.onSurfaceVariant, ); + void onLongPress() => imageSaveDialog(title: item.title, cover: item.cover); return Material( type: MaterialType.transparency, child: InkWell( @@ -28,8 +30,8 @@ class MemberComicItem extends StatelessWidget { }, ); }, - onLongPress: () => - imageSaveDialog(title: item.title, cover: item.cover), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/member_favorite/widget/item.dart b/lib/pages/member_favorite/widget/item.dart index 4b8dc8de6..20795f408 100644 --- a/lib/pages/member_favorite/widget/item.dart +++ b/lib/pages/member_favorite/widget/item.dart @@ -19,6 +19,10 @@ class MemberFavItem extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Material( type: MaterialType.transparency, child: InkWell( @@ -44,10 +48,8 @@ class MemberFavItem extends StatelessWidget { ); } }, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/member_home/widgets/fav_item.dart b/lib/pages/member_home/widgets/fav_item.dart index 836da834a..c11c84799 100644 --- a/lib/pages/member_home/widgets/fav_item.dart +++ b/lib/pages/member_home/widgets/fav_item.dart @@ -13,6 +13,10 @@ class MemberFavItem extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Material( type: MaterialType.transparency, child: InkWell( @@ -25,10 +29,8 @@ class MemberFavItem extends StatelessWidget { }, ); }, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, 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 b71f4182d..c7a56a0e5 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 @@ -9,6 +9,7 @@ import 'package:PiliPlus/utils/app_scheme.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'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -62,16 +63,18 @@ class VideoCardVMemberHome extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: videoItem.title, + cover: videoItem.cover, + aid: videoItem.param, + bvid: videoItem.bvid, + ); return Card( clipBehavior: Clip.hardEdge, child: InkWell( onTap: onPushDetail, - onLongPress: () => imageSaveDialog( - title: videoItem.title, - cover: videoItem.cover, - aid: videoItem.param, - bvid: videoItem.bvid, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/member_pgc/widgets/pgc_card_v_member_pgc.dart b/lib/pages/member_pgc/widgets/pgc_card_v_member_pgc.dart index 6134f4083..52abde0f9 100644 --- a/lib/pages/member_pgc/widgets/pgc_card_v_member_pgc.dart +++ b/lib/pages/member_pgc/widgets/pgc_card_v_member_pgc.dart @@ -3,6 +3,7 @@ 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_archive/item.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -16,15 +17,17 @@ class PgcCardVMemberPgc extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Card( shape: const RoundedRectangleBorder(borderRadius: StyleString.mdRadius), child: InkWell( borderRadius: StyleString.mdRadius, onTap: () => PageUtils.viewPgc(seasonId: item.param), - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ 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 db9a81486..79058be8a 100644 --- a/lib/pages/member_season_series/widget/season_series_card.dart +++ b/lib/pages/member_season_series/widget/season_series_card.dart @@ -4,6 +4,7 @@ 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_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; class SeasonSeriesCard extends StatelessWidget { @@ -17,13 +18,15 @@ class SeasonSeriesCard extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.meta!.name, + cover: item.meta!.cover, + ); return Material( type: MaterialType.transparency, child: InkWell( - onLongPress: () => imageSaveDialog( - title: item.meta!.name, - cover: item.meta!.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric( 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 3967eda0b..9dcc1c902 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 @@ -11,6 +11,7 @@ import 'package:PiliPlus/models_new/space/space_archive/item.dart'; import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -31,17 +32,19 @@ class VideoCardHMemberVideo extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); + void onLongPress() => imageSaveDialog( + title: videoItem.title, + cover: videoItem.cover, + bvid: videoItem.bvid, + ); return Material( type: MaterialType.transparency, child: Stack( clipBehavior: Clip.none, children: [ InkWell( - onLongPress: () => imageSaveDialog( - title: videoItem.title, - cover: videoItem.cover, - bvid: videoItem.bvid, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, onTap: onTap ?? () async { diff --git a/lib/pages/msg_feed_top/at_me/view.dart b/lib/pages/msg_feed_top/at_me/view.dart index 04295a36d..abc6bf931 100644 --- a/lib/pages/msg_feed_top/at_me/view.dart +++ b/lib/pages/msg_feed_top/at_me/view.dart @@ -1,6 +1,7 @@ import 'package:PiliPlus/common/skeleton/msg_feed_top.dart'; import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/common/widgets/list_tile.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/grpc/bilibili/app/im/v1.pbenum.dart' @@ -12,7 +13,8 @@ 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_utils.dart'; -import 'package:flutter/material.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart' hide ListTile; import 'package:get/get.dart'; class AtMePage extends StatefulWidget { @@ -91,7 +93,13 @@ class _AtMePageState extends State { _atMeController.onLoadMore(); } final item = response[index]; + void onLongPress() => showConfirmDialog( + context: context, + title: '确定删除该通知?', + onConfirm: () => _atMeController.onRemove(item.id, index), + ); return ListTile( + safeArea: true, onTap: () { String? nativeUri = item.item?.nativeUri; if (nativeUri == null || @@ -101,11 +109,8 @@ class _AtMePageState extends State { } PiliScheme.routePushFromUrl(nativeUri); }, - onLongPress: () => showConfirmDialog( - context: context, - title: '确定删除该通知?', - onConfirm: () => _atMeController.onRemove(item.id, index), - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, leading: GestureDetector( onTap: () => Get.toNamed('/member?mid=${item.user?.mid}'), child: NetworkImgLayer( diff --git a/lib/pages/msg_feed_top/like_me/view.dart b/lib/pages/msg_feed_top/like_me/view.dart index b754cc364..382e78617 100644 --- a/lib/pages/msg_feed_top/like_me/view.dart +++ b/lib/pages/msg_feed_top/like_me/view.dart @@ -1,6 +1,7 @@ import 'package:PiliPlus/common/skeleton/msg_feed_top.dart'; import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/common/widgets/list_tile.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/pair.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; @@ -13,7 +14,8 @@ 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_utils.dart'; -import 'package:flutter/material.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart' hide ListTile; import 'package:get/get.dart'; class LikeMePage extends StatefulWidget { @@ -162,7 +164,60 @@ class _LikeMePageState extends State { MsgLikeItem item, ValueChanged onRemove, ) { + void onLongPress() => showDialog( + context: context, + builder: (context) { + final isNotice = item.noticeState == 0; + return AlertDialog( + clipBehavior: Clip.hardEdge, + contentPadding: const EdgeInsets.symmetric(vertical: 12), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + onTap: () { + Get.back(); + showConfirmDialog( + context: context, + title: '删除', + content: '该条通知删除后,当有新点赞时会重新出现在列表,是否继续?', + onConfirm: () => onRemove(item.id), + ); + }, + dense: true, + title: const Text( + '删除', + style: TextStyle(fontSize: 14), + ), + ), + ListTile( + onTap: () { + Get.back(); + if (isNotice) { + showConfirmDialog( + context: context, + title: '不再通知', + content: '这条内容的点赞将不再通知,但仍可在列表内查看,是否继续?', + onConfirm: () => + _likeMeController.onSetNotice(item, isNotice), + ); + } else { + _likeMeController.onSetNotice(item, isNotice); + } + }, + dense: true, + title: Text( + isNotice ? '不再通知' : '接收通知', + style: const TextStyle(fontSize: 14), + ), + ), + ], + ), + ); + }, + ); return ListTile( + safeArea: true, onTap: () { String? nativeUri = item.item?.nativeUri; bool isInvalid = @@ -183,58 +238,8 @@ class _LikeMePageState extends State { } PiliScheme.routePushFromUrl(nativeUri); }, - onLongPress: () => showDialog( - context: context, - builder: (context) { - final isNotice = item.noticeState == 0; - return AlertDialog( - clipBehavior: Clip.hardEdge, - contentPadding: const EdgeInsets.symmetric(vertical: 12), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - onTap: () { - Get.back(); - showConfirmDialog( - context: context, - title: '删除', - content: '该条通知删除后,当有新点赞时会重新出现在列表,是否继续?', - onConfirm: () => onRemove(item.id), - ); - }, - dense: true, - title: const Text( - '删除', - style: TextStyle(fontSize: 14), - ), - ), - ListTile( - onTap: () { - Get.back(); - if (isNotice) { - showConfirmDialog( - context: context, - title: '不再通知', - content: '这条内容的点赞将不再通知,但仍可在列表内查看,是否继续?', - onConfirm: () => - _likeMeController.onSetNotice(item, isNotice), - ); - } else { - _likeMeController.onSetNotice(item, isNotice); - } - }, - dense: true, - title: Text( - isNotice ? '不再通知' : '接收通知', - style: const TextStyle(fontSize: 14), - ), - ), - ], - ), - ); - }, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, leading: Column( children: [ const Spacer(), diff --git a/lib/pages/msg_feed_top/reply_me/view.dart b/lib/pages/msg_feed_top/reply_me/view.dart index 5aa325750..9f6fe6a02 100644 --- a/lib/pages/msg_feed_top/reply_me/view.dart +++ b/lib/pages/msg_feed_top/reply_me/view.dart @@ -1,6 +1,7 @@ import 'package:PiliPlus/common/skeleton/msg_feed_top.dart'; import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/common/widgets/list_tile.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/grpc/bilibili/app/im/v1.pbenum.dart' @@ -12,7 +13,8 @@ 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_utils.dart'; -import 'package:flutter/material.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart' hide ListTile; import 'package:get/get.dart'; class ReplyMePage extends StatefulWidget { @@ -92,7 +94,16 @@ class _ReplyMePageState extends State { } MsgReplyItem item = response[index]; + + void onLongPress() => showConfirmDialog( + context: context, + title: '确定删除该通知?', + onConfirm: () => + _replyMeController.onRemove(item.id, index), + ); + return ListTile( + safeArea: true, onTap: () { String? nativeUri = item.item?.nativeUri; if (nativeUri == null || @@ -106,12 +117,8 @@ class _ReplyMePageState extends State { oid: item.item?.subjectId, ); }, - onLongPress: () => showConfirmDialog( - context: context, - title: '确定删除该通知?', - onConfirm: () => - _replyMeController.onRemove(item.id, index), - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, leading: GestureDetector( onTap: () => Get.toNamed('/member?mid=${item.user?.mid}'), child: NetworkImgLayer( diff --git a/lib/pages/msg_feed_top/sys_msg/view.dart b/lib/pages/msg_feed_top/sys_msg/view.dart index 71669eef4..c6c41f255 100644 --- a/lib/pages/msg_feed_top/sys_msg/view.dart +++ b/lib/pages/msg_feed_top/sys_msg/view.dart @@ -1,5 +1,6 @@ import 'package:PiliPlus/common/skeleton/msg_feed_sys_msg_.dart'; import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; +import 'package:PiliPlus/common/widgets/list_tile.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; @@ -10,7 +11,7 @@ import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide ListTile; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -78,13 +79,15 @@ class _SysMsgPageState extends State { _sysMsgController.onLoadMore(); } final item = response[index]; + void onLongPress() => showConfirmDialog( + context: context, + title: '确定删除该通知?', + onConfirm: () => _sysMsgController.onRemove(item.id, index), + ); return ListTile( - onLongPress: () => showConfirmDialog( - context: context, - title: '确定删除该通知?', - onConfirm: () => - _sysMsgController.onRemove(item.id, index), - ), + safeArea: true, + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, title: Text( "${item.title}", style: theme.textTheme.titleMedium, diff --git a/lib/pages/music/widget/music_video_card_h.dart b/lib/pages/music/widget/music_video_card_h.dart index f3ab4b0bd..7dd602f0b 100644 --- a/lib/pages/music/widget/music_video_card_h.dart +++ b/lib/pages/music/widget/music_video_card_h.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/music/bgm_recommend_list.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; class MusicVideoCardH extends StatelessWidget { @@ -22,6 +23,11 @@ class MusicVideoCardH extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: videoItem.title, + cover: videoItem.cover, + bvid: videoItem.bvid, + ); return Material( type: MaterialType.transparency, child: InkWell( @@ -37,11 +43,8 @@ class MusicVideoCardH extends StatelessWidget { ); } }, - onLongPress: () => imageSaveDialog( - title: videoItem.title, - cover: videoItem.cover, - bvid: videoItem.bvid, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/pgc/widgets/pgc_card_v.dart b/lib/pages/pgc/widgets/pgc_card_v.dart index 99f26c016..34d88d951 100644 --- a/lib/pages/pgc/widgets/pgc_card_v.dart +++ b/lib/pages/pgc/widgets/pgc_card_v.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models_new/fav/fav_pgc/list.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -18,14 +19,16 @@ class PgcCardV extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Card( shape: const RoundedRectangleBorder(borderRadius: StyleString.mdRadius), child: InkWell( borderRadius: StyleString.mdRadius, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, onTap: () => PageUtils.viewPgc(seasonId: item.seasonId), child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/pages/pgc/widgets/pgc_card_v_timeline.dart b/lib/pages/pgc/widgets/pgc_card_v_timeline.dart index 91c54866b..effaba8c3 100644 --- a/lib/pages/pgc/widgets/pgc_card_v_timeline.dart +++ b/lib/pages/pgc/widgets/pgc_card_v_timeline.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models_new/pgc/pgc_timeline/episode.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -18,14 +19,16 @@ class PgcCardVTimeline extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Card( shape: const RoundedRectangleBorder(borderRadius: StyleString.mdRadius), child: InkWell( borderRadius: StyleString.mdRadius, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, onTap: () => PageUtils.viewPgc(seasonId: item.seasonId, epId: item.episodeId), child: Column( diff --git a/lib/pages/pgc_index/widgets/pgc_card_v_pgc_index.dart b/lib/pages/pgc_index/widgets/pgc_card_v_pgc_index.dart index 2b974e028..a6ceec9b2 100644 --- a/lib/pages/pgc_index/widgets/pgc_card_v_pgc_index.dart +++ b/lib/pages/pgc_index/widgets/pgc_card_v_pgc_index.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models_new/pgc/pgc_index_result/list.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -18,15 +19,17 @@ class PgcCardVPgcIndex extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Card( shape: const RoundedRectangleBorder(borderRadius: StyleString.mdRadius), child: InkWell( borderRadius: StyleString.mdRadius, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), onTap: () => PageUtils.viewPgc(seasonId: item.seasonId), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/rank/zone/widget/pgc_rank_item.dart b/lib/pages/rank/zone/widget/pgc_rank_item.dart index 183b6d9aa..d56bc490b 100644 --- a/lib/pages/rank/zone/widget/pgc_rank_item.dart +++ b/lib/pages/rank/zone/widget/pgc_rank_item.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/stat/stat.dart'; import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models_new/pgc/pgc_rank/pgc_rank_item_model.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; class PgcRankItem extends StatelessWidget { @@ -14,6 +15,10 @@ class PgcRankItem extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Material( type: MaterialType.transparency, child: InkWell( @@ -22,10 +27,8 @@ class PgcRankItem extends StatelessWidget { PiliScheme.routePushFromUrl(item.url!); } }, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/search_panel/all/widgets/pgc_card_v_search.dart b/lib/pages/search_panel/all/widgets/pgc_card_v_search.dart index 74522720b..ad0172753 100644 --- a/lib/pages/search_panel/all/widgets/pgc_card_v_search.dart +++ b/lib/pages/search_panel/all/widgets/pgc_card_v_search.dart @@ -4,6 +4,7 @@ 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/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 视频卡片 - 垂直布局 @@ -17,14 +18,16 @@ class PgcCardVSearch extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: item.title.map((e) => e.text).join(), + cover: item.cover, + ); return Card( shape: const RoundedRectangleBorder(borderRadius: StyleString.mdRadius), child: InkWell( borderRadius: StyleString.mdRadius, - onLongPress: () => imageSaveDialog( - title: item.title.map((e) => e.text).join(), - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, onTap: () => PageUtils.viewPgc(seasonId: item.seasonId), child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/pages/search_panel/article/widgets/item.dart b/lib/pages/search_panel/article/widgets/item.dart index 471e6df8b..7fa43db6e 100644 --- a/lib/pages/search_panel/article/widgets/item.dart +++ b/lib/pages/search_panel/article/widgets/item.dart @@ -3,6 +3,7 @@ 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_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -18,6 +19,10 @@ class SearchArticleItem extends StatelessWidget { fontSize: theme.textTheme.labelSmall!.fontSize, color: theme.colorScheme.outline, ); + void onLongPress() => imageSaveDialog( + title: item.title.map((item) => item.text).join(), + cover: item.imageUrls?.firstOrNull, + ); return Material( type: MaterialType.transparency, child: InkWell( @@ -28,10 +33,8 @@ class SearchArticleItem extends StatelessWidget { 'type': 'read', }, ), - onLongPress: () => imageSaveDialog( - title: item.title.map((item) => item.text).join(), - cover: item.imageUrls?.firstOrNull, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/search_panel/live/widgets/item.dart b/lib/pages/search_panel/live/widgets/item.dart index f3b8235f2..ec7a9b714 100644 --- a/lib/pages/search_panel/live/widgets/item.dart +++ b/lib/pages/search_panel/live/widgets/item.dart @@ -3,6 +3,7 @@ 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/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; class LiveItem extends StatelessWidget { @@ -13,14 +14,16 @@ class LiveItem extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); + void onLongPress() => imageSaveDialog( + title: liveItem.title.map((item) => item.text).join(), + cover: liveItem.cover, + ); return Card( clipBehavior: Clip.hardEdge, child: InkWell( onTap: () => PageUtils.toLiveRoom(liveItem.roomid), - onLongPress: () => imageSaveDialog( - title: liveItem.title.map((item) => item.text).join(), - cover: liveItem.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/pages/search_panel/pgc/widgets/item.dart b/lib/pages/search_panel/pgc/widgets/item.dart index a8ceb4cb4..75a7e8f39 100644 --- a/lib/pages/search_panel/pgc/widgets/item.dart +++ b/lib/pages/search_panel/pgc/widgets/item.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; class SearchPgcItem extends StatelessWidget { @@ -19,14 +20,16 @@ class SearchPgcItem extends StatelessWidget { Widget build(BuildContext context) { final ThemeData theme = Theme.of(context); const TextStyle style = TextStyle(fontSize: 13); + void onLongPress() => imageSaveDialog( + title: item.title.map((item) => item.text).join(), + cover: item.cover, + ); return Material( type: MaterialType.transparency, child: InkWell( onTap: () => PageUtils.viewPgc(seasonId: item.seasonId), - onLongPress: () => imageSaveDialog( - title: item.title.map((item) => item.text).join(), - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/subscription/widgets/item.dart b/lib/pages/subscription/widgets/item.dart index 58111fa29..1cccaad3d 100644 --- a/lib/pages/subscription/widgets/item.dart +++ b/lib/pages/subscription/widgets/item.dart @@ -26,6 +26,10 @@ class SubItem extends StatelessWidget { 21 => '合集', _ => '其它(${item.type})', }; + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + ); return Material( type: MaterialType.transparency, child: InkWell( @@ -50,10 +54,8 @@ class SubItem extends StatelessWidget { ); } }, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), child: Row( diff --git a/lib/pages/subscription_detail/widget/sub_video_card.dart b/lib/pages/subscription_detail/widget/sub_video_card.dart index ab3ac06c0..b0efa48cd 100644 --- a/lib/pages/subscription_detail/widget/sub_video_card.dart +++ b/lib/pages/subscription_detail/widget/sub_video_card.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/models_new/sub/sub_detail/media.dart'; import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; // 收藏视频卡片 - 水平布局 @@ -25,6 +26,11 @@ class SubVideoCardH extends StatelessWidget { @override Widget build(BuildContext context) { + void onLongPress() => imageSaveDialog( + title: videoItem.title, + cover: videoItem.cover, + bvid: videoItem.bvid, + ); return Material( type: MaterialType.transparency, child: InkWell( @@ -39,11 +45,8 @@ class SubVideoCardH extends StatelessWidget { ); } }, - onLongPress: () => imageSaveDialog( - title: videoItem.title, - cover: videoItem.cover, - bvid: videoItem.bvid, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/video/medialist/view.dart b/lib/pages/video/medialist/view.dart index dd12d07fb..f4aba57f5 100644 --- a/lib/pages/video/medialist/view.dart +++ b/lib/pages/video/medialist/view.dart @@ -11,6 +11,7 @@ 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_slide_page.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart' hide RefreshCallback; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -154,6 +155,12 @@ class _MediaListPanelState extends State bool isCurr, bool showDelBtn, ) { + void onLongPress() => imageSaveDialog( + title: item.title, + cover: item.cover, + aid: item.aid, + bvid: item.bvid, + ); return Padding( padding: const EdgeInsets.only(bottom: 2), child: SizedBox( @@ -169,12 +176,8 @@ class _MediaListPanelState extends State Get.back(); widget.onChangeEpisode(item); }, - onLongPress: () => imageSaveDialog( - title: item.title, - cover: item.cover, - aid: item.aid, - bvid: item.bvid, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Stack( clipBehavior: Clip.none, children: [ 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 758f7c4ec..f0fe37e2b 100644 --- a/lib/pages/video/reply_search_item/child/widgets/item.dart +++ b/lib/pages/video/reply_search_item/child/widgets/item.dart @@ -7,6 +7,7 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/reply/reply_search_type.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -47,14 +48,16 @@ class ReplySearchItem extends StatelessWidget { cover = article.covers.firstOrNull ?? ''; upNickname = article.upNickname; } + void onLongPress() => imageSaveDialog( + title: title, + cover: cover, + ); return Material( type: MaterialType.transparency, child: InkWell( onTap: () => Get.back(result: (title: title, url: item.url)), - onLongPress: () => imageSaveDialog( - title: title, - cover: cover, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, child: Padding( padding: const EdgeInsets.symmetric( horizontal: StyleString.safeSpace, diff --git a/lib/pages/whisper/widgets/item.dart b/lib/pages/whisper/widgets/item.dart index c90e692a3..ba1dcb2d5 100644 --- a/lib/pages/whisper/widgets/item.dart +++ b/lib/pages/whisper/widgets/item.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:PiliPlus/common/widgets/badge.dart'; import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; +import 'package:PiliPlus/common/widgets/list_tile.dart'; import 'package:PiliPlus/common/widgets/pendant_avatar.dart'; import 'package:PiliPlus/grpc/bilibili/app/im/v1.pb.dart' show Session, SessionId, SessionPageType, SessionType, UnreadStyle; @@ -9,8 +10,9 @@ 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.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:fixnum/fixnum.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide ListTile; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -41,60 +43,65 @@ class WhisperSessionItem extends StatelessWidget { ? jsonDecode(item.sessionInfo.vipInfo) : null; final ThemeData theme = Theme.of(context); + + void onLongPress() => showDialog( + context: context, + builder: (context) { + return AlertDialog( + clipBehavior: Clip.hardEdge, + contentPadding: const EdgeInsets.symmetric(vertical: 12), + content: DefaultTextStyle( + style: const TextStyle(fontSize: 14), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + dense: true, + onTap: () { + Get.back(); + onSetTop(item.isPinned, item.id); + }, + title: Text(item.isPinned ? '移除置顶' : '置顶'), + ), + if (item.id.privateId.hasTalkerUid()) + ListTile( + dense: true, + onTap: () { + Get.back(); + onSetMute(item.isMuted, item.id.privateId.talkerUid); + }, + title: Text('${item.isMuted ? '关闭' : '开启'}免打扰'), + ), + if (item.id.privateId.hasTalkerUid()) + ListTile( + dense: true, + onTap: () { + Get.back(); + showConfirmDialog( + context: context, + title: '确定删除该对话?', + onConfirm: () => + onRemove(item.id.privateId.talkerUid.toInt()), + ); + }, + title: const Text('删除'), + ), + ], + ), + ), + ); + }, + ); + return ListTile( + safeArea: true, tileColor: item.isPinned ? theme.colorScheme.onInverseSurface.withValues( alpha: Get.isDarkMode ? 0.4 : 0.8, ) : null, - onLongPress: () => showDialog( - context: context, - builder: (context) { - return AlertDialog( - clipBehavior: Clip.hardEdge, - contentPadding: const EdgeInsets.symmetric(vertical: 12), - content: DefaultTextStyle( - style: const TextStyle(fontSize: 14), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - dense: true, - onTap: () { - Get.back(); - onSetTop(item.isPinned, item.id); - }, - title: Text(item.isPinned ? '移除置顶' : '置顶'), - ), - if (item.id.privateId.hasTalkerUid()) - ListTile( - dense: true, - onTap: () { - Get.back(); - onSetMute(item.isMuted, item.id.privateId.talkerUid); - }, - title: Text('${item.isMuted ? '关闭' : '开启'}免打扰'), - ), - if (item.id.privateId.hasTalkerUid()) - ListTile( - dense: true, - onTap: () { - Get.back(); - showConfirmDialog( - context: context, - title: '确定删除该对话?', - onConfirm: () => - onRemove(item.id.privateId.talkerUid.toInt()), - ); - }, - title: const Text('删除'), - ), - ], - ), - ), - ); - }, - ), + onLongPress: onLongPress, + onSecondaryTap: Utils.isMobile ? null : onLongPress, onTap: () { if (item.hasUnread()) { item.clearUnread();