feat: optiminize message&img display

This commit is contained in:
butterfly 2024-04-19 19:28:48 +08:00
parent 1074fffe79
commit 37cc87531c
10 changed files with 132 additions and 43 deletions

View File

@ -0,0 +1,52 @@
import { CSSProperties } from "react";
import { getMessageImages } from "@/app/utils";
import { RequestMessage } from "@/app/client/api";
interface ImgsProps {
message: RequestMessage;
isMobileScreen?: boolean;
}
export default function Imgs(props: ImgsProps) {
const { message, isMobileScreen } = props;
const imgSrcs = getMessageImages(message);
if (imgSrcs.length < 1) {
return <></>;
}
let imgVars = {
"--imgs-width": `calc(var(--max-message-width) - ${
imgSrcs.length - 1
}*0.25rem)`,
"--img-width": `calc(var(--imgs-width)/ ${imgSrcs.length})`,
};
if (isMobileScreen) {
imgVars = {
"--imgs-width": `calc(var(--max-message-width) - ${
imgSrcs.length - 1
}*0.25rem)`,
"--img-width": `calc(var(--imgs-width)/ ${imgSrcs.length})`,
};
}
return (
<div
className={`w-[100%] mt-[0.625rem] flex gap-1`}
style={imgVars as CSSProperties}
>
{imgSrcs.map((image, index) => {
return (
<div
key={index}
className="flex-1 min-w-[var(--img-width)] pb-[var(--img-width)] object-cover bg-cover bg-no-repeat bg-center box-border rounded-chat-img"
style={{
backgroundImage: `url(${image})`,
}}
/>
);
})}
</div>
);
}

View File

@ -1,6 +1,6 @@
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import { useMemo, ReactNode } from "react"; import { useMemo, ReactNode } from "react";
import { Path, SlotID } from "@/app/constant"; import { Path, SIDEBAR_ID, SlotID } from "@/app/constant";
import { getLang } from "@/app/locales"; import { getLang } from "@/app/locales";
import useMobileScreen from "@/app/hooks/useMobileScreen"; import useMobileScreen from "@/app/hooks/useMobileScreen";
@ -47,7 +47,9 @@ export default function Screen(props: ScreenProps) {
props.noAuth props.noAuth
) : ( ) : (
<> <>
<div className={sidebarClassName}>{props.sidebar}</div> <div className={sidebarClassName} id={SIDEBAR_ID}>
{props.sidebar}
</div>
<div <div
className={pageClassName} className={pageClassName}

View File

@ -49,6 +49,8 @@ export enum StoreKey {
Sync = "sync", Sync = "sync",
} }
export const NARROW_SIDEBAR_WIDTH = 100;
export const DEFAULT_SIDEBAR_WIDTH = 340; export const DEFAULT_SIDEBAR_WIDTH = 340;
export const MAX_SIDEBAR_WIDTH = 440; export const MAX_SIDEBAR_WIDTH = 440;
export const MIN_SIDEBAR_WIDTH = 230; export const MIN_SIDEBAR_WIDTH = 230;
@ -383,3 +385,5 @@ export const internalWhiteWebDavEndpoints = [
"https://webdav.yandex.com", "https://webdav.yandex.com",
"https://app.koofr.net/dav/Koofr", "https://app.koofr.net/dav/Koofr",
]; ];
export const SIDEBAR_ID = "sidebar";

View File

@ -20,6 +20,7 @@ import useRelativePosition, {
Orientation, Orientation,
} from "@/app/hooks/useRelativePosition"; } from "@/app/hooks/useRelativePosition";
import MessageActions, { RenderMessage } from "./MessageActions"; import MessageActions, { RenderMessage } from "./MessageActions";
import Imgs from "@/app/components/Imgs";
export type { RenderMessage }; export type { RenderMessage };
@ -186,7 +187,11 @@ export default function ChatMessagePanel(props: ChatMessagePanelProps) {
</> </>
)} )}
</div> </div>
<div className={`group relative max-w-message-width`}> <div
className={`group relative flex-1 flex ${
isUser ? "flex-row-reverse" : ""
}`}
>
<div <div
className={` pointer-events-none text-gray-500 text-right text-time whitespace-nowrap transition-all duration-500 text-sm absolute z-1 ${ className={` pointer-events-none text-gray-500 text-right text-time whitespace-nowrap transition-all duration-500 text-sm absolute z-1 ${
isUser ? "right-0" : "left-0" isUser ? "right-0" : "left-0"
@ -198,10 +203,10 @@ export default function ChatMessagePanel(props: ChatMessagePanelProps) {
</div> </div>
<div <div
className={`transition-all duration-300 select-text break-words font-common text-sm-title ${ className={`transition-all duration-300 select-text break-words font-common text-sm-title ${
isUser ? "rounded-user-message" : "rounded-bot-message" isUser
} box-border peer py-2 px-3 ${ ? "rounded-user-message bg-message-bg"
isUser ? "text-right bg-message-bg" : " bg-white" : "rounded-bot-message bg-white"
}`} } box-border peer py-2 px-3`}
onPointerMoveCapture={(e) => onPointerMoveCapture={(e) =>
getRelativePosition(e.currentTarget, message.id) getRelativePosition(e.currentTarget, message.id)
} }
@ -221,22 +226,11 @@ export default function ChatMessagePanel(props: ChatMessagePanelProps) {
fontSize={fontSize} fontSize={fontSize}
parentRef={scrollRef} parentRef={scrollRef}
defaultShow={i >= messages.length - 6} defaultShow={i >= messages.length - 6}
className={isUser ? " text-white" : "text-black"} className={`max-w-message-width ${
isUser ? " text-white" : "text-black"
}`}
/> />
{getMessageImages(message).length > 0 && ( <Imgs message={message} isMobileScreen={isMobileScreen} />
<div className={`w-[100%]`}>
{getMessageImages(message).map((image, index) => {
return (
<img
className={`w-[100%] mt-2.5 rounded-chat-img`}
key={index}
src={image}
alt=""
/>
);
})}
</div>
)}
</div> </div>
<MessageActions <MessageActions
className={actionsBarPosition} className={actionsBarPosition}

View File

@ -3,8 +3,9 @@ import {
MAX_SIDEBAR_WIDTH, MAX_SIDEBAR_WIDTH,
MIN_SIDEBAR_WIDTH, MIN_SIDEBAR_WIDTH,
} from "@/app/constant"; } from "@/app/constant";
import { useAppConfig } from "../store/config"; import { useAppConfig } from "@/app/store/config";
import { useRef } from "react"; import { useRef } from "react";
import { updateGlobalCSSVars } from "@/app/utils/client";
export default function useDragSideBar() { export default function useDragSideBar() {
const limit = (x: number) => const limit = (x: number) =>
@ -35,9 +36,11 @@ export default function useDragSideBar() {
const d = e.clientX - startX.current; const d = e.clientX - startX.current;
const nextWidth = limit(startDragWidth.current + d); const nextWidth = limit(startDragWidth.current + d);
const { menuWidth } = updateGlobalCSSVars(nextWidth);
document.documentElement.style.setProperty( document.documentElement.style.setProperty(
"--sidebar-width", "--menu-width",
`${nextWidth}px`, `${menuWidth}px`,
); );
config.update((config) => { config.update((config) => {
config.sidebarWidth = nextWidth; config.sidebarWidth = nextWidth;
@ -62,7 +65,7 @@ export default function useDragSideBar() {
// useLayoutEffect(() => { // useLayoutEffect(() => {
// const barWidth = limit(config.sidebarWidth ?? DEFAULT_SIDEBAR_WIDTH); // const barWidth = limit(config.sidebarWidth ?? DEFAULT_SIDEBAR_WIDTH);
// document.documentElement.style.setProperty("--sidebar-width", `${barWidth}px`); // document.documentElement.style.setProperty("--menu-width", `${barWidth}px`);
// }, [config.sidebarWidth]); // }, [config.sidebarWidth]);
return { return {

View File

@ -8,8 +8,10 @@ import {
DEFAULT_SIDEBAR_WIDTH, DEFAULT_SIDEBAR_WIDTH,
MAX_SIDEBAR_WIDTH, MAX_SIDEBAR_WIDTH,
MIN_SIDEBAR_WIDTH, MIN_SIDEBAR_WIDTH,
SIDEBAR_ID,
} from "@/app/constant"; } from "@/app/constant";
import { useAppConfig } from "../store/config"; import { useAppConfig } from "@/app/store/config";
import { updateGlobalCSSVars } from "@/app/utils/client";
export const MOBILE_MAX_WIDTH = 768; export const MOBILE_MAX_WIDTH = 768;
@ -42,16 +44,10 @@ export default function useListenWinResize() {
} }
} }
nextSidebar = Math.max( const { menuWidth } = updateGlobalCSSVars(nextSidebar);
MIN_SIDEBAR_WIDTH,
Math.min(MAX_SIDEBAR_WIDTH, nextSidebar),
);
document.documentElement.style.setProperty(
"--sidebar-width",
`${nextSidebar}px`,
);
config.update((config) => { config.update((config) => {
config.sidebarWidth = nextSidebar; config.sidebarWidth = menuWidth;
}); });
}); });
} }

View File

@ -28,4 +28,5 @@ body {
--tip-popover-color: #434360; --tip-popover-color: #434360;
--chat-panel-bg: rgb(249, 250, 251, 1); --chat-panel-bg: rgb(249, 250, 251, 1);
--siderbar-mobile-height: 3.125rem; --siderbar-mobile-height: 3.125rem;
--max-message-width: calc(var(--chat-panel-max-width) * 0.6);
} }

View File

@ -61,7 +61,7 @@
--window-width: 90vw; --window-width: 90vw;
--window-height: 90vh; --window-height: 90vh;
// --sidebar-width: 300px; --sidebar-width: 300px;
--window-content-width: calc(100% - var(--sidebar-width)); --window-content-width: calc(100% - var(--sidebar-width));
--message-max-width: 80%; --message-max-width: 80%;
--full-height: 100%; --full-height: 100%;
@ -71,7 +71,7 @@
:root { :root {
--window-width: 100vw; --window-width: 100vw;
--window-height: var(--full-height); --window-height: var(--full-height);
// --sidebar-width: 100vw; --sidebar-width: 100vw;
--window-content-width: var(--window-width); --window-content-width: var(--window-width);
--message-max-width: 100%; --message-max-width: 100%;
} }

34
app/utils/client.ts Normal file
View File

@ -0,0 +1,34 @@
import {
MAX_SIDEBAR_WIDTH,
MIN_SIDEBAR_WIDTH,
SIDEBAR_ID,
WINDOW_WIDTH_MD,
} from "@/app/constant";
export function updateGlobalCSSVars(nextSidebar: number) {
const windowSize = window.innerWidth;
const inMobile = windowSize <= WINDOW_WIDTH_MD;
nextSidebar = Math.max(
MIN_SIDEBAR_WIDTH,
Math.min(MAX_SIDEBAR_WIDTH, nextSidebar),
);
const menuWidth = inMobile ? 0 : nextSidebar;
const navigateBarWidth = inMobile
? 0
: document.querySelector(`#${SIDEBAR_ID}`)?.clientWidth ?? 0;
const chatPanelWidth = windowSize - navigateBarWidth - menuWidth;
document.documentElement.style.setProperty("--menu-width", `${menuWidth}px`);
document.documentElement.style.setProperty(
"--navigate-bar-width",
`${navigateBarWidth}px`,
);
document.documentElement.style.setProperty(
"--chat-panel-max-width",
`${chatPanelWidth}px`,
);
return { menuWidth };
}

View File

@ -37,7 +37,7 @@ module.exports = {
'md': '15rem', 'md': '15rem',
'lg': '21.25rem', 'lg': '21.25rem',
'2xl': '27.5rem', '2xl': '27.5rem',
'page': 'calc(100% - var(--sidebar-width))', 'page': 'calc(100% - var(--menu-width))',
'thumbnail': '5rem', 'thumbnail': '5rem',
'actions-popover': '203px', 'actions-popover': '203px',
}, },
@ -52,12 +52,14 @@ module.exports = {
'setting-panel-mobile': 'calc(100vh - var(--siderbar-mobile-height))', 'setting-panel-mobile': 'calc(100vh - var(--siderbar-mobile-height))',
}, },
flexBasis: { flexBasis: {
'sidebar': 'var(--sidebar-width)', 'sidebar': 'var(--menu-width)',
'page': 'calc(100% - var(--sidebar-width))', 'page': 'calc(100% - var(--menu-width))',
'message-width': 'var(--max-message-width)',
}, },
spacing: { spacing: {
'chat-header-gap': '0.625rem', 'chat-header-gap': '0.625rem',
'chat-panel-mobile': 'var(--siderbar-mobile-height)' 'chat-panel-mobile': 'var(--siderbar-mobile-height)',
'message-img': 'calc((100%- var(--img-gap-count)*0.25rem)/var(--img-count))',
}, },
backgroundImage: { backgroundImage: {
'message-bg': 'linear-gradient(259deg, #9786FF 8.42%, #4A5CFF 90.13%)', 'message-bg': 'linear-gradient(259deg, #9786FF 8.42%, #4A5CFF 90.13%)',
@ -67,8 +69,9 @@ module.exports = {
'time': 'all ease 0.6s', 'time': 'all ease 0.6s',
'message': 'all ease 0.3s', 'message': 'all ease 0.3s',
}, },
maxHeight: {},
maxWidth: { maxWidth: {
'message-width': 'var(--max-message-width, 80%)' 'message-width': 'var(--max-message-width)',
}, },
backgroundColor: { backgroundColor: {
'select-btn': 'rgba(0, 0, 0, 0.05)', 'select-btn': 'rgba(0, 0, 0, 0.05)',