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

View File

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