diff --git a/.env.development b/.env.development index 8260881..d34032d 100644 --- a/.env.development +++ b/.env.development @@ -1,3 +1,5 @@ NOVLEAI_ENVIRONMENT=debug +NOVELAI_BACKEND_URL=http://localhost:6969 NOVELAI_MOCK_ENV=false NOVELAI_RECAPTCHA_KEY= +NEXT_PUBLIC_IS_ISEKAI=false diff --git a/.gitignore b/.gitignore index 6d3d351..ebd323b 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ yarn-error.log* .env.development.local .env.test.local .env.production.local +.env.production # vercel .vercel diff --git a/next.config.js b/next.config.js index 4eee98b..5c8949d 100644 --- a/next.config.js +++ b/next.config.js @@ -52,6 +52,7 @@ const sharedConfig = { NEXT_PUBLIC_PADDLE_GIFTKEY_TABLET_ID: process.env.NOVELAI_PADDLE_GIFTKEY_TABLET_ID, NEXT_PUBLIC_PADDLE_GIFTKEY_SCROLL_ID: process.env.NOVELAI_PADDLE_GIFTKEY_SCROLL_ID, NEXT_PUBLIC_PADDLE_GIFTKEY_OPUS_ID: process.env.NOVELAI_PADDLE_GIFTKEY_OPUS_ID, + NEXT_PUBLIC_IS_ISEKAI: process.env.NOVELAI_IS_ISEKAI, }, productionBrowserSourceMaps: true, generateBuildId: () => commithash.slice(0, 7) + '-' + process.env.NOVELAI_ENVIRONMENT, diff --git a/src/globals/constants.ts b/src/globals/constants.ts index 86a9a82..3eb752c 100644 --- a/src/globals/constants.ts +++ b/src/globals/constants.ts @@ -1,3 +1,5 @@ +export const IsIsekai = process.env.NEXT_PUBLIC_IS_ISEKAI === 'true' + export const Environment = process.env.NEXT_PUBLIC_ENVIRONMENT || 'debug' export const CommitHash = process.env.NEXT_PUBLIC_COMMITHASH || 'unknown' diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 20e7c17..032d3ec 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -153,12 +153,11 @@ function App(props: AppPropsWithErrAndLayout): JSX.Element { diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index 3100079..eacebee 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -1,6 +1,7 @@ import Document, { DocumentContext, DocumentInitialProps, Html, Head, Main, NextScript } from 'next/document' import { Fragment } from 'react' import { ServerStyleSheet } from 'styled-components' +import { IsIsekai } from '../globals/constants' export default class CustomDocument extends Document { static async getInitialProps(ctx: DocumentContext): Promise { @@ -35,10 +36,18 @@ export default class CustomDocument extends Document { + {/* Remove resources which not exists + */} + {IsIsekai && ( + <> + + + + )}
diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 4c0703b..c2d9617 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -8,7 +8,7 @@ import { useRouter } from 'next/router' import { AnimatePresence, motion } from 'framer-motion' import { HexAlphaColorPicker, HexColorInput } from 'react-colorful' import { MdFileUpload, MdHelpOutline } from 'react-icons/md' -import { FaQuestion } from 'react-icons/fa' +import { FaCoffee, FaQuestion } from 'react-icons/fa' import TextareaAutosize from 'react-textarea-autosize' import JSZip from 'jszip' import { saveAs } from 'file-saver' @@ -64,7 +64,7 @@ import Checkbox from '../components/controls/checkbox' import { getStorage } from '../data/storage/storage' import { getUserSetting } from '../data/user/settings' import { useReload } from '../hooks/useReload' -import { BackendURLTagSearch } from '../globals/constants' +import { BackendURLTagSearch, IsIsekai } from '../globals/constants' import Tooltip from '../components/tooltip' import { WorkerInterface } from '../tokenizer/interface' import { EncoderType } from '../tokenizer/encoder' @@ -561,7 +561,7 @@ function ImageGenContent(): JSX.Element { const [purchaseModalOpen, setPurchaseModalOpen] = useState(false) - useEffect(() => {}, [ + useEffect(() => { }, [ params, selectedModel, session, @@ -604,10 +604,10 @@ function ImageGenContent(): JSX.Element { lastPromptTokensGood.current = false toast.warn( 'Prompt is too long and will be cut off. Using ' + - promptTokens + - ' out of ' + - SD_TOKEN_LIMIT + - ' available tokens.' + promptTokens + + ' out of ' + + SD_TOKEN_LIMIT + + ' available tokens.' ) } else if (promptTokens.every((t) => t <= SD_TOKEN_LIMIT)) { lastPromptTokensGood.current = true @@ -646,10 +646,10 @@ function ImageGenContent(): JSX.Element { lastNegPromptTokensGood.current = false toast.warn( 'Negative prompt is too long and will be cut off. Using ' + - negPromptTokens + - ' out of ' + - SD_TOKEN_LIMIT + - ' available tokens.' + negPromptTokens + + ' out of ' + + SD_TOKEN_LIMIT + + ' available tokens.' ) } else if (negPromptTokens <= SD_TOKEN_LIMIT) { lastNegPromptTokensGood.current = true @@ -673,8 +673,8 @@ function ImageGenContent(): JSX.Element { lastTagSearchRequest.current = requestId fetch( BackendURLTagSearch + - //`?model=${encodeURIComponent(selectedModel.toString())}&prompt=${encodeURIComponent( - `?prompt=${encodeURIComponent(prompt.trim())}`, + //`?model=${encodeURIComponent(selectedModel.toString())}&prompt=${encodeURIComponent( + `?prompt=${encodeURIComponent(prompt.trim())}`, { mode: 'cors', cache: 'default', @@ -2004,18 +2004,43 @@ function ImageGenContent(): JSX.Element { - - - + {IsIsekai && ( + + +   + 异世界百科 + + )} + + + + @@ -2244,12 +2269,12 @@ function ImageGenContent(): JSX.Element { } else { return e.key === 'ArrowUp' ? (suggestionSelectionIndex + - tagSuggestions.length - - 1) % - tagSuggestions.length + tagSuggestions.length - + 1) % + tagSuggestions.length : (suggestionSelectionIndex + - 1) % - tagSuggestions.length + 1) % + tagSuggestions.length } } ) @@ -2267,7 +2292,7 @@ function ImageGenContent(): JSX.Element { e.stopPropagation() insertTagToPrompt( tagSuggestions[ - suggestionSelectionIndex + suggestionSelectionIndex ][0], promptid ) @@ -2322,11 +2347,10 @@ function ImageGenContent(): JSX.Element { SD_TOKEN_LIMIT } style={{ - height: `${ - ((promptTokens[promptid] ?? 0) / - SD_TOKEN_LIMIT) * + height: `${((promptTokens[promptid] ?? 0) / + SD_TOKEN_LIMIT) * 100 - }%`, + }%`, }} /> @@ -2483,19 +2507,19 @@ function ImageGenContent(): JSX.Element { /> {(shownHover === i || images[selectedImage].length === 1) && ( - <> - {images[selectedImage].length === 1 && - img && - topButtonGroup(img, 0)} - - {images[selectedImage].length !== 1 && - specialButtonGroup(img, i)} - {saveButtonGroup(img)} - - {images[selectedImage].length === 1 && - seedButtonGroup(img, i)} - - )} + <> + {images[selectedImage].length === 1 && + img && + topButtonGroup(img, 0)} + + {images[selectedImage].length !== 1 && + specialButtonGroup(img, i)} + {saveButtonGroup(img)} + + {images[selectedImage].length === 1 && + seedButtonGroup(img, i)} + + )} {img.isVariationOriginal && (
` +const HistoryButton = styled(SubtleButton) <{ selected: boolean; img: string }>` border: ${(props) => props.selected ? `2px solid ${props.theme.colors.textHeadings}` : `2px solid transparent`}; border-radius: 3px; @@ -3323,7 +3347,7 @@ function GenerationOptions(props: { onMouseDown: (e: any) => { if (e.target !== document.activeElement) { e.preventDefault() - ;(e.target as HTMLInputElement).select() + ; (e.target as HTMLInputElement).select() } }, } @@ -3692,7 +3716,6 @@ function GenerationOptions(props: { maxRows={6} placeholder="Anything in here is added to the preset selected above." value={props.negPrompt ?? ''} - warn={props.negPromptTokens > SD_TOKEN_LIMIT} onChange={(e) => { props.setNegPrompt((e.target.value || '').replace(/(\n|\r)/g, '')) }} @@ -3888,7 +3911,7 @@ const Input = styled.input<{ warn?: boolean }>` } ` -const LargeInput = styled(TextareaAutosize)<{ warn?: boolean }>` +const LargeInput = styled(TextareaAutosize) <{ warn?: boolean }>` padding: 12px 20px; border: 1px solid ${(props) => (props.warn ? props.theme.colors.warning : props.theme.colors.bg3)}; border-radius: 3px; @@ -4907,7 +4930,7 @@ function Canvas(props: { onMouseDown: (e: any) => { if (e.target !== document.activeElement) { e.preventDefault() - ;(e.target as HTMLInputElement).select() + ; (e.target as HTMLInputElement).select() } }, } @@ -5537,7 +5560,7 @@ function Canvas(props: { backgroundImage: props.rerollImage ? `url(${props.rerollImage?.url})` : // eslint-disable-next-line max-len - `linear-gradient(45deg, #A0A0A0 25%, transparent 25%), linear-gradient(-45deg, #A0A0A0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #A0A0A0 75%), linear-gradient(-45deg, transparent 75%, #A0A0A0 75%)`, + `linear-gradient(45deg, #A0A0A0 25%, transparent 25%), linear-gradient(-45deg, #A0A0A0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #A0A0A0 75%), linear-gradient(-45deg, transparent 75%, #A0A0A0 75%)`, backgroundSize: props.rerollImage?.url ? '100%' : '30px 30px', backgroundPosition: '0 0, 0 15px, 15px -15px, -15px 0px', }} @@ -5882,7 +5905,7 @@ const Filler = styled.div` height: 30px; ` -const CanvasControlButton = styled(SubtleButton)<{ selected?: boolean }>` +const CanvasControlButton = styled(SubtleButton) <{ selected?: boolean }>` padding: 8px; height: 44px; min-width: 58px; @@ -5902,13 +5925,13 @@ const CanvasControlButton = styled(SubtleButton)<{ selected?: boolean }>` width: 18px; height: 18px; background-color: ${(props) => - props.selected ? props.theme.colors.bg0 : props.theme.colors.textMain}; + props.selected ? props.theme.colors.bg0 : props.theme.colors.textMain}; } &:hover { color: ${(props) => (props.selected ? props.theme.colors.bg3 : props.theme.colors.textHeadings)}; > div { background-color: ${(props) => - props.selected ? props.theme.colors.bg0 : props.theme.colors.textHeadings}; + props.selected ? props.theme.colors.bg0 : props.theme.colors.textHeadings}; } }