From 14ee0543599f2ec73b7f5d2dbd8415f47fe592aa Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Sun, 27 Jul 2025 18:06:44 +0200 Subject: [PATCH 001/206] feat: Translate frontend/src/i18n/en.json in sk --- frontend/src/i18n/sk.json | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/frontend/src/i18n/sk.json b/frontend/src/i18n/sk.json index 5f36b283..a8e957de 100644 --- a/frontend/src/i18n/sk.json +++ b/frontend/src/i18n/sk.json @@ -7,13 +7,13 @@ "copy": "Kopírovať", "copyFile": "Kopírovať súbor", "copyToClipboard": "Kopírovať do schránky", - "copyDownloadLinkToClipboard": "Copy download link to clipboard", + "copyDownloadLinkToClipboard": "Kopírovať odkaz na stiahnutie do schránky", "create": "Vytvoriť", "delete": "Odstrániť", "download": "Stiahnuť", "file": "Súbor", "folder": "Priečinok", - "fullScreen": "Toggle full screen", + "fullScreen": "Prepnúť na celú obrazovku", "hideDotfiles": "Skryť súbory začínajúce bodkou", "info": "Info", "more": "Viac", @@ -24,7 +24,7 @@ "ok": "OK", "permalink": "Získať trvalý odkaz", "previous": "Predošlé", - "preview": "Preview", + "preview": "Náhľad", "publish": "Zverejniť", "rename": "Premenovať", "replace": "Nahradiť", @@ -42,7 +42,7 @@ "update": "Aktualizovať", "upload": "Nahrať", "openFile": "Otvoriť súbor", - "discardChanges": "Discard" + "discardChanges": "Zahodiť" }, "download": { "downloadFile": "Stiahnuť súbor", @@ -50,7 +50,7 @@ "downloadSelected": "Stiahnuť vybraté" }, "upload": { - "abortUpload": "Are you sure you wish to abort?" + "abortUpload": "Naozaj chcete prerušiť?" }, "errors": { "forbidden": "You don't have permissions to access this.", @@ -110,7 +110,7 @@ "deleteMessageMultiple": "Naozaj chcete odstrániť {count} súbor(ov)?", "deleteMessageSingle": "Naozaj chcete odstrániť tento súbor/priečinok?", "deleteMessageShare": "Naozaj chcete odstrániť toto zdieľanie({path})?", - "deleteUser": "Are you sure you want to delete this user?", + "deleteUser": "Naozaj chcete odstrániť tohto používateľa?", "deleteTitle": "Odstránenie súborov", "displayName": "Zobrazený názov:", "download": "Stiahnuť súbory", @@ -137,11 +137,11 @@ "show": "Zobraziť", "size": "Veľkosť", "upload": "Nahrať", - "uploadFiles": "Uploading {files} files...", + "uploadFiles": "Nahráva sa {files} súborov...", "uploadMessage": "Zvoľte možnosť nahrávania.", "optionalPassword": "Voliteľné heslo", - "resolution": "Resolution", - "discardEditorChanges": "Are you sure you wish to discard the changes you've made?" + "resolution": "Rozlíšenie", + "discardEditorChanges": "Naozaj chcete zahodiť vykonané zmeny?" }, "search": { "images": "Obrázky", @@ -170,14 +170,14 @@ "commandRunnerHelp": "Sem môžete nastaviť príkazy, ktoré sa vykonajú pri určitých udalostiach. Musíte písať jeden na riadok. Premenné prostredia {0} a {1} sú k dispozícii, s tým že {0} relatívne k {1}. Viac informácií o tejto funkcionalite a dostupných premenných prostredia nájdete na {2}.", "commandsUpdated": "Príkazy upravené!", "createUserDir": "Automaticky vytvoriť domovský priečinok pri pridaní používateľa", - "minimumPasswordLength": "Minimum password length", - "tusUploads": "Chunked Uploads", - "tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.", - "tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.", - "tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.", - "userHomeBasePath": "Base path for user home directories", - "userScopeGenerationPlaceholder": "The scope will be auto generated", - "createUserHomeDirectory": "Create user home directory", + "minimumPasswordLength": "Minimálna dĺžka hesla", + "tusUploads": "Nahrávanie po častiach", + "tusUploadsHelp": "Prehliadač súborov podporuje nahrávanie súborov po častiach, čo umožňuje vytváranie efektívnych, spoľahlivých, obnoviteľných a po častiach nahrávaných súborov aj v prípade nespoľahlivých sietí.", + "tusUploadsChunkSize": "Označuje maximálnu veľkosť požiadavky (pre menšie nahratia sa použijú priame nahratia). Môžete zadať celé číslo označujúce veľkosť v bajtoch alebo reťazec ako 10 MB, 1 GB atď.", + "tusUploadsRetryCount": "Počet opakovaných pokusov, ktoré sa majú vykonať, ak sa nepodarí nahrať časť súboru.", + "userHomeBasePath": "Východisková cesta pre domáce adresáre používateľov", + "userScopeGenerationPlaceholder": "Rozsah bude automaticky generovaný", + "createUserHomeDirectory": "Vytvoriť domovský adresár používateľa", "customStylesheet": "Vlastný Stylesheet", "defaultUserDescription": "Toto sú predvolané nastavenia nového používateľa.", "disableExternalLinks": "Vypnúť externé odkazy (okrem dokumentácie)", @@ -217,14 +217,14 @@ "rules": "Pravidlá", "rulesHelp": "Tu môžete definovať pravidlá pre konkrétneho používateľa. Blokované súbory používateľ nebude vidieť a ani nebude k nim mať prístup. Podporujeme regex a cesty relatívne k používateľovi.\n", "scope": "Scope", - "setDateFormat": "Set exact date format", + "setDateFormat": "Nastaviť presný formát dátumu", "settingsUpdated": "Nastavenia upravené!", "shareDuration": "Trvanie zdieľania", "shareManagement": "Správa zdieľania", "shareDeleted": "Zdieľanie odstránené!", "singleClick": "Používať jeden klik na otváranie súborov a priečinkov", "themes": { - "default": "System default", + "default": "Predvolené nastavenie systému", "dark": "Tmavá", "light": "Svetlá", "title": "Téma" From 4ff634715543b65878943273dff70f340167900b Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 31 Jul 2025 07:25:21 +0200 Subject: [PATCH 002/206] fix: directory mode on config init --- cmd/config_init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/config_init.go b/cmd/config_init.go index ea756d0b..26db2d27 100644 --- a/cmd/config_init.go +++ b/cmd/config_init.go @@ -103,7 +103,7 @@ override the options.`, return err } - s.DirMode, err = getMode(flags, "file-mode") + s.DirMode, err = getMode(flags, "dir-mode") if err != nil { return err } From 75baf7ce337671a1045f897ba4a19967a31b1aec Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 04:38:32 +0000 Subject: [PATCH 003/206] feat: Translate frontend/src/i18n/en.json in vi 100% translated source file: 'frontend/src/i18n/en.json' on 'vi'. --- frontend/src/i18n/vi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/i18n/vi.json b/frontend/src/i18n/vi.json index cc301e1f..e47e73c1 100644 --- a/frontend/src/i18n/vi.json +++ b/frontend/src/i18n/vi.json @@ -170,7 +170,7 @@ "commandRunnerHelp": "Tại đây, bạn có thể thiết lập các lệnh được thực thi trong các sự kiện đã định. Bạn phải viết một lệnh trên mỗi dòng. Các biến môi trường {0} và {1} sẽ có sẵn, trong đó {0} tương đối với {1}. Để biết thêm thông tin về tính năng này và các biến môi trường có sẵn, vui lòng đọc {2}.", "commandsUpdated": "Lệnh đã được cập nhật!", "createUserDir": "Tự động tạo thư mục chính của người dùng khi thêm người dùng mới", - "minimumPasswordLength": "Minimum password length", + "minimumPasswordLength": "Độ dài mật khẩu tối thiểu", "tusUploads": "Tải lên theo phân đoạn", "tusUploadsHelp": "File Browser hỗ trợ tải lên tệp theo phân đoạn, giúp việc tải lên trở nên hiệu quả, đáng tin cậy, có thể tiếp tục và phù hợp với mạng không ổn định.", "tusUploadsChunkSize": "Kích thước tối đa của một yêu cầu (tải lên trực tiếp sẽ được sử dụng cho các tệp nhỏ hơn). Bạn có thể nhập một số nguyên biểu thị kích thước theo byte hoặc một chuỗi như 10MB, 1GB, v.v.", From af9b42549ff5db3305e0bee51387dd763beeff9f Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 31 Jul 2025 07:28:32 +0200 Subject: [PATCH 004/206] chore(release): 2.42.1 --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f754b6f..5465c72a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [2.42.1](https://github.com/filebrowser/filebrowser/compare/v2.42.0...v2.42.1) (2025-07-31) + + +### Features + +* Translate frontend/src/i18n/en.json in sk ([14ee054](https://github.com/filebrowser/filebrowser/commit/14ee0543599f2ec73b7f5d2dbd8415f47fe592aa)) +* Translate frontend/src/i18n/en.json in vi ([75baf7c](https://github.com/filebrowser/filebrowser/commit/75baf7ce337671a1045f897ba4a19967a31b1aec)) + + +### Bug Fixes + +* directory mode on config init ([4ff6347](https://github.com/filebrowser/filebrowser/commit/4ff634715543b65878943273dff70f340167900b)) + ## [2.42.0](https://github.com/filebrowser/filebrowser/compare/v2.41.0...v2.42.0) (2025-07-27) From 06e8713fa55065d38f02499d3e8d39fc86926cab Mon Sep 17 00:00:00 2001 From: Ramires Viana <59319979+ramiresviana@users.noreply.github.com> Date: Fri, 1 Aug 2025 13:44:38 -0300 Subject: [PATCH 005/206] fix: show file upload errors --- frontend/src/api/tus.ts | 14 ++++++++++++-- frontend/src/components/Sidebar.vue | 9 ++------- frontend/src/views/Files.vue | 5 ++++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/frontend/src/api/tus.ts b/frontend/src/api/tus.ts index fbfef4da..8bffa6a5 100644 --- a/frontend/src/api/tus.ts +++ b/frontend/src/api/tus.ts @@ -55,12 +55,22 @@ export async function upload( return true; }, - onError: function (error) { + onError: function (error: Error | tus.DetailedError) { if (CURRENT_UPLOAD_LIST[filePath].interval) { clearInterval(CURRENT_UPLOAD_LIST[filePath].interval); } delete CURRENT_UPLOAD_LIST[filePath]; - reject(new Error(`Upload failed: ${error.message}`)); + + const message = + error instanceof tus.DetailedError + ? error.originalResponse === null + ? "000 No connection" + : error.originalResponse.getBody() + : "Upload failed"; + + console.error(error); + + reject(new Error(message)); }, onProgress: function (bytesUploaded) { const fileData = CURRENT_UPLOAD_LIST[filePath]; diff --git a/frontend/src/components/Sidebar.vue b/frontend/src/components/Sidebar.vue index 74fb45ad..5bbf8847 100644 --- a/frontend/src/components/Sidebar.vue +++ b/frontend/src/components/Sidebar.vue @@ -132,7 +132,6 @@ import { import { files as api } from "@/api"; import ProgressBar from "@/components/ProgressBar.vue"; import prettyBytes from "pretty-bytes"; -import { StatusError } from "@/api/utils.js"; const USAGE_DEFAULT = { used: "0 B", total: "0 B", usedPercentage: 0 }; @@ -181,13 +180,9 @@ export default { total: prettyBytes(usage.total, { binary: true }), usedPercentage: Math.round((usage.used / usage.total) * 100), }; - } catch (error) { - if (error instanceof StatusError && error.is_canceled) { - return; - } - this.$showError(error); + } finally { + return Object.assign(this.usage, usageStats); } - return Object.assign(this.usage, usageStats); }, toRoot() { this.$router.push({ path: "/files" }); diff --git a/frontend/src/views/Files.vue b/frontend/src/views/Files.vue index 805f4027..950cb86d 100644 --- a/frontend/src/views/Files.vue +++ b/frontend/src/views/Files.vue @@ -26,6 +26,7 @@ import { computed, defineAsyncComponent, + inject, onBeforeUnmount, onMounted, onUnmounted, @@ -50,6 +51,8 @@ import { name } from "../utils/constants"; const Editor = defineAsyncComponent(() => import("@/views/files/Editor.vue")); const Preview = defineAsyncComponent(() => import("@/views/files/Preview.vue")); +const $showError = inject("$showError")!; + const layoutStore = useLayoutStore(); const fileStore = useFileStore(); const uploadStore = useUploadStore(); @@ -109,7 +112,7 @@ watch(reload, (newValue) => { newValue && fetchData(); }); watch(uploadError, (newValue) => { - newValue && layoutStore.showError(); + newValue && $showError(newValue); }); // Define functions From 6d620c00a19c33e5cac10bfb2441846f30d0bade Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Mon, 4 Aug 2025 08:11:40 +0200 Subject: [PATCH 006/206] docs: reword configuration intro --- www/docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/docs/configuration.md b/www/docs/configuration.md index c8107b30..77f341a4 100644 --- a/www/docs/configuration.md +++ b/www/docs/configuration.md @@ -1,6 +1,6 @@ # Configuration -Most of the configuration can be understood through our Command Line Interface documentation. Although there are some specific topics that we want to cover on this section. +Most of the configuration can be understood through the command line interface documentation. To access it, you need to install File Browser and run `filebrowser --help`. In this page, we cover some specific, more complex, topics. ## Custom Branding From c14cf86f8304e01d804e01a7eef5ea093627ef37 Mon Sep 17 00:00:00 2001 From: Ramires Viana <59319979+ramiresviana@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:47:48 -0300 Subject: [PATCH 007/206] refactor: upload progress calculation (#5350) --- frontend/src/api/search.ts | 2 +- frontend/src/api/tus.ts | 112 +----- .../src/components/prompts/UploadFiles.vue | 204 +++++++---- frontend/src/stores/upload.ts | 334 ++++++++---------- frontend/src/types/file.d.ts | 1 + frontend/src/types/upload.d.ts | 43 +-- frontend/src/utils/upload.ts | 11 +- frontend/src/views/Files.vue | 9 - frontend/src/views/Layout.vue | 14 +- frontend/tsconfig.tsc.json | 3 +- 10 files changed, 321 insertions(+), 412 deletions(-) diff --git a/frontend/src/api/search.ts b/frontend/src/api/search.ts index 871f0aed..6fa02d06 100644 --- a/frontend/src/api/search.ts +++ b/frontend/src/api/search.ts @@ -13,7 +13,7 @@ export default async function search(base: string, query: string) { let data = await res.json(); - data = data.map((item: UploadItem) => { + data = data.map((item: ResourceItem & { dir: boolean }) => { item.url = `/files${base}` + url.encodePath(item.path); if (item.dir) { diff --git a/frontend/src/api/tus.ts b/frontend/src/api/tus.ts index 8bffa6a5..d6601166 100644 --- a/frontend/src/api/tus.ts +++ b/frontend/src/api/tus.ts @@ -1,17 +1,11 @@ import * as tus from "tus-js-client"; import { baseURL, tusEndpoint, tusSettings, origin } from "@/utils/constants"; import { useAuthStore } from "@/stores/auth"; -import { useUploadStore } from "@/stores/upload"; import { removePrefix } from "@/api/utils"; const RETRY_BASE_DELAY = 1000; const RETRY_MAX_DELAY = 20000; -const SPEED_UPDATE_INTERVAL = 1000; -const ALPHA = 0.2; -const ONE_MINUS_ALPHA = 1 - ALPHA; -const RECENT_SPEEDS_LIMIT = 5; -const MB_DIVISOR = 1024 * 1024; -const CURRENT_UPLOAD_LIST: CurrentUploadList = {}; +const CURRENT_UPLOAD_LIST: { [key: string]: tus.Upload } = {}; export async function upload( filePath: string, @@ -56,11 +50,12 @@ export async function upload( return true; }, onError: function (error: Error | tus.DetailedError) { - if (CURRENT_UPLOAD_LIST[filePath].interval) { - clearInterval(CURRENT_UPLOAD_LIST[filePath].interval); - } delete CURRENT_UPLOAD_LIST[filePath]; + if (error.message === "Upload aborted") { + return reject(error); + } + const message = error instanceof tus.DetailedError ? error.originalResponse === null @@ -73,40 +68,16 @@ export async function upload( reject(new Error(message)); }, onProgress: function (bytesUploaded) { - const fileData = CURRENT_UPLOAD_LIST[filePath]; - fileData.currentBytesUploaded = bytesUploaded; - - if (!fileData.hasStarted) { - fileData.hasStarted = true; - fileData.lastProgressTimestamp = Date.now(); - - fileData.interval = window.setInterval(() => { - calcProgress(filePath); - }, SPEED_UPDATE_INTERVAL); - } if (typeof onupload === "function") { onupload({ loaded: bytesUploaded }); } }, onSuccess: function () { - if (CURRENT_UPLOAD_LIST[filePath].interval) { - clearInterval(CURRENT_UPLOAD_LIST[filePath].interval); - } delete CURRENT_UPLOAD_LIST[filePath]; resolve(); }, }); - CURRENT_UPLOAD_LIST[filePath] = { - upload: upload, - recentSpeeds: [], - initialBytesUploaded: 0, - currentBytesUploaded: 0, - currentAverageSpeed: 0, - lastProgressTimestamp: null, - sumOfRecentSpeeds: 0, - hasStarted: false, - interval: undefined, - }; + CURRENT_UPLOAD_LIST[filePath] = upload; upload.start(); }); } @@ -138,76 +109,11 @@ function isTusSupported() { return tus.isSupported === true; } -function computeETA(speed?: number) { - const state = useUploadStore(); - if (state.speedMbyte === 0) { - return Infinity; - } - const totalSize = state.sizes.reduce( - (acc: number, size: number) => acc + size, - 0 - ); - const uploadedSize = state.progress.reduce((a, b) => a + b, 0); - const remainingSize = totalSize - uploadedSize; - const speedBytesPerSecond = (speed ?? state.speedMbyte) * 1024 * 1024; - return remainingSize / speedBytesPerSecond; -} - -function computeGlobalSpeedAndETA() { - let totalSpeed = 0; - let totalCount = 0; - - for (const filePath in CURRENT_UPLOAD_LIST) { - totalSpeed += CURRENT_UPLOAD_LIST[filePath].currentAverageSpeed; - totalCount++; - } - - if (totalCount === 0) return { speed: 0, eta: Infinity }; - - const averageSpeed = totalSpeed / totalCount; - const averageETA = computeETA(averageSpeed); - - return { speed: averageSpeed, eta: averageETA }; -} - -function calcProgress(filePath: string) { - const uploadStore = useUploadStore(); - const fileData = CURRENT_UPLOAD_LIST[filePath]; - - const elapsedTime = - (Date.now() - (fileData.lastProgressTimestamp ?? 0)) / 1000; - const bytesSinceLastUpdate = - fileData.currentBytesUploaded - fileData.initialBytesUploaded; - const currentSpeed = bytesSinceLastUpdate / MB_DIVISOR / elapsedTime; - - if (fileData.recentSpeeds.length >= RECENT_SPEEDS_LIMIT) { - fileData.sumOfRecentSpeeds -= fileData.recentSpeeds.shift() ?? 0; - } - - fileData.recentSpeeds.push(currentSpeed); - fileData.sumOfRecentSpeeds += currentSpeed; - - const avgRecentSpeed = - fileData.sumOfRecentSpeeds / fileData.recentSpeeds.length; - fileData.currentAverageSpeed = - ALPHA * avgRecentSpeed + ONE_MINUS_ALPHA * fileData.currentAverageSpeed; - - const { speed, eta } = computeGlobalSpeedAndETA(); - uploadStore.setUploadSpeed(speed); - uploadStore.setETA(eta); - - fileData.initialBytesUploaded = fileData.currentBytesUploaded; - fileData.lastProgressTimestamp = Date.now(); -} - export function abortAllUploads() { for (const filePath in CURRENT_UPLOAD_LIST) { - if (CURRENT_UPLOAD_LIST[filePath].interval) { - clearInterval(CURRENT_UPLOAD_LIST[filePath].interval); - } - if (CURRENT_UPLOAD_LIST[filePath].upload) { - CURRENT_UPLOAD_LIST[filePath].upload.abort(true); - CURRENT_UPLOAD_LIST[filePath].upload.options!.onError!( + if (CURRENT_UPLOAD_LIST[filePath]) { + CURRENT_UPLOAD_LIST[filePath].abort(true); + CURRENT_UPLOAD_LIST[filePath].options!.onError!( new Error("Upload aborted") ); } diff --git a/frontend/src/components/prompts/UploadFiles.vue b/frontend/src/components/prompts/UploadFiles.vue index eb599aa8..883fffe3 100644 --- a/frontend/src/components/prompts/UploadFiles.vue +++ b/frontend/src/components/prompts/UploadFiles.vue @@ -1,20 +1,25 @@ - diff --git a/frontend/src/stores/upload.ts b/frontend/src/stores/upload.ts index 8429146e..53d96ea9 100644 --- a/frontend/src/stores/upload.ts +++ b/frontend/src/stores/upload.ts @@ -1,8 +1,9 @@ import { defineStore } from "pinia"; import { useFileStore } from "./file"; import { files as api } from "@/api"; -import { throttle } from "lodash-es"; import buttons from "@/utils/buttons"; +import { computed, inject, markRaw, ref } from "vue"; +import * as tus from "@/api/tus"; // TODO: make this into a user setting const UPLOADS_LIMIT = 5; @@ -13,208 +14,167 @@ const beforeUnload = (event: Event) => { // event.returnValue = ""; }; -// Utility function to format bytes into a readable string -function formatSize(bytes: number): string { - if (bytes === 0) return "0.00 Bytes"; +export const useUploadStore = defineStore("upload", () => { + const $showError = inject("$showError")!; - const k = 1024; - const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; - const i = Math.floor(Math.log(bytes) / Math.log(k)); + let progressInterval: number | null = null; - // Return the rounded size with two decimal places - return (bytes / k ** i).toFixed(2) + " " + sizes[i]; -} + // + // STATE + // -export const useUploadStore = defineStore("upload", { - // convert to a function - state: (): { - id: number; - sizes: number[]; - progress: number[]; - queue: UploadItem[]; - uploads: Uploads; - speedMbyte: number; - eta: number; - error: Error | null; - } => ({ - id: 0, - sizes: [], - progress: [], - queue: [], - uploads: {}, - speedMbyte: 0, - eta: 0, - error: null, - }), - getters: { - // user and jwt getter removed, no longer needed - getProgress: (state) => { - if (state.progress.length === 0) { - return 0; + const allUploads = ref([]); + const activeUploads = ref>(new Set()); + const lastUpload = ref(-1); + const totalBytes = ref(0); + const sentBytes = ref(0); + + // + // ACTIONS + // + + const upload = ( + path: string, + name: string, + file: File | null, + overwrite: boolean, + type: ResourceType + ) => { + if (!hasActiveUploads() && !hasPendingUploads()) { + window.addEventListener("beforeunload", beforeUnload); + buttons.loading("upload"); + } + + const upload: Upload = { + path, + name, + file, + overwrite, + type, + totalBytes: file?.size || 1, + sentBytes: 0, + // Stores rapidly changing sent bytes value without causing component re-renders + rawProgress: markRaw({ + sentBytes: 0, + }), + }; + + totalBytes.value += upload.totalBytes; + allUploads.value.push(upload); + + processUploads(); + }; + + const abort = () => { + // Resets the state by preventing the processing of the remaning uploads + lastUpload.value = Infinity; + tus.abortAllUploads(); + }; + + // + // GETTERS + // + + const pendingUploadCount = computed( + () => + allUploads.value.length - + (lastUpload.value + 1) + + activeUploads.value.size + ); + + // + // PRIVATE FUNCTIONS + // + + const hasActiveUploads = () => activeUploads.value.size > 0; + + const hasPendingUploads = () => + allUploads.value.length > lastUpload.value + 1; + + const isActiveUploadsOnLimit = () => activeUploads.value.size < UPLOADS_LIMIT; + + const processUploads = async () => { + if (!hasActiveUploads() && !hasPendingUploads()) { + const fileStore = useFileStore(); + window.removeEventListener("beforeunload", beforeUnload); + buttons.success("upload"); + reset(); + fileStore.reload = true; + } + + if (isActiveUploadsOnLimit() && hasPendingUploads()) { + if (!hasActiveUploads()) { + // Update the state in a fixed time interval + progressInterval = window.setInterval(syncState, 1000); } - const totalSize = state.sizes.reduce((a, b) => a + b, 0); - const sum = state.progress.reduce((a, b) => a + b, 0); - return Math.ceil((sum / totalSize) * 100); - }, - getProgressDecimal: (state) => { - if (state.progress.length === 0) { - return 0; + const upload = nextUpload(); + + if (upload.type === "dir") { + await api.post(upload.path).catch($showError); + } else { + const onUpload = (event: ProgressEvent) => { + upload.rawProgress.sentBytes = event.loaded; + }; + + await api + .post(upload.path, upload.file!, upload.overwrite, onUpload) + .catch((err) => err.message !== "Upload aborted" && $showError(err)); } - const totalSize = state.sizes.reduce((a, b) => a + b, 0); - const sum = state.progress.reduce((a, b) => a + b, 0); - return ((sum / totalSize) * 100).toFixed(2); - }, - getTotalProgressBytes: (state) => { - if (state.progress.length === 0 || state.sizes.length === 0) { - return "0 Bytes"; - } - const sum = state.progress.reduce((a, b) => a + b, 0); - return formatSize(sum); - }, - getTotalSize: (state) => { - if (state.sizes.length === 0) { - return "0 Bytes"; - } - const totalSize = state.sizes.reduce((a, b) => a + b, 0); - return formatSize(totalSize); - }, - filesInUploadCount: (state) => { - return Object.keys(state.uploads).length + state.queue.length; - }, - filesInUpload: (state) => { - const files = []; + finishUpload(upload); + } + }; - for (const index in state.uploads) { - const upload = state.uploads[index]; - const id = upload.id; - const type = upload.type; - const name = upload.file.name; - const size = state.sizes[id]; - const isDir = upload.file.isDir; - const progress = isDir - ? 100 - : Math.ceil((state.progress[id] / size) * 100); + const nextUpload = (): Upload => { + lastUpload.value++; - files.push({ - id, - name, - progress, - type, - isDir, - }); - } + const upload = allUploads.value[lastUpload.value]; + activeUploads.value.add(upload); - return files.sort((a, b) => a.progress - b.progress); - }, - uploadSpeed: (state) => { - return state.speedMbyte; - }, - getETA: (state) => state.eta, - }, - actions: { - // no context as first argument, use `this` instead - setProgress({ id, loaded }: { id: number; loaded: number }) { - this.progress[id] = loaded; - }, - setError(error: Error) { - this.error = error; - }, - reset() { - this.id = 0; - this.sizes = []; - this.progress = []; - this.queue = []; - this.uploads = {}; - this.speedMbyte = 0; - this.eta = 0; - this.error = null; - }, - addJob(item: UploadItem) { - this.queue.push(item); - this.sizes[this.id] = item.file.size; - this.id++; - }, - moveJob() { - const item = this.queue[0]; - this.queue.shift(); - this.uploads[item.id] = item; - }, - removeJob(id: number) { - delete this.uploads[id]; - }, - upload(item: UploadItem) { - const uploadsCount = Object.keys(this.uploads).length; + return upload; + }; - const isQueueEmpty = this.queue.length == 0; - const isUploadsEmpty = uploadsCount == 0; + const finishUpload = (upload: Upload) => { + sentBytes.value += upload.totalBytes - upload.sentBytes; + upload.sentBytes = upload.totalBytes; + upload.file = null; - if (isQueueEmpty && isUploadsEmpty) { - window.addEventListener("beforeunload", beforeUnload); - buttons.loading("upload"); - } + activeUploads.value.delete(upload); + processUploads(); + }; - this.addJob(item); - this.processUploads(); - }, - finishUpload(item: UploadItem) { - this.setProgress({ id: item.id, loaded: item.file.size }); - this.removeJob(item.id); - this.processUploads(); - }, - async processUploads() { - const uploadsCount = Object.keys(this.uploads).length; + const syncState = () => { + for (const upload of activeUploads.value) { + sentBytes.value += upload.rawProgress.sentBytes - upload.sentBytes; + upload.sentBytes = upload.rawProgress.sentBytes; + } + }; - const isBelowLimit = uploadsCount < UPLOADS_LIMIT; - const isQueueEmpty = this.queue.length == 0; - const isUploadsEmpty = uploadsCount == 0; + const reset = () => { + if (progressInterval !== null) { + clearInterval(progressInterval); + progressInterval = null; + } - const isFinished = isQueueEmpty && isUploadsEmpty; - const canProcess = isBelowLimit && !isQueueEmpty; + allUploads.value = []; + activeUploads.value = new Set(); + lastUpload.value = -1; + totalBytes.value = 0; + sentBytes.value = 0; + }; - if (isFinished) { - const fileStore = useFileStore(); - window.removeEventListener("beforeunload", beforeUnload); - buttons.success("upload"); - this.reset(); - fileStore.reload = true; - } + return { + // STATE + activeUploads, + totalBytes, + sentBytes, - if (canProcess) { - const item = this.queue[0]; - this.moveJob(); + // ACTIONS + upload, + abort, - if (item.file.isDir) { - await api.post(item.path).catch(this.setError); - } else { - const onUpload = throttle( - (event: ProgressEvent) => - this.setProgress({ - id: item.id, - loaded: event.loaded, - }), - 100, - { leading: true, trailing: false } - ); - - await api - .post(item.path, item.file.file as File, item.overwrite, onUpload) - .catch(this.setError); - } - - this.finishUpload(item); - } - }, - setUploadSpeed(value: number) { - this.speedMbyte = value; - }, - setETA(value: number) { - this.eta = value; - }, - // easily reset state using `$reset` - clearUpload() { - this.$reset(); - }, - }, + // GETTERS + pendingUploadCount, + }; }); diff --git a/frontend/src/types/file.d.ts b/frontend/src/types/file.d.ts index db2aa5fe..5664c16b 100644 --- a/frontend/src/types/file.d.ts +++ b/frontend/src/types/file.d.ts @@ -29,6 +29,7 @@ interface ResourceItem extends ResourceBase { } type ResourceType = + | "dir" | "video" | "audio" | "image" diff --git a/frontend/src/types/upload.d.ts b/frontend/src/types/upload.d.ts index 131f4b2c..4bad9e06 100644 --- a/frontend/src/types/upload.d.ts +++ b/frontend/src/types/upload.d.ts @@ -1,22 +1,15 @@ -interface Uploads { - [key: number]: Upload; -} - -interface Upload { - id: number; - file: UploadEntry; - type?: ResourceType; -} - -interface UploadItem { - id: number; - url?: string; +type Upload = { path: string; - file: UploadEntry; - dir?: boolean; - overwrite?: boolean; - type?: ResourceType; -} + name: string; + file: File | null; + type: ResourceType; + overwrite: boolean; + totalBytes: number; + sentBytes: number; + rawProgress: { + sentBytes: number; + }; +}; interface UploadEntry { name: string; @@ -27,17 +20,3 @@ interface UploadEntry { } type UploadList = UploadEntry[]; - -type CurrentUploadList = { - [key: string]: { - upload: import("tus-js-client").Upload; - recentSpeeds: number[]; - initialBytesUploaded: number; - currentBytesUploaded: number; - currentAverageSpeed: number; - lastProgressTimestamp: number | null; - sumOfRecentSpeeds: number; - hasStarted: boolean; - interval: number | undefined; - }; -}; diff --git a/frontend/src/utils/upload.ts b/frontend/src/utils/upload.ts index cdd974e8..e951cb43 100644 --- a/frontend/src/utils/upload.ts +++ b/frontend/src/utils/upload.ts @@ -132,7 +132,6 @@ export function handleFiles( layoutStore.closeHovers(); for (const file of files) { - const id = uploadStore.id; let path = base; if (file.fullPath !== undefined) { @@ -145,14 +144,8 @@ export function handleFiles( path += "/"; } - const item: UploadItem = { - id, - path, - file, - overwrite, - ...(!file.isDir && { type: detectType((file.file as File).type) }), - }; + const type = file.isDir ? "dir" : detectType((file.file as File).type); - uploadStore.upload(item); + uploadStore.upload(path, file.name, file.file ?? null, overwrite, type); } } diff --git a/frontend/src/views/Files.vue b/frontend/src/views/Files.vue index 950cb86d..5001659f 100644 --- a/frontend/src/views/Files.vue +++ b/frontend/src/views/Files.vue @@ -26,7 +26,6 @@ import { computed, defineAsyncComponent, - inject, onBeforeUnmount, onMounted, onUnmounted, @@ -37,7 +36,6 @@ import { files as api } from "@/api"; import { storeToRefs } from "pinia"; import { useFileStore } from "@/stores/file"; import { useLayoutStore } from "@/stores/layout"; -import { useUploadStore } from "@/stores/upload"; import HeaderBar from "@/components/header/HeaderBar.vue"; import Breadcrumbs from "@/components/Breadcrumbs.vue"; @@ -51,14 +49,10 @@ import { name } from "../utils/constants"; const Editor = defineAsyncComponent(() => import("@/views/files/Editor.vue")); const Preview = defineAsyncComponent(() => import("@/views/files/Preview.vue")); -const $showError = inject("$showError")!; - const layoutStore = useLayoutStore(); const fileStore = useFileStore(); -const uploadStore = useUploadStore(); const { reload } = storeToRefs(fileStore); -const { error: uploadError } = storeToRefs(uploadStore); const route = useRoute(); @@ -111,9 +105,6 @@ watch(route, () => { watch(reload, (newValue) => { newValue && fetchData(); }); -watch(uploadError, (newValue) => { - newValue && $showError(newValue); -}); // Define functions diff --git a/frontend/src/views/Layout.vue b/frontend/src/views/Layout.vue index 597a680e..5a91bee5 100644 --- a/frontend/src/views/Layout.vue +++ b/frontend/src/views/Layout.vue @@ -1,7 +1,11 @@ diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 7de128ed..4070619d 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -42,7 +42,8 @@ "update": "Update", "upload": "Upload", "openFile": "Open file", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Download File", diff --git a/frontend/src/stores/layout.ts b/frontend/src/stores/layout.ts index faf8bca7..372fca06 100644 --- a/frontend/src/stores/layout.ts +++ b/frontend/src/stores/layout.ts @@ -41,6 +41,7 @@ export const useLayoutStore = defineStore("layout", { prompt: value, confirm: null, action: undefined, + saveAction: undefined, props: null, close: null, }); @@ -51,6 +52,7 @@ export const useLayoutStore = defineStore("layout", { prompt: value.prompt, confirm: value?.confirm, action: value?.action, + saveAction: value?.saveAction, props: value?.props, close: value?.close, }); diff --git a/frontend/src/types/layout.d.ts b/frontend/src/types/layout.d.ts index b625cc07..a5c3f160 100644 --- a/frontend/src/types/layout.d.ts +++ b/frontend/src/types/layout.d.ts @@ -2,6 +2,7 @@ interface PopupProps { prompt: string; confirm?: any; action?: PopupAction; + saveAction?: () => void; props?: any; close?: (() => Promise) | null; } diff --git a/frontend/src/views/files/Editor.vue b/frontend/src/views/files/Editor.vue index 8db6252b..13013a9f 100644 --- a/frontend/src/views/files/Editor.vue +++ b/frontend/src/views/files/Editor.vue @@ -157,6 +157,10 @@ onBeforeRouteUpdate((to, from, next) => { event.preventDefault(); next(); }, + saveAction: async () => { + await save(); + next(); + }, }); }); From 82dc57ad43503c87428af9b1e9c814f4621e3cd0 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sat, 13 Sep 2025 08:44:52 +0200 Subject: [PATCH 024/206] chore(release): 2.43.0 --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc661cfd..6f487429 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,33 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.43.0](https://github.com/filebrowser/filebrowser/compare/v2.42.5...v2.43.0) (2025-09-13) + + +### Features + +* "save changes" button to discard changes dialog ([84e8632](https://github.com/filebrowser/filebrowser/commit/84e8632b98e315bfef2da77dd7d1049daec99241)) +* Translate frontend/src/i18n/en.json in es ([571ce6c](https://github.com/filebrowser/filebrowser/commit/571ce6cb0d7c8725d1cc1a3238ea506ddc72b060)) +* Translate frontend/src/i18n/en.json in fr ([6b1fa87](https://github.com/filebrowser/filebrowser/commit/6b1fa87ad38ebbb1a9c5d0e5fc88ba796c148bcf)) +* Updates for project File Browser ([#5427](https://github.com/filebrowser/filebrowser/issues/5427)) ([8950585](https://github.com/filebrowser/filebrowser/commit/89505851414bfcee6b9ff02087eb4cec51c330f6)) + + +### Bug Fixes + +* optimize markdown preview height ([783503a](https://github.com/filebrowser/filebrowser/commit/783503aece7fca9e26f7e849b0e7478aba976acb)) + + +### Build + +* **deps-dev:** bump vite from 6.1.6 to 6.3.6 in /frontend ([36c6cc2](https://github.com/filebrowser/filebrowser/commit/36c6cc203e10947439519a0413d5817921a1690d)) +* **deps:** bump github.com/go-viper/mapstructure/v2 in /tools ([280fa56](https://github.com/filebrowser/filebrowser/commit/280fa562a67824887ae6e2530a3b73739d6e1bb4)) +* **deps:** bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 ([950028a](https://github.com/filebrowser/filebrowser/commit/950028abebe2898bac4ecfd8715c0967246310cb)) + + +### Refactorings + +* to use strings.Lines ([b482a9b](https://github.com/filebrowser/filebrowser/commit/b482a9bf0d292ec6542d2145a4408971e4c985f1)) + ### [2.42.5](https://github.com/filebrowser/filebrowser/compare/v2.42.4...v2.42.5) (2025-08-16) From 07692653ffe0ea5e517e6dc1fd3961172e931843 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sat, 13 Sep 2025 09:03:12 +0200 Subject: [PATCH 025/206] revert: build(deps): bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 788dcf19..cf005b55 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/cast v1.9.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/ulikunitz/xz v0.5.14 // indirect + github.com/ulikunitz/xz v0.5.12 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/multierr v1.11.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect diff --git a/go.sum b/go.sum index a2988587..a9ccaa5b 100644 --- a/go.sum +++ b/go.sum @@ -232,8 +232,8 @@ github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSW github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg= -github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= From 2f0c1f5fa288bad90ab70d5801a11f86a69b5cac Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sat, 13 Sep 2025 09:04:12 +0200 Subject: [PATCH 026/206] chore(release): 2.43.0 --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f487429..f81c8cd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,38 @@ All notable changes to this project will be documented in this file. See [standa * optimize markdown preview height ([783503a](https://github.com/filebrowser/filebrowser/commit/783503aece7fca9e26f7e849b0e7478aba976acb)) +### Reverts + +* build(deps): bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 ([0769265](https://github.com/filebrowser/filebrowser/commit/07692653ffe0ea5e517e6dc1fd3961172e931843)) + + +### Build + +* **deps-dev:** bump vite from 6.1.6 to 6.3.6 in /frontend ([36c6cc2](https://github.com/filebrowser/filebrowser/commit/36c6cc203e10947439519a0413d5817921a1690d)) +* **deps:** bump github.com/go-viper/mapstructure/v2 in /tools ([280fa56](https://github.com/filebrowser/filebrowser/commit/280fa562a67824887ae6e2530a3b73739d6e1bb4)) +* **deps:** bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 ([950028a](https://github.com/filebrowser/filebrowser/commit/950028abebe2898bac4ecfd8715c0967246310cb)) + + +### Refactorings + +* to use strings.Lines ([b482a9b](https://github.com/filebrowser/filebrowser/commit/b482a9bf0d292ec6542d2145a4408971e4c985f1)) + +## [2.43.0](https://github.com/filebrowser/filebrowser/compare/v2.42.5...v2.43.0) (2025-09-13) + + +### Features + +* "save changes" button to discard changes dialog ([84e8632](https://github.com/filebrowser/filebrowser/commit/84e8632b98e315bfef2da77dd7d1049daec99241)) +* Translate frontend/src/i18n/en.json in es ([571ce6c](https://github.com/filebrowser/filebrowser/commit/571ce6cb0d7c8725d1cc1a3238ea506ddc72b060)) +* Translate frontend/src/i18n/en.json in fr ([6b1fa87](https://github.com/filebrowser/filebrowser/commit/6b1fa87ad38ebbb1a9c5d0e5fc88ba796c148bcf)) +* Updates for project File Browser ([#5427](https://github.com/filebrowser/filebrowser/issues/5427)) ([8950585](https://github.com/filebrowser/filebrowser/commit/89505851414bfcee6b9ff02087eb4cec51c330f6)) + + +### Bug Fixes + +* optimize markdown preview height ([783503a](https://github.com/filebrowser/filebrowser/commit/783503aece7fca9e26f7e849b0e7478aba976acb)) + + ### Build * **deps-dev:** bump vite from 6.1.6 to 6.3.6 in /frontend ([36c6cc2](https://github.com/filebrowser/filebrowser/commit/36c6cc203e10947439519a0413d5817921a1690d)) From 4ff247e134e4d61668ee656a258ed67f71414e18 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 13:10:27 +0200 Subject: [PATCH 027/206] feat: Updates for project File Browser (#5446) Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- frontend/src/i18n/ar.json | 3 +- frontend/src/i18n/ca.json | 3 +- frontend/src/i18n/cs.json | 3 +- frontend/src/i18n/de.json | 3 +- frontend/src/i18n/el.json | 3 +- frontend/src/i18n/es.json | 3 +- frontend/src/i18n/fa.json | 3 +- frontend/src/i18n/he.json | 3 +- frontend/src/i18n/hu.json | 3 +- frontend/src/i18n/is.json | 3 +- frontend/src/i18n/it.json | 3 +- frontend/src/i18n/ja.json | 3 +- frontend/src/i18n/ko.json | 59 ++++++++++++++++++------------------ frontend/src/i18n/nl-be.json | 3 +- frontend/src/i18n/no.json | 3 +- frontend/src/i18n/pl.json | 3 +- frontend/src/i18n/pt-br.json | 3 +- frontend/src/i18n/pt.json | 3 +- frontend/src/i18n/ro.json | 3 +- frontend/src/i18n/ru.json | 3 +- frontend/src/i18n/sk.json | 3 +- frontend/src/i18n/sv-se.json | 3 +- frontend/src/i18n/tr.json | 3 +- frontend/src/i18n/uk.json | 3 +- frontend/src/i18n/vi.json | 3 +- frontend/src/i18n/zh-cn.json | 3 +- frontend/src/i18n/zh-tw.json | 3 +- 27 files changed, 82 insertions(+), 55 deletions(-) diff --git a/frontend/src/i18n/ar.json b/frontend/src/i18n/ar.json index 03edf825..7dcc555d 100644 --- a/frontend/src/i18n/ar.json +++ b/frontend/src/i18n/ar.json @@ -42,7 +42,8 @@ "update": "تحديث", "upload": "رفع", "openFile": "فتح الملف", - "discardChanges": "إلغاء التغييرات" + "discardChanges": "إلغاء التغييرات", + "saveChanges": "Save changes" }, "download": { "downloadFile": "تحميل الملف", diff --git a/frontend/src/i18n/ca.json b/frontend/src/i18n/ca.json index 77e32e47..6ba909df 100644 --- a/frontend/src/i18n/ca.json +++ b/frontend/src/i18n/ca.json @@ -42,7 +42,8 @@ "update": "Actualitzar", "upload": "Pujar", "openFile": "Obrir fitxer", - "discardChanges": "Descartar" + "discardChanges": "Descartar", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarregar fitxer", diff --git a/frontend/src/i18n/cs.json b/frontend/src/i18n/cs.json index 1c1077c8..58029d3a 100644 --- a/frontend/src/i18n/cs.json +++ b/frontend/src/i18n/cs.json @@ -42,7 +42,8 @@ "update": "Aktualizovat", "upload": "Nahrát", "openFile": "Otevřít soubor", - "discardChanges": "Zrušit změny" + "discardChanges": "Zrušit změny", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Stáhnout soubor", diff --git a/frontend/src/i18n/de.json b/frontend/src/i18n/de.json index 0a307f64..aaa647de 100644 --- a/frontend/src/i18n/de.json +++ b/frontend/src/i18n/de.json @@ -42,7 +42,8 @@ "update": "Update", "upload": "Upload", "openFile": "Datei öffnen", - "discardChanges": "Verwerfen" + "discardChanges": "Verwerfen", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Download Datei", diff --git a/frontend/src/i18n/el.json b/frontend/src/i18n/el.json index 9b021b80..13150356 100644 --- a/frontend/src/i18n/el.json +++ b/frontend/src/i18n/el.json @@ -42,7 +42,8 @@ "update": "Ενημέρωση", "upload": "Μεταφόρτωση", "openFile": "Άνοιγμα αρχείου", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Λήψη αρχείου", diff --git a/frontend/src/i18n/es.json b/frontend/src/i18n/es.json index 646c7519..3ab1025d 100644 --- a/frontend/src/i18n/es.json +++ b/frontend/src/i18n/es.json @@ -42,7 +42,8 @@ "update": "Actualizar", "upload": "Subir", "openFile": "Abrir archivo", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Guardar cambios" }, "download": { "downloadFile": "Descargar fichero", diff --git a/frontend/src/i18n/fa.json b/frontend/src/i18n/fa.json index 478e8148..eb8ef99e 100644 --- a/frontend/src/i18n/fa.json +++ b/frontend/src/i18n/fa.json @@ -42,7 +42,8 @@ "update": "به روز سانی", "upload": "آپلود", "openFile": "باز کردن فایل", - "discardChanges": "لغو کردن" + "discardChanges": "لغو کردن", + "saveChanges": "Save changes" }, "download": { "downloadFile": "دانلود فایل", diff --git a/frontend/src/i18n/he.json b/frontend/src/i18n/he.json index 009f07b7..b7f13d88 100644 --- a/frontend/src/i18n/he.json +++ b/frontend/src/i18n/he.json @@ -42,7 +42,8 @@ "update": "עדכון", "upload": "העלאה", "openFile": "פתח קובץ", - "discardChanges": "זריקת השינויים" + "discardChanges": "זריקת השינויים", + "saveChanges": "Save changes" }, "download": { "downloadFile": "הורד קובץ", diff --git a/frontend/src/i18n/hu.json b/frontend/src/i18n/hu.json index 507f08da..2b426eb6 100644 --- a/frontend/src/i18n/hu.json +++ b/frontend/src/i18n/hu.json @@ -42,7 +42,8 @@ "update": "Frissítés", "upload": "Feltöltés", "openFile": "Fájl megnyitása", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Fájl letöltése", diff --git a/frontend/src/i18n/is.json b/frontend/src/i18n/is.json index 54eeb727..c29ce698 100644 --- a/frontend/src/i18n/is.json +++ b/frontend/src/i18n/is.json @@ -42,7 +42,8 @@ "update": "Vista", "upload": "Hlaða upp", "openFile": "Open file", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Sækja skjal", diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index 0205b955..000bd8ce 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -42,7 +42,8 @@ "update": "Aggiorna", "upload": "Carica", "openFile": "Apri file", - "discardChanges": "Ignora" + "discardChanges": "Ignora", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Scarica file", diff --git a/frontend/src/i18n/ja.json b/frontend/src/i18n/ja.json index cd380304..6ce903f7 100644 --- a/frontend/src/i18n/ja.json +++ b/frontend/src/i18n/ja.json @@ -42,7 +42,8 @@ "update": "更新", "upload": "アップロード", "openFile": "ファイルを開く", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "ファイルのダウンロード", diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json index 11fe3aac..54307897 100644 --- a/frontend/src/i18n/ko.json +++ b/frontend/src/i18n/ko.json @@ -3,17 +3,17 @@ "cancel": "취소", "clear": "지우기", "close": "닫기", - "continue": "Continue", + "continue": "계속", "copy": "복사", "copyFile": "파일 복사", "copyToClipboard": "클립보드 복사", - "copyDownloadLinkToClipboard": "Copy download link to clipboard", + "copyDownloadLinkToClipboard": "다운로드 링크 복사", "create": "생성", "delete": "삭제", "download": "다운로드", - "file": "File", - "folder": "Folder", - "fullScreen": "Toggle full screen", + "file": "파일", + "folder": "폴더", + "fullScreen": "전체 화면 전환", "hideDotfiles": "숨김파일(dotfile)을 표시 안함", "info": "정보", "more": "더보기", @@ -24,7 +24,7 @@ "ok": "확인", "permalink": "링크 얻기", "previous": "이전", - "preview": "Preview", + "preview": "미리보기", "publish": "게시", "rename": "이름 바꾸기", "replace": "대체", @@ -36,13 +36,14 @@ "selectMultiple": "다중 선택", "share": "공유", "shell": "쉘 전환", - "submit": "Submit", + "submit": "제출", "switchView": "보기 전환", "toggleSidebar": "사이드바 전환", "update": "업데이트", "upload": "업로드", - "openFile": "Open file", - "discardChanges": "Discard" + "openFile": "파일 열기", + "discardChanges": "변경 사항 취소", + "saveChanges": "변경사항 저장" }, "download": { "downloadFile": "파일 다운로드", @@ -50,13 +51,13 @@ "downloadSelected": "선택 항목 다운로드" }, "upload": { - "abortUpload": "Are you sure you wish to abort?" + "abortUpload": "업로드를 중단하시겠습니까?" }, "errors": { "forbidden": "접근 권한이 없습니다.", "internal": "오류가 발생하였습니다.", "notFound": "해당 경로를 찾을 수 없습니다.", - "connection": "The server can't be reached." + "connection": "서버에 연결할 수 없습니다." }, "files": { "body": "본문", @@ -74,7 +75,7 @@ "sortByLastModified": "수정시간순 정렬", "sortByName": "이름순", "sortBySize": "크기순", - "noPreview": "Preview is not available for this file." + "noPreview": "미리 보기가 지원되지 않는 파일 유형입니다." }, "help": { "click": "파일이나 디렉토리를 선택해주세요.", @@ -109,8 +110,8 @@ "currentlyNavigating": "현재 위치:", "deleteMessageMultiple": "{count} 개의 파일을 삭제하시겠습니까?", "deleteMessageSingle": "파일 혹은 디렉토리를 삭제하시겠습니까?", - "deleteMessageShare": "Are you sure you wish to delete this share({path})?", - "deleteUser": "Are you sure you want to delete this user?", + "deleteMessageShare": "이 공유({path})를 삭제하시겠습니까?", + "deleteUser": "이 계정을 삭제하시겠습니까?", "deleteTitle": "파일 삭제", "displayName": "게시 이름:", "download": "파일 다운로드", @@ -137,11 +138,11 @@ "show": "보기", "size": "크기", "upload": "업로드", - "uploadFiles": "Uploading {files} files...", + "uploadFiles": "{files}개의 파일 업로드 중...", "uploadMessage": "업로드 옵션을 선택하세요.", - "optionalPassword": "Optional password", - "resolution": "Resolution", - "discardEditorChanges": "Are you sure you wish to discard the changes you've made?" + "optionalPassword": "비밀번호 (선택)", + "resolution": "해상도", + "discardEditorChanges": "변경 사항을 취소하시겠습니까?" }, "search": { "images": "이미지", @@ -170,14 +171,14 @@ "commandRunnerHelp": "이벤트에 해당하는 명령을 설정하세요. 줄당 1개의 명령을 적으세요. 환경 변수{0} 와 {1}이 사용가능하며, {0} 은 {1}에 상대 경로 입니다. 자세한 사항은 {2} 를 참조하세요.", "commandsUpdated": "명령 수정됨!", "createUserDir": "Auto create user home dir while adding new user", - "minimumPasswordLength": "Minimum password length", - "tusUploads": "Chunked Uploads", - "tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.", - "tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.", - "tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.", - "userHomeBasePath": "Base path for user home directories", - "userScopeGenerationPlaceholder": "The scope will be auto generated", - "createUserHomeDirectory": "Create user home directory", + "minimumPasswordLength": "최소 비밀번호 길이", + "tusUploads": "분할 업로드", + "tusUploadsHelp": "File Browser는 불안정한 네트워크에서도 효율적이고 신뢰성 있는 분할 업로드를 지원합니다.", + "tusUploadsChunkSize": "업로드 요청의 최대 크기 (예: 10MB, 1GB)", + "tusUploadsRetryCount": "업로드 실패 시 재시도 횟수", + "userHomeBasePath": "사용자 홈 폴더 기본 경로", + "userScopeGenerationPlaceholder": "범위는 자동으로 생성됩니다.", + "createUserHomeDirectory": "사용자 홈 폴더 생성", "customStylesheet": "커스텀 스타일시트", "defaultUserDescription": "아래 사항은 신규 사용자들에 대한 기본 설정입니다.", "disableExternalLinks": "외부 링크 감추기", @@ -217,14 +218,14 @@ "rules": "룰", "rulesHelp": "사용자별로 규칙을 허용/방지를 지정할 수 있습니다. 방지된 파일은 보이지 않고 사용자들은 접근할 수 없습니다. 사용자의 접근 허용 범위와 관련해 정규표현식(regex)과 경로를 지원합니다.\n", "scope": "범위", - "setDateFormat": "Set exact date format", + "setDateFormat": "날짜 형식 설정", "settingsUpdated": "설정 수정됨!", "shareDuration": "공유 기간", "shareManagement": "공유 내역 관리", - "shareDeleted": "Share deleted!", + "shareDeleted": "공유 삭제됨!", "singleClick": "한번 클릭으로 파일과 폴더를 열도록 합니다.", "themes": { - "default": "System default", + "default": "시스템 기본값", "dark": "다크테마", "light": "라이트테마", "title": "테마" diff --git a/frontend/src/i18n/nl-be.json b/frontend/src/i18n/nl-be.json index 9bf3b1fa..860f12ed 100644 --- a/frontend/src/i18n/nl-be.json +++ b/frontend/src/i18n/nl-be.json @@ -42,7 +42,8 @@ "update": "Updaten", "upload": "Uploaden", "openFile": "Open file", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Bestand downloaden", diff --git a/frontend/src/i18n/no.json b/frontend/src/i18n/no.json index d077e96f..ae35e04e 100644 --- a/frontend/src/i18n/no.json +++ b/frontend/src/i18n/no.json @@ -42,7 +42,8 @@ "update": "Opptater", "upload": "Last opp", "openFile": "Open file", - "discardChanges": "Slett" + "discardChanges": "Slett", + "saveChanges": "Lagre Endringane " }, "download": { "downloadFile": "Nedlast filen", diff --git a/frontend/src/i18n/pl.json b/frontend/src/i18n/pl.json index 3d7835cc..5837faa7 100644 --- a/frontend/src/i18n/pl.json +++ b/frontend/src/i18n/pl.json @@ -42,7 +42,8 @@ "update": "Aktualizuj", "upload": "Wyślij", "openFile": "Otwórz plik", - "discardChanges": "Odrzuć" + "discardChanges": "Odrzuć", + "saveChanges": "Zapisz zmiany" }, "download": { "downloadFile": "Pobierz plik", diff --git a/frontend/src/i18n/pt-br.json b/frontend/src/i18n/pt-br.json index e0f04b66..ccce0f4d 100644 --- a/frontend/src/i18n/pt-br.json +++ b/frontend/src/i18n/pt-br.json @@ -42,7 +42,8 @@ "update": "Atualizar", "upload": "Enviar", "openFile": "Abrir", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Baixar arquivo", diff --git a/frontend/src/i18n/pt.json b/frontend/src/i18n/pt.json index 6041ddd2..7babc212 100644 --- a/frontend/src/i18n/pt.json +++ b/frontend/src/i18n/pt.json @@ -42,7 +42,8 @@ "update": "Atualizar", "upload": "Enviar", "openFile": "Open file", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarregar ficheiro", diff --git a/frontend/src/i18n/ro.json b/frontend/src/i18n/ro.json index 8063e655..b03d8c21 100644 --- a/frontend/src/i18n/ro.json +++ b/frontend/src/i18n/ro.json @@ -42,7 +42,8 @@ "update": "Actualizează", "upload": "Încarcă", "openFile": "Open file", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarcă fișier", diff --git a/frontend/src/i18n/ru.json b/frontend/src/i18n/ru.json index 6d8d8059..3a9ff33a 100644 --- a/frontend/src/i18n/ru.json +++ b/frontend/src/i18n/ru.json @@ -42,7 +42,8 @@ "update": "Обновить", "upload": "Загрузить", "openFile": "Открыть файл", - "discardChanges": "Отказаться" + "discardChanges": "Отказаться", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Скачать файл", diff --git a/frontend/src/i18n/sk.json b/frontend/src/i18n/sk.json index a8e957de..d8b66b58 100644 --- a/frontend/src/i18n/sk.json +++ b/frontend/src/i18n/sk.json @@ -42,7 +42,8 @@ "update": "Aktualizovať", "upload": "Nahrať", "openFile": "Otvoriť súbor", - "discardChanges": "Zahodiť" + "discardChanges": "Zahodiť", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Stiahnuť súbor", diff --git a/frontend/src/i18n/sv-se.json b/frontend/src/i18n/sv-se.json index 015c106b..11315728 100644 --- a/frontend/src/i18n/sv-se.json +++ b/frontend/src/i18n/sv-se.json @@ -42,7 +42,8 @@ "update": "Uppdatera", "upload": "Ladda upp", "openFile": "Open file", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Ladda ner fil", diff --git a/frontend/src/i18n/tr.json b/frontend/src/i18n/tr.json index 1c4572c0..6b87681c 100644 --- a/frontend/src/i18n/tr.json +++ b/frontend/src/i18n/tr.json @@ -42,7 +42,8 @@ "update": "Güncelle", "upload": "Yükle", "openFile": "Dosyayı aç", - "discardChanges": "Discard" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Dosyayı indir", diff --git a/frontend/src/i18n/uk.json b/frontend/src/i18n/uk.json index 08bb9cfd..7cddd910 100644 --- a/frontend/src/i18n/uk.json +++ b/frontend/src/i18n/uk.json @@ -42,7 +42,8 @@ "update": "Оновити", "upload": "Вивантажити", "openFile": "Відкрити файл", - "discardChanges": "Скасувати" + "discardChanges": "Скасувати", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Завантажити файл", diff --git a/frontend/src/i18n/vi.json b/frontend/src/i18n/vi.json index e47e73c1..a84ea286 100644 --- a/frontend/src/i18n/vi.json +++ b/frontend/src/i18n/vi.json @@ -42,7 +42,8 @@ "update": "Cập nhật", "upload": "Tải lên", "openFile": "Mở tệp", - "discardChanges": "Hủy bỏ thay đổi" + "discardChanges": "Hủy bỏ thay đổi", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Tải xuống tệp tin", diff --git a/frontend/src/i18n/zh-cn.json b/frontend/src/i18n/zh-cn.json index fac470e8..c50e2d4e 100644 --- a/frontend/src/i18n/zh-cn.json +++ b/frontend/src/i18n/zh-cn.json @@ -42,7 +42,8 @@ "update": "更新", "upload": "上传", "openFile": "打开文件", - "discardChanges": "放弃更改" + "discardChanges": "放弃更改", + "saveChanges": "Save changes" }, "download": { "downloadFile": "下载文件", diff --git a/frontend/src/i18n/zh-tw.json b/frontend/src/i18n/zh-tw.json index 966cb14e..1522e28d 100644 --- a/frontend/src/i18n/zh-tw.json +++ b/frontend/src/i18n/zh-tw.json @@ -42,7 +42,8 @@ "update": "更新", "upload": "上傳", "openFile": "開啟檔案", - "discardChanges": "放棄變更" + "discardChanges": "放棄變更", + "saveChanges": "Save changes" }, "download": { "downloadFile": "下載檔案", From e6c674b3c616831942c4d4aacab0907d58003e23 Mon Sep 17 00:00:00 2001 From: MSomnium Studios <70982507+ArielLeyva@users.noreply.github.com> Date: Fri, 19 Sep 2025 09:09:26 -0400 Subject: [PATCH 028/206] fix: show login when session token expires --- frontend/src/css/login.css | 9 +++++++++ frontend/src/i18n/en.json | 5 ++++- frontend/src/stores/auth.ts | 5 +++++ frontend/src/utils/auth.ts | 24 ++++++++++++++++++++++-- frontend/src/views/Login.vue | 5 +++++ 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/frontend/src/css/login.css b/frontend/src/css/login.css index 14bfd1a5..62150ee6 100644 --- a/frontend/src/css/login.css +++ b/frontend/src/css/login.css @@ -45,6 +45,15 @@ animation: 0.2s opac forwards; } +#login .logout-message { + background: var(--icon-orange); + color: #fff; + padding: 0.5em; + text-align: center; + animation: 0.2s opac forwards; + text-transform: none; +} + @keyframes opac { 0% { opacity: 0; diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 4070619d..9411d91e 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -101,7 +101,10 @@ "submit": "Login", "username": "Username", "usernameTaken": "Username already taken", - "wrongCredentials": "Wrong credentials" + "wrongCredentials": "Wrong credentials", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanent", "prompts": { diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts index 459141ad..c33db87a 100644 --- a/frontend/src/stores/auth.ts +++ b/frontend/src/stores/auth.ts @@ -7,9 +7,11 @@ export const useAuthStore = defineStore("auth", { state: (): { user: IUser | null; jwt: string; + logoutTimer: number | null; } => ({ user: null, jwt: "", + logoutTimer: null, }), getters: { // user and jwt getter removed, no longer needed @@ -37,5 +39,8 @@ export const useAuthStore = defineStore("auth", { clearUser() { this.$reset(); }, + setLogoutTimer(logoutTimer: number | null) { + this.logoutTimer = logoutTimer; + }, }, }); diff --git a/frontend/src/utils/auth.ts b/frontend/src/utils/auth.ts index b868d90f..2b940cd4 100644 --- a/frontend/src/utils/auth.ts +++ b/frontend/src/utils/auth.ts @@ -16,6 +16,17 @@ export function parseToken(token: string) { const authStore = useAuthStore(); authStore.jwt = token; authStore.setUser(data.user); + + if (authStore.logoutTimer) { + clearTimeout(authStore.logoutTimer); + } + + const expiresAt = new Date(data.exp! * 1000); + authStore.setLogoutTimer( + window.setTimeout(() => { + logout("inactivity"); + }, expiresAt.getTime() - Date.now()) + ); } export async function validateLogin() { @@ -92,7 +103,7 @@ export async function signup(username: string, password: string) { } } -export function logout() { +export function logout(reason?: string) { document.cookie = "auth=; Max-Age=0; Path=/; SameSite=Strict;"; const authStore = useAuthStore(); @@ -102,6 +113,15 @@ export function logout() { if (noAuth) { window.location.reload(); } else { - router.push({ path: "/login" }); + if (typeof reason === "string" && reason.trim() !== "") { + router.push({ + path: "/login", + query: { "logout-reason": reason }, + }); + } else { + router.push({ + path: "/login", + }); + } } } diff --git a/frontend/src/views/Login.vue b/frontend/src/views/Login.vue index 5804789a..c0e78225 100644 --- a/frontend/src/views/Login.vue +++ b/frontend/src/views/Login.vue @@ -3,6 +3,9 @@
File Browser

{{ name }}

+

+ {{ t(`login.logout_reasons.${reason}`) }} +

{{ error }}
(createMode.value = !createMode.value); const $showError = inject("$showError")!; +const reason = route.query["logout-reason"] ?? null; + const submit = async (event: Event) => { event.preventDefault(); event.stopPropagation(); From 0eade717ce9d04bf48051922f11d983edbc7c2d0 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 21:32:15 +0200 Subject: [PATCH 029/206] feat: Updates for project File Browser (#5450) Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- frontend/src/i18n/ar.json | 5 ++++- frontend/src/i18n/ca.json | 5 ++++- frontend/src/i18n/cs.json | 5 ++++- frontend/src/i18n/de.json | 5 ++++- frontend/src/i18n/el.json | 5 ++++- frontend/src/i18n/es.json | 5 ++++- frontend/src/i18n/fa.json | 5 ++++- frontend/src/i18n/fr.json | 8 ++++++-- frontend/src/i18n/he.json | 5 ++++- frontend/src/i18n/hu.json | 5 ++++- frontend/src/i18n/is.json | 5 ++++- frontend/src/i18n/it.json | 5 ++++- frontend/src/i18n/ja.json | 5 ++++- frontend/src/i18n/ko.json | 5 ++++- frontend/src/i18n/nl-be.json | 5 ++++- frontend/src/i18n/no.json | 5 ++++- frontend/src/i18n/pl.json | 5 ++++- frontend/src/i18n/pt-br.json | 5 ++++- frontend/src/i18n/pt.json | 5 ++++- frontend/src/i18n/ro.json | 5 ++++- frontend/src/i18n/ru.json | 5 ++++- frontend/src/i18n/sk.json | 5 ++++- frontend/src/i18n/sv-se.json | 5 ++++- frontend/src/i18n/tr.json | 5 ++++- frontend/src/i18n/uk.json | 5 ++++- frontend/src/i18n/vi.json | 5 ++++- frontend/src/i18n/zh-cn.json | 5 ++++- frontend/src/i18n/zh-tw.json | 5 ++++- 28 files changed, 114 insertions(+), 29 deletions(-) diff --git a/frontend/src/i18n/ar.json b/frontend/src/i18n/ar.json index 7dcc555d..70feef51 100644 --- a/frontend/src/i18n/ar.json +++ b/frontend/src/i18n/ar.json @@ -101,7 +101,10 @@ "submit": "تسجيل دخول", "username": "إسم المستخدم", "usernameTaken": "إسم المستخدم غير متاح", - "wrongCredentials": "بيانات دخول خاطئة" + "wrongCredentials": "بيانات دخول خاطئة", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "دائم", "prompts": { diff --git a/frontend/src/i18n/ca.json b/frontend/src/i18n/ca.json index 6ba909df..4d698fa5 100644 --- a/frontend/src/i18n/ca.json +++ b/frontend/src/i18n/ca.json @@ -101,7 +101,10 @@ "submit": "Iniciar sessió", "username": "Usuari", "usernameTaken": "Nom d'usuari no disponible", - "wrongCredentials": "Usuari i/o contrasenya incorrectes" + "wrongCredentials": "Usuari i/o contrasenya incorrectes", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanent", "prompts": { diff --git a/frontend/src/i18n/cs.json b/frontend/src/i18n/cs.json index 58029d3a..c7e32842 100644 --- a/frontend/src/i18n/cs.json +++ b/frontend/src/i18n/cs.json @@ -101,7 +101,10 @@ "submit": "Přihlásit se", "username": "Uživatelské jméno", "usernameTaken": "Uživatelské jméno již existuje", - "wrongCredentials": "Nesprávné přihlašovací údaje" + "wrongCredentials": "Nesprávné přihlašovací údaje", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Trvalý", "prompts": { diff --git a/frontend/src/i18n/de.json b/frontend/src/i18n/de.json index aaa647de..d22a3be1 100644 --- a/frontend/src/i18n/de.json +++ b/frontend/src/i18n/de.json @@ -101,7 +101,10 @@ "submit": "Login", "username": "Benutzername", "usernameTaken": "Benutzername ist bereits vergeben", - "wrongCredentials": "Falsche Zugangsdaten" + "wrongCredentials": "Falsche Zugangsdaten", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanent", "prompts": { diff --git a/frontend/src/i18n/el.json b/frontend/src/i18n/el.json index 13150356..9fed72f1 100644 --- a/frontend/src/i18n/el.json +++ b/frontend/src/i18n/el.json @@ -101,7 +101,10 @@ "submit": "Είσοδος", "username": "Όνομα χρήστη", "usernameTaken": "Το όνομα χρήστη χρησιμοποιείται ήδη", - "wrongCredentials": "Λάθος όνομα ή/και κωδικός πρόσβασης" + "wrongCredentials": "Λάθος όνομα ή/και κωδικός πρόσβασης", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Μόνιμο", "prompts": { diff --git a/frontend/src/i18n/es.json b/frontend/src/i18n/es.json index 3ab1025d..e7f9e882 100644 --- a/frontend/src/i18n/es.json +++ b/frontend/src/i18n/es.json @@ -101,7 +101,10 @@ "submit": "Iniciar sesión", "username": "Usuario", "usernameTaken": "Nombre usuario no disponible", - "wrongCredentials": "Usuario y/o contraseña incorrectos" + "wrongCredentials": "Usuario y/o contraseña incorrectos", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanente", "prompts": { diff --git a/frontend/src/i18n/fa.json b/frontend/src/i18n/fa.json index eb8ef99e..70e10c12 100644 --- a/frontend/src/i18n/fa.json +++ b/frontend/src/i18n/fa.json @@ -101,7 +101,10 @@ "submit": "ورود", "username": "نام کاربری", "usernameTaken": "نام کاربری تکراری", - "wrongCredentials": "خطا در اعتبارسنجی" + "wrongCredentials": "خطا در اعتبارسنجی", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "دائمی", "prompts": { diff --git a/frontend/src/i18n/fr.json b/frontend/src/i18n/fr.json index c9110f66..16508807 100644 --- a/frontend/src/i18n/fr.json +++ b/frontend/src/i18n/fr.json @@ -42,7 +42,8 @@ "update": "Mettre à jour", "upload": "Importer", "openFile": "Ouvrir le fichier", - "discardChanges": "Annuler" + "discardChanges": "Annuler", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Télécharger le fichier", @@ -100,7 +101,10 @@ "submit": "Se connecter", "username": "Utilisateur·ice", "usernameTaken": "Le nom d'utilisateur·ice est déjà pris", - "wrongCredentials": "Identifiants incorrects !" + "wrongCredentials": "Identifiants incorrects !", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanent", "prompts": { diff --git a/frontend/src/i18n/he.json b/frontend/src/i18n/he.json index b7f13d88..a8e89a93 100644 --- a/frontend/src/i18n/he.json +++ b/frontend/src/i18n/he.json @@ -101,7 +101,10 @@ "submit": "התחברות", "username": "שם משתמש", "usernameTaken": "שם המשתמש כבר קיים", - "wrongCredentials": "פרטי התחברות שגויים" + "wrongCredentials": "פרטי התחברות שגויים", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "קבוע", "prompts": { diff --git a/frontend/src/i18n/hu.json b/frontend/src/i18n/hu.json index 2b426eb6..00fc419e 100644 --- a/frontend/src/i18n/hu.json +++ b/frontend/src/i18n/hu.json @@ -101,7 +101,10 @@ "submit": "Belépés", "username": "Felhasználói név", "usernameTaken": "A felhasználói név már foglalt", - "wrongCredentials": "Hibás hitelesítő adatok" + "wrongCredentials": "Hibás hitelesítő adatok", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Állandó", "prompts": { diff --git a/frontend/src/i18n/is.json b/frontend/src/i18n/is.json index c29ce698..c55455e5 100644 --- a/frontend/src/i18n/is.json +++ b/frontend/src/i18n/is.json @@ -101,7 +101,10 @@ "submit": "Innskráning", "username": "Notendanafn", "usernameTaken": "Þetta norendanafn er þegar í notkun", - "wrongCredentials": "Rangar notendaupplýsingar" + "wrongCredentials": "Rangar notendaupplýsingar", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Varanlegt", "prompts": { diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index 000bd8ce..995ba7cd 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -101,7 +101,10 @@ "submit": "Entra", "username": "Nome utente", "usernameTaken": "Username già usato", - "wrongCredentials": "Credenziali errate" + "wrongCredentials": "Credenziali errate", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanente", "prompts": { diff --git a/frontend/src/i18n/ja.json b/frontend/src/i18n/ja.json index 6ce903f7..99e4b017 100644 --- a/frontend/src/i18n/ja.json +++ b/frontend/src/i18n/ja.json @@ -101,7 +101,10 @@ "submit": "ログイン", "username": "ユーザー名", "usernameTaken": "ユーザー名はすでに取得されています", - "wrongCredentials": "ユーザー名またはパスワードが間違っています" + "wrongCredentials": "ユーザー名またはパスワードが間違っています", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "永久", "prompts": { diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json index 54307897..ec64bd62 100644 --- a/frontend/src/i18n/ko.json +++ b/frontend/src/i18n/ko.json @@ -101,7 +101,10 @@ "submit": "로그인", "username": "사용자 이름", "usernameTaken": "사용자 이름이 존재합니다", - "wrongCredentials": "사용자 이름 또는 비밀번호를 확인하십시오" + "wrongCredentials": "사용자 이름 또는 비밀번호를 확인하십시오", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "영구", "prompts": { diff --git a/frontend/src/i18n/nl-be.json b/frontend/src/i18n/nl-be.json index 860f12ed..c104ef81 100644 --- a/frontend/src/i18n/nl-be.json +++ b/frontend/src/i18n/nl-be.json @@ -101,7 +101,10 @@ "submit": "Log in", "username": "Gebruikersnaam", "usernameTaken": "Gebruikersnaam reeds in gebruik", - "wrongCredentials": "Verkeerde inloggegevens" + "wrongCredentials": "Verkeerde inloggegevens", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanent", "prompts": { diff --git a/frontend/src/i18n/no.json b/frontend/src/i18n/no.json index ae35e04e..b3ff472f 100644 --- a/frontend/src/i18n/no.json +++ b/frontend/src/i18n/no.json @@ -101,7 +101,10 @@ "submit": "Logg inn", "username": "Brukernavn", "usernameTaken": "Brukernavn er allerede i bruk", - "wrongCredentials": "Feil legitimasjon" + "wrongCredentials": "Feil legitimasjon", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanent", "prompts": { diff --git a/frontend/src/i18n/pl.json b/frontend/src/i18n/pl.json index 5837faa7..54dd9aed 100644 --- a/frontend/src/i18n/pl.json +++ b/frontend/src/i18n/pl.json @@ -101,7 +101,10 @@ "submit": "Zaloguj", "username": "Nazwa użytkownika", "usernameTaken": "Ta nazwa użytkownika jest zajęta", - "wrongCredentials": "Błędne dane logowania" + "wrongCredentials": "Błędne dane logowania", + "logout_reasons": { + "inactivity": "Wylogowano z powodu braku aktywności." + } }, "permanent": "Permanentny", "prompts": { diff --git a/frontend/src/i18n/pt-br.json b/frontend/src/i18n/pt-br.json index ccce0f4d..8e314c77 100644 --- a/frontend/src/i18n/pt-br.json +++ b/frontend/src/i18n/pt-br.json @@ -101,7 +101,10 @@ "submit": "Login", "username": "Nome do usuário", "usernameTaken": "Nome de usuário já existe", - "wrongCredentials": "Ops! Dados incorretos." + "wrongCredentials": "Ops! Dados incorretos.", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanente", "prompts": { diff --git a/frontend/src/i18n/pt.json b/frontend/src/i18n/pt.json index 7babc212..4c719cc9 100644 --- a/frontend/src/i18n/pt.json +++ b/frontend/src/i18n/pt.json @@ -101,7 +101,10 @@ "submit": "Entrar na conta", "username": "Nome de utilizador", "usernameTaken": "O nome de utilizador já está registado", - "wrongCredentials": "Dados errados" + "wrongCredentials": "Dados errados", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanente", "prompts": { diff --git a/frontend/src/i18n/ro.json b/frontend/src/i18n/ro.json index b03d8c21..232b0e4d 100644 --- a/frontend/src/i18n/ro.json +++ b/frontend/src/i18n/ro.json @@ -101,7 +101,10 @@ "submit": "Autentificare", "username": "Utilizator", "usernameTaken": "Utilizatorul există", - "wrongCredentials": "Informații greșite" + "wrongCredentials": "Informații greșite", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanent", "prompts": { diff --git a/frontend/src/i18n/ru.json b/frontend/src/i18n/ru.json index 3a9ff33a..931cf68d 100644 --- a/frontend/src/i18n/ru.json +++ b/frontend/src/i18n/ru.json @@ -101,7 +101,10 @@ "submit": "Войти", "username": "Имя пользователя", "usernameTaken": "Данное имя пользователя уже занято", - "wrongCredentials": "Неверные данные" + "wrongCredentials": "Неверные данные", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Постоянный", "prompts": { diff --git a/frontend/src/i18n/sk.json b/frontend/src/i18n/sk.json index d8b66b58..2f01ef8c 100644 --- a/frontend/src/i18n/sk.json +++ b/frontend/src/i18n/sk.json @@ -101,7 +101,10 @@ "submit": "Prihlásiť", "username": "Používateľské meno", "usernameTaken": "Meno je už obsadené", - "wrongCredentials": "Nesprávne prihlasovacie údaje" + "wrongCredentials": "Nesprávne prihlasovacie údaje", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Trvalé", "prompts": { diff --git a/frontend/src/i18n/sv-se.json b/frontend/src/i18n/sv-se.json index 11315728..319b7eb2 100644 --- a/frontend/src/i18n/sv-se.json +++ b/frontend/src/i18n/sv-se.json @@ -101,7 +101,10 @@ "submit": "Logga in", "username": "Användarnamn", "usernameTaken": "Användarnamn upptaget", - "wrongCredentials": "Fel inloggning" + "wrongCredentials": "Fel inloggning", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Permanent", "prompts": { diff --git a/frontend/src/i18n/tr.json b/frontend/src/i18n/tr.json index 6b87681c..aa0d3558 100644 --- a/frontend/src/i18n/tr.json +++ b/frontend/src/i18n/tr.json @@ -101,7 +101,10 @@ "submit": "Giriş", "username": "Kullanıcı adı", "usernameTaken": "Kullanıcı adı mevcut", - "wrongCredentials": "Yanlış hesap bilgileri" + "wrongCredentials": "Yanlış hesap bilgileri", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Kalıcı", "prompts": { diff --git a/frontend/src/i18n/uk.json b/frontend/src/i18n/uk.json index 7cddd910..d3f01c9f 100644 --- a/frontend/src/i18n/uk.json +++ b/frontend/src/i18n/uk.json @@ -101,7 +101,10 @@ "submit": "Увійти", "username": "Ім'я користувача", "usernameTaken": "Ім'я користувача вже використовується", - "wrongCredentials": "Неправильне ім'я користувача або пароль" + "wrongCredentials": "Неправильне ім'я користувача або пароль", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Постійний", "prompts": { diff --git a/frontend/src/i18n/vi.json b/frontend/src/i18n/vi.json index a84ea286..380f98ff 100644 --- a/frontend/src/i18n/vi.json +++ b/frontend/src/i18n/vi.json @@ -101,7 +101,10 @@ "submit": "Đăng nhập", "username": "Tên người dùng", "usernameTaken": "Tên người dùng đã tồn tại", - "wrongCredentials": "Thông tin đăng nhập không đúng" + "wrongCredentials": "Thông tin đăng nhập không đúng", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "Vĩnh viễn", "prompts": { diff --git a/frontend/src/i18n/zh-cn.json b/frontend/src/i18n/zh-cn.json index c50e2d4e..c18c7e98 100644 --- a/frontend/src/i18n/zh-cn.json +++ b/frontend/src/i18n/zh-cn.json @@ -101,7 +101,10 @@ "submit": "登录", "username": "用户名", "usernameTaken": "用户名已经被使用", - "wrongCredentials": "用户名或密码错误" + "wrongCredentials": "用户名或密码错误", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "永久", "prompts": { diff --git a/frontend/src/i18n/zh-tw.json b/frontend/src/i18n/zh-tw.json index 1522e28d..adcfde91 100644 --- a/frontend/src/i18n/zh-tw.json +++ b/frontend/src/i18n/zh-tw.json @@ -101,7 +101,10 @@ "submit": "登入", "username": "帳號", "usernameTaken": "用戶名已存在", - "wrongCredentials": "帳號或密碼錯誤" + "wrongCredentials": "帳號或密碼錯誤", + "logout_reasons": { + "inactivity": "You have been logged out due to inactivity." + } }, "permanent": "永久", "prompts": { From dec7a027378fbc6948d203199c44a640a141bcad Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:26:24 +0000 Subject: [PATCH 030/206] feat: Translate frontend/src/i18n/en.json in no 100% translated source file: 'frontend/src/i18n/en.json' on 'no'. --- frontend/src/i18n/no.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/i18n/no.json b/frontend/src/i18n/no.json index b3ff472f..a3803ae9 100644 --- a/frontend/src/i18n/no.json +++ b/frontend/src/i18n/no.json @@ -103,7 +103,7 @@ "usernameTaken": "Brukernavn er allerede i bruk", "wrongCredentials": "Feil legitimasjon", "logout_reasons": { - "inactivity": "You have been logged out due to inactivity." + "inactivity": "Du har blitt logget ut på grunn av inaktivitet" } }, "permanent": "Permanent", From b9787c78f3889171f94db19e7655dce68c64b6fb Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 25 Sep 2025 16:47:00 +0200 Subject: [PATCH 031/206] feat: allow setting ace editor theme (#3826) Co-authored-by: Henrique Dias --- cmd/config.go | 1 + cmd/root.go | 7 +++-- cmd/users.go | 3 ++ .../components/settings/AceEditorTheme.vue | 24 ++++++++++++++ frontend/src/i18n/en.json | 1 + frontend/src/types/settings.d.ts | 1 + frontend/src/types/user.d.ts | 1 + frontend/src/utils/theme.ts | 16 ++++++++++ frontend/src/views/files/Editor.vue | 15 +++++---- frontend/src/views/settings/Profile.vue | 14 ++++++++- http/auth.go | 2 ++ settings/defaults.go | 20 ++++++------ tools/package.json | 3 +- users/users.go | 31 ++++++++++--------- 14 files changed, 104 insertions(+), 35 deletions(-) create mode 100644 frontend/src/components/settings/AceEditorTheme.vue diff --git a/cmd/config.go b/cmd/config.go index 5ce54ad9..ebb9c69f 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -221,6 +221,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut fmt.Fprintf(w, "\tFile Creation Mode:\t%O\n", set.FileMode) fmt.Fprintf(w, "\tDirectory Creation Mode:\t%O\n", set.DirMode) fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.Defaults.Commands, " ")) + fmt.Fprintf(w, "\tAce editor syntax highlighting theme:\t%s\n", set.Defaults.AceEditorTheme) fmt.Fprintf(w, "\tSorting:\n") fmt.Fprintf(w, "\t\tBy:\t%s\n", set.Defaults.Sorting.By) fmt.Fprintf(w, "\t\tAsc:\t%t\n", set.Defaults.Sorting.Asc) diff --git a/cmd/root.go b/cmd/root.go index 286f6343..a9704cf4 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -424,9 +424,10 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) error { MinimumPasswordLength: settings.DefaultMinimumPasswordLength, UserHomeBasePath: settings.DefaultUsersHomeBasePath, Defaults: settings.UserDefaults{ - Scope: ".", - Locale: "en", - SingleClick: false, + Scope: ".", + Locale: "en", + SingleClick: false, + AceEditorTheme: getStringParam(flags, "defaults.aceEditorTheme"), Perm: users.Permissions{ Admin: false, Execute: true, diff --git a/cmd/users.go b/cmd/users.go index dd3d1f52..5b458a5a 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -79,6 +79,7 @@ func addUserFlags(flags *pflag.FlagSet) { flags.Bool("singleClick", false, "use single clicks only") flags.Bool("dateFormat", false, "use date format (true for absolute time, false for relative)") flags.Bool("hideDotfiles", false, "hide dotfiles") + flags.String("aceEditorTheme", "", "ace editor's syntax highlighting theme for users") } func getViewMode(flags *pflag.FlagSet) (users.ViewMode, error) { @@ -110,6 +111,8 @@ func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all defaults.ViewMode, err = getViewMode(flags) case "singleClick": defaults.SingleClick, err = getBool(flags, flag.Name) + case "aceEditorTheme": + defaults.AceEditorTheme, err = getString(flags, flag.Name) case "perm.admin": defaults.Perm.Admin, err = getBool(flags, flag.Name) case "perm.execute": diff --git a/frontend/src/components/settings/AceEditorTheme.vue b/frontend/src/components/settings/AceEditorTheme.vue new file mode 100644 index 00000000..09efe48b --- /dev/null +++ b/frontend/src/components/settings/AceEditorTheme.vue @@ -0,0 +1,24 @@ + + + diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 9411d91e..b6325511 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Execute commands", diff --git a/frontend/src/types/settings.d.ts b/frontend/src/types/settings.d.ts index 90ca6ae7..ba56c612 100644 --- a/frontend/src/types/settings.d.ts +++ b/frontend/src/types/settings.d.ts @@ -21,6 +21,7 @@ interface SettingsDefaults { commands: any[]; hideDotfiles: boolean; dateFormat: boolean; + aceEditorTheme: string; } interface SettingsBranding { diff --git a/frontend/src/types/user.d.ts b/frontend/src/types/user.d.ts index b81806fc..40c453c5 100644 --- a/frontend/src/types/user.d.ts +++ b/frontend/src/types/user.d.ts @@ -13,6 +13,7 @@ interface IUser { dateFormat: boolean; viewMode: ViewModeType; sorting?: Sorting; + aceEditorTheme: string; } type ViewModeType = "list" | "mosaic" | "mosaic gallery"; diff --git a/frontend/src/utils/theme.ts b/frontend/src/utils/theme.ts index 8058356a..0244b044 100644 --- a/frontend/src/utils/theme.ts +++ b/frontend/src/utils/theme.ts @@ -1,4 +1,6 @@ import { theme } from "./constants"; +import "ace-builds"; +import { themesByName } from "ace-builds/src-noconflict/ext-themelist"; export const getTheme = (): UserTheme => { return (document.documentElement.className as UserTheme) || theme; @@ -32,3 +34,17 @@ export const getMediaPreference = (): UserTheme => { return "light"; } }; + +export const getEditorTheme = (themeName: string) => { + if (!themeName.startsWith("ace/theme/")) { + themeName = `ace/theme/${themeName}`; + } + const themeKey = themeName.replace("ace/theme/", ""); + if (themesByName[themeKey] !== undefined) { + return themeName; + } else if (getTheme() === "dark") { + return "ace/theme/twilight"; + } else { + return "ace/theme/chrome"; + } +}; diff --git a/frontend/src/views/files/Editor.vue b/frontend/src/views/files/Editor.vue index 13013a9f..f3d9aa94 100644 --- a/frontend/src/views/files/Editor.vue +++ b/frontend/src/views/files/Editor.vue @@ -69,7 +69,7 @@ import HeaderBar from "@/components/header/HeaderBar.vue"; import { useAuthStore } from "@/stores/auth"; import { useFileStore } from "@/stores/file"; import { useLayoutStore } from "@/stores/layout"; -import { getTheme } from "@/utils/theme"; +import { getEditorTheme } from "@/utils/theme"; import { marked } from "marked"; import { inject, onBeforeUnmount, onMounted, ref, watchEffect } from "vue"; import { useI18n } from "vue-i18n"; @@ -122,7 +122,7 @@ onMounted(() => { value: fileContent, showPrintMargin: false, readOnly: fileStore.req?.type === "textImmutable", - theme: "ace/theme/chrome", + theme: getEditorTheme(authStore.user?.aceEditorTheme ?? ""), mode: modelist.getModeForPath(fileStore.req!.name).mode, wrap: true, enableBasicAutocompletion: true, @@ -130,10 +130,6 @@ onMounted(() => { enableSnippets: true, }); - if (getTheme() === "dark") { - editor.value!.setTheme("ace/theme/twilight"); - } - editor.value.setFontSize(fontSize.value); editor.value.focus(); }); @@ -219,6 +215,13 @@ const decreaseFontSize = () => { }; const close = () => { + if (!editor.value?.session.getUndoManager().isClean()) { + layoutStore.showHover("discardEditorChanges"); + return; + } + + fileStore.updateRequest(null); + const uri = url.removeLastDir(route.path) + "/"; router.push({ path: uri }); }; diff --git a/frontend/src/views/settings/Profile.vue b/frontend/src/views/settings/Profile.vue index c677092f..1b079473 100644 --- a/frontend/src/views/settings/Profile.vue +++ b/frontend/src/views/settings/Profile.vue @@ -24,6 +24,13 @@ class="input input--block" v-model:locale="locale" > + +

{{ t("settings.aceEditorTheme") }}

+
@@ -81,6 +88,7 @@ import { useAuthStore } from "@/stores/auth"; import { useLayoutStore } from "@/stores/layout"; import { users as api } from "@/api"; +import AceEditorTheme from "@/components/settings/AceEditorTheme.vue"; import Languages from "@/components/settings/Languages.vue"; import { computed, inject, onMounted, ref } from "vue"; import { useI18n } from "vue-i18n"; @@ -98,6 +106,7 @@ const hideDotfiles = ref(false); const singleClick = ref(false); const dateFormat = ref(false); const locale = ref(""); +const aceEditorTheme = ref(""); const passwordClass = computed(() => { const baseClass = "input input--block"; @@ -113,13 +122,14 @@ const passwordClass = computed(() => { return `${baseClass} input--red`; }); -onMounted(() => { +onMounted(async () => { layoutStore.loading = true; if (authStore.user === null) return false; locale.value = authStore.user.locale; hideDotfiles.value = authStore.user.hideDotfiles; singleClick.value = authStore.user.singleClick; dateFormat.value = authStore.user.dateFormat; + aceEditorTheme.value = authStore.user.aceEditorTheme; layoutStore.loading = false; return true; }); @@ -163,6 +173,7 @@ const updateSettings = async (event: Event) => { hideDotfiles: hideDotfiles.value, singleClick: singleClick.value, dateFormat: dateFormat.value, + aceEditorTheme: aceEditorTheme.value, }; await api.update(data, [ @@ -170,6 +181,7 @@ const updateSettings = async (event: Event) => { "hideDotfiles", "singleClick", "dateFormat", + "aceEditorTheme", ]); authStore.updateUser(data); $showSuccess(t("settings.settingsUpdated")); diff --git a/http/auth.go b/http/auth.go index 0ecaed14..62d6779e 100644 --- a/http/auth.go +++ b/http/auth.go @@ -31,6 +31,7 @@ type userInfo struct { HideDotfiles bool `json:"hideDotfiles"` DateFormat bool `json:"dateFormat"` Username string `json:"username"` + AceEditorTheme string `json:"aceEditorTheme"` } type authToken struct { @@ -200,6 +201,7 @@ func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.Use HideDotfiles: user.HideDotfiles, DateFormat: user.DateFormat, Username: user.Username, + AceEditorTheme: user.AceEditorTheme, }, RegisteredClaims: jwt.RegisteredClaims{ IssuedAt: jwt.NewNumericDate(time.Now()), diff --git a/settings/defaults.go b/settings/defaults.go index d60e36dc..5b6c3f2a 100644 --- a/settings/defaults.go +++ b/settings/defaults.go @@ -8,15 +8,16 @@ import ( // UserDefaults is a type that holds the default values // for some fields on User. type UserDefaults struct { - Scope string `json:"scope"` - Locale string `json:"locale"` - ViewMode users.ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Sorting files.Sorting `json:"sorting"` - Perm users.Permissions `json:"perm"` - Commands []string `json:"commands"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` + Scope string `json:"scope"` + Locale string `json:"locale"` + ViewMode users.ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Sorting files.Sorting `json:"sorting"` + Perm users.Permissions `json:"perm"` + Commands []string `json:"commands"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` + AceEditorTheme string `json:"aceEditorTheme"` } // Apply applies the default options to a user. @@ -30,4 +31,5 @@ func (d *UserDefaults) Apply(u *users.User) { u.Commands = d.Commands u.HideDotfiles = d.HideDotfiles u.DateFormat = d.DateFormat + u.AceEditorTheme = d.AceEditorTheme } diff --git a/tools/package.json b/tools/package.json index 9a2bd1c6..9433b94e 100644 --- a/tools/package.json +++ b/tools/package.json @@ -3,5 +3,6 @@ "@commitlint/cli": "^15.0.0", "@commitlint/config-conventional": "^15.0.0", "standard-version": "^9.3.2" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/users/users.go b/users/users.go index e0310f21..020faf11 100644 --- a/users/users.go +++ b/users/users.go @@ -20,21 +20,22 @@ const ( // User describes a user. type User struct { - ID uint `storm:"id,increment" json:"id"` - Username string `storm:"unique" json:"username"` - Password string `json:"password"` - Scope string `json:"scope"` - Locale string `json:"locale"` - LockPassword bool `json:"lockPassword"` - ViewMode ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Perm Permissions `json:"perm"` - Commands []string `json:"commands"` - Sorting files.Sorting `json:"sorting"` - Fs afero.Fs `json:"-" yaml:"-"` - Rules []rules.Rule `json:"rules"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` + ID uint `storm:"id,increment" json:"id"` + Username string `storm:"unique" json:"username"` + Password string `json:"password"` + Scope string `json:"scope"` + Locale string `json:"locale"` + LockPassword bool `json:"lockPassword"` + ViewMode ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Perm Permissions `json:"perm"` + Commands []string `json:"commands"` + Sorting files.Sorting `json:"sorting"` + Fs afero.Fs `json:"-" yaml:"-"` + Rules []rules.Rule `json:"rules"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` + AceEditorTheme string `json:"aceEditorTheme"` } // GetRules implements rules.Provider. From 692ca5eaf01e4dcf346ba03f82c5dbd50cce246b Mon Sep 17 00:00:00 2001 From: MSomnium Studios <70982507+ArielLeyva@users.noreply.github.com> Date: Thu, 25 Sep 2025 10:54:28 -0400 Subject: [PATCH 032/206] fix(upload): throttle upload speed calculation to 100ms to avoid Infinity MB/s (#5456) Co-authored-by: Henrique Dias --- .../src/components/prompts/UploadFiles.vue | 29 ++++++++++++-- http/auth.go | 40 +++++++++---------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/prompts/UploadFiles.vue b/frontend/src/components/prompts/UploadFiles.vue index 883fffe3..4d96d5bb 100644 --- a/frontend/src/components/prompts/UploadFiles.vue +++ b/frontend/src/components/prompts/UploadFiles.vue @@ -14,7 +14,7 @@ }}
-
{{ speedMbytes }}/s
+
{{ speedText }}/s
{{ formattedETA }} remaining
{{ sentPercent }}% Completed
@@ -88,6 +88,7 @@ const uploadStore = useUploadStore(); const { sentBytes, totalBytes } = storeToRefs(uploadStore); const byteToMbyte = partial({ exponent: 2 }); +const byteToKbyte = partial({ exponent: 1 }); const sentPercent = computed(() => ((uploadStore.sentBytes / uploadStore.totalBytes) * 100).toFixed(2) @@ -95,11 +96,33 @@ const sentPercent = computed(() => const sentMbytes = computed(() => byteToMbyte(uploadStore.sentBytes)); const totalMbytes = computed(() => byteToMbyte(uploadStore.totalBytes)); -const speedMbytes = computed(() => byteToMbyte(speed.value)); +const speedText = computed(() => { + const bytes = speed.value; + + if (bytes < 1024 * 1024) { + const kb = parseFloat(byteToKbyte(bytes)); + return `${kb.toFixed(2)} KB`; + } else { + const mb = parseFloat(byteToMbyte(bytes)); + return `${mb.toFixed(2)} MB`; + } +}); let lastSpeedUpdate: number = 0; let recentSpeeds: number[] = []; +let lastThrottleTime = 0; + +const throttledCalculateSpeed = (sentBytes: number, oldSentBytes: number) => { + const now = Date.now(); + if (now - lastThrottleTime < 100) { + return; + } + + lastThrottleTime = now; + calculateSpeed(sentBytes, oldSentBytes); +}; + const calculateSpeed = (sentBytes: number, oldSentBytes: number) => { // Reset the state when the uploads batch is complete if (sentBytes === 0) { @@ -149,7 +172,7 @@ const calculateEta = () => { eta.value = remainingSize / speedBytesPerSecond; }; -watch(sentBytes, calculateSpeed); +watch(sentBytes, throttledCalculateSpeed); watch(totalBytes, (totalBytes, oldTotalBytes) => { if (oldTotalBytes !== 0) { diff --git a/http/auth.go b/http/auth.go index 62d6779e..18d10025 100644 --- a/http/auth.go +++ b/http/auth.go @@ -21,16 +21,16 @@ const ( ) type userInfo struct { - ID uint `json:"id"` - Locale string `json:"locale"` - ViewMode users.ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Perm users.Permissions `json:"perm"` - Commands []string `json:"commands"` - LockPassword bool `json:"lockPassword"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` - Username string `json:"username"` + ID uint `json:"id"` + Locale string `json:"locale"` + ViewMode users.ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Perm users.Permissions `json:"perm"` + Commands []string `json:"commands"` + LockPassword bool `json:"lockPassword"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` + Username string `json:"username"` AceEditorTheme string `json:"aceEditorTheme"` } @@ -191,16 +191,16 @@ func renewHandler(tokenExpireTime time.Duration) handleFunc { func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.User, tokenExpirationTime time.Duration) (int, error) { claims := &authToken{ User: userInfo{ - ID: user.ID, - Locale: user.Locale, - ViewMode: user.ViewMode, - SingleClick: user.SingleClick, - Perm: user.Perm, - LockPassword: user.LockPassword, - Commands: user.Commands, - HideDotfiles: user.HideDotfiles, - DateFormat: user.DateFormat, - Username: user.Username, + ID: user.ID, + Locale: user.Locale, + ViewMode: user.ViewMode, + SingleClick: user.SingleClick, + Perm: user.Perm, + LockPassword: user.LockPassword, + Commands: user.Commands, + HideDotfiles: user.HideDotfiles, + DateFormat: user.DateFormat, + Username: user.Username, AceEditorTheme: user.AceEditorTheme, }, RegisteredClaims: jwt.RegisteredClaims{ From d29ad356d1067c87b2821debab91286549f512a0 Mon Sep 17 00:00:00 2001 From: MSomnium Studios <70982507+ArielLeyva@users.noreply.github.com> Date: Thu, 25 Sep 2025 10:57:30 -0400 Subject: [PATCH 033/206] feat: Improved path display in the new file and directory modal (#5451) --- .../src/components/prompts/CreateFilePath.vue | 87 +++++++++++++++++++ frontend/src/components/prompts/NewDir.vue | 2 + frontend/src/components/prompts/NewFile.vue | 2 + 3 files changed, 91 insertions(+) create mode 100644 frontend/src/components/prompts/CreateFilePath.vue diff --git a/frontend/src/components/prompts/CreateFilePath.vue b/frontend/src/components/prompts/CreateFilePath.vue new file mode 100644 index 00000000..9636b6cc --- /dev/null +++ b/frontend/src/components/prompts/CreateFilePath.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/frontend/src/components/prompts/NewDir.vue b/frontend/src/components/prompts/NewDir.vue index 1eb6d481..85d47bb8 100644 --- a/frontend/src/components/prompts/NewDir.vue +++ b/frontend/src/components/prompts/NewDir.vue @@ -14,6 +14,7 @@ v-model.trim="name" tabindex="1" /> +
@@ -48,6 +49,7 @@ import { files as api } from "@/api"; import url from "@/utils/url"; import { useRoute, useRouter } from "vue-router"; import { useI18n } from "vue-i18n"; +import CreateFilePath from "@/components/prompts/CreateFilePath.vue"; const $showError = inject("$showError")!; diff --git a/frontend/src/components/prompts/NewFile.vue b/frontend/src/components/prompts/NewFile.vue index b7c05d44..d3fb34ed 100644 --- a/frontend/src/components/prompts/NewFile.vue +++ b/frontend/src/components/prompts/NewFile.vue @@ -13,6 +13,7 @@ @keyup.enter="submit" v-model.trim="name" /> +
@@ -42,6 +43,7 @@ import { useI18n } from "vue-i18n"; import { useRoute, useRouter } from "vue-router"; import { useFileStore } from "@/stores/file"; import { useLayoutStore } from "@/stores/layout"; +import CreateFilePath from "@/components/prompts/CreateFilePath.vue"; import { files as api } from "@/api"; import url from "@/utils/url"; From c4725428e07da72b855009e2c13c6ed91d32e0b7 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 25 Sep 2025 17:09:16 +0200 Subject: [PATCH 034/206] fix: computation of file path --- frontend/src/components/prompts/CreateFilePath.vue | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/prompts/CreateFilePath.vue b/frontend/src/components/prompts/CreateFilePath.vue index 9636b6cc..ec470f3a 100644 --- a/frontend/src/components/prompts/CreateFilePath.vue +++ b/frontend/src/components/prompts/CreateFilePath.vue @@ -41,12 +41,11 @@ const container = ref(null); const path = computed(() => { let basePath = fileStore.isFiles ? route.path : url.removeLastDir(route.path); + if (!basePath.endsWith("/")) { + basePath += "/"; + } basePath += props.name; - - return basePath - .replace(/^\/[^\/]+/, "") - .split("/") - .filter(Boolean); + return basePath.split("/").filter(Boolean).splice(1); }); watch(path, () => { From 949ddffef20e38169902c5fd74dca4815dcecf11 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 25 Sep 2025 17:13:30 +0200 Subject: [PATCH 035/206] fix: some formatting issues with i18n files --- frontend/src/i18n/ar.json | 4 ++-- frontend/src/i18n/ca.json | 4 ++-- frontend/src/i18n/cs.json | 4 ++-- frontend/src/i18n/de.json | 4 ++-- frontend/src/i18n/el.json | 4 ++-- frontend/src/i18n/en.json | 4 ++-- frontend/src/i18n/es.json | 4 ++-- frontend/src/i18n/fa.json | 4 ++-- frontend/src/i18n/fr.json | 4 ++-- frontend/src/i18n/he.json | 4 ++-- frontend/src/i18n/hu.json | 4 ++-- frontend/src/i18n/is.json | 4 ++-- frontend/src/i18n/it.json | 4 ++-- frontend/src/i18n/ja.json | 4 ++-- frontend/src/i18n/ko.json | 4 ++-- frontend/src/i18n/nl-be.json | 4 ++-- frontend/src/i18n/no.json | 4 ++-- frontend/src/i18n/pl.json | 4 ++-- frontend/src/i18n/pt-br.json | 4 ++-- frontend/src/i18n/pt.json | 4 ++-- frontend/src/i18n/ro.json | 4 ++-- frontend/src/i18n/ru.json | 4 ++-- frontend/src/i18n/sk.json | 4 ++-- frontend/src/i18n/sv-se.json | 4 ++-- frontend/src/i18n/tr.json | 4 ++-- frontend/src/i18n/uk.json | 4 ++-- frontend/src/i18n/vi.json | 4 ++-- frontend/src/i18n/zh-cn.json | 4 ++-- frontend/src/i18n/zh-tw.json | 4 ++-- 29 files changed, 58 insertions(+), 58 deletions(-) diff --git a/frontend/src/i18n/ar.json b/frontend/src/i18n/ar.json index 70feef51..9b06d2d3 100644 --- a/frontend/src/i18n/ar.json +++ b/frontend/src/i18n/ar.json @@ -42,8 +42,8 @@ "update": "تحديث", "upload": "رفع", "openFile": "فتح الملف", - "discardChanges": "إلغاء التغييرات", - "saveChanges": "Save changes" + "discardChanges": "إلغاء التغييرات", + "saveChanges": "Save changes" }, "download": { "downloadFile": "تحميل الملف", diff --git a/frontend/src/i18n/ca.json b/frontend/src/i18n/ca.json index 4d698fa5..353eeb22 100644 --- a/frontend/src/i18n/ca.json +++ b/frontend/src/i18n/ca.json @@ -42,8 +42,8 @@ "update": "Actualitzar", "upload": "Pujar", "openFile": "Obrir fitxer", - "discardChanges": "Descartar", - "saveChanges": "Save changes" + "discardChanges": "Descartar", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarregar fitxer", diff --git a/frontend/src/i18n/cs.json b/frontend/src/i18n/cs.json index c7e32842..635a1d96 100644 --- a/frontend/src/i18n/cs.json +++ b/frontend/src/i18n/cs.json @@ -42,8 +42,8 @@ "update": "Aktualizovat", "upload": "Nahrát", "openFile": "Otevřít soubor", - "discardChanges": "Zrušit změny", - "saveChanges": "Save changes" + "discardChanges": "Zrušit změny", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Stáhnout soubor", diff --git a/frontend/src/i18n/de.json b/frontend/src/i18n/de.json index d22a3be1..40971820 100644 --- a/frontend/src/i18n/de.json +++ b/frontend/src/i18n/de.json @@ -42,8 +42,8 @@ "update": "Update", "upload": "Upload", "openFile": "Datei öffnen", - "discardChanges": "Verwerfen", - "saveChanges": "Save changes" + "discardChanges": "Verwerfen", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Download Datei", diff --git a/frontend/src/i18n/el.json b/frontend/src/i18n/el.json index 9fed72f1..ba75606f 100644 --- a/frontend/src/i18n/el.json +++ b/frontend/src/i18n/el.json @@ -42,8 +42,8 @@ "update": "Ενημέρωση", "upload": "Μεταφόρτωση", "openFile": "Άνοιγμα αρχείου", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Λήψη αρχείου", diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index b6325511..15a297df 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -42,8 +42,8 @@ "update": "Update", "upload": "Upload", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Download File", diff --git a/frontend/src/i18n/es.json b/frontend/src/i18n/es.json index e7f9e882..a3565f4f 100644 --- a/frontend/src/i18n/es.json +++ b/frontend/src/i18n/es.json @@ -42,8 +42,8 @@ "update": "Actualizar", "upload": "Subir", "openFile": "Abrir archivo", - "discardChanges": "Discard", - "saveChanges": "Guardar cambios" + "discardChanges": "Discard", + "saveChanges": "Guardar cambios" }, "download": { "downloadFile": "Descargar fichero", diff --git a/frontend/src/i18n/fa.json b/frontend/src/i18n/fa.json index 70e10c12..e4a2532e 100644 --- a/frontend/src/i18n/fa.json +++ b/frontend/src/i18n/fa.json @@ -42,8 +42,8 @@ "update": "به روز سانی", "upload": "آپلود", "openFile": "باز کردن فایل", - "discardChanges": "لغو کردن", - "saveChanges": "Save changes" + "discardChanges": "لغو کردن", + "saveChanges": "Save changes" }, "download": { "downloadFile": "دانلود فایل", diff --git a/frontend/src/i18n/fr.json b/frontend/src/i18n/fr.json index 16508807..fcbd239b 100644 --- a/frontend/src/i18n/fr.json +++ b/frontend/src/i18n/fr.json @@ -42,8 +42,8 @@ "update": "Mettre à jour", "upload": "Importer", "openFile": "Ouvrir le fichier", - "discardChanges": "Annuler", - "saveChanges": "Save changes" + "discardChanges": "Annuler", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Télécharger le fichier", diff --git a/frontend/src/i18n/he.json b/frontend/src/i18n/he.json index a8e89a93..9bb3145a 100644 --- a/frontend/src/i18n/he.json +++ b/frontend/src/i18n/he.json @@ -42,8 +42,8 @@ "update": "עדכון", "upload": "העלאה", "openFile": "פתח קובץ", - "discardChanges": "זריקת השינויים", - "saveChanges": "Save changes" + "discardChanges": "זריקת השינויים", + "saveChanges": "Save changes" }, "download": { "downloadFile": "הורד קובץ", diff --git a/frontend/src/i18n/hu.json b/frontend/src/i18n/hu.json index 00fc419e..0971d9cc 100644 --- a/frontend/src/i18n/hu.json +++ b/frontend/src/i18n/hu.json @@ -42,8 +42,8 @@ "update": "Frissítés", "upload": "Feltöltés", "openFile": "Fájl megnyitása", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Fájl letöltése", diff --git a/frontend/src/i18n/is.json b/frontend/src/i18n/is.json index c55455e5..65a5eb00 100644 --- a/frontend/src/i18n/is.json +++ b/frontend/src/i18n/is.json @@ -42,8 +42,8 @@ "update": "Vista", "upload": "Hlaða upp", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Sækja skjal", diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index 995ba7cd..b1135aac 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -42,8 +42,8 @@ "update": "Aggiorna", "upload": "Carica", "openFile": "Apri file", - "discardChanges": "Ignora", - "saveChanges": "Save changes" + "discardChanges": "Ignora", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Scarica file", diff --git a/frontend/src/i18n/ja.json b/frontend/src/i18n/ja.json index 99e4b017..574bf59a 100644 --- a/frontend/src/i18n/ja.json +++ b/frontend/src/i18n/ja.json @@ -42,8 +42,8 @@ "update": "更新", "upload": "アップロード", "openFile": "ファイルを開く", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "ファイルのダウンロード", diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json index ec64bd62..ea5a1e67 100644 --- a/frontend/src/i18n/ko.json +++ b/frontend/src/i18n/ko.json @@ -42,8 +42,8 @@ "update": "업데이트", "upload": "업로드", "openFile": "파일 열기", - "discardChanges": "변경 사항 취소", - "saveChanges": "변경사항 저장" + "discardChanges": "변경 사항 취소", + "saveChanges": "변경사항 저장" }, "download": { "downloadFile": "파일 다운로드", diff --git a/frontend/src/i18n/nl-be.json b/frontend/src/i18n/nl-be.json index c104ef81..af659e5c 100644 --- a/frontend/src/i18n/nl-be.json +++ b/frontend/src/i18n/nl-be.json @@ -42,8 +42,8 @@ "update": "Updaten", "upload": "Uploaden", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Bestand downloaden", diff --git a/frontend/src/i18n/no.json b/frontend/src/i18n/no.json index a3803ae9..08c6992c 100644 --- a/frontend/src/i18n/no.json +++ b/frontend/src/i18n/no.json @@ -42,8 +42,8 @@ "update": "Opptater", "upload": "Last opp", "openFile": "Open file", - "discardChanges": "Slett", - "saveChanges": "Lagre Endringane " + "discardChanges": "Slett", + "saveChanges": "Lagre Endringane " }, "download": { "downloadFile": "Nedlast filen", diff --git a/frontend/src/i18n/pl.json b/frontend/src/i18n/pl.json index 54dd9aed..06f1c8fd 100644 --- a/frontend/src/i18n/pl.json +++ b/frontend/src/i18n/pl.json @@ -42,8 +42,8 @@ "update": "Aktualizuj", "upload": "Wyślij", "openFile": "Otwórz plik", - "discardChanges": "Odrzuć", - "saveChanges": "Zapisz zmiany" + "discardChanges": "Odrzuć", + "saveChanges": "Zapisz zmiany" }, "download": { "downloadFile": "Pobierz plik", diff --git a/frontend/src/i18n/pt-br.json b/frontend/src/i18n/pt-br.json index 8e314c77..a4938c49 100644 --- a/frontend/src/i18n/pt-br.json +++ b/frontend/src/i18n/pt-br.json @@ -42,8 +42,8 @@ "update": "Atualizar", "upload": "Enviar", "openFile": "Abrir", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Baixar arquivo", diff --git a/frontend/src/i18n/pt.json b/frontend/src/i18n/pt.json index 4c719cc9..2555eafb 100644 --- a/frontend/src/i18n/pt.json +++ b/frontend/src/i18n/pt.json @@ -42,8 +42,8 @@ "update": "Atualizar", "upload": "Enviar", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarregar ficheiro", diff --git a/frontend/src/i18n/ro.json b/frontend/src/i18n/ro.json index 232b0e4d..5f4a630e 100644 --- a/frontend/src/i18n/ro.json +++ b/frontend/src/i18n/ro.json @@ -42,8 +42,8 @@ "update": "Actualizează", "upload": "Încarcă", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Descarcă fișier", diff --git a/frontend/src/i18n/ru.json b/frontend/src/i18n/ru.json index 931cf68d..d9407647 100644 --- a/frontend/src/i18n/ru.json +++ b/frontend/src/i18n/ru.json @@ -42,8 +42,8 @@ "update": "Обновить", "upload": "Загрузить", "openFile": "Открыть файл", - "discardChanges": "Отказаться", - "saveChanges": "Save changes" + "discardChanges": "Отказаться", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Скачать файл", diff --git a/frontend/src/i18n/sk.json b/frontend/src/i18n/sk.json index 2f01ef8c..06c73a98 100644 --- a/frontend/src/i18n/sk.json +++ b/frontend/src/i18n/sk.json @@ -42,8 +42,8 @@ "update": "Aktualizovať", "upload": "Nahrať", "openFile": "Otvoriť súbor", - "discardChanges": "Zahodiť", - "saveChanges": "Save changes" + "discardChanges": "Zahodiť", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Stiahnuť súbor", diff --git a/frontend/src/i18n/sv-se.json b/frontend/src/i18n/sv-se.json index 319b7eb2..47c041c0 100644 --- a/frontend/src/i18n/sv-se.json +++ b/frontend/src/i18n/sv-se.json @@ -42,8 +42,8 @@ "update": "Uppdatera", "upload": "Ladda upp", "openFile": "Open file", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Ladda ner fil", diff --git a/frontend/src/i18n/tr.json b/frontend/src/i18n/tr.json index aa0d3558..ed635501 100644 --- a/frontend/src/i18n/tr.json +++ b/frontend/src/i18n/tr.json @@ -42,8 +42,8 @@ "update": "Güncelle", "upload": "Yükle", "openFile": "Dosyayı aç", - "discardChanges": "Discard", - "saveChanges": "Save changes" + "discardChanges": "Discard", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Dosyayı indir", diff --git a/frontend/src/i18n/uk.json b/frontend/src/i18n/uk.json index d3f01c9f..a81010f6 100644 --- a/frontend/src/i18n/uk.json +++ b/frontend/src/i18n/uk.json @@ -42,8 +42,8 @@ "update": "Оновити", "upload": "Вивантажити", "openFile": "Відкрити файл", - "discardChanges": "Скасувати", - "saveChanges": "Save changes" + "discardChanges": "Скасувати", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Завантажити файл", diff --git a/frontend/src/i18n/vi.json b/frontend/src/i18n/vi.json index 380f98ff..07864ce8 100644 --- a/frontend/src/i18n/vi.json +++ b/frontend/src/i18n/vi.json @@ -42,8 +42,8 @@ "update": "Cập nhật", "upload": "Tải lên", "openFile": "Mở tệp", - "discardChanges": "Hủy bỏ thay đổi", - "saveChanges": "Save changes" + "discardChanges": "Hủy bỏ thay đổi", + "saveChanges": "Save changes" }, "download": { "downloadFile": "Tải xuống tệp tin", diff --git a/frontend/src/i18n/zh-cn.json b/frontend/src/i18n/zh-cn.json index c18c7e98..6a8b9065 100644 --- a/frontend/src/i18n/zh-cn.json +++ b/frontend/src/i18n/zh-cn.json @@ -42,8 +42,8 @@ "update": "更新", "upload": "上传", "openFile": "打开文件", - "discardChanges": "放弃更改", - "saveChanges": "Save changes" + "discardChanges": "放弃更改", + "saveChanges": "Save changes" }, "download": { "downloadFile": "下载文件", diff --git a/frontend/src/i18n/zh-tw.json b/frontend/src/i18n/zh-tw.json index adcfde91..4ceb886c 100644 --- a/frontend/src/i18n/zh-tw.json +++ b/frontend/src/i18n/zh-tw.json @@ -42,8 +42,8 @@ "update": "更新", "upload": "上傳", "openFile": "開啟檔案", - "discardChanges": "放棄變更", - "saveChanges": "Save changes" + "discardChanges": "放棄變更", + "saveChanges": "Save changes" }, "download": { "downloadFile": "下載檔案", From 1165f00bd4dcb0dcfbc084f54f51902ba4b4a714 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:19:21 +0200 Subject: [PATCH 036/206] feat: Updates for project File Browser (#5457) Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- frontend/src/i18n/ar.json | 1 + frontend/src/i18n/ca.json | 1 + frontend/src/i18n/cs.json | 1 + frontend/src/i18n/de.json | 1 + frontend/src/i18n/el.json | 1 + frontend/src/i18n/es.json | 1 + frontend/src/i18n/fa.json | 1 + frontend/src/i18n/fr.json | 1 + frontend/src/i18n/he.json | 1 + frontend/src/i18n/hu.json | 1 + frontend/src/i18n/is.json | 1 + frontend/src/i18n/it.json | 1 + frontend/src/i18n/ja.json | 1 + frontend/src/i18n/ko.json | 1 + frontend/src/i18n/nl-be.json | 1 + frontend/src/i18n/no.json | 1 + frontend/src/i18n/pl.json | 1 + frontend/src/i18n/pt-br.json | 1 + frontend/src/i18n/pt.json | 1 + frontend/src/i18n/ro.json | 1 + frontend/src/i18n/ru.json | 1 + frontend/src/i18n/sk.json | 1 + frontend/src/i18n/sv-se.json | 1 + frontend/src/i18n/tr.json | 1 + frontend/src/i18n/uk.json | 1 + frontend/src/i18n/vi.json | 1 + frontend/src/i18n/zh-cn.json | 1 + frontend/src/i18n/zh-tw.json | 1 + 28 files changed, 28 insertions(+) diff --git a/frontend/src/i18n/ar.json b/frontend/src/i18n/ar.json index 9b06d2d3..26e95765 100644 --- a/frontend/src/i18n/ar.json +++ b/frontend/src/i18n/ar.json @@ -158,6 +158,7 @@ "video": "فيديوهات" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "إدارة", "administrator": "مدير", "allowCommands": "تنفيذ اﻷوامر", diff --git a/frontend/src/i18n/ca.json b/frontend/src/i18n/ca.json index 353eeb22..e17c7c80 100644 --- a/frontend/src/i18n/ca.json +++ b/frontend/src/i18n/ca.json @@ -158,6 +158,7 @@ "video": "Vídeo" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrador", "allowCommands": "Executar comandes", diff --git a/frontend/src/i18n/cs.json b/frontend/src/i18n/cs.json index 635a1d96..914b843f 100644 --- a/frontend/src/i18n/cs.json +++ b/frontend/src/i18n/cs.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrátor", "allowCommands": "Povolit příkazy", diff --git a/frontend/src/i18n/de.json b/frontend/src/i18n/de.json index 40971820..48c91eb8 100644 --- a/frontend/src/i18n/de.json +++ b/frontend/src/i18n/de.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Befehle ausführen", diff --git a/frontend/src/i18n/el.json b/frontend/src/i18n/el.json index ba75606f..97206a1f 100644 --- a/frontend/src/i18n/el.json +++ b/frontend/src/i18n/el.json @@ -158,6 +158,7 @@ "video": "Βίντεο" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Διαχειριστής", "administrator": "Διαχειριστής", "allowCommands": "Εκτέλεση εντολών", diff --git a/frontend/src/i18n/es.json b/frontend/src/i18n/es.json index a3565f4f..2981ece1 100644 --- a/frontend/src/i18n/es.json +++ b/frontend/src/i18n/es.json @@ -158,6 +158,7 @@ "video": "Vídeo" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrador", "allowCommands": "Ejecutar comandos", diff --git a/frontend/src/i18n/fa.json b/frontend/src/i18n/fa.json index e4a2532e..1d885fcc 100644 --- a/frontend/src/i18n/fa.json +++ b/frontend/src/i18n/fa.json @@ -158,6 +158,7 @@ "video": "ویدئو " }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "اجرای دستورات", diff --git a/frontend/src/i18n/fr.json b/frontend/src/i18n/fr.json index fcbd239b..bf07499a 100644 --- a/frontend/src/i18n/fr.json +++ b/frontend/src/i18n/fr.json @@ -158,6 +158,7 @@ "video": "Vidéo" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrateur·ice", "allowCommands": "Exécuter des commandes", diff --git a/frontend/src/i18n/he.json b/frontend/src/i18n/he.json index 9bb3145a..6576ebd0 100644 --- a/frontend/src/i18n/he.json +++ b/frontend/src/i18n/he.json @@ -158,6 +158,7 @@ "video": "וידאו" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "מנהל", "administrator": "מנהל ראשי", "allowCommands": "הפעלת פקודות", diff --git a/frontend/src/i18n/hu.json b/frontend/src/i18n/hu.json index 0971d9cc..dd58ed1d 100644 --- a/frontend/src/i18n/hu.json +++ b/frontend/src/i18n/hu.json @@ -158,6 +158,7 @@ "video": "Videó" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Adminisztrátor", "allowCommands": "Parancsok futtatása", diff --git a/frontend/src/i18n/is.json b/frontend/src/i18n/is.json index 65a5eb00..431f21ef 100644 --- a/frontend/src/i18n/is.json +++ b/frontend/src/i18n/is.json @@ -158,6 +158,7 @@ "video": "Myndbönd" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Stjórnandi", "administrator": "Stjórnandi", "allowCommands": "Senda skipanir", diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index b1135aac..929d90ed 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Amministratore", "allowCommands": "Esegui comandi", diff --git a/frontend/src/i18n/ja.json b/frontend/src/i18n/ja.json index 574bf59a..0e6b9c04 100644 --- a/frontend/src/i18n/ja.json +++ b/frontend/src/i18n/ja.json @@ -158,6 +158,7 @@ "video": "動画" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "管理者", "administrator": "管理者", "allowCommands": "コマンドの実行", diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json index ea5a1e67..64a6c7d5 100644 --- a/frontend/src/i18n/ko.json +++ b/frontend/src/i18n/ko.json @@ -158,6 +158,7 @@ "video": "비디오" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "관리자", "administrator": "관리자", "allowCommands": "명령 실행", diff --git a/frontend/src/i18n/nl-be.json b/frontend/src/i18n/nl-be.json index af659e5c..78a7c281 100644 --- a/frontend/src/i18n/nl-be.json +++ b/frontend/src/i18n/nl-be.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Commando's uitvoeren", diff --git a/frontend/src/i18n/no.json b/frontend/src/i18n/no.json index 08c6992c..3eea3638 100644 --- a/frontend/src/i18n/no.json +++ b/frontend/src/i18n/no.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Utfør kommandoer", diff --git a/frontend/src/i18n/pl.json b/frontend/src/i18n/pl.json index 06f1c8fd..b9db7455 100644 --- a/frontend/src/i18n/pl.json +++ b/frontend/src/i18n/pl.json @@ -158,6 +158,7 @@ "video": "Wideo" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Wykonaj polecenie", diff --git a/frontend/src/i18n/pt-br.json b/frontend/src/i18n/pt-br.json index a4938c49..d29f98d6 100644 --- a/frontend/src/i18n/pt-br.json +++ b/frontend/src/i18n/pt-br.json @@ -158,6 +158,7 @@ "video": "Vídeos" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrador", "allowCommands": "Executar comandos", diff --git a/frontend/src/i18n/pt.json b/frontend/src/i18n/pt.json index 2555eafb..e54a4f0d 100644 --- a/frontend/src/i18n/pt.json +++ b/frontend/src/i18n/pt.json @@ -158,6 +158,7 @@ "video": "Vídeos" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrador", "allowCommands": "Executar comandos", diff --git a/frontend/src/i18n/ro.json b/frontend/src/i18n/ro.json index 5f4a630e..73719a4e 100644 --- a/frontend/src/i18n/ro.json +++ b/frontend/src/i18n/ro.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrator", "allowCommands": "Execută comenzi", diff --git a/frontend/src/i18n/ru.json b/frontend/src/i18n/ru.json index d9407647..0678ce14 100644 --- a/frontend/src/i18n/ru.json +++ b/frontend/src/i18n/ru.json @@ -158,6 +158,7 @@ "video": "Видео" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Админ", "administrator": "Администратор", "allowCommands": "Запуск команд", diff --git a/frontend/src/i18n/sk.json b/frontend/src/i18n/sk.json index 06c73a98..68112fba 100644 --- a/frontend/src/i18n/sk.json +++ b/frontend/src/i18n/sk.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administrátor", "allowCommands": "Vykonávať príkazy", diff --git a/frontend/src/i18n/sv-se.json b/frontend/src/i18n/sv-se.json index 47c041c0..9f66a141 100644 --- a/frontend/src/i18n/sv-se.json +++ b/frontend/src/i18n/sv-se.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Admin", "administrator": "Administratör", "allowCommands": "Exekvera kommandon", diff --git a/frontend/src/i18n/tr.json b/frontend/src/i18n/tr.json index ed635501..7493821e 100644 --- a/frontend/src/i18n/tr.json +++ b/frontend/src/i18n/tr.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Yönetim", "administrator": "Yönetici", "allowCommands": "Komutları çalıştır", diff --git a/frontend/src/i18n/uk.json b/frontend/src/i18n/uk.json index a81010f6..40a96893 100644 --- a/frontend/src/i18n/uk.json +++ b/frontend/src/i18n/uk.json @@ -158,6 +158,7 @@ "video": "Відео" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Адмін", "administrator": "Адміністратор", "allowCommands": "Запуск команд", diff --git a/frontend/src/i18n/vi.json b/frontend/src/i18n/vi.json index 07864ce8..fab93759 100644 --- a/frontend/src/i18n/vi.json +++ b/frontend/src/i18n/vi.json @@ -158,6 +158,7 @@ "video": "Video" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "Quản trị viên", "administrator": "Người quản trị", "allowCommands": "Thực thi lệnh", diff --git a/frontend/src/i18n/zh-cn.json b/frontend/src/i18n/zh-cn.json index 6a8b9065..15cf8e3c 100644 --- a/frontend/src/i18n/zh-cn.json +++ b/frontend/src/i18n/zh-cn.json @@ -158,6 +158,7 @@ "video": "视频" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "管理员", "administrator": "管理员", "allowCommands": "执行命令(Shell 命令)", diff --git a/frontend/src/i18n/zh-tw.json b/frontend/src/i18n/zh-tw.json index 4ceb886c..d59f1efd 100644 --- a/frontend/src/i18n/zh-tw.json +++ b/frontend/src/i18n/zh-tw.json @@ -158,6 +158,7 @@ "video": "影片" }, "settings": { + "aceEditorTheme": "Ace editor theme", "admin": "管理員", "administrator": "管理員", "allowCommands": "執行命令", From 878cdfbc52bdb4c4385f24904a87927f852cb907 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 25 Sep 2025 17:20:12 +0200 Subject: [PATCH 037/206] chore(release): 2.44.0 --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f81c8cd4..9bf8bd77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.44.0](https://github.com/filebrowser/filebrowser/compare/v2.43.0...v2.44.0) (2025-09-25) + + +### Features + +* allow setting ace editor theme ([#3826](https://github.com/filebrowser/filebrowser/issues/3826)) ([b9787c7](https://github.com/filebrowser/filebrowser/commit/b9787c78f3889171f94db19e7655dce68c64b6fb)) +* Improved path display in the new file and directory modal ([#5451](https://github.com/filebrowser/filebrowser/issues/5451)) ([d29ad35](https://github.com/filebrowser/filebrowser/commit/d29ad356d1067c87b2821debab91286549f512a0)) +* Translate frontend/src/i18n/en.json in no ([dec7a02](https://github.com/filebrowser/filebrowser/commit/dec7a027378fbc6948d203199c44a640a141bcad)) +* Updates for project File Browser ([#5446](https://github.com/filebrowser/filebrowser/issues/5446)) ([4ff247e](https://github.com/filebrowser/filebrowser/commit/4ff247e134e4d61668ee656a258ed67f71414e18)) +* Updates for project File Browser ([#5450](https://github.com/filebrowser/filebrowser/issues/5450)) ([0eade71](https://github.com/filebrowser/filebrowser/commit/0eade717ce9d04bf48051922f11d983edbc7c2d0)) +* Updates for project File Browser ([#5457](https://github.com/filebrowser/filebrowser/issues/5457)) ([1165f00](https://github.com/filebrowser/filebrowser/commit/1165f00bd4dcb0dcfbc084f54f51902ba4b4a714)) + + +### Bug Fixes + +* computation of file path ([c472542](https://github.com/filebrowser/filebrowser/commit/c4725428e07da72b855009e2c13c6ed91d32e0b7)) +* show login when session token expires ([e6c674b](https://github.com/filebrowser/filebrowser/commit/e6c674b3c616831942c4d4aacab0907d58003e23)) +* some formatting issues with i18n files ([949ddff](https://github.com/filebrowser/filebrowser/commit/949ddffef20e38169902c5fd74dca4815dcecf11)) +* **upload:** throttle upload speed calculation to 100ms to avoid Infinity MB/s ([#5456](https://github.com/filebrowser/filebrowser/issues/5456)) ([692ca5e](https://github.com/filebrowser/filebrowser/commit/692ca5eaf01e4dcf346ba03f82c5dbd50cce246b)) + ## [2.43.0](https://github.com/filebrowser/filebrowser/compare/v2.42.5...v2.43.0) (2025-09-13) From d0039afbb76a9364c1e6ac9715ccc3c239dc8cb6 Mon Sep 17 00:00:00 2001 From: Ryan <43447928+Rmiller5466@users.noreply.github.com> Date: Fri, 3 Oct 2025 04:42:24 -0400 Subject: [PATCH 038/206] fix: wrong url on settings branding link --- frontend/src/views/settings/Global.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/settings/Global.vue b/frontend/src/views/settings/Global.vue index e397c6f7..0a42a293 100644 --- a/frontend/src/views/settings/Global.vue +++ b/frontend/src/views/settings/Global.vue @@ -65,7 +65,7 @@ {{ t("settings.documentation") }} From a397e7305d1572baf67823413f97a29eea38f0cc Mon Sep 17 00:00:00 2001 From: Ryan <43447928+Rmiller5466@users.noreply.github.com> Date: Fri, 17 Oct 2025 10:45:36 -0400 Subject: [PATCH 039/206] fix: editor discard prompt doesn't save nor discard Co-authored-by: Ryan Miller --- .../components/prompts/DiscardEditorChanges.vue | 10 ++-------- frontend/src/views/files/Editor.vue | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/prompts/DiscardEditorChanges.vue b/frontend/src/components/prompts/DiscardEditorChanges.vue index bd6bc49a..7a99c5fc 100644 --- a/frontend/src/components/prompts/DiscardEditorChanges.vue +++ b/frontend/src/components/prompts/DiscardEditorChanges.vue @@ -17,7 +17,7 @@