From c444dc51007fd9f1998c5f5b6d5f976ac5d4d15d Mon Sep 17 00:00:00 2001 From: Mahiru Date: Thu, 4 Jan 2024 20:16:13 +0800 Subject: [PATCH 1/6] Update ChangeFigure.tsx --- .../GraphicalEditor/SentenceEditor/ChangeFigure.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx index d53b7506a..8d901e854 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx @@ -46,25 +46,25 @@ export default function ChangeFigure(props: ISentenceEditorProps) { axios.get(`/games/${gameName}/game/figure/${figureFile.value}`).then(resp => { const data = resp.data; - if(data.motions){ + if(data?.motions){ // 处理 motions const motions = Object.keys(data.motions); setL2dMotionsList(motions.sort((a, b) => a.localeCompare(b))); } // 处理 expressions - if (data.expressions) { + if (data?.expressions) { const expressions: string[] = data.expressions.map((exp: { name: string }) => exp.name); setL2dExpressionsList(expressions.sort((a, b) => a.localeCompare(b))); } // 处理 v3 版本的 model - if(data['FileReferences']['Motions']){ + if(data?.['FileReferences']?.['Motions']){ const motions = Object.keys(data['FileReferences']['Motions']); setL2dMotionsList(motions.sort((a, b) => a.localeCompare(b))); } - if(data['FileReferences']['Expressions']){ + if(data?.['FileReferences']?.['Expressions']){ const expressions: string[] = data['FileReferences']['Expressions'].map((exp: { Name: string }) => exp.Name); setL2dExpressionsList(expressions.sort((a, b) => a.localeCompare(b))); } From 85412cb9012a9a4e5284b271748c96982c4cb810 Mon Sep 17 00:00:00 2001 From: tinyAdapter Date: Fri, 5 Jan 2024 17:16:15 +0800 Subject: [PATCH 2/6] feat: listening port at env var WEBGAL_PORT --- packages/dev-server/index.js | 46 +++++++++++++++++++++----------- packages/origine2/openapi.ts | 10 +++++-- packages/origine2/package.json | 2 +- packages/origine2/vite.config.ts | 15 ++++++++--- packages/terre2/src/main.ts | 10 +++++-- 5 files changed, 59 insertions(+), 24 deletions(-) diff --git a/packages/dev-server/index.js b/packages/dev-server/index.js index d9c9be64d..200248dee 100644 --- a/packages/dev-server/index.js +++ b/packages/dev-server/index.js @@ -1,12 +1,17 @@ const express = require("express"); const { createProxyMiddleware } = require("http-proxy-middleware"); +const { env } = require("process") + const app = express(); app.set("port", "80"); -app.all("*", function(req, res, next) { +app.all("*", function (req, res, next) { // 解决跨域问题 res.header("Access-Control-Allow-Origin", "*"); - res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With"); + res.header( + "Access-Control-Allow-Headers", + "Content-Type,Content-Length, Authorization, Accept,X-Requested-With" + ); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); if (req.method === "OPTIONS") { res.send(200); @@ -15,21 +20,32 @@ app.all("*", function(req, res, next) { } }); -app.use(createProxyMiddleware("/api", { - target: "http://localhost:3001",// http代理跨域目标接口 - changeOrigin: true -})); +let WEBGAL_PORT = 3000; // default port +if (env.WEBGAL_PORT) { + WEBGAL_PORT = Number.parseInt(env.WEBGAL_PORT); +} + +app.use( + createProxyMiddleware("/api", { + target: `http://localhost:${WEBGAL_PORT + 1}`, // http代理跨域目标接口 + changeOrigin: true, + }) +); -app.use(createProxyMiddleware("/games", { - target: "http://localhost:3001",// http代理跨域目标接口 - changeOrigin: true, -})); +app.use( + createProxyMiddleware("/games", { + target: `http://localhost:${WEBGAL_PORT + 1}`, // http代理跨域目标接口 + changeOrigin: true, + }) +); -app.use(createProxyMiddleware("/", { - target: "http://localhost:3000",// http代理跨域目标接口 - ws:true, - changeOrigin: true -})); +app.use( + createProxyMiddleware("/", { + target: `http://localhost:${WEBGAL_PORT}`, // http代理跨域目标接口 + ws: true, + changeOrigin: true, + }) +); app.listen(app.get("port"), () => { console.log(`反向代理已开启,端口:${app.get("port")}`); diff --git a/packages/origine2/openapi.ts b/packages/origine2/openapi.ts index 084d1c9f1..3f40b6974 100644 --- a/packages/origine2/openapi.ts +++ b/packages/origine2/openapi.ts @@ -4,9 +4,15 @@ import axios from 'axios'; import {writeFileSync} from 'fs'; -import { exec } from 'child_process'; +import { exec } from 'child_process' +import { env } from 'process'; -const SWAGGER_URL = 'http://localhost:3001/api-json'; +let WEBGAL_PORT = 3000; // default port +if (env.WEBGAL_PORT) { + WEBGAL_PORT = Number.parseInt(env.WEBGAL_PORT); +}; + +const SWAGGER_URL = `http://localhost:${WEBGAL_PORT + 1}/api-json`; const SWAGGER_JSON_PATH = './src/config/swagger.json'; const API_OUTPUT_PATH = './src/api'; diff --git a/packages/origine2/package.json b/packages/origine2/package.json index 9cf761f8f..de9f335ad 100644 --- a/packages/origine2/package.json +++ b/packages/origine2/package.json @@ -4,7 +4,7 @@ "version": "4.4.8", "license": "MPL-2.0", "scripts": { - "dev": "vite --port=3000 --host", + "dev": "vite --host", "build": "node version-sync.js && tsc && vite build --base=./", "build-lowram": "node version-sync.js && tsc && node --max_old_space_size=512000 ./node_modules/bin/vite build --base=./", "preview": "vite preview", diff --git a/packages/origine2/vite.config.ts b/packages/origine2/vite.config.ts index 202e7c5a8..82a013c55 100644 --- a/packages/origine2/vite.config.ts +++ b/packages/origine2/vite.config.ts @@ -1,6 +1,12 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import {resolve} from 'path'; +import { resolve } from 'path'; +import { env } from 'process'; + +let WEBGAL_PORT = 3000; // default port +if (env.WEBGAL_PORT) { + WEBGAL_PORT = Number.parseInt(env.WEBGAL_PORT); +} // https://vitejs.dev/config/ export default defineConfig({ @@ -11,18 +17,19 @@ export default defineConfig({ }, }, server: { + port: WEBGAL_PORT, proxy: { // 接口地址代理 '/api': { - target: 'http://localhost:3001', // 接口的域名 + target: `http://localhost:${WEBGAL_PORT + 1}`, // 接口的域名 secure: true, // 如果是https接口,需要配置这个参数 changeOrigin: true, // 如果接口跨域,需要进行这个参数配置 }, '/games': { - target: 'http://localhost:3001', // 接口的域名 + target: `http://localhost:${WEBGAL_PORT + 1}`, // 接口的域名 secure: true, // 如果是https接口,需要配置这个参数 changeOrigin: true, // 如果接口跨域,需要进行这个参数配置 }, }, }, -}) +}); diff --git a/packages/terre2/src/main.ts b/packages/terre2/src/main.ts index 36667cca7..a36650960 100644 --- a/packages/terre2/src/main.ts +++ b/packages/terre2/src/main.ts @@ -4,6 +4,12 @@ import * as process from 'process'; import { _open } from './util/open'; import { urlencoded, json } from 'express'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; +import { env } from 'process'; + +let WEBGAL_PORT = 3000; // default port +if (env.WEBGAL_PORT) { + WEBGAL_PORT = Number.parseInt(env.WEBGAL_PORT); +} async function bootstrap() { const app = await NestFactory.create(AppModule); @@ -16,11 +22,11 @@ async function bootstrap() { .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); - await app.listen(3001); + await app.listen(WEBGAL_PORT + 1); } bootstrap().then(() => { console.log(`WebGAL Terre 4.4.8 starting at ${process.cwd()}`); if ((process?.env?.NODE_ENV ?? '') !== 'development') - _open('http://localhost:3001'); + _open(`http://localhost:${WEBGAL_PORT + 1}`); }); From ebc429a4a0f421175c25324223b68e817f1933e0 Mon Sep 17 00:00:00 2001 From: Mahiru Date: Fri, 5 Jan 2024 20:52:05 +0800 Subject: [PATCH 3/6] fix: live2d figure motion and expression get --- .../editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx index 8d901e854..2c6906906 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx @@ -43,6 +43,7 @@ export default function ChangeFigure(props: ISentenceEditorProps) { useEffect(() => { if (figureFile.value.includes('json')) { + console.log('loading JSON file to get motion and expression'); axios.get(`/games/${gameName}/game/figure/${figureFile.value}`).then(resp => { const data = resp.data; @@ -71,7 +72,7 @@ export default function ChangeFigure(props: ISentenceEditorProps) { }); } - }, [figureFile]); + }, [figureFile.value]); const toggleAccordion = () => { setIsAccordionOpen(!isAccordionOpen); }; From 4eb8ece4805ba9d9dcc093b20136d2fca6c1a25f Mon Sep 17 00:00:00 2001 From: Mahiru Date: Tue, 9 Jan 2024 21:16:47 +0800 Subject: [PATCH 4/6] fix: Say editor and panel expand --- packages/origine2/src/hooks/useExpand.ts | 10 ++++ .../GraphicalEditor/GraphicalEditor.tsx | 4 +- .../SentenceEditor/ChangeBg.tsx | 49 ++++++++++--------- .../SentenceEditor/ChangeFigure.tsx | 10 ++-- .../GraphicalEditor/SentenceEditor/Intro.tsx | 44 ++++++++--------- .../GraphicalEditor/SentenceEditor/Say.tsx | 5 +- .../SentenceEditor/SetTransform.tsx | 7 +-- .../GraphicalEditor/SentenceEditor/index.tsx | 1 + .../GraphicalEditor/components/TerrePanel.tsx | 14 +++--- packages/origine2/src/store/statusReducer.ts | 20 ++++++-- 10 files changed, 96 insertions(+), 68 deletions(-) create mode 100644 packages/origine2/src/hooks/useExpand.ts diff --git a/packages/origine2/src/hooks/useExpand.ts b/packages/origine2/src/hooks/useExpand.ts new file mode 100644 index 000000000..ffe38666b --- /dev/null +++ b/packages/origine2/src/hooks/useExpand.ts @@ -0,0 +1,10 @@ +import {useDispatch, useSelector} from "react-redux"; +import {RootState} from "@/store/origineStore"; +import {updateGraphicalEditorCurrentExpandSentence} from "@/store/statusReducer"; + +export function useExpand() { + const currentExpandSentence = useSelector((state: RootState) => state.status.editor.graphicalEditorState.currentExpandSentence); + const dispatch = useDispatch(); + const updateIndex = (index:number)=>dispatch(updateGraphicalEditorCurrentExpandSentence(index)); + return {expandIndex:currentExpandSentence,updateExpandIndex:updateIndex}; +} diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/GraphicalEditor.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/GraphicalEditor.tsx index 15bca86ef..5fee4f337 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/GraphicalEditor.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/GraphicalEditor.tsx @@ -163,7 +163,7 @@ export default function GraphicalEditor(props: IGraphicalEditorProps) { // console.log(sentence.command); const sentenceConfig = sentenceEditorConfig.find((e) => e.type === sentence.command) ?? sentenceEditorDefault; const SentenceEditor = sentenceConfig.component; - return {(provided, snapshot) => (
- {showSentence.value[i] && { + {showSentence.value[i] && { updateSentenceByIndex(newSentence, i); }}/>} diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeBg.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeBg.tsx index 375400421..8147d7988 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeBg.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeBg.tsx @@ -1,15 +1,16 @@ import CommonOptions from "../components/CommonOption"; -import { ISentenceEditorProps } from "./index"; +import {ISentenceEditorProps} from "./index"; import styles from "./sentenceEditor.module.scss"; import ChooseFile from "../../ChooseFile/ChooseFile"; -import { useValue } from "../../../../hooks/useValue"; -import { getArgByKey } from "../utils/getArgByKey"; +import {useValue} from "../../../../hooks/useValue"; +import {getArgByKey} from "../utils/getArgByKey"; import TerreToggle from "../../../../components/terreToggle/TerreToggle"; import useTrans from "@/hooks/useTrans"; import CommonTips from "@/pages/editor/GraphicalEditor/components/CommonTips"; import {EffectEditor} from "@/pages/editor/GraphicalEditor/components/EffectEditor"; import {DefaultButton, PrimaryButton, TextField} from "@fluentui/react"; import {TerrePanel} from "@/pages/editor/GraphicalEditor/components/TerrePanel"; +import {useExpand} from "@/hooks/useExpand"; export default function ChangeBg(props: ISentenceEditorProps) { const t = useTrans('editor.graphical.sentences.changeBg.'); @@ -18,14 +19,14 @@ export default function ChangeBg(props: ISentenceEditorProps) { const bgFile = useValue(props.sentence.content); const unlockName = useValue(getArgByKey(props.sentence, "unlockname").toString() ?? ""); const unlockSeries = useValue(getArgByKey(props.sentence, "series").toString() ?? ""); - const isShowEffectEditor = useValue(false); - const json = useValue(getArgByKey(props.sentence,'transform') as string); - const duration = useValue(getArgByKey(props.sentence,'duration') as number); + const {updateExpandIndex} = useExpand(); + const json = useValue(getArgByKey(props.sentence, 'transform') as string); + const duration = useValue(getArgByKey(props.sentence, 'duration') as number); const submit = () => { const isGoNextStr = isGoNext.value ? " -next" : ""; - const durationStr = duration.value===""?'':` -duration=${duration.value}`; - const transformStr = json.value===""?'':` -transform=${json.value}`; - if(bgFile.value !== "none"){ + const durationStr = duration.value === "" ? '' : ` -duration=${duration.value}`; + const transformStr = json.value === "" ? '' : ` -transform=${json.value}`; + if (bgFile.value !== "none") { props.onSubmit(`changeBg:${bgFile.value}${isGoNextStr}${durationStr}${transformStr}${unlockName.value !== "" ? " -unlockname=" + unlockName.value : ""}${unlockSeries.value !== "" ? " -series=" + unlockSeries.value : ""};`); } else { props.onSubmit(`changeBg:${bgFile.value}${isGoNextStr};`); @@ -41,7 +42,7 @@ export default function ChangeBg(props: ISentenceEditorProps) { } else bgFile.set("none"); submit(); - }} onText={t('options.hide.on')} offText={t('options.hide.off')} isChecked={isNoFile} /> + }} onText={t('options.hide.on')} offText={t('options.hide.off')} isChecked={isNoFile}/> {!isNoFile && <> @@ -50,14 +51,15 @@ export default function ChangeBg(props: ISentenceEditorProps) { bgFile.set(fileDesc?.name ?? ""); submit(); }} - extName={[".png", ".jpg", ".webp"]} /> + extName={[".png", ".jpg", ".webp"]}/> } { isGoNext.set(newValue); submit(); - }} onText={t('$editor.graphical.sentences.common.options.goNext.on')} offText={t('$editor.graphical.sentences.common.options.goNext.off')} isChecked={isGoNext.value} /> + }} onText={t('$editor.graphical.sentences.common.options.goNext.on')} + offText={t('$editor.graphical.sentences.common.options.goNext.off')} isChecked={isGoNext.value}/> {!isNoFile && } { - isShowEffectEditor.value = true; + updateExpandIndex(props.index); }}>{t('$打开效果编辑器')} - isShowEffectEditor.set(false)} isOpen={isShowEffectEditor.value} title={t("$效果编辑器")}> +
@@ -86,14 +88,15 @@ export default function ChangeBg(props: ISentenceEditorProps) { }}/>
- { - const newDuration = Number(newValue); - if (isNaN(newDuration) || newValue === '') - duration.set(""); - else - duration.set(newDuration); - submit(); - }}/> + { + const newDuration = Number(newValue); + if (isNaN(newDuration) || newValue === '') + duration.set(""); + else + duration.set(newDuration); + submit(); + }}/>
diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx index 2c6906906..680392c25 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/ChangeFigure.tsx @@ -14,6 +14,7 @@ import axios from "axios"; import {useSelector} from "react-redux"; import {RootState} from "@/store/origineStore"; import {TerrePanel} from "@/pages/editor/GraphicalEditor/components/TerrePanel"; +import {useExpand} from "@/hooks/useExpand"; export default function ChangeFigure(props: ISentenceEditorProps) { const gameName = useSelector((state: RootState) => state.status.editor.currentEditingGame); @@ -25,7 +26,7 @@ export default function ChangeFigure(props: ISentenceEditorProps) { const id = useValue(getArgByKey(props.sentence, "id").toString() ?? ""); const json = useValue(getArgByKey(props.sentence, 'transform') as string); const duration = useValue(getArgByKey(props.sentence, 'duration') as number); - const isShowEffectEditor = useValue(false); + const {updateExpandIndex} = useExpand(); const mouthOpen = useValue(getArgByKey(props.sentence, "mouthOpen").toString() ?? ""); const mouthHalfOpen = useValue(getArgByKey(props.sentence, "mouthHalfOpen").toString() ?? ""); const mouthClose = useValue(getArgByKey(props.sentence, "mouthClose").toString() ?? ""); @@ -209,15 +210,12 @@ export default function ChangeFigure(props: ISentenceEditorProps) { { - isShowEffectEditor.value = true; + updateExpandIndex(props.index); }}>{t('$打开效果编辑器')} { - isShowEffectEditor.value = false; - }} + sentenceIndex={props.index} >
{ const animationValue = getArgByKey(props.sentence, "animation"); - if (typeof animationValue === 'string' && ["fadeIn","slideIn","typingEffect","pixelateEffect","revealAnimation"].includes(animationValue)) { + if (typeof animationValue === 'string' && ["fadeIn", "slideIn", "typingEffect", "pixelateEffect", "revealAnimation"].includes(animationValue)) { return animationValue; } @@ -123,22 +124,22 @@ export default function Intro(props: ISentenceEditorProps) { ]; const animations = [ - { key: "fadeIn", text: "fadeIn" }, - { key: "slideIn", text: "slideIn" }, - { key: "typingEffect", text: "typingEffect" }, - { key: "pixelateEffect", text: "pixelateEffect" }, - { key: "revealAnimation", text: "revealAnimation" }, + {key: "fadeIn", text: "fadeIn"}, + {key: "slideIn", text: "slideIn"}, + {key: "typingEffect", text: "typingEffect"}, + {key: "pixelateEffect", text: "pixelateEffect"}, + {key: "revealAnimation", text: "revealAnimation"}, ]; const delayTimes = [ - { key: "1500", text: "1.5" }, - { key: "2000", text: "2" }, - { key: "2500", text: "2.5" }, - { key: "3000", text: "3" }, - { key: "3500", text: "3.5" }, - { key: "4000", text: "4" }, - { key: "4500", text: "4.5" }, - { key: "5000", text: "5" }, + {key: "1500", text: "1.5"}, + {key: "2000", text: "2"}, + {key: "2500", text: "2.5"}, + {key: "3000", text: "3"}, + {key: "3500", text: "3.5"}, + {key: "4000", text: "4"}, + {key: "4500", text: "4.5"}, + {key: "5000", text: "5"}, ]; const backgroundColor = useValue(getBackgroundColor()); @@ -148,10 +149,7 @@ export default function Intro(props: ISentenceEditorProps) { const delayTime = useValue(getInitialDelayTime()); const [localBackgroundColor, setLocalBackgroundColor] = useState(backgroundColor.value); const [localFontColor, setLocalFontColor] = useState(fontColor.value); - const [isAccordionOpen, setIsAccordionOpen] = useState(false); - const toggleAccordion = () => { - setIsAccordionOpen(!isAccordionOpen); - }; + const {updateExpandIndex} = useExpand(); const optionButtonStyles = { root: { // margin: '6px 0 0 0', @@ -217,10 +215,10 @@ export default function Intro(props: ISentenceEditorProps) { introTextList.set(newList); submit(); }}>{t('add.button')} - + updateExpandIndex(props.index)} styles={optionButtonStyles}> {t('$效果选项')} - setIsAccordionOpen(!isAccordionOpen)} isOpen={isAccordionOpen} title="效果选项"> +
diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/Say.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/Say.tsx index 1f8469f5e..5beb4dce9 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/Say.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/Say.tsx @@ -60,10 +60,11 @@ export default function Say(props: ISentenceEditorProps) { const selectedFontSize = fontSize.value; const pos = figurePosition.value !== "" ? ` -${figurePosition.value}` : ""; const idStr = figureId.value !== "" ? ` -figureId=${figureId.value}` : ""; + const commitValue = currentValue.value.map(e=>e.replaceAll('\n','|')); if(figurePosition.value === "id"){ - props.onSubmit(`${isNoSpeaker.value ? "" : currentSpeaker.value}${isNoSpeaker.value || currentSpeaker.value !== "" ? ":" : ""}${currentValue.value.join("|")}${vocal.value === "" ? "" : " -" + vocal.value} -fontSize=${selectedFontSize}${pos}${idStr};`); + props.onSubmit(`${isNoSpeaker.value ? "" : currentSpeaker.value}${isNoSpeaker.value || currentSpeaker.value !== "" ? ":" : ""}${commitValue.join("|")}${vocal.value === "" ? "" : " -" + vocal.value} -fontSize=${selectedFontSize}${pos}${idStr};`); } else { - props.onSubmit(`${isNoSpeaker.value ? "" : currentSpeaker.value}${isNoSpeaker.value || currentSpeaker.value !== "" ? ":" : ""}${currentValue.value.join("|")}${vocal.value === "" ? "" : " -" + vocal.value} -fontSize=${selectedFontSize}${pos};`); + props.onSubmit(`${isNoSpeaker.value ? "" : currentSpeaker.value}${isNoSpeaker.value || currentSpeaker.value !== "" ? ":" : ""}${commitValue.join("|")}${vocal.value === "" ? "" : " -" + vocal.value} -fontSize=${selectedFontSize}${pos};`); } }; diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/SetTransform.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/SetTransform.tsx index 6ab32dabb..e0bbab332 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/SetTransform.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/SetTransform.tsx @@ -8,6 +8,7 @@ import {DefaultButton, Dropdown, PrimaryButton, TextField} from "@fluentui/react import {EffectEditor} from "@/pages/editor/GraphicalEditor/components/EffectEditor"; import TerreToggle from "@/components/terreToggle/TerreToggle"; import {TerrePanel} from "@/pages/editor/GraphicalEditor/components/TerrePanel"; +import {useExpand} from "@/hooks/useExpand"; export default function SetTransform(props: ISentenceEditorProps) { // const t = useTrans('editor.graphical.components.template.'); @@ -17,7 +18,7 @@ export default function SetTransform(props: ISentenceEditorProps) { const durationFromArgs = getArgByKey(sentence, 'duration'); const transform = useValue((json ?? '') as string); const duration = useValue((durationFromArgs ?? 0) as number); - const isShowEffectEditor = useValue(false); + const {updateExpandIndex} = useExpand(); const isGoNext = useValue(!!getArgByKey(props.sentence, "next")); const target = useValue(getArgByKey(props.sentence, "target")?.toString() ?? ""); const isPresetTarget = ["bg-main", "fig-left", "fig-center", "fig-right"].includes(target.value); @@ -33,9 +34,9 @@ export default function SetTransform(props: ISentenceEditorProps) {
{ - isShowEffectEditor.value = true; + updateExpandIndex(props.index); }}>{tTarget('$打开效果编辑器')} - isShowEffectEditor.set(false)} isOpen={isShowEffectEditor.value} title={tTarget("$效果编辑器")}> + { transform.set(newJson); submit(); diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/index.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/index.tsx index 8f9f75d21..422435818 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/index.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/SentenceEditor/index.tsx @@ -48,6 +48,7 @@ import GetUserInput from "@/pages/editor/GraphicalEditor/SentenceEditor/GetUserI export interface ISentenceEditorProps { sentence: ISentence; onSubmit: (newSentence: string) => void; + index:number } export interface ISentenceEditorConfig { diff --git a/packages/origine2/src/pages/editor/GraphicalEditor/components/TerrePanel.tsx b/packages/origine2/src/pages/editor/GraphicalEditor/components/TerrePanel.tsx index 7f5c63103..584e06ee2 100644 --- a/packages/origine2/src/pages/editor/GraphicalEditor/components/TerrePanel.tsx +++ b/packages/origine2/src/pages/editor/GraphicalEditor/components/TerrePanel.tsx @@ -1,21 +1,23 @@ import {Panel, PanelType} from "@fluentui/react"; import React, {ReactNode} from "react"; +import {useExpand} from "@/hooks/useExpand"; export function TerrePanel(props: { children: ReactNode, - onDismiss: () => void, - isOpen: boolean, width?: number, - title: string + title: string, + sentenceIndex: number, }) { const {width = 750} = props; + const {expandIndex, updateExpandIndex} = useExpand(); + const isExpand = expandIndex === props.sentenceIndex; return updateExpandIndex(0)} customWidth={`${width}px`} // You MUST provide this prop! Otherwise, screen readers will just say "button" with no label. closeButtonAriaLabel="Close" diff --git a/packages/origine2/src/store/statusReducer.ts b/packages/origine2/src/store/statusReducer.ts index a0913a403..19ae08202 100644 --- a/packages/origine2/src/store/statusReducer.ts +++ b/packages/origine2/src/store/statusReducer.ts @@ -35,6 +35,10 @@ export enum TopbarTabs { AddSentence } +interface IGraphicalEditorState { + currentExpandSentence: number; +} + interface IEditorState { currentEditingGame: string, isEnableLivePreview: boolean, @@ -44,7 +48,8 @@ interface IEditorState { selectedTagTarget: string, isCodeMode: boolean, currentTopbarTab: TopbarTabs | undefined, - language: language + language: language, + graphicalEditorState: IGraphicalEditorState, } // tag的假数据,用于测试 @@ -64,7 +69,10 @@ export const editorInitState: IEditorState = { tags: [], selectedTagTarget: "", isCodeMode: (localStorage.getItem("isCodeMode") ?? "") === "true", - language: language.zhCn + language: language.zhCn, + graphicalEditorState: { + currentExpandSentence: 0 + } }; const initialState = { @@ -126,6 +134,7 @@ const statusSlice = createSlice({ */ setCurrentTagTarget: function (state, action: PayloadAction) { state.editor.selectedTagTarget = action.payload; + state.editor.graphicalEditorState.currentExpandSentence = 0; }, /** * 添加编辑页 Tag @@ -156,6 +165,10 @@ const statusSlice = createSlice({ setIsLivePreview: (state, action: PayloadAction) => { state.editor.isEnableLivePreview = action.payload; + }, + + updateGraphicalEditorCurrentExpandSentence:(state,action:PayloadAction)=>{ + state.editor.graphicalEditorState.currentExpandSentence = action.payload; } } @@ -170,7 +183,8 @@ export const { setCurrentTagTarget, setEditMode, setLanguage, - setIsLivePreview + setIsLivePreview, + updateGraphicalEditorCurrentExpandSentence } = statusSlice.actions; export const statusActions = statusSlice.actions; From 0369ee009d8f68dfc9751d38bb7ad39d808d350f Mon Sep 17 00:00:00 2001 From: 22 <60903333+nini22P@users.noreply.github.com> Date: Tue, 9 Jan 2024 23:36:40 +0800 Subject: [PATCH 5/6] feat: dashBoard migrating to fluent ui v9 --- packages/origine2/package.json | 2 + packages/origine2/src/App.css | 3 + packages/origine2/src/App.tsx | 3 +- packages/origine2/src/main.tsx | 35 +- .../origine2/src/pages/dashboard/About.tsx | 68 +- .../src/pages/dashboard/DashBoard.tsx | 104 +- .../src/pages/dashboard/GameElement.tsx | 179 ++- .../src/pages/dashboard/GamePreview.tsx | 17 +- .../origine2/src/pages/dashboard/Sidebar.tsx | 73 +- .../src/pages/dashboard/about.module.scss | 30 - .../src/pages/dashboard/dashboard.module.scss | 10 +- .../pages/dashboard/gameElement.module.scss | 24 +- .../pages/dashboard/gamepreview.module.scss | 13 +- .../src/pages/dashboard/sidebar.module.scss | 13 +- .../pages/editor/Topbar/topbar.module.scss | 1 - .../src/pages/editor/editor.module.scss | 1 - packages/origine2/yarn.lock | 979 -------------- yarn.lock | 1163 +++++++++++++++-- 18 files changed, 1294 insertions(+), 1424 deletions(-) delete mode 100644 packages/origine2/src/pages/dashboard/about.module.scss delete mode 100644 packages/origine2/yarn.lock diff --git a/packages/origine2/package.json b/packages/origine2/package.json index 323ebcc31..52bc59f10 100644 --- a/packages/origine2/package.json +++ b/packages/origine2/package.json @@ -13,6 +13,8 @@ }, "dependencies": { "@fluentui/react": "^8.77.3", + "@fluentui/react-components": "^9.44.1", + "@fluentui/react-icons": "^2.0.224", "@fluentui/react-icons-mdl2": "^1.3.41", "@icon-park/react": "^1.4.2", "@monaco-editor/react": "^4.4.5", diff --git a/packages/origine2/src/App.css b/packages/origine2/src/App.css index 9f450a33d..f74f5f48c 100644 --- a/packages/origine2/src/App.css +++ b/packages/origine2/src/App.css @@ -1,5 +1,8 @@ .App { text-align: center; + background-color: #fafafa; + width: 100%; + height: 100%; } .App-logo { diff --git a/packages/origine2/src/App.tsx b/packages/origine2/src/App.tsx index 7ac2f8cd3..6ce7071af 100644 --- a/packages/origine2/src/App.tsx +++ b/packages/origine2/src/App.tsx @@ -51,9 +51,10 @@ function App() { }, triggerCharacters: ["-", "", ":", "\n"] }); }); + return ( // 将编辑器的根元素占满整个视口 -
+
diff --git a/packages/origine2/src/main.tsx b/packages/origine2/src/main.tsx index 1c7611a4f..4f1444222 100644 --- a/packages/origine2/src/main.tsx +++ b/packages/origine2/src/main.tsx @@ -10,6 +10,37 @@ import { jp } from "./translations/jp"; import 'primereact/resources/themes/fluent-light/theme.css'; import "primereact/resources/primereact.min.css"; import "./primereact.scss"; +import { BrandVariants, createLightTheme, createDarkTheme, FluentProvider, makeStyles, Theme } from "@fluentui/react-components"; + +const terre: BrandVariants = { + 10: "#020306", + 20: "#111725", + 30: "#152642", + 40: "#17325A", + 50: "#163E73", + 60: "#124B8D", + 70: "#0558A8", + 80: "#2A65B4", + 90: "#4672BC", + 100: "#5D80C3", + 110: "#728ECA", + 120: "#859CD1", + 130: "#98ABD8", + 140: "#ABB9DF", + 150: "#BEC8E7", + 160: "#D0D7EE" +}; + +const lightTheme: Theme = { + ...createLightTheme(terre), +}; + +const darkTheme: Theme = { + ...createDarkTheme(terre), +}; + +darkTheme.colorBrandForeground1 = terre[110]; +darkTheme.colorBrandForeground2 = terre[120]; function initTranslation() { i18n.use(initReactI18next) // passes i18n down to react-i18next @@ -38,6 +69,8 @@ initializeIcons(); // 不用 StrictMode,因为会和 react-butiful-dnd 冲突 ReactDOM.createRoot(document.getElementById("root")!).render( // - + + + // ); diff --git a/packages/origine2/src/pages/dashboard/About.tsx b/packages/origine2/src/pages/dashboard/About.tsx index 3d392aacb..2f5faeaa8 100644 --- a/packages/origine2/src/pages/dashboard/About.tsx +++ b/packages/origine2/src/pages/dashboard/About.tsx @@ -1,12 +1,11 @@ import * as React from 'react'; -import { Callout, Link, Text } from '@fluentui/react'; -import { useBoolean, useId } from '@fluentui/react-hooks'; -import { CommandBarButton } from '@fluentui/react/lib/Button'; -import styles from './about.module.scss'; import { __INFO } from "@/config/info"; import { useRelease } from "../../hooks/useRelease"; import { logger } from '@/utils/logger'; import useTrans from '@/hooks/useTrans'; +import { Link, Popover, PopoverSurface, PopoverTrigger, Text, Title1, ToolbarButton } from '@fluentui/react-components'; +import { Info24Filled, Info24Regular, bundleIcon } from '@fluentui/react-icons'; +import { useState } from 'react'; interface DateTimeFormatOptions { year: 'numeric' | '2-digit'; @@ -15,15 +14,12 @@ interface DateTimeFormatOptions { } const About: React.FunctionComponent = () => { - const [isCalloutVisible, { toggle: toggleIsCalloutVisible }] = useBoolean(false); - const buttonId = useId('callout-button'); - const labelId = useId('callout-label'); - const descriptionId = useId('callout-description'); - + const [open, setOpen] = useState(false); const t = useTrans('editor.topBar.'); - const latestRelease = useRelease(); + const InfoIcon = bundleIcon(Info24Filled, Info24Regular); + /** * 比较版本号 * @param latestVersion 最新版本 @@ -60,29 +56,23 @@ const About: React.FunctionComponent = () => { const dateTimeOptions: DateTimeFormatOptions = { year: 'numeric', month: '2-digit', day: '2-digit' }; return ( - <> - - {isCalloutVisible && - - + setOpen(!open)} + > + + }> + {t('about.about')} {isNewRelease ? `(${t('about.checkedForNewVersion')})` : ''} + + + +
+ WebGAL Terre - +

{t('about.slogan')}

{t('about.currentVersion')}: {`${__INFO.version} (${new Date(__INFO.buildTime).toLocaleString('zh-CN', dateTimeOptions).replaceAll('/', '-')})`}
@@ -95,7 +85,7 @@ const About: React.FunctionComponent = () => {

{ isNewRelease && - + {t('about.downloadLatest')} } @@ -109,20 +99,20 @@ const About: React.FunctionComponent = () => {

-
- +
+ {t('about.homePage')} - + {t('about.document')} - + GitHub
- - } - +
+ + ); }; diff --git a/packages/origine2/src/pages/dashboard/DashBoard.tsx b/packages/origine2/src/pages/dashboard/DashBoard.tsx index 89f7f8fa3..c9bd9a918 100644 --- a/packages/origine2/src/pages/dashboard/DashBoard.tsx +++ b/packages/origine2/src/pages/dashboard/DashBoard.tsx @@ -5,15 +5,16 @@ import { logger } from "../../utils/logger"; import { Message, TestRefRef } from "../../components/message/Message"; import styles from "./dashboard.module.scss"; import Sidebar from "./Sidebar"; -import { GamePreview } from "./GamePreview"; +import GamePreview from "./GamePreview"; import { useSelector } from "react-redux"; -import { origineStore, RootState } from "../../store/origineStore"; +import { RootState } from "../../store/origineStore"; import useTrans from "@/hooks/useTrans"; import useLanguage from "@/hooks/useLanguage"; -import { CommandBar, ICommandBarItemProps } from "@fluentui/react"; import { language } from "@/store/statusReducer"; import About from "./About"; import { WebgalParser } from "../editor/GraphicalEditor/parser"; +import { Card, Menu, MenuItem, MenuList, MenuPopover, MenuTrigger, Toolbar, ToolbarButton } from "@fluentui/react-components"; +import { LocalLanguage24Filled, LocalLanguage24Regular, bundleIcon } from "@fluentui/react-icons"; // 返回的文件信息(单个) interface IFileInfo { @@ -33,6 +34,8 @@ export default function DashBoard() { const setLanguage = useLanguage(); const trans = useTrans('dashBoard.'); + const LocalLanguageIcon = bundleIcon(LocalLanguage24Filled, LocalLanguage24Regular); + const isDashboardShow:boolean = useSelector((state: RootState) => state.status.dashboard.showDashBoard); const messageRef = useRef(null); @@ -83,68 +86,53 @@ export default function DashBoard() { refreashDashboard(); }, []); - const _items: ICommandBarItemProps[] = [ - { - key: "language", - text: t('commandBar.items.language.text'), - cacheKey: 'language', - iconProps: { iconName: 'LocaleLanguage'}, - subMenuProps: { - items: [ - { - key: 'zhCn', - text: '简体中文', - onClick() {setLanguage(language.zhCn);} - }, - { - key: 'en', - text: 'English', - onClick() {setLanguage(language.en);} - }, - { - key: 'jp', - text: '日本語', - onClick() {setLanguage(language.jp);} - } - ] - } - }, - ]; - const refreash = () => { refreashDashboard(); setCurrentGame(null); }; return <> - { isDashboardShow && (
-
+ { isDashboardShow && +
+
WebGAL Terre -
- + + + + + }>{t('commandBar.items.language.text')} + + + + setLanguage(language.zhCn)}>简体中文 + setLanguage(language.en)}>English + setLanguage(language.jp)}>日本语 + + + + +
+
+ +
+ + { + currentGame.value && + e.dir === currentGame.value)!} + /> + } + +
+
- -
-
- - - {currentGame.value && - e.dir === currentGame.value)!}/>} - {/* 测试新建游戏 */} -
-
)} +
} ; } diff --git a/packages/origine2/src/pages/dashboard/GameElement.tsx b/packages/origine2/src/pages/dashboard/GameElement.tsx index bb18f0258..1e3052c3b 100644 --- a/packages/origine2/src/pages/dashboard/GameElement.tsx +++ b/packages/origine2/src/pages/dashboard/GameElement.tsx @@ -1,5 +1,4 @@ import styles from "./gameElement.module.scss"; -import { CommandBarButton, DefaultButton, Dialog, DialogFooter, DialogType, IContextualMenuProps, PrimaryButton, Stack, TextField } from "@fluentui/react"; import axios from "axios"; import { useDispatch } from "react-redux"; import { setDashboardShow, setEditingGame } from "../../store/statusReducer"; @@ -7,12 +6,14 @@ import { useValue } from "../../hooks/useValue"; import useVarTrans from "@/hooks/useVarTrans"; import { GameInfo } from "./DashBoard"; import { useMemo } from "react"; -import {api} from "@/api"; +import { api } from "@/api"; +import { Button, Dialog, DialogActions, DialogBody, DialogContent, DialogSurface, DialogTitle, Input, Menu, MenuButton, MenuItem, MenuList, MenuPopover, MenuTrigger } from "@fluentui/react-components"; +import { Delete24Filled, Delete24Regular, FolderOpen24Filled, FolderOpen24Regular, MoreVertical24Filled, MoreVertical24Regular, Open24Filled, Open24Regular, Rename24Filled, Rename24Regular, bundleIcon } from "@fluentui/react-icons"; interface IGameElementProps { gameInfo: GameInfo; checked: boolean; - onClick: Function; + onClick: () => void; refreash?: () => void; } @@ -22,10 +23,16 @@ export default function GameElement(props: IGameElementProps) { const t = useVarTrans('dashBoard.'); const dispatch = useDispatch(); - function enterEditor(gameName: string) { + const MoreVerticalIcon = bundleIcon(MoreVertical24Filled, MoreVertical24Regular); + const FolderOpenIcon = bundleIcon(FolderOpen24Filled, FolderOpen24Regular); + const OpenIcon = bundleIcon(Open24Filled, Open24Regular); + const RenameIcon = bundleIcon(Rename24Filled, Rename24Regular); + const DeleteIcon = bundleIcon(Delete24Filled, Delete24Regular); + + const enterEditor = (gameName: string) => { dispatch(setEditingGame(gameName)); dispatch(setDashboardShow(false)); - } + }; let className = styles.gameElement_main; if (props.checked) { @@ -47,46 +54,6 @@ export default function GameElement(props: IGameElementProps) { const isShowRenameDialog = useValue(false); const newGameName = useValue(props.gameInfo.dir); - const deleteDialogContentProps = { - type: DialogType.normal, - title: t('dialogs.deleteGame.title'), - subText: t('dialogs.deleteGame.subtext', {gameName: props.gameInfo.dir}), - }; - - const renameDialogContentProps = { - type: DialogType.normal, - title: t('dialogs.renameDir.title'), - }; - - const menuProps: IContextualMenuProps = { - items: [ - { - key: 'openInFileExplorer', - text: t('menu.openInFileExplorer'), - iconProps: { iconName: 'OpenFolderHorizontal' }, - onClick: () => openInFileExplorer(), - }, - { - key: 'previewInNewTab', - text: t('menu.previewInNewTab'), - iconProps: { iconName: 'OpenInNewTab' }, - onClick: () => previewInNewTab(), - }, - { - key: 'renameDir', - text: t('menu.renameDir'), - iconProps: { iconName: 'Rename' }, - onClick: () => isShowRenameDialog.set(true), - }, - { - key: 'deleteGame', - text: t('menu.deleteGame'), - iconProps: { iconName: 'Delete' }, - onClick: () => isShowDeleteDialog.set(true), - }, - ], - }; - const openInFileExplorer = () => { api.manageGameControllerOpenGameDict(props.gameInfo.dir); }; @@ -113,56 +80,76 @@ export default function GameElement(props: IGameElementProps) { ); }; - // @ts-ignore - return
- {props.gameInfo.title} -
- {props.gameInfo.title} -
-
- {props.gameInfo.dir} -
- enterEditor(props.gameInfo.dir)} className={styles.editGameButton}>{t('preview.editGame')} - - - + return ( + <> +
+ {props.gameInfo.title} +
+ {props.gameInfo.title} +
+
+ {props.gameInfo.dir} +
event.stopPropagation()}> + + + + } /> + + + + } onClick={() => openInFileExplorer()}>{t('menu.openInFileExplorer')} + } onClick={() => previewInNewTab()}>{t('menu.previewInNewTab')} + } onClick={() => isShowRenameDialog.set(true)}>{t('menu.renameDir')} + } onClick={() => isShowDeleteDialog.set(true)}>{t('menu.deleteGame')} + + + +
+
-
- {/* 删除对话框 */} - - {/* 重命名对话框 */} - -
; + {/* 重命名对话框 */} + isShowRenameDialog.set(!isShowRenameDialog.value)} + > + + + {t('dialogs.renameDir.title')} + + newGameName.set(event.target.value ? event.target.value.trim() : props.gameInfo.dir)} + onKeyDown={(event) => (event.key === 'Enter') && renameThisGame(props.gameInfo.dir, newGameName.value)} + /> + + + + + + + + + {/* 删除对话框 */} + isShowDeleteDialog.set(!isShowDeleteDialog.value)} + > + + + {t('dialogs.deleteGame.title')} + {t('dialogs.deleteGame.subtext', { gameName: props.gameInfo.dir })} + + + + + + + + + ); }; diff --git a/packages/origine2/src/pages/dashboard/GamePreview.tsx b/packages/origine2/src/pages/dashboard/GamePreview.tsx index ec303cb89..58cf89ed9 100644 --- a/packages/origine2/src/pages/dashboard/GamePreview.tsx +++ b/packages/origine2/src/pages/dashboard/GamePreview.tsx @@ -3,7 +3,8 @@ import { useDispatch } from "react-redux"; import { setDashboardShow, setEditingGame } from "../../store/statusReducer"; import useTrans from "@/hooks/useTrans"; import { GameInfo } from './DashBoard'; -import { IconButton } from "@fluentui/react"; +import { Button } from "@fluentui/react-components"; +import { Dismiss48Filled, Dismiss48Regular, bundleIcon } from "@fluentui/react-icons"; interface IGamePreviewProps { currentGame: string; @@ -11,26 +12,22 @@ interface IGamePreviewProps { gameInfo: GameInfo; } -export function GamePreview(props: IGamePreviewProps) { +export default function GamePreview(props: IGamePreviewProps) { const t = useTrans('dashBoard.preview.'); const dispatch = useDispatch(); + + const DismissIcon = bundleIcon(Dismiss48Filled, Dismiss48Regular); + if (props.currentGame === null) { return
{t('noneChecked')}
; } - function enterEditor(gameName: string) { - dispatch(setEditingGame(gameName)); - dispatch(setDashboardShow(false)); - } - return
- props.setCurrentGame(null)} /> - {/* enterEditor(props.currentGame.dir)} className={styles.editGameButton}>{t('editGame')} */} {props.gameInfo.title} - +
{/* eslint-disable-next-line react/iframe-missing-sandbox */}