update deps

This commit is contained in:
SrGooglo 2025-02-05 02:47:13 +00:00
parent d50ba06a55
commit 5d4c25c413
2 changed files with 272 additions and 242 deletions

View File

@ -1,89 +1,90 @@
{ {
"name": "@comty/web-app", "name": "@comty/web-app",
"version": "1.0.0-beta", "version": "1.0.0-beta",
"license": "ComtyLicense", "license": "ComtyLicense",
"main": "electron/main", "main": "electron/main",
"author": "RageStudio", "author": "RageStudio",
"description": "A prototype of a social network.", "description": "A prototype of a social network.",
"scripts": { "scripts": {
"build": "vite build", "build": "vite build",
"dev": "vite", "dev": "vite",
"docker-compose:update_run": "docker-compose down && git pull && yarn build && docker-compose up -d --build", "docker-compose:update_run": "docker-compose down && git pull && yarn build && docker-compose up -d --build",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.4.0", "@ant-design/icons": "^5.4.0",
"@capacitor/android": "^5.0.5", "@capacitor/android": "^5.0.5",
"@capacitor/app": "^5.0.3", "@capacitor/app": "^5.0.3",
"@capacitor/assets": "^2.0.4", "@capacitor/assets": "^2.0.4",
"@capacitor/cli": "^5.0.5", "@capacitor/cli": "^5.0.5",
"@capacitor/core": "^5.0.5", "@capacitor/core": "^5.0.5",
"@capacitor/haptics": "1.1.4", "@capacitor/haptics": "1.1.4",
"@capacitor/splash-screen": "^5.0.4", "@capacitor/splash-screen": "^5.0.4",
"@capacitor/status-bar": "^5.0.4", "@capacitor/status-bar": "^5.0.4",
"@capacitor/storage": "^1.2.5", "@capacitor/storage": "^1.2.5",
"@capgo/capacitor-updater": "^5.0.1", "@capgo/capacitor-updater": "^5.0.1",
"@dnd-kit/core": "^6.0.8", "@dnd-kit/core": "^6.0.8",
"@dnd-kit/sortable": "^7.0.2", "@dnd-kit/sortable": "^7.0.2",
"@emotion/react": "^11.13.0", "@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0", "@emotion/styled": "^11.13.0",
"@ffmpeg/ffmpeg": "^0.12.10", "@ffmpeg/ffmpeg": "^0.12.10",
"@ffmpeg/util": "^0.12.1", "@ffmpeg/util": "^0.12.1",
"@loadable/component": "5.15.2", "@loadable/component": "5.15.2",
"@mui/material": "^5.11.9", "@mui/material": "^5.11.9",
"@ragestudio/cordova-nfc": "^1.2.0", "@ragestudio/cordova-nfc": "^1.2.0",
"@ragestudio/vessel": "^0.18.1", "@ragestudio/vessel": "^0.18.1",
"@sentry/browser": "^7.64.0", "@sentry/browser": "^7.64.0",
"@tauri-apps/api": "^1.5.4", "@tauri-apps/api": "^1.5.4",
"@tsmx/human-readable": "^1.0.7", "@tsmx/human-readable": "^1.0.7",
"antd": "^5.20.6", "antd": "^5.20.6",
"axios": "^1.7.7", "axios": "^1.7.7",
"bear-react-carousel": "^4.0.10-alpha.0", "bear-react-carousel": "^4.0.10-alpha.0",
"capacitor-music-controls-plugin-v3": "^1.1.0", "capacitor-music-controls-plugin-v3": "^1.1.0",
"classnames": "2.3.1", "classnames": "2.3.1",
"dompurify": "^3.0.0", "dashjs": "^4.7.4",
"fast-average-color": "^9.2.0", "dompurify": "^3.0.0",
"framer-motion": "^10.12.17", "fast-average-color": "^9.2.0",
"fuse.js": "6.5.3", "framer-motion": "^10.12.17",
"hls.js": "^1.5.17", "fuse.js": "6.5.3",
"howler": "2.2.3", "hls.js": "^1.5.17",
"i18next": "21.6.6", "howler": "2.2.3",
"js-cookie": "3.0.1", "i18next": "21.6.6",
"jsmediatags": "^3.9.7", "js-cookie": "3.0.1",
"less": "4.1.2", "jsmediatags": "^3.9.7",
"lottie-react": "^2.4.0", "less": "4.1.2",
"luxon": "^3.0.4", "lottie-react": "^2.4.0",
"million": "^2.6.4", "luxon": "^3.0.4",
"mime": "^3.0.0", "million": "^2.6.4",
"moment": "2.29.4", "mime": "^3.0.0",
"mpegts.js": "^1.6.10", "moment": "2.29.4",
"nprogress": "^0.2.0", "mpegts.js": "^1.6.10",
"plyr": "^3.6.12", "nprogress": "^0.2.0",
"plyr-react": "^3.2.1", "plyr": "^3.6.12",
"prop-types": "^15.8.1", "plyr-react": "^3.2.1",
"react": "^18.2.0", "prop-types": "^15.8.1",
"react-beautiful-dnd": "^13.1.1", "react": "^18.2.0",
"react-color": "2.19.3", "react-beautiful-dnd": "^13.1.1",
"react-countup": "^6.4.1", "react-color": "2.19.3",
"react-dom": "18.2.0", "react-countup": "^6.4.1",
"react-fast-marquee": "^1.3.5", "react-dom": "18.2.0",
"react-helmet": "6.1.0", "react-fast-marquee": "^1.3.5",
"react-i18next": "11.15.3", "react-helmet": "6.1.0",
"react-icons": "^4.8.0", "react-i18next": "11.15.3",
"react-lazy-load-image-component": "^1.5.4", "react-icons": "^4.8.0",
"react-markdown": "^8.0.3", "react-lazy-load-image-component": "^1.5.4",
"react-modal-image": "^2.6.0", "react-markdown": "^8.0.3",
"react-motion": "0.5.2", "react-modal-image": "^2.6.0",
"react-rnd": "10.3.5", "react-motion": "0.5.2",
"react-router-dom": "^6.26.2", "react-rnd": "10.3.5",
"react-transition-group": "^4.4.5", "react-router-dom": "^6.26.2",
"react-useanimations": "^2.10.0", "react-transition-group": "^4.4.5",
"realtime-bpm-analyzer": "^3.2.1", "react-useanimations": "^2.10.0",
"remark-gfm": "^3.0.1", "realtime-bpm-analyzer": "^3.2.1",
"rxjs": "^7.5.5", "remark-gfm": "^3.0.1",
"store": "^2.0.12", "rxjs": "^7.5.5",
"ua-parser-js": "^1.0.36", "store": "^2.0.12",
"vaul": "^0.9.2", "ua-parser-js": "^1.0.36",
"vite": "^5.4.4" "vaul": "^0.9.2",
} "vite": "^5.4.4"
}
} }

View File

@ -1,201 +1,230 @@
import { EventBus } from "@ragestudio/vessel" import { EventBus } from "@ragestudio/vessel"
import { events, stream } from "fetch-event-stream"
export default class ChunkedUpload { export default class ChunkedUpload {
constructor(params) { constructor(params) {
const { const {
endpoint, endpoint,
file, file,
headers = {}, headers = {},
splitChunkSize = 1024 * 1024 * 10, splitChunkSize = 1024 * 1024 * 10,
maxRetries = 3, maxRetries = 3,
delayBeforeRetry = 5, delayBeforeRetry = 5,
} = params } = params
if (!endpoint) { if (!endpoint) {
throw new Error("Missing endpoint") throw new Error("Missing endpoint")
} }
if (!file instanceof File) { if ((!file) instanceof File) {
throw new Error("Invalid or missing file") throw new Error("Invalid or missing file")
} }
if (typeof headers !== "object") { if (typeof headers !== "object") {
throw new Error("Invalid headers") throw new Error("Invalid headers")
} }
if (splitChunkSize <= 0) { if (splitChunkSize <= 0) {
throw new Error("Invalid splitChunkSize") throw new Error("Invalid splitChunkSize")
} }
this.chunkCount = 0 this.chunkCount = 0
this.retriesCount = 0 this.retriesCount = 0
this.splitChunkSize = splitChunkSize this.splitChunkSize = splitChunkSize
this.totalChunks = Math.ceil(file.size / splitChunkSize) this.totalChunks = Math.ceil(file.size / splitChunkSize)
this.maxRetries = maxRetries this.maxRetries = maxRetries
this.delayBeforeRetry = delayBeforeRetry this.delayBeforeRetry = delayBeforeRetry
this.offline = this.paused = false this.offline = this.paused = false
this.endpoint = endpoint this.endpoint = endpoint
this.file = file this.file = file
this.headers = { this.headers = {
...headers, ...headers,
"uploader-original-name": encodeURIComponent(file.name), "uploader-original-name": encodeURIComponent(file.name),
"uploader-file-id": this.getFileUID(file), "uploader-file-id": this.getFileUID(file),
"uploader-chunks-total": this.totalChunks, "uploader-chunks-total": this.totalChunks,
"chunk-size": splitChunkSize, "chunk-size": splitChunkSize,
"Connection": "keep-alive", Connection: "keep-alive",
"Cache-Control": "no-cache" "Cache-Control": "no-cache",
} }
this.setupListeners() this.setupListeners()
this.nextSend() this.nextSend()
console.debug("[Uploader] Created", { console.debug("[Uploader] Created", {
splitChunkSize: splitChunkSize, splitChunkSize: splitChunkSize,
totalChunks: this.totalChunks, totalChunks: this.totalChunks,
totalSize: file.size totalSize: file.size,
}) })
} }
_reader = new FileReader() _reader = new FileReader()
events = new EventBus() events = new EventBus()
setupListeners() { setupListeners() {
window.addEventListener("online", () => !this.offline && (this.offline = false, this.events.emit("online"), this.nextSend())) window.addEventListener(
window.addEventListener("offline", () => (this.offline = true, this.events.emit("offline"))) "online",
} () =>
!this.offline &&
((this.offline = false),
this.events.emit("online"),
this.nextSend()),
)
window.addEventListener(
"offline",
() => ((this.offline = true), this.events.emit("offline")),
)
}
getFileUID(file) { getFileUID(file) {
return Math.floor(Math.random() * 100000000) + Date.now() + file.size + "_tmp" return (
} Math.floor(Math.random() * 100000000) +
Date.now() +
file.size +
"_tmp"
)
}
loadChunk() { loadChunk() {
return new Promise((resolve) => { return new Promise((resolve) => {
const start = this.chunkCount * this.splitChunkSize const start = this.chunkCount * this.splitChunkSize
const end = Math.min(start + this.splitChunkSize, this.file.size) 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.onload = () =>
this._reader.readAsArrayBuffer(this.file.slice(start, end)) resolve(
}) new Blob([this._reader.result], {
} type: "application/octet-stream",
}),
)
this._reader.readAsArrayBuffer(this.file.slice(start, end))
})
}
async sendChunk() { async sendChunk() {
const form = new FormData() const form = new FormData()
form.append("file", this.chunk) form.append("file", this.chunk)
this.headers["uploader-chunk-number"] = this.chunkCount this.headers["uploader-chunk-number"] = this.chunkCount
console.log(`[UPLOADER] Sending chunk ${this.chunkCount}`, { console.log(`[UPLOADER] Sending chunk ${this.chunkCount}`, {
currentChunk: this.chunkCount, currentChunk: this.chunkCount,
totalChunks: this.totalChunks, totalChunks: this.totalChunks,
}) })
try { try {
const res = await fetch( const res = await fetch(this.endpoint, {
this.endpoint, method: "POST",
{ headers: this.headers,
method: "POST", body: form,
headers: this.headers, })
body: form,
},
)
return res return res
} catch (error) { } catch (error) {
this.manageRetries() this.manageRetries()
} }
} }
manageRetries() { manageRetries() {
if (++this.retriesCount < this.maxRetries) { if (++this.retriesCount < this.maxRetries) {
setTimeout(() => this.nextSend(), this.delayBeforeRetry * 1000) setTimeout(() => this.nextSend(), this.delayBeforeRetry * 1000)
this.events.emit("fileRetry", { message: `Retrying chunk ${this.chunkCount}`, chunk: this.chunkCount, retriesLeft: this.retries - this.retriesCount }) this.events.emit("fileRetry", {
} else { message: `Retrying chunk ${this.chunkCount}`,
this.events.emit("error", { message: `No more retries for 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() { async nextSend() {
if (this.paused || this.offline) { if (this.paused || this.offline) {
return null return null
} }
this.chunk = await this.loadChunk() this.chunk = await this.loadChunk()
const res = await this.sendChunk() const res = await this.sendChunk()
const data = await res.json() const data = await res.json()
if ([200, 201, 204].includes(res.status)) { if ([200, 201, 204].includes(res.status)) {
console.log(`[UPLOADER] Chunk ${this.chunkCount} sent`) console.log(`[UPLOADER] Chunk ${this.chunkCount} sent`)
this.chunkCount = this.chunkCount + 1 this.chunkCount = this.chunkCount + 1
if (this.chunkCount < this.totalChunks) { if (this.chunkCount < this.totalChunks) {
this.nextSend() this.nextSend()
} }
// check if is the last chunk, if so, handle sse events // check if is the last chunk, if so, handle sse events
if (this.chunkCount === this.totalChunks) { if (this.chunkCount === this.totalChunks) {
if (data.eventChannelURL) { if (data.eventChannelURL) {
console.log(`[UPLOADER] Connecting to SSE channel >`, data.eventChannelURL) console.log(
`[UPLOADER] Connecting to SSE channel >`,
data.eventChannelURL,
)
const eventSource = new EventSource(data.eventChannelURL) const eventSource = new EventSource(data.eventChannelURL)
eventSource.onerror = (error) => { eventSource.onerror = (error) => {
this.events.emit("error", error) this.events.emit("error", error)
} }
eventSource.onopen = () => { eventSource.onopen = () => {
console.log(`[UPLOADER] SSE channel opened`) console.log(`[UPLOADER] SSE channel opened`)
} }
eventSource.onmessage = (event) => { eventSource.onmessage = (event) => {
// parse json // parse json
const messageData = JSON.parse(event.data) const messageData = JSON.parse(event.data)
console.log(`[UPLOADER] SSE Event >`, messageData) console.log(`[UPLOADER] SSE Event >`, messageData)
if (messageData.status === "done") { if (messageData.status === "done") {
this.events.emit("finish", messageData.result) this.events.emit("finish", messageData.result)
eventSource.close() eventSource.close()
} }
if (messageData.status === "error") { if (messageData.status === "error") {
this.events.emit("error", messageData.result) this.events.emit("error", messageData.result)
} }
if (messageData.status === "progress") { if (messageData.status === "progress") {
this.events.emit("progress", { this.events.emit("progress", {
percentProgress: messageData.progress, percentProgress: messageData.progress,
}) })
} }
} }
} else { } else {
this.events.emit("finish", data) this.events.emit("finish", data)
} }
} }
this.events.emit("progress", { this.events.emit("progress", {
percentProgress: Math.round((100 / this.totalChunks) * this.chunkCount) percentProgress: Math.round(
}) (100 / this.totalChunks) * this.chunkCount,
} else if ([408, 502, 503, 504].includes(res.status)) { ),
this.manageRetries() })
} else { } else if ([408, 502, 503, 504].includes(res.status)) {
this.events.emit("error", { message: `[${res.status}] ${data.error ?? data.message}` }) this.manageRetries()
} } else {
} this.events.emit("error", {
message: `[${res.status}] ${data.error ?? data.message}`,
})
}
}
togglePause() { togglePause() {
this.paused = !this.paused this.paused = !this.paused
if (!this.paused) { if (!this.paused) {
return this.nextSend() return this.nextSend()
} }
} }
} }