🐛 Fix context menu mis placed on device which showing the side navigation
This commit is contained in:
parent
06dd3e092a
commit
4d96a15c31
@ -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
|
||||||
|
@ -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}'])),
|
||||||
|
47
lib/widgets/context_menu.dart
Normal file
47
lib/widgets/context_menu.dart
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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(
|
||||||
|
16
pubspec.lock
16
pubspec.lock
@ -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:
|
||||||
|
@ -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
|
||||||
|
221
web/index.html
221
web/index.html
@ -1,130 +1,133 @@
|
|||||||
<!DOCTYPE html><html><head>
|
<!DOCTYPE html>
|
||||||
<!--
|
<html lang="en" oncontextmenu="event.preventDefault();">
|
||||||
If you are serving your web app in a path other than the root, change the
|
<head>
|
||||||
href value below to reflect the base path you are serving from.
|
<!--
|
||||||
|
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.
|
||||||
|
|
||||||
The path provided below has to start and end with a slash "/" in order for
|
The path provided below has to start and end with a slash "/" in order for
|
||||||
it to work correctly.
|
it to work correctly.
|
||||||
|
|
||||||
For more details:
|
For more details:
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||||
|
|
||||||
This is a placeholder for base href that will be replaced by the value of
|
This is a placeholder for base href that will be replaced by the value of
|
||||||
the `--base-href` argument provided to `flutter build`.
|
the `--base-href` argument provided to `flutter build`.
|
||||||
-->
|
-->
|
||||||
<base href="$FLUTTER_BASE_HREF">
|
<base href="$FLUTTER_BASE_HREF">
|
||||||
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||||
<meta name="description" content="A new Flutter project.">
|
<meta name="description" content="A new Flutter project.">
|
||||||
|
|
||||||
<!-- iOS meta tags & icons -->
|
<!-- iOS meta tags & icons -->
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
<meta name="apple-mobile-web-app-title" content="surface">
|
<meta name="apple-mobile-web-app-title" content="surface">
|
||||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||||
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" type="image/png" href="favicon.png">
|
<link rel="icon" type="image/png" href="favicon.png">
|
||||||
|
|
||||||
<title>Solian</title>
|
<title>Solian</title>
|
||||||
<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">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style id="splash-screen-style">
|
|
||||||
html {
|
|
||||||
height: 100%
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
min-height: 100%;
|
|
||||||
background-color: #ffffff;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.center {
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||||
margin: 0;
|
name="viewport">
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
-ms-transform: translate(-50%, -50%);
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.contain {
|
|
||||||
display:block;
|
|
||||||
width:100%; height:100%;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stretch {
|
<style id="splash-screen-style">
|
||||||
display:block;
|
html {
|
||||||
width:100%; height:100%;
|
height: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
.cover {
|
body {
|
||||||
display:block;
|
margin: 0;
|
||||||
width:100%; height:100%;
|
min-height: 100%;
|
||||||
object-fit: cover;
|
background-color: #ffffff;
|
||||||
}
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.bottom {
|
.center {
|
||||||
position: absolute;
|
margin: 0;
|
||||||
bottom: 0;
|
position: absolute;
|
||||||
left: 50%;
|
top: 50%;
|
||||||
-ms-transform: translate(-50%, 0);
|
left: 50%;
|
||||||
transform: translate(-50%, 0);
|
-ms-transform: translate(-50%, -50%);
|
||||||
}
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
.bottomLeft {
|
.contain {
|
||||||
position: absolute;
|
display:block;
|
||||||
bottom: 0;
|
width:100%; height:100%;
|
||||||
left: 0;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottomRight {
|
.stretch {
|
||||||
position: absolute;
|
display:block;
|
||||||
bottom: 0;
|
width:100%; height:100%;
|
||||||
right: 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
.cover {
|
||||||
body {
|
display:block;
|
||||||
background-color: #000000;
|
width:100%; height:100%;
|
||||||
}
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
<script id="splash-screen-script">
|
.bottom {
|
||||||
function removeSplashFromWeb() {
|
position: absolute;
|
||||||
document.getElementById("splash")?.remove();
|
bottom: 0;
|
||||||
document.getElementById("splash-branding")?.remove();
|
left: 50%;
|
||||||
document.body.style.background = "transparent";
|
-ms-transform: translate(-50%, 0);
|
||||||
}
|
transform: translate(-50%, 0);
|
||||||
</script>
|
}
|
||||||
|
|
||||||
|
.bottomLeft {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottomRight {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
body {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script id="splash-screen-script">
|
||||||
|
function removeSplashFromWeb() {
|
||||||
|
document.getElementById("splash")?.remove();
|
||||||
|
document.getElementById("splash-branding")?.remove();
|
||||||
|
document.body.style.background = "transparent";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</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)">
|
||||||
<img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt="">
|
<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"
|
||||||
</picture>
|
media="(prefers-color-scheme: dark)">
|
||||||
|
<img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt="">
|
||||||
|
</picture>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="flutter_bootstrap.js" async=""></script>
|
|
||||||
|
|
||||||
|
|
||||||
</body></html>
|
<script src="flutter_bootstrap.js" async=""></script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user