diff --git a/comty.js b/comty.js
index 94c8d738..fe5cb1a9 160000
--- a/comty.js
+++ b/comty.js
@@ -1 +1 @@
-Subproject commit 94c8d7383e84a2de4b193d27adfcb1baa4163f68
+Subproject commit fe5cb1a9a275444abd7307bbd8a4e7c68221369b
diff --git a/packages/app/config/defaultTheme.json b/packages/app/config/defaultTheme.json
index ccfdfa75..62a76546 100755
--- a/packages/app/config/defaultTheme.json
+++ b/packages/app/config/defaultTheme.json
@@ -1,76 +1,78 @@
{
- "defaultVars": {
- "fontScale": "1",
- "backgroundBlur": "10px",
- "colorPrimary": "#ff6064",
- "app-color": "#ff6064",
- "danger-color": "#ff6064",
- "backgroundColorTransparency": "0.8",
- "backgroundImage": "",
- "fontFamily": "'Noto Sans', sans-serif",
- "layoutMargin": "unset",
- "layoutPadding": "20px 20px 20px 20px",
- "borderRadius": "8px",
- "text-color-white": "#d2d2d2",
- "text-color-black": "#000000",
- "page-transition-duration": "150ms",
- "backgroundSize": "cover",
- "backgroundPosition": "center",
- "backgroundRepeat": "no-repeat",
- "backgroundAttachment": "fixed",
- "top-bar-height": "52px",
- "bottom-bar-height": "80px",
- "compact-mode": false
- },
- "defaultVariant": "dark",
- "variants": {
- "light": {
- "bg_color_1": "255, 255, 255",
- "bg_color_2": "200, 200, 200",
- "bg_color_3": "150, 150, 150",
- "bg_color_4": "100, 100, 100",
- "bg_color_5": "45, 45, 45",
- "bg_color_6": "0, 0, 0",
- "text-color": "var(--text-color-black)",
- "svg-color": "var(--text-color)",
- "disabled-color": "#d2d2d2",
- "layoutBackgroundColor": "255, 255, 255",
- "layout-background-contrast": "38, 38, 38",
- "background-color-primary": "#ffffff",
- "background-color-primary-2": "#f0f0f0",
- "shadow-color": "#4b4b4b7c",
- "background-color-accent-values": "240, 242, 245",
- "background-color-accent": "#f0f2f5",
- "background-color-contrast": "#4b4b4b",
- "border-color": "rgba(75, 75, 75, 0.2)",
- "sidebar-background-color": "var(--background-color-accent)",
- "sidedrawer-background-color": "var(--background-color-accent)"
- },
- "dark": {
- "bg_color_1": "38, 38, 38",
- "bg_color_2": "65, 65, 65",
- "bg_color_3": "90, 90, 90",
- "bg_color_4": "115, 115, 115",
- "bg_color_5": "140, 140, 140",
- "bg_color_6": "165, 165, 165",
- "text-color": "var(--text-color-white)",
- "svg-color": "var(--text-color)",
- "disabled-color": "#4b4b4b",
- "shadow-color": "#1010107c",
- "layoutBackgroundColor": "38, 38, 38",
- "layout-background-contrast": "255, 255, 255",
- "background-color-primary": "#262626",
- "background-color-primary-2": "#2c2c2c",
- "background-color-accent-values": "53, 53, 53",
- "background-color-accent": "#353535",
- "background-color-contrast": "#ffffff",
- "background_disabled": "#0A0A0A",
- "border-color": "rgba(170, 170, 170, 0.2)",
- "header-text-color": "#d2d2d2",
- "button-background-color": "var(--colorPrimary)",
- "button-text-color": "var(--background-color-contrast)",
- "sidebar-background-color": "var(--background-color-accent)",
- "sidedrawer-background-color": "var(--background-color-accent)"
- }
- }
-}
\ No newline at end of file
+ "defaultVars": {
+ "fontScale": "1",
+ "backgroundBlur": "10px",
+ "colorPrimary": "#ff6064",
+ "app-color": "#ff6064",
+ "danger-color": "#ff6064",
+ "backgroundColorTransparency": "0.8",
+ "backgroundImage": "",
+ "fontFamily": "'Noto Sans', sans-serif",
+ "layoutMargin": "unset",
+ "layoutPadding": "20px 20px 20px 20px",
+ "borderRadius": "8px",
+ "text-color-white": "#d2d2d2",
+ "text-color-black": "#000000",
+ "page-transition-duration": "150ms",
+ "backgroundSize": "cover",
+ "backgroundPosition": "center",
+ "backgroundRepeat": "no-repeat",
+ "backgroundAttachment": "fixed",
+ "top-bar-height": "52px",
+ "bottom-bar-height": "80px",
+ "compact-mode": false
+ },
+ "defaultVariant": "dark",
+ "variants": {
+ "light": {
+ "bg_color_1": "255, 255, 255",
+ "bg_color_2": "200, 200, 200",
+ "bg_color_3": "150, 150, 150",
+ "bg_color_4": "100, 100, 100",
+ "bg_color_5": "45, 45, 45",
+ "bg_color_6": "0, 0, 0",
+ "text-color": "var(--text-color-black)",
+ "svg-color": "var(--text-color)",
+ "disabled-color": "#d2d2d2",
+ "layoutBackgroundColor": "255, 255, 255",
+ "layout-background-contrast": "38, 38, 38",
+ "background-color-primary": "#ffffff",
+ "background-color-primary-2": "#f0f0f0",
+ "shadow-color": "#4b4b4b7c",
+ "background-color-accent-values": "240, 242, 245",
+ "background-color-accent": "#f0f2f5",
+ "background-color-contrast": "#4b4b4b",
+ "border-color": "rgba(75, 75, 75, 0.2)",
+ "border-color-solid": "#b3b3b3",
+ "sidebar-background-color": "var(--background-color-accent)",
+ "sidedrawer-background-color": "var(--background-color-accent)"
+ },
+ "dark": {
+ "bg_color_1": "38, 38, 38",
+ "bg_color_2": "65, 65, 65",
+ "bg_color_3": "90, 90, 90",
+ "bg_color_4": "115, 115, 115",
+ "bg_color_5": "140, 140, 140",
+ "bg_color_6": "165, 165, 165",
+ "text-color": "var(--text-color-white)",
+ "svg-color": "var(--text-color)",
+ "disabled-color": "#4b4b4b",
+ "shadow-color": "#1010107c",
+ "layoutBackgroundColor": "38, 38, 38",
+ "layout-background-contrast": "255, 255, 255",
+ "background-color-primary": "#262626",
+ "background-color-primary-2": "#2c2c2c",
+ "background-color-accent-values": "53, 53, 53",
+ "background-color-accent": "#353535",
+ "background-color-contrast": "#ffffff",
+ "background_disabled": "#0A0A0A",
+ "border-color": "rgba(170, 170, 170, 0.2)",
+ "border-color-solid": "#4c4c4c",
+ "header-text-color": "#d2d2d2",
+ "button-background-color": "var(--colorPrimary)",
+ "button-text-color": "var(--background-color-contrast)",
+ "sidebar-background-color": "var(--background-color-accent)",
+ "sidedrawer-background-color": "var(--background-color-accent)"
+ }
+ }
+}
diff --git a/packages/app/eslint.config.js b/packages/app/eslint.config.js
new file mode 100644
index 00000000..e52a61a5
--- /dev/null
+++ b/packages/app/eslint.config.js
@@ -0,0 +1,17 @@
+import js from "@eslint/js"
+import globals from "globals"
+import pluginReact from "eslint-plugin-react"
+import { defineConfig } from "eslint/config"
+
+export default defineConfig([
+ {
+ files: ["**/*.{js,mjs,cjs,jsx}"],
+ plugins: { js },
+ extends: ["js/recommended"],
+ },
+ {
+ files: ["**/*.{js,mjs,cjs,jsx}"],
+ languageOptions: { globals: globals.browser },
+ },
+ pluginReact.configs.flat.recommended,
+])
diff --git a/packages/app/package.json b/packages/app/package.json
index fe225cb5..6ad6d9a2 100755
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -1,6 +1,6 @@
{
"name": "@comty/app",
- "version": "1.41.0@alpha",
+ "version": "1.42.0@alpha",
"license": "ComtyLicense",
"main": "electron/main",
"type": "module",
@@ -11,7 +11,8 @@
"build": "vite build",
"preview": "vite preview",
"release": "node ./scripts/release.js",
- "postinstall": "./scripts/postinstall.sh"
+ "postinstall": "./scripts/postinstall.sh",
+ "eslint": "eslint"
},
"dependencies": {
"@ant-design/icons": "^5.4.0",
@@ -33,7 +34,7 @@
"axios": "^1.7.7",
"bear-react-carousel": "^4.0.10-alpha.0",
"classnames": "2.3.1",
- "comty.js": "^0.65.5",
+ "comty.js": "^0.66.0",
"d3": "^7.9.0",
"dashjs": "^5.0.0",
"dompurify": "^3.0.0",
@@ -79,9 +80,13 @@
"vite": "^6.2.6"
},
"devDependencies": {
+ "@eslint/js": "^9.26.0",
"@octokit/rest": "^21.1.1",
"7zip-min": "1.4.3",
"dotenv": "16.0.3",
- "form-data": "^4.0.0"
+ "eslint": "^9.26.0",
+ "eslint-plugin-react": "^7.37.5",
+ "form-data": "^4.0.0",
+ "globals": "^16.1.0"
}
}
diff --git a/packages/app/src/classes/ChunkedUpload/index.js b/packages/app/src/classes/ChunkedUpload/index.js
deleted file mode 100644
index 22cc95cb..00000000
--- a/packages/app/src/classes/ChunkedUpload/index.js
+++ /dev/null
@@ -1,237 +0,0 @@
-import { EventBus } from "@ragestudio/vessel"
-
-export default class ChunkedUpload {
- constructor(params) {
- const {
- endpoint,
- file,
- headers = {},
- splitChunkSize = 1024 * 1024 * 10,
- maxRetries = 3,
- delayBeforeRetry = 5,
- } = params
-
- if (!endpoint) {
- throw new Error("Missing endpoint")
- }
-
- if ((!file) instanceof File) {
- throw new Error("Invalid or missing file")
- }
-
- if (typeof headers !== "object") {
- throw new Error("Invalid headers")
- }
-
- if (splitChunkSize <= 0) {
- throw new Error("Invalid splitChunkSize")
- }
-
- this.chunkCount = 0
- this.retriesCount = 0
-
- this.splitChunkSize = splitChunkSize
- this.totalChunks = Math.ceil(file.size / splitChunkSize)
-
- this.maxRetries = maxRetries
- this.delayBeforeRetry = delayBeforeRetry
- this.offline = this.paused = false
-
- this.endpoint = endpoint
- this.file = file
- this.headers = {
- ...headers,
- "uploader-original-name": encodeURIComponent(file.name),
- "uploader-file-id": this.getFileUID(file),
- "uploader-chunks-total": this.totalChunks,
- "chunk-size": splitChunkSize,
- "cache-control": "no-cache",
- connection: "keep-alive",
- }
-
- this.setupListeners()
- this.nextSend()
-
- console.debug("[Uploader] Created", {
- splitChunkSize: splitChunkSize,
- totalChunks: this.totalChunks,
- totalSize: file.size,
- fileName: file.name,
- fileType: file.type,
- })
- }
-
- _reader = new FileReader()
- events = new EventBus()
-
- setupListeners() {
- window.addEventListener(
- "online",
- () =>
- !this.offline &&
- ((this.offline = false),
- this.events.emit("online"),
- this.nextSend()),
- )
- window.addEventListener(
- "offline",
- () => ((this.offline = true), this.events.emit("offline")),
- )
- }
-
- getFileUID(file) {
- return (
- Math.floor(Math.random() * 100000000) +
- Date.now() +
- file.size +
- "_tmp"
- )
- }
-
- loadChunk() {
- return new Promise((resolve) => {
- const start = this.chunkCount * this.splitChunkSize
- const end = Math.min(start + this.splitChunkSize, this.file.size)
-
- this._reader.onload = () => {
- resolve(
- new Blob([this._reader.result], {
- type: "application/octet-stream",
- }),
- )
- }
- this._reader.readAsArrayBuffer(this.file.slice(start, end))
- })
- }
-
- async sendChunk() {
- console.log(`[UPLOADER] Sending chunk ${this.chunkCount}`, {
- currentChunk: this.chunkCount,
- totalChunks: this.totalChunks,
- chunk: this.chunk,
- })
-
- try {
- const res = await fetch(this.endpoint, {
- method: "POST",
- headers: {
- ...this.headers,
- "uploader-chunk-number": this.chunkCount,
- },
- body: this.chunk,
- })
-
- return res
- } catch (error) {
- this.manageRetries()
- }
- }
-
- manageRetries() {
- if (++this.retriesCount < this.maxRetries) {
- setTimeout(() => this.nextSend(), this.delayBeforeRetry * 1000)
-
- this.events.emit("fileRetry", {
- message: `Retrying chunk ${this.chunkCount}`,
- chunk: this.chunkCount,
- retriesLeft: this.retries - this.retriesCount,
- })
- } else {
- this.events.emit("error", {
- message: `No more retries for chunk ${this.chunkCount}`,
- })
- }
- }
-
- async nextSend() {
- if (this.paused || this.offline) {
- return null
- }
-
- this.chunk = await this.loadChunk()
-
- try {
- const res = await this.sendChunk()
-
- if (![200, 201, 204].includes(res.status)) {
- // failed!!
- return this.manageRetries()
- }
-
- const data = await res.json()
-
- console.log(`[UPLOADER] Chunk ${this.chunkCount} sent`)
-
- this.chunkCount = this.chunkCount + 1
-
- if (this.chunkCount < this.totalChunks) {
- this.nextSend()
- }
-
- // check if is the last chunk, if so, handle sse events
- if (this.chunkCount === this.totalChunks) {
- if (data.sseChannelId || data.sseUrl) {
- this.waitOnSSE(data)
- } else {
- this.events.emit("finish", data)
- }
- }
-
- this.events.emit("progress", {
- percent: Math.round((100 / this.totalChunks) * this.chunkCount),
- state: "Uploading",
- })
- } catch (error) {
- this.events.emit("error", error)
- }
- }
-
- togglePause() {
- this.paused = !this.paused
-
- if (!this.paused) {
- return this.nextSend()
- }
- }
-
- waitOnSSE(data) {
- // temporal solution until comty.js manages this
- const url = `${app.cores.api.client().mainOrigin}/upload/sse_events/${data.sseChannelId}`
-
- console.log(`[UPLOADER] Connecting to SSE channel >`, url)
- const eventSource = new EventSource(url)
-
- eventSource.onerror = (error) => {
- this.events.emit("error", error)
- eventSource.close()
- }
-
- eventSource.onopen = () => {
- console.log(`[UPLOADER] SSE channel opened`)
- }
-
- eventSource.onmessage = (event) => {
- // parse json
- const messageData = JSON.parse(event.data)
-
- console.log(`[UPLOADER] SSE Event >`, messageData)
-
- if (messageData.event === "done") {
- this.events.emit("finish", messageData.result)
- eventSource.close()
- }
-
- if (messageData.event === "error") {
- this.events.emit("error", messageData.result)
- eventSource.close()
- }
-
- if (messageData.state) {
- this.events.emit("progress", {
- percent: messageData.percent,
- state: messageData.state,
- })
- }
- }
- }
-}
diff --git a/packages/app/src/components/MusicStudio/ReleaseEditor/tabs/Tracks/index.jsx b/packages/app/src/components/MusicStudio/ReleaseEditor/tabs/Tracks/index.jsx
index 4f36d67b..14c2c29d 100644
--- a/packages/app/src/components/MusicStudio/ReleaseEditor/tabs/Tracks/index.jsx
+++ b/packages/app/src/components/MusicStudio/ReleaseEditor/tabs/Tracks/index.jsx
@@ -1,9 +1,10 @@
import React from "react"
import * as antd from "antd"
-import classnames from "classnames"
-import { DragDropContext, Droppable } from "react-beautiful-dnd"
import { createSwapy } from "swapy"
+import queuedUploadFile from "@utils/queuedUploadFile"
+import FilesModel from "@models/files"
+
import TrackManifest from "@cores/player/classes/TrackManifest"
import { Icons } from "@components/Icons"
@@ -209,14 +210,14 @@ class TracksManager extends React.Component {
console.log(
`[${trackManifest.uid}] Founded cover, uploading...`,
)
+
const coverFile = new File(
[trackManifest._coverBlob],
"cover.jpg",
{ type: trackManifest._coverBlob.type },
)
- const coverUpload =
- await app.cores.remoteStorage.uploadFile(coverFile)
+ const coverUpload = await FilesModel.upload(coverFile)
trackManifest.cover = coverUpload.url
}
@@ -243,25 +244,16 @@ class TracksManager extends React.Component {
}
uploadToStorage = async (req) => {
- const response = await app.cores.remoteStorage
- .uploadFile(req.file, {
- onProgress: this.handleTrackFileUploadProgress,
- headers: {
- transformations: "a-dash",
- },
- })
- .catch((error) => {
- console.error(error)
- antd.message.error(error)
-
- req.onError(error)
-
- return false
- })
-
- if (response) {
- req.onSuccess(response)
- }
+ await queuedUploadFile(req.file, {
+ onFinish: (file, response) => {
+ req.onSuccess(response)
+ },
+ onError: req.onError,
+ onProgress: this.handleTrackFileUploadProgress,
+ headers: {
+ transformations: "a-dash",
+ },
+ })
}
handleTrackFileUploadProgress = async (file, progress) => {
diff --git a/packages/app/src/components/PostCreator/index.jsx b/packages/app/src/components/PostCreator/index.jsx
index 89ca7b61..ba44a55e 100755
--- a/packages/app/src/components/PostCreator/index.jsx
+++ b/packages/app/src/components/PostCreator/index.jsx
@@ -10,6 +10,7 @@ import { Icons } from "@components/Icons"
import Poll from "@components/Poll"
import clipboardEventFileToFile from "@utils/clipboardEventFileToFile"
+import queuedUploadFile from "@utils/queuedUploadFile"
import PostModel from "@models/post"
import SearchModel from "@models/search"
@@ -195,22 +196,14 @@ export default class PostCreator extends React.Component {
uploadFile = async (req) => {
this.toggleUploaderVisibility(false)
- const request = await app.cores.remoteStorage
- .uploadFile(req.file)
- .catch((error) => {
- console.error(error)
- antd.message.error(error)
-
- req.onError(error)
-
- return false
- })
-
- if (request) {
- console.log(`Upload done >`, request)
-
- return req.onSuccess(request)
- }
+ await queuedUploadFile(req.file, {
+ onFinish: (file, response) => {
+ req.onSuccess(response)
+ },
+ onError: (file, response) => {
+ req.onError(response)
+ },
+ })
}
removeAttachment = (file_uid) => {
diff --git a/packages/app/src/components/UploadButton/index.jsx b/packages/app/src/components/UploadButton/index.jsx
index 90ca59e4..2fee6122 100755
--- a/packages/app/src/components/UploadButton/index.jsx
+++ b/packages/app/src/components/UploadButton/index.jsx
@@ -1,12 +1,13 @@
import React from "react"
import { Upload, Progress } from "antd"
import classnames from "classnames"
+import queuedUploadFile from "@utils/queuedUploadFile"
import { Icons } from "@components/Icons"
import "./index.less"
-export default (props) => {
+const UploadButton = (props) => {
const [uploading, setUploading] = React.useState(false)
const [progress, setProgress] = React.useState(null)
@@ -40,17 +41,7 @@ export default (props) => {
handleOnStart(req.file.uid, req.file)
- await app.cores.remoteStorage.uploadFile(req.file, {
- headers: props.headers,
- onProgress: (file, progress) => {
- setProgress(progress)
- handleOnProgress(file.uid, progress)
- },
- onError: (file, error) => {
- setProgress(null)
- handleOnError(file.uid, error)
- setUploading(false)
- },
+ await queuedUploadFile(req.file, {
onFinish: (file, response) => {
if (typeof props.ctx?.onUpdateItem === "function") {
props.ctx.onUpdateItem(response.url)
@@ -67,6 +58,16 @@ export default (props) => {
setProgress(null)
}, 1000)
},
+ onError: (file, error) => {
+ setProgress(null)
+ handleOnError(file.uid, error)
+ setUploading(false)
+ },
+ onProgress: (file, progress) => {
+ setProgress(progress)
+ handleOnProgress(file.uid, progress)
+ },
+ headers: props.headers,
})
}
@@ -106,3 +107,5 @@ export default (props) => {
)
}
+
+export default UploadButton
diff --git a/packages/app/src/cores/remoteStorage/remoteStorage.core.js b/packages/app/src/cores/remoteStorage/remoteStorage.core.js
deleted file mode 100755
index 3cca026c..00000000
--- a/packages/app/src/cores/remoteStorage/remoteStorage.core.js
+++ /dev/null
@@ -1,117 +0,0 @@
-import { Core } from "@ragestudio/vessel"
-
-import ChunkedUpload from "@classes/ChunkedUpload"
-import SessionModel from "@models/session"
-
-export default class RemoteStorage extends Core {
- static namespace = "remoteStorage"
- static depends = ["api", "tasksQueue"]
-
- public = {
- uploadFile: this.uploadFile,
- getFileHash: this.getFileHash,
- binaryArrayToFile: this.binaryArrayToFile,
- }
-
- binaryArrayToFile(bin, filename) {
- const { format, data } = bin
-
- const filenameExt = format.split("/")[1]
- filename = `${filename}.${filenameExt}`
-
- const byteArray = new Uint8Array(data)
- const blob = new Blob([byteArray], { type: data.type })
-
- return new File([blob], filename, {
- type: format,
- })
- }
-
- async getFileHash(file) {
- const buffer = await file.arrayBuffer()
- const hash = await crypto.subtle.digest("SHA-256", buffer)
- const hashArray = Array.from(new Uint8Array(hash))
- const hashHex = hashArray
- .map((b) => b.toString(16).padStart(2, "0"))
- .join("")
-
- return hashHex
- }
-
- async uploadFile(
- file,
- {
- onProgress = () => {},
- onFinish = () => {},
- onError = () => {},
- service = "standard",
- headers = {},
- } = {},
- ) {
- return await new Promise((_resolve, _reject) => {
- const fn = async () =>
- new Promise((resolve, reject) => {
- const uploader = new ChunkedUpload({
- endpoint: `${app.cores.api.client().mainOrigin}/upload/chunk`,
- splitChunkSize: 5 * 1024 * 1024,
- file: file,
- service: service,
- headers: {
- ...headers,
- "provider-type": service,
- Authorization: `Bearer ${SessionModel.token}`,
- },
- })
-
- uploader.events.on("error", ({ message }) => {
- this.console.error("[Uploader] Error", message)
-
- app.cores.notifications.new(
- {
- title: "Could not upload file",
- description: message,
- },
- {
- type: "error",
- },
- )
-
- if (typeof onError === "function") {
- onError(file, message)
- }
-
- reject(message)
- _reject(message)
- })
-
- uploader.events.on("progress", (data) => {
- if (typeof onProgress === "function") {
- onProgress(file, data)
- }
- })
-
- uploader.events.on("finish", (data) => {
- this.console.debug("[Uploader] Finish", data)
-
- app.cores.notifications.new(
- {
- title: "File uploaded",
- },
- {
- type: "success",
- },
- )
-
- if (typeof onFinish === "function") {
- onFinish(file, data)
- }
-
- resolve(data)
- _resolve(data)
- })
- })
-
- app.cores.tasksQueue.appendToQueue(`upload_${file.name}`, fn)
- })
- }
-}
diff --git a/packages/app/src/cores/sync/sync.core.js b/packages/app/src/cores/sync/sync.core.js
deleted file mode 100755
index 5ed2b0ac..00000000
--- a/packages/app/src/cores/sync/sync.core.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { Core } from "@ragestudio/vessel"
-import SyncModel from "comty.js/models/sync"
-
-export default class SyncCore extends Core {
- static namespace = "sync"
- static dependencies = ["api", "settings"]
-
- activeLinkedServices = {}
-
- services = {
-
- }
-
- public = {
- getActiveLinkedServices: function () {
- return this.activeLinkedServices
- }.bind(this),
- services: this.services,
- }
-
- events = {
- "app.initialization.start": async () => {
- const activeServices = await SyncModel.getLinkedServices().catch((error) => {
- this.console.error(error)
- return null
- })
-
- if (activeServices) {
- this.console.log(`Active services`, activeServices)
- this.activeLinkedServices = activeServices
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/app/src/cores/tasksQueue/tasksQueue.core.js b/packages/app/src/cores/tasksQueue/tasksQueue.core.js
index 4327ad25..99241c87 100755
--- a/packages/app/src/cores/tasksQueue/tasksQueue.core.js
+++ b/packages/app/src/cores/tasksQueue/tasksQueue.core.js
@@ -2,90 +2,95 @@ import { Core } from "@ragestudio/vessel"
import { Observable } from "object-observer"
export default class TasksQueue extends Core {
- static depends = ["settings"]
+ static depends = ["settings"]
- static namespace = "tasksQueue"
+ static namespace = "tasksQueue"
- static get maxRunningTasks() {
- return app.cores.settings.get("tasks.maxRunningTasks") ?? 3
- }
+ static get maxRunningTasks() {
+ return app.cores.settings.get("tasks.maxRunningTasks") ?? 3
+ }
- public = {
- appendToQueue: this.appendToQueue.bind(this),
- processTasks: this.processTasks.bind(this),
- }
+ public = {
+ appendToQueue: this.appendToQueue.bind(this),
+ processTasks: this.processTasks.bind(this),
+ }
- taskQueue = Observable.from([])
+ taskQueue = Observable.from([])
- runningTasksIds = Observable.from([])
+ runningTasksIds = Observable.from([])
- processTasks() {
- if (this.runningTasksIds.length >= TasksQueue.maxRunningTasks ?? 1) {
- this.console.log("We are already running the maximum number of tasks")
- return false
- }
+ processTasks() {
+ if (this.runningTasksIds.length >= TasksQueue.maxRunningTasks ?? 1) {
+ this.console.log(
+ "We are already running the maximum number of tasks",
+ )
+ return false
+ }
- // check if there are new tasks in the queue and move them to the tasks array with the maximum number of tasks can be run
- if (this.taskQueue.length === 0) {
- this.console.log("No tasks in the queue")
- return false
- }
+ // check if there are new tasks in the queue and move them to the tasks array with the maximum number of tasks can be run
+ if (this.taskQueue.length === 0) {
+ this.console.log("No tasks in the queue")
+ return false
+ }
- let tasks = this.taskQueue.splice(0, TasksQueue.maxRunningTasks ?? 1)
+ let tasks = this.taskQueue.splice(0, TasksQueue.maxRunningTasks ?? 1)
- tasks = tasks.filter((task) => task)
+ tasks = tasks.filter((task) => task)
- const promises = tasks.map(async (task) => {
- if (typeof task.fn !== "function") {
- throw new Error("Task must be a function")
- }
+ const promises = tasks.map(async (task) => {
+ if (typeof task.fn !== "function") {
+ throw new Error("Task must be a function")
+ }
- if (typeof task.id === "undefined") {
- throw new Error("Task id is required")
- }
+ if (typeof task.id === "undefined") {
+ throw new Error("Task id is required")
+ }
- // add the task to the running tasks array
- this.runningTasksIds.push(task.id)
+ // add the task to the running tasks array
+ this.runningTasksIds.push(task.id)
- const taskResult = await task.fn()
- .catch((error) => {
- // delete the task from the running tasks array
- this.runningTasksIds = this.runningTasksIds.filter((runningTaskId) => runningTaskId !== task.id)
+ const taskResult = await task.fn().catch((error) => {
+ // delete the task from the running tasks array
+ this.runningTasksIds = this.runningTasksIds.filter(
+ (runningTaskId) => runningTaskId !== task.id,
+ )
- // propagate the error through an exception
- throw error
- })
+ // propagate the error through an exception
+ throw error
+ })
- // delete the task from the running tasks array
- this.runningTasksIds = this.runningTasksIds.filter((runningTaskId) => runningTaskId !== task.id)
+ // delete the task from the running tasks array
+ this.runningTasksIds = this.runningTasksIds.filter(
+ (runningTaskId) => runningTaskId !== task.id,
+ )
- return taskResult
- })
+ return taskResult
+ })
- Promise.all(promises)
- .then((res) => {
- this.processTasks()
- })
- .catch((error) => {
- this.console.error(error)
- this.processTasks()
- })
- }
+ Promise.all(promises)
+ .then((res) => {
+ this.processTasks()
+ })
+ .catch((error) => {
+ this.console.error(error)
+ this.processTasks()
+ })
+ }
- appendToQueue(taskId, task) {
- if (!taskId) {
- throw new Error("Task id is required")
- }
+ appendToQueue(taskId, task) {
+ if (!taskId) {
+ throw new Error("Task id is required")
+ }
- if (Array.isArray(task)) {
- throw new Error("Task must be a function")
- }
+ if (Array.isArray(task)) {
+ throw new Error("Task must be a function")
+ }
- this.taskQueue.unshift({
- id: taskId,
- fn: task,
- })
+ this.taskQueue.unshift({
+ id: taskId,
+ fn: task,
+ })
- this.processTasks()
- }
-}
\ No newline at end of file
+ this.processTasks()
+ }
+}
diff --git a/packages/app/src/pages/auth/index.jsx b/packages/app/src/pages/auth/index.jsx
index 6efef997..e1e23e50 100755
--- a/packages/app/src/pages/auth/index.jsx
+++ b/packages/app/src/pages/auth/index.jsx
@@ -54,9 +54,9 @@ const AuthPage = (props) => {