bugfix: 200slot gui

This commit is contained in:
w-okada 2023-08-04 12:20:04 +09:00
parent 2777896bb0
commit 8b5eb32047
5 changed files with 261 additions and 58 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,83 +1,114 @@
import React, { useMemo } from "react" import React, { useMemo, useState } from "react";
import { useAppState } from "../../../001_provider/001_AppStateProvider" import { useAppState } from "../../../001_provider/001_AppStateProvider";
import { useGuiState } from "../001_GuiStateProvider" import { useGuiState } from "../001_GuiStateProvider";
import { useMessageBuilder } from "../../../hooks/useMessageBuilder" import { useMessageBuilder } from "../../../hooks/useMessageBuilder";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
export type ModelSlotAreaProps = { export type ModelSlotAreaProps = {};
}
const SortTypes = {
slot: "slot",
name: "name",
} as const;
export type SortTypes = (typeof SortTypes)[keyof typeof SortTypes];
export const ModelSlotArea = (_props: ModelSlotAreaProps) => { export const ModelSlotArea = (_props: ModelSlotAreaProps) => {
const { serverSetting, getInfo } = useAppState() const { serverSetting, getInfo } = useAppState();
const guiState = useGuiState() const guiState = useGuiState();
const messageBuilderState = useMessageBuilder() const messageBuilderState = useMessageBuilder();
const [sortType, setSortType] = useState<SortTypes>("slot");
useMemo(() => { useMemo(() => {
messageBuilderState.setMessage(__filename, "edit", { "ja": "編集", "en": "edit" }) messageBuilderState.setMessage(__filename, "edit", { ja: "編集", en: "edit" });
}, []) }, []);
const modelTiles = useMemo(() => { const modelTiles = useMemo(() => {
if (!serverSetting.serverSetting.modelSlots) { if (!serverSetting.serverSetting.modelSlots) {
return [] return [];
} }
return serverSetting.serverSetting.modelSlots.map((x, index) => { const modelSlots =
sortType == "slot"
? serverSetting.serverSetting.modelSlots
: serverSetting.serverSetting.modelSlots.slice().sort((a, b) => {
return a.name.localeCompare(b.name);
});
return modelSlots
.map((x, index) => {
if (!x.modelFile || x.modelFile.length == 0) { if (!x.modelFile || x.modelFile.length == 0) {
return null return null;
} }
const tileContainerClass = index == serverSetting.serverSetting.modelSlotIndex ? "model-slot-tile-container-selected" : "model-slot-tile-container" const tileContainerClass = x.id == serverSetting.serverSetting.modelSlotIndex ? "model-slot-tile-container-selected" : "model-slot-tile-container";
const name = x.name.length > 8 ? x.name.substring(0, 7) + "..." : x.name const name = x.name.length > 8 ? x.name.substring(0, 7) + "..." : x.name;
const iconElem = x.iconFile.length > 0 ? const iconElem =
x.iconFile.length > 0 ? (
<> <>
<img className="model-slot-tile-icon" src={x.iconFile} alt={x.name} /> <img className="model-slot-tile-icon" src={x.iconFile} alt={x.name} />
<div className="model-slot-tile-vctype">{x.voiceChangerType}</div> <div className="model-slot-tile-vctype">{x.voiceChangerType}</div>
</> </>
: ) : (
<> <>
<div className="model-slot-tile-icon-no-entry">no image</div> <div className="model-slot-tile-icon-no-entry">no image</div>
<div className="model-slot-tile-vctype">{x.voiceChangerType}</div> <div className="model-slot-tile-vctype">{x.voiceChangerType}</div>
</> </>
);
const clickAction = async () => { const clickAction = async () => {
const dummyModelSlotIndex = (Math.floor(Date.now() / 1000)) * 1000 + index const dummyModelSlotIndex = Math.floor(Date.now() / 1000) * 1000 + x.id;
await serverSetting.updateServerSettings({ ...serverSetting.serverSetting, modelSlotIndex: dummyModelSlotIndex }) await serverSetting.updateServerSettings({ ...serverSetting.serverSetting, modelSlotIndex: dummyModelSlotIndex });
setTimeout(() => { // quick hack setTimeout(() => {
getInfo() // quick hack
}, 1000 * 2) getInfo();
} }, 1000 * 2);
};
return ( return (
<div key={index} className={tileContainerClass} onClick={clickAction}> <div key={index} className={tileContainerClass} onClick={clickAction}>
<div className="model-slot-tile-icon-div"> <div className="model-slot-tile-icon-div">{iconElem}</div>
{iconElem} <div className="model-slot-tile-dscription">{name}</div>
</div> </div>
<div className="model-slot-tile-dscription"> );
{name} })
</div> .filter((x) => x != null);
</div > }, [serverSetting.serverSetting.modelSlots, serverSetting.serverSetting.modelSlotIndex, sortType]);
)
}).filter(x => x != null)
}, [serverSetting.serverSetting.modelSlots, serverSetting.serverSetting.modelSlotIndex])
const modelSlotArea = useMemo(() => { const modelSlotArea = useMemo(() => {
const onModelSlotEditClicked = () => { const onModelSlotEditClicked = () => {
guiState.stateControls.showModelSlotManagerCheckbox.updateState(true) guiState.stateControls.showModelSlotManagerCheckbox.updateState(true);
} };
const sortSlotByIdClass = sortType == "slot" ? "model-slot-sort-button-active" : "model-slot-sort-button";
const sortSlotByNameClass = sortType == "name" ? "model-slot-sort-button-active" : "model-slot-sort-button";
return ( return (
<div className="model-slot-area"> <div className="model-slot-area">
<div className="model-slot-panel"> <div className="model-slot-panel">
<div className="model-slot-tiles-container">{modelTiles}</div> <div className="model-slot-tiles-container">{modelTiles}</div>
<div className="model-slot-buttons"> <div className="model-slot-buttons">
<div className="model-slot-sort-buttons">
<div
className={sortSlotByIdClass}
onClick={() => {
setSortType("slot");
}}
>
<FontAwesomeIcon icon={["fas", "arrow-down-1-9"]} style={{ fontSize: "1rem" }} />
</div>
<div
className={sortSlotByNameClass}
onClick={() => {
setSortType("name");
}}
>
<FontAwesomeIcon icon={["fas", "arrow-down-a-z"]} style={{ fontSize: "1rem" }} />
</div>
</div>
<div className="model-slot-button" onClick={onModelSlotEditClicked}> <div className="model-slot-button" onClick={onModelSlotEditClicked}>
{messageBuilderState.getMessage(__filename, "edit")} {messageBuilderState.getMessage(__filename, "edit")}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
) );
}, [modelTiles]) }, [modelTiles, sortType]);
return modelSlotArea return modelSlotArea;
} };

View File

@ -757,6 +757,18 @@ body {
max-height: 60vh; max-height: 60vh;
width: 100%; width: 100%;
overflow-y: scroll; overflow-y: scroll;
&::-webkit-scrollbar {
width: 10px;
height: 10px;
}
&::-webkit-scrollbar-track {
background-color: #eee;
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: #f7cfec80;
border-radius: 3px;
}
.model-slot { .model-slot {
height: 5rem; height: 5rem;
@ -1152,12 +1164,28 @@ body {
flex-wrap: wrap; flex-wrap: wrap;
overflow-y: scroll; overflow-y: scroll;
max-height: 12rem; max-height: 12rem;
&::-webkit-scrollbar {
width: 10px;
height: 10px;
}
&::-webkit-scrollbar-track {
background-color: #eee;
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: #f7cfec80;
border-radius: 3px;
}
/* width: calc(30rem + 40px + 10px); */ /* width: calc(30rem + 40px + 10px); */
} }
.model-slot-buttons { .model-slot-buttons {
display: flex; display: flex;
flex-direction: column-reverse; gap: 5px;
flex-direction: column;
justify-content: space-between;
width: 4rem;
.model-slot-button { .model-slot-button {
border: solid 2px #999; border: solid 2px #999;
color: white; color: white;
@ -1166,10 +1194,41 @@ body {
background: #333; background: #333;
cursor: pointer; cursor: pointer;
padding: 5px; padding: 5px;
text-align: center;
width: 3rem;
} }
.model-slot-button:hover { .model-slot-button:hover {
border: solid 2px #faa; border: solid 2px #faa;
} }
.model-slot-sort-buttons {
height: 50%;
.model-slot-sort-button {
color: white;
font-size: 0.8rem;
border-radius: 4px;
background: #333;
border: solid 2px #444;
cursor: pointer;
padding: 1px;
text-align: center;
width: 3rem;
}
.model-slot-sort-button-active {
color: white;
font-size: 0.8rem;
border-radius: 4px;
background: #595;
border: solid 2px #595;
cursor: pointer;
padding: 1px;
text-align: center;
width: 3rem;
}
.model-slot-sort-button:hover {
border: solid 2px #faa;
background: #343;
}
}
} }
} }
} }
@ -1639,6 +1698,19 @@ audio::-webkit-media-controls-overlay-enclosure{
width: 70%; width: 70%;
overflow-y: scroll; overflow-y: scroll;
max-height: 20rem; max-height: 20rem;
&::-webkit-scrollbar {
width: 10px;
height: 10px;
}
&::-webkit-scrollbar-track {
background-color: #eee;
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: #f7cfec80;
border-radius: 3px;
}
.merge-lab-model-item { .merge-lab-model-item {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

View File

@ -193,6 +193,7 @@ export type VoiceChangerServerSetting = {
} }
type ModelSlot = { type ModelSlot = {
id: number
voiceChangerType: VoiceChangerType voiceChangerType: VoiceChangerType
name: string, name: string,
description: string, description: string,

View File

@ -9,6 +9,7 @@ import json
@dataclass @dataclass
class ModelSlot: class ModelSlot:
id: int = -1
voiceChangerType: VoiceChangerType | None = None voiceChangerType: VoiceChangerType | None = None
name: str = "" name: str = ""
description: str = "" description: str = ""
@ -153,6 +154,7 @@ def loadAllSlotInfo(model_dir: str):
slotInfos: list[ModelSlots] = [] slotInfos: list[ModelSlots] = []
for slotIndex in range(MAX_SLOT_NUM): for slotIndex in range(MAX_SLOT_NUM):
slotInfo = loadSlotInfo(model_dir, slotIndex) slotInfo = loadSlotInfo(model_dir, slotIndex)
slotInfo.id = slotIndex
slotInfos.append(slotInfo) slotInfos.append(slotInfo)
return slotInfos return slotInfos