diff --git a/components/mobile-wrapper-dialog/MobileWrapperDialog.tsx b/components/mobile-wrapper-dialog/MobileWrapperDialog.tsx index d220520e7d..2ec23c87c6 100644 --- a/components/mobile-wrapper-dialog/MobileWrapperDialog.tsx +++ b/components/mobile-wrapper-dialog/MobileWrapperDialog.tsx @@ -29,19 +29,24 @@ export default function MobileWrapperDialog({ readonly tall?: boolean | undefined; readonly fixedHeight?: boolean | undefined; }) { - const { isCapacitor } = useCapacitor(); + const { isCapacitor, isIos } = useCapacitor(); const bottomPadding = noPadding ? "env(safe-area-inset-bottom,0px)" : "calc(env(safe-area-inset-bottom,0px) + 1.5rem)"; + const viewportHeight = "min(100vh, 100svh)"; const getHeight = () => { if (tall && !isCapacitor) { - return "calc(100dvh - 4rem)"; + return `calc(${viewportHeight} - 4rem)`; } - return "calc(100dvh - 10rem)"; + return `calc(${viewportHeight} - 10rem)`; }; + const panelClassNames = `mobile-wrapper-dialog tw-pointer-events-auto tw-relative tw-w-screen md:tw-max-w-screen-md${ + isIos ? "" : " tw-transform-gpu tw-will-change-transform" + }`; + return ( e.stopPropagation()} > (null); + useEffect(() => { if (isCapacitor) { document.body.classList.add("capacitor-native"); @@ -12,5 +14,35 @@ export default function CapacitorSetup() { document.body.classList.remove("capacitor-native"); } }, [isCapacitor]); + + useEffect(() => { + if (typeof document === "undefined") return; + + const meta = + document.querySelector('meta[name="viewport"]') ?? + document.createElement("meta"); + + if (!meta.getAttribute("name")) { + meta.setAttribute("name", "viewport"); + document.head.appendChild(meta); + } + + originalViewport.current ??= meta.getAttribute("content"); + + if (isCapacitor) { + meta.setAttribute( + "content", + "width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover" + ); + } else if (originalViewport.current) { + meta.setAttribute("content", originalViewport.current); + } + + return () => { + if (originalViewport.current) { + meta.setAttribute("content", originalViewport.current); + } + }; + }, [isCapacitor]); return null; } diff --git a/components/waves/CreateDropInput.tsx b/components/waves/CreateDropInput.tsx index f5782e8a09..9841b50ec8 100644 --- a/components/waves/CreateDropInput.tsx +++ b/components/waves/CreateDropInput.tsx @@ -1,10 +1,7 @@ "use client"; -import type { - InitialConfigType} from "@lexical/react/LexicalComposer"; -import { - LexicalComposer, -} from "@lexical/react/LexicalComposer"; +import type { InitialConfigType } from "@lexical/react/LexicalComposer"; +import { LexicalComposer } from "@lexical/react/LexicalComposer"; import { forwardRef, useImperativeHandle, @@ -12,13 +9,8 @@ import { useEffect, useRef, } from "react"; -import type { - EditorState} from "lexical"; -import { - RootNode, - COMMAND_PRIORITY_CRITICAL, - createCommand, -} from "lexical"; +import type { EditorState } from "lexical"; +import { RootNode, COMMAND_PRIORITY_CRITICAL, createCommand } from "lexical"; import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin"; import { ContentEditable } from "@lexical/react/LexicalContentEditable"; @@ -43,17 +35,11 @@ import { HashtagNode } from "../drops/create/lexical/nodes/HashtagNode"; import { ImageNode } from "../drops/create/lexical/nodes/ImageNode"; import ExampleTheme from "../drops/create/lexical/ExampleTheme"; import { assertUnreachable } from "@/helpers/AllowlistToolHelpers"; -import type { - ClearEditorPluginHandles, -} from "../drops/create/lexical/plugins/ClearEditorPlugin"; +import type { ClearEditorPluginHandles } from "../drops/create/lexical/plugins/ClearEditorPlugin"; import ClearEditorPlugin from "../drops/create/lexical/plugins/ClearEditorPlugin"; -import type { - NewMentionsPluginHandles, -} from "../drops/create/lexical/plugins/mentions/MentionsPlugin"; +import type { NewMentionsPluginHandles } from "../drops/create/lexical/plugins/mentions/MentionsPlugin"; import NewMentionsPlugin from "../drops/create/lexical/plugins/mentions/MentionsPlugin"; -import type { - NewHastagsPluginHandles, -} from "../drops/create/lexical/plugins/hashtags/HashtagsPlugin"; +import type { NewHastagsPluginHandles } from "../drops/create/lexical/plugins/hashtags/HashtagsPlugin"; import NewHashtagsPlugin from "../drops/create/lexical/plugins/hashtags/HashtagsPlugin"; import { MaxLengthPlugin } from "../drops/create/lexical/plugins/MaxLengthPlugin"; import DragDropPastePlugin from "../drops/create/lexical/plugins/DragDropPastePlugin"; @@ -170,7 +156,7 @@ const CreateDropInput = forwardRef< const getPlaceHolderText = () => { if (isStormMode) return "Add to the storm"; - if (!type) return isDropMode ? "Create a drop" : "Create a post"; + if (type === null) return isDropMode ? "Create a drop" : "Create a post"; switch (type) { case ActiveDropAction.REPLY: return isDropMode ? "Drop a reply" : "Post a reply"; @@ -202,7 +188,7 @@ const CreateDropInput = forwardRef< editorRef.current?.querySelector( '[contenteditable="true"]' ) as HTMLElement - )?.focus(); + ).focus(); }, })); @@ -243,16 +229,17 @@ const CreateDropInput = forwardRef< { // Ensure the contenteditable is properly focused and ready for paste const target = e.currentTarget; - if (target && !submitting) { + if (!submitting) { // Use a microtask to ensure focus happens after any other handlers Promise.resolve().then(() => { target.focus(); // If there's no selection, place cursor at end const selection = window.getSelection(); - if (selection && selection.rangeCount === 0) { + if (selection?.rangeCount === 0) { const range = document.createRange(); range.selectNodeContents(target); range.collapse(false); @@ -261,10 +248,9 @@ const CreateDropInput = forwardRef< }); } }} - className={`tw-max-h-[40vh] editor-input-one-liner tw-resize-none tw-form-input tw-block tw-w-full tw-rounded-lg tw-border-0 tw-bg-iron-900 tw-text-white tw-font-normal tw-caret-primary-400 tw-shadow-sm tw-ring-1 tw-ring-inset tw-ring-iron-700 placeholder:tw-text-iron-500 focus:tw-outline-none focus:tw-bg-iron-950 focus:tw-ring-1 focus:tw-ring-inset focus:tw-ring-primary-400 tw-text-base sm:tw-text-sm tw-leading-6 tw-transition tw-duration-300 tw-ease-out - tw-pl-3 tw-py-2.5 tw-scrollbar-thin tw-scrollbar-thumb-iron-600 tw-scrollbar-track-iron-900 ${ - submitting ? "tw-opacity-50 tw-cursor-default" : "" - } ${isCapacitor ? "tw-pr-[35px]" : "tw-pr-[40px]"}`} + className={`editor-input-one-liner tw-form-input tw-block tw-max-h-[40vh] tw-w-full tw-resize-none tw-rounded-lg tw-border-0 tw-bg-iron-900 tw-py-2.5 tw-pl-3 tw-text-base tw-font-normal tw-leading-6 tw-text-white tw-caret-primary-400 tw-shadow-sm tw-ring-1 tw-ring-inset tw-ring-iron-700 tw-transition tw-duration-300 tw-ease-out tw-scrollbar-thin tw-scrollbar-track-iron-900 tw-scrollbar-thumb-iron-600 placeholder:tw-text-iron-500 focus:tw-bg-iron-950 focus:tw-outline-none focus:tw-ring-1 focus:tw-ring-inset focus:tw-ring-primary-400 sm:tw-text-sm ${ + submitting ? "tw-cursor-default tw-opacity-50" : "" + } ${isCapacitor ? "tw-pr-[35px]" : "tw-pr-[40px]"}`} /> diff --git a/styles/globals.scss b/styles/globals.scss index 673b2ce8b6..86a3499a1c 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -203,6 +203,15 @@ body { } } +.mobile-wrapper-dialog { + input, + textarea, + select { + font-size: 16px; + touch-action: manipulation; + } +} + textarea, select, input, @@ -569,7 +578,9 @@ h5:not(.tailwind-scope h5) { .edit-profile { opacity: 0; - transition: visibility 0s, opacity 0.3s ease-out; + transition: + visibility 0s, + opacity 0.3s ease-out; } .edit-profile:hover { @@ -632,21 +643,18 @@ h5:not(.tailwind-scope h5) { // Scroll shadow for content overflow indication .scroll-shadow { background: - /* Shadow at the top */ linear-gradient( + /* Shadow at the top */ + linear-gradient( to bottom, rgba(14, 16, 21, 0.8) 0%, rgba(14, 16, 21, 0) 10px ) 0 0, /* Shadow at the bottom */ - linear-gradient( - to top, - rgba(14, 16, 21, 0.8) 0%, - rgba(14, 16, 21, 0) 10px - ) + linear-gradient(to top, rgba(14, 16, 21, 0.8) 0%, rgba(14, 16, 21, 0) 10px) 0 100%, /* Preventing the shadows from overlapping the content */ - radial-gradient( + radial-gradient( farthest-side at 50% 0, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0) @@ -660,7 +668,11 @@ h5:not(.tailwind-scope h5) { 0 100%; background-repeat: no-repeat; - background-size: 100% 10px, 100% 10px, 100% 10px, 100% 10px; + background-size: + 100% 10px, + 100% 10px, + 100% 10px, + 100% 10px; /* Make sure the shadows remain fixed during scrolling */ background-attachment: local, local, scroll, scroll;