diff --git a/app/components/home.module.scss b/app/components/home.module.scss index 87231fee..cef1662b 100644 --- a/app/components/home.module.scss +++ b/app/components/home.module.scss @@ -26,13 +26,13 @@ @media only screen and (min-width: 600px) { .tight-container { --window-width: 100vw; - --window-height: 100vh; + --window-height: var(--full-height); --window-content-width: calc(100% - var(--sidebar-width)); @include container(); max-width: 100vw; - max-height: 100vh; + max-height: var(--full-height); border-radius: 0; } @@ -74,7 +74,7 @@ position: absolute; left: -100%; z-index: 999; - height: 100vh; + height: var(--full-height); transition: all ease 0.3s; box-shadow: none; } diff --git a/app/components/home.tsx b/app/components/home.tsx index da65b1d6..2f09aa27 100644 --- a/app/components/home.tsx +++ b/app/components/home.tsx @@ -23,7 +23,13 @@ import DownloadIcon from "../icons/download.svg"; import { Message, SubmitKey, useChatStore, ChatSession } from "../store"; import { showModal, showToast } from "./ui-lib"; -import { copyToClipboard, downloadAs, isIOS, selectOrCopy } from "../utils"; +import { + copyToClipboard, + downloadAs, + isIOS, + isMobileScreen, + selectOrCopy, +} from "../utils"; import Locale from "../locales"; import dynamic from "next/dynamic"; @@ -102,7 +108,7 @@ export function ChatList() { state.currentSessionIndex, state.selectSession, state.removeSession, - ] + ], ); return ( @@ -196,7 +202,7 @@ export function Chat(props: { setPromptHints(promptStore.search(text)); }, 100, - { leading: true, trailing: true } + { leading: true, trailing: true }, ); const onPromptSelect = (prompt: Prompt) => { @@ -210,7 +216,7 @@ export function Chat(props: { if (!dom) return; const paddingBottomNum: number = parseInt( window.getComputedStyle(dom).paddingBottom, - 10 + 10, ); dom.scrollTop = dom.scrollHeight - dom.offsetHeight + paddingBottomNum; }; @@ -284,9 +290,7 @@ export function Chat(props: { // for auto-scroll const latestMessageRef = useRef(null); - - // wont scroll while hovering messages - const [autoScroll, setAutoScroll] = useState(false); + const [autoScroll, setAutoScroll] = useState(true); // preview messages const messages = (session.messages as RenderMessage[]) @@ -300,7 +304,7 @@ export function Chat(props: { preview: true, }, ] - : [] + : [], ) .concat( userInput.length > 0 @@ -312,14 +316,24 @@ export function Chat(props: { preview: true, }, ] - : [] + : [], ); // auto scroll useLayoutEffect(() => { setTimeout(() => { const dom = latestMessageRef.current; - if (dom && !isIOS() && autoScroll) { + const inputDom = inputRef.current; + + // only scroll when input overlaped message body + let shouldScroll = true; + if (dom && inputDom) { + const domRect = dom.getBoundingClientRect(); + const inputRect = inputDom.getBoundingClientRect(); + shouldScroll = domRect.top > inputRect.top; + } + + if (dom && autoScroll && shouldScroll) { dom.scrollIntoView({ block: "end", }); @@ -340,7 +354,7 @@ export function Chat(props: { const newTopic = prompt(Locale.Chat.Rename, session.topic); if (newTopic && newTopic !== session.topic) { chatStore.updateCurrentSession( - (session) => (session.topic = newTopic!) + (session) => (session.topic = newTopic!), ); } }} @@ -475,7 +489,7 @@ export function Chat(props: { onFocus={() => setAutoScroll(true)} onBlur={() => { setAutoScroll(false); - setTimeout(() => setPromptHints([]), 100); + setTimeout(() => setPromptHints([]), 500); }} autoFocus={!props?.sideBarShowing} /> @@ -586,7 +600,7 @@ export function Home() { state.newSession, state.currentSessionIndex, state.removeSession, - ] + ], ); const loading = !useHasHydrated(); const [showSideBar, setShowSideBar] = useState(true); @@ -604,7 +618,9 @@ export function Home() { return (
void }) { const updateStore = useUpdateStore(); const [checkingUpdate, setCheckingUpdate] = useState(false); - const currentId = getCurrentCommitId(); + const currentId = getCurrentVersion(); const remoteId = updateStore.remoteId; const hasNewVersion = currentId !== remoteId; @@ -267,19 +267,17 @@ export function Settings(props: { closeSettings: () => void }) { > -
- - - updateConfig( - (config) => (config.tightBorder = e.currentTarget.checked), - ) - } - > - -
+ + + updateConfig( + (config) => (config.tightBorder = e.currentTarget.checked), + ) + } + > + 0 || IS_IN_DOCKER) ? "enabled" : "disabled", + access: ACCESS_CODES.size > 0 || IS_IN_DOCKER ? "enabled" : "disabled", }; return ( diff --git a/app/store/update.ts b/app/store/update.ts index 118ea3ce..0699369d 100644 --- a/app/store/update.ts +++ b/app/store/update.ts @@ -1,7 +1,7 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; -import { FETCH_COMMIT_URL } from "../constant"; -import { getCurrentCommitId } from "../utils"; +import { FETCH_COMMIT_URL, FETCH_TAG_URL } from "../constant"; +import { getCurrentVersion } from "../utils"; export interface UpdateStore { lastUpdate: number; @@ -19,16 +19,15 @@ export const useUpdateStore = create()( remoteId: "", async getLatestCommitId(force = false) { - const overOneHour = Date.now() - get().lastUpdate > 3600 * 1000; - const shouldFetch = force || overOneHour; + const overTenMins = Date.now() - get().lastUpdate > 10 * 60 * 1000; + const shouldFetch = force || overTenMins; if (!shouldFetch) { - return getCurrentCommitId(); + return getCurrentVersion(); } try { - const data = await (await fetch(FETCH_COMMIT_URL)).json(); - const sha = data[0].sha as string; - const remoteId = sha.substring(0, 7); + const data = await (await fetch(FETCH_TAG_URL)).json(); + const remoteId = data[0].name as string; set(() => ({ lastUpdate: Date.now(), remoteId, @@ -37,13 +36,13 @@ export const useUpdateStore = create()( return remoteId; } catch (error) { console.error("[Fetch Upstream Commit Id]", error); - return getCurrentCommitId(); + return getCurrentVersion(); } }, }), { name: UPDATE_KEY, version: 1, - } - ) + }, + ), ); diff --git a/app/styles/globals.scss b/app/styles/globals.scss index b4b25b5c..c514274a 100644 --- a/app/styles/globals.scss +++ b/app/styles/globals.scss @@ -53,12 +53,13 @@ --sidebar-width: 300px; --window-content-width: calc(100% - var(--sidebar-width)); --message-max-width: 80%; + --full-height: 100vh; } @media only screen and (max-width: 600px) { :root { --window-width: 100vw; - --window-height: 100vh; + --window-height: var(--full-height); --sidebar-width: 100vw; --window-content-width: var(--window-width); --message-max-width: 100%; @@ -80,14 +81,14 @@ body { color: var(--black); margin: 0; padding: 0; - height: 100vh; + height: var(--full-height); width: 100vw; display: flex; justify-content: center; align-items: center; user-select: none; font-family: "Noto Sans SC", "SF Pro SC", "SF Pro Text", "SF Pro Icons", - "PingFang SC", "Helvetica Neue", "Helvetica", "Arial", sans-serif; + "PingFang SC", "Helvetica Neue", "Helvetica", "Arial", sans-serif; @media only screen and (max-width: 600px) { background-color: var(--second); @@ -119,6 +120,11 @@ select { cursor: pointer; background-color: var(--white); color: var(--black); + text-align: center; +} + +input { + text-align: center; } input[type="checkbox"] { @@ -196,7 +202,7 @@ div.math { position: fixed; top: 0; left: 0; - height: 100vh; + height: var(--full-height); width: 100vw; background-color: rgba($color: #000000, $alpha: 0.5); display: flex; diff --git a/app/styles/prism.scss b/app/styles/prism.scss index 0d011ce0..65ee8b5f 100644 --- a/app/styles/prism.scss +++ b/app/styles/prism.scss @@ -120,33 +120,3 @@ cursor: help; } } - -@mixin light { - .markdown-body pre { - filter: invert(1) hue-rotate(90deg) brightness(1.3); - } -} - -@mixin dark { - .markdown-body pre { - filter: none; - } -} - -:root { - @include light(); -} - -.light { - @include light(); -} - -.dark { - @include dark(); -} - -@media (prefers-color-scheme: dark) { - :root { - @include dark(); - } -} diff --git a/app/utils.ts b/app/utils.ts index b3233232..64120df4 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -45,6 +45,10 @@ export function isIOS() { return /iphone|ipad|ipod/.test(userAgent); } +export function isMobileScreen() { + return window.innerWidth <= 600; +} + export function selectOrCopy(el: HTMLElement, content: string) { const currentSelection = window.getSelection(); @@ -72,7 +76,7 @@ export function queryMeta(key: string, defaultValue?: string): string { } let currentId: string; -export function getCurrentCommitId() { +export function getCurrentVersion() { if (currentId) { return currentId; }