fix some bugs

This commit is contained in:
wataru 2023-02-22 07:35:26 +09:00
parent 98db8862b5
commit 35ca5a7618
17 changed files with 225 additions and 2676 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@dannadori/voice-changer-client-js": "^1.0.76",
"@dannadori/voice-changer-client-js": "^1.0.78",
"@fortawesome/fontawesome-svg-core": "^6.3.0",
"@fortawesome/free-brands-svg-icons": "^6.3.0",
"@fortawesome/free-regular-svg-icons": "^6.3.0",
@ -3187,9 +3187,9 @@
}
},
"node_modules/@dannadori/voice-changer-client-js": {
"version": "1.0.76",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.76.tgz",
"integrity": "sha512-NOYlPaarEwhxv7CzegXzbiC5XA8ARDwLnU2pn7JSCH8EAfk4SV+qGohdSg12H1Z3u0ry7RT2kyWPNJuMH0dZ5A==",
"version": "1.0.78",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.78.tgz",
"integrity": "sha512-1M5X7WKhpBXaiMxNxrXYeGRby52vq1QUkSzbBWq73kBd0ANesbeLxshhYN+fXCdazTbcDbb5ONNaFw797e7kSA==",
"dependencies": {
"@types/readable-stream": "^2.3.15",
"amazon-chime-sdk-js": "^3.11.0",
@ -13473,9 +13473,9 @@
}
},
"@dannadori/voice-changer-client-js": {
"version": "1.0.76",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.76.tgz",
"integrity": "sha512-NOYlPaarEwhxv7CzegXzbiC5XA8ARDwLnU2pn7JSCH8EAfk4SV+qGohdSg12H1Z3u0ry7RT2kyWPNJuMH0dZ5A==",
"version": "1.0.78",
"resolved": "https://registry.npmjs.org/@dannadori/voice-changer-client-js/-/voice-changer-client-js-1.0.78.tgz",
"integrity": "sha512-1M5X7WKhpBXaiMxNxrXYeGRby52vq1QUkSzbBWq73kBd0ANesbeLxshhYN+fXCdazTbcDbb5ONNaFw797e7kSA==",
"requires": {
"@types/readable-stream": "^2.3.15",
"amazon-chime-sdk-js": "^3.11.0",

View File

@ -51,7 +51,7 @@
"webpack-dev-server": "^4.11.1"
},
"dependencies": {
"@dannadori/voice-changer-client-js": "^1.0.76",
"@dannadori/voice-changer-client-js": "^1.0.78",
"@fortawesome/fontawesome-svg-core": "^6.3.0",
"@fortawesome/free-brands-svg-icons": "^6.3.0",
"@fortawesome/free-regular-svg-icons": "^6.3.0",

View File

@ -1,16 +1,18 @@
import * as React from "react";
import { createRoot } from "react-dom/client";
import "./css/App.css"
import { useMemo, } from "react";
import { ErrorInfo, useMemo, useState, } from "react";
import { useMicrophoneOptions } from "./100_options_microphone";
import { AppStateProvider, useAppState } from "./001_provider/001_AppStateProvider";
import localForage from "localforage";
import { library } from "@fortawesome/fontawesome-svg-core";
import { fas } from "@fortawesome/free-solid-svg-icons";
import { far } from "@fortawesome/free-regular-svg-icons";
import { fab } from "@fortawesome/free-brands-svg-icons";
import { AppRootProvider } from "./001_provider/001_AppRootProvider";
import ErrorBoundary from "./001_provider/900_ErrorBoundary";
import { INDEXEDDB_KEY_CLIENT, INDEXEDDB_KEY_MODEL_DATA, INDEXEDDB_KEY_SERVER, INDEXEDDB_KEY_WORKLET, INDEXEDDB_KEY_WORKLETNODE } from "@dannadori/voice-changer-client-js";
library.add(fas, far, fab);
@ -21,7 +23,6 @@ const root = createRoot(container);
const App = () => {
const appState = useAppState()
const { voiceChangerSetting } = useMicrophoneOptions()
const titleRow = useMemo(() => {
return (
<div className="top-title">
@ -87,14 +88,73 @@ const App = () => {
}
const AppStateWrapper = () => {
// const appRoot = useAppRoot()
// if (!appRoot.audioContextState.audioContext) {
// return <>please click window</>
// }
// エラーバウンダリー設定
const [error, setError] = useState<{ error: Error, errorInfo: ErrorInfo }>()
// localForage.config({
// driver: localForage.INDEXEDDB,
// name: INDEXEDDB_DB_APP_NAME,
// version: 1.0,
// storeName: INDEXEDDB_DB_NAME,
// description: 'appStorage'
// })
const errorComponent = useMemo(() => {
const errorName = error?.error.name || "no error name"
const errorMessage = error?.error.message || "no error message"
const errorInfos = (error?.errorInfo.componentStack || "no error stack").split("\n")
const onClearCacheClicked = () => {
[
INDEXEDDB_KEY_CLIENT,
INDEXEDDB_KEY_SERVER,
INDEXEDDB_KEY_WORKLETNODE,
INDEXEDDB_KEY_MODEL_DATA,
INDEXEDDB_KEY_WORKLET
].forEach((x) => {
localForage.removeItem(x)
})
location.reload();
}
return (
<div className="error-container">
<div className="top-error-message">
</div>
<div className="top-error-description">
<p></p>
<p></p>
<p><button onClick={onClearCacheClicked}></button></p>
</div>
<div className="error-detail">
<div className="error-name">
{errorName}
</div>
<div className="error-message">
{errorMessage}
</div>
<div className="error-info-container">
{errorInfos.map(x => {
return <div className="error-info-line" key={x}>{x}</div>
})}
</div>
</div>
</div>
)
}, [error])
const updateError = (error: Error, errorInfo: React.ErrorInfo) => {
console.log("error compo", error, errorInfo)
setError({ error, errorInfo })
}
return (
<AppStateProvider>
<App></App>
</AppStateProvider>
<ErrorBoundary fallback={errorComponent} onError={updateError}>
<AppStateProvider>
<App></App>
</AppStateProvider>
</ErrorBoundary>
)
}
@ -103,3 +163,4 @@ root.render(
<AppStateWrapper></AppStateWrapper>
</AppRootProvider>
);

View File

@ -13,8 +13,8 @@ export const useAudioConfig = (): AudioConfigState => {
document.removeEventListener('mousedown', createAudioContext);
setAudioContext(ctx)
}
document.addEventListener('touchstart', createAudioContext);
document.addEventListener('mousedown', createAudioContext);
document.addEventListener('touchstart', createAudioContext, false);
document.addEventListener('mousedown', createAudioContext, false);
}, [])
const ret: AudioConfigState = {

View File

@ -1,4 +1,4 @@
import React, { useContext } from "react";
import React, { useContext, useRef } from "react";
import { ReactNode } from "react";
import { AudioConfigState, useAudioConfig } from "../001_globalHooks/001_useAudioConfig";
@ -8,6 +8,7 @@ type Props = {
type AppRootValue = {
audioContextState: AudioConfigState
}
const AppRootContext = React.createContext<AppRootValue | null>(null);
@ -21,9 +22,8 @@ export const useAppRoot = (): AppRootValue => {
export const AppRootProvider = ({ children }: Props) => {
const audioContextState = useAudioConfig()
const providerValue: AppRootValue = {
audioContextState
audioContextState,
};
return <AppRootContext.Provider value={providerValue}>{children}</AppRootContext.Provider>;

View File

@ -1,5 +1,5 @@
import { ClientState } from "@dannadori/voice-changer-client-js";
import React, { useContext, useEffect } from "react";
import React, { useContext, useEffect, useRef } from "react";
import { ReactNode } from "react";
import { useVCClient, VCClientState } from "../001_globalHooks/001_useVCClient";
import { FrontendManagerStateAndMethod, useFrontendManager } from "../001_globalHooks/010_useFrontendManager";
@ -12,6 +12,7 @@ type Props = {
type AppStateValue = ClientState & {
audioContext: AudioContext
frontendManagerState: FrontendManagerStateAndMethod;
initializedRef: React.MutableRefObject<boolean>
}
const AppStateContext = React.createContext<AppStateValue | null>(null);
@ -28,10 +29,21 @@ export const AppStateProvider = ({ children }: Props) => {
const clientState = useVCClient({ audioContext: appRoot.audioContextState.audioContext })
const frontendManagerState = useFrontendManager();
const initializedRef = useRef<boolean>(false)
useEffect(() => {
if (clientState.clientState.initialized) {
initializedRef.current = true
}
}, [clientState.clientState.initialized])
const providerValue: AppStateValue = {
audioContext: appRoot.audioContextState.audioContext!,
...clientState.clientState,
frontendManagerState
frontendManagerState,
initializedRef
};
return <AppStateContext.Provider value={providerValue}>{children}</AppStateContext.Provider>;

View File

@ -0,0 +1,56 @@
import React, { createRef, ErrorInfo } from 'react';
type ErrorBoundaryProps = {
children: React.ReactNode;
fallback: React.ReactNode;
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
}
type ErrorBoundaryState = {
hasError: boolean;
}
class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
private eventHandler: () => void
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false };
this.eventHandler = this.updateError.bind(this);
}
static getDerivedStateFromError(_error: Error) {
// console.warn("React Error Boundary Catch", error)
return { hasError: true };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
// For logging
console.warn("React Error Boundary Catch", error, errorInfo)
const { onError } = this.props;
if (onError) {
onError(error, errorInfo);
}
}
// 非同期例外対応
updateError() {
this.setState({ hasError: true });
}
componentDidMount() {
window.addEventListener('unhandledrejection', this.eventHandler)
}
componentWillUnmount() {
window.removeEventListener('unhandledrejection', this.eventHandler)
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}
export default ErrorBoundary;

View File

@ -29,11 +29,17 @@ export const useServerControl = () => {
const startButtonRow = useMemo(() => {
const onStartClicked = async () => {
if (!appState.audioContext) {
await new Promise<void>((resolve) => {
console.log("wait 2000ms")
setTimeout(resolve, 1000 * 2)
})
if (!appState.initializedRef.current) {
while (true) {
// console.log("wait 500ms")
await new Promise<void>((resolve) => {
setTimeout(resolve, 500)
})
// console.log("initiliazed", appState.initializedRef.current)
if (appState.initializedRef.current) {
break
}
}
setStartWithAudioContextCreate(true)
} else {
appState.frontendManagerState.setIsConverting(true)

View File

@ -121,6 +121,9 @@ export const useModelSettingArea = (): ServerSettingState => {
const pyTorchFilenameText = appState.serverSetting.fileUploadSetting.pyTorchModel?.filename || appState.serverSetting.fileUploadSetting.pyTorchModel?.file?.name || ""
const correspondenceFileText = appState.clientSetting.clientSetting.correspondences ? JSON.stringify(appState.clientSetting.clientSetting.correspondences.map(x => { return x.dirname })) : ""
const uploadingStatus = appState.serverSetting.isUploading ?
appState.serverSetting.uploadProgress == 0 ? `loading model...(wait about 20sec)` : `uploading.... ${appState.serverSetting.uploadProgress}%` : ""
return (
<>
<div className="body-row split-3-3-4 left-padding-1 guided">
@ -190,7 +193,7 @@ export const useModelSettingArea = (): ServerSettingState => {
<div className="body-row split-3-3-4 left-padding-1 guided">
<div className="body-item-title left-padding-2"></div>
<div className="body-item-text">
{appState.serverSetting.isUploading ? `uploading.... ${appState.serverSetting.uploadProgress}%` : ""}
{uploadingStatus}
</div>
<div className="body-button-container">
<div className={uploadButtonClassName} onClick={uploadButtonAction}>{uploadButtonLabel}</div>

View File

@ -2,7 +2,7 @@
@import url("https://fonts.googleapis.com/css2?family=Yusei+Magic&display=swap");
@import "./101_RotatedButton.css";
@import "./Error.css";
:root {
--text-color: #333;
--company-color1: rgba(64, 119, 187, 1);
@ -54,6 +54,12 @@ body {
height: 100%;
width: 100%;
}
.first-gesture {
background: rgba(200, 0, 0, 0.2);
width: 100%;
height: 100%;
position: absolute;
}
/* Main + Section Partition*/
.main-body {

View File

@ -0,0 +1,30 @@
.error-container {
margin: 2rem;
.top-error-message {
color: #44a;
font-size: 2rem;
font-weight: 100;
}
.top-error-description {
color: #444;
font-size: 1rem;
font-weight: 100;
}
.error-detail {
margin-top: 2rem;
padding: 1rem;
border: 1px solid;
.error-name {
font-weight: 700;
}
.error-message {
margin-top: 0.5rem;
}
.error-info-container {
margin-top: 0.5rem;
font-size: 0.8rem;
.error-info-line {
}
}
}
}

View File

@ -1,12 +1,12 @@
{
"name": "@dannadori/voice-changer-client-js",
"version": "1.0.77",
"version": "1.0.78",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@dannadori/voice-changer-client-js",
"version": "1.0.77",
"version": "1.0.78",
"license": "ISC",
"dependencies": {
"@types/readable-stream": "^2.3.15",

View File

@ -1,6 +1,6 @@
{
"name": "@dannadori/voice-changer-client-js",
"version": "1.0.77",
"version": "1.0.78",
"description": "",
"main": "dist/index.js",
"directories": {

View File

@ -11,6 +11,7 @@ export type UseClientProps = {
}
export type ClientState = {
initialized: boolean
// 各種設定I/Fへの参照
workletSetting: WorkletSettingState
clientSetting: ClientSettingState
@ -43,6 +44,7 @@ const InitialPerformanceData: PerformanceData = {
export const useClient = (props: UseClientProps): ClientState => {
const [initialized, setInitialized] = useState<boolean>(false)
// (1-1) クライアント
const voiceChangerClientRef = useRef<VoiceChangerClient | null>(null)
const [voiceChangerClient, setVoiceChangerClient] = useState<VoiceChangerClient | null>(voiceChangerClientRef.current)
@ -110,6 +112,7 @@ export const useClient = (props: UseClientProps): ClientState => {
audio.srcObject = voiceChangerClientRef.current.stream
audio.play()
initializedResolveRef.current!()
setInitialized(true)
}
initialized()
}, [props.audioContext])
@ -133,6 +136,7 @@ export const useClient = (props: UseClientProps): ClientState => {
}
return {
initialized,
// 各種設定I/Fへの参照
clientSetting,
workletNodeSetting,

View File

@ -28,6 +28,10 @@ export const useClientSetting = (props: UseClientSettingProps): ClientSettingSta
useEffect(() => {
const loadCache = async () => {
const setting = await getItem(INDEXEDDB_KEY_CLIENT) as VoiceChangerClientSetting
if (!setting) {
return
}
console.log("[ClientSetting] Load Setting from db", setting)
if (setting.audioInput == "null") {
setting.audioInput = null