diff --git a/packages/core/src/handlers/checkUpdate.js b/packages/core/src/handlers/checkUpdate.js new file mode 100644 index 0000000..48fe56b --- /dev/null +++ b/packages/core/src/handlers/checkUpdate.js @@ -0,0 +1,43 @@ +import Logger from "../logger" +import DB from "../db" + +import softRead from "./read" + +const Log = Logger.child({ service: "CHECK_UPDATE" }) + +export default async function checkUpdate(pkg_id) { + const pkg = await DB.getPackages(pkg_id) + + if (!pkg) { + Log.error("Package not found") + return false + } + + Log.info(`Checking update for [${pkg_id}]`) + + const remoteSoftManifest = await softRead(pkg.remote_manifest, { + soft: true + }) + + if (!remoteSoftManifest) { + Log.error("Cannot read remote manifest") + return false + } + + if (pkg.version === remoteSoftManifest.version) { + Log.info("No update available") + return false + } + + Log.info("Update available") + Log.info("Local:", pkg.version) + Log.info("Remote:", remoteSoftManifest.version) + Log.info("Changelog:", remoteSoftManifest.changelog_url) + + return { + id: pkg.id, + local: pkg.version, + remote: remoteSoftManifest.version, + changelog: remoteSoftManifest.changelog_url, + } +} \ No newline at end of file diff --git a/packages/core/src/helpers/setup.js b/packages/core/src/helpers/setup.js index 0058dcc..826c4c6 100644 --- a/packages/core/src/helpers/setup.js +++ b/packages/core/src/helpers/setup.js @@ -92,7 +92,9 @@ export default async () => { } ) } catch (error) { - await fs.promises.rm(prerequisite.destination) + if (fs.existsSync(prerequisite.destination)) { + await fs.promises.rm(prerequisite.destination) + } throw error } @@ -153,6 +155,12 @@ export default async () => { if (Array.isArray(prerequisite.moveDirs)) { for (const dir of prerequisite.moveDirs) { + if (Array.isArray(dir.requireOs)) { + if (!dir.requireOs.includes(resolveOs())) { + continue + } + } + Log.info(`Moving ${dir.from} to ${dir.to}...`) global._relic_eventBus.emit("app:setup", { @@ -182,9 +190,10 @@ export default async () => { message: error.message, }) - Log.error(error) Log.error("Aborting setup due to an error...") - return false + Log.error(error) + + throw error } Log.info(`All prerequisites are ready!`) diff --git a/packages/core/src/index.js b/packages/core/src/index.js index 841c1f7..de39263 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -17,6 +17,7 @@ import PackageApply from "./handlers/apply" import PackageList from "./handlers/list" import PackageRead from "./handlers/read" import PackageAuthorize from "./handlers/authorize" +import PackageCheckUpdate from "./handlers/checkUpdate" export default class RelicCore { constructor(params) { @@ -27,6 +28,8 @@ export default class RelicCore { logger = Logger + db = DB + async initialize() { await DB.initialize() @@ -52,6 +55,7 @@ export default class RelicCore { list: PackageList, read: PackageRead, authorize: PackageAuthorize, + checkUpdate: PackageCheckUpdate } openPath(pkg_id) { diff --git a/packages/core/src/prerequisites.js b/packages/core/src/prerequisites.js index b2f357d..9fb7df7 100644 --- a/packages/core/src/prerequisites.js +++ b/packages/core/src/prerequisites.js @@ -26,7 +26,7 @@ export default [ { id: "rclone-bin", finalBin: Vars.rclone_bin, - url: resolveRemoteBinPath(`${baseURL}/rclone-bin`, "rclone-bin.zip"), + url: resolveRemoteBinPath(`${baseURL}/rclone`, "rclone-bin.zip"), destination: path.resolve(Vars.binaries_path, "rclone-bin.zip"), extract: path.resolve(Vars.binaries_path, "rclone-bin"), requireOs: ["win32"], @@ -58,6 +58,7 @@ export default [ extractTargetFromName: true, moveDirs: [ { + requireOs: ["macos"], from: path.resolve(Vars.binaries_path, "java_jre_bin", "zulu-22.jre", "Contents"), to: path.resolve(Vars.binaries_path, "java_jre_bin", "Contents"), deleteParentBefore: true diff --git a/packages/gui/src/main/index.js b/packages/gui/src/main/index.js index c21f305..5184c4a 100644 --- a/packages/gui/src/main/index.js +++ b/packages/gui/src/main/index.js @@ -3,7 +3,7 @@ global.SettingsStore = new Store({ watch: true, }) -import RelicCore from "@ragestudio/relic-core/src" +import RelicCore from "../../../core/src" import CoreAdapter from "./classes/CoreAdapter" import sendToRender from "./utils/sendToRender" @@ -63,7 +63,16 @@ class ElectronApp { "pkg:uninstall": async (event, pkg_id) => { return await this.core.package.uninstall(pkg_id) }, - "pkg:execute": async (event, pkg_id) => { + "pkg:execute": async (event, pkg_id, { force = false } = {}) => { + // check for updates first + if (!force) { + const update = await this.core.package.checkUpdate(pkg_id) + + if (update) { + return sendToRender("pkg:update_available", update) + } + } + return await this.core.package.execute(pkg_id) }, "pkg:open": async (event, pkg_id) => { @@ -93,18 +102,22 @@ class ElectronApp { try { await this.core.initialize() await this.core.setup() - } catch (err) { - console.error(err) - sendToRender("new:notification", { - message: "Setup failed", - description: err.message + return { + pkg: pkg, + authorizedServices: {} + } + } catch (error) { + console.error(error) + + sendToRender("app:init:failed", { + message: "Initalization failed", + error: error, }) - } - return { - pkg: pkg, - authorizedServices: {} + return { + error + } } } } diff --git a/packages/gui/src/renderer/assets/bruh_fox.jpg b/packages/gui/src/renderer/assets/bruh_fox.jpg new file mode 100644 index 0000000..bc3399e Binary files /dev/null and b/packages/gui/src/renderer/assets/bruh_fox.jpg differ diff --git a/packages/gui/src/renderer/src/App.jsx b/packages/gui/src/renderer/src/App.jsx index 995491d..3323cb8 100644 --- a/packages/gui/src/renderer/src/App.jsx +++ b/packages/gui/src/renderer/src/App.jsx @@ -59,7 +59,9 @@ class App extends React.Component { } this.setState({ - updateAvailable: true, + appUpdate: { + available: true, + }, }) app.appUpdateAvailable(data) @@ -79,15 +81,23 @@ class App extends React.Component { app.pkgUpdateAvailable(data) }, "pkg:installation:invoked": (event, data) => { - if (this.state.initializing) { - return false - } + if (this.state.initializing) { + return false + } - app.invokeInstall(data) + app.invokeInstall(data) + }, + "app:init:failed": (event, data) => { + this.setState({ + crash: data, + }) } } componentDidMount = async () => { + console.log(`React version > ${versions["react"]}`) + console.log(`DOMRouter version > ${versions["react-router-dom"]}`) + window.app.style.appendClassname("initializing") for (const event in this.ipcEvents) { @@ -96,10 +106,12 @@ class App extends React.Component { const mainInitialization = await ipc.exec("app:init") - console.log(`React version > ${versions["react"]}`) - console.log(`DOMRouter version > ${versions["react-router-dom"]}`) console.log(`app:init() | Result >`, mainInitialization) + if (mainInitialization.error) { + return false + } + await this.setState({ initializing: false, pkg: mainInitialization.pkg, diff --git a/packages/gui/src/renderer/src/GlobalApp.jsx b/packages/gui/src/renderer/src/GlobalApp.jsx index 432d170..4a50a20 100644 --- a/packages/gui/src/renderer/src/GlobalApp.jsx +++ b/packages/gui/src/renderer/src/GlobalApp.jsx @@ -29,12 +29,6 @@ class GlobalStyleController { export default class GlobalCTXApp { static style = GlobalStyleController - static applyUpdate = () => { - message.loading("Updating, please wait...") - - ipc.exec("updater:apply") - } - static invokeInstall = (manifest) => { console.log(`installation invoked >`, manifest) @@ -80,6 +74,12 @@ export default class GlobalCTXApp { }) } + static applyUpdate = () => { + message.loading("Updating, please wait...") + + ipc.exec("updater:apply") + } + static checkUpdates = () => { ipc.exec("updater:check") } diff --git a/packages/gui/src/renderer/src/components/Crash/index.jsx b/packages/gui/src/renderer/src/components/Crash/index.jsx new file mode 100644 index 0000000..dfad2bc --- /dev/null +++ b/packages/gui/src/renderer/src/components/Crash/index.jsx @@ -0,0 +1,27 @@ +import React from "react" +import "./index.less" + +const Crash = (props) => { + const { crash } = props + + return
+
+ +
+ +

Crash

+

The application has encontered a critical error that cannot handle it, so must be terminated.

+ +
+

Detailed error:

+ + + {JSON.stringify(crash, null, 2)} + +
+
+} + +export default Crash \ No newline at end of file diff --git a/packages/gui/src/renderer/src/components/Crash/index.less b/packages/gui/src/renderer/src/components/Crash/index.less new file mode 100644 index 0000000..54aa325 --- /dev/null +++ b/packages/gui/src/renderer/src/components/Crash/index.less @@ -0,0 +1,56 @@ +.app-crash { + display: flex; + flex-direction: column; + + height: 100%; + + gap: 20px; + + h1 { + font-size: 1.5rem; + font-weight: bold; + } + + .crash-icon { + display: flex; + flex-direction: row; + + justify-content: center; + align-items: center; + + width: 100%; + + img { + width: 200px; + height: 200px; + + object-fit: contain; + + border-radius: 12px; + } + } + + .crash-details { + display: flex; + flex-direction: column; + + width: 100%; + + gap: 7px; + + code { + background-color: var(--background-color-secondary); + + padding: 10px; + + border-radius: 12px; + + font-family: "DM Mono", monospace; + + font-size: 0.8rem; + + word-break: break-all; + white-space: pre-wrap; + } + } +} \ No newline at end of file diff --git a/packages/gui/src/renderer/src/components/PackageUpdateAvailable/index.jsx b/packages/gui/src/renderer/src/components/PackageUpdateAvailable/index.jsx index 03c9e15..99a6eb9 100644 --- a/packages/gui/src/renderer/src/components/PackageUpdateAvailable/index.jsx +++ b/packages/gui/src/renderer/src/components/PackageUpdateAvailable/index.jsx @@ -16,7 +16,7 @@ const PackageUpdateAvailable = ({ update, close }) => { } function handleUpdate() { - ipc.exec("pkg:update", update.manifest.id, { + ipc.exec("pkg:update", update.id, { execOnFinish: true }) @@ -24,7 +24,7 @@ const PackageUpdateAvailable = ({ update, close }) => { } function handleContinue() { - ipc.exec("pkg:execute", update.manifest.id, { + ipc.exec("pkg:execute", update.id, { force: true }) @@ -38,7 +38,7 @@ const PackageUpdateAvailable = ({ update, close }) => {

- {update.current_version} {`->`} {update.new_version} + {update.local} {`->`} {update.remote}

diff --git a/packages/gui/src/renderer/src/components/Splash/index.jsx b/packages/gui/src/renderer/src/components/Splash/index.jsx index d0fa2cc..5ab9e95 100644 --- a/packages/gui/src/renderer/src/components/Splash/index.jsx +++ b/packages/gui/src/renderer/src/components/Splash/index.jsx @@ -22,11 +22,13 @@ const Splash = (props) => { { globalState.appSetup.message && <> +
{globalState.appSetup.message}
+
{ } { - ctx.updateAvailable && } onClick={app.applyUpdate} type="primary" > - Update now + Update app } diff --git a/packages/gui/src/renderer/src/router.jsx b/packages/gui/src/renderer/src/router.jsx index 599c16e..33c696b 100644 --- a/packages/gui/src/renderer/src/router.jsx +++ b/packages/gui/src/renderer/src/router.jsx @@ -7,6 +7,7 @@ import loadable from "@loadable/component" import GlobalStateContext from "contexts/global" import SplashScreen from "components/Splash" +import CrashError from "components/Crash" const DefaultNotFoundRender = () => { return
Not found
@@ -130,6 +131,18 @@ export const InternalRouter = (props) => { } export const PageRender = (props) => { + const globalState = React.useContext(GlobalStateContext) + + if (globalState.crash) { + return + } + + if (globalState.initializing) { + return + } + const routes = React.useMemo(() => { let paths = { ...import.meta.glob("/src/pages/**/[a-z[]*.jsx"), @@ -154,12 +167,6 @@ export const PageRender = (props) => { return paths }, []) - const globalState = React.useContext(GlobalStateContext) - - if (globalState.initializing) { - return - } - return { routes.map((route, index) => { diff --git a/packages/gui/src/renderer/src/style/index.less b/packages/gui/src/renderer/src/style/index.less index bf6bd32..b53479d 100644 --- a/packages/gui/src/renderer/src/style/index.less +++ b/packages/gui/src/renderer/src/style/index.less @@ -15,6 +15,19 @@ --app_global_padding: @var-app_global_padding; } +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + opacity: 0; +} + +::-webkit-scrollbar-thumb { + background-color: rgba(255, 255, 255, 0.1); + border-radius: 10px; +} + html, body { padding: 0;