diff --git a/.eslintrc.json b/.eslintrc.json index bffb357..d229e86 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,4 @@ { - "extends": "next/core-web-vitals" + "extends": "next/core-web-vitals", + "plugins": ["prettier"] } diff --git a/.gitignore b/.gitignore index 354be80..0a3e52a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts -dev \ No newline at end of file +dev + +public/prompts.json \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..0312b76 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged \ No newline at end of file diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 0000000..023bf16 --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,6 @@ +{ + "./app/**/*.{js,ts,jsx,tsx,json,html,css,scss,md}": [ + "eslint --fix", + "prettier --write" + ] +} \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..95cc75f --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,10 @@ +module.exports = { + printWidth: 80, + tabWidth: 2, + useTabs: false, + semi: true, + singleQuote: false, + trailingComma: 'all', + bracketSpacing: true, + arrowParens: 'always', +}; diff --git a/README.md b/README.md index c0f6d9d..dc1e7ca 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ One-Click to deploy your own ChatGPT web UI. - 在 1 分钟内使用 Vercel **免费一键部署** - 精心设计的 UI,响应式设计,支持深色模式 - 极快的首屏加载速度(~85kb) +- 海量的内置 prompt 列表,来自[中文](https://github.com/PlexPt/awesome-chatgpt-prompts-zh)和[英文](https://github.com/f/awesome-chatgpt-prompts) - 自动压缩上下文聊天记录,在节省 Token 的同时支持超长对话 - 一键导出聊天记录,完整的 Markdown 支持 - 拥有自己的域名?好上加好,绑定后即可在任何地方**无障碍**快速访问 @@ -31,6 +32,7 @@ One-Click to deploy your own ChatGPT web UI. - **Deploy for free with one-click** on Vercel in under 1 minute - Responsive design, and dark mode - Fast first screen loading speed (~85kb) +- Awesome prompts powered by [awesome-chatgpt-prompts-zh](https://github.com/PlexPt/awesome-chatgpt-prompts-zh) and [awesome-chatgpt-prompts](https://github.com/f/awesome-chatgpt-prompts) - Automatically compresses chat history to support long conversations while also saving your tokens - One-click export all chat history with full Markdown support diff --git a/app/components/home.module.scss b/app/components/home.module.scss index 730c05e..462b19c 100644 --- a/app/components/home.module.scss +++ b/app/components/home.module.scss @@ -333,11 +333,65 @@ .chat-input-panel { position: absolute; - bottom: 20px; + bottom: 0px; display: flex; width: 100%; padding: 20px; box-sizing: border-box; + flex-direction: column; +} + +@mixin single-line { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.prompt-hints { + min-height: 20px; + width: 100%; + max-height: 50vh; + overflow: auto; + display: flex; + flex-direction: column-reverse; + + background-color: var(--white); + border: var(--border-in-light); + border-radius: 10px; + margin-bottom: 10px; + box-shadow: var(--shadow); + + .prompt-hint { + color: var(--black); + padding: 6px 10px; + animation: slide-in ease 0.3s; + cursor: pointer; + transition: all ease 0.3s; + border: transparent 1px solid; + margin: 4px; + border-radius: 8px; + + &:not(:last-child) { + margin-top: 0; + } + + .hint-title { + font-size: 12px; + font-weight: bolder; + + @include single-line(); + } + .hint-content { + font-size: 12px; + + @include single-line(); + } + + &-selected, + &:hover { + border-color: var(--primary); + } + } } .chat-input-panel-inner { @@ -375,7 +429,7 @@ position: absolute; right: 30px; - bottom: 10px; + bottom: 30px; } .export-content { diff --git a/app/components/home.tsx b/app/components/home.tsx index 850c517..1a84d72 100644 --- a/app/components/home.tsx +++ b/app/components/home.tsx @@ -1,6 +1,7 @@ "use client"; import { useState, useRef, useEffect, useLayoutEffect } from "react"; +import { useDebouncedCallback } from "use-debounce"; import { IconButton } from "./button"; import styles from "./home.module.scss"; @@ -28,6 +29,7 @@ import Locale from "../locales"; import dynamic from "next/dynamic"; import { REPO_URL } from "../constant"; import { ControllerPool } from "../requests"; +import { Prompt, usePromptStore } from "../store/prompt"; export function Loading(props: { noLogo?: boolean }) { return ( @@ -146,24 +148,77 @@ function useSubmitHandler() { }; } +export function PromptHints(props: { + prompts: Prompt[]; + onPromptSelect: (prompt: Prompt) => void; +}) { + if (props.prompts.length === 0) return null; + + return ( +