fix: 修复移动端输入框被键盘遮挡的问题
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.pnpm-store
|
||||
.omc
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vocechat-web",
|
||||
"version": "0.9.78",
|
||||
"version": "0.9.79",
|
||||
"homepage": "https://voce.chat",
|
||||
"dependencies": {
|
||||
"@metamask/onboarding": "^1.0.1",
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
const isIOS = () =>
|
||||
/iPad|iPhone|iPod/.test(navigator.userAgent) ||
|
||||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
|
||||
|
||||
/**
|
||||
* Listens to the VisualViewport API and writes the visible height as a CSS
|
||||
* custom property (`--vh-visible`) on `document.documentElement`.
|
||||
*
|
||||
* On Android mobile browsers the virtual keyboard shrinks the visual viewport
|
||||
* while `100vh` still refers to the full layout viewport, which causes
|
||||
* bottom-pinned elements (like the chat input) to be hidden behind the
|
||||
* keyboard or the browser chrome.
|
||||
*
|
||||
* iOS Safari handles this natively via scroll-into-view behaviour and
|
||||
* `-webkit-fill-available`, so we skip it there to avoid the container
|
||||
* being over-shrunk when the keyboard opens.
|
||||
*/
|
||||
export default function useVirtualKeyboard() {
|
||||
useEffect(() => {
|
||||
if (isIOS()) return;
|
||||
|
||||
const vv = window.visualViewport;
|
||||
|
||||
function update() {
|
||||
const height = vv ? vv.height : window.innerHeight;
|
||||
document.documentElement.style.setProperty("--vh-visible", `${height}px`);
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
if (vv) {
|
||||
vv.addEventListener("resize", update);
|
||||
vv.addEventListener("scroll", update);
|
||||
} else {
|
||||
window.addEventListener("resize", update);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (vv) {
|
||||
vv.removeEventListener("resize", update);
|
||||
vv.removeEventListener("scroll", update);
|
||||
} else {
|
||||
window.removeEventListener("resize", update);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import ChannelModal from "@/components/ChannelModal";
|
||||
import ErrorCatcher from "@/components/ErrorCatcher";
|
||||
import Server from "@/components/Server";
|
||||
import UsersModal from "@/components/UsersModal";
|
||||
import useVirtualKeyboard from "@/hooks/useVirtualKeyboard";
|
||||
import { isIOS } from "@/utils";
|
||||
import ChannelChat from "./ChannelChat";
|
||||
import DMChat from "./DMChat";
|
||||
import GuestBlankPlaceholder from "./GuestBlankPlaceholder";
|
||||
@@ -19,6 +21,7 @@ import VoiceFullscreen from "./VoiceFullscreen";
|
||||
import { shallowEqual } from "react-redux";
|
||||
|
||||
function ChatPage() {
|
||||
useVirtualKeyboard();
|
||||
const isHomePath = useMatch(`/`);
|
||||
const isChatHomePath = useMatch(`/chat`);
|
||||
const [sessionListVisible, setSessionListVisible] = useState(false);
|
||||
@@ -65,6 +68,8 @@ function ChatPage() {
|
||||
const contextId = (+channel_id || callingTo) ?? 0;
|
||||
console.log("fffff", channel_id, user_id, aside, channelChatVisible);
|
||||
|
||||
const mobileHeight = isIOS() ? "h-screen" : "h-[var(--vh-visible,100vh)]";
|
||||
|
||||
return (
|
||||
<ErrorCatcher>
|
||||
{channelModalVisible && (
|
||||
@@ -73,7 +78,7 @@ function ChatPage() {
|
||||
{usersModalVisible && <UsersModal closeModal={toggleUsersModalVisible} />}
|
||||
<div
|
||||
className={clsx(
|
||||
`flex h-screen md:h-full md:pt-2 md:pb-2.5 md:pr-1`,
|
||||
`flex ${mobileHeight} md:h-full md:pt-2 md:pb-2.5 md:pr-1`,
|
||||
isGuest ? "guest-container md:px-1" : "md:pr-12"
|
||||
)}
|
||||
>
|
||||
@@ -85,7 +90,7 @@ function ChatPage() {
|
||||
)}
|
||||
<div
|
||||
className={clsx(
|
||||
"left-container flex-col md:rounded-l-2xl w-full h-screen md:h-full md:max-w-[250px] md:min-w-[268px] shadow-[rgb(0_0_0_/_10%)_-1px_0px_0px_inset] bg-white dark:!bg-gray-800",
|
||||
`left-container flex-col md:rounded-l-2xl w-full ${mobileHeight} md:h-full md:max-w-[250px] md:min-w-[268px] shadow-[rgb(0_0_0_/_10%)_-1px_0px_0px_inset] bg-white dark:!bg-gray-800`,
|
||||
isMainPath ? "flex" : "hidden md:flex"
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -13,6 +13,8 @@ import Tooltip from "@/components/Tooltip";
|
||||
import UnreadTabTip from "@/components/UnreadTabTip";
|
||||
import Voice from "@/components/Voice";
|
||||
import usePreload from "@/hooks/usePreload";
|
||||
import useVirtualKeyboard from "@/hooks/useVirtualKeyboard";
|
||||
import { isIOS } from "@/utils";
|
||||
import FavIcon from "@/assets/icons/bookmark.svg";
|
||||
import ChatIcon from "@/assets/icons/chat.svg";
|
||||
import FolderIcon from "@/assets/icons/folder.svg";
|
||||
@@ -23,6 +25,7 @@ import User from "./User";
|
||||
import StreamStatus from "@/components/StreamStatus";
|
||||
|
||||
function HomePage() {
|
||||
useVirtualKeyboard();
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const isHomePath = useMatch(`/`);
|
||||
@@ -66,7 +69,9 @@ function HomePage() {
|
||||
<Manifest />
|
||||
{!guest && <Notification />}
|
||||
<div
|
||||
className={`vocechat-container flex w-screen h-screen bg-neutral-100 dark:bg-neutral-900`}
|
||||
className={`vocechat-container flex w-screen ${
|
||||
isIOS() ? "h-screen" : "h-[var(--vh-visible,100vh)]"
|
||||
} bg-neutral-100 dark:bg-neutral-900`}
|
||||
>
|
||||
{!guest && (
|
||||
<div
|
||||
|
||||
@@ -61,6 +61,10 @@ export function getMessageFromPlateValues(values: ParagraphInput[]): MessageWith
|
||||
export const isMobile = () =>
|
||||
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||
|
||||
export const isIOS = () =>
|
||||
/iPad|iPhone|iPod/.test(navigator.userAgent) ||
|
||||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
|
||||
|
||||
export const getLocalAuthData = () => {
|
||||
return {
|
||||
token: localStorage.getItem(KEY_TOKEN) || "",
|
||||
|
||||
Reference in New Issue
Block a user