opt mouse control

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-09-28 15:33:09 +08:00
parent 2031604ea2
commit 5f8dc76891
19 changed files with 268 additions and 191 deletions

View File

@@ -270,6 +270,7 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
itemCount: widget.sources.length, itemCount: widget.sources.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
final item = widget.sources[index]; final item = widget.sources[index];
final isFileImg = item.sourceType == SourceType.fileImage;
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () => EasyThrottle.throttle( onTap: () => EasyThrottle.throttle(
@@ -285,9 +286,12 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
const Duration(milliseconds: 555), const Duration(milliseconds: 555),
onDoubleTap, onDoubleTap,
), ),
onLongPress: item.sourceType == SourceType.fileImage onLongPress: !isFileImg && Utils.isMobile
? null ? () => onLongPress(item)
: () => onLongPress(item), : null,
onSecondaryTap: !isFileImg && !Utils.isMobile
? () => onLongPress(item)
: null,
child: widget.itemBuilder != null child: widget.itemBuilder != null
? widget.itemBuilder!( ? widget.itemBuilder!(
context, context,

View File

@@ -67,6 +67,11 @@ class VideoCardV extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
void onLongPress() => imageSaveDialog(
title: videoItem.title,
cover: videoItem.cover,
bvid: videoItem.bvid,
);
return Stack( return Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
@@ -74,11 +79,8 @@ class VideoCardV extends StatelessWidget {
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
child: InkWell( child: InkWell(
onTap: () => onPushDetail(Utils.makeHeroTag(videoItem.aid)), onTap: () => onPushDetail(Utils.makeHeroTag(videoItem.aid)),
onLongPress: () => imageSaveDialog( onLongPress: Utils.isMobile ? onLongPress : null,
title: videoItem.title, onSecondaryTap: Utils.isMobile ? null : onLongPress,
cover: videoItem.cover,
bvid: videoItem.bvid,
),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [

View File

@@ -107,7 +107,8 @@ abstract class CommonRichTextPubPageState<T extends CommonRichTextPubPage>
); );
controller.restoreChatPanel(); controller.restoreChatPanel();
}, },
onLongPress: onClear, onLongPress: Utils.isMobile ? onClear : null,
onSecondaryTap: Utils.isMobile ? null : onClear,
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(4)), borderRadius: const BorderRadius.all(Radius.circular(4)),
child: Image( child: Image(

View File

@@ -5,6 +5,7 @@ import 'package:PiliPlus/pages/dynamics/widgets/action_panel.dart';
import 'package:PiliPlus/pages/dynamics/widgets/author_panel.dart'; import 'package:PiliPlus/pages/dynamics/widgets/author_panel.dart';
import 'package:PiliPlus/pages/dynamics/widgets/dyn_content.dart'; import 'package:PiliPlus/pages/dynamics/widgets/dyn_content.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart' hide InkWell; import 'package:flutter/material.dart' hide InkWell;
class DynamicPanel extends StatelessWidget { class DynamicPanel extends StatelessWidget {
@@ -45,6 +46,9 @@ class DynamicPanel extends StatelessWidget {
onSetTop: onSetTop, onSetTop: onSetTop,
onBlock: onBlock, onBlock: onBlock,
); );
void showMore() => _imageSaveDialog(context, authorWidget.morePanel);
final child = Material( final child = Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: InkWell( child: InkWell(
@@ -62,7 +66,8 @@ class DynamicPanel extends StatelessWidget {
}.contains(item.type) }.contains(item.type)
? null ? null
: () => PageUtils.pushDynDetail(item), : () => PageUtils.pushDynDetail(item),
onLongPress: () => _imageSaveDialog(context, authorWidget.morePanel), onLongPress: Utils.isMobile ? showMore : null,
onSecondaryTap: Utils.isMobile ? null : showMore,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

View File

@@ -5,6 +5,7 @@ import 'package:PiliPlus/pages/dynamics/widgets/dyn_content.dart';
import 'package:PiliPlus/pages/dynamics/widgets/module_panel.dart'; import 'package:PiliPlus/pages/dynamics/widgets/module_panel.dart';
import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/date_utils.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart' hide InkWell; import 'package:flutter/material.dart' hide InkWell;
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -59,44 +60,47 @@ Widget forwardPanel(
return child; return child;
} }
void showMore() {
String? title, cover, bvid;
switch (orig.type) {
case 'DYNAMIC_TYPE_AV':
title = major?.archive?.title;
cover = major?.archive?.cover;
bvid = major?.archive?.bvid;
break;
case 'DYNAMIC_TYPE_UGC_SEASON':
title = major?.ugcSeason?.title;
cover = major?.ugcSeason?.cover;
bvid = major?.ugcSeason?.bvid;
break;
case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
title = major?.pgc?.title;
cover = major?.pgc?.cover;
break;
case 'DYNAMIC_TYPE_LIVE_RCMD':
title = major?.liveRcmd?.title;
cover = major?.liveRcmd?.cover;
break;
case 'DYNAMIC_TYPE_LIVE':
title = major?.live?.title;
cover = major?.live?.cover;
break;
default:
return;
}
if (cover != null) {
imageSaveDialog(
title: title,
cover: cover,
bvid: bvid,
);
}
}
return InkWell( return InkWell(
onTap: () => PageUtils.pushDynDetail(orig), onTap: () => PageUtils.pushDynDetail(orig),
onLongPress: () { onLongPress: Utils.isMobile ? showMore : null,
String? title, cover, bvid; onSecondaryTap: Utils.isMobile ? null : showMore,
switch (orig.type) {
case 'DYNAMIC_TYPE_AV':
title = major?.archive?.title;
cover = major?.archive?.cover;
bvid = major?.archive?.bvid;
break;
case 'DYNAMIC_TYPE_UGC_SEASON':
title = major?.ugcSeason?.title;
cover = major?.ugcSeason?.cover;
bvid = major?.ugcSeason?.bvid;
break;
case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
title = major?.pgc?.title;
cover = major?.pgc?.cover;
break;
case 'DYNAMIC_TYPE_LIVE_RCMD':
title = major?.liveRcmd?.title;
cover = major?.liveRcmd?.cover;
break;
case 'DYNAMIC_TYPE_LIVE':
title = major?.live?.title;
cover = major?.live?.cover;
break;
default:
return;
}
if (cover != null) {
imageSaveDialog(
title: title,
cover: cover,
bvid: bvid,
);
}
},
child: child, child: child,
); );
} }

View File

@@ -7,6 +7,7 @@ import 'package:PiliPlus/pages/dynamics/controller.dart';
import 'package:PiliPlus/pages/live_follow/view.dart'; import 'package:PiliPlus/pages/live_follow/view.dart';
import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/feed_back.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart' hide InkWell; import 'package:flutter/material.dart' hide InkWell;
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -25,6 +26,8 @@ class _UpPanelState extends State<UpPanel> {
late final controller = widget.dynamicsController; late final controller = widget.dynamicsController;
late final isTop = controller.upPanelPosition == UpPanelPosition.top; late final isTop = controller.upPanelPosition == UpPanelPosition.top;
void toFollowPage() => Get.to(const LiveFollowPage());
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final accountService = controller.accountService; final accountService = controller.accountService;
@@ -45,7 +48,8 @@ class _UpPanelState extends State<UpPanel> {
onTap: () => setState(() { onTap: () => setState(() {
controller.showLiveUp = !controller.showLiveUp; controller.showLiveUp = !controller.showLiveUp;
}), }),
onLongPress: () => Get.to(const LiveFollowPage()), onLongPress: Utils.isMobile ? toFollowPage : null,
onSecondaryTap: Utils.isMobile ? null : toFollowPage,
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
height: isTop ? 76 : 60, height: isTop ? 76 : 60,
@@ -138,6 +142,10 @@ class _UpPanelState extends State<UpPanel> {
final currentMid = controller.currentMid; final currentMid = controller.currentMid;
final isLive = data is LiveUserItem; final isLive = data is LiveUserItem;
bool isCurrent = isLive || currentMid == data.mid || currentMid == -1; bool isCurrent = isLive || currentMid == data.mid || currentMid == -1;
final isAll = data.mid == -1;
void toMemberPage() => Get.toNamed('/member?mid=${data.mid}');
return SizedBox( return SizedBox(
height: 76, height: 76,
width: isTop ? 70 : null, width: isTop ? 70 : null,
@@ -153,9 +161,8 @@ class _UpPanelState extends State<UpPanel> {
} }
}, },
// onDoubleTap: isLive ? () => _onSelect(data) : null, // onDoubleTap: isLive ? () => _onSelect(data) : null,
onLongPress: data.mid == -1 onLongPress: !isAll && Utils.isMobile ? toMemberPage : null,
? null onSecondaryTap: !isAll && !Utils.isMobile ? toMemberPage : null,
: () => Get.toNamed('/member?mid=${data.mid}'),
child: AnimatedOpacity( child: AnimatedOpacity(
opacity: isCurrent ? 1 : 0.6, opacity: isCurrent ? 1 : 0.6,
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),

View File

@@ -111,6 +111,14 @@ class _FansPageState extends State<FansPage> {
} }
Widget _buildItem(ColorScheme theme, int index, FansItemModel item) { Widget _buildItem(ColorScheme theme, int index, FansItemModel item) {
final isSelect = widget.onSelect != null;
void onRemove() => showConfirmDialog(
context: context,
title: '确定移除 ${item.uname} ',
onConfirm: () => _fansController.onRemoveFan(index, item.mid!),
);
final flag = !isSelect && isOwner;
return SizedBox( return SizedBox(
height: 66, height: 66,
child: InkWell( child: InkWell(
@@ -127,15 +135,8 @@ class _FansPageState extends State<FansPage> {
} }
Get.toNamed('/member?mid=${item.mid}'); Get.toNamed('/member?mid=${item.mid}');
}, },
onLongPress: widget.onSelect != null onLongPress: flag && Utils.isMobile ? onRemove : null,
? null onSecondaryTap: flag && !Utils.isMobile ? onRemove : null,
: isOwner
? () => showConfirmDialog(
context: context,
title: '确定移除 ${item.uname} ',
onConfirm: () => _fansController.onRemoveFan(index, item.mid!),
)
: null,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 12, horizontal: 12,

View File

@@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/select_mask.dart';
import 'package:PiliPlus/models_new/fav/fav_note/list.dart'; import 'package:PiliPlus/models_new/fav/fav_note/list.dart';
import 'package:PiliPlus/pages/fav/note/controller.dart'; import 'package:PiliPlus/pages/fav/note/controller.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class FavNoteItem extends StatelessWidget { class FavNoteItem extends StatelessWidget {
@@ -18,6 +19,13 @@ class FavNoteItem extends StatelessWidget {
final FavNoteController ctr; final FavNoteController ctr;
final VoidCallback onSelect; final VoidCallback onSelect;
void onLongPress() {
if (!ctr.enableMultiSelect.value) {
ctr.enableMultiSelect.value = true;
onSelect();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
@@ -36,12 +44,8 @@ class FavNoteItem extends StatelessWidget {
); );
} }
}, },
onLongPress: () { onLongPress: Utils.isMobile ? onLongPress : null,
if (!ctr.enableMultiSelect.value) { onSecondaryTap: Utils.isMobile ? null : onLongPress,
ctr.enableMultiSelect.value = true;
onSelect();
}
},
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: StyleString.safeSpace, horizontal: StyleString.safeSpace,

View File

@@ -7,6 +7,7 @@ import 'package:PiliPlus/models/common/badge_type.dart';
import 'package:PiliPlus/models_new/fav/fav_pgc/list.dart'; import 'package:PiliPlus/models_new/fav/fav_pgc/list.dart';
import 'package:PiliPlus/pages/common/multi_select/base.dart'; import 'package:PiliPlus/pages/common/multi_select/base.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class FavPgcItem extends StatelessWidget { class FavPgcItem extends StatelessWidget {
@@ -23,6 +24,13 @@ class FavPgcItem extends StatelessWidget {
final VoidCallback onSelect; final VoidCallback onSelect;
final VoidCallback onUpdateStatus; final VoidCallback onUpdateStatus;
void onLongPress() {
if (!ctr.enableMultiSelect.value) {
ctr.enableMultiSelect.value = true;
onSelect();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
@@ -39,12 +47,8 @@ class FavPgcItem extends StatelessWidget {
} }
PageUtils.viewPgc(seasonId: item.seasonId); PageUtils.viewPgc(seasonId: item.seasonId);
}, },
onLongPress: () { onLongPress: Utils.isMobile ? onLongPress : null,
if (!ctr.enableMultiSelect.value) { onSecondaryTap: Utils.isMobile ? null : onLongPress,
ctr.enableMultiSelect.value = true;
onSelect();
}
},
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: StyleString.safeSpace, horizontal: StyleString.safeSpace,

View File

@@ -6,6 +6,7 @@ import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models_new/fav/fav_topic/topic_item.dart'; import 'package:PiliPlus/models_new/fav/fav_topic/topic_item.dart';
import 'package:PiliPlus/pages/fav/topic/controller.dart'; import 'package:PiliPlus/pages/fav/topic/controller.dart';
import 'package:PiliPlus/utils/grid.dart'; import 'package:PiliPlus/utils/grid.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -78,6 +79,13 @@ class _FavTopicPageState extends State<FavTopicPage>
_controller.onLoadMore(); _controller.onLoadMore();
} }
final item = response[index]; final item = response[index];
void onLongPress() => showConfirmDialog(
context: context,
title: '确定取消收藏?',
onConfirm: () => _controller.onRemove(index, item.id),
);
return Material( return Material(
color: theme.colorScheme.onInverseSurface, color: theme.colorScheme.onInverseSurface,
borderRadius: const BorderRadius.all(Radius.circular(6)), borderRadius: const BorderRadius.all(Radius.circular(6)),
@@ -89,13 +97,8 @@ class _FavTopicPageState extends State<FavTopicPage>
'name': item.name!, 'name': item.name!,
}, },
), ),
onLongPress: () => showConfirmDialog( onLongPress: Utils.isMobile ? onLongPress : null,
context: context, onSecondaryTap: Utils.isMobile ? null : onLongPress,
title: '确定取消收藏?',
onConfirm: () {
_controller.onRemove(index, item.id);
},
),
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(
Radius.circular(6), Radius.circular(6),
), ),

View File

@@ -106,10 +106,15 @@ class _FollowPageState extends State<FollowPage> {
if (_isCustomTag(item.tagid)) { if (_isCustomTag(item.tagid)) {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onLongPress: () { onLongPress: Utils.isMobile
Feedback.forLongPress(context); ? () {
_onHandleTag(index, item); Feedback.forLongPress(context);
}, _onHandleTag(index, item);
}
: null,
onSecondaryTap: Utils.isMobile
? null
: () => _onHandleTag(index, item),
child: Tab( child: Tab(
child: Row( child: Row(
children: [ children: [

View File

@@ -18,6 +18,7 @@ import 'package:PiliPlus/pages/live_follow/view.dart';
import 'package:PiliPlus/pages/search/widgets/search_text.dart'; import 'package:PiliPlus/pages/search/widgets/search_text.dart';
import 'package:PiliPlus/utils/grid.dart'; import 'package:PiliPlus/utils/grid.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -287,10 +288,15 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () => PageUtils.toLiveRoom(item.roomid), onTap: () => PageUtils.toLiveRoom(item.roomid),
onLongPress: () { onLongPress: Utils.isMobile
Feedback.forLongPress(context); ? () {
Get.toNamed('/member?mid=${item.uid}'); Feedback.forLongPress(context);
}, Get.toNamed('/member?mid=${item.uid}');
}
: null,
onSecondaryTap: Utils.isMobile
? null
: () => Get.toNamed('/member?mid=${item.uid}'),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [

View File

@@ -223,10 +223,15 @@ class _MediaPageState extends CommonPageState<MinePage, MineController>
GestureDetector( GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: controller.onLogin, onTap: controller.onLogin,
onLongPress: () { onLongPress: Utils.isMobile
Feedback.forLongPress(context); ? () {
controller.onLogin(true); Feedback.forLongPress(context);
}, controller.onLogin(true);
}
: null,
onSecondaryTap: Utils.isMobile
? null
: () => controller.onLogin(true),
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [

View File

@@ -14,6 +14,7 @@ import 'package:PiliPlus/pages/pgc_review/post/view.dart';
import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/num_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -108,6 +109,76 @@ class _PgcReviewChildPageState extends State<PgcReviewChildPage>
} }
Widget _itemWidget(ThemeData theme, int index, PgcReviewItemModel item) { Widget _itemWidget(ThemeData theme, int index, PgcReviewItemModel item) {
void showMore() => showDialog(
context: context,
builder: (context) => AlertDialog(
clipBehavior: Clip.hardEdge,
contentPadding: const EdgeInsets.symmetric(vertical: 12),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (item.author!.mid == Accounts.main.mid) ...[
ListTile(
dense: true,
title: const Text(
'编辑',
style: TextStyle(fontSize: 14),
),
onTap: () {
Get.back();
showModalBottomSheet(
context: context,
useSafeArea: true,
isScrollControlled: true,
builder: (context) {
return PgcReviewPostPanel(
name: widget.name,
mediaId: widget.mediaId,
reviewId: item.reviewId,
content: item.content,
score: item.score,
);
},
);
},
),
ListTile(
dense: true,
title: const Text(
'删除',
style: TextStyle(fontSize: 14),
),
onTap: () {
Get.back();
showConfirmDialog(
context: context,
title: '删除短评,同时删除评分?',
onConfirm: () => _controller.onDel(index, item.reviewId),
);
},
),
],
ListTile(
dense: true,
title: const Text(
'举报',
style: TextStyle(fontSize: 14),
),
onTap: () => Get
..back()
..toNamed(
'/webview',
parameters: {
'url':
'https://www.bilibili.com/appeal/?reviewId=${item.reviewId}&type=shortComment&mediaId=${widget.mediaId}',
},
),
),
],
),
),
);
return Material( return Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: InkWell( child: InkWell(
@@ -120,78 +191,8 @@ class _PgcReviewChildPageState extends State<PgcReviewChildPage>
}, },
) )
: null, : null,
onLongPress: isLongReview onLongPress: !isLongReview && Utils.isMobile ? showMore : null,
? null onSecondaryTap: !isLongReview && !Utils.isMobile ? showMore : null,
: () => showDialog(
context: context,
builder: (context) => AlertDialog(
clipBehavior: Clip.hardEdge,
contentPadding: const EdgeInsets.symmetric(vertical: 12),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (item.author!.mid == Accounts.main.mid) ...[
ListTile(
dense: true,
title: const Text(
'编辑',
style: TextStyle(fontSize: 14),
),
onTap: () {
Get.back();
showModalBottomSheet(
context: context,
useSafeArea: true,
isScrollControlled: true,
builder: (context) {
return PgcReviewPostPanel(
name: widget.name,
mediaId: widget.mediaId,
reviewId: item.reviewId,
content: item.content,
score: item.score,
);
},
);
},
),
ListTile(
dense: true,
title: const Text(
'删除',
style: TextStyle(fontSize: 14),
),
onTap: () {
Get.back();
showConfirmDialog(
context: context,
title: '删除短评,同时删除评分?',
onConfirm: () =>
_controller.onDel(index, item.reviewId),
);
},
),
],
ListTile(
dense: true,
title: const Text(
'举报',
style: TextStyle(fontSize: 14),
),
onTap: () => Get
..back()
..toNamed(
'/webview',
parameters: {
'url':
'https://www.bilibili.com/appeal/?reviewId=${item.reviewId}&type=shortComment&mediaId=${widget.mediaId}',
},
),
),
],
),
),
),
child: Padding( child: Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Column( child: Column(

View File

@@ -1,3 +1,4 @@
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SearchText extends StatelessWidget { class SearchText extends StatelessWidget {
@@ -25,12 +26,18 @@ class SearchText extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
late final colorScheme = Theme.of(context).colorScheme; late final colorScheme = Theme.of(context).colorScheme;
final hasLongPress = onLongPress != null;
return Material( return Material(
color: bgColor ?? colorScheme.onInverseSurface, color: bgColor ?? colorScheme.onInverseSurface,
borderRadius: const BorderRadius.all(Radius.circular(6)), borderRadius: const BorderRadius.all(Radius.circular(6)),
child: InkWell( child: InkWell(
onTap: () => onTap?.call(text), onTap: () => onTap?.call(text),
onLongPress: onLongPress != null ? () => onLongPress!(text) : null, onLongPress: hasLongPress && Utils.isMobile
? () => onLongPress!(text)
: null,
onSecondaryTap: hasLongPress && !Utils.isMobile
? () => onLongPress!(text)
: null,
borderRadius: const BorderRadius.all(Radius.circular(6)), borderRadius: const BorderRadius.all(Radius.circular(6)),
child: Padding( child: Padding(
padding: padding:

View File

@@ -78,6 +78,25 @@ class ReplyItemGrpc extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
final isMobile = Utils.isMobile;
void showMore() => showModalBottomSheet(
context: context,
useSafeArea: true,
isScrollControlled: true,
constraints: BoxConstraints(
maxWidth: min(640, context.mediaQueryShortestSide),
),
builder: (context) {
return morePanel(
context: context,
item: replyItem,
onDelete: () => onDelete?.call(replyItem, null),
isSubReply: false,
);
},
);
return Material( return Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: InkWell( child: InkWell(
@@ -85,25 +104,13 @@ class ReplyItemGrpc extends StatelessWidget {
feedBack(); feedBack();
replyReply?.call(replyItem, null); replyReply?.call(replyItem, null);
}, },
onLongPress: () { onLongPress: isMobile
feedBack(); ? () {
showModalBottomSheet( feedBack();
context: context, showMore();
useSafeArea: true, }
isScrollControlled: true, : null,
constraints: BoxConstraints( onSecondaryTap: isMobile ? null : showMore,
maxWidth: min(640, context.mediaQueryShortestSide),
),
builder: (context) {
return morePanel(
context: context,
item: replyItem,
onDelete: () => onDelete?.call(replyItem, null),
isSubReply: false,
);
},
);
},
child: _buildContent(context, theme), child: _buildContent(context, theme),
), ),
); );

View File

@@ -16,6 +16,7 @@ import 'package:PiliPlus/utils/duration_utils.dart';
import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/image_utils.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -83,12 +84,13 @@ class ChatItem extends StatelessWidget {
textColor: textColor, textColor: textColor,
) )
: GestureDetector( : GestureDetector(
onLongPress: onLongPress == null onLongPress: onLongPress != null && Utils.isMobile
? null ? () {
: () {
Feedback.forLongPress(context); Feedback.forLongPress(context);
onLongPress!(); onLongPress!();
}, }
: null,
onSecondaryTap: !Utils.isMobile ? onLongPress : null,
child: Row( child: Row(
mainAxisAlignment: isOwner mainAxisAlignment: isOwner
? MainAxisAlignment.end ? MainAxisAlignment.end

View File

@@ -411,11 +411,17 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
), ),
), ),
onTap: widget.showViewPoints, onTap: widget.showViewPoints,
onLongPress: () { onLongPress: Utils.isMobile
Feedback.forLongPress(context); ? () {
videoDetailController.showVP.value = Feedback.forLongPress(context);
!videoDetailController.showVP.value; videoDetailController.showVP.value =
}, !videoDetailController.showVP.value;
}
: null,
onSecondaryTap: Utils.isMobile
? null
: () => videoDetailController.showVP.value =
!videoDetailController.showVP.value,
), ),
), ),

View File

@@ -4,6 +4,7 @@ class ComBtn extends StatelessWidget {
final Widget icon; final Widget icon;
final VoidCallback? onTap; final VoidCallback? onTap;
final VoidCallback? onLongPress; final VoidCallback? onLongPress;
final VoidCallback? onSecondaryTap;
final double width; final double width;
final double height; final double height;
final String? tooltip; final String? tooltip;
@@ -13,6 +14,7 @@ class ComBtn extends StatelessWidget {
required this.icon, required this.icon,
this.onTap, this.onTap,
this.onLongPress, this.onLongPress,
this.onSecondaryTap,
this.width = 34, this.width = 34,
this.height = 34, this.height = 34,
this.tooltip, this.tooltip,
@@ -26,6 +28,7 @@ class ComBtn extends StatelessWidget {
child: GestureDetector( child: GestureDetector(
onTap: onTap, onTap: onTap,
onLongPress: onLongPress, onLongPress: onLongPress,
onSecondaryTap: onSecondaryTap,
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: icon, child: icon,
), ),