mirror of
https://github.com/Gabi-Zar/Silk-Fly-Launcher.git
synced 2026-04-17 05:26:04 +02:00
Add welcome page and clean a bit
This commit is contained in:
53
main.js
53
main.js
@@ -9,6 +9,7 @@ const Nexus = require('@nexusmods/nexus-api').default;
|
|||||||
|
|
||||||
const store = new Store();
|
const store = new Store();
|
||||||
const userSavePath = app.getPath('userData')
|
const userSavePath = app.getPath('userData')
|
||||||
|
const dataPath = `${userSavePath}\\config.json`
|
||||||
let silksongPath = store.get('silksong-path')
|
let silksongPath = store.get('silksong-path')
|
||||||
let nexusAPI = store.get('nexus-api')
|
let nexusAPI = store.get('nexus-api')
|
||||||
let nexus = undefined
|
let nexus = undefined
|
||||||
@@ -29,7 +30,7 @@ let bepinexBackupVersion
|
|||||||
|
|
||||||
let mainWindow
|
let mainWindow
|
||||||
|
|
||||||
const createWindow = () => {
|
async function createWindow() {
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
width: 1280,
|
width: 1280,
|
||||||
height: 720,
|
height: 720,
|
||||||
@@ -38,7 +39,14 @@ const createWindow = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
mainWindow.loadFile('renderer/index.html')
|
if(await fileExists(dataPath)) {
|
||||||
|
htmlFile = "renderer/index.html"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
htmlFile = "renderer/welcome.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
mainWindow.loadFile(htmlFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
@@ -58,11 +66,15 @@ app.on('window-all-closed', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('save-path', (event, path) => {
|
ipcMain.handle('save-path', (event, path) => {
|
||||||
|
saveSilksongPath(path)
|
||||||
|
});
|
||||||
|
|
||||||
|
function saveSilksongPath(path) {
|
||||||
silksongPath = path;
|
silksongPath = path;
|
||||||
bepinexFolderPath = `${silksongPath}/BepInEx`
|
bepinexFolderPath = `${silksongPath}/BepInEx`
|
||||||
bepinexBackupPath = `${silksongPath}/BepInEx-Backup`
|
bepinexBackupPath = `${silksongPath}/BepInEx-Backup`
|
||||||
store.set('silksong-path', silksongPath);
|
store.set('silksong-path', silksongPath);
|
||||||
});
|
}
|
||||||
|
|
||||||
ipcMain.handle('load-path', () => {
|
ipcMain.handle('load-path', () => {
|
||||||
silksongPath = store.get('silksong-path');
|
silksongPath = store.get('silksong-path');
|
||||||
@@ -127,17 +139,11 @@ ipcMain.handle('file-exists', async (_, filePath) => {
|
|||||||
return await fileExists(filePath);
|
return await fileExists(filePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('get-userSavePath', () => {
|
ipcMain.handle('delete-data', async () => {
|
||||||
return userSavePath
|
await fs.unlink(dataPath)
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.handle('delete-data', async (event, path) => {
|
|
||||||
await fs.unlink(path)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('export-data', async () => {
|
ipcMain.handle('export-data', async () => {
|
||||||
const dataPath = `${userSavePath}\\config.json`
|
|
||||||
|
|
||||||
const { canceled, filePath } = await dialog.showSaveDialog({
|
const { canceled, filePath } = await dialog.showSaveDialog({
|
||||||
title: 'Export Data',
|
title: 'Export Data',
|
||||||
defaultPath: 'config.json',
|
defaultPath: 'config.json',
|
||||||
@@ -152,20 +158,19 @@ ipcMain.handle('export-data', async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('import-data', async () => {
|
ipcMain.handle('import-data', async () => {
|
||||||
const dataPath = `${userSavePath}\\config.json`
|
|
||||||
|
|
||||||
const { canceled, filePaths } = await dialog.showOpenDialog({
|
const { canceled, filePaths } = await dialog.showOpenDialog({
|
||||||
title: 'Import Data',
|
title: 'Import Data',
|
||||||
properties: ['openFile'],
|
properties: ['openFile'],
|
||||||
filters: [{ name: 'JSON', extensions: ['json'] }]
|
filters: [{ name: 'JSON', extensions: ['json'] }]
|
||||||
})
|
})
|
||||||
|
|
||||||
if (canceled || !filePaths) return
|
if (canceled || !filePaths) return false
|
||||||
|
|
||||||
if(await fileExists(dataPath)) {
|
if(await fileExists(dataPath)) {
|
||||||
await fs.unlink(dataPath)
|
await fs.unlink(dataPath)
|
||||||
}
|
}
|
||||||
await fs.copyFile(filePaths[0], dataPath,fs.constants.COPYFILE_EXCL)
|
await fs.copyFile(filePaths[0], dataPath,fs.constants.COPYFILE_EXCL)
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('open-link', async (event, link) => {
|
ipcMain.handle('open-link', async (event, link) => {
|
||||||
@@ -360,3 +365,23 @@ ipcMain.handle('download-mod', async (event, link) => {
|
|||||||
|
|
||||||
nexusWindow.loadURL(link)
|
nexusWindow.loadURL(link)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('auto-detect-game-path', async () => {
|
||||||
|
const defaultsSilksongPaths = [
|
||||||
|
":/Program Files (x86)/Steam/steamapps/common/Hollow Knight Silksong",
|
||||||
|
":/SteamLibrary/steamapps/common/Hollow Knight Silksong"
|
||||||
|
]
|
||||||
|
for (const path of defaultsSilksongPaths) {
|
||||||
|
for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) {
|
||||||
|
const fullPath = `${String.fromCharCode(i)}${path}`
|
||||||
|
if (await fileExists(fullPath)) {
|
||||||
|
saveSilksongPath(fullPath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('load-main-page', () => {
|
||||||
|
mainWindow.loadFile("renderer/index.html")
|
||||||
|
})
|
||||||
@@ -8,11 +8,11 @@ contextBridge.exposeInMainWorld('versions', {
|
|||||||
|
|
||||||
contextBridge.exposeInMainWorld('files', {
|
contextBridge.exposeInMainWorld('files', {
|
||||||
fileExists: (path) => ipcRenderer.invoke('file-exists', path),
|
fileExists: (path) => ipcRenderer.invoke('file-exists', path),
|
||||||
userSavePath: () => ipcRenderer.invoke('get-userSavePath'),
|
delete: () => ipcRenderer.invoke('delete-data'),
|
||||||
delete: (path) => ipcRenderer.invoke('delete-data', path),
|
|
||||||
export: () => ipcRenderer.invoke('export-data'),
|
export: () => ipcRenderer.invoke('export-data'),
|
||||||
import: () => ipcRenderer.invoke('import-data'),
|
import: () => ipcRenderer.invoke('import-data'),
|
||||||
|
|
||||||
|
autoDetectGamePath: () => ipcRenderer.invoke('auto-detect-game-path'),
|
||||||
saveSilksongPath: (path) => ipcRenderer.invoke('save-path', path),
|
saveSilksongPath: (path) => ipcRenderer.invoke('save-path', path),
|
||||||
loadSilksongPath: () => ipcRenderer.invoke('load-path'),
|
loadSilksongPath: () => ipcRenderer.invoke('load-path'),
|
||||||
loadBepinexVersion: () => ipcRenderer.invoke('load-bepinex-version'),
|
loadBepinexVersion: () => ipcRenderer.invoke('load-bepinex-version'),
|
||||||
@@ -23,7 +23,8 @@ contextBridge.exposeInMainWorld('files', {
|
|||||||
|
|
||||||
contextBridge.exposeInMainWorld('electronAPI', {
|
contextBridge.exposeInMainWorld('electronAPI', {
|
||||||
openExternalLink: (url) => ipcRenderer.invoke('open-link', url),
|
openExternalLink: (url) => ipcRenderer.invoke('open-link', url),
|
||||||
launchGame: (mode) => ipcRenderer.invoke('launch-game', mode)
|
launchGame: (mode) => ipcRenderer.invoke('launch-game', mode),
|
||||||
|
loadMainPage: () => ipcRenderer.invoke('load-main-page')
|
||||||
});
|
});
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('bepinex', {
|
contextBridge.exposeInMainWorld('bepinex', {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="fr">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>Silk Fly Launcher</title>
|
<title>Silk Fly Launcher</title>
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
<h1 id="title">Home</h1>
|
<h1 id="title">Home</h1>
|
||||||
<div class="view" id="view">
|
<div class="view" id="view">
|
||||||
</div>
|
</div>
|
||||||
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Template -->
|
<!-- Template -->
|
||||||
|
|||||||
@@ -11,16 +11,6 @@ const versionText = HomeTemplate.content.getElementById("version-text");
|
|||||||
|
|
||||||
navigate("home")
|
navigate("home")
|
||||||
|
|
||||||
let savePath
|
|
||||||
files.userSavePath().then(path => {
|
|
||||||
savePath = `${path}\\config.json`
|
|
||||||
files.fileExists(savePath).then(result => {
|
|
||||||
if(!result) {
|
|
||||||
autoDetectGamePath()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
async function navigate(page) {
|
async function navigate(page) {
|
||||||
view.replaceChildren()
|
view.replaceChildren()
|
||||||
switch (page) {
|
switch (page) {
|
||||||
@@ -138,27 +128,16 @@ async function launch(mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function autoDetectGamePath() {
|
async function autoDetectGamePath() {
|
||||||
const defaultsSilksongPaths = [
|
await files.autoDetectGamePath()
|
||||||
":/Program Files (x86)/Steam/steamapps/common/Hollow Knight Silksong",
|
if (document.getElementById("silksong-path-input")) {
|
||||||
":/SteamLibrary/steamapps/common/Hollow Knight Silksong"
|
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
|
||||||
]
|
|
||||||
for (const path of defaultsSilksongPaths) {
|
|
||||||
for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) {
|
|
||||||
const fullPath = `${String.fromCharCode(i)}${path}`
|
|
||||||
if (await files.fileExists(fullPath)) {
|
|
||||||
await files.saveSilksongPath(fullPath)
|
|
||||||
if (document.getElementById("silksong-path-input")) {
|
|
||||||
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteData() {
|
async function deleteData() {
|
||||||
await files.delete(savePath)
|
await files.delete()
|
||||||
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
|
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
|
||||||
|
document.getElementById("nexus-api-input").value = await files.loadNexusAPI()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function exportData() {
|
async function exportData() {
|
||||||
@@ -168,6 +147,7 @@ async function exportData() {
|
|||||||
async function importData() {
|
async function importData() {
|
||||||
await files.import()
|
await files.import()
|
||||||
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
|
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
|
||||||
|
document.getElementById("nexus-api-input").value = await files.loadNexusAPI()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function installBepinex() {
|
async function installBepinex() {
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ body {
|
|||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content h2 {
|
.content h2 {
|
||||||
@@ -199,6 +201,13 @@ body {
|
|||||||
border-color: rgba(255, 25, 0, 0.8);
|
border-color: rgba(255, 25, 0, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bigger-button {
|
||||||
|
width: 240px;
|
||||||
|
height: 80px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
.search-container {
|
.search-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
@@ -305,3 +314,12 @@ body {
|
|||||||
height: 32px;
|
height: 32px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: #ffffff;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link:hover {
|
||||||
|
color: #ff6b6b;
|
||||||
|
}
|
||||||
25
renderer/welcome.css
Normal file
25
renderer/welcome.css
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
.welcome-div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
font-size: 60px;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
color: #ffffff;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-div {
|
||||||
|
display: flex;
|
||||||
|
flex: 2;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 8px;
|
||||||
|
gap: 40px;
|
||||||
|
}
|
||||||
70
renderer/welcome.html
Normal file
70
renderer/welcome.html
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Welcome to Silk Fly Launcher</title>
|
||||||
|
<link rel="stylesheet" href="welcome.css" />
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="app">
|
||||||
|
<video autoplay muted loop id="menu_wallpaper" class="background_video">
|
||||||
|
<source src="assets/background.mp4" type="video/mp4">
|
||||||
|
</video>
|
||||||
|
|
||||||
|
<div class="welcome-div" id="main-div">
|
||||||
|
<br>
|
||||||
|
<div id="page">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-div" id="button-div">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template id="welcome-template">
|
||||||
|
<h1 class="title">Welcome to Silk Fly Launcher</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="one-button-template">
|
||||||
|
<button class="default-button bigger-button" onclick="importData()">Import Data</button>
|
||||||
|
<button class="default-button bigger-button" onclick="next()">Next →</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="two-button-template">
|
||||||
|
<button class="default-button bigger-button" onclick="back()">← Back</button>
|
||||||
|
<button class="default-button bigger-button" onclick="next()">Next →</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="path-template">
|
||||||
|
<h1 class="title">Enter Hollow Knight: Silksong path</h1>
|
||||||
|
<p>Please verify the path to your game and edit it if the auto detection didn't work</p>
|
||||||
|
<div class="horizontal-div">
|
||||||
|
<label for="silksong-path-label">Enter Silksong path: </label>
|
||||||
|
<input type="text" class="input" id="silksong-path-input" name="silksong-path-input">
|
||||||
|
<button class="default-button" onclick="autoDetectGamePath()">Auto Detect</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="nexus-template">
|
||||||
|
<h1 class="title">Enter your nexus API key</h1>
|
||||||
|
<p>Please enter your nexus API key. To get your API key go to <a href="https://www.nexusmods.com/settings/api-keys" class="link" id="external-link">https://www.nexusmods.com/settings/api-keys</a> and click on new personnal API key</p>
|
||||||
|
<div class="horizontal-div">
|
||||||
|
<label for="nexus-api-label">Enter your nexus api: </label>
|
||||||
|
<input type="text" class="input" id="nexus-api-input" name="nexus-api-input">
|
||||||
|
<img class="nexus-check-image" id="nexus-check-image" src="assets/cross.svg">
|
||||||
|
<button class="default-button" onclick="verifyNexusAPI()">Verify</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="style-template">
|
||||||
|
<h1 class="title">Chose the theme of the app</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="tutorial-template">
|
||||||
|
<h1 class="title">Tutorial to download mod from nexus</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="welcome.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
112
renderer/welcome.js
Normal file
112
renderer/welcome.js
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
let actualPage = 0
|
||||||
|
|
||||||
|
const pageDiv = document.getElementById("page");
|
||||||
|
const buttonDiv = document.getElementById("button-div");
|
||||||
|
|
||||||
|
const oneButtonTemplate = document.getElementById("one-button-template");
|
||||||
|
const twoButtonTemplate = document.getElementById("two-button-template");
|
||||||
|
|
||||||
|
const welcomeTemplate = document.getElementById("welcome-template");
|
||||||
|
const silksongPathTemplate = document.getElementById("path-template");
|
||||||
|
const nexusTemplate = document.getElementById("nexus-template");
|
||||||
|
const styleTemplate = document.getElementById("style-template");
|
||||||
|
const tutorialTemplate = document.getElementById("tutorial-template");
|
||||||
|
|
||||||
|
navigate()
|
||||||
|
|
||||||
|
async function navigate() {
|
||||||
|
pageDiv.replaceChildren()
|
||||||
|
switch (actualPage) {
|
||||||
|
case 0:
|
||||||
|
pageDiv.appendChild(welcomeTemplate.content.cloneNode(true))
|
||||||
|
buttonDiv.replaceChildren()
|
||||||
|
buttonDiv.appendChild(oneButtonTemplate.content.cloneNode(true))
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
pageDiv.appendChild(silksongPathTemplate.content.cloneNode(true))
|
||||||
|
buttonDiv.replaceChildren()
|
||||||
|
buttonDiv.appendChild(twoButtonTemplate.content.cloneNode(true))
|
||||||
|
|
||||||
|
const silksongPathInput = document.getElementById("silksong-path-input")
|
||||||
|
if (await files.loadSilksongPath() == "") {
|
||||||
|
autoDetectGamePath()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
|
||||||
|
}
|
||||||
|
|
||||||
|
silksongPathInput.addEventListener('input', async function(event) {
|
||||||
|
let silksongPath = silksongPathInput.value
|
||||||
|
await files.saveSilksongPath(silksongPath)
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
pageDiv.appendChild(nexusTemplate.content.cloneNode(true))
|
||||||
|
const nexusLink = document.getElementById("external-link")
|
||||||
|
nexusLink.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const url = nexusLink.href
|
||||||
|
electronAPI.openExternalLink(url)
|
||||||
|
})
|
||||||
|
|
||||||
|
const nexusAPIInput = document.getElementById("nexus-api-input")
|
||||||
|
nexusAPIInput.value = await files.loadNexusAPI()
|
||||||
|
nexusAPIInput.addEventListener('input', async function(event) {
|
||||||
|
let nexusAPI = nexusAPIInput.value
|
||||||
|
await files.saveNexusAPI(nexusAPI)
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
pageDiv.appendChild(styleTemplate.content.cloneNode(true))
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
pageDiv.appendChild(tutorialTemplate.content.cloneNode(true))
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
electronAPI.loadMainPage()
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
actualPage++
|
||||||
|
navigate()
|
||||||
|
}
|
||||||
|
|
||||||
|
function back() {
|
||||||
|
actualPage--
|
||||||
|
navigate()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function autoDetectGamePath() {
|
||||||
|
await files.autoDetectGamePath()
|
||||||
|
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function verifyNexusAPI() {
|
||||||
|
response = await nexus.verifyAPI()
|
||||||
|
|
||||||
|
const nexusCheckImage = document.getElementById("nexus-check-image")
|
||||||
|
if (nexusCheckImage == undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
nexusCheckImage.src = "assets/check.svg"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nexusCheckImage.src = "assets/cross.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function importData() {
|
||||||
|
const res = await files.import()
|
||||||
|
if (res) {
|
||||||
|
electronAPI.loadMainPage()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user