diff --git a/app/components/auth.module.scss b/app/components/auth/auth.module.scss similarity index 100% rename from app/components/auth.module.scss rename to app/components/auth/auth.module.scss diff --git a/app/components/auth.tsx b/app/components/auth/auth.tsx similarity index 90% rename from app/components/auth.tsx rename to app/components/auth/auth.tsx index 57118349bac..99c25a745dc 100644 --- a/app/components/auth.tsx +++ b/app/components/auth/auth.tsx @@ -1,14 +1,14 @@ import styles from "./auth.module.scss"; -import { IconButton } from "./button"; +import { IconButton } from "@/app/components/button/button"; import { useNavigate } from "react-router-dom"; -import { Path } from "../constant"; -import { useAccessStore } from "../store"; -import Locale from "../locales"; +import { Path } from "@/app/constant"; +import { useAccessStore } from "@/app/store"; +import Locale from "@/app/locales"; -import BotIcon from "../icons/bot.svg"; +import BotIcon from "@/app/icons/bot.svg"; import { useEffect } from "react"; -import { getClientConfig } from "../config/client"; +import { getClientConfig } from "@/app/config/client"; export function AuthPage() { const navigate = useNavigate(); diff --git a/app/components/auth/index.tsx b/app/components/auth/index.tsx new file mode 100644 index 00000000000..97ccf76494a --- /dev/null +++ b/app/components/auth/index.tsx @@ -0,0 +1 @@ +export * from "./auth"; diff --git a/app/components/button.module.scss b/app/components/button/button.module.scss similarity index 100% rename from app/components/button.module.scss rename to app/components/button/button.module.scss diff --git a/app/components/button.tsx b/app/components/button/button.tsx similarity index 100% rename from app/components/button.tsx rename to app/components/button/button.tsx diff --git a/app/components/button/index.tsx b/app/components/button/index.tsx new file mode 100644 index 00000000000..98d55acde68 --- /dev/null +++ b/app/components/button/index.tsx @@ -0,0 +1 @@ +export * from "./button"; diff --git a/app/components/chat-list.tsx b/app/components/chat-list/chat-list.tsx similarity index 90% rename from app/components/chat-list.tsx rename to app/components/chat-list/chat-list.tsx index 7ef6e7b8337..55cd6085085 100644 --- a/app/components/chat-list.tsx +++ b/app/components/chat-list/chat-list.tsx @@ -1,7 +1,7 @@ -import DeleteIcon from "../icons/delete.svg"; -import BotIcon from "../icons/bot.svg"; +import DeleteIcon from "@/app/icons/delete.svg"; +import BotIcon from "@/app/icons/bot.svg"; -import styles from "./home.module.scss"; +import styles from "@/app/components/home/home.module.scss"; import { DragDropContext, Droppable, @@ -9,16 +9,16 @@ import { OnDragEndResponder, } from "@hello-pangea/dnd"; -import { useChatStore } from "../store"; +import { useChatStore } from "@/app/store"; -import Locale from "../locales"; +import Locale from "@/app/locales"; import { Link, useLocation, useNavigate } from "react-router-dom"; -import { Path } from "../constant"; -import { MaskAvatar } from "./mask"; -import { Mask } from "../store/mask"; +import { Path } from "@/app/constant"; +import { MaskAvatar } from "@/app/components/mask/mask"; +import { Mask } from "@/app/store/mask"; import { useRef, useEffect } from "react"; -import { showConfirm } from "./ui-lib"; -import { useMobileScreen } from "../utils"; +import { showConfirm } from "@/app/components/ui-lib"; +import { useMobileScreen } from "@/app/utils"; export function ChatItem(props: { onClick?: () => void; diff --git a/app/components/chat-list/index.tsx b/app/components/chat-list/index.tsx new file mode 100644 index 00000000000..442a559e3d3 --- /dev/null +++ b/app/components/chat-list/index.tsx @@ -0,0 +1 @@ +export * from "./chat-list"; diff --git a/app/components/chat.module.scss b/app/components/chat/chat.module.scss similarity index 94% rename from app/components/chat.module.scss rename to app/components/chat/chat.module.scss index e7619e92b89..cb92dc5720e 100644 --- a/app/components/chat.module.scss +++ b/app/components/chat/chat.module.scss @@ -1,4 +1,4 @@ -@import "../styles/animation.scss"; +@import "../../styles/animation.scss"; .attach-images { position: absolute; @@ -231,10 +231,12 @@ animation: slide-in ease 0.3s; - $linear: linear-gradient(to right, - rgba(0, 0, 0, 0), - rgba(0, 0, 0, 1), - rgba(0, 0, 0, 0)); + $linear: linear-gradient( + to right, + rgba(0, 0, 0, 0), + rgba(0, 0, 0, 1), + rgba(0, 0, 0, 0) + ); mask-image: $linear; @mixin show { @@ -367,7 +369,7 @@ } } -.chat-message-user>.chat-message-container { +.chat-message-user > .chat-message-container { align-items: flex-end; } @@ -450,23 +452,27 @@ border: rgba($color: #888, $alpha: 0.2) 1px solid; } - @media only screen and (max-width: 600px) { - $calc-image-width: calc(100vw/3*2/var(--image-count)); + $calc-image-width: calc(100vw / 3 * 2 / var(--image-count)); .chat-message-item-image-multi { width: $calc-image-width; height: $calc-image-width; } - + .chat-message-item-image { - max-width: calc(100vw/3*2); + max-width: calc(100vw / 3 * 2); } } @media screen and (min-width: 600px) { - $max-image-width: calc(calc(1200px - var(--sidebar-width))/3*2/var(--image-count)); - $image-width: calc(calc(var(--window-width) - var(--sidebar-width))/3*2/var(--image-count)); + $max-image-width: calc( + calc(1200px - var(--sidebar-width)) / 3 * 2 / var(--image-count) + ); + $image-width: calc( + calc(var(--window-width) - var(--sidebar-width)) / 3 * 2 / + var(--image-count) + ); .chat-message-item-image-multi { width: $image-width; @@ -476,7 +482,7 @@ } .chat-message-item-image { - max-width: calc(calc(1200px - var(--sidebar-width))/3*2); + max-width: calc(calc(1200px - var(--sidebar-width)) / 3 * 2); } } @@ -494,7 +500,7 @@ z-index: 1; } -.chat-message-user>.chat-message-container>.chat-message-item { +.chat-message-user > .chat-message-container > .chat-message-item { background-color: var(--second); &:hover { @@ -605,7 +611,8 @@ min-height: 68px; } -.chat-input:focus {} +.chat-input:focus { +} .chat-input-send { background-color: var(--primary); @@ -624,4 +631,4 @@ .chat-input-send { bottom: 30px; } -} \ No newline at end of file +} diff --git a/app/components/chat.tsx b/app/components/chat/chat.tsx similarity index 95% rename from app/components/chat.tsx rename to app/components/chat/chat.tsx index 08bcd04fd56..56d1f72c1db 100644 --- a/app/components/chat.tsx +++ b/app/components/chat/chat.tsx @@ -9,34 +9,34 @@ import React, { RefObject, } from "react"; -import SendWhiteIcon from "../icons/send-white.svg"; -import BrainIcon from "../icons/brain.svg"; -import RenameIcon from "../icons/rename.svg"; -import ExportIcon from "../icons/share.svg"; -import ReturnIcon from "../icons/return.svg"; -import CopyIcon from "../icons/copy.svg"; -import LoadingIcon from "../icons/three-dots.svg"; -import LoadingButtonIcon from "../icons/loading.svg"; -import PromptIcon from "../icons/prompt.svg"; -import MaskIcon from "../icons/mask.svg"; -import MaxIcon from "../icons/max.svg"; -import MinIcon from "../icons/min.svg"; -import ResetIcon from "../icons/reload.svg"; -import BreakIcon from "../icons/break.svg"; -import SettingsIcon from "../icons/chat-settings.svg"; -import DeleteIcon from "../icons/clear.svg"; -import PinIcon from "../icons/pin.svg"; -import EditIcon from "../icons/rename.svg"; -import ConfirmIcon from "../icons/confirm.svg"; -import CancelIcon from "../icons/cancel.svg"; -import ImageIcon from "../icons/image.svg"; - -import LightIcon from "../icons/light.svg"; -import DarkIcon from "../icons/dark.svg"; -import AutoIcon from "../icons/auto.svg"; -import BottomIcon from "../icons/bottom.svg"; -import StopIcon from "../icons/pause.svg"; -import RobotIcon from "../icons/robot.svg"; +import SendWhiteIcon from "@/app/icons/send-white.svg"; +import BrainIcon from "@/app/icons/brain.svg"; +import RenameIcon from "@/app/icons/rename.svg"; +import ExportIcon from "@/app/icons/share.svg"; +import ReturnIcon from "@/app/icons/return.svg"; +import CopyIcon from "@/app/icons/copy.svg"; +import LoadingIcon from "@/app/icons/three-dots.svg"; +import LoadingButtonIcon from "@/app/icons/loading.svg"; +import PromptIcon from "@/app/icons/prompt.svg"; +import MaskIcon from "@/app/icons/mask.svg"; +import MaxIcon from "@/app/icons/max.svg"; +import MinIcon from "@/app/icons/min.svg"; +import ResetIcon from "@/app/icons/reload.svg"; +import BreakIcon from "@/app/icons/break.svg"; +import SettingsIcon from "@/app/icons/chat-settings.svg"; +import DeleteIcon from "@/app/icons/clear.svg"; +import PinIcon from "@/app/icons/pin.svg"; +import EditIcon from "@/app/icons/rename.svg"; +import ConfirmIcon from "@/app/icons/confirm.svg"; +import CancelIcon from "@/app/icons/cancel.svg"; +import ImageIcon from "@/app/icons/image.svg"; + +import LightIcon from "@/app/icons/light.svg"; +import DarkIcon from "@/app/icons/dark.svg"; +import AutoIcon from "@/app/icons/auto.svg"; +import BottomIcon from "@/app/icons/bottom.svg"; +import StopIcon from "@/app/icons/pause.svg"; +import RobotIcon from "@/app/icons/robot.svg"; import { ChatMessage, @@ -49,7 +49,7 @@ import { useAppConfig, DEFAULT_TOPIC, ModelType, -} from "../store"; +} from "@/app/store"; import { copyToClipboard, @@ -59,17 +59,17 @@ import { getMessageTextContent, getMessageImages, isVisionModel, -} from "../utils"; +} from "@/app/utils"; import { uploadImage as uploadImageRemote } from "@/app/utils/chat"; import dynamic from "next/dynamic"; -import { ChatControllerPool } from "../client/controller"; -import { Prompt, usePromptStore } from "../store/prompt"; -import Locale from "../locales"; +import { ChatControllerPool } from "@/app/client/controller"; +import { Prompt, usePromptStore } from "@/app/store/prompt"; +import Locale from "@/app/locales"; -import { IconButton } from "./button"; +import { IconButton } from "@/app/components/button"; import styles from "./chat.module.scss"; import { @@ -80,7 +80,7 @@ import { showConfirm, showPrompt, showToast, -} from "./ui-lib"; +} from "@/app/components/ui-lib"; import { useNavigate } from "react-router-dom"; import { CHAT_PAGE_SIZE, @@ -89,20 +89,27 @@ import { REQUEST_TIMEOUT_MS, UNFINISHED_INPUT, ServiceProvider, -} from "../constant"; -import { Avatar } from "./emoji"; -import { ContextPrompts, MaskAvatar, MaskConfig } from "./mask"; -import { useMaskStore } from "../store/mask"; -import { ChatCommandPrefix, useChatCommand, useCommand } from "../command"; -import { prettyObject } from "../utils/format"; -import { ExportMessageModal } from "./exporter"; -import { getClientConfig } from "../config/client"; -import { useAllModels } from "../utils/hooks"; -import { MultimodalContent } from "../client/api"; - -const Markdown = dynamic(async () => (await import("./markdown")).Markdown, { - loading: () => , -}); +} from "@/app/constant"; +import { Avatar } from "../emoji"; +import { + ContextPrompts, + MaskAvatar, + MaskConfig, +} from "@/app/components/mask/mask"; +import { useMaskStore } from "@/app/store/mask"; +import { ChatCommandPrefix, useChatCommand, useCommand } from "@/app/command"; +import { prettyObject } from "@/app/utils/format"; +import { ExportMessageModal } from "@/app/components/exporter/exporter"; +import { getClientConfig } from "@/app/config/client"; +import { useAllModels } from "@/app/utils/hooks"; +import { MultimodalContent } from "@/app/client/api"; + +const Markdown = dynamic( + async () => (await import("../markdown/markdown")).Markdown, + { + loading: () => , + }, +); export function SessionConfigModel(props: { onClose: () => void }) { const chatStore = useChatStore(); diff --git a/app/components/chat/index.tsx b/app/components/chat/index.tsx new file mode 100644 index 00000000000..d27da0d9705 --- /dev/null +++ b/app/components/chat/index.tsx @@ -0,0 +1 @@ +export * from "./chat"; diff --git a/app/components/emoji.tsx b/app/components/emoji/emoji.tsx similarity index 91% rename from app/components/emoji.tsx rename to app/components/emoji/emoji.tsx index 3b1f5e7516b..47090138dc7 100644 --- a/app/components/emoji.tsx +++ b/app/components/emoji/emoji.tsx @@ -4,10 +4,10 @@ import EmojiPicker, { Theme as EmojiTheme, } from "emoji-picker-react"; -import { ModelType } from "../store"; +import { ModelType } from "@/app/store"; -import BotIcon from "../icons/bot.svg"; -import BlackBotIcon from "../icons/black-bot.svg"; +import BotIcon from "@/app/icons/bot.svg"; +import BlackBotIcon from "@/app/icons/black-bot.svg"; export function getEmojiUrl(unified: string, style: EmojiStyle) { // Whoever owns this Content Delivery Network (CDN), I am using your CDN to serve emojis diff --git a/app/components/emoji/index.tsx b/app/components/emoji/index.tsx new file mode 100644 index 00000000000..ebaf40c172a --- /dev/null +++ b/app/components/emoji/index.tsx @@ -0,0 +1 @@ +export * from "./emoji"; diff --git a/app/components/error.tsx b/app/components/error/error.tsx similarity index 83% rename from app/components/error.tsx rename to app/components/error/error.tsx index 914740f9686..b9eae4e0e36 100644 --- a/app/components/error.tsx +++ b/app/components/error/error.tsx @@ -1,11 +1,11 @@ import React from "react"; -import { IconButton } from "./button"; -import GithubIcon from "../icons/github.svg"; -import ResetIcon from "../icons/reload.svg"; -import { ISSUE_URL } from "../constant"; -import Locale from "../locales"; -import { showConfirm } from "./ui-lib"; -import { useSyncStore } from "../store/sync"; +import { IconButton } from "@/app/components/button"; +import GithubIcon from "@/app/icons/github.svg"; +import ResetIcon from "@/app/icons/reload.svg"; +import { ISSUE_URL } from "@/app/constant"; +import Locale from "@/app/locales"; +import { showConfirm } from "@/app/components/ui-lib"; +import { useSyncStore } from "@/app/store/sync"; interface IErrorBoundaryState { hasError: boolean; diff --git a/app/components/error/index.tsx b/app/components/error/index.tsx new file mode 100644 index 00000000000..0ad13d9140e --- /dev/null +++ b/app/components/error/index.tsx @@ -0,0 +1 @@ +export * from "./error"; diff --git a/app/components/exporter.module.scss b/app/components/exporter/exporter.module.scss similarity index 100% rename from app/components/exporter.module.scss rename to app/components/exporter/exporter.module.scss diff --git a/app/components/exporter.tsx b/app/components/exporter/exporter.tsx similarity index 93% rename from app/components/exporter.tsx rename to app/components/exporter/exporter.tsx index 948807d4ca2..35f0bc1436e 100644 --- a/app/components/exporter.tsx +++ b/app/components/exporter/exporter.tsx @@ -1,6 +1,11 @@ /* eslint-disable @next/next/no-img-element */ -import { ChatMessage, ModelType, useAppConfig, useChatStore } from "../store"; -import Locale from "../locales"; +import { + ChatMessage, + ModelType, + useAppConfig, + useChatStore, +} from "@/app/store"; +import Locale from "@/app/locales"; import styles from "./exporter.module.scss"; import { List, @@ -10,40 +15,46 @@ import { showImageModal, showModal, showToast, -} from "./ui-lib"; -import { IconButton } from "./button"; +} from "@/app/components/ui-lib"; +import { IconButton } from "@/app/components/button"; import { copyToClipboard, downloadAs, getMessageImages, useMobileScreen, -} from "../utils"; +} from "@/app/utils"; -import CopyIcon from "../icons/copy.svg"; -import LoadingIcon from "../icons/three-dots.svg"; -import ChatGptIcon from "../icons/chatgpt.png"; -import ShareIcon from "../icons/share.svg"; -import BotIcon from "../icons/bot.png"; +import CopyIcon from "@/app/icons/copy.svg"; +import LoadingIcon from "@/app/icons/three-dots.svg"; +import ChatGptIcon from "@/app/icons/chatgpt.png"; +import ShareIcon from "@/app/icons/share.svg"; +import BotIcon from "@/app/icons/bot.png"; -import DownloadIcon from "../icons/download.svg"; +import DownloadIcon from "@/app/icons/download.svg"; import { useEffect, useMemo, useRef, useState } from "react"; -import { MessageSelector, useMessageSelector } from "./message-selector"; -import { Avatar } from "./emoji"; +import { + MessageSelector, + useMessageSelector, +} from "@/app/components/message-selector/message-selector"; +import { Avatar } from "@/app/components/emoji"; import dynamic from "next/dynamic"; import NextImage from "next/image"; import { toBlob, toPng } from "html-to-image"; -import { DEFAULT_MASK_AVATAR } from "../store/mask"; - -import { prettyObject } from "../utils/format"; -import { EXPORT_MESSAGE_CLASS_NAME } from "../constant"; -import { getClientConfig } from "../config/client"; -import { type ClientApi, getClientApi } from "../client/api"; -import { getMessageTextContent } from "../utils"; - -const Markdown = dynamic(async () => (await import("./markdown")).Markdown, { - loading: () => , -}); +import { DEFAULT_MASK_AVATAR } from "@/app/store/mask"; + +import { prettyObject } from "@/app/utils/format"; +import { EXPORT_MESSAGE_CLASS_NAME } from "@/app/constant"; +import { getClientConfig } from "@/app/config/client"; +import { type ClientApi, getClientApi } from "@/app/client/api"; +import { getMessageTextContent } from "@/app/utils"; + +const Markdown = dynamic( + async () => (await import("@/app/components/markdown/markdown")).Markdown, + { + loading: () => , + }, +); export function ExportMessageModal(props: { onClose: () => void }) { return ( diff --git a/app/components/exporter/index.tsx b/app/components/exporter/index.tsx new file mode 100644 index 00000000000..0c7070773e1 --- /dev/null +++ b/app/components/exporter/index.tsx @@ -0,0 +1 @@ +export * from "./exporter"; diff --git a/app/components/home.module.scss b/app/components/home/home.module.scss similarity index 100% rename from app/components/home.module.scss rename to app/components/home/home.module.scss diff --git a/app/components/home.tsx b/app/components/home/home.tsx similarity index 77% rename from app/components/home.tsx rename to app/components/home/home.tsx index e127c65f8fd..c8e7adff15b 100644 --- a/app/components/home.tsx +++ b/app/components/home/home.tsx @@ -1,21 +1,21 @@ "use client"; -require("../polyfill"); +require("../../polyfill"); import { useState, useEffect } from "react"; import styles from "./home.module.scss"; -import BotIcon from "../icons/bot.svg"; -import LoadingIcon from "../icons/three-dots.svg"; +import BotIcon from "@/app/icons/bot.svg"; +import LoadingIcon from "@/app/icons/three-dots.svg"; -import { getCSSVar, useMobileScreen } from "../utils"; +import { getCSSVar, useMobileScreen } from "@/app/utils"; import dynamic from "next/dynamic"; -import { Path, SlotID } from "../constant"; -import { ErrorBoundary } from "./error"; +import { Path, SlotID } from "@/app/constant"; +import { ErrorBoundary } from "@/app/components/error"; -import { getISOLang, getLang } from "../locales"; +import { getISOLang, getLang } from "@/app/locales"; import { HashRouter as Router, @@ -23,12 +23,12 @@ import { Route, useLocation, } from "react-router-dom"; -import { SideBar } from "./sidebar"; -import { useAppConfig } from "../store/config"; -import { AuthPage } from "./auth"; -import { getClientConfig } from "../config/client"; -import { type ClientApi, getClientApi } from "../client/api"; -import { useAccessStore } from "../store"; +import { SideBar } from "@/app/components/sidebar"; +import { useAppConfig } from "@/app/store/config"; +import { AuthPage } from "@/app/components/auth/auth"; +import { getClientConfig } from "@/app/config/client"; +import { type ClientApi, getClientApi } from "@/app/client/api"; +import { useAccessStore } from "@/app/store"; export function Loading(props: { noLogo?: boolean }) { return ( @@ -39,21 +39,33 @@ export function Loading(props: { noLogo?: boolean }) { ); } -const Settings = dynamic(async () => (await import("./settings")).Settings, { - loading: () => , -}); - -const Chat = dynamic(async () => (await import("./chat")).Chat, { - loading: () => , -}); - -const NewChat = dynamic(async () => (await import("./new-chat")).NewChat, { - loading: () => , -}); - -const MaskPage = dynamic(async () => (await import("./mask")).MaskPage, { - loading: () => , -}); +const Settings = dynamic( + async () => (await import("@/app/components/settings/settings")).Settings, + { + loading: () => , + }, +); + +const Chat = dynamic( + async () => (await import("@/app/components/chat/chat")).Chat, + { + loading: () => , + }, +); + +const NewChat = dynamic( + async () => (await import("@/app/components/new-chat/new-chat")).NewChat, + { + loading: () => , + }, +); + +const MaskPage = dynamic( + async () => (await import("@/app/components/mask/mask")).MaskPage, + { + loading: () => , + }, +); export function useSwitchTheme() { const config = useAppConfig(); diff --git a/app/components/home/index.tsx b/app/components/home/index.tsx new file mode 100644 index 00000000000..84d36cd2911 --- /dev/null +++ b/app/components/home/index.tsx @@ -0,0 +1 @@ +export * from "./home"; diff --git a/app/components/input-range/index.tsx b/app/components/input-range/index.tsx new file mode 100644 index 00000000000..4da4c77680c --- /dev/null +++ b/app/components/input-range/index.tsx @@ -0,0 +1 @@ +export * from "./input-range"; diff --git a/app/components/input-range.module.scss b/app/components/input-range/input-range.module.scss similarity index 100% rename from app/components/input-range.module.scss rename to app/components/input-range/input-range.module.scss diff --git a/app/components/input-range.tsx b/app/components/input-range/input-range.tsx similarity index 100% rename from app/components/input-range.tsx rename to app/components/input-range/input-range.tsx diff --git a/app/components/markdown/index.tsx b/app/components/markdown/index.tsx new file mode 100644 index 00000000000..453ec62bcf0 --- /dev/null +++ b/app/components/markdown/index.tsx @@ -0,0 +1 @@ +export * from "./markdown"; diff --git a/app/components/markdown.tsx b/app/components/markdown/markdown.tsx similarity index 96% rename from app/components/markdown.tsx rename to app/components/markdown/markdown.tsx index 1afd7de3b45..a4deffb2fc7 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown/markdown.tsx @@ -6,13 +6,13 @@ import RehypeKatex from "rehype-katex"; import RemarkGfm from "remark-gfm"; import RehypeHighlight from "rehype-highlight"; import { useRef, useState, RefObject, useEffect, useMemo } from "react"; -import { copyToClipboard } from "../utils"; +import { copyToClipboard } from "@/app/utils"; import mermaid from "mermaid"; -import LoadingIcon from "../icons/three-dots.svg"; +import LoadingIcon from "@/app/icons/three-dots.svg"; import React from "react"; import { useDebouncedCallback } from "use-debounce"; -import { showImageModal } from "./ui-lib"; +import { showImageModal } from "@/app/components/ui-lib"; export function Mermaid(props: { code: string }) { const ref = useRef(null); diff --git a/app/components/mask/index.tsx b/app/components/mask/index.tsx new file mode 100644 index 00000000000..f27b1770814 --- /dev/null +++ b/app/components/mask/index.tsx @@ -0,0 +1 @@ +export * from "./mask"; diff --git a/app/components/mask.module.scss b/app/components/mask/mask.module.scss similarity index 98% rename from app/components/mask.module.scss rename to app/components/mask/mask.module.scss index d66d98864df..ed196001a7c 100644 --- a/app/components/mask.module.scss +++ b/app/components/mask/mask.module.scss @@ -1,4 +1,4 @@ -@import "../styles/animation.scss"; +@import "../../styles/animation.scss"; .mask-page { height: 100%; display: flex; diff --git a/app/components/mask.tsx b/app/components/mask/mask.tsx similarity index 94% rename from app/components/mask.tsx rename to app/components/mask/mask.tsx index 77682b0b1ec..e059d47dc82 100644 --- a/app/components/mask.tsx +++ b/app/components/mask/mask.tsx @@ -1,19 +1,19 @@ -import { IconButton } from "./button"; -import { ErrorBoundary } from "./error"; +import { IconButton } from "@/app/components/button"; +import { ErrorBoundary } from "@/app/components/error"; import styles from "./mask.module.scss"; -import DownloadIcon from "../icons/download.svg"; -import UploadIcon from "../icons/upload.svg"; -import EditIcon from "../icons/edit.svg"; -import AddIcon from "../icons/add.svg"; -import CloseIcon from "../icons/close.svg"; -import DeleteIcon from "../icons/delete.svg"; -import EyeIcon from "../icons/eye.svg"; -import CopyIcon from "../icons/copy.svg"; -import DragIcon from "../icons/drag.svg"; - -import { DEFAULT_MASK_AVATAR, Mask, useMaskStore } from "../store/mask"; +import DownloadIcon from "@/app/icons/download.svg"; +import UploadIcon from "@/app/icons/upload.svg"; +import EditIcon from "@/app/icons/edit.svg"; +import AddIcon from "@/app/icons/add.svg"; +import CloseIcon from "@/app/icons/close.svg"; +import DeleteIcon from "@/app/icons/delete.svg"; +import EyeIcon from "@/app/icons/eye.svg"; +import CopyIcon from "@/app/icons/copy.svg"; +import DragIcon from "@/app/icons/drag.svg"; + +import { DEFAULT_MASK_AVATAR, Mask, useMaskStore } from "@/app/store/mask"; import { ChatMessage, createMessage, @@ -21,8 +21,8 @@ import { ModelType, useAppConfig, useChatStore, -} from "../store"; -import { MultimodalContent, ROLES } from "../client/api"; +} from "@/app/store"; +import { MultimodalContent, ROLES } from "@/app/client/api"; import { Input, List, @@ -31,23 +31,23 @@ import { Popover, Select, showConfirm, -} from "./ui-lib"; -import { Avatar, AvatarPicker } from "./emoji"; -import Locale, { AllLangs, ALL_LANG_OPTIONS, Lang } from "../locales"; +} from "@/app/components/ui-lib"; +import { Avatar, AvatarPicker } from "@/app/components/emoji"; +import Locale, { AllLangs, ALL_LANG_OPTIONS, Lang } from "@/app/locales"; import { useNavigate } from "react-router-dom"; -import chatStyle from "./chat.module.scss"; +import chatStyle from "@/app/components/chat/chat.module.scss"; import { useEffect, useState } from "react"; import { copyToClipboard, downloadAs, getMessageImages, readFromFile, -} from "../utils"; -import { Updater } from "../typing"; -import { ModelConfigList } from "./model-config"; -import { FileName, Path } from "../constant"; -import { BUILTIN_MASK_STORE } from "../masks"; +} from "@/app/utils"; +import { Updater } from "@/app/typing"; +import { ModelConfigList } from "@/app/components/model-config"; +import { FileName, Path } from "@/app/constant"; +import { BUILTIN_MASK_STORE } from "@/app/masks"; import { nanoid } from "nanoid"; import { DragDropContext, @@ -55,7 +55,7 @@ import { Draggable, OnDragEndResponder, } from "@hello-pangea/dnd"; -import { getMessageTextContent } from "../utils"; +import { getMessageTextContent } from "@/app/utils"; // drag and drop helper function function reorder(list: T[], startIndex: number, endIndex: number): T[] { diff --git a/app/components/message-selector/index.tsx b/app/components/message-selector/index.tsx new file mode 100644 index 00000000000..c916a2561c1 --- /dev/null +++ b/app/components/message-selector/index.tsx @@ -0,0 +1 @@ +export * from "./message-selector"; diff --git a/app/components/message-selector.module.scss b/app/components/message-selector/message-selector.module.scss similarity index 100% rename from app/components/message-selector.module.scss rename to app/components/message-selector/message-selector.module.scss diff --git a/app/components/message-selector.tsx b/app/components/message-selector/message-selector.tsx similarity index 95% rename from app/components/message-selector.tsx rename to app/components/message-selector/message-selector.tsx index 8198a3cd4eb..58323c83ab9 100644 --- a/app/components/message-selector.tsx +++ b/app/components/message-selector/message-selector.tsx @@ -1,13 +1,13 @@ import { useEffect, useMemo, useState } from "react"; -import { ChatMessage, useAppConfig, useChatStore } from "../store"; -import { Updater } from "../typing"; -import { IconButton } from "./button"; -import { Avatar } from "./emoji"; -import { MaskAvatar } from "./mask"; -import Locale from "../locales"; +import { ChatMessage, useAppConfig, useChatStore } from "@/app/store"; +import { Updater } from "@/app/typing"; +import { IconButton } from "@/app/components/button"; +import { Avatar } from "@/app/components/emoji"; +import { MaskAvatar } from "@/app/components/mask"; +import Locale from "@/app/locales"; import styles from "./message-selector.module.scss"; -import { getMessageTextContent } from "../utils"; +import { getMessageTextContent } from "@/app/utils"; function useShiftRange() { const [startIndex, setStartIndex] = useState(); diff --git a/app/components/model-config/index.tsx b/app/components/model-config/index.tsx new file mode 100644 index 00000000000..d0ab1229a91 --- /dev/null +++ b/app/components/model-config/index.tsx @@ -0,0 +1 @@ +export * from "./model-config"; diff --git a/app/components/model-config.tsx b/app/components/model-config/model-config.tsx similarity index 96% rename from app/components/model-config.tsx rename to app/components/model-config/model-config.tsx index 346fd3a7129..134c081570a 100644 --- a/app/components/model-config.tsx +++ b/app/components/model-config/model-config.tsx @@ -1,10 +1,10 @@ import { ServiceProvider } from "@/app/constant"; -import { ModalConfigValidator, ModelConfig } from "../store"; +import { ModalConfigValidator, ModelConfig } from "@/app/store"; -import Locale from "../locales"; -import { InputRange } from "./input-range"; -import { ListItem, Select } from "./ui-lib"; -import { useAllModels } from "../utils/hooks"; +import Locale from "@/app/locales"; +import { InputRange } from "@/app/components/input-range"; +import { ListItem, Select } from "@/app/components/ui-lib"; +import { useAllModels } from "@/app/utils/hooks"; export function ModelConfigList(props: { modelConfig: ModelConfig; diff --git a/app/components/new-chat/index.tsx b/app/components/new-chat/index.tsx new file mode 100644 index 00000000000..12ca5c51da6 --- /dev/null +++ b/app/components/new-chat/index.tsx @@ -0,0 +1 @@ +export * from "./new-chat"; diff --git a/app/components/new-chat.module.scss b/app/components/new-chat/new-chat.module.scss similarity index 98% rename from app/components/new-chat.module.scss rename to app/components/new-chat/new-chat.module.scss index b291a23664a..7f8fb7df766 100644 --- a/app/components/new-chat.module.scss +++ b/app/components/new-chat/new-chat.module.scss @@ -1,4 +1,4 @@ -@import "../styles/animation.scss"; +@import "../../styles/animation.scss"; .new-chat { height: 100%; diff --git a/app/components/new-chat.tsx b/app/components/new-chat/new-chat.tsx similarity index 87% rename from app/components/new-chat.tsx rename to app/components/new-chat/new-chat.tsx index 54c646f237c..2648f160b7c 100644 --- a/app/components/new-chat.tsx +++ b/app/components/new-chat/new-chat.tsx @@ -1,21 +1,21 @@ import { useEffect, useRef, useState } from "react"; -import { Path, SlotID } from "../constant"; -import { IconButton } from "./button"; -import { EmojiAvatar } from "./emoji"; +import { Path, SlotID } from "@/app/constant"; +import { IconButton } from "@/app/components/button"; +import { EmojiAvatar } from "@/app/components/emoji"; import styles from "./new-chat.module.scss"; -import LeftIcon from "../icons/left.svg"; -import LightningIcon from "../icons/lightning.svg"; -import EyeIcon from "../icons/eye.svg"; +import LeftIcon from "@/app/icons/left.svg"; +import LightningIcon from "@/app/icons/lightning.svg"; +import EyeIcon from "@/app/icons/eye.svg"; import { useLocation, useNavigate } from "react-router-dom"; -import { Mask, useMaskStore } from "../store/mask"; -import Locale from "../locales"; -import { useAppConfig, useChatStore } from "../store"; -import { MaskAvatar } from "./mask"; -import { useCommand } from "../command"; -import { showConfirm } from "./ui-lib"; -import { BUILTIN_MASK_STORE } from "../masks"; +import { Mask, useMaskStore } from "@/app/store/mask"; +import Locale from "@/app/locales"; +import { useAppConfig, useChatStore } from "@/app/store"; +import { MaskAvatar } from "@/app/components/mask"; +import { useCommand } from "@/app/command"; +import { showConfirm } from "@/app/components/ui-lib"; +import { BUILTIN_MASK_STORE } from "@/app/masks"; function MaskItem(props: { mask: Mask; onClick?: () => void }) { return ( diff --git a/app/components/settings/index.tsx b/app/components/settings/index.tsx new file mode 100644 index 00000000000..dcf101b0c62 --- /dev/null +++ b/app/components/settings/index.tsx @@ -0,0 +1 @@ +export * from "./settings"; diff --git a/app/components/settings.module.scss b/app/components/settings/settings.module.scss similarity index 100% rename from app/components/settings.module.scss rename to app/components/settings/settings.module.scss diff --git a/app/components/settings.tsx b/app/components/settings/settings.tsx similarity index 96% rename from app/components/settings.tsx rename to app/components/settings/settings.tsx index e95722f1d28..ac6d9e36011 100644 --- a/app/components/settings.tsx +++ b/app/components/settings/settings.tsx @@ -2,22 +2,22 @@ import { useState, useEffect, useMemo } from "react"; import styles from "./settings.module.scss"; -import ResetIcon from "../icons/reload.svg"; -import AddIcon from "../icons/add.svg"; -import CloseIcon from "../icons/close.svg"; -import CopyIcon from "../icons/copy.svg"; -import ClearIcon from "../icons/clear.svg"; -import LoadingIcon from "../icons/three-dots.svg"; -import EditIcon from "../icons/edit.svg"; -import EyeIcon from "../icons/eye.svg"; -import DownloadIcon from "../icons/download.svg"; -import UploadIcon from "../icons/upload.svg"; -import ConfigIcon from "../icons/config.svg"; -import ConfirmIcon from "../icons/confirm.svg"; - -import ConnectionIcon from "../icons/connection.svg"; -import CloudSuccessIcon from "../icons/cloud-success.svg"; -import CloudFailIcon from "../icons/cloud-fail.svg"; +import ResetIcon from "@/app/icons/reload.svg"; +import AddIcon from "@/app/icons/add.svg"; +import CloseIcon from "@/app/icons/close.svg"; +import CopyIcon from "@/app/icons/copy.svg"; +import ClearIcon from "@/app/icons/clear.svg"; +import LoadingIcon from "@/app/icons/three-dots.svg"; +import EditIcon from "@/app/icons/edit.svg"; +import EyeIcon from "@/app/icons/eye.svg"; +import DownloadIcon from "@/app/icons/download.svg"; +import UploadIcon from "@/app/icons/upload.svg"; +import ConfigIcon from "@/app/icons/config.svg"; +import ConfirmIcon from "@/app/icons/confirm.svg"; + +import ConnectionIcon from "@/app/icons/connection.svg"; +import CloudSuccessIcon from "@/app/icons/cloud-success.svg"; +import CloudFailIcon from "@/app/icons/cloud-fail.svg"; import { Input, @@ -29,10 +29,10 @@ import { Select, showConfirm, showToast, -} from "./ui-lib"; -import { ModelConfigList } from "./model-config"; +} from "@/app/components/ui-lib"; +import { ModelConfigList } from "@/app/components/model-config"; -import { IconButton } from "./button"; +import { IconButton } from "@/app/components/button"; import { SubmitKey, useChatStore, @@ -40,15 +40,15 @@ import { useUpdateStore, useAccessStore, useAppConfig, -} from "../store"; +} from "@/app/store"; import Locale, { AllLangs, ALL_LANG_OPTIONS, changeLang, getLang, -} from "../locales"; -import { copyToClipboard } from "../utils"; +} from "@/app/locales"; +import { copyToClipboard } from "@/app/utils"; import Link from "next/link"; import { Anthropic, @@ -65,17 +65,17 @@ import { ServiceProvider, SlotID, UPDATE_URL, -} from "../constant"; -import { Prompt, SearchService, usePromptStore } from "../store/prompt"; -import { ErrorBoundary } from "./error"; -import { InputRange } from "./input-range"; +} from "@/app/constant"; +import { Prompt, SearchService, usePromptStore } from "@/app/store/prompt"; +import { ErrorBoundary } from "@/app/components/error"; +import { InputRange } from "@/app/components/input-range"; import { useNavigate } from "react-router-dom"; -import { Avatar, AvatarPicker } from "./emoji"; -import { getClientConfig } from "../config/client"; -import { useSyncStore } from "../store/sync"; +import { Avatar, AvatarPicker } from "@/app/components/emoji"; +import { getClientConfig } from "@/app/config/client"; +import { useSyncStore } from "@/app/store/sync"; import { nanoid } from "nanoid"; -import { useMaskStore } from "../store/mask"; -import { ProviderType } from "../utils/cloud"; +import { useMaskStore } from "@/app/store/mask"; +import { ProviderType } from "@/app/utils/cloud"; function EditPromptModal(props: { id: string; onClose: () => void }) { const promptStore = usePromptStore(); diff --git a/app/components/sidebar/index.tsx b/app/components/sidebar/index.tsx new file mode 100644 index 00000000000..01acaeffb14 --- /dev/null +++ b/app/components/sidebar/index.tsx @@ -0,0 +1 @@ +export * from "./sidebar"; diff --git a/app/components/sidebar.tsx b/app/components/sidebar/sidebar.tsx similarity index 88% rename from app/components/sidebar.tsx rename to app/components/sidebar/sidebar.tsx index 69b2e71f871..2f8f22d15a1 100644 --- a/app/components/sidebar.tsx +++ b/app/components/sidebar/sidebar.tsx @@ -1,21 +1,21 @@ import { useEffect, useRef, useMemo } from "react"; -import styles from "./home.module.scss"; +import styles from "@/app/components/home/home.module.scss"; -import { IconButton } from "./button"; -import SettingsIcon from "../icons/settings.svg"; -import GithubIcon from "../icons/github.svg"; -import ChatGptIcon from "../icons/chatgpt.svg"; -import AddIcon from "../icons/add.svg"; -import CloseIcon from "../icons/close.svg"; -import DeleteIcon from "../icons/delete.svg"; -import MaskIcon from "../icons/mask.svg"; -import PluginIcon from "../icons/plugin.svg"; -import DragIcon from "../icons/drag.svg"; +import { IconButton } from "@/app/components/button"; +import SettingsIcon from "@/app/icons/settings.svg"; +import GithubIcon from "@/app/icons/github.svg"; +import ChatGptIcon from "@/app/icons/chatgpt.svg"; +import AddIcon from "@/app/icons/add.svg"; +import CloseIcon from "@/app/icons/close.svg"; +import DeleteIcon from "@/app/icons/delete.svg"; +import MaskIcon from "@/app/icons/mask.svg"; +import PluginIcon from "@/app/icons/plugin.svg"; +import DragIcon from "@/app/icons/drag.svg"; -import Locale from "../locales"; +import Locale from "@/app/locales"; -import { useAppConfig, useChatStore } from "../store"; +import { useAppConfig, useChatStore } from "@/app/store"; import { DEFAULT_SIDEBAR_WIDTH, @@ -24,16 +24,19 @@ import { NARROW_SIDEBAR_WIDTH, Path, REPO_URL, -} from "../constant"; +} from "@/app/constant"; import { Link, useNavigate } from "react-router-dom"; -import { isIOS, useMobileScreen } from "../utils"; +import { isIOS, useMobileScreen } from "@/app/utils"; import dynamic from "next/dynamic"; -import { showConfirm, showToast } from "./ui-lib"; - -const ChatList = dynamic(async () => (await import("./chat-list")).ChatList, { - loading: () => null, -}); +import { showConfirm, showToast } from "@/app/components/ui-lib"; + +const ChatList = dynamic( + async () => (await import("@/app/components/chat-list")).ChatList, + { + loading: () => null, + }, +); function useHotKey() { const chatStore = useChatStore(); diff --git a/app/components/ui-lib/index.tsx b/app/components/ui-lib/index.tsx new file mode 100644 index 00000000000..8bcae8c98e9 --- /dev/null +++ b/app/components/ui-lib/index.tsx @@ -0,0 +1 @@ +export * from "./ui-lib"; diff --git a/app/components/ui-lib.module.scss b/app/components/ui-lib/ui-lib.module.scss similarity index 99% rename from app/components/ui-lib.module.scss rename to app/components/ui-lib/ui-lib.module.scss index 83c02f92a23..f7fffdc90be 100644 --- a/app/components/ui-lib.module.scss +++ b/app/components/ui-lib/ui-lib.module.scss @@ -1,4 +1,4 @@ -@import "../styles/animation.scss"; +@import "../../styles/animation.scss"; .card { background-color: var(--white); diff --git a/app/components/ui-lib.tsx b/app/components/ui-lib/ui-lib.tsx similarity index 95% rename from app/components/ui-lib.tsx rename to app/components/ui-lib/ui-lib.tsx index da700c0fb7c..79c002b0e51 100644 --- a/app/components/ui-lib.tsx +++ b/app/components/ui-lib/ui-lib.tsx @@ -1,20 +1,20 @@ /* eslint-disable @next/next/no-img-element */ import styles from "./ui-lib.module.scss"; -import LoadingIcon from "../icons/three-dots.svg"; -import CloseIcon from "../icons/close.svg"; -import EyeIcon from "../icons/eye.svg"; -import EyeOffIcon from "../icons/eye-off.svg"; -import DownIcon from "../icons/down.svg"; -import ConfirmIcon from "../icons/confirm.svg"; -import CancelIcon from "../icons/cancel.svg"; -import MaxIcon from "../icons/max.svg"; -import MinIcon from "../icons/min.svg"; - -import Locale from "../locales"; +import LoadingIcon from "@/app/icons/three-dots.svg"; +import CloseIcon from "@/app/icons/close.svg"; +import EyeIcon from "@/app/icons/eye.svg"; +import EyeOffIcon from "@/app/icons/eye-off.svg"; +import DownIcon from "@/app/icons/down.svg"; +import ConfirmIcon from "@/app/icons/confirm.svg"; +import CancelIcon from "@/app/icons/cancel.svg"; +import MaxIcon from "@/app/icons/max.svg"; +import MinIcon from "@/app/icons/min.svg"; + +import Locale from "@/app/locales"; import { createRoot } from "react-dom/client"; import React, { HTMLProps, useEffect, useState } from "react"; -import { IconButton } from "./button"; +import { IconButton } from "@/app/components/button"; export function Popover(props: { children: JSX.Element; diff --git a/app/page.tsx b/app/page.tsx index b3f169a9b74..66507445e20 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,8 +1,8 @@ import { Analytics } from "@vercel/analytics/react"; -import { Home } from "./components/home"; +import { Home } from "@/app/components/home"; -import { getServerSideConfig } from "./config/server"; +import { getServerSideConfig } from "@/app/config/server"; const serverConfig = getServerSideConfig(); diff --git a/app/store/chat.ts b/app/store/chat.ts index 5892ef0c8c6..ed065517162 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -1,7 +1,7 @@ import { trimTopic, getMessageTextContent } from "../utils"; import Locale, { getLang } from "../locales"; -import { showToast } from "../components/ui-lib"; +import { showToast } from "@/app/components/ui-lib"; import { ModelConfig, ModelType, useAppConfig } from "./config"; import { createEmptyMask, Mask } from "./mask"; import { diff --git a/app/store/sync.ts b/app/store/sync.ts index d3582e3c935..3546708076b 100644 --- a/app/store/sync.ts +++ b/app/store/sync.ts @@ -10,7 +10,7 @@ import { setLocalAppState, } from "../utils/sync"; import { downloadAs, readFromFile } from "../utils"; -import { showToast } from "../components/ui-lib"; +import { showToast } from "@/app/components/ui-lib"; import Locale from "../locales"; import { createSyncClient, ProviderType } from "../utils/cloud"; import { corsPath } from "../utils/cors"; @@ -100,15 +100,17 @@ export const useSyncStore = createPersistStore( const remoteState = await client.get(config.username); if (!remoteState || remoteState === "") { await client.set(config.username, JSON.stringify(localState)); - console.log("[Sync] Remote state is empty, using local state instead."); - return + console.log( + "[Sync] Remote state is empty, using local state instead.", + ); + return; } else { const parsedRemoteState = JSON.parse( await client.get(config.username), ) as AppState; mergeAppState(localState, parsedRemoteState); setLocalAppState(localState); - } + } } catch (e) { console.log("[Sync] failed to get remote state", e); throw e; diff --git a/app/utils.ts b/app/utils.ts index 2f2c8ae95ab..497f9ec0118 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { showToast } from "./components/ui-lib"; +import { showToast } from "@/app/components/ui-lib"; import Locale from "./locales"; import { RequestMessage } from "./client/api";