🐛 Fix context menu mis placed on device which showing the side navigation

This commit is contained in:
LittleSheep 2024-12-24 23:07:47 +08:00
parent 06dd3e092a
commit 4d96a15c31
7 changed files with 178 additions and 126 deletions

View File

@ -173,7 +173,7 @@ PODS:
- in_app_review (2.0.0): - in_app_review (2.0.0):
- Flutter - Flutter
- Kingfisher (8.1.3) - Kingfisher (8.1.3)
- livekit_client (2.3.2): - livekit_client (2.3.3):
- Flutter - Flutter
- flutter_webrtc - flutter_webrtc
- WebRTC-SDK (= 125.6422.06) - WebRTC-SDK (= 125.6422.06)
@ -386,7 +386,7 @@ SPEC CHECKSUMS:
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
in_app_review: a31b5257259646ea78e0e35fc914979b0031d011 in_app_review: a31b5257259646ea78e0e35fc914979b0031d011
Kingfisher: f2af9028b16baf9dc6c07c570072bc41cbf009ef Kingfisher: f2af9028b16baf9dc6c07c570072bc41cbf009ef
livekit_client: 6108dad8b77db3142bafd4c630f471d0a54335cd livekit_client: 02cf2cc4357a655af12ccee70ff5596ae4e6feef
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e

View File

@ -10,6 +10,7 @@ import 'package:surface/providers/userinfo.dart';
import 'package:surface/types/chat.dart'; import 'package:surface/types/chat.dart';
import 'package:surface/widgets/account/account_image.dart'; import 'package:surface/widgets/account/account_image.dart';
import 'package:surface/widgets/attachment/attachment_list.dart'; import 'package:surface/widgets/attachment/attachment_list.dart';
import 'package:surface/widgets/context_menu.dart';
import 'package:surface/widgets/link_preview.dart'; import 'package:surface/widgets/link_preview.dart';
import 'package:surface/widgets/markdown_content.dart'; import 'package:surface/widgets/markdown_content.dart';
import 'package:swipe_to/swipe_to.dart'; import 'package:swipe_to/swipe_to.dart';
@ -53,7 +54,7 @@ class ChatMessage extends StatelessWidget {
swipeSensitivity: 20, swipeSensitivity: 20,
onLeftSwipe: onReply != null ? (_) => onReply!(data) : null, onLeftSwipe: onReply != null ? (_) => onReply!(data) : null,
onRightSwipe: onEdit != null ? (_) => onEdit!(data) : null, onRightSwipe: onEdit != null ? (_) => onEdit!(data) : null,
child: ContextMenuRegion( child: ContextMenuArea(
contextMenu: ContextMenu( contextMenu: ContextMenu(
entries: [ entries: [
MenuHeader(text: "eventResourceTag".tr(args: ['#${data.id}'])), MenuHeader(text: "eventResourceTag".tr(args: ['#${data.id}'])),

View File

@ -0,0 +1,47 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:flutter_context_menu/flutter_context_menu.dart';
import 'package:responsive_framework/responsive_framework.dart';
class ContextMenuArea extends StatelessWidget {
final ContextMenu contextMenu;
final Widget child;
final ValueChanged<dynamic>? onItemSelected;
const ContextMenuArea({
super.key,
required this.contextMenu,
required this.child,
this.onItemSelected,
});
@override
Widget build(BuildContext context) {
Offset mousePosition = Offset.zero;
return Listener(
onPointerDown: (event) {
mousePosition = event.position;
final isCollapseDrawer = ResponsiveBreakpoints.of(context).smallerOrEqualTo(MOBILE);
if (!isCollapseDrawer) {
final isExpandDrawer = ResponsiveBreakpoints.of(context).largerThan(TABLET);
// Leave padding for side navigation
mousePosition = isExpandDrawer
? mousePosition.copyWith(dx: mousePosition.dx - 304 * 2)
: mousePosition.copyWith(dx: mousePosition.dx - 72 * 2);
}
},
child: GestureDetector(
onLongPress: () => _showMenu(context, mousePosition),
onSecondaryTap: () => _showMenu(context, mousePosition),
child: child,
),
);
}
void _showMenu(BuildContext context, Offset mousePosition) async {
final menu = contextMenu.copyWith(position: contextMenu.position ?? mousePosition);
final value = await showContextMenu(context, contextMenu: menu);
onItemSelected?.call(value);
}
}

View File

@ -14,6 +14,7 @@ import 'package:styled_widget/styled_widget.dart';
import 'package:surface/controllers/post_write_controller.dart'; import 'package:surface/controllers/post_write_controller.dart';
import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/sn_network.dart';
import 'package:surface/widgets/attachment/attachment_zoom.dart'; import 'package:surface/widgets/attachment/attachment_zoom.dart';
import 'package:surface/widgets/context_menu.dart';
import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/dialog.dart';
class PostMediaPendingList extends StatelessWidget { class PostMediaPendingList extends StatelessWidget {
@ -87,7 +88,7 @@ class PostMediaPendingList extends StatelessWidget {
} }
} }
ContextMenu _buildContextMenu(BuildContext context, int idx, PostWriteMedia media) { ContextMenu _createContextMenu(BuildContext context, int idx, PostWriteMedia media) {
return ContextMenu( return ContextMenu(
entries: [ entries: [
if (media.attachment == null && onUpload != null) if (media.attachment == null && onUpload != null)
@ -174,8 +175,8 @@ class PostMediaPendingList extends StatelessWidget {
children: [ children: [
const Gap(8), const Gap(8),
if (thumbnail != null) if (thumbnail != null)
ContextMenuRegion( ContextMenuArea(
contextMenu: _buildContextMenu(context, -1, thumbnail!), contextMenu: _createContextMenu(context, -1, thumbnail!),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( border: Border.all(
@ -224,8 +225,8 @@ class PostMediaPendingList extends StatelessWidget {
itemCount: attachments.length, itemCount: attachments.length,
itemBuilder: (context, idx) { itemBuilder: (context, idx) {
final media = attachments[idx]; final media = attachments[idx];
return ContextMenuRegion( return ContextMenuArea(
contextMenu: _buildContextMenu(context, idx, media), contextMenu: _createContextMenu(context, idx, media),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( border: Border.all(

View File

@ -753,10 +753,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_udid name: flutter_udid
sha256: be464dc5b1fb7ee894f6a32d65c086ca5e177fdcf9375ac08d77495b98150f84 sha256: "166bee5989a58c66b8b62000ea65edccc7c8167bbafdbb08022638db330dd030"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "4.0.0"
flutter_web_plugins: flutter_web_plugins:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -766,10 +766,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_webrtc name: flutter_webrtc
sha256: "430859fb5b763d7556d06ef287cfca582e17d9a2dc36da26017f25a5c0b2523e" sha256: "0e138a0a3bf6830c29c8439b17be0e222d0de27fa72f24e6aee4d34de72f22ef"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.4" version: "0.12.5"
freezed: freezed:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -934,10 +934,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image_picker_android name: image_picker_android
sha256: fa8141602fde3f7e2f81dbf043613eb44dfa325fa0bcf93c0f142c9f7a2c193e sha256: aa6f1280b670861ac45220cc95adc59bb6ae130259d36f980ccb62220dc5e59f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.12+18" version: "0.8.12+19"
image_picker_for_web: image_picker_for_web:
dependency: transitive dependency: transitive
description: description:
@ -1086,10 +1086,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: livekit_client name: livekit_client
sha256: "7802b5de1cae2ee3439db730d24d31c6dcbce173c5e6db2fc5774039a290bc2d" sha256: a3ff529fe6745ee40cdedcd021d81c4a6ad946dd495e782596f2856eeeabc739
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.3.3"
logging: logging:
dependency: transitive dependency: transitive
description: description:

View File

@ -80,7 +80,7 @@ dependencies:
firebase_core: ^3.8.0 firebase_core: ^3.8.0
firebase_messaging: ^15.1.5 firebase_messaging: ^15.1.5
firebase_analytics: ^11.3.5 firebase_analytics: ^11.3.5
flutter_udid: ^3.0.0 flutter_udid: ^4.0.0
media_kit: ^1.1.11 media_kit: ^1.1.11
media_kit_video: ^1.2.5 media_kit_video: ^1.2.5
media_kit_libs_video: ^1.0.5 media_kit_libs_video: ^1.0.5

View File

@ -1,4 +1,6 @@
<!DOCTYPE html><html><head> <!DOCTYPE html>
<html lang="en" oncontextmenu="event.preventDefault();">
<head>
<!-- <!--
If you are serving your web app in a path other than the root, change the If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from. href value below to reflect the base path you are serving from.
@ -31,9 +33,8 @@
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
name="viewport">
<style id="splash-screen-style"> <style id="splash-screen-style">
@ -110,21 +111,23 @@
</head> </head>
<body> <body>
<picture id="splash-branding"> <picture id="splash-branding">
<source srcset="splash/img/branding-1x.png 1x, splash/img/branding-2x.png 2x, splash/img/branding-3x.png 3x, splash/img/branding-4x.png 4x" media="(prefers-color-scheme: light)"> <source srcset="splash/img/branding-1x.png 1x, splash/img/branding-2x.png 2x, splash/img/branding-3x.png 3x, splash/img/branding-4x.png 4x"
<source srcset="splash/img/branding-dark-1x.png 1x, splash/img/branding-dark-2x.png 2x, splash/img/branding-dark-3x.png 3x, splash/img/branding-dark-4x.png 4x" media="(prefers-color-scheme: dark)"> media="(prefers-color-scheme: light)">
<source srcset="splash/img/branding-dark-1x.png 1x, splash/img/branding-dark-2x.png 2x, splash/img/branding-dark-3x.png 3x, splash/img/branding-dark-4x.png 4x"
media="(prefers-color-scheme: dark)">
<img class="bottom" aria-hidden="true" src="splash/img/branding-1x.png" alt=""> <img class="bottom" aria-hidden="true" src="splash/img/branding-1x.png" alt="">
</picture> </picture>
<picture id="splash"> <picture id="splash">
<source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x" media="(prefers-color-scheme: light)"> <source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x"
<source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x" media="(prefers-color-scheme: dark)"> media="(prefers-color-scheme: light)">
<source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x"
media="(prefers-color-scheme: dark)">
<img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt=""> <img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt="">
</picture> </picture>
<script src="flutter_bootstrap.js" async=""></script> <script src="flutter_bootstrap.js" async=""></script>
</body></html> </body>
</html>