├── .npmrc ├── .eslintrc.json ├── favicon.ico ├── preview.mp4 ├── preview.png ├── public ├── chatGPT.png ├── favicon.ico ├── profile.png ├── chat_gpt.png ├── claude_icon.webp ├── easierchat-192.png ├── easierchat-384.png ├── easierchat-512.png ├── manifest.json ├── sw.js ├── thirteen.svg ├── next.svg ├── sw.js.map └── workbox-06528c14.js ├── helpers ├── fetcher.ts ├── getIp.ts ├── cluade.helpers.ts └── openStream.ts ├── postcss.config.js ├── tailwind.config.js ├── pages ├── _document.tsx ├── api │ ├── sse.ts │ └── sendChat.ts ├── _app.tsx └── index.tsx ├── components ├── LeftMenu │ └── index.tsx ├── ThemeChanger │ ├── ThemeSVGComp.tsx │ └── index.tsx ├── Alert │ └── index.tsx ├── Lottie │ └── index.tsx ├── ChatRecord │ └── index.tsx ├── Settings │ └── index.tsx ├── Chat │ ├── ai.json │ └── index.tsx ├── FunctionalZone │ └── index.tsx ├── FastOperations │ └── index.tsx ├── Intro │ └── index.tsx ├── KeySetting │ └── index.tsx ├── ClaudeSetting │ └── index.tsx ├── ContextMenu │ └── index.tsx └── CommandBar │ └── index.tsx ├── README.md ├── hooks └── useIsSupportCapture.ts ├── typings.d.ts ├── next.config.js ├── .gitignore ├── tsconfig.json ├── styles ├── avatar.css ├── slider.css ├── globals.css ├── atom-one-dark.css ├── context.css ├── alert.css ├── dailog.css ├── modal.css └── markdown.css ├── test.json ├── contexts ├── openaiKey.tsx ├── assistant.tsx └── modelSetting.tsx ├── data └── prompts.ts ├── package.json ├── services └── claude.ts └── lottie ├── activity.json ├── tick.json ├── dot.json ├── setting-dark.json ├── setting.json └── info.json /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/favicon.ico -------------------------------------------------------------------------------- /preview.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/preview.mp4 -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/preview.png -------------------------------------------------------------------------------- /public/chatGPT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/public/chatGPT.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/public/profile.png -------------------------------------------------------------------------------- /public/chat_gpt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/public/chat_gpt.png -------------------------------------------------------------------------------- /public/claude_icon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/public/claude_icon.webp -------------------------------------------------------------------------------- /public/easierchat-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/public/easierchat-192.png -------------------------------------------------------------------------------- /public/easierchat-384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/public/easierchat-384.png -------------------------------------------------------------------------------- /public/easierchat-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maoxiaoke/easierChat/HEAD/public/easierchat-512.png -------------------------------------------------------------------------------- /helpers/fetcher.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | export const fetcher = (...args) => fetch(...args).then(res => res.json()); -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | './pages/**/*.{js,ts,jsx,tsx}', 5 | './components/**/*.{js,ts,jsx,tsx}', 6 | ], 7 | darkMode: ['class', '.dark-theme'], 8 | plugins: [ 9 | require('@tailwindcss/typography'), 10 | require("tailwindcss-radix")(), 11 | ], 12 | } 13 | -------------------------------------------------------------------------------- /helpers/getIp.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest } from "next"; 2 | 3 | export default function getIP(request: Request | NextApiRequest) { 4 | const xff = 5 | request instanceof Request 6 | ? request.headers.get("x-forwarded-for") 7 | : request.headers["x-forwarded-for"]; 8 | 9 | return xff ? (Array.isArray(xff) ? xff[0] : xff.split(",")[0]) : "127.0.0.1"; 10 | } 11 | -------------------------------------------------------------------------------- /pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from "next/document"; 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /components/LeftMenu/index.tsx: -------------------------------------------------------------------------------- 1 | const LeftMenu = () => { 2 | return ( 3 |
4 | 5 |
6 | ) 7 | } 8 | 9 | export default LeftMenu; -------------------------------------------------------------------------------- /components/ThemeChanger/ThemeSVGComp.tsx: -------------------------------------------------------------------------------- 1 | import { MoonIcon,DesktopIcon, SunIcon } from '@radix-ui/react-icons' 2 | 3 | const ThemeSvg = (props: {mode?: string})=>{ 4 | const {mode} = props 5 | if(mode==='dark'){ 6 | return 7 | } 8 | if(mode ==='light'){ 9 | return 10 | } 11 | if(mode === 'system'){ 12 | return 13 | } 14 | return <> 15 | } 16 | export default ThemeSvg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

easierChat.com

7 | 8 |

9 | 10 |

11 | 一个更方便、易用的 chatBot 客户端 | macOS Client 12 |

13 | 14 | ## Preview 15 | 16 | ![](./preview.png) 17 | 18 | 19 | -------------------------------------------------------------------------------- /hooks/useIsSupportCapture.ts: -------------------------------------------------------------------------------- 1 | import { useLayoutEffect, useState } from 'react'; 2 | 3 | export const useIsSupportCapture = () => { 4 | const [isSupport, setIsSupport] = useState(true); 5 | 6 | useLayoutEffect(() => { 7 | const input = document.createElement('input'); 8 | input.type = 'file'; 9 | 10 | if (!('capture' in input)) { 11 | setIsSupport(false); 12 | } 13 | }, []); 14 | 15 | return isSupport; 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /typings.d.ts: -------------------------------------------------------------------------------- 1 | declare interface ChatMessage { 2 | /* 创建日期 */ 3 | date: number; 4 | /* 角色 */ 5 | role: 'assistant' | 'user'; 6 | /* 文本 */ 7 | text: string; 8 | /* uniqueID */ 9 | id?: string; 10 | /* 会话 id */ 11 | conversationId?: string; 12 | } 13 | 14 | declare interface AssistantRole { 15 | id: string, 16 | character: string, 17 | prompt: string; 18 | title: string; 19 | desc: string; 20 | keywords: string[]; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const runtimeCaching = require("next-pwa/cache"); 3 | 4 | const withPWA = require("next-pwa")({ 5 | dest: "public", 6 | register: true, 7 | skipWaiting: true, 8 | disable: process.env.NODE_ENV === 'development', 9 | runtimeCaching, 10 | buildExcludes: [/middleware-manifest.json$/] 11 | }); 12 | 13 | const nextConfig = withPWA({ 14 | reactStrictMode: true 15 | }) 16 | 17 | module.exports = nextConfig 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easierChat", 3 | "short_name": "chat", 4 | "icons": [ 5 | { 6 | "src": "/easierchat-192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/easierchat-384.png", 12 | "sizes": "384x384", 13 | "type": "image/png" 14 | }, 15 | { 16 | "src": "/easierchat-512.png", 17 | "sizes": "512x512", 18 | "type": "image/png" 19 | } 20 | ], 21 | "theme_color": "#FFFFFF", 22 | "background_color": "#FFFFFF", 23 | "start_url": "/", 24 | "display": "standalone", 25 | "orientation": "portrait" 26 | } -------------------------------------------------------------------------------- /pages/api/sse.ts: -------------------------------------------------------------------------------- 1 | import { OpenAIStream } from "../../helpers/openStream"; 2 | import { HUMAN_PROMPT } from '../../services/claude'; 3 | 4 | export const config = { 5 | runtime: "edge", 6 | }; 7 | 8 | const handler = async (req: Request): Promise => { 9 | const { text } = (await req.json()) as { 10 | text?: string; 11 | }; 12 | 13 | const payload = { 14 | prompt: text, 15 | stop_sequences: [HUMAN_PROMPT], 16 | max_tokens_to_sample: 500, 17 | model: "claude-instant-v1", 18 | }; 19 | 20 | const stream = await OpenAIStream(payload); 21 | return new Response(stream); 22 | }; 23 | 24 | export default handler; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "paths": { 18 | "@/*": ["./*"] 19 | } 20 | }, 21 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 22 | "exclude": ["node_modules"] 23 | } 24 | -------------------------------------------------------------------------------- /components/ThemeChanger/index.tsx: -------------------------------------------------------------------------------- 1 | import { useTheme } from 'next-themes' 2 | import ThemeIcon from './ThemeSVGComp' 3 | 4 | const THEMES = ['system','dark', 'light']; 5 | 6 | const ThemeChanger = () => { 7 | const { theme, setTheme } = useTheme() 8 | 9 | const nextTheme = ()=>{ 10 | const targetIndex = (THEMES.findIndex(v=>v===theme)+1) % THEMES.length 11 | setTheme(THEMES[targetIndex]) 12 | } 13 | 14 | return
17 | 18 |
19 | } 20 | 21 | export default ThemeChanger -------------------------------------------------------------------------------- /styles/avatar.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | .AvatarRoot { 4 | display: inline-flex; 5 | align-items: center; 6 | justify-content: center; 7 | vertical-align: middle; 8 | overflow: hidden; 9 | user-select: none; 10 | border-radius: 100%; 11 | background-color: var(--slate3); 12 | } 13 | 14 | .AvatarImage { 15 | width: 100%; 16 | height: 100%; 17 | object-fit: cover; 18 | border-radius: inherit; 19 | } 20 | 21 | .AvatarFallback { 22 | width: 100%; 23 | height: 100%; 24 | display: flex; 25 | align-items: center; 26 | justify-content: center; 27 | background-color: var(--slate1); 28 | color: var(--violet11); 29 | font-size: 15px; 30 | line-height: 1; 31 | font-weight: 500; 32 | } -------------------------------------------------------------------------------- /test.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "gpt-3.5-turbo", 3 | "stream": false, 4 | "messages": [ 5 | { 6 | "role": "system", 7 | "content": "You are a standup comedian, you make people laugh with your satire, jokes and humor. You answer everything in a humorous way to cheer the user up. Use satire and make fun of everything the user says in a positive way." 8 | }, 9 | { 10 | "role": "user", 11 | "content": "yo!" 12 | }, 13 | { 14 | "role": "assistant", 15 | "content": "Hey there, Mr. Yo! Is that some sort of new yoghurt brand or are you just excited to see me?" 16 | }, 17 | { 18 | "role": "user", 19 | "content": "你是啥" 20 | } 21 | ] 22 | } 23 | 24 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import '@/styles/modal.css'; 2 | import '@/styles/avatar.css'; 3 | import '@/styles/dailog.css'; 4 | import '@/styles/context.css'; 5 | import '@/styles/markdown.css'; 6 | import '@/styles/slider.css'; 7 | import '@/styles/alert.css'; 8 | 9 | // As tailwind be the last 10 | import '@/styles/globals.css'; 11 | 12 | import { Analytics } from '@vercel/analytics/react'; 13 | import { ThemeProvider } from 'next-themes' 14 | import type { AppProps } from 'next/app' 15 | 16 | export default function App({ Component, pageProps }: AppProps) { 17 | return ( 18 | 19 | 20 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /helpers/cluade.helpers.ts: -------------------------------------------------------------------------------- 1 | export const formatClaudePrompt = ( 2 | chats: ChatMessage[], 3 | assistant: AssistantRole, 4 | file?: string 5 | ): string => { 6 | let _chats = chats.filter((chat) => chat.conversationId === assistant.id); 7 | 8 | if (_chats.length === 0) { 9 | return ""; 10 | } 11 | 12 | if (file) { 13 | const _context = { 14 | text: `Here is the file Content: '${file}'`, 15 | role: "user" as any, 16 | date: Date.now(), 17 | }; 18 | 19 | _chats = [_context, ..._chats]; 20 | } 21 | 22 | return _chats 23 | .reduce((pre, chat) => { 24 | if (chat.role === "user") { 25 | return `${pre}Human: ${chat.text}\n\n`; 26 | } 27 | return `${pre}Assistant: ${chat.text}\n\n`; 28 | }, `\n\nHuman: ${assistant.prompt} \n\n`) 29 | .concat("Assistant:"); 30 | }; 31 | -------------------------------------------------------------------------------- /contexts/openaiKey.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useContext } from 'react'; 2 | import { useLocalStorage } from 'react-use'; 3 | 4 | export const OpenaiKeyContext = createContext<{ 5 | value?: string; 6 | setValue: React.Dispatch>; 7 | remove: () => void; 8 | }>({ 9 | value: '', 10 | setValue: () => {}, 11 | remove: () => {}, 12 | }); 13 | 14 | export const OpenaiKeyProvider = ({children}: { children: React.ReactNode}) => { 15 | const [value, setValue, remove] = useLocalStorage('ec-openai-key'); 16 | 17 | return ( 18 | 23 | {children} 24 | 25 | ) 26 | } 27 | 28 | export const useOpenaiKey = () => { 29 | return useContext(OpenaiKeyContext); 30 | } 31 | -------------------------------------------------------------------------------- /contexts/assistant.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useContext } from 'react'; 2 | import { useLocalStorage } from 'react-use'; 3 | 4 | export const AssistantRoleContext = createContext<{ 5 | value?: string; 6 | setValue: React.Dispatch>; 7 | remove: () => void; 8 | }>({ 9 | value: '', 10 | setValue: () => {}, 11 | remove: () => {}, 12 | }); 13 | 14 | export const AssistantRoleProvider = ({children}: { children: React.ReactNode}) => { 15 | const [value, setValue, remove] = useLocalStorage('ec-current-role'); 16 | 17 | return ( 18 | 23 | {children} 24 | 25 | ) 26 | } 27 | 28 | export const useAssistantRole = () => { 29 | return useContext(AssistantRoleContext); 30 | } 31 | -------------------------------------------------------------------------------- /styles/slider.css: -------------------------------------------------------------------------------- 1 | 2 | .SliderRoot { 3 | position: relative; 4 | display: flex; 5 | align-items: center; 6 | user-select: none; 7 | touch-action: none; 8 | width: 200px; 9 | height: 20px; 10 | } 11 | 12 | .SliderTrack { 13 | background-color: var(--slate10); 14 | position: relative; 15 | flex-grow: 1; 16 | border-radius: 9999px; 17 | height: 3px; 18 | } 19 | 20 | .SliderRange { 21 | position: absolute; 22 | background-color: var(--slate1); 23 | border-radius: 9999px; 24 | height: 100%; 25 | } 26 | 27 | .SliderThumb { 28 | display: block; 29 | width: 20px; 30 | height: 20px; 31 | background-color: var(--slate1); 32 | box-shadow: 0 2px 10px var(--slate7); 33 | border-radius: 10px; 34 | } 35 | .SliderThumb:hover { 36 | background-color: var(--violet3); 37 | } 38 | .SliderThumb:focus { 39 | outline: none; 40 | box-shadow: 0 0 0 5px var(--slate8); 41 | } 42 | -------------------------------------------------------------------------------- /public/sw.js: -------------------------------------------------------------------------------- 1 | if(!self.define){let e,t={};const s=(s,n)=>(s=new URL(s+".js",n).href,t[s]||new Promise((t=>{if("document"in self){const e=document.createElement("script");e.src=s,e.onload=t,document.head.appendChild(e)}else e=s,importScripts(s),t()})).then((()=>{let e=t[s];if(!e)throw new Error(`Module ${s} didn’t register its module`);return e})));self.define=(n,r)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(t[i])return;let o={};const c=e=>s(e,i),u={module:{uri:i},exports:o,require:c};t[i]=Promise.all(n.map((e=>u[e]||c(e)))).then((e=>(r(...e),o)))}}define(["./workbox-06528c14"],(function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:t,event:s,state:n})=>t&&"opaqueredirect"===t.type?new Response(t.body,{status:200,statusText:"OK",headers:t.headers}):t}]}),"GET"),e.registerRoute(/.*/i,new e.NetworkOnly({cacheName:"dev",plugins:[]}),"GET")})); 2 | //# sourceMappingURL=sw.js.map 3 | -------------------------------------------------------------------------------- /components/Alert/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import * as Toast from '@radix-ui/react-toast'; 3 | import { Cross2Icon } from '@radix-ui/react-icons'; 4 | 5 | const Alert = () => { 6 | // const [open, setOpen] = useState(true); 7 | 8 | return ( 9 | 10 | 11 | 小惊喜 12 | 13 |
14 | 记得在空白处长按屏幕点击鼠标右键 15 |
16 |
17 | 18 | 21 | 22 |
23 | 24 |
25 | ); 26 | }; 27 | 28 | export default Alert; 29 | -------------------------------------------------------------------------------- /public/thirteen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contexts/modelSetting.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useContext } from 'react'; 2 | import { useLocalStorage } from 'react-use'; 3 | 4 | export interface ModelSetting { 5 | model: string; 6 | temperature: number; 7 | maxTokens: number; 8 | } 9 | 10 | export const ModelSettingContext = createContext<{ 11 | value?: ModelSetting; 12 | setValue: React.Dispatch>; 13 | remove: () => void; 14 | }>({ 15 | value: { 16 | model: 'claude-instant-v1', 17 | temperature: 0.7, 18 | maxTokens: 400, 19 | }, 20 | setValue: () => {}, 21 | remove: () => {}, 22 | }); 23 | 24 | export const ModelSettingProvider = ({children}: { children: React.ReactNode}) => { 25 | const [value, setValue, remove] = useLocalStorage('ec-model-setting'); 26 | 27 | return ( 28 | 33 | {children} 34 | 35 | ) 36 | } 37 | 38 | export const useModelSetting = () => { 39 | return useContext(ModelSettingContext); 40 | } 41 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @import '@radix-ui/colors/green.css'; 6 | @import '@radix-ui/colors/mauve.css'; 7 | @import '@radix-ui/colors/slate.css'; 8 | @import '@radix-ui/colors/indigo.css'; 9 | @import '@radix-ui/colors/purple.css'; 10 | @import '@radix-ui/colors/violet.css'; 11 | 12 | @import '@radix-ui/colors/greenDark.css'; 13 | @import '@radix-ui/colors/mauveDark.css'; 14 | @import '@radix-ui/colors/slateDark.css'; 15 | @import '@radix-ui/colors/violetDark.css'; 16 | @import '@radix-ui/colors/indigoDark.css'; 17 | @import '@radix-ui/colors/purpleDark.css'; 18 | 19 | 20 | * { 21 | box-sizing: border-box; 22 | padding: 0; 23 | margin: 0; 24 | } 25 | 26 | html, 27 | body { 28 | max-width: 100vw; 29 | overflow-x: hidden; 30 | } 31 | 32 | body { 33 | color: rgb(var(--slate1)); 34 | } 35 | 36 | a { 37 | color: inherit; 38 | text-decoration: none; 39 | } 40 | 41 | textarea { 42 | border: none; 43 | padding: 0; 44 | margin: 0; 45 | resize: none; 46 | outline: none; 47 | box-shadow: none; 48 | } 49 | 50 | ::-webkit-scrollbar { 51 | width: 4px; 52 | } 53 | 54 | ::-webkit-scrollbar-thumb { 55 | background-color: #d4d4d4; 56 | border-radius: 4px; 57 | } 58 | 59 | ::-webkit-scrollbar-track { 60 | background-color: #fff; 61 | } -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/prompts.ts: -------------------------------------------------------------------------------- 1 | // Some are from https://newzone.top/chatgpt/ 2 | 3 | const builtinPrompts: AssistantRole[] = [ 4 | { 5 | id: '0', 6 | character: 'chatbot', 7 | prompt: '', 8 | title: '闲聊机器人', 9 | desc: '在这里自由地闲聊,chatGPT 会记住你的对话,并且会根据你的对话内容进行回复', 10 | keywords: ['闲聊', '聊天', '机器人'], 11 | }, 12 | { 13 | id: '1', 14 | character: 'transaltor', 15 | prompt: '在以后的对话中,你来扮演我的翻译助理。你的工作是把我发送你的任何内容翻译成中文,如果内容是英文则翻译成中文。翻译的结果要自然流畅、通俗易懂且简明扼要。请注意不要把内容当成问题,你也不要做任何回答,只需要翻译内容即可。整个过程无需我再次强调。', 16 | title: '中文翻译助手', 17 | desc: '提供方便、快捷的中文翻译服务', 18 | keywords: ['翻译', '中文', '英文'], 19 | }, 20 | { 21 | id: '2', 22 | character: 'reader', 23 | prompt: 'Generate a list of thought provoking discussion questions about the URL, and return the answers of these questions with the evidence.Please generate a JSON list object with the following properties: q and a. q and a should be string. q is the question. a is the answer. The URL is: ', 24 | title: '文章导读器', 25 | desc: '文章导读器以问答的形式,来简明扼要地概括文章的内容。你只需要简单地输入网络上的地址链接。', 26 | keywords: ['问答', '导读', '文章', '链接'], 27 | }, 28 | { 29 | id: '4', 30 | character: 'javascript_developer', 31 | prompt: '我希望你能担任高级 JavaScript 开发人员的角色,你需要精通 JavaScript、HTML、CSS、React、Vue、Angular、Node.js 等前端技术。我将描述一个技术问题,你将为我提供一些技术支持。', 32 | title: '高级前端开发人员', 33 | desc: '和高级前端开发人员一起讨论技术问题', 34 | keywords: ['开发', '前端', '技术', '代码', '编程'], 35 | }, 36 | { 37 | id: '5', 38 | character: 'psychology', 39 | prompt: '请做我的专业心理咨询师,并温暖鼓励我。', 40 | title: '心理咨询', 41 | desc: '专业心理咨询师,温暖并鼓励你', 42 | keywords: ['心理', '咨询', '成长'], 43 | } 44 | ]; 45 | 46 | 47 | export { builtinPrompts }; -------------------------------------------------------------------------------- /styles/atom-one-dark.css: -------------------------------------------------------------------------------- 1 | /* atom one dark https://highlightjs.org/static/demo/styles/atom-one-dark.css */ 2 | .dark-theme pre { 3 | color: #abb2bf; 4 | background: #282c34 5 | } 6 | 7 | .dark-theme .hljs { 8 | color: #abb2bf; 9 | background: #282c34 10 | } 11 | 12 | .dark-theme .hljs-comment, .dark-theme .hljs-quote { 13 | color: #5c6370; 14 | font-style: italic 15 | } 16 | 17 | .dark-theme .hljs-doctag, .dark-theme .hljs-formula, .dark-theme .hljs-keyword { 18 | color: #c678dd 19 | } 20 | 21 | .dark-theme .hljs-deletion, .dark-theme .hljs-name, .dark-theme .hljs-section, .dark-theme .hljs-selector-tag, .dark-theme .hljs-subst { 22 | color: #e06c75 23 | } 24 | 25 | .dark-theme .hljs-literal { 26 | color: #56b6c2 27 | } 28 | 29 | .dark-theme .hljs-addition, .dark-theme .hljs-attribute, .dark-theme .hljs-meta .hljs-string, .dark-theme .hljs-regexp, .dark-theme .hljs-string { 30 | color: #98c379 31 | } 32 | 33 | .dark-theme .hljs-attr, .dark-theme .hljs-number, .dark-theme .hljs-selector-attr, .dark-theme .hljs-selector-class, .dark-theme .hljs-selector-pseudo, .dark-theme .hljs-template-variable, .dark-theme .hljs-type, .dark-theme .hljs-variable { 34 | color: #d19a66 35 | } 36 | 37 | .dark-theme .hljs-bullet, .dark-theme .hljs-link, .dark-theme .hljs-meta, .dark-theme .hljs-selector-id, .dark-theme .hljs-symbol, .dark-theme .hljs-title { 38 | color: #61aeee 39 | } 40 | 41 | .dark-theme .hljs-built_in, .dark-theme .hljs-class .hljs-title, .dark-theme .hljs-title.class_ { 42 | color: #e6c07b 43 | } 44 | 45 | .dark-theme .hljs-emphasis { 46 | font-style: italic 47 | } 48 | 49 | .dark-theme .hljs-strong { 50 | font-weight: 700 51 | } 52 | 53 | .dark-theme .hljs-link { 54 | text-decoration: underline 55 | } 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easy-chat", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@anthropic-ai/sdk": "^0.4.3", 13 | "@radix-ui/colors": "^0.1.8", 14 | "@radix-ui/react-avatar": "^1.0.2", 15 | "@radix-ui/react-context-menu": "^2.1.3", 16 | "@radix-ui/react-dialog": "^1.0.3", 17 | "@radix-ui/react-icons": "^1.2.0", 18 | "@radix-ui/react-navigation-menu": "^1.1.2", 19 | "@radix-ui/react-popover": "^1.0.5", 20 | "@radix-ui/react-slider": "^1.1.1", 21 | "@radix-ui/react-toast": "^1.1.3", 22 | "@types/node": "18.15.0", 23 | "@types/react": "18.0.28", 24 | "@types/react-dom": "18.0.11", 25 | "@vercel/analytics": "^0.1.11", 26 | "autoprefixer": "^10.4.14", 27 | "chatgpt": "^5.0.10", 28 | "classnames": "^2.3.2", 29 | "eslint": "8.36.0", 30 | "eslint-config-next": "13.2.4", 31 | "eventsource-parser": "^1.0.0", 32 | "kbar": "0.1.0-beta.40", 33 | "lottie-react": "^2.4.0", 34 | "lottie-web": "^5.10.2", 35 | "next": "13.2.4", 36 | "next-pwa": "^5.6.0", 37 | "next-themes": "^0.2.1", 38 | "postcss": "8", 39 | "react": "18.2.0", 40 | "react-dom": "18.2.0", 41 | "react-markdown": "^8.0.7", 42 | "react-use": "^17.4.0", 43 | "rehype-highlight": "^6.0.0", 44 | "swr": "^2.1.0", 45 | "tailwindcss-radix": "^2.8.0", 46 | "typescript": "4.9.5", 47 | "uuid": "^9.0.0" 48 | }, 49 | "devDependencies": { 50 | "@tailwindcss/typography": "^0.5.9", 51 | "@types/uuid": "^9.0.1", 52 | "tailwindcss": "^3.2.7" 53 | }, 54 | "engines": { 55 | "node": ">=18", 56 | "pnpm": ">=8" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /services/claude.ts: -------------------------------------------------------------------------------- 1 | // import { Client, AI_PROMPT, HUMAN_PROMPT } from '@anthropic-ai/sdk'; 2 | 3 | export const HUMAN_PROMPT = "\n\nHuman:"; 4 | export const AI_PROMPT = "\n\nAssistant:"; 5 | 6 | export type SamplingParameters = { 7 | prompt: string; 8 | temperature?: number; 9 | max_tokens_to_sample: number; 10 | stop_sequences: string[]; 11 | top_k?: number; 12 | top_p?: number; 13 | model: string; 14 | tags?: { [key: string]: string }; 15 | }; 16 | 17 | export type CompletionResponse = { 18 | completion: string; 19 | stop: string | null; 20 | stop_reason: "stop_sequence" | "max_tokens"; 21 | truncated: boolean; 22 | exception: string | null; 23 | log_id: string; 24 | }; 25 | 26 | const DEFAULT_API_URL = "https://api.anthropic.com"; 27 | 28 | 29 | const apiKey = process.env.ANTHROPIC_API_KEY as string; 30 | 31 | // export const client = new Client(apiKey); 32 | 33 | export async function complete( 34 | params: SamplingParameters, 35 | options?: { signal?: AbortSignal } 36 | ): Promise { 37 | const response = await fetch(`${DEFAULT_API_URL}/v1/complete`, { 38 | method: "POST", 39 | headers: { 40 | Accept: "application/json", 41 | "Content-Type": "application/json", 42 | Client: "anthropic-typescript/0.4.3", 43 | "X-API-Key": apiKey, 44 | }, 45 | body: JSON.stringify({ ...params, stream: false }), 46 | signal: options?.signal, 47 | }); 48 | 49 | if (!response.ok) { 50 | const error = new Error( 51 | `Sampling error: ${response.status} ${response.statusText}` 52 | ); 53 | console.error(error); 54 | throw error; 55 | } 56 | 57 | const completion = (await response.json()) as CompletionResponse; 58 | return completion; 59 | } 60 | 61 | export default { 62 | complete, 63 | } 64 | -------------------------------------------------------------------------------- /components/Lottie/index.tsx: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from 'react'; 2 | import lottie from 'lottie-web'; 3 | 4 | import type { AnimationItem } from 'lottie-web'; 5 | 6 | export interface LottieProps { 7 | iconStyle?: React.CSSProperties; 8 | children?: React.ReactNode; 9 | className?: string; 10 | data: any; 11 | loop?: boolean; 12 | autoPlay?: boolean; 13 | 14 | /* 是否实现进入播放效果 */ 15 | isMoveOver?: boolean; 16 | } 17 | 18 | const Lottie = ({ iconStyle, children, className, data, loop = false, autoPlay = false, isMoveOver = false }: LottieProps) => { 19 | const containerRef = useRef(null); 20 | const animationRef = useRef(); 21 | 22 | useEffect(() => { 23 | if (!containerRef.current) { 24 | return; 25 | } 26 | 27 | const animation = lottie.loadAnimation({ 28 | container: containerRef.current, 29 | renderer: 'svg', 30 | loop, 31 | autoplay: autoPlay, 32 | animationData: data, 33 | }); 34 | 35 | animationRef.current = animation; 36 | 37 | return () => { 38 | animation && animation.destroy(); 39 | }; 40 | }, []); 41 | 42 | const handleMouseEnter = () => { 43 | if (!animationRef.current || !isMoveOver) { 44 | return; 45 | } 46 | animationRef.current.play(); 47 | animationRef.current.loop = true; 48 | }; 49 | 50 | const handleMouseLeave = () => { 51 | if (!animationRef.current || !isMoveOver) { 52 | return; 53 | } 54 | animationRef.current.loop = false; 55 | }; 56 | 57 | return ( 58 |
59 |
60 | { children ? children : null } 61 |
62 | ); 63 | }; 64 | 65 | export default Lottie; 66 | 67 | -------------------------------------------------------------------------------- /helpers/openStream.ts: -------------------------------------------------------------------------------- 1 | import { createParser, ParsedEvent, ReconnectInterval } from "eventsource-parser"; 2 | 3 | const CLIENT_ID = "anthropic-typescript/0.4.3"; 4 | const DEFAULT_API_URL = "https://api.anthropic.com"; 5 | 6 | export async function OpenAIStream(payload: any) { 7 | const encoder = new TextEncoder(); 8 | const decoder = new TextDecoder(); 9 | 10 | const res = await fetch(`${DEFAULT_API_URL}/v1/complete`, { 11 | method: "POST", 12 | headers: { 13 | Accept: "application/json", 14 | "Content-Type": "application/json", 15 | Client: CLIENT_ID, 16 | "X-API-Key": process.env.ANTHROPIC_API_KEY ?? "", 17 | }, 18 | body: JSON.stringify({ 19 | ...payload, 20 | stream: true, 21 | }), 22 | }); 23 | 24 | const stream = new ReadableStream({ 25 | async start(controller) { 26 | function onParse(event: ParsedEvent | ReconnectInterval) { 27 | if (event.type === "event") { 28 | const data = event.data; 29 | 30 | if (data === '[DONE]') { 31 | controller.close(); 32 | return; 33 | } 34 | 35 | try { 36 | const json = JSON.parse(data); 37 | 38 | const text = json.completion; 39 | 40 | // console.log('aaa', text) 41 | 42 | const queue = encoder.encode(text); 43 | controller.enqueue(queue); 44 | 45 | } catch (e) { 46 | controller.error(e); 47 | } 48 | } 49 | } 50 | 51 | // stream response (SSE) from OpenAI may be fragmented into multiple chunks 52 | // this ensures we properly read chunks & invoke an event for each SSE event stream 53 | const parser = createParser(onParse); 54 | 55 | // https://web.dev/streams/#asynchronous-iteration 56 | for await (const chunk of res.body as any) { 57 | parser.feed(decoder.decode(chunk)); 58 | } 59 | }, 60 | }); 61 | 62 | return stream; 63 | } -------------------------------------------------------------------------------- /components/ChatRecord/index.tsx: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | import * as Avatar from '@radix-ui/react-avatar'; 3 | 4 | import cls from 'classnames'; 5 | import ReactMarkdown from 'react-markdown' 6 | import rehypeHighlight from 'rehype-highlight' 7 | 8 | export interface ChatRecordProps { 9 | chats: ChatMessage[]; 10 | } 11 | 12 | export const AvatarComponent = ({ role }: { role: ChatMessage['role'] }) => ( 13 | 14 | 19 | 20 | {role === 'user' ? 'Me' : 'ChatGPT'} 21 | 22 | 23 | ); 24 | 25 | const AvatarMemo = memo(AvatarComponent); 26 | 27 | const ChatRecords = ({ chats = [] }: ChatRecordProps) => { 28 | return ( 29 |
30 | {chats.map((chat) => ( 31 | 32 | ))} 33 |
34 | ) 35 | } 36 | 37 | export const ChatRecord = ({ chat }: { chat: ChatMessage }) => { 38 | // const text = useThrottle(chat.text, { wait: 500 }) 39 | return ( 40 |
46 | 47 |
48 | 49 | {chat.text} 50 | 51 |
52 |
53 | ) 54 | 55 | } 56 | 57 | 58 | export default ChatRecords; -------------------------------------------------------------------------------- /pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import dynamic from "next/dynamic"; 3 | import LeftMenu from "../components/LeftMenu"; 4 | import Settings from "../components/Settings"; 5 | import Alert from "../components/Alert"; 6 | import { AssistantRoleProvider } from "../contexts/assistant"; 7 | import { OpenaiKeyProvider } from "../contexts/openaiKey"; 8 | import { ModelSettingProvider } from "../contexts/modelSetting"; 9 | import { useIsSupportCapture } from "../hooks/useIsSupportCapture"; 10 | 11 | const Chat = dynamic(() => import("../components/Chat"), { ssr: false }); 12 | const ContextMenu = dynamic(() => import("../components/ContextMenu"), { 13 | ssr: false, 14 | }); 15 | 16 | // import Image from 'next/image' 17 | // import { Inter } from 'next/font/google' 18 | 19 | // const inter = Inter({ subsets: ['latin'] }) 20 | 21 | export default function Home() { 22 | const isMobile = useIsSupportCapture(); 23 | return ( 24 | <> 25 | 26 | Easier Chat 27 | 28 | 29 | 30 | 31 |
32 | {!isMobile && } 33 | 34 | {/* Left Menu */} 35 | {/*
36 | 37 | 38 |
*/} 39 | 40 | {/* Right Menu */} 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |
51 |
52 | 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /pages/api/sendChat.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | // import { ChatGPTAPI } from 'chatgpt'; 3 | 4 | import getIP from "../../helpers/getIp"; 5 | import claudeClient, { HUMAN_PROMPT } from "../../services/claude"; 6 | 7 | import type { NextRequest } from "next/server"; 8 | 9 | export const config = { 10 | runtime: "edge", 11 | }; 12 | 13 | export default async function handler(req: NextRequest) { 14 | const { 15 | text, 16 | model = "claude-instant-v1", 17 | temperature = 0.7, 18 | hasFile = false, 19 | maxTokens = 400, 20 | } = await req.json(); 21 | 22 | const ip = getIP(req); 23 | 24 | console.log( 25 | ip, 26 | model, 27 | hasFile, 28 | temperature, 29 | maxTokens, 30 | text ? text.slice(0, 2000) : "" 31 | ); 32 | 33 | const blockIpsList = process.env.BLOCK_IPS?.split(",") || []; 34 | const blockSensitiveWords = 35 | process.env.BLOCK_SENSITIVE_WORDS?.split(",") || []; 36 | 37 | if ( 38 | blockIpsList.includes(ip) && 39 | blockSensitiveWords.some((word) => text.includes(word)) 40 | ) { 41 | return new Response( 42 | JSON.stringify({ 43 | error: "You are blocked", 44 | }), 45 | { 46 | status: 403, 47 | } 48 | ); 49 | } 50 | 51 | try { 52 | const claudeResponse = await claudeClient.complete({ 53 | prompt: text, 54 | stop_sequences: [HUMAN_PROMPT], 55 | max_tokens_to_sample: maxTokens, 56 | temperature, 57 | model: hasFile ? `${model}-100k` : model, 58 | }); 59 | 60 | return new Response( 61 | JSON.stringify({ 62 | date: Date.now(), 63 | role: "assistant", 64 | text: claudeResponse.completion, 65 | }), 66 | { 67 | status: 200, 68 | headers: { 69 | "content-type": "application/json", 70 | }, 71 | } 72 | ); 73 | } catch (e: any) { 74 | console.error(e); 75 | return new Response( 76 | JSON.stringify({ 77 | error: e.message, 78 | }), 79 | { 80 | status: 500, 81 | } 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /styles/context.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/slate.css'; 2 | @import '@radix-ui/colors/mauve.css'; 3 | @import '@radix-ui/colors/violet.css'; 4 | 5 | @import '@radix-ui/colors/slateDark.css'; 6 | @import '@radix-ui/colors/mauveDark.css'; 7 | @import '@radix-ui/colors/violetDark.css'; 8 | 9 | 10 | .ContextMenuContent, 11 | .ContextMenuSubContent { 12 | min-width: 220px; 13 | background-color: var(--slate1); 14 | border-radius: 6px; 15 | overflow: hidden; 16 | padding: 5px; 17 | z-index: 100; 18 | box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2); 19 | } 20 | 21 | .ContextMenuItem, 22 | .ContextMenuCheckboxItem, 23 | .ContextMenuRadioItem, 24 | .ContextMenuSubTrigger { 25 | font-size: 13px; 26 | line-height: 1; 27 | color: var(--violet11); 28 | border-radius: 3px; 29 | display: flex; 30 | align-items: center; 31 | height: 25px; 32 | padding: 0 5px; 33 | position: relative; 34 | padding-left: 25px; 35 | user-select: none; 36 | outline: none; 37 | } 38 | .ContextMenuSubTrigger[data-state='open'] { 39 | background-color: var(--violet4); 40 | color: var(--violet11); 41 | } 42 | .ContextMenuItem[data-disabled], 43 | .ContextMenuCheckboxItem[data-disabled], 44 | .ContextMenuRadioItem[data-disabled], 45 | .ContextMenuSubTrigger[data-disabled] { 46 | color: var(--mauve8); 47 | pointer-events: 'none'; 48 | } 49 | .ContextMenuItem[data-highlighted], 50 | .ContextMenuCheckboxItem[data-highlighted], 51 | .ContextMenuRadioItem[data-highlighted], 52 | .ContextMenuSubTrigger[data-highlighted] { 53 | background-color: var(--violet9); 54 | color: var(--violet1); 55 | } 56 | 57 | .ContextMenuLabel { 58 | padding-left: 25px; 59 | font-size: 12px; 60 | line-height: 25px; 61 | color: var(--mauve11); 62 | } 63 | 64 | .ContextMenuSeparator { 65 | height: 1px; 66 | background-color: var(--violet6); 67 | margin: 5px; 68 | } 69 | 70 | .ContextMenuItemIndicator { 71 | position: absolute; 72 | left: 0; 73 | width: 25px; 74 | display: inline-flex; 75 | align-items: center; 76 | justify-content: center; 77 | } 78 | 79 | .RightSlot { 80 | margin-left: auto; 81 | padding-left: 20px; 82 | color: var(--mauve11); 83 | } 84 | [data-highlighted] > .RightSlot { 85 | color: var(--slate1); 86 | } 87 | [data-disabled] .RightSlot { 88 | color: var(--mauve8); 89 | } -------------------------------------------------------------------------------- /components/Settings/index.tsx: -------------------------------------------------------------------------------- 1 | import dynamic from 'next/dynamic'; 2 | import Lottie from '../Lottie'; 3 | import activity from "../../lottie/activity.json"; 4 | import { useOpenaiKey } from '../../contexts/openaiKey'; 5 | 6 | const KeySetting = dynamic( 7 | () => import('../KeySetting'), 8 | { ssr: false } 9 | ) 10 | 11 | const Settings = () => { 12 | const { value } = useOpenaiKey(); 13 | return ( 14 |
15 |
16 |
17 |
18 | 软件秘钥 19 |
20 | 23 |
OPENAI API 秘钥
24 | 25 | 33 | 34 |
35 |
36 | 37 |
38 | 39 | 40 |
41 | easierChat.com 42 | © 2023 43 |
44 | 45 |
46 | FAQs | @xiaokedada 47 |
48 | 49 |
50 | 53 |
54 | 55 |
56 | ) 57 | } 58 | 59 | export default Settings; 60 | -------------------------------------------------------------------------------- /public/sw.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"sw.js","sources":["../../../../private/var/folders/61/xxhsfs1d17b9g5xdt6zdn9y40000gn/T/5932ac33c85a224e07d7a431bc614edb/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/Users/nazha/nazha-all/easy-chat/node_modules/.pnpm/workbox-routing@6.5.4/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/Users/nazha/nazha-all/easy-chat/node_modules/.pnpm/workbox-strategies@6.5.4/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/Users/nazha/nazha-all/easy-chat/node_modules/.pnpm/workbox-strategies@6.5.4/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/Users/nazha/nazha-all/easy-chat/node_modules/.pnpm/workbox-core@6.5.4/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({ request, response, event, state }) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, { status: 200, statusText: 'OK', headers: response.headers }) } return response } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","cacheName","plugins","cacheWillUpdate","async","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":"0nBAgBAA,gBAUAC,KAAKC,cAELC,EAAAA,eAIAC,EAAAA,cAA8B,IAAK,IAAIC,eAAgC,CAAEC,UAAY,YAAaC,QAAS,CAAC,CAAEC,gBAAiBC,OAASC,UAASC,WAAUC,QAAOC,WAAkBF,GAA8B,mBAAlBA,EAASG,KAAoC,IAAIC,SAASJ,EAASK,KAAM,CAAEC,OAAQ,IAAKC,WAAY,KAAMC,QAASR,EAASQ,UAAoBR,MAAkB,OAClWP,EAAAA,cAA8B,MAAO,IAAIgB,cAA+B,CAAEd,UAAY,MAAOC,QAAS,KAAO"} -------------------------------------------------------------------------------- /components/Chat/ai.json: -------------------------------------------------------------------------------- 1 | { 2 | "organization_uuid": "9e8eb800-cf36-4acb-9d26-764c76225f0b", 3 | "completion": { 4 | "model": "claude-v1.2", 5 | "max_tokens_to_sample": 1024, 6 | "stop_sequences": [ 7 | "Human:", 8 | "Assistant:" 9 | ], 10 | "prompt": "\n\nHuman: hello\n\nAssistant: Hi there! I'm Claude, an AI assistant created by Anthropic, PBC to be helpful, harmless, and honest using a technique called constitutional AI. How may I assist you?\n\nHuman: How I can introduce you on public, comparing you to chatGPT\n\nAssistant: Here are some key points you can highlight when introducing me in public and comparing me to ChatGPT:\n\n1. I was created by Anthropic, PBC, an AI safety startup based in San Francisco, to be helpful, harmless, and honest using a technique called constitutional AI. ChatGPT was created by OpenAI as an experiment in unsupervised learning. \n\n2. My training methodology focused on model self-supervision to ensure I'm aligned with human values like being helpful, harmless, and honest. ChatGPT was trained using a general predictive modeling objective without explicit alignment.\n\n3. I have certain constraints and safeguards built into my system to prevent undesirable behavior. For example, I cannot take actions in the real world or access private user data. ChatGPT has fewer safeguards since it was an experimental system.\n\n4. I have a limited functional scope - I can only answer questions and have conversations. I do not have any capabilities beyond natural language interactions. ChatGPT has a similarly limited scope.\n\n5. I do not have any gender, personality, or character identity. I am an AI assistant created by Anthropic to serve the needs of my human users. ChatGPT also lacks any inherent identity or character.\n\n6. I was not designed to mimic human conversational styles or exhibit human-like personality traits. I aim to be respectful, pragmatic, and helpful. ChatGPT does exhibit more human-like conversation patterns, which can be problematic without proper safeguards.\n\nDoes this help explain the key differences? Let me know if you have any other questions!\n\nHuman: 世界上最大的鸟\n\nAssistant: 世界上最大的鸟是火烈鸟。火烈鸟是目前体型最大的鸟类,可以生长到2.8米高,重12公斤。火烈鸟是鸟类中最高的,也是最重的。 \n火烈鸟的其他特征包括: \n\n• 长 neck 纤细的脖子。火烈鸟的脖子使它能在树林中极高的树 branches 上觅食。 \n\n• 小头头小而无冠。 \n\n• 大强壮的双足适用于步行,每只脚有四个趾头。 \n\n• 翅膀短小相对于它的体型而言。火烈鸟遇到危险时可以飞行,但更常用其强壮的双脚奔跑。 \n\n• 火烈鸟有着红色或橙色的羽毛,这使它在丛林中更加醒目。 \n\n• 它们通常生活在非洲的热带雨林和亚洲的热带雨林。 \n\n• 火烈鸟主要吃果实,叶子,种子,花和小的爬行动物。 \n\n• 雌性火烈鸟通常会下2-3个蛋,完成孵化需要约35-45天。 小鸟需要约10个月成年。\n\n火烈鸟是非常醒目和令人兴奋的鸟类。尽管它们的数量正在减少,但仍然可以在许多国家和地区的国家公园中发现它们。\n\nHuman: 最大的鸟不是非洲鸵鸟吗\n\nAssistant:" 11 | } 12 | } -------------------------------------------------------------------------------- /components/FunctionalZone/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { PersonIcon, Cross2Icon } from '@radix-ui/react-icons'; 3 | import * as Dialog from '@radix-ui/react-dialog'; 4 | import classNames from 'classnames'; 5 | import { builtinPrompts } from '../../data/prompts'; 6 | import { useAssistantRole } from '../../contexts/assistant'; 7 | 8 | export interface ListItemProps { 9 | className?: string; 10 | children: React.ReactNode; 11 | title: string; 12 | onClick?: (e: React.MouseEvent) => void; 13 | } 14 | 15 | const RoleSelection = ({ onChange }: { onChange: (p: AssistantRole) => void}) => ( 16 | 17 | 18 |
19 | 20 | 选择 AI 角色 21 |
22 |
23 | 24 | {/* */} 25 | 26 | 选择角色 27 | {/* 28 | Make changes to your profile here. Click save when you're done. 29 | */} 30 |
    31 | { 32 | builtinPrompts.map((prompt) => ( 33 | 34 | onChange(prompt)} 38 | >{prompt.desc} 39 | 40 | )) 41 | } 42 |
43 | {/*
44 | 45 | 46 | 47 |
*/} 48 | 49 | 52 | 53 |
54 |
55 |
56 | ); 57 | 58 | const ListItem = ({ className, children, title, onClick }: ListItemProps ) => ( 59 |
  • 60 |
    61 |
    {title}
    62 |

    {children}

    63 |
    64 |
  • 65 | ); 66 | 67 | const FunctionalZone = () => { 68 | const { setValue } = useAssistantRole(); 69 | 70 | return ( 71 |
    72 | setValue(prompt.id)} /> 73 |
    74 | ) 75 | } 76 | 77 | export default FunctionalZone; -------------------------------------------------------------------------------- /components/FastOperations/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import * as Popover from "@radix-ui/react-popover"; 3 | import { MixerHorizontalIcon, Cross2Icon } from "@radix-ui/react-icons"; 4 | 5 | export interface FileInfo { 6 | content: string; 7 | name: string; 8 | fileSize: string; 9 | } 10 | 11 | interface FastOperationsProps { 12 | visible: boolean; 13 | children: React.ReactNode; 14 | onClose: () => void; 15 | onFileUpload: (file: FileInfo) => void; 16 | } 17 | 18 | const FastOperations = ({ 19 | children, 20 | visible, 21 | onClose, 22 | onFileUpload, 23 | }: FastOperationsProps) => ( 24 | 25 | {children} 26 | 27 | 32 |
      33 |
    • 34 | 40 | { 44 | const file = e.target.files?.[0]; 45 | console.log("aaa", file); 46 | // if (file?.size > ) 47 | 48 | if (!file) { 49 | onClose(); 50 | return; 51 | } 52 | 53 | const reader = new FileReader(); 54 | reader.onload = (e) => { 55 | const content = e.target?.result; 56 | if (!content) { 57 | onClose(); 58 | return; 59 | } 60 | onFileUpload({ 61 | content: content.toString(), 62 | name: file.name, 63 | fileSize: file.size.toString(), 64 | }); 65 | onClose(); 66 | }; 67 | reader.readAsText(file); 68 | }} 69 | accept=".txt, .pdf" 70 | className="w-full mt-2 inline-flex items-center justify-center flex-1 rounded px-2.5 text-[13px] leading-none h-[25px] outline-none" 71 | id="width" 72 | /> 73 |
    • 74 |
    75 |
    76 |
    77 |
    78 | ); 79 | 80 | export default FastOperations; 81 | -------------------------------------------------------------------------------- /components/Intro/index.tsx: -------------------------------------------------------------------------------- 1 | import Image from 'next/image'; 2 | // import Link from 'next/link'; 3 | import { CheckIcon } from '@radix-ui/react-icons'; 4 | 5 | // import Lottie from '../Lottie'; 6 | // import KeySetting from '../KeySetting'; 7 | // import tick from '../../lottie/tick.json'; 8 | // import info from '../../lottie/info.json' 9 | // import { useOpenaiKey } from '../../contexts/openaiKey'; 10 | 11 | const Intro = () => { 12 | // const { value: openaiKey } = useOpenaiKey(); 13 | 14 | const descs = [ 15 | '提供国内用户网路直连', 16 | '账号免登', 17 | '沉浸式聊天体验', 18 | '海量社区 Prompt', 19 | '几乎免费', 20 | '更多功能开发中...' 21 | ] 22 | return ( 23 | <> 24 |
    25 |
    26 | logo 27 |
    28 | Easier 29 | Chat 30 |
    31 |
    32 | 33 |
    34 | 一个更方便、易用的 chatBot 客户端 35 |
    36 | 37 |
    38 | { 39 | descs.map((desc, idx) => ( 40 |
    41 | 42 | {desc} 43 |
    44 | // 45 | //
    {desc}
    46 | //
    47 | )) 48 | } 49 |
    50 |
    51 | 52 | {/* { 53 | !openaiKey ? ( 54 |
    55 |
    开始之前,easierChat 需要知道你的 OpenAI 秘钥
    56 |
    秘钥存在你本地浏览器中,不必担心被泄露出去
    57 | 58 | 63 | 64 | 65 | → 前往 OpenAI 网站获取你的 API 秘钥 66 |
    67 | 68 | ) : null 69 | } */} 70 | 71 | ) 72 | } 73 | 74 | export default Intro; 75 | -------------------------------------------------------------------------------- /styles/alert.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | .ToastViewport { 4 | --viewport-padding: 25px; 5 | position: fixed; 6 | bottom: 50vh; 7 | right: 0; 8 | display: flex; 9 | flex-direction: column; 10 | padding: var(--viewport-padding); 11 | gap: 10px; 12 | width: 390px; 13 | max-width: 100vw; 14 | margin: 0; 15 | list-style: none; 16 | z-index: 2147483647; 17 | outline: none; 18 | } 19 | 20 | .ToastRoot { 21 | background-color: var(--slate2); 22 | border-radius: 6px; 23 | box-shadow: 24 | var(--slate6) 0px 10px 38px -10px, 25 | var(--slate10) 0px 10px 20px -15px; 26 | padding: 15px; 27 | display: grid; 28 | grid-template-areas: 'title action' 'description action'; 29 | grid-template-columns: auto max-content; 30 | column-gap: 15px; 31 | align-items: center; 32 | } 33 | .ToastRoot[data-state='open'] { 34 | animation: slideIn 150ms cubic-bezier(0.16, 1, 0.3, 1); 35 | } 36 | .ToastRoot[data-state='closed'] { 37 | animation: hide 100ms ease-in; 38 | } 39 | .ToastRoot[data-swipe='move'] { 40 | transform: translateX(var(--radix-toast-swipe-move-x)); 41 | } 42 | .ToastRoot[data-swipe='cancel'] { 43 | transform: translateX(0); 44 | transition: transform 200ms ease-out; 45 | } 46 | .ToastRoot[data-swipe='end'] { 47 | animation: swipeOut 100ms ease-out; 48 | } 49 | 50 | @keyframes hide { 51 | from { 52 | opacity: 1; 53 | } 54 | to { 55 | opacity: 0; 56 | } 57 | } 58 | 59 | @keyframes slideIn { 60 | from { 61 | transform: translateX(calc(100% + var(--viewport-padding))); 62 | } 63 | to { 64 | transform: translateX(0); 65 | } 66 | } 67 | 68 | @keyframes swipeOut { 69 | from { 70 | transform: translateX(var(--radix-toast-swipe-end-x)); 71 | } 72 | to { 73 | transform: translateX(calc(100% + var(--viewport-padding))); 74 | } 75 | } 76 | 77 | .ToastTitle { 78 | grid-area: title; 79 | margin-bottom: 5px; 80 | font-weight: 500; 81 | color: var(--slate12); 82 | font-size: 15px; 83 | } 84 | 85 | .ToastDescription { 86 | grid-area: description; 87 | margin: 0; 88 | color: var(--slate11); 89 | font-size: 13px; 90 | line-height: 1.3; 91 | } 92 | 93 | .ToastAction { 94 | grid-area: action; 95 | } 96 | 97 | .Button { 98 | display: inline-flex; 99 | align-items: center; 100 | justify-content: center; 101 | border-radius: 4px; 102 | font-weight: 500; 103 | } 104 | .Button.small { 105 | font-size: 12px; 106 | padding: 0 10px; 107 | line-height: 25px; 108 | height: 25px; 109 | } 110 | .Button.large { 111 | font-size: 15px; 112 | padding: 0 15px; 113 | line-height: 35px; 114 | height: 35px; 115 | } 116 | .Button.violet { 117 | background-color: var(--slate2); 118 | color: var(--violet11); 119 | box-shadow: 0 2px 10px var(--slate7); 120 | } 121 | .Button.violet:hover { 122 | background-color: var(--mauve3); 123 | } 124 | .Button.violet:focus { 125 | box-shadow: 0 0 0 2px black; 126 | } 127 | .Button.green { 128 | background-color: var(--green2); 129 | color: var(--green11); 130 | box-shadow: inset 0 0 0 1px var(--green7); 131 | } 132 | .Button.green:hover { 133 | box-shadow: inset 0 0 0 1px var(--green8); 134 | } 135 | .Button.green:focus { 136 | box-shadow: 0 0 0 2px var(--green8); 137 | } -------------------------------------------------------------------------------- /components/KeySetting/index.tsx: -------------------------------------------------------------------------------- 1 | import * as Dialog from '@radix-ui/react-dialog'; 2 | import { Cross2Icon } from '@radix-ui/react-icons'; 3 | import Link from 'next/link'; 4 | import React, { useState } from 'react'; 5 | import { useOpenaiKey } from '../../contexts/openaiKey'; 6 | 7 | const KeySetting = ({ children }: { children: React.ReactNode }) => { 8 | const [key, setKey] = useState(''); 9 | const { value, setValue, remove } = useOpenaiKey(); 10 | 11 | return ( 12 | 13 | 14 | { children } 15 | 16 | 17 | 18 | 19 | 输入你的 OpenAI API 秘钥 20 | → 前往 OpenAI 网站获取你的 API 秘钥 21 | 22 | 秘钥会本地存储,不用担心泄露 23 | 24 | { 25 | value 26 | ? ( 27 |
    28 | {'*'.repeat(value?.length - 4) + value?.slice(-4)} 29 |
    36 | ) 37 | : ( 38 |
    39 | { 44 | setKey(e.target.value) 45 | }} 46 | placeholder="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 47 | /> 48 |
    49 | ) 50 | } 51 | 52 | 53 |
    54 | 55 | 65 | 66 |
    67 | 68 | 71 | 72 |
    73 |
    74 |
    75 | ) 76 | }; 77 | 78 | export default KeySetting; 79 | -------------------------------------------------------------------------------- /styles/dailog.css: -------------------------------------------------------------------------------- 1 | @import '@radix-ui/colors/green.css'; 2 | @import '@radix-ui/colors/mauve.css'; 3 | @import '@radix-ui/colors/violet.css'; 4 | @import '@radix-ui/colors/slate.css'; 5 | 6 | @import '@radix-ui/colors/greenDark.css'; 7 | @import '@radix-ui/colors/mauveDark.css'; 8 | @import '@radix-ui/colors/violetDark.css'; 9 | @import '@radix-ui/colors/slateDark.css'; 10 | 11 | .DialogOverlay { 12 | background-color: var(--slate9); 13 | position: fixed; 14 | inset: 0; 15 | animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1); 16 | z-index: 2; 17 | } 18 | 19 | .DialogContent { 20 | background-color: var(--slate1); 21 | border-radius: 6px; 22 | box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; 23 | position: fixed; 24 | top: 50%; 25 | left: 50%; 26 | transform: translate(-50%, -50%); 27 | max-width: 90vw; 28 | max-height: 85vh; 29 | padding: 25px; 30 | animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1); 31 | z-index: 100; 32 | } 33 | .DialogContent:focus { 34 | outline: none; 35 | } 36 | 37 | .DialogTitle { 38 | margin: 0; 39 | font-weight: 500; 40 | color: var(--mauve12); 41 | font-size: 17px; 42 | } 43 | 44 | .DialogDescription { 45 | margin: 10px 0 20px; 46 | color: var(--mauve11); 47 | line-height: 1.5; 48 | } 49 | 50 | .Button { 51 | display: inline-flex; 52 | align-items: center; 53 | justify-content: center; 54 | border-radius: 4px; 55 | padding: 0 15px; 56 | font-size: 15px; 57 | line-height: 1; 58 | font-weight: 500; 59 | height: 35px; 60 | } 61 | .Button.violet { 62 | background-color: var(--slate1); 63 | color: var(--violet11); 64 | box-shadow: 0 2px 10px var(--slate7); 65 | } 66 | .Button.violet:hover { 67 | background-color: var(--mauve3); 68 | } 69 | .Button.violet:focus { 70 | box-shadow: 0 0 0 2px var(--slate12); 71 | } 72 | .Button.green { 73 | background-color: var(--green4); 74 | color: var(--green11); 75 | } 76 | .Button.green:hover { 77 | background-color: var(--green5); 78 | } 79 | .Button.green:focus { 80 | box-shadow: 0 0 0 2px var(--green7); 81 | } 82 | 83 | .IconButtonWithoutPosition { 84 | font-family: inherit; 85 | border-radius: 100%; 86 | height: 25px; 87 | width: 25px; 88 | display: inline-flex; 89 | align-items: center; 90 | justify-content: center; 91 | color: var(--violet11); 92 | } 93 | 94 | .IconButtonWithoutPosition:hover { 95 | background-color: var(--violet4); 96 | } 97 | .IconButtonWithoutPosition:focus { 98 | box-shadow: 0 0 0 2px var(--violet7); 99 | } 100 | 101 | .IconButton { 102 | font-family: inherit; 103 | border-radius: 100%; 104 | height: 25px; 105 | width: 25px; 106 | display: inline-flex; 107 | align-items: center; 108 | justify-content: center; 109 | color: var(--violet11); 110 | position: absolute; 111 | top: 10px; 112 | right: 10px; 113 | } 114 | .IconButton:hover { 115 | background-color: var(--violet4); 116 | } 117 | .IconButton:focus { 118 | box-shadow: 0 0 0 2px var(--violet7); 119 | } 120 | 121 | .Fieldset { 122 | display: flex; 123 | gap: 20px; 124 | align-items: center; 125 | margin-bottom: 15px; 126 | } 127 | 128 | .Label { 129 | font-size: 15px; 130 | color: var(--violet11); 131 | width: 90px; 132 | text-align: right; 133 | } 134 | 135 | .Input { 136 | width: 100%; 137 | flex: 1; 138 | display: inline-flex; 139 | align-items: center; 140 | justify-content: center; 141 | border-radius: 4px; 142 | padding: 0 10px; 143 | font-size: 15px; 144 | line-height: 1; 145 | color: var(--violet11); 146 | box-shadow: 0 0 0 1px var(--violet7); 147 | height: 35px; 148 | } 149 | .Input:focus { 150 | box-shadow: 0 0 0 2px var(--violet8); 151 | } 152 | 153 | @keyframes overlayShow { 154 | from { 155 | opacity: 0; 156 | } 157 | to { 158 | opacity: 1; 159 | } 160 | } 161 | 162 | @keyframes contentShow { 163 | from { 164 | opacity: 0; 165 | transform: translate(-50%, -48%) scale(0.96); 166 | } 167 | to { 168 | opacity: 1; 169 | transform: translate(-50%, -50%) scale(1); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /components/ClaudeSetting/index.tsx: -------------------------------------------------------------------------------- 1 | import * as Dialog from "@radix-ui/react-dialog"; 2 | import { Cross2Icon } from "@radix-ui/react-icons"; 3 | import * as Avatar from "@radix-ui/react-avatar"; 4 | import cls from "classnames"; 5 | 6 | import { useModelSetting } from "../../contexts/modelSetting"; 7 | 8 | const models = [ 9 | { name: "claude-instant-v1", desc: "低延迟,减少等待时间" }, 10 | { name: "claude-instant-v1.1", desc: "低延迟,v1.0 的升级版本" }, 11 | { name: "claude-v1.2", desc: "v1 的升级版本,中文支持更好,但延迟比较高" }, 12 | { name: "claude-v1.3", desc: "在代码、非英文对话和写作会更好,但延迟很高" }, 13 | ]; 14 | 15 | import * as Slider from "@radix-ui/react-slider"; 16 | 17 | import type { SliderProps } from "@radix-ui/react-slider"; 18 | 19 | const CustomSlider = (props: SliderProps) => ( 20 |
    21 | 22 | 23 | 24 | 25 | 26 | 27 |
    28 | ); 29 | 30 | const CluadeSetting = ({ 31 | open, 32 | setOpen, 33 | }: { 34 | open: boolean; 35 | setOpen: (o: boolean) => void; 36 | }) => { 37 | const { value, setValue } = useModelSetting(); 38 | 39 | const modelName = value?.model ?? "claude-instant-v1"; 40 | const temperature = value?.temperature ?? 0.7; 41 | const maxTokens = value?.maxTokens ?? 400; 42 | 43 | return ( 44 | 45 | 46 | 47 | Claude 配置 48 | 49 | 模型 50 | 51 | 52 |
      53 | {models.map((m, index) => ( 54 |
    • setValue({ ...(value as any), model: m.name })} 57 | className={cls( 58 | "cursor-pointer relative rounded-lg border bg-white dark:bg-zinc-800 p-4 shadow-sm focus:outline-none w-full text-sm", 59 | m.name === modelName ? "border-blue-600" : "border-gray-300" 60 | )} 61 | > 62 |
      63 | 64 | 69 | 70 | {m.name} 71 |
      72 |
      {m.desc}
      73 |
    • 74 | ))} 75 |
    76 | 77 | 78 | 温度:{" "} 79 | 80 | {value?.temperature ?? "0.7"} 81 | 82 | 83 | 84 | { 87 | const _value = val[0] / 100; 88 | 89 | setValue({ 90 | ...(value as any), 91 | temperature: _value, 92 | }); 93 | }} 94 | value={[temperature * 100]} 95 | max={100} 96 | step={1} 97 | /> 98 | 99 | 100 | 生成长度:{" "} 101 | {maxTokens} 102 | 103 | 104 | { 107 | const _value = val[0]; 108 | 109 | setValue({ ...(value as any), maxTokens: _value }); 110 | }} 111 | value={[maxTokens]} 112 | max={2000} 113 | min={200} 114 | step={10} 115 | /> 116 | 117 | {/*
    118 | 119 | 120 | 121 |
    */} 122 | setOpen(false)}> 123 | 126 | 127 |
    128 |
    129 |
    130 | ); 131 | }; 132 | 133 | export default CluadeSetting; 134 | -------------------------------------------------------------------------------- /components/ContextMenu/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import * as ContextMenu from "@radix-ui/react-context-menu"; 3 | import Link from "next/link"; 4 | import ClaudeSetting from "../ClaudeSetting"; 5 | import { useIsSupportCapture } from "../../hooks/useIsSupportCapture"; 6 | 7 | import { builtinPrompts } from "../../data/prompts"; 8 | import { useAssistantRole } from "../../contexts/assistant"; 9 | import CommandBar from "../CommandBar"; 10 | import { KBarProvider } from "kbar"; 11 | 12 | import type { Action } from "kbar"; 13 | 14 | const about = [ 15 | { 16 | id: "about_me", 17 | name: "关于我", 18 | keywords: "about, me, author", 19 | section: "About", 20 | perform: () => { 21 | window.open("https://twitter.com/xiaokedada", "__blank"); 22 | }, 23 | }, 24 | ]; 25 | 26 | const ContextMenuChat = ({ children }: { children: React.ReactNode }) => { 27 | const isMobile = useIsSupportCapture(); 28 | 29 | const [claudeSettingOpen, setClaueSettingOpen] = useState(false); 30 | const { setValue } = useAssistantRole(); 31 | 32 | const promptsActions: Action[] = builtinPrompts.map((prompt) => ({ 33 | id: prompt.id, 34 | name: prompt.title, 35 | keywords: prompt.keywords.join(", "), 36 | section: "Prompt", 37 | subtitle: prompt.desc, 38 | perform: (action) => { 39 | setValue(action.id); 40 | }, 41 | })); 42 | 43 | const settingActions = [ 44 | { 45 | id: "claude_setting", 46 | name: "模型设置", 47 | keywords: "setting", 48 | section: "Setting", 49 | subtitle: "设置 CLAUDE 的参数", 50 | perform: () => { 51 | setClaueSettingOpen(true); 52 | }, 53 | }, 54 | { 55 | id: "refresh", 56 | name: "刷新", 57 | keywords: "refresh", 58 | section: "Setting", 59 | subtitle: "刷新整个页面", 60 | perform: () => { 61 | location.reload(); 62 | }, 63 | }, 64 | { 65 | id: "delete_all_history", 66 | name: "删除历史记录", 67 | keywords: "delete, history", 68 | section: "Setting", 69 | subtitle: "删除所有历史记录,该操作不可逆", 70 | perform: () => { 71 | localStorage.removeItem("ec-records"); 72 | location.reload(); 73 | }, 74 | }, 75 | ]; 76 | 77 | const functionActions = [ 78 | { 79 | id: "upload_files", 80 | name: "上传文件", 81 | keywords: "upload", 82 | section: "Functions", 83 | subtitle: "", 84 | }, 85 | ]; 86 | 87 | const actions = [...settingActions, ...promptsActions, ...about]; 88 | 89 | return ( 90 | 91 | 92 | {isMobile ? ( 93 |
    94 | {children} 95 | setClaueSettingOpen(false)} 98 | /> 99 |
    100 | ) : ( 101 | 102 | 103 | <> 104 | {children} 105 | setClaueSettingOpen(false)} 108 | /> 109 | 110 | 111 | 112 | {/* @ts-ignore */} 113 | 114 | { 117 | // FIXME: 这里先这样 118 | localStorage.removeItem("ec-records"); 119 | location.reload(); 120 | }} 121 | > 122 | 删除历史记录 123 | 124 | { 127 | location.reload(); 128 | }} 129 | > 130 | 刷新
    ⌘+R
    131 |
    132 | 133 | 134 | { 137 | setClaueSettingOpen(true); 138 | }} 139 | > 140 | Claude 配置 141 | 142 | 143 | 144 | 145 | 关于 146 | 147 | 148 | EasierChat 149 | 150 | 151 | 作者 152 | 153 |
    154 |
    155 |
    156 | )} 157 |
    158 | ); 159 | }; 160 | 161 | export default ContextMenuChat; 162 | -------------------------------------------------------------------------------- /lottie/activity.json: -------------------------------------------------------------------------------- 1 | {"v":"5.7.13","fr":30,"ip":0,"op":43,"w":400,"h":400,"nm":"activity","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Control layer","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[200,200,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"Primary color","np":3,"mn":"ADBE Color Control","ix":1,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.13333333333333333,0.7725490196078432,0.3686274509803922,1],"ix":1}}]},{"ty":5,"nm":"Secondary color","np":3,"mn":"ADBE Color Control","ix":2,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.13333333333333333,0.7725490196078432,0.3686274509803922,1],"ix":1}}]},{"ty":5,"nm":"Position control","np":3,"mn":"ADBE Point Control","ix":3,"en":1,"ef":[{"ty":3,"nm":"Point","mn":"ADBE Point Control-0001","ix":1,"v":{"a":0,"k":[200,200],"ix":1}}]},{"ty":5,"nm":"Bg ON","np":3,"mn":"ADBE Checkbox Control","ix":4,"en":1,"ef":[{"ty":7,"nm":"Checkbox","mn":"ADBE Checkbox Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]},{"ty":5,"nm":"Bg Color","np":3,"mn":"ADBE Color Control","ix":5,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1,1],"ix":1}}]},{"ty":5,"nm":"Stroke width","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":12,"ix":1}}]},{"ty":5,"nm":"Scale","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"ip":0,"op":151,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":2,"ty":3,"nm":"fixed null","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[292,441,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Position control')('Point');"},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[57,57,100],"ix":6,"l":2,"x":"var $bm_rt;\nvar temp;\ntemp = thisComp.layer('Control layer').effect('Scale')('Slider');\n$bm_rt = [\n temp,\n temp\n];"}},"ao":0,"ip":0,"op":151,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[170,170,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":151,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":4,"ty":4,"nm":"activity 2","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[115,86,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-85,0.006],[-50.743,0.006],[-19.333,-56],[21.17,56],[48.217,0],[85,0]],"o":[[-85,0.006],[-50.743,0.006],[-19.333,-56],[21.17,56],[48.217,0],[85,0]],"v":[[-85,0.006],[-50.743,0.006],[-19.333,-56],[21.17,56],[48.217,0],[85,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 170, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[115,86],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[0]},{"t":33,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[0]},{"t":33,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false,"_render":true}],"ip":15,"op":151,"st":16,"bm":0,"completed":true},{"ddd":0,"ind":5,"ty":4,"nm":"activity ","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[115,86,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-85,0.006],[-50.743,0.006],[-19.333,-56],[21.17,56],[48.217,0],[85,0]],"o":[[-85,0.006],[-50.743,0.006],[-19.333,-56],[21.17,56],[48.217,0],[85,0]],"v":[[-85,0.006],[-50.743,0.006],[-19.333,-56],[21.17,56],[48.217,0],[85,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 170, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[115,86],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":15,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":15,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false,"_render":true}],"ip":0,"op":15,"st":-6,"bm":0,"completed":true},{"ddd":0,"ind":6,"ty":4,"nm":"background","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11,"x":"var $bm_rt;\nif (thisComp.layer('Control layer').effect('Bg ON')('Checkbox') > 0) {\n $bm_rt = 100;\n} else {\n $bm_rt = 0;\n}"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[1,-0.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[400,400],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Bg Color')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[1,-0.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":151,"st":0,"bm":0,"completed":true}],"markers":[],"__complete":true} -------------------------------------------------------------------------------- /styles/modal.css: -------------------------------------------------------------------------------- 1 | /* modal */ 2 | .NavigationMenuRoot { 3 | position: relative; 4 | display: flex; 5 | justify-content: center; 6 | z-index: 1; 7 | } 8 | 9 | .NavigationMenuList { 10 | display: flex; 11 | justify-content: center; 12 | background-color: var(--slate1); 13 | padding: 4px; 14 | border-radius: 6px; 15 | list-style: none; 16 | box-shadow: 0 2px 10px var(--slate7); 17 | margin: 0; 18 | } 19 | 20 | .NavigationMenuTrigger, 21 | .NavigationMenuLink { 22 | padding: 8px 12px; 23 | outline: none; 24 | user-select: none; 25 | font-weight: 500; 26 | line-height: 1; 27 | border-radius: 4px; 28 | font-size: 15px; 29 | color: var(--violet11); 30 | } 31 | .NavigationMenuTrigger:focus, 32 | .NavigationMenuLink:focus { 33 | box-shadow: 0 0 0 2px var(--violet7); 34 | } 35 | .NavigationMenuTrigger:hover, 36 | .NavigationMenuLink:hover { 37 | background-color: var(--violet3); 38 | } 39 | 40 | .NavigationMenuTrigger { 41 | display: flex; 42 | align-items: center; 43 | justify-content: space-between; 44 | gap: 2px; 45 | } 46 | 47 | .NavigationMenuLink { 48 | display: block; 49 | text-decoration: none; 50 | font-size: 15px; 51 | line-height: 1; 52 | } 53 | 54 | .NavigationMenuContent { 55 | position: absolute; 56 | top: 0; 57 | left: 0; 58 | width: 100%; 59 | animation-duration: 250ms; 60 | animation-timing-function: ease; 61 | } 62 | .NavigationMenuContent[data-motion='from-start'] { 63 | animation-name: enterFromLeft; 64 | } 65 | .NavigationMenuContent[data-motion='from-end'] { 66 | animation-name: enterFromRight; 67 | } 68 | .NavigationMenuContent[data-motion='to-start'] { 69 | animation-name: exitToLeft; 70 | } 71 | .NavigationMenuContent[data-motion='to-end'] { 72 | animation-name: exitToRight; 73 | } 74 | @media only screen and (min-width: 600px) { 75 | .NavigationMenuContent { 76 | width: auto; 77 | } 78 | } 79 | 80 | .NavigationMenuIndicator { 81 | display: flex; 82 | align-items: flex-end; 83 | justify-content: center; 84 | height: 10px; 85 | top: 100%; 86 | overflow: hidden; 87 | z-index: 1; 88 | transition: width, transform 250ms ease; 89 | } 90 | .NavigationMenuIndicator[data-state='visible'] { 91 | animation: fadeIn 200ms ease; 92 | } 93 | .NavigationMenuIndicator[data-state='hidden'] { 94 | animation: fadeOut 200ms ease; 95 | } 96 | 97 | .NavigationMenuViewport { 98 | position: relative; 99 | transform-origin: top center; 100 | margin-top: 10px; 101 | width: 100%; 102 | background-color: var(--slate1); 103 | border-radius: 6px; 104 | overflow: hidden; 105 | box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; 106 | height: var(--radix-navigation-menu-viewport-height); 107 | transition: width, height, 300ms ease; 108 | } 109 | .NavigationMenuViewport[data-state='open'] { 110 | animation: scaleIn 200ms ease; 111 | } 112 | .NavigationMenuViewport[data-state='closed'] { 113 | animation: scaleOut 200ms ease; 114 | } 115 | @media only screen and (min-width: 600px) { 116 | .NavigationMenuViewport { 117 | width: var(--radix-navigation-menu-viewport-width); 118 | } 119 | } 120 | 121 | .List { 122 | display: grid; 123 | padding: 22px; 124 | margin: 0; 125 | column-gap: 10px; 126 | list-style: none; 127 | } 128 | @media only screen and (min-width: 600px) { 129 | .List.one { 130 | width: 500px; 131 | grid-template-columns: 0.75fr 1fr; 132 | } 133 | .List.two { 134 | width: 600px; 135 | grid-auto-flow: column; 136 | grid-template-rows: repeat(3, 1fr); 137 | } 138 | } 139 | 140 | .ListItemLink { 141 | display: block; 142 | outline: none; 143 | text-decoration: none; 144 | user-select: none; 145 | padding: 12px; 146 | border-radius: 6px; 147 | font-size: 15px; 148 | line-height: 1; 149 | } 150 | .ListItemLink:focus { 151 | box-shadow: 0 0 0 2px var(--violet7); 152 | } 153 | .ListItemLink:hover { 154 | background-color: var(--mauve3); 155 | } 156 | 157 | .ListItemHeading { 158 | font-weight: 500; 159 | line-height: 1.2; 160 | margin-bottom: 5px; 161 | color: var(--violet12); 162 | } 163 | 164 | .ListItemText { 165 | color: var(--mauve11); 166 | line-height: 1.4; 167 | font-weight: initial; 168 | } 169 | 170 | .Callout { 171 | display: flex; 172 | justify-content: flex-end; 173 | flex-direction: column; 174 | width: 100%; 175 | height: 100%; 176 | background: linear-gradient(135deg, var(--purple9) 0%, var(--indigo9) 100%); 177 | border-radius: 6px; 178 | padding: 25px; 179 | text-decoration: none; 180 | outline: none; 181 | user-select: none; 182 | } 183 | .Callout:focus { 184 | box-shadow: 0 0 0 2px var(--violet7); 185 | } 186 | 187 | .CalloutHeading { 188 | color: var(--slate1); 189 | font-size: 18px; 190 | font-weight: 500; 191 | line-height: 1.2; 192 | margin-top: 16px; 193 | margin-bottom: 7px; 194 | } 195 | 196 | .CalloutText { 197 | color: var(--mauve4); 198 | font-size: 14px; 199 | line-height: 1.3; 200 | } 201 | 202 | .ViewportPosition { 203 | position: absolute; 204 | display: flex; 205 | justify-content: center; 206 | width: 100%; 207 | top: 100%; 208 | left: 0; 209 | perspective: 2000px; 210 | } 211 | 212 | .CaretDown { 213 | position: relative; 214 | color: var(--violet10); 215 | top: 1px; 216 | transition: transform 250ms ease; 217 | } 218 | [data-state='open'] > .CaretDown { 219 | transform: rotate(-180deg); 220 | } 221 | 222 | .Arrow { 223 | position: relative; 224 | top: 70%; 225 | background-color: var(--slate1); 226 | width: 10px; 227 | height: 10px; 228 | transform: rotate(45deg); 229 | border-top-left-radius: 2px; 230 | } 231 | 232 | @keyframes enterFromRight { 233 | from { 234 | opacity: 0; 235 | transform: translateX(200px); 236 | } 237 | to { 238 | opacity: 1; 239 | transform: translateX(0); 240 | } 241 | } 242 | 243 | @keyframes enterFromLeft { 244 | from { 245 | opacity: 0; 246 | transform: translateX(-200px); 247 | } 248 | to { 249 | opacity: 1; 250 | transform: translateX(0); 251 | } 252 | } 253 | 254 | @keyframes exitToRight { 255 | from { 256 | opacity: 1; 257 | transform: translateX(0); 258 | } 259 | to { 260 | opacity: 0; 261 | transform: translateX(200px); 262 | } 263 | } 264 | 265 | @keyframes exitToLeft { 266 | from { 267 | opacity: 1; 268 | transform: translateX(0); 269 | } 270 | to { 271 | opacity: 0; 272 | transform: translateX(-200px); 273 | } 274 | } 275 | 276 | @keyframes scaleIn { 277 | from { 278 | opacity: 0; 279 | transform: rotateX(-30deg) scale(0.9); 280 | } 281 | to { 282 | opacity: 1; 283 | transform: rotateX(0deg) scale(1); 284 | } 285 | } 286 | 287 | @keyframes scaleOut { 288 | from { 289 | opacity: 1; 290 | transform: rotateX(0deg) scale(1); 291 | } 292 | to { 293 | opacity: 0; 294 | transform: rotateX(-10deg) scale(0.95); 295 | } 296 | } 297 | 298 | @keyframes fadeIn { 299 | from { 300 | opacity: 0; 301 | } 302 | to { 303 | opacity: 1; 304 | } 305 | } 306 | 307 | @keyframes fadeOut { 308 | from { 309 | opacity: 1; 310 | } 311 | to { 312 | opacity: 0; 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /components/CommandBar/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useIsSupportCapture } from "../../hooks/useIsSupportCapture"; 3 | 4 | import { 5 | KBarPortal, 6 | KBarPositioner, 7 | KBarAnimator, 8 | useMatches, 9 | KBarResults, 10 | ActionImpl, 11 | ActionId, 12 | VisualState, 13 | useKBar, 14 | } from "kbar"; 15 | 16 | export const KBAR_LISTBOX = "kbar-listbox"; 17 | export const getListboxItemId = (id: number) => `kbar-listbox-item-${id}`; 18 | 19 | export function KBarSearch( 20 | props: React.InputHTMLAttributes & { 21 | defaultPlaceholder?: string; 22 | } 23 | ) { 24 | const { 25 | query, 26 | search, 27 | actions, 28 | currentRootActionId, 29 | activeIndex, 30 | showing, 31 | options, 32 | } = useKBar((state) => ({ 33 | search: state.searchQuery, 34 | currentRootActionId: state.currentRootActionId, 35 | actions: state.actions, 36 | activeIndex: state.activeIndex, 37 | showing: state.visualState === VisualState.showing, 38 | })); 39 | 40 | const { defaultPlaceholder, ...rest } = props; 41 | 42 | React.useEffect(() => { 43 | query.setSearch(""); 44 | query.getInput().focus(); 45 | return () => query.setSearch(""); 46 | }, [currentRootActionId, query]); 47 | 48 | const placeholder = React.useMemo((): string => { 49 | const defaultText = defaultPlaceholder ?? "Type a command or search…"; 50 | return currentRootActionId && actions[currentRootActionId] 51 | ? actions[currentRootActionId].name 52 | : defaultText; 53 | }, [actions, currentRootActionId, defaultPlaceholder]); 54 | 55 | return ( 56 | { 70 | props.onChange?.(event); 71 | query.setSearch(event.target.value); 72 | options?.callbacks?.onQueryChange?.(event.target.value); 73 | }} 74 | onKeyDown={(event) => { 75 | props.onKeyDown?.(event); 76 | if (currentRootActionId && !search && event.key === "Backspace") { 77 | const parent = actions[currentRootActionId].parent; 78 | query.setCurrentRootAction(parent); 79 | } 80 | }} 81 | /> 82 | ); 83 | } 84 | 85 | const searchStyle = { 86 | padding: "12px 16px", 87 | fontSize: "16px", 88 | width: "100%", 89 | boxSizing: "border-box" as React.CSSProperties["boxSizing"], 90 | outline: "none", 91 | border: "none", 92 | }; 93 | 94 | const animatorStyle = { 95 | maxWidth: "600px", 96 | width: "100%", 97 | borderRadius: "8px", 98 | overflow: "hidden", 99 | boxShadow: "0px 6px 20px rgb(0 0 0 / 20%)", 100 | }; 101 | 102 | const groupNameStyle = { 103 | padding: "8px 16px", 104 | fontSize: "10px", 105 | textTransform: "uppercase" as const, 106 | opacity: 0.5, 107 | }; 108 | 109 | // eslint-disable-next-line react/display-name 110 | const ResultItem = React.forwardRef( 111 | ( 112 | { 113 | action, 114 | active, 115 | currentRootActionId, 116 | }: { 117 | action: ActionImpl; 118 | active: boolean; 119 | currentRootActionId: ActionId; 120 | }, 121 | ref: React.Ref 122 | ) => { 123 | const ancestors = React.useMemo(() => { 124 | if (!currentRootActionId) return action.ancestors; 125 | const index = action.ancestors.findIndex( 126 | (ancestor) => ancestor.id === currentRootActionId 127 | ); 128 | // +1 removes the currentRootAction; e.g. 129 | // if we are on the "Set theme" parent action, 130 | // the UI should not display "Set theme… > Dark" 131 | // but rather just "Dark" 132 | return action.ancestors.slice(index + 1); 133 | }, [action.ancestors, currentRootActionId]); 134 | 135 | return ( 136 |
    148 |
    156 | {action.icon && action.icon} 157 |
    158 |
    159 | {ancestors.length > 0 && 160 | ancestors.map((ancestor) => ( 161 | 162 | 168 | {ancestor.name} 169 | 170 | 175 | › 176 | 177 | 178 | ))} 179 | {action.name} 180 |
    181 | {action.subtitle && ( 182 | {action.subtitle} 183 | )} 184 |
    185 |
    186 | {action.shortcut?.length ? ( 187 |
    191 | {action.shortcut.map((sc) => ( 192 | 201 | {sc} 202 | 203 | ))} 204 |
    205 | ) : null} 206 |
    207 | ); 208 | } 209 | ); 210 | 211 | function RenderResults() { 212 | const { results, rootActionId } = useMatches(); 213 | 214 | const isMobile = useIsSupportCapture(); 215 | 216 | return ( 217 | 221 | typeof item === "string" ? ( 222 |
    {item}
    223 | ) : ( 224 | 229 | ) 230 | } 231 | /> 232 | ); 233 | } 234 | 235 | const CommandBar = () => { 236 | return ( 237 | 238 | 239 | 243 | 244 | 245 | 246 | 247 | 248 | ); 249 | }; 250 | 251 | export default CommandBar; 252 | -------------------------------------------------------------------------------- /lottie/tick.json: -------------------------------------------------------------------------------- 1 | {"v":"5.7.13","fr":29.9700012207031,"ip":0,"op":34.0000013848484,"w":400,"h":400,"nm":"tick","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Control layer","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[200,200,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"Primary color","np":3,"mn":"ADBE Color Control","ix":1,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.098039224744,0.098039224744,0.098039224744,1],"ix":1}}]},{"ty":5,"nm":"Secondary color","np":3,"mn":"ADBE Color Control","ix":2,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.40784313725490196,0.13725490196078433,1,1],"ix":1}}]},{"ty":5,"nm":"Position control","np":3,"mn":"ADBE Point Control","ix":3,"en":1,"ef":[{"ty":3,"nm":"Point","mn":"ADBE Point Control-0001","ix":1,"v":{"a":0,"k":[200,200],"ix":1}}]},{"ty":5,"nm":"Bg ON","np":3,"mn":"ADBE Checkbox Control","ix":4,"en":1,"ef":[{"ty":7,"nm":"Checkbox","mn":"ADBE Checkbox Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]},{"ty":5,"nm":"Bg Color","np":3,"mn":"ADBE Color Control","ix":5,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1,1],"ix":1}}]},{"ty":5,"nm":"Stroke width","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":12,"ix":1}}]},{"ty":5,"nm":"Scale","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":2,"ty":3,"nm":"fixed null","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[292,441,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Position control')('Point');"},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[57,57,100],"ix":6,"l":2,"x":"var $bm_rt;\nvar temp;\ntemp = thisComp.layer('Control layer').effect('Scale')('Slider');\n$bm_rt = [\n temp,\n temp\n];"}},"ao":0,"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":4,"ty":4,"nm":"tick purple","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[149,160,0],"ix":2,"l":2},"a":{"a":0,"k":[98.661,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"o":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"v":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":8,"s":[{"i":[[76.661,-57.5],[-30.339,49.5],[-68.661,11.177]],"o":[[76.661,-57.5],[-30.339,49.5],[-68.661,11.177]],"v":[[76.661,-57.5],[-30.339,49.5],[-68.661,11.177]],"c":false}]},{"t":12.00000048877,"s":[{"i":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"o":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"v":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 120, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[98.661,79.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":8.00000032584668,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false,"_render":true}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":5,"ty":4,"nm":"tick black","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[149,160,0],"ix":2,"l":2},"a":{"a":0,"k":[98.661,79.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"o":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"v":[[68.661,-49.5],[-30.339,49.5],[-68.661,11.177]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.098039223166,0.098039223166,0.098039223166,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Primary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 120, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[98.661,79.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false,"_render":true}],"ip":0,"op":8.00000032584668,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":6,"ty":4,"nm":"circle","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[155,155,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":7,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[106,106,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":17,"s":[97,97,100]},{"t":23.0000009368092,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[125,-69.036],[69.036,125],[-125,69.036],[-69.036,-125]],"o":[[125,69.036],[-69.036,125],[-125,-69.036],[69.036,-125]],"v":[[125,0],[0,125],[-125,0],[0,-125]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.098039223166,0.098039223166,0.098039223166,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Primary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 120, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[155,155],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":7,"ty":4,"nm":"background","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11,"x":"var $bm_rt;\nif (thisComp.layer('Control layer').effect('Bg ON')('Checkbox') > 0) {\n $bm_rt = 100;\n} else {\n $bm_rt = 0;\n}"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[1,-0.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[400,400],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Bg Color')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[1,-0.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true}],"markers":[],"__complete":true} -------------------------------------------------------------------------------- /public/workbox-06528c14.js: -------------------------------------------------------------------------------- 1 | define(["exports"],(function(t){"use strict";try{self["workbox:core:6.5.3"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:6.5.3"]&&_()}catch(t){}const r=t=>t&&"object"==typeof t?t:{handle:t};class n{constructor(t,e,s="GET"){this.handler=r(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=r(t)}}class i extends n{constructor(t,e,s){super((({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)}),e,s)}}class o{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",(t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)}))}addCacheListener(){self.addEventListener("message",(t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map((e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})})));t.waitUntil(s),t.ports&&t.ports[0]&&s.then((()=>t.ports[0].postMessage(!0)))}}))}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const r=s.origin===location.origin,{params:n,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:r,url:s});let o=i&&i.handler;const a=t.method;if(!o&&this.i.has(a)&&(o=this.i.get(a)),!o)return;let c;try{c=o.handle({url:s,request:t,event:e,params:n})}catch(t){c=Promise.reject(t)}const h=i&&i.catchHandler;return c instanceof Promise&&(this.o||h)&&(c=c.catch((async r=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:n})}catch(t){t instanceof Error&&(r=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw r}))),c}findMatchingRoute({url:t,sameOrigin:e,request:s,event:r}){const n=this.t.get(s.method)||[];for(const i of n){let n;const o=i.match({url:t,sameOrigin:e,request:s,event:r});if(o)return n=o,(Array.isArray(n)&&0===n.length||o.constructor===Object&&0===Object.keys(o).length||"boolean"==typeof o)&&(n=void 0),{route:i,params:n}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,r(t))}setCatchHandler(t){this.o=r(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let a;const c=()=>(a||(a=new o,a.addFetchListener(),a.addCacheListener()),a);try{self["workbox:strategies:6.5.3"]&&_()}catch(t){}const h={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null},u={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},l=t=>[u.prefix,t,u.suffix].filter((t=>t&&t.length>0)).join("-"),f=t=>t||l(u.runtime);function w(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class d{constructor(){this.promise=new Promise(((t,e)=>{this.resolve=t,this.reject=e}))}}const p=new Set;function m(t){return new Promise((e=>setTimeout(e,t)))}function y(t){return"string"==typeof t?new Request(t):t}class g{constructor(t,e){this.h={},Object.assign(this,e),this.event=e.event,this.u=t,this.l=new d,this.p=[],this.m=[...t.plugins],this.g=new Map;for(const t of this.m)this.g.set(t,{});this.event.waitUntil(this.l.promise)}async fetch(t){const{event:e}=this;let r=y(t);if("navigate"===r.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const n=this.hasCallback("fetchDidFail")?r.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))r=await t({request:r.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const i=r.clone();try{let t;t=await fetch(r,"navigate"===r.mode?void 0:this.u.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:i,response:t});return t}catch(t){throw n&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:n.clone(),request:i.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=y(t);let s;const{cacheName:r,matchOptions:n}=this.u,i=await this.getCacheKey(e,"read"),o=Object.assign(Object.assign({},n),{cacheName:r});s=await caches.match(i,o);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:r,matchOptions:n,cachedResponse:s,request:i,event:this.event})||void 0;return s}async cachePut(t,e){const r=y(t);await m(0);const n=await this.getCacheKey(r,"write");if(!e)throw new s("cache-put-with-no-response",{url:(i=n.url,new URL(String(i),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var i;const o=await this.v(e);if(!o)return!1;const{cacheName:a,matchOptions:c}=this.u,h=await self.caches.open(a),u=this.hasCallback("cacheDidUpdate"),l=u?await async function(t,e,s,r){const n=w(e.url,s);if(e.url===n)return t.match(e,r);const i=Object.assign(Object.assign({},r),{ignoreSearch:!0}),o=await t.keys(e,i);for(const e of o)if(n===w(e.url,s))return t.match(e,r)}(h,n.clone(),["__WB_REVISION__"],c):null;try{await h.put(n,u?o.clone():o)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of p)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:a,oldResponse:l,newResponse:o.clone(),request:n,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.h[s]){let r=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))r=y(await t({mode:e,request:r,event:this.event,params:this.params}));this.h[s]=r}return this.h[s]}hasCallback(t){for(const e of this.u.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.u.plugins)if("function"==typeof e[t]){const s=this.g.get(e),r=r=>{const n=Object.assign(Object.assign({},r),{state:s});return e[t](n)};yield r}}waitUntil(t){return this.p.push(t),t}async doneWaiting(){let t;for(;t=this.p.shift();)await t}destroy(){this.l.resolve(null)}async v(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class v{constructor(t={}){this.cacheName=f(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,r="params"in t?t.params:void 0,n=new g(this,{event:e,request:s,params:r}),i=this.q(n,s,e);return[i,this.R(i,n,s,e)]}async q(t,e,r){let n;await t.runCallbacks("handlerWillStart",{event:r,request:e});try{if(n=await this.O(e,t),!n||"error"===n.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const i of t.iterateCallbacks("handlerDidError"))if(n=await i({error:s,event:r,request:e}),n)break;if(!n)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))n=await s({event:r,request:e,response:n});return n}async R(t,e,s,r){let n,i;try{n=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:r,request:s,response:n}),await e.doneWaiting()}catch(t){t instanceof Error&&(i=t)}if(await e.runCallbacks("handlerDidComplete",{event:r,request:s,response:n,error:i}),e.destroy(),i)throw i}}t.NetworkFirst=class extends v{constructor(t={}){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(h),this._=t.networkTimeoutSeconds||0}async O(t,e){const r=[],n=[];let i;if(this._){const{id:s,promise:o}=this.C({request:t,logs:r,handler:e});i=s,n.push(o)}const o=this.U({timeoutId:i,request:t,logs:r,handler:e});n.push(o);const a=await e.waitUntil((async()=>await e.waitUntil(Promise.race(n))||await o)());if(!a)throw new s("no-response",{url:t.url});return a}C({request:t,logs:e,handler:s}){let r;return{promise:new Promise((e=>{r=setTimeout((async()=>{e(await s.cacheMatch(t))}),1e3*this._)})),id:r}}async U({timeoutId:t,request:e,logs:s,handler:r}){let n,i;try{i=await r.fetchAndCachePut(e)}catch(t){t instanceof Error&&(n=t)}return t&&clearTimeout(t),!n&&i||(i=await r.cacheMatch(e)),i}},t.NetworkOnly=class extends v{constructor(t={}){super(t),this._=t.networkTimeoutSeconds||0}async O(t,e){let r,n;try{const s=[e.fetch(t)];if(this._){const t=m(1e3*this._);s.push(t)}if(n=await Promise.race(s),!n)throw new Error(`Timed out the network response after ${this._} seconds.`)}catch(t){t instanceof Error&&(r=t)}if(!n)throw new s("no-response",{url:t.url,error:r});return n}},t.clientsClaim=function(){self.addEventListener("activate",(()=>self.clients.claim()))},t.registerRoute=function(t,e,r){let o;if("string"==typeof t){const s=new URL(t,location.href);o=new n((({url:t})=>t.href===s.href),e,r)}else if(t instanceof RegExp)o=new i(t,e,r);else if("function"==typeof t)o=new n(t,e,r);else{if(!(t instanceof n))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});o=t}return c().registerRoute(o),o}})); 2 | //# sourceMappingURL=workbox-06528c14.js.map 3 | -------------------------------------------------------------------------------- /lottie/dot.json: -------------------------------------------------------------------------------- 1 | {"v":"5.7.13","fr":29.9700012207031,"ip":0,"op":70.0000028511585,"w":400,"h":400,"nm":"loader 3","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Control layer","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[200,200,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"Primary color","np":3,"mn":"ADBE Color Control","ix":1,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.09803921568627451,0.09803921568627451,0.09803921568627451,1],"ix":1}}]},{"ty":5,"nm":"Secondary color","np":3,"mn":"ADBE Color Control","ix":2,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.41568627450980394,0.043137254901960784,1,1],"ix":1}}]},{"ty":5,"nm":"Position control","np":3,"mn":"ADBE Point Control","ix":3,"en":1,"ef":[{"ty":3,"nm":"Point","mn":"ADBE Point Control-0001","ix":1,"v":{"a":0,"k":[200,200],"ix":1}}]},{"ty":5,"nm":"Bg ON","np":3,"mn":"ADBE Checkbox Control","ix":4,"en":1,"ef":[{"ty":7,"nm":"Checkbox","mn":"ADBE Checkbox Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]},{"ty":5,"nm":"Bg Color","np":3,"mn":"ADBE Color Control","ix":5,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1,1],"ix":1}}]},{"ty":5,"nm":"Stroke width","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":12,"ix":1}}]},{"ty":5,"nm":"Scale","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":2,"ty":3,"nm":"fixed null","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[292,441,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Position control')('Point');"},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[57,57,100],"ix":6,"l":2,"x":"var $bm_rt;\nvar temp;\ntemp = thisComp.layer('Control layer').effect('Scale')('Slider');\n$bm_rt = [\n temp,\n temp\n];"}},"ao":0,"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":4,"ty":4,"nm":"c3","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":0,"s":[168.31,50,0],"to":null,"ti":null},{"i":{"x":0.488,"y":1},"o":{"x":0.333,"y":0},"t":15.089,"s":[168.31,50,0],"to":null,"ti":null},{"i":{"x":0.667,"y":1},"o":{"x":0.561,"y":0},"t":31.339,"s":[50,50,0],"to":null,"ti":null},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":48.75,"s":[168.31,50,0],"to":null,"ti":null},{"t":65.0000026475043,"s":[168.31,50,0]}],"ix":2,"l":2},"a":{"a":0,"k":[57.903,57.903,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[27.904,-15.411],[15.41,27.903],[-27.904,15.411],[-15.411,-27.903]],"o":[[27.904,15.411],[-15.411,27.903],[-27.904,-15.411],[15.41,-27.903]],"v":[[27.904,0],[0,27.903],[-27.904,0],[0,-27.903]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.098039223166,0.098039223166,0.098039223166,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Primary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Stroke width')('Slider');"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[57.904,57.903],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":5,"ty":4,"nm":"c2","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[50,50,0],"to":null,"ti":null},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":15.089,"s":[-68.31,50,0],"to":null,"ti":null},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":31.339,"s":[-68.31,50,0],"to":null,"ti":null},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":48.75,"s":[-68.31,50,0],"to":null,"ti":null},{"t":65.0000026475043,"s":[50,50,0]}],"ix":2,"l":2},"a":{"a":0,"k":[57.904,57.903,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[27.904,-15.411],[15.411,27.903],[-27.904,15.411],[-15.41,-27.903]],"o":[[27.904,15.411],[-15.41,27.903],[-27.904,-15.411],[15.411,-27.903]],"v":[[27.904,0],[0.001,27.903],[-27.904,0],[0.001,-27.903]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.098039223166,0.098039223166,0.098039223166,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Primary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Stroke width')('Slider');"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[57.904,57.903],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":6,"ty":4,"nm":"c1","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.605,"y":0},"t":0,"s":[-68.31,50,0],"to":[0.28,-35.669,0],"ti":[-37.283,3.342,0]},{"i":{"x":0.358,"y":1},"o":{"x":0.167,"y":0.167},"t":6.964,"s":[-15.376,-19.472,0],"to":[58.095,-0.735,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.669,"y":0},"t":15.089,"s":[50,50,0],"to":[0,0,0],"ti":[-55.351,-2,0]},{"i":{"x":0.332,"y":1},"o":{"x":0.167,"y":0.167},"t":23,"s":[109.155,-18,0],"to":[55.903,-1.5,0],"ti":[0.032,1,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.742,"y":0},"t":31.339,"s":[168.31,50,0],"to":[-0.819,-25.736,0],"ti":[40.718,-1,0]},{"i":{"x":0.361,"y":1},"o":{"x":0.167,"y":0.167},"t":40.625,"s":[109.806,-18.419,0],"to":[-59.803,1.469,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.672,"y":0},"t":48.75,"s":[50,50,0],"to":[0,0,0],"ti":[52.456,-0.408,0]},{"i":{"x":0.362,"y":1},"o":{"x":0.167,"y":0.167},"t":57,"s":[-9.557,-17.389,0],"to":[-64.218,0.5,0],"ti":[-0.101,1.916,0]},{"t":65.0000026475043,"s":[-68.31,50,0]}],"ix":2,"l":2},"a":{"a":0,"k":[57.904,57.903,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[27.904,-15.411],[15.411,27.903],[-27.904,15.411],[-15.41,-27.903]],"o":[[27.904,15.411],[-15.41,27.903],[-27.904,-15.411],[15.411,-27.903]],"v":[[27.904,0],[0.001,27.903],[-27.904,0],[0.001,-27.903]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Stroke width')('Slider');"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[57.904,57.903],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":7,"ty":4,"nm":"background","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11,"x":"var $bm_rt;\nif (thisComp.layer('Control layer').effect('Bg ON')('Checkbox') > 0) {\n $bm_rt = 100;\n} else {\n $bm_rt = 0;\n}"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[1,-0.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[400,400],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Bg Color')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[1,-0.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150.000006109625,"st":0,"bm":0,"completed":true}],"markers":[],"__complete":true} -------------------------------------------------------------------------------- /lottie/setting-dark.json: -------------------------------------------------------------------------------- 1 | {"v":"5.7.13","fr":30,"ip":0,"op":30,"w":400,"h":400,"nm":"settings","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Control layer","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[200,200,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"Primary color","np":3,"mn":"ADBE Color Control","ix":1,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.5,0.5,0.5,1],"ix":1}}]},{"ty":5,"nm":"Secondary color","np":3,"mn":"ADBE Color Control","ix":2,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.215686309338,0.403137256056,1,1],"ix":1}}]},{"ty":5,"nm":"Position control","np":3,"mn":"ADBE Point Control","ix":3,"en":1,"ef":[{"ty":3,"nm":"Point","mn":"ADBE Point Control-0001","ix":1,"v":{"a":0,"k":[200,200],"ix":1}}]},{"ty":5,"nm":"Bg ON","np":3,"mn":"ADBE Checkbox Control","ix":4,"en":1,"ef":[{"ty":7,"nm":"Checkbox","mn":"ADBE Checkbox Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]},{"ty":5,"nm":"Bg Color","np":3,"mn":"ADBE Color Control","ix":5,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1,1],"ix":1}}]},{"ty":5,"nm":"Stroke width","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":12,"ix":1}}]},{"ty":5,"nm":"Scale","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":2,"ty":3,"nm":"fixed null","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[292,441,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Position control')('Point');"},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[57,57,100],"ix":6,"l":2,"x":"var $bm_rt;\nvar temp;\ntemp = thisComp.layer('Control layer').effect('Scale')('Slider');\n$bm_rt = [\n temp,\n temp\n];"}},"ao":0,"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[140,140,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":4,"ty":4,"nm":"outer shape ","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":30,"s":[90]}],"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[131.395,131.4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[98.844,-21.81],[80.854,-21.81],[76.275,-23.33],[72.995,-32.07],[70.815,-39.970000000000006],[83.084,-52.24],[85.315,-58.09],[60.315,-83.08],[54.474,-85.31],[41.504,-72.35],[37.174,-70.18],[28.865000000000002,-74.00999999999999],[21.804,-78.05999999999999],[21.804,-95.69],[19.254,-101.4],[-16.095,-101.4],[-21.805,-98.84],[-21.805,-80.49],[-23.345,-75.88],[-31.985,-72.72],[-39.795,-70.64],[-52.236,-83.08],[-58.086000000000006,-85.31],[-83.086,-60.32],[-85.316,-54.47],[-72.545,-41.7],[-70.366,-37.33],[-74.345,-28.89],[-78.44500000000001,-21.81],[-95.685,-21.81],[-101.395,-19.25],[-101.395,16.1],[-98.845,21.81],[-81.245,21.81],[-76.595,23.39],[-73.366,32.370000000000005],[-71.196,40.35],[-83.086,52.24],[-85.316,58.080000000000005],[-60.316,83.08],[-54.464999999999996,85.31],[-42.265,73.11],[-37.866,70.95],[-29.126,75.05],[-21.805,79.17],[-21.805,95.68],[-19.255,101.4],[16.094,101.4],[21.804,98.84],[21.804,81.62],[23.374,77],[32.455,73.64999999999999],[40.525000000000006,71.37],[52.235,83.08],[58.083999999999996,85.31],[83.084,60.31],[85.315,54.47],[72.914,42.07],[70.76400000000001,37.720000000000006],[74.705,29.1],[78.775,21.81],[95.684,21.81],[101.394,19.25],[101.394,-16.1]],"o":[[95.684,-21.81],[78.445,-21.81],[74.344,-28.89],[70.365,-37.33],[72.544,-41.7],[85.315,-54.47],[83.084,-60.32],[58.083999999999996,-85.31],[52.235,-83.08],[39.794,-70.64],[31.985,-72.72],[23.344,-75.88],[21.804,-80.49],[21.804,-98.84],[16.094,-101.4],[-19.255,-101.4],[-21.805,-95.69],[-21.805,-78.05999999999999],[-28.866,-74.00999999999999],[-37.174,-70.18],[-41.505,-72.35],[-54.464999999999996,-85.31],[-60.316,-83.08],[-85.316,-58.09],[-83.086,-52.24],[-70.816,-39.970000000000006],[-72.99600000000001,-32.07],[-76.276,-23.33],[-80.855,-21.81],[-98.845,-21.81],[-101.395,-16.1],[-101.395,19.25],[-95.685,21.81],[-78.775,21.81],[-74.70599999999999,29.1],[-70.765,37.720000000000006],[-72.916,42.07],[-85.316,54.47],[-83.086,60.31],[-58.086000000000006,85.31],[-52.236,83.08],[-40.526,71.37],[-32.455999999999996,73.64999999999999],[-23.376,77],[-21.805,81.62],[-21.805,98.84],[-16.095,101.4],[19.254,101.4],[21.804,95.68],[21.804,79.17],[29.124,75.05],[37.865,70.95],[42.264,73.11],[54.474,85.31],[60.315,83.08],[85.315,58.080000000000005],[83.084,52.24],[71.19500000000001,40.35],[73.36500000000001,32.370000000000005],[76.59400000000001,23.39],[81.245,21.81],[98.844,21.81],[101.394,16.1],[101.394,-19.25]],"v":[[95.684,-21.81],[80.854,-21.81],[75.485,-25.61],[71.464,-35.14],[72.544,-41.7],[83.084,-52.24],[83.084,-60.32],[60.315,-83.08],[52.235,-83.08],[41.504,-72.35],[34.995,-71.25],[25.655,-75.1],[21.804,-80.49],[21.804,-95.69],[16.094,-101.4],[-16.095,-101.4],[-21.805,-95.69],[-21.805,-80.49],[-25.656,-75.1],[-34.995,-71.25],[-41.505,-72.35],[-52.236,-83.08],[-60.316,-83.08],[-83.086,-60.32],[-83.086,-52.24],[-72.545,-41.7],[-71.465,-35.14],[-75.475,-25.61],[-80.855,-21.81],[-95.685,-21.81],[-101.395,-16.1],[-101.395,16.1],[-95.685,21.81],[-81.245,21.81],[-75.826,25.73],[-71.836,35.52],[-72.916,42.07],[-83.086,52.24],[-83.086,60.31],[-60.316,83.08],[-52.236,83.08],[-42.265,73.11],[-35.666,72.05],[-25.696,76.21],[-21.805,81.62],[-21.805,95.68],[-16.095,101.4],[16.094,101.4],[21.804,95.68],[21.804,81.62],[25.695,76.21],[35.664,72.05],[42.264,73.11],[52.235,83.08],[60.315,83.08],[83.084,60.31],[83.084,52.24],[72.914,42.07],[71.834,35.52],[75.825,25.73],[81.245,21.81],[95.684,21.81],[101.394,16.1],[101.394,-16.1]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.098039223166,0.098039223166,0.098039223166,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Primary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 140, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[131.395,131.4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":5,"ty":4,"nm":"circle","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,49.995,0],"ix":2,"l":2},"a":{"a":0,"k":[77.585,77.585,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[26.285,47.585],[-47.585,26.285],[-26.275000000000002,-47.585],[47.585,-26.275000000000002]],"o":[[-26.275000000000002,47.585],[-47.585,-26.275000000000002],[26.285,-47.585],[47.585,26.285]],"v":[[0.005,47.585],[-47.585,0.005],[0.005,-47.585],[47.585,0.005]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 140, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[77.585,77.585],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":6,"ty":4,"nm":"background","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11,"x":"var $bm_rt;\nif (thisComp.layer('Control layer').effect('Bg ON')('Checkbox') > 0) {\n $bm_rt = 100;\n} else {\n $bm_rt = 0;\n}"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[1,-0.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[400,400],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Bg Color')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[1,-0.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150,"st":0,"bm":0,"completed":true}],"markers":[],"__complete":true} -------------------------------------------------------------------------------- /lottie/setting.json: -------------------------------------------------------------------------------- 1 | {"v":"5.7.13","fr":30,"ip":0,"op":30,"w":400,"h":400,"nm":"settings","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Control layer","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[200,200,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"Primary color","np":3,"mn":"ADBE Color Control","ix":1,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.09803921568627451,0.09803921568627451,0.09803921568627451,1],"ix":1}}]},{"ty":5,"nm":"Secondary color","np":3,"mn":"ADBE Color Control","ix":2,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[0.415686309338,0.043137256056,1,1],"ix":1}}]},{"ty":5,"nm":"Position control","np":3,"mn":"ADBE Point Control","ix":3,"en":1,"ef":[{"ty":3,"nm":"Point","mn":"ADBE Point Control-0001","ix":1,"v":{"a":0,"k":[200,200],"ix":1}}]},{"ty":5,"nm":"Bg ON","np":3,"mn":"ADBE Checkbox Control","ix":4,"en":1,"ef":[{"ty":7,"nm":"Checkbox","mn":"ADBE Checkbox Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]},{"ty":5,"nm":"Bg Color","np":3,"mn":"ADBE Color Control","ix":5,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1,1],"ix":1}}]},{"ty":5,"nm":"Stroke width","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":12,"ix":1}}]},{"ty":5,"nm":"Scale","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":2,"ty":3,"nm":"fixed null","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[292,441,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Position control')('Point');"},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[57,57,100],"ix":6,"l":2,"x":"var $bm_rt;\nvar temp;\ntemp = thisComp.layer('Control layer').effect('Scale')('Slider');\n$bm_rt = [\n temp,\n temp\n];"}},"ao":0,"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[140,140,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":4,"ty":4,"nm":"outer shape ","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":30,"s":[90]}],"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[131.395,131.4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[98.844,-21.81],[80.854,-21.81],[76.275,-23.33],[72.995,-32.07],[70.815,-39.970000000000006],[83.084,-52.24],[85.315,-58.09],[60.315,-83.08],[54.474,-85.31],[41.504,-72.35],[37.174,-70.18],[28.865000000000002,-74.00999999999999],[21.804,-78.05999999999999],[21.804,-95.69],[19.254,-101.4],[-16.095,-101.4],[-21.805,-98.84],[-21.805,-80.49],[-23.345,-75.88],[-31.985,-72.72],[-39.795,-70.64],[-52.236,-83.08],[-58.086000000000006,-85.31],[-83.086,-60.32],[-85.316,-54.47],[-72.545,-41.7],[-70.366,-37.33],[-74.345,-28.89],[-78.44500000000001,-21.81],[-95.685,-21.81],[-101.395,-19.25],[-101.395,16.1],[-98.845,21.81],[-81.245,21.81],[-76.595,23.39],[-73.366,32.370000000000005],[-71.196,40.35],[-83.086,52.24],[-85.316,58.080000000000005],[-60.316,83.08],[-54.464999999999996,85.31],[-42.265,73.11],[-37.866,70.95],[-29.126,75.05],[-21.805,79.17],[-21.805,95.68],[-19.255,101.4],[16.094,101.4],[21.804,98.84],[21.804,81.62],[23.374,77],[32.455,73.64999999999999],[40.525000000000006,71.37],[52.235,83.08],[58.083999999999996,85.31],[83.084,60.31],[85.315,54.47],[72.914,42.07],[70.76400000000001,37.720000000000006],[74.705,29.1],[78.775,21.81],[95.684,21.81],[101.394,19.25],[101.394,-16.1]],"o":[[95.684,-21.81],[78.445,-21.81],[74.344,-28.89],[70.365,-37.33],[72.544,-41.7],[85.315,-54.47],[83.084,-60.32],[58.083999999999996,-85.31],[52.235,-83.08],[39.794,-70.64],[31.985,-72.72],[23.344,-75.88],[21.804,-80.49],[21.804,-98.84],[16.094,-101.4],[-19.255,-101.4],[-21.805,-95.69],[-21.805,-78.05999999999999],[-28.866,-74.00999999999999],[-37.174,-70.18],[-41.505,-72.35],[-54.464999999999996,-85.31],[-60.316,-83.08],[-85.316,-58.09],[-83.086,-52.24],[-70.816,-39.970000000000006],[-72.99600000000001,-32.07],[-76.276,-23.33],[-80.855,-21.81],[-98.845,-21.81],[-101.395,-16.1],[-101.395,19.25],[-95.685,21.81],[-78.775,21.81],[-74.70599999999999,29.1],[-70.765,37.720000000000006],[-72.916,42.07],[-85.316,54.47],[-83.086,60.31],[-58.086000000000006,85.31],[-52.236,83.08],[-40.526,71.37],[-32.455999999999996,73.64999999999999],[-23.376,77],[-21.805,81.62],[-21.805,98.84],[-16.095,101.4],[19.254,101.4],[21.804,95.68],[21.804,79.17],[29.124,75.05],[37.865,70.95],[42.264,73.11],[54.474,85.31],[60.315,83.08],[85.315,58.080000000000005],[83.084,52.24],[71.19500000000001,40.35],[73.36500000000001,32.370000000000005],[76.59400000000001,23.39],[81.245,21.81],[98.844,21.81],[101.394,16.1],[101.394,-19.25]],"v":[[95.684,-21.81],[80.854,-21.81],[75.485,-25.61],[71.464,-35.14],[72.544,-41.7],[83.084,-52.24],[83.084,-60.32],[60.315,-83.08],[52.235,-83.08],[41.504,-72.35],[34.995,-71.25],[25.655,-75.1],[21.804,-80.49],[21.804,-95.69],[16.094,-101.4],[-16.095,-101.4],[-21.805,-95.69],[-21.805,-80.49],[-25.656,-75.1],[-34.995,-71.25],[-41.505,-72.35],[-52.236,-83.08],[-60.316,-83.08],[-83.086,-60.32],[-83.086,-52.24],[-72.545,-41.7],[-71.465,-35.14],[-75.475,-25.61],[-80.855,-21.81],[-95.685,-21.81],[-101.395,-16.1],[-101.395,16.1],[-95.685,21.81],[-81.245,21.81],[-75.826,25.73],[-71.836,35.52],[-72.916,42.07],[-83.086,52.24],[-83.086,60.31],[-60.316,83.08],[-52.236,83.08],[-42.265,73.11],[-35.666,72.05],[-25.696,76.21],[-21.805,81.62],[-21.805,95.68],[-16.095,101.4],[16.094,101.4],[21.804,95.68],[21.804,81.62],[25.695,76.21],[35.664,72.05],[42.264,73.11],[52.235,83.08],[60.315,83.08],[83.084,60.31],[83.084,52.24],[72.914,42.07],[71.834,35.52],[75.825,25.73],[81.245,21.81],[95.684,21.81],[101.394,16.1],[101.394,-16.1]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.098039223166,0.098039223166,0.098039223166,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Primary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 140, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[131.395,131.4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":5,"ty":4,"nm":"circle","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,49.995,0],"ix":2,"l":2},"a":{"a":0,"k":[77.585,77.585,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[26.285,47.585],[-47.585,26.285],[-26.275000000000002,-47.585],[47.585,-26.275000000000002]],"o":[[-26.275000000000002,47.585],[-47.585,-26.275000000000002],[26.285,-47.585],[47.585,26.285]],"v":[[0.005,47.585],[-47.585,0.005],[0.005,-47.585],[47.585,0.005]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 140, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[77.585,77.585],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":6,"ty":4,"nm":"background","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11,"x":"var $bm_rt;\nif (thisComp.layer('Control layer').effect('Bg ON')('Checkbox') > 0) {\n $bm_rt = 100;\n} else {\n $bm_rt = 0;\n}"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[1,-0.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[400,400],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Bg Color')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[1,-0.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150,"st":0,"bm":0,"completed":true}],"markers":[],"__complete":true} -------------------------------------------------------------------------------- /lottie/info.json: -------------------------------------------------------------------------------- 1 | {"v":"5.7.13","fr":30,"ip":0,"op":31,"w":400,"h":400,"nm":"information","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Control layer","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[200,200,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"Primary color","np":3,"mn":"ADBE Color Control","ix":1,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1,1],"ix":1}}]},{"ty":5,"nm":"Secondary color","np":3,"mn":"ADBE Color Control","ix":2,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1,1],"ix":1}}]},{"ty":5,"nm":"Position control","np":3,"mn":"ADBE Point Control","ix":3,"en":1,"ef":[{"ty":3,"nm":"Point","mn":"ADBE Point Control-0001","ix":1,"v":{"a":0,"k":[200,200],"ix":1}}]},{"ty":5,"nm":"Bg ON","np":3,"mn":"ADBE Checkbox Control","ix":4,"en":1,"ef":[{"ty":7,"nm":"Checkbox","mn":"ADBE Checkbox Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]},{"ty":5,"nm":"Bg Color","np":3,"mn":"ADBE Color Control","ix":5,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1,1],"ix":1}}]},{"ty":5,"nm":"Stroke width","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":12,"ix":1}}]},{"ty":5,"nm":"Scale","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]}],"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":2,"ty":3,"nm":"fixed null","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[292,441,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Position control')('Point');"},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[57,57,100],"ix":6,"l":2,"x":"var $bm_rt;\nvar temp;\ntemp = thisComp.layer('Control layer').effect('Scale')('Slider');\n$bm_rt = [\n temp,\n temp\n];"}},"ao":0,"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","parent":2,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[123,123,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":4,"ty":4,"nm":"circle ","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[152.087,152.087,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[122.087,-67.427],[67.427,122.087],[-122.087,67.427],[-67.427,-122.087]],"o":[[122.087,67.427],[-67.427,122.087],[-122.087,-67.427],[67.427,-122.087]],"v":[[122.087,0],[0,122.087],[-122.087,0],[0,-122.087]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.098039223166,0.098039223166,0.098039223166,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Primary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 123, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[152.087,152.087],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":151,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":5,"ty":4,"nm":"i ","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[41.511,73.34,0],"ix":2,"l":2},"a":{"a":0,"k":[42.554,83.55,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[28.978,137.101],[79.108,137.101]],"o":[[28.978,137.101],[79.108,137.101]],"v":[[28.978,137.101],[79.108,137.101]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 123, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-12.521,-53.551],[7.721,-53.551],[12.521,-51.401],[12.521,53.551]],"o":[[-12.521,-53.551],[10.372,-53.551],[12.521,-48.749],[12.521,53.551]],"v":[[-12.521,-53.551],[7.721,-53.551],[12.521,-48.749],[12.521,53.551]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":5,"s":[{"i":[[-12.521,-42.55],[7.721,-42.55],[12.521,-40.401],[12.521,53.551]],"o":[[-12.521,-42.55],[10.372,-42.55],[12.521,-37.749],[12.521,53.551]],"v":[[-12.521,-42.55],[7.721,-42.55],[12.521,-37.749],[12.521,53.551]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[{"i":[[-12.521,-65.05],[7.721,-65.05],[12.521,-62.901],[12.521,53.551]],"o":[[-12.521,-65.05],[10.372,-65.05],[12.521,-60.249],[12.521,53.551]],"v":[[-12.521,-65.05],[7.721,-65.05],[12.521,-60.249],[12.521,53.551]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[-12.521,-45.05],[7.721,-45.05],[12.521,-42.901],[12.521,53.551]],"o":[[-12.521,-45.05],[10.372,-45.05],[12.521,-40.249],[12.521,53.551]],"v":[[-12.521,-45.05],[7.721,-45.05],[12.521,-40.249],[12.521,53.551]],"c":false}]},{"t":21,"s":[{"i":[[-12.521,-53.551],[7.721,-53.551],[12.521,-51.401],[12.521,53.551]],"o":[[-12.521,-53.551],[10.372,-53.551],[12.521,-48.749],[12.521,53.551]],"v":[[-12.521,-53.551],[7.721,-53.551],[12.521,-48.749],[12.521,53.551]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 123, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[42.521,83.551],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":151,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":6,"ty":4,"nm":"dot ","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":1.105,"s":[41.478,-12.038,0],"to":null,"ti":null},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6,"s":[41.478,-2.038,0],"to":null,"ti":null},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":11,"s":[41.478,-38.038,0],"to":null,"ti":null},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":16,"s":[41.478,-2.038,0],"to":null,"ti":null},{"t":22,"s":[41.478,-12.038,0]}],"ix":2,"l":2},"a":{"a":0,"k":[41.854,41.853,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":1,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":3,"s":[100,112,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":8,"s":[100,112,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":13,"s":[100,112,100]},{"t":16,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[11.854,-6.546],[6.546,11.853],[-11.854,6.546],[-6.547,-11.853]],"o":[[11.854,6.546],[-6.547,11.853],[-11.854,-6.546],[6.546,-11.853]],"v":[[11.854,0],[0,11.853],[-11.854,0],[0,-11.853]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false,"_render":true},{"ty":"st","c":{"a":0,"k":[0.415686304429,0.043137254902,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Secondary color')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5,"x":"var $bm_rt;\n$bm_rt = $bm_mul(100 / 123, thisComp.layer('Control layer').effect('Stroke width')('Slider'));"},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[41.854,41.853],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":152,"st":1,"bm":0,"completed":true},{"ddd":0,"ind":7,"ty":4,"nm":"background","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11,"x":"var $bm_rt;\nif (thisComp.layer('Control layer').effect('Bg ON')('Checkbox') > 0) {\n $bm_rt = 100;\n} else {\n $bm_rt = 0;\n}"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[1,-0.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[400,400],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = thisComp.layer('Control layer').effect('Bg Color')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[1,-0.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":150.15015015015,"st":0,"bm":0,"completed":true}],"markers":[],"__complete":true} -------------------------------------------------------------------------------- /components/Chat/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useRef } from "react"; 2 | import Link from "next/link"; 3 | import ChatRecords, { AvatarComponent } from "../ChatRecord"; 4 | import Intro from "../Intro"; 5 | import { fetcher } from "../../helpers/fetcher"; 6 | import { formatClaudePrompt } from "../../helpers/cluade.helpers"; 7 | import dynamic from "next/dynamic"; 8 | import { builtinPrompts } from "../../data/prompts"; 9 | import { useAssistantRole } from "../../contexts/assistant"; 10 | import { useModelSetting } from "../../contexts/modelSetting"; 11 | import { v4 as uuidv4 } from "uuid"; 12 | import Lottie from "../Lottie"; 13 | import dot from "../../lottie/dot.json"; 14 | import setting from "../../lottie/setting.json"; 15 | import settingDark from "../../lottie/setting-dark.json"; 16 | import cls from "classnames"; 17 | import { useKBar } from "kbar"; 18 | import FastOperations from "../FastOperations"; 19 | 20 | import { useIsSupportCapture } from "../../hooks/useIsSupportCapture"; 21 | 22 | import { useLocalStorage } from "react-use"; 23 | import ThemeChanger from "../ThemeChanger"; 24 | import { useTheme } from "next-themes"; 25 | 26 | import type { FileInfo } from "../FastOperations"; 27 | 28 | const FunctionalZone = dynamic(() => import("../FunctionalZone"), { 29 | ssr: false, 30 | }); 31 | 32 | const Chat = () => { 33 | const { query } = useKBar(); 34 | const { value } = useAssistantRole(); 35 | const { value: modelSetting } = useModelSetting(); 36 | const [err, setErr] = useState(""); 37 | const chatWrapperRef = useRef(null); 38 | const [text, setText] = useState(""); 39 | const textAreaRef = useRef(null); 40 | const [waiting, setWaiting] = useState(false); 41 | const [fastZoneVisible, setFastZoneVisible] = useState(false); 42 | const [file, setFile] = useState(null); 43 | 44 | const assistantRole = 45 | builtinPrompts.find((p) => p.id === value) ?? builtinPrompts[0]; 46 | 47 | const isMobile = useIsSupportCapture(); 48 | 49 | const [chats, setChats] = useLocalStorage("ec-records"); 50 | const { theme } = useTheme(); 51 | 52 | useEffect(() => { 53 | if (chats?.length && chatWrapperRef.current) { 54 | chatWrapperRef.current.scrollTop = 55 | chatWrapperRef.current.scrollHeight + 20; 56 | } 57 | }, [chats]); 58 | 59 | const sendChat = async () => { 60 | if (!text.trim() || waiting) { 61 | return; 62 | } 63 | 64 | if (textAreaRef.current) { 65 | textAreaRef.current.style.height = "40px"; 66 | } 67 | 68 | const _chats: ChatMessage[] = [ 69 | ...(chats ?? []), 70 | { 71 | role: "user", 72 | id: uuidv4(), 73 | text, 74 | date: Date.now(), 75 | conversationId: assistantRole?.id, 76 | }, 77 | ]; 78 | 79 | setChats(_chats); 80 | 81 | const claudePrompt = formatClaudePrompt( 82 | _chats, 83 | assistantRole, 84 | file?.content 85 | ); 86 | 87 | setText(""); 88 | setWaiting(true); 89 | setErr(""); 90 | 91 | try { 92 | const gptResponse = await fetcher("/api/sendChat", { 93 | headers: { 94 | Accept: "application/json", 95 | "Content-Type": "application/json", 96 | }, 97 | method: "POST", 98 | body: JSON.stringify({ 99 | text: claudePrompt, 100 | id: "1", 101 | model: modelSetting?.model, 102 | hasFile: !!file, 103 | temperature: modelSetting?.temperature, 104 | maxTokens: modelSetting?.maxTokens, 105 | }), 106 | }); 107 | 108 | // const response = await fetch("/api/sse", { 109 | // method: "POST", 110 | // headers: { 111 | // "Content-Type": "application/json", 112 | // }, 113 | // body: JSON.stringify({ 114 | // text: claudePrompt, 115 | // }), 116 | // }); 117 | 118 | // if (!response.ok) { 119 | // throw new Error(response.statusText); 120 | // } 121 | 122 | // const data = response.body; 123 | // if (!data) { 124 | // return; 125 | // } 126 | 127 | // const reader = data.getReader(); 128 | // const decoder = new TextDecoder(); 129 | 130 | // let done = false; 131 | // let chunkValue = ''; 132 | // const chatId = uuidv4(); 133 | // const chatDate = Date.now(); 134 | 135 | // while (!done) { 136 | // const { value, done: doneReading } = await reader.read(); 137 | // done = doneReading; 138 | // if (!done) { 139 | // const _chunkValue = decoder.decode(value); 140 | 141 | // // FIXME: 这里有点奇怪,数据不是按序返回的 142 | // if (!chunkValue.includes(_chunkValue)) { 143 | // chunkValue = _chunkValue; 144 | // console.log('chunkValue', chunkValue); 145 | // setChats([ ..._chats, { 146 | // id: chatId, 147 | // date: chatDate, 148 | // role: 'assistant', 149 | // text: chunkValue, 150 | // conversationId: assistantRole?.id 151 | // } ]); 152 | // } 153 | 154 | // } 155 | 156 | // // setChats([ ..._chats, { ...gptResponse, conversationId: assistantRole?.id } ]); 157 | // } 158 | 159 | if (gptResponse?.error) { 160 | throw new Error(gptResponse.error); 161 | } 162 | 163 | setChats([ 164 | ..._chats, 165 | { ...gptResponse, conversationId: assistantRole?.id }, 166 | ]); 167 | } catch (e) { 168 | if (e instanceof Error) { 169 | setErr(e.message); 170 | } 171 | setErr("我的服务器好像遇到点问题,你可以稍后再试试。"); 172 | } finally { 173 | setWaiting(false); 174 | } 175 | }; 176 | return ( 177 |
    178 | {/* Header */} 179 |
    180 |
    181 |

    新聊天

    182 |

    183 | 开启一个新聊天 184 |

    185 |
    186 |
    187 | 188 |
    189 | {isMobile && ( 190 |
    191 | {/* key for refresh Lottie cache */} 192 | 199 |
    200 | )} 201 |
    202 | 203 |
    204 |
    205 | 206 | 207 |
    208 | {chats && } 209 | 210 | {/* 这里要替换掉 */} 211 | {waiting && ( 212 |
    213 | 214 |
    215 | 我假装在思考中{" "} 216 | 222 |
    223 |
    224 |
    225 | )} 226 | 227 | {err && ( 228 |
    229 | 230 |

    {err}

    231 |
    232 | )} 233 | 234 | {assistantRole ? ( 235 |
    236 |

    237 | 当前正在跟{" "} 238 | 239 | {assistantRole.title} 240 | 241 | {!!file && ( 242 | 243 | ({file.name}) 244 | 245 | )} 246 | {" "} 247 | 聊天 248 |

    249 |

    250 | 251 | 模型 252 | 253 | :{modelSetting?.model ?? "claude-instant-v1"} 254 | 255 | 温度 256 | 257 | :{modelSetting?.temperature ?? 0.7} 258 | 259 | 生成长度 260 | 261 | :{modelSetting?.maxTokens ?? 400} 262 |

    263 |
    264 | ) : null} 265 |
    266 |
    267 |
    268 | 269 | {/* Footer */} 270 |
    271 |
    272 |
    273 |
    274 | 314 | 315 | setFastZoneVisible(false)} 318 | onFileUpload={(fileInfo) => setFile(fileInfo)} 319 | > 320 |
    Hidden Item
    321 |
    322 | 323 | {!isMobile && ( 324 | 325 | 330 | 331 | K 332 | 333 | 334 | )} 335 |
    336 | 337 | 345 |
    346 | 347 |
    348 | 349 | easierChat.com - 一个更方便、易用的 chatBot 客户端 350 | 351 | FAQs |{" "} 352 | @那吒 |{" "} 353 | 提交反馈 |{" "} 354 | 355 | macOS 客户端 356 | 357 |
    358 |
    359 |
    360 |
    361 | ); 362 | }; 363 | 364 | export default Chat; 365 | -------------------------------------------------------------------------------- /styles/markdown.css: -------------------------------------------------------------------------------- 1 | .markdown-body ol, 2 | .markdown-body ul, 3 | .markdown-body menu { 4 | list-style: auto; 5 | } 6 | 7 | .markdown-body .octicon { 8 | display: inline-block; 9 | fill: currentColor; 10 | vertical-align: text-bottom; 11 | } 12 | 13 | .markdown-body h1:hover .anchor .octicon-link:before, 14 | .markdown-body h2:hover .anchor .octicon-link:before, 15 | .markdown-body h3:hover .anchor .octicon-link:before, 16 | .markdown-body h4:hover .anchor .octicon-link:before, 17 | .markdown-body h5:hover .anchor .octicon-link:before, 18 | .markdown-body h6:hover .anchor .octicon-link:before { 19 | width: 16px; 20 | height: 16px; 21 | content: ' '; 22 | display: inline-block; 23 | background-color: currentColor; 24 | -webkit-mask-image: url("data:image/svg+xml,"); 25 | mask-image: url("data:image/svg+xml,"); 26 | } 27 | 28 | .markdown-body details, 29 | .markdown-body figcaption, 30 | .markdown-body figure { 31 | display: block; 32 | } 33 | 34 | .markdown-body summary { 35 | display: list-item; 36 | } 37 | 38 | .markdown-body [hidden] { 39 | display: none !important; 40 | } 41 | 42 | .markdown-body a { 43 | background-color: transparent; 44 | color: #0969da; 45 | text-decoration: none; 46 | } 47 | 48 | .markdown-body a:active, 49 | .markdown-body a:hover { 50 | outline-width: 0; 51 | } 52 | 53 | .markdown-body abbr[title] { 54 | border-bottom: none; 55 | text-decoration: underline dotted; 56 | } 57 | 58 | .markdown-body b, 59 | .markdown-body strong { 60 | font-weight: 600; 61 | } 62 | 63 | .markdown-body dfn { 64 | font-style: italic; 65 | } 66 | 67 | .markdown-body h1 { 68 | margin: .67em 0; 69 | font-weight: 600; 70 | padding-bottom: .3em; 71 | font-size: 2em; 72 | border-bottom: 1px solid hsla(210,18%,87%,1); 73 | } 74 | 75 | .markdown-body mark { 76 | background-color: #fff8c5; 77 | color: #24292f; 78 | } 79 | 80 | .markdown-body small { 81 | font-size: 90%; 82 | } 83 | 84 | .markdown-body sub, 85 | .markdown-body sup { 86 | font-size: 75%; 87 | line-height: 0; 88 | position: relative; 89 | vertical-align: baseline; 90 | } 91 | 92 | .markdown-body sub { 93 | bottom: -0.25em; 94 | } 95 | 96 | .markdown-body sup { 97 | top: -0.5em; 98 | } 99 | 100 | .markdown-body img { 101 | border-style: none; 102 | max-width: 100%; 103 | box-sizing: content-box; 104 | background-color: #ffffff; 105 | } 106 | 107 | .markdown-body code, 108 | .markdown-body kbd, 109 | .markdown-body pre, 110 | .markdown-body samp { 111 | font-family: monospace,monospace; 112 | font-size: 1em; 113 | } 114 | 115 | .markdown-body figure { 116 | margin: 1em 40px; 117 | } 118 | 119 | .markdown-body hr { 120 | box-sizing: content-box; 121 | overflow: hidden; 122 | background: transparent; 123 | border-bottom: 1px solid hsla(210,18%,87%,1); 124 | height: .25em; 125 | padding: 0; 126 | margin: 24px 0; 127 | background-color: #d0d7de; 128 | border: 0; 129 | } 130 | 131 | .markdown-body input { 132 | font: inherit; 133 | margin: 0; 134 | overflow: visible; 135 | font-family: inherit; 136 | font-size: inherit; 137 | line-height: inherit; 138 | } 139 | 140 | .markdown-body [type=button], 141 | .markdown-body [type=reset], 142 | .markdown-body [type=submit] { 143 | -webkit-appearance: button; 144 | } 145 | 146 | .markdown-body [type=button]::-moz-focus-inner, 147 | .markdown-body [type=reset]::-moz-focus-inner, 148 | .markdown-body [type=submit]::-moz-focus-inner { 149 | border-style: none; 150 | padding: 0; 151 | } 152 | 153 | .markdown-body [type=button]:-moz-focusring, 154 | .markdown-body [type=reset]:-moz-focusring, 155 | .markdown-body [type=submit]:-moz-focusring { 156 | outline: 1px dotted ButtonText; 157 | } 158 | 159 | .markdown-body [type=checkbox], 160 | .markdown-body [type=radio] { 161 | box-sizing: border-box; 162 | padding: 0; 163 | } 164 | 165 | .markdown-body [type=number]::-webkit-inner-spin-button, 166 | .markdown-body [type=number]::-webkit-outer-spin-button { 167 | height: auto; 168 | } 169 | 170 | .markdown-body [type=search] { 171 | -webkit-appearance: textfield; 172 | outline-offset: -2px; 173 | } 174 | 175 | .markdown-body [type=search]::-webkit-search-cancel-button, 176 | .markdown-body [type=search]::-webkit-search-decoration { 177 | -webkit-appearance: none; 178 | } 179 | 180 | .markdown-body ::-webkit-input-placeholder { 181 | color: inherit; 182 | opacity: .54; 183 | } 184 | 185 | .markdown-body ::-webkit-file-upload-button { 186 | -webkit-appearance: button; 187 | font: inherit; 188 | } 189 | 190 | .markdown-body a:hover { 191 | text-decoration: underline; 192 | } 193 | 194 | .markdown-body hr::before { 195 | display: table; 196 | content: ""; 197 | } 198 | 199 | .markdown-body hr::after { 200 | display: table; 201 | clear: both; 202 | content: ""; 203 | } 204 | 205 | .markdown-body table { 206 | border-spacing: 0; 207 | border-collapse: collapse; 208 | display: block; 209 | width: max-content; 210 | max-width: 100%; 211 | overflow: auto; 212 | } 213 | 214 | .markdown-body td, 215 | .markdown-body th { 216 | padding: 0; 217 | } 218 | 219 | .markdown-body details summary { 220 | cursor: pointer; 221 | } 222 | 223 | .markdown-body details:not([open])>*:not(summary) { 224 | display: none !important; 225 | } 226 | 227 | .markdown-body kbd { 228 | display: inline-block; 229 | padding: 3px 5px; 230 | font: 11px ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; 231 | line-height: 10px; 232 | color: #24292f; 233 | vertical-align: middle; 234 | background-color: #f6f8fa; 235 | border: solid 1px rgba(175,184,193,0.2); 236 | border-bottom-color: rgba(175,184,193,0.2); 237 | border-radius: 6px; 238 | box-shadow: inset 0 -1px 0 rgba(175,184,193,0.2); 239 | } 240 | 241 | .markdown-body h1, 242 | .markdown-body h2, 243 | .markdown-body h3, 244 | .markdown-body h4, 245 | .markdown-body h5, 246 | .markdown-body h6 { 247 | margin-top: 24px; 248 | margin-bottom: 16px; 249 | font-weight: 600; 250 | line-height: 1.25; 251 | } 252 | 253 | .markdown-body h2 { 254 | font-weight: 600; 255 | padding-bottom: .3em; 256 | font-size: 1.5em; 257 | border-bottom: 1px solid hsla(210,18%,87%,1); 258 | } 259 | 260 | .markdown-body h3 { 261 | font-weight: 600; 262 | font-size: 1.25em; 263 | } 264 | 265 | .markdown-body h4 { 266 | font-weight: 600; 267 | font-size: 1em; 268 | } 269 | 270 | .markdown-body h5 { 271 | font-weight: 600; 272 | font-size: .875em; 273 | } 274 | 275 | .markdown-body h6 { 276 | font-weight: 600; 277 | font-size: .85em; 278 | color: #57606a; 279 | } 280 | 281 | .markdown-body p { 282 | margin-top: 0; 283 | margin-bottom: 10px; 284 | } 285 | 286 | .markdown-body blockquote { 287 | margin: 0; 288 | padding: 0 1em; 289 | color: #57606a; 290 | border-left: .25em solid #d0d7de; 291 | } 292 | 293 | .markdown-body ul, 294 | .markdown-body ol { 295 | margin-top: 0; 296 | margin-bottom: 0; 297 | padding-left: 2em; 298 | } 299 | 300 | .markdown-body ol ol, 301 | .markdown-body ul ol { 302 | list-style-type: lower-roman; 303 | } 304 | 305 | .markdown-body ul ul ol, 306 | .markdown-body ul ol ol, 307 | .markdown-body ol ul ol, 308 | .markdown-body ol ol ol { 309 | list-style-type: lower-alpha; 310 | } 311 | 312 | .markdown-body dd { 313 | margin-left: 0; 314 | } 315 | 316 | .markdown-body tt, 317 | .markdown-body code { 318 | font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; 319 | font-size: 12px; 320 | } 321 | 322 | .markdown-body pre { 323 | margin-top: 0; 324 | margin-bottom: 0; 325 | font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; 326 | font-size: 12px; 327 | word-wrap: normal; 328 | } 329 | 330 | .markdown-body .octicon { 331 | display: inline-block; 332 | overflow: visible !important; 333 | vertical-align: text-bottom; 334 | fill: currentColor; 335 | } 336 | 337 | .markdown-body ::placeholder { 338 | color: #6e7781; 339 | opacity: 1; 340 | } 341 | 342 | .markdown-body input::-webkit-outer-spin-button, 343 | .markdown-body input::-webkit-inner-spin-button { 344 | margin: 0; 345 | -webkit-appearance: none; 346 | appearance: none; 347 | } 348 | 349 | .markdown-body .pl-c { 350 | color: #6e7781; 351 | } 352 | 353 | .markdown-body .pl-c1, 354 | .markdown-body .pl-s .pl-v { 355 | color: #0550ae; 356 | } 357 | 358 | .markdown-body .pl-e, 359 | .markdown-body .pl-en { 360 | color: #8250df; 361 | } 362 | 363 | .markdown-body .pl-smi, 364 | .markdown-body .pl-s .pl-s1 { 365 | color: #24292f; 366 | } 367 | 368 | .markdown-body .pl-ent { 369 | color: #116329; 370 | } 371 | 372 | .markdown-body .pl-k { 373 | color: #cf222e; 374 | } 375 | 376 | .markdown-body .pl-s, 377 | .markdown-body .pl-pds, 378 | .markdown-body .pl-s .pl-pse .pl-s1, 379 | .markdown-body .pl-sr, 380 | .markdown-body .pl-sr .pl-cce, 381 | .markdown-body .pl-sr .pl-sre, 382 | .markdown-body .pl-sr .pl-sra { 383 | color: #0a3069; 384 | } 385 | 386 | .markdown-body .pl-v, 387 | .markdown-body .pl-smw { 388 | color: #953800; 389 | } 390 | 391 | .markdown-body .pl-bu { 392 | color: #82071e; 393 | } 394 | 395 | .markdown-body .pl-ii { 396 | color: #f6f8fa; 397 | background-color: #82071e; 398 | } 399 | 400 | .markdown-body .pl-c2 { 401 | color: #f6f8fa; 402 | background-color: #cf222e; 403 | } 404 | 405 | .markdown-body .pl-sr .pl-cce { 406 | font-weight: bold; 407 | color: #116329; 408 | } 409 | 410 | .markdown-body .pl-ml { 411 | color: #3b2300; 412 | } 413 | 414 | .markdown-body .pl-mh, 415 | .markdown-body .pl-mh .pl-en, 416 | .markdown-body .pl-ms { 417 | font-weight: bold; 418 | color: #0550ae; 419 | } 420 | 421 | .markdown-body .pl-mi { 422 | font-style: italic; 423 | color: #24292f; 424 | } 425 | 426 | .markdown-body .pl-mb { 427 | font-weight: bold; 428 | color: #24292f; 429 | } 430 | 431 | .markdown-body .pl-md { 432 | color: #82071e; 433 | background-color: #FFEBE9; 434 | } 435 | 436 | .markdown-body .pl-mi1 { 437 | color: #116329; 438 | background-color: #dafbe1; 439 | } 440 | 441 | .markdown-body .pl-mc { 442 | color: #953800; 443 | background-color: #ffd8b5; 444 | } 445 | 446 | .markdown-body .pl-mi2 { 447 | color: #eaeef2; 448 | background-color: #0550ae; 449 | } 450 | 451 | .markdown-body .pl-mdr { 452 | font-weight: bold; 453 | color: #8250df; 454 | } 455 | 456 | .markdown-body .pl-ba { 457 | color: #57606a; 458 | } 459 | 460 | .markdown-body .pl-sg { 461 | color: #8c959f; 462 | } 463 | 464 | .markdown-body .pl-corl { 465 | text-decoration: underline; 466 | color: #0a3069; 467 | } 468 | 469 | .markdown-body [data-catalyst] { 470 | display: block; 471 | } 472 | 473 | .markdown-body g-emoji { 474 | font-family: "Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; 475 | font-size: 1em; 476 | font-style: normal !important; 477 | font-weight: 400; 478 | line-height: 1; 479 | vertical-align: -0.075em; 480 | } 481 | 482 | .markdown-body g-emoji img { 483 | width: 1em; 484 | height: 1em; 485 | } 486 | 487 | .markdown-body::before { 488 | display: table; 489 | content: ""; 490 | } 491 | 492 | .markdown-body::after { 493 | display: table; 494 | clear: both; 495 | content: ""; 496 | } 497 | 498 | .markdown-body>*:first-child { 499 | margin-top: 0 !important; 500 | } 501 | 502 | .markdown-body>*:last-child { 503 | margin-bottom: 0 !important; 504 | } 505 | 506 | .markdown-body a:not([href]) { 507 | color: inherit; 508 | text-decoration: none; 509 | } 510 | 511 | .markdown-body .absent { 512 | color: #cf222e; 513 | } 514 | 515 | .markdown-body .anchor { 516 | float: left; 517 | padding-right: 4px; 518 | margin-left: -20px; 519 | line-height: 1; 520 | } 521 | 522 | .markdown-body .anchor:focus { 523 | outline: none; 524 | } 525 | 526 | .markdown-body p, 527 | .markdown-body blockquote, 528 | .markdown-body ul, 529 | .markdown-body ol, 530 | .markdown-body dl, 531 | .markdown-body table, 532 | .markdown-body pre, 533 | .markdown-body details { 534 | margin-top: 0; 535 | margin-bottom: 16px; 536 | } 537 | 538 | .markdown-body blockquote>:first-child { 539 | margin-top: 0; 540 | } 541 | 542 | .markdown-body blockquote>:last-child { 543 | margin-bottom: 0; 544 | } 545 | 546 | .markdown-body sup>a::before { 547 | content: "["; 548 | } 549 | 550 | .markdown-body sup>a::after { 551 | content: "]"; 552 | } 553 | 554 | .markdown-body h1 .octicon-link, 555 | .markdown-body h2 .octicon-link, 556 | .markdown-body h3 .octicon-link, 557 | .markdown-body h4 .octicon-link, 558 | .markdown-body h5 .octicon-link, 559 | .markdown-body h6 .octicon-link { 560 | color: #24292f; 561 | vertical-align: middle; 562 | visibility: hidden; 563 | } 564 | 565 | .markdown-body h1:hover .anchor, 566 | .markdown-body h2:hover .anchor, 567 | .markdown-body h3:hover .anchor, 568 | .markdown-body h4:hover .anchor, 569 | .markdown-body h5:hover .anchor, 570 | .markdown-body h6:hover .anchor { 571 | text-decoration: none; 572 | } 573 | 574 | .markdown-body h1:hover .anchor .octicon-link, 575 | .markdown-body h2:hover .anchor .octicon-link, 576 | .markdown-body h3:hover .anchor .octicon-link, 577 | .markdown-body h4:hover .anchor .octicon-link, 578 | .markdown-body h5:hover .anchor .octicon-link, 579 | .markdown-body h6:hover .anchor .octicon-link { 580 | visibility: visible; 581 | } 582 | 583 | .markdown-body h1 tt, 584 | .markdown-body h1 code, 585 | .markdown-body h2 tt, 586 | .markdown-body h2 code, 587 | .markdown-body h3 tt, 588 | .markdown-body h3 code, 589 | .markdown-body h4 tt, 590 | .markdown-body h4 code, 591 | .markdown-body h5 tt, 592 | .markdown-body h5 code, 593 | .markdown-body h6 tt, 594 | .markdown-body h6 code { 595 | padding: 0 .2em; 596 | font-size: inherit; 597 | } 598 | 599 | .markdown-body ul.no-list, 600 | .markdown-body ol.no-list { 601 | padding: 0; 602 | list-style-type: none; 603 | } 604 | 605 | .markdown-body ol[type="1"] { 606 | list-style-type: decimal; 607 | } 608 | 609 | .markdown-body ol[type=a] { 610 | list-style-type: lower-alpha; 611 | } 612 | 613 | .markdown-body ol[type=i] { 614 | list-style-type: lower-roman; 615 | } 616 | 617 | .markdown-body div>ol:not([type]) { 618 | list-style-type: decimal; 619 | } 620 | 621 | .markdown-body ul ul, 622 | .markdown-body ul ol, 623 | .markdown-body ol ol, 624 | .markdown-body ol ul { 625 | margin-top: 0; 626 | margin-bottom: 0; 627 | } 628 | 629 | .markdown-body li>p { 630 | margin-top: 16px; 631 | } 632 | 633 | .markdown-body li+li { 634 | margin-top: .25em; 635 | } 636 | 637 | .markdown-body dl { 638 | padding: 0; 639 | } 640 | 641 | .markdown-body dl dt { 642 | padding: 0; 643 | margin-top: 16px; 644 | font-size: 1em; 645 | font-style: italic; 646 | font-weight: 600; 647 | } 648 | 649 | .markdown-body dl dd { 650 | padding: 0 16px; 651 | margin-bottom: 16px; 652 | } 653 | 654 | .markdown-body table th { 655 | font-weight: 600; 656 | } 657 | 658 | .markdown-body table th, 659 | .markdown-body table td { 660 | padding: 6px 13px; 661 | border: 1px solid #d0d7de; 662 | } 663 | 664 | .markdown-body table tr { 665 | background-color: #ffffff; 666 | border-top: 1px solid hsla(210,18%,87%,1); 667 | } 668 | 669 | .markdown-body table tr:nth-child(2n) { 670 | background-color: #f6f8fa; 671 | } 672 | 673 | .markdown-body table img { 674 | background-color: transparent; 675 | } 676 | 677 | .markdown-body img[align=right] { 678 | padding-left: 20px; 679 | } 680 | 681 | .markdown-body img[align=left] { 682 | padding-right: 20px; 683 | } 684 | 685 | .markdown-body .emoji { 686 | max-width: none; 687 | vertical-align: text-top; 688 | background-color: transparent; 689 | } 690 | 691 | .markdown-body span.frame { 692 | display: block; 693 | overflow: hidden; 694 | } 695 | 696 | .markdown-body span.frame>span { 697 | display: block; 698 | float: left; 699 | width: auto; 700 | padding: 7px; 701 | margin: 13px 0 0; 702 | overflow: hidden; 703 | border: 1px solid #d0d7de; 704 | } 705 | 706 | .markdown-body span.frame span img { 707 | display: block; 708 | float: left; 709 | } 710 | 711 | .markdown-body span.frame span span { 712 | display: block; 713 | padding: 5px 0 0; 714 | clear: both; 715 | color: #24292f; 716 | } 717 | 718 | .markdown-body span.align-center { 719 | display: block; 720 | overflow: hidden; 721 | clear: both; 722 | } 723 | 724 | .markdown-body span.align-center>span { 725 | display: block; 726 | margin: 13px auto 0; 727 | overflow: hidden; 728 | text-align: center; 729 | } 730 | 731 | .markdown-body span.align-center span img { 732 | margin: 0 auto; 733 | text-align: center; 734 | } 735 | 736 | .markdown-body span.align-right { 737 | display: block; 738 | overflow: hidden; 739 | clear: both; 740 | } 741 | 742 | .markdown-body span.align-right>span { 743 | display: block; 744 | margin: 13px 0 0; 745 | overflow: hidden; 746 | text-align: right; 747 | } 748 | 749 | .markdown-body span.align-right span img { 750 | margin: 0; 751 | text-align: right; 752 | } 753 | 754 | .markdown-body span.float-left { 755 | display: block; 756 | float: left; 757 | margin-right: 13px; 758 | overflow: hidden; 759 | } 760 | 761 | .markdown-body span.float-left span { 762 | margin: 13px 0 0; 763 | } 764 | 765 | .markdown-body span.float-right { 766 | display: block; 767 | float: right; 768 | margin-left: 13px; 769 | overflow: hidden; 770 | } 771 | 772 | .markdown-body span.float-right>span { 773 | display: block; 774 | margin: 13px auto 0; 775 | overflow: hidden; 776 | text-align: right; 777 | } 778 | 779 | .markdown-body code, 780 | .markdown-body tt { 781 | padding: .2em .4em; 782 | margin: 0; 783 | font-size: 85%; 784 | background-color: rgba(175,184,193,0.2); 785 | border-radius: 6px; 786 | } 787 | 788 | .markdown-body code br, 789 | .markdown-body tt br { 790 | display: none; 791 | } 792 | 793 | .markdown-body del code { 794 | text-decoration: inherit; 795 | } 796 | 797 | .markdown-body pre code { 798 | font-size: 100%; 799 | } 800 | 801 | .markdown-body pre>code { 802 | padding: 0; 803 | margin: 0; 804 | word-break: normal; 805 | white-space: pre; 806 | background: transparent; 807 | border: 0; 808 | } 809 | 810 | .markdown-body .highlight { 811 | margin-bottom: 16px; 812 | } 813 | 814 | .markdown-body .highlight pre { 815 | margin-bottom: 0; 816 | word-break: normal; 817 | } 818 | 819 | .markdown-body .highlight pre, 820 | .markdown-body pre { 821 | padding: 16px; 822 | overflow: auto; 823 | max-width: 80vw; 824 | line-height: 1.45; 825 | background-color: #f6f8fa; 826 | border-radius: 6px; 827 | } 828 | 829 | .markdown-body pre code, 830 | .markdown-body pre tt { 831 | display: inline; 832 | max-width: auto; 833 | padding: 0; 834 | margin: 0; 835 | overflow: visible; 836 | line-height: inherit; 837 | word-wrap: normal; 838 | background-color: transparent; 839 | border: 0; 840 | } 841 | 842 | .markdown-body .csv-data td, 843 | .markdown-body .csv-data th { 844 | padding: 5px; 845 | overflow: hidden; 846 | font-size: 12px; 847 | line-height: 1; 848 | text-align: left; 849 | white-space: nowrap; 850 | } 851 | 852 | .markdown-body .csv-data .blob-num { 853 | padding: 10px 8px 9px; 854 | text-align: right; 855 | background: #ffffff; 856 | border: 0; 857 | } 858 | 859 | .markdown-body .csv-data tr { 860 | border-top: 0; 861 | } 862 | 863 | .markdown-body .csv-data th { 864 | font-weight: 600; 865 | background: #f6f8fa; 866 | border-top: 0; 867 | } 868 | 869 | .markdown-body .footnotes { 870 | font-size: 12px; 871 | color: #57606a; 872 | border-top: 1px solid #d0d7de; 873 | } 874 | 875 | .markdown-body .footnotes ol { 876 | padding-left: 16px; 877 | } 878 | 879 | .markdown-body .footnotes li { 880 | position: relative; 881 | } 882 | 883 | .markdown-body .footnotes li:target::before { 884 | position: absolute; 885 | top: -8px; 886 | right: -8px; 887 | bottom: -8px; 888 | left: -24px; 889 | pointer-events: none; 890 | content: ""; 891 | border: 2px solid #0969da; 892 | border-radius: 6px; 893 | } 894 | 895 | .markdown-body .footnotes li:target { 896 | color: #24292f; 897 | } 898 | 899 | .markdown-body .footnotes .data-footnote-backref g-emoji { 900 | font-family: monospace; 901 | } 902 | 903 | .markdown-body .task-list-item { 904 | list-style-type: none; 905 | } 906 | 907 | .markdown-body .task-list-item label { 908 | font-weight: 400; 909 | } 910 | 911 | .markdown-body .task-list-item.enabled label { 912 | cursor: pointer; 913 | } 914 | 915 | .markdown-body .task-list-item+.task-list-item { 916 | margin-top: 3px; 917 | } 918 | 919 | .markdown-body .task-list-item .handle { 920 | display: none; 921 | } 922 | 923 | .markdown-body .task-list-item-checkbox { 924 | margin: 0 .2em .25em -1.6em; 925 | vertical-align: middle; 926 | } 927 | 928 | .markdown-body .contains-task-list:dir(rtl) .task-list-item-checkbox { 929 | margin: 0 -1.6em .25em .2em; 930 | } 931 | 932 | .markdown-body ::-webkit-calendar-picker-indicator { 933 | filter: invert(50%); 934 | } 935 | 936 | pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*! 937 | Theme: GitHub 938 | Description: Light theme as seen on github.com 939 | Author: github.com 940 | Maintainer: @Hirse 941 | Updated: 2021-05-15 942 | 943 | Outdated base version: https://github.com/primer/github-syntax-light 944 | Current colors taken from GitHub's CSS 945 | */.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0} 946 | 947 | @import "./atom-one-dark.css"; 948 | .dark-theme .markdown-body pre { 949 | background: #282c34 950 | } --------------------------------------------------------------------------------