feat: optiminize message&img display
This commit is contained in:
parent
1074fffe79
commit
37cc87531c
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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}
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
|
}
|
|
@ -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)',
|
||||||
|
|
Loading…
Reference in New Issue