mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-21 01:12:40 -04:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4daa98d47e | ||
|
|
46b70de389 | ||
|
|
82ed0c5da3 |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { LoadingDots, TopBar } from "~/components";
|
||||
import { Controls3D } from "./comps/Controls3D";
|
||||
@@ -23,13 +22,13 @@ import { Outliner } from "./comps/Outliner";
|
||||
import { CameraAspectRatio } from "./enums";
|
||||
import { PromptBox } from "./comps/PromptBox";
|
||||
import { OnboardingHelper } from "./comps/OnboardingHelper";
|
||||
import { IsDesktopApp } from "@storyteller/tauri-utils";
|
||||
import { FocalLengthDisplay } from "./comps/FocalLengthDisplay/FocalLengthDisplay";
|
||||
import { DemoModal } from "@storyteller/ui-demo-modal";
|
||||
import { appTabId, setAppTabId } from "~/signals/appTab";
|
||||
import { LoginModal } from "@storyteller/ui-login-modal";
|
||||
|
||||
export const PageEditor = () => {
|
||||
useSignals();
|
||||
const [showLoginModal, setShowLoginModal] = useState(true);
|
||||
//console.log(api());
|
||||
//To prevent the click event from propagating to the canvas: TODO: HANDLE THIS BETTER?
|
||||
const handleOverlayClick = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
@@ -158,7 +157,7 @@ export const PageEditor = () => {
|
||||
<Timeline />
|
||||
</div> */}
|
||||
|
||||
<DemoModal
|
||||
{/* <DemoModal
|
||||
title="Welcome to ArtCraft 3D"
|
||||
subTitle="Your 3D editor for digital art and design"
|
||||
description="Set up your scene by adding objects and start bringing your ideas to life!"
|
||||
@@ -171,6 +170,13 @@ export const PageEditor = () => {
|
||||
console.error("This is not the Desktop app.");
|
||||
}
|
||||
}}
|
||||
/> */}
|
||||
|
||||
<LoginModal
|
||||
onClose={() => {}}
|
||||
videoSrc2D="/resources/videos/artcraft-canvas-demo.mp4"
|
||||
videoSrc3D="/resources/videos/artcraft-3d-demo.mp4"
|
||||
openAiLogo="/resources/images/openai-logo.png"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -54,6 +54,15 @@
|
||||
{
|
||||
"path": "../../libs/components/demo-modal"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/soundboard"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/tab-selector"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/api"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/tooltip"
|
||||
},
|
||||
@@ -65,12 +74,6 @@
|
||||
},
|
||||
{
|
||||
"path": "../../libs/tauri-utils"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/api"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/soundboard"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ export function DemoModal({
|
||||
<video autoPlay muted loop controls={false}>
|
||||
<source src={videoSrc} type="video/mp4" />
|
||||
</video>
|
||||
W
|
||||
</div>
|
||||
<Button
|
||||
className="font-semibold"
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nx/react/babel",
|
||||
{
|
||||
"runtime": "automatic",
|
||||
"useBuiltIns": "usage"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# @storyteller/ui-login-modal
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test @storyteller/ui-login-modal` to execute the unit tests via [Vitest](https://vitest.dev/).
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@storyteller/ui-login-modal",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"development": "./src/index.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
export * from './lib/login-modal';
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Replace this with your own classes
|
||||
*
|
||||
* e.g.
|
||||
* .container {
|
||||
* }
|
||||
*/
|
||||
@@ -0,0 +1,12 @@
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
import LoginModal from './login-modal';
|
||||
|
||||
describe('LoginModal', () => {
|
||||
|
||||
it('should render successfully', () => {
|
||||
const { baseElement } = render(<LoginModal />);
|
||||
expect(baseElement).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,271 @@
|
||||
import { Button } from "@storyteller/ui-button";
|
||||
import { Transition, TransitionChild } from "@headlessui/react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
faArrowRight,
|
||||
faRightToBracket,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { faDiscord } from "@fortawesome/free-brands-svg-icons";
|
||||
import { IsDesktopApp } from "@storyteller/tauri-utils";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
interface LoginModalProps {
|
||||
onClose: () => void;
|
||||
videoSrc2D: string;
|
||||
videoSrc3D: string;
|
||||
openAiLogo: string;
|
||||
}
|
||||
|
||||
export function LoginModal({
|
||||
onClose,
|
||||
videoSrc2D,
|
||||
videoSrc3D,
|
||||
openAiLogo,
|
||||
}: LoginModalProps) {
|
||||
const [step, setStep] = useState(1);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [hasSession, setHasSession] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const totalSteps = 3;
|
||||
|
||||
const checkSession = async () => {
|
||||
// Bombay: This will be replaced with actual session check
|
||||
// For testing: return true to simulate having a session, false to simulate no session
|
||||
const sessionExists = false;
|
||||
setHasSession(sessionExists);
|
||||
return sessionExists;
|
||||
};
|
||||
|
||||
// Check session on component mount
|
||||
useEffect(() => {
|
||||
const initSession = async () => {
|
||||
const sessionExists = await checkSession();
|
||||
if (!sessionExists) {
|
||||
setIsOpen(true);
|
||||
setStep(1);
|
||||
} else {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
initSession();
|
||||
}, [hasSession]);
|
||||
|
||||
const handleClose = () => {
|
||||
setIsOpen(false);
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleNext = async () => {
|
||||
if (step === 2) {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
if (IsDesktopApp()) {
|
||||
await invoke("open_sora_login_command");
|
||||
const sessionExists = await checkSession();
|
||||
if (sessionExists) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
} else {
|
||||
const sessionExists = true;
|
||||
alert("Please open the desktop app to login");
|
||||
if (sessionExists) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Login failed:", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
} else if (step < totalSteps) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
if (step > 1) setStep(step - 1);
|
||||
};
|
||||
|
||||
// Progress bar rendering
|
||||
const renderProgress = () => (
|
||||
<div className="flex items-center justify-center gap-2 mb-2">
|
||||
{[...Array(totalSteps)].map((_, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className={`h-1.5 rounded transition-all duration-300 w-16 ${
|
||||
idx < step ? "bg-primary" : "bg-white/30"
|
||||
}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
// Step content rendering
|
||||
const renderStepContent = () => {
|
||||
switch (step) {
|
||||
case 1:
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full">
|
||||
<h2 className="text-3xl font-bold mb-2 text-center">
|
||||
Welcome to ArtCraft
|
||||
</h2>
|
||||
<p className="text-white/70 mb-6 text-center">
|
||||
Here's what you can do...
|
||||
</p>
|
||||
<div className="grid grid-cols-2 gap-6 h-full grow">
|
||||
<div className="h-full">
|
||||
<div className="aspect-[4/3] w-full overflow-hidden bg-black/20 rounded-t-lg">
|
||||
<video
|
||||
className="object-cover w-full h-full"
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
controls={false}
|
||||
>
|
||||
<source src={videoSrc2D} type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
<p className="text-center px-1.5 py-2 text-white/90 bg-black/20 rounded-b-lg font-medium text-sm">
|
||||
2D Canvas
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div className="aspect-[4/3] w-full overflow-hidden bg-black/20 rounded-t-lg">
|
||||
<video
|
||||
className="object-cover w-full h-full"
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
controls={false}
|
||||
>
|
||||
<source src={videoSrc3D} type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
<p className="text-center px-1.5 py-2 text-white/90 bg-black/20 rounded-b-lg font-medium text-sm">
|
||||
3D Scene Editor
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
case 2:
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full">
|
||||
<h2 className="text-3xl font-bold mb-2 text-center">
|
||||
Login with your OpenAI account
|
||||
</h2>
|
||||
<p className="text-white/70 mb-6 text-center px-16">
|
||||
We're the application layer for images and video. To provide you
|
||||
with <b>100% free service</b>, we use your existing AI accounts.
|
||||
To start off, you'll need to add your OpenAI Sora account. If you
|
||||
have a ChatGPT subscription, you can log in with Sora.
|
||||
</p>
|
||||
<img
|
||||
src={openAiLogo}
|
||||
alt="OpenAI Logo"
|
||||
className="w-72 h-72 mx-auto grow"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
case 3:
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full">
|
||||
<h2 className="text-3xl font-bold mb-2 text-center">
|
||||
Thank you for signing in!
|
||||
</h2>
|
||||
<p className="text-white/70 mb-6 text-center px-24">
|
||||
You're all set to start creating amazing content. Join our Discord
|
||||
community to connect with other creators, share your work, and get
|
||||
the latest updates.
|
||||
</p>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() =>
|
||||
window.open("https://discord.gg/75svZP2Vje", "_blank")
|
||||
}
|
||||
icon={faDiscord}
|
||||
className="text-md bg-[#5865F2] hover:bg-[#6a76ff] rounded-xl"
|
||||
>
|
||||
Join our Discord
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return createPortal(
|
||||
<Transition appear show={isOpen}>
|
||||
<div className="fixed inset-0 z-[100]">
|
||||
<TransitionChild
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 cursor-pointer bg-black/60" />
|
||||
</TransitionChild>
|
||||
<div className="fixed inset-0 flex items-center justify-center p-4">
|
||||
<TransitionChild
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 scale-95"
|
||||
enterTo="opacity-100 scale-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100 scale-100"
|
||||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
<div
|
||||
className="relative h-[660px] max-w-4xl w-full rounded-xl bg-[#2C2C2C] text-white shadow-lg border border-white/5"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex flex-col gap-4 p-8 h-full">
|
||||
<span className="text-sm text-center opacity-60 font-medium">
|
||||
Step {step} of {totalSteps}
|
||||
</span>
|
||||
{renderProgress()}
|
||||
{renderStepContent()}
|
||||
<div className="flex items-end justify-center gap-2.5 mt-10 grow">
|
||||
{step > 1 && step !== 3 ? (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={handleBack}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
) : null}
|
||||
{step < totalSteps ? (
|
||||
<Button
|
||||
icon={step === 2 ? faRightToBracket : faArrowRight}
|
||||
iconFlip={step !== 2}
|
||||
onClick={handleNext}
|
||||
loading={isLoading}
|
||||
disabled={isLoading}
|
||||
>
|
||||
{step === 2 ? "Login with OpenAI" : "Continue"}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
icon={faArrowRight}
|
||||
iconFlip={true}
|
||||
onClick={handleClose}
|
||||
>
|
||||
Start Creating Now
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TransitionChild>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>,
|
||||
document.body
|
||||
);
|
||||
}
|
||||
|
||||
export default LoginModal;
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../../tsconfig.base.json"
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"types": [
|
||||
"node",
|
||||
"@nx/react/typings/cssmodule.d.ts",
|
||||
"@nx/react/typings/image.d.ts",
|
||||
"vite/client"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"jsx": "react-jsx",
|
||||
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
|
||||
},
|
||||
"exclude": [
|
||||
"out-tsc",
|
||||
"dist",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.test.jsx",
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.jsx",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/vitest",
|
||||
"types": [
|
||||
"vitest/globals",
|
||||
"vitest/importMeta",
|
||||
"vite/client",
|
||||
"node",
|
||||
"vitest"
|
||||
],
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import * as path from 'path';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
root: __dirname,
|
||||
cacheDir: '../../../node_modules/.vite/libs/components/login-modal',
|
||||
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
// Configuration for building your library.
|
||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||
build: {
|
||||
outDir: './dist',
|
||||
emptyOutDir: true,
|
||||
reportCompressedSize: true,
|
||||
commonjsOptions: {
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
lib: {
|
||||
// Could also be a dictionary or array of multiple entry points.
|
||||
entry: 'src/index.ts',
|
||||
name: '@storyteller/ui-login-modal',
|
||||
fileName: 'index',
|
||||
// Change this to the formats you want to support.
|
||||
// Don't forget to update your package.json as well.
|
||||
formats: ['es' as const]
|
||||
},
|
||||
rollupOptions: {
|
||||
// External packages that should not be bundled into your library.
|
||||
external: ['react','react-dom','react/jsx-runtime']
|
||||
},
|
||||
},
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './test-output/vitest/coverage',
|
||||
provider: 'v8' as const,
|
||||
}
|
||||
},
|
||||
}));
|
||||
@@ -2,27 +2,21 @@
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "../modal"
|
||||
},
|
||||
{
|
||||
"path": "../select"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "../input"
|
||||
},
|
||||
{
|
||||
"path": "../button"
|
||||
},
|
||||
{
|
||||
"path": "../modal"
|
||||
},
|
||||
{
|
||||
"path": "../../api"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-utils"
|
||||
},
|
||||
{
|
||||
"path": "../../soundboard"
|
||||
},
|
||||
|
||||
@@ -43,29 +43,23 @@
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../modal/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../select/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../input/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../button/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../modal/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../api/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-utils/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../soundboard/tsconfig.lib.json"
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Generated
+8
@@ -2215,6 +2215,10 @@
|
||||
"name": "@storyteller/ui-loading-spinner",
|
||||
"version": "0.0.1"
|
||||
},
|
||||
"libs/components/login-modal": {
|
||||
"name": "@storyteller/ui-login-modal",
|
||||
"version": "0.0.1"
|
||||
},
|
||||
"libs/components/modal": {
|
||||
"name": "@storyteller/ui-modal",
|
||||
"version": "0.0.1"
|
||||
@@ -10320,6 +10324,10 @@
|
||||
"resolved": "libs/components/loading-spinner",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@storyteller/ui-login-modal": {
|
||||
"resolved": "libs/components/login-modal",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@storyteller/ui-modal": {
|
||||
"resolved": "libs/components/modal",
|
||||
"link": true
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
},
|
||||
{
|
||||
"path": "./libs/tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "./libs/components/login-modal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user