Compare commits

...
37 Commits
Author SHA1 Message Date
Henrique Dias cbcf708d94 chore(release): 2.61.2 2026-03-06 16:17:33 +01:00
Henrique Dias 4d9e6b8218 fix(frontend): do not delete original assets 2026-03-06 16:07:08 +01:00
Henrique Dias 8ee55761a1 fix(frontend): input password type 2026-03-06 16:06:54 +01:00
Marcel SzalbachandGitHub 8598db2acc fix: added dateFormat to getUserDefaults so this is respected in the … (#5804) 2026-03-06 15:32:04 +01:00
transifex-integration[bot]GitHubtransifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
a7dc7bf88a chore: update translations (#5796)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2026-03-06 15:28:29 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
9f56826fb2 chore(deps): update all non-major dependencies (#5794)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 15:27:14 +01:00
Ariel LeyvaandGitHub d7b00ce5f6 fix: avoid sending the same name in the file/folder rename modal (#5806) 2026-03-06 15:26:54 +01:00
Ariel LeyvaandGitHub 177c7cfcce fix: validate current password with a modal (#5805) 2026-03-06 15:26:41 +01:00
Ariel LeyvaandGitHub 4af3f85e64 fix(csv-viewer): add support for missing text encodings in dropdown list (#5795) 2026-03-06 15:26:13 +01:00
Henrique Dias c950a57df8 chore(release): 2.61.1 2026-03-04 10:04:51 +01:00
Henrique Dias 7ed1425115 fix: check for correct permission in TUS Delete 2026-03-04 10:04:22 +01:00
Henrique Dias 148b3c5942 chore(release): 2.61.0 2026-02-28 10:54:35 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
a40f80672d chore(deps): update all non-major dependencies (#5791)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-28 10:44:31 +01:00
transifex-integration[bot]GitHubtransifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
8dc618a24b chore: update translations (#5790)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2026-02-28 10:44:24 +01:00
Henrique Dias 31194fb57a fix: correctly clean path 2026-02-28 10:31:09 +01:00
Ariel LeyvaandGitHub aa809096eb feat: improved conflict resolution when uploading/copying/moving files (#5765) 2026-02-27 14:55:49 +01:00
renovate[bot]andGitHub e3d00d591b chore(deps): update goreleaser/goreleaser-action action to v7 (#5782) 2026-02-22 07:12:45 +01:00
Henrique Dias 7b16e2de90 chore(release): 2.60.0 2026-02-21 18:18:55 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2470b9eb69 chore(deps): update all non-major dependencies (#5780)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-21 18:17:51 +01:00
transifex-integration[bot]GitHubtransifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
9940bdd663 feat: Updates for project File Browser (#5764)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2026-02-21 18:12:43 +01:00
Ariel LeyvaandGitHub 200d501547 fix: modal lifecycle issues, multiple modals, new directory creation and discard changes behavior (#5773) 2026-02-21 18:12:10 +01:00
Ariel LeyvaandGitHub 3169a14a4d fix: always show separators and encoding list in the CSV viewer (#5774) 2026-02-21 18:11:50 +01:00
Henrique Dias 7e78ad97ad chore(release): 2.59.0 2026-02-15 13:54:23 +01:00
NN708andGitHub 0467326d5c fix: render equations in markdown preview (#5745) 2026-02-15 13:53:36 +01:00
transifex-integration[bot]GitHubtransifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
63a76ef18c feat: Updates for project File Browser (#5760)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2026-02-15 13:28:37 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3cad9a2b0e chore(deps): update dependency eslint to v10 (#5748)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-15 13:28:26 +01:00
Marek BaczyńskiandGitHub 804b14b698 feat: add 'Open direct' button to images (#5678) 2026-02-15 12:46:39 +01:00
Henrique Dias 95e6ed75a7 chore(release): 2.58.0 2026-02-14 08:42:21 +01:00
Henrique Dias b09960e538 fix(frontend): pnpm lock 2026-02-14 08:41:51 +01:00
transifex-integration[bot]GitHubtransifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
5e8f5be245 feat: Updates for project File Browser (#5759)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2026-02-14 08:27:14 +01:00
Aaron DillandGitHub e5bc0d3cce fix: wrap response text in Error before reject (#5753) 2026-02-14 07:40:52 +01:00
Ariel LeyvaandGitHub f67bccf8c5 feat: support for multiple encodings in CSV files (#5756) 2026-02-14 07:37:28 +01:00
Henrique Dias 88b97def9e feat: nederlands 2026-02-14 07:35:42 +01:00
Henrique Dias 1f7904dad2 fix: ignore version.go 2026-02-14 07:35:34 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
5feaf66575 chore(deps): update all non-major dependencies (#5758)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-14 07:31:45 +01:00
transifex-integration[bot]GitHubtransifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
c94870fcfe feat: Updates for project File Browser (#5749)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2026-02-14 07:30:21 +01:00
NianandGitHub 6a76dfeba9 fix: respect Accept-Encoding for pre-compressed JS (#5750) 2026-02-14 07:30:10 +01:00
82 changed files with 3913 additions and 2123 deletions
+5 -5
View File
@@ -34,7 +34,7 @@ jobs:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.25.x"
go-version: "1.26.x"
- uses: golangci/golangci-lint-action@v9
with:
version: "latest"
@@ -46,7 +46,7 @@ jobs:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.25.x"
go-version: "1.26.x"
- run: go test --race ./...
build:
@@ -58,7 +58,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-go@v6
with:
go-version: '1.25'
go-version: '1.26'
- uses: pnpm/action-setup@v4
with:
package_json_file: "frontend/package.json"
@@ -82,7 +82,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-go@v6
with:
go-version: '1.25'
go-version: '1.26'
- uses: pnpm/action-setup@v4
with:
package_json_file: "frontend/package.json"
@@ -104,7 +104,7 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
uses: goreleaser/goreleaser-action@v7
with:
version: latest
args: release --clean
+75
View File
@@ -2,6 +2,81 @@
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
## [2.61.2](https://github.com/filebrowser/filebrowser/compare/v2.61.1...v2.61.2) (2026-03-06)
### Bug Fixes
* added dateFormat to getUserDefaults so this is respected in the … ([#5804](https://github.com/filebrowser/filebrowser/issues/5804)) ([8598db2](https://github.com/filebrowser/filebrowser/commit/8598db2accccf5b87353e5e718b2ad1c946e5c44))
* avoid sending the same name in the file/folder rename modal ([#5806](https://github.com/filebrowser/filebrowser/issues/5806)) ([d7b00ce](https://github.com/filebrowser/filebrowser/commit/d7b00ce5f672b7ce0b26ce31abdfc74f8b00b939))
* **csv-viewer:** add support for missing text encodings in dropdown list ([#5795](https://github.com/filebrowser/filebrowser/issues/5795)) ([4af3f85](https://github.com/filebrowser/filebrowser/commit/4af3f85e64e795e8ae1d87d4caee8185028294ac))
* **frontend:** do not delete original assets ([4d9e6b8](https://github.com/filebrowser/filebrowser/commit/4d9e6b821852203cef67233791a922013bd5b64d))
* **frontend:** input password type ([8ee5576](https://github.com/filebrowser/filebrowser/commit/8ee55761a1aa9bc091d8466c44f03c2043a8ca79))
* validate current password with a modal ([#5805](https://github.com/filebrowser/filebrowser/issues/5805)) ([177c7cf](https://github.com/filebrowser/filebrowser/commit/177c7cfcce36779e2c5ebaa4b59a055dd1e17648))
## [2.61.1](https://github.com/filebrowser/filebrowser/compare/v2.61.0...v2.61.1) (2026-03-04)
### Bug Fixes
* check for correct permission in TUS Delete ([7ed1425](https://github.com/filebrowser/filebrowser/commit/7ed1425115be602c2b23236c410098ea2d74b42f))
## [2.61.0](https://github.com/filebrowser/filebrowser/compare/v2.60.0...v2.61.0) (2026-02-28)
### Features
* improved conflict resolution when uploading/copying/moving files ([#5765](https://github.com/filebrowser/filebrowser/issues/5765)) ([aa80909](https://github.com/filebrowser/filebrowser/commit/aa809096eb35fdfbdeb6784b1ebfe2ca1e42f52b))
### Bug Fixes
* correctly clean path ([31194fb](https://github.com/filebrowser/filebrowser/commit/31194fb57a5b92e7155219d7ec7273028fcb2e83))
## [2.60.0](https://github.com/filebrowser/filebrowser/compare/v2.59.0...v2.60.0) (2026-02-21)
### Features
* Updates for project File Browser ([#5764](https://github.com/filebrowser/filebrowser/issues/5764)) ([9940bdd](https://github.com/filebrowser/filebrowser/commit/9940bdd663ff5141110778524b8a22c957036e78))
### Bug Fixes
* always show separators and encoding list in the CSV viewer ([#5774](https://github.com/filebrowser/filebrowser/issues/5774)) ([3169a14](https://github.com/filebrowser/filebrowser/commit/3169a14a4d63a0a11a5288f4f3a674c0a0edb972))
* modal lifecycle issues, multiple modals, new directory creation and discard changes behavior ([#5773](https://github.com/filebrowser/filebrowser/issues/5773)) ([200d501](https://github.com/filebrowser/filebrowser/commit/200d5015472c79d5caa683ea291ebf500356a39f))
## [2.59.0](https://github.com/filebrowser/filebrowser/compare/v2.58.0...v2.59.0) (2026-02-15)
### Features
* add 'Open direct' button to images ([#5678](https://github.com/filebrowser/filebrowser/issues/5678)) ([804b14b](https://github.com/filebrowser/filebrowser/commit/804b14b698aa218fa5c2aaba687e72c5f7617f0f))
* Updates for project File Browser ([#5760](https://github.com/filebrowser/filebrowser/issues/5760)) ([63a76ef](https://github.com/filebrowser/filebrowser/commit/63a76ef18c51121e08634810a894c1e22a870428))
### Bug Fixes
* render equations in markdown preview ([#5745](https://github.com/filebrowser/filebrowser/issues/5745)) ([0467326](https://github.com/filebrowser/filebrowser/commit/0467326d5c082c42c0ede88ee2d3472f5fb65600))
## [2.58.0](https://github.com/filebrowser/filebrowser/compare/v2.57.1...v2.58.0) (2026-02-14)
### Features
* nederlands ([88b97de](https://github.com/filebrowser/filebrowser/commit/88b97def9ee72fe6e8094209aebb71830b7305be))
* support for multiple encodings in CSV files ([#5756](https://github.com/filebrowser/filebrowser/issues/5756)) ([f67bccf](https://github.com/filebrowser/filebrowser/commit/f67bccf8c5470cb280fe854d92aa2666c270bcf5))
* Updates for project File Browser ([#5749](https://github.com/filebrowser/filebrowser/issues/5749)) ([c94870f](https://github.com/filebrowser/filebrowser/commit/c94870fcfe1b4acb2db9ab897b9f7d35e3b75770))
* Updates for project File Browser ([#5759](https://github.com/filebrowser/filebrowser/issues/5759)) ([5e8f5be](https://github.com/filebrowser/filebrowser/commit/5e8f5be245fd0126545ef5ca61c2d428ac128ad5))
### Bug Fixes
* **frontend:** pnpm lock ([b09960e](https://github.com/filebrowser/filebrowser/commit/b09960e538387ff29371c80be1584720f65181e7))
* ignore version.go ([1f7904d](https://github.com/filebrowser/filebrowser/commit/1f7904dad21a87f04e1543ee10b60ce79e5eebe9))
* respect Accept-Encoding for pre-compressed JS ([#5750](https://github.com/filebrowser/filebrowser/issues/5750)) ([6a76dfe](https://github.com/filebrowser/filebrowser/commit/6a76dfeba9254a938e320928c67d110f73f83715))
* wrap response text in Error before reject ([#5753](https://github.com/filebrowser/filebrowser/issues/5753)) ([e5bc0d3](https://github.com/filebrowser/filebrowser/commit/e5bc0d3cce18fa7b069688b176b99efbb67382d2))
## [2.57.1](https://github.com/filebrowser/filebrowser/compare/v2.57.0...v2.57.1) (2026-02-08)
+2
View File
@@ -168,6 +168,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
Sorting: a.Settings.Defaults.Sorting,
Perm: a.Settings.Defaults.Perm,
Commands: a.Settings.Defaults.Commands,
DateFormat: a.Settings.Defaults.DateFormat,
HideDotfiles: a.Settings.Defaults.HideDotfiles,
}
u = a.GetUser(d)
@@ -233,6 +234,7 @@ func (a *HookAuth) GetUser(d *users.User) *users.User {
By: a.Fields.GetString("user.sorting.by", d.Sorting.By),
},
Commands: a.Fields.GetArray("user.commands", d.Commands),
DateFormat: a.Fields.GetBoolean("user.dateFormat", d.DateFormat),
HideDotfiles: a.Fields.GetBoolean("user.hideDotfiles", d.HideDotfiles),
Perm: perms,
LockPassword: true,
+2 -1
View File
@@ -99,7 +99,7 @@ func getProxyAuth(flags *pflag.FlagSet, defaultAuther map[string]interface{}) (a
return nil, err
}
if header == "" && defaultAuther != nil {
if header == "" && defaultAuther != nil {
header = defaultAuther["header"].(string)
}
@@ -236,6 +236,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
fmt.Fprintln(w, "\nDefaults:")
fmt.Fprintf(w, "\tScope:\t%s\n", set.Defaults.Scope)
fmt.Fprintf(w, "\tDateFormat:\t%t\n", set.Defaults.DateFormat)
fmt.Fprintf(w, "\tHideDotfiles:\t%t\n", set.Defaults.HideDotfiles)
fmt.Fprintf(w, "\tLocale:\t%s\n", set.Defaults.Locale)
fmt.Fprintf(w, "\tView mode:\t%s\n", set.Defaults.ViewMode)
+2
View File
@@ -138,6 +138,8 @@ func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all
defaults.Sorting.By, err = flags.GetString(flag.Name)
case "sorting.asc":
defaults.Sorting.Asc, err = flags.GetBool(flag.Name)
case "dateFormat":
defaults.DateFormat, err = flags.GetBool(flag.Name)
case "hideDotfiles":
defaults.HideDotfiles, err = flags.GetBool(flag.Name)
}
+5 -4
View File
@@ -21,6 +21,7 @@
"@vueuse/core": "^14.0.0",
"@vueuse/integrations": "^14.0.0",
"ace-builds": "^1.43.2",
"csv-parse": "^6.1.0",
"dayjs": "^1.11.13",
"dompurify": "^3.2.6",
"epubjs": "^0.3.93",
@@ -29,6 +30,7 @@
"jwt-decode": "^4.0.0",
"lodash-es": "^4.17.21",
"marked": "^17.0.0",
"marked-katex-extension": "^5.1.6",
"material-icons": "^1.13.14",
"normalize.css": "^8.0.1",
"pinia": "^3.0.4",
@@ -40,7 +42,6 @@
"videojs-hotkeys": "^0.2.28",
"videojs-mobile-ui": "^1.1.1",
"vue": "^3.5.17",
"vue-final-modal": "^4.5.5",
"vue-i18n": "^11.1.10",
"vue-lazyload": "^3.0.0",
"vue-reader": "^1.2.17",
@@ -57,9 +58,9 @@
"@vitejs/plugin-vue": "^6.0.1",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.6.0",
"@vue/tsconfig": "^0.8.1",
"@vue/tsconfig": "^0.9.0",
"autoprefixer": "^10.4.21",
"eslint": "^9.31.0",
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-prettier": "^5.5.1",
"eslint-plugin-vue": "^10.5.1",
@@ -71,5 +72,5 @@
"vite-plugin-compression2": "^2.3.1",
"vue-tsc": "^3.1.3"
},
"packageManager": "pnpm@10.29.1+sha512.48dae233635a645768a3028d19545cacc1688639eeb1f3734e42d6d6b971afbf22aa1ac9af52a173d9c3a20c15857cfa400f19994d79a2f626fcc73fccda9bbc"
"packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017"
}
+1354 -1579
View File
File diff suppressed because it is too large Load Diff
+19 -5
View File
@@ -3,14 +3,25 @@ import { useLayoutStore } from "@/stores/layout";
import { baseURL } from "@/utils/constants";
import { upload as postTus, useTus } from "./tus";
import { createURL, fetchURL, removePrefix, StatusError } from "./utils";
import { isEncodableResponse, makeRawResource } from "@/utils/encodings";
export async function fetch(url: string, signal?: AbortSignal) {
const encoding = isEncodableResponse(url);
url = removePrefix(url);
const res = await fetchURL(`/api/resources${url}`, { signal });
const res = await fetchURL(`/api/resources${url}`, {
signal,
headers: {
"X-Encoding": encoding ? "true" : "false",
},
});
let data: Resource;
try {
data = (await res.json()) as Resource;
if (res.headers.get("Content-Type") == "application/octet-stream") {
data = await makeRawResource(res, url);
} else {
data = (await res.json()) as Resource;
}
} catch (e) {
// Check if the error is an intentional cancellation
if (e instanceof Error && e.name === "AbortError") {
@@ -140,9 +151,9 @@ async function postResources(
if (request.status === 200) {
resolve(request.responseText);
} else if (request.status === 409) {
reject(request.status);
reject(new Error(request.status.toString()));
} else {
reject(request.responseText);
reject(new Error(request.responseText));
}
};
@@ -166,9 +177,12 @@ function moveCopy(
for (const item of items) {
const from = item.from;
const to = encodeURIComponent(removePrefix(item.to ?? ""));
const finalOverwrite =
item.overwrite == undefined ? overwrite : item.overwrite;
const finalRename = item.rename == undefined ? rename : item.rename;
const url = `${from}?action=${
copy ? "copy" : "rename"
}&destination=${to}&override=${overwrite}&rename=${rename}`;
}&destination=${to}&override=${finalOverwrite}&rename=${finalRename}`;
promises.push(resourceAction(url, "PATCH"));
}
layoutStore.closeHovers();
+142
View File
@@ -0,0 +1,142 @@
<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import { vClickOutside } from "@/utils/index";
const props = withDefaults(
defineProps<{
position?: "top-left" | "bottom-left" | "bottom-right" | "top-right";
closeOnClick?: boolean;
}>(),
{
position: "bottom-right",
closeOnClick: true,
}
);
const isOpen = defineModel<boolean>();
const triggerRef = ref<HTMLElement | null>(null);
const listRef = ref<HTMLElement | null>(null);
const dropdownStyle = ref<Record<string, string>>({});
const updatePosition = () => {
if (!isOpen.value || !triggerRef.value) return;
const rect = triggerRef.value.getBoundingClientRect();
dropdownStyle.value = {
position: "fixed",
top: props.position.includes("bottom")
? `${rect.bottom + 2}px`
: `${rect.top}px`,
left: props.position.includes("left") ? `${rect.left}px` : "auto",
right: props.position.includes("right")
? `${window.innerWidth - rect.right}px`
: "auto",
zIndex: "11000",
};
};
watch(isOpen, (open) => {
if (open) {
updatePosition();
}
});
const onWindowChange = () => {
updatePosition();
};
const closeDropdown = (e: Event) => {
if (
e.target instanceof HTMLElement &&
listRef.value?.contains(e.target) &&
!props.closeOnClick
) {
return;
}
isOpen.value = false;
};
onMounted(() => {
window.addEventListener("resize", onWindowChange);
window.addEventListener("scroll", onWindowChange, true);
});
onBeforeUnmount(() => {
window.removeEventListener("resize", onWindowChange);
window.removeEventListener("scroll", onWindowChange, true);
});
</script>
<script lang="ts">
export default {
directives: {
clickOutside: vClickOutside,
},
};
</script>
<template>
<div
class="dropdown-modal-container"
v-click-outside="closeDropdown"
ref="triggerRef"
>
<button @click="isOpen = !isOpen" class="dropdown-modal-trigger">
<slot></slot>
<i class="material-icons">chevron_right</i>
</button>
<teleport to="body">
<div
ref="listRef"
class="dropdown-modal-list"
:class="{ 'dropdown-modal-open': isOpen }"
:style="dropdownStyle"
>
<div>
<slot name="list"></slot>
</div>
</div>
</teleport>
</div>
</template>
<style scoped>
.dropdown-modal-trigger {
background: var(--surfacePrimary);
color: var(--textSecondary);
border: 1px solid var(--borderPrimary);
border-radius: 0.1em;
padding: 0.5em 1em;
transition: 0.2s ease all;
margin: 0;
display: flex;
justify-content: space-between;
gap: 1rem;
align-items: center;
}
.dropdown-modal-trigger > i {
transform: rotate(90deg);
}
.dropdown-modal-list {
padding: 0.25rem;
background-color: var(--surfacePrimary);
color: var(--textSecondary);
display: none;
border: 1px solid var(--borderPrimary);
border-radius: 0.1em;
}
.dropdown-modal-list > div {
max-height: 450px;
padding: 0.25rem;
}
.dropdown-modal-open {
display: block;
}
</style>
+170 -56
View File
@@ -1,10 +1,64 @@
<template>
<div class="csv-viewer">
<div class="csv-header">
<div class="header-select">
<label for="columnSeparator">{{ $t("files.columnSeparator") }}</label>
<select
id="columnSeparator"
class="input input--block"
v-model="columnSeparator"
>
<option :value="[',']">
{{ $t("files.csvSeparators.comma") }}
</option>
<option :value="[';']">
{{ $t("files.csvSeparators.semicolon") }}
</option>
<option :value="[',', ';']">
{{ $t("files.csvSeparators.both") }}
</option>
</select>
</div>
<div class="header-select" v-if="isEncodedContent">
<label for="fileEncoding">{{ $t("files.fileEncoding") }}</label>
<DropdownModal
v-model="isEncondingDropdownOpen"
:close-on-click="false"
>
<div>
<span class="selected-encoding">{{ selectedEncoding }}</span>
</div>
<template v-slot:list>
<input
v-model="encodingSearch"
:placeholder="$t('search.search')"
class="input input--block"
name="encoding"
/>
<div class="encoding-list">
<div v-if="encodingList.length == 0" class="message">
<i class="material-icons">sentiment_dissatisfied</i>
<span>{{ $t("files.lonely") }}</span>
</div>
<button
v-for="encoding in encodingList"
:value="encoding"
:key="encoding"
class="encoding-button"
@click="selectedEncoding = encoding"
>
{{ encoding }}
</button>
</div>
</template>
</DropdownModal>
</div>
</div>
<div v-if="displayError" class="csv-error">
<i class="material-icons">error</i>
<p>{{ displayError }}</p>
</div>
<div v-else-if="data.headers.length === 0" class="csv-empty">
<div v-else-if="parsed.headers.length === 0" class="csv-empty">
<i class="material-icons">description</i>
<p>{{ $t("files.lonely") }}</p>
</div>
@@ -12,13 +66,13 @@
<table class="csv-table">
<thead>
<tr>
<th v-for="(header, index) in data.headers" :key="index">
<th v-for="(header, index) in parsed.headers" :key="index">
{{ header || `Column ${index + 1}` }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in data.rows" :key="rowIndex">
<tr v-for="(row, rowIndex) in parsed.rows" :key="rowIndex">
<td v-for="(cell, cellIndex) in row" :key="cellIndex">
{{ cell }}
</td>
@@ -26,29 +80,11 @@
</tbody>
</table>
<div class="csv-footer">
<div class="csv-info" v-if="data.rows.length > 100">
<div class="csv-info" v-if="parsed.rows.length > 100">
<i class="material-icons">info</i>
<span>
{{ $t("files.showingRows", { count: data.rows.length }) }}</span
>
</div>
<div class="column-separator">
<label for="columnSeparator">{{ $t("files.columnSeparator") }}</label>
<select
id="columnSeparator"
class="input input--block"
v-model="columnSeparator"
>
<option :value="[',']">
{{ $t("files.csvSeparators.comma") }}
</option>
<option :value="[';']">
{{ $t("files.csvSeparators.semicolon") }}
</option>
<option :value="[',', ';']">
{{ $t("files.csvSeparators.both") }}
</option>
</select>
{{ $t("files.showingRows", { count: parsed.rows.length }) }}
</span>
</div>
</div>
</div>
@@ -56,11 +92,16 @@
</template>
<script setup lang="ts">
import { parseCSV, type CsvData } from "@/utils/csv";
import { computed, ref } from "vue";
import { computed, ref, watch, watchEffect } from "vue";
import { parse } from "csv-parse/browser/esm";
import { useI18n } from "vue-i18n";
import { availableEncodings, decode } from "@/utils/encodings";
import DropdownModal from "../DropdownModal.vue";
const { t } = useI18n({});
interface Props {
content: string;
content: ArrayBuffer | string;
error?: string;
}
@@ -68,31 +109,58 @@ const props = withDefaults(defineProps<Props>(), {
error: "",
});
const columnSeparator = ref([","]);
const isEncondingDropdownOpen = ref(false);
const data = computed<CsvData>(() => {
try {
return parseCSV(props.content, columnSeparator.value);
} catch (e) {
console.error("Failed to parse CSV:", e);
return { headers: [], rows: [] };
const encodingSearch = ref<string>("");
const encodingList = computed(() => {
return availableEncodings.filter((e) =>
e.toLowerCase().includes(encodingSearch.value.toLowerCase())
);
});
const columnSeparator = ref([",", ";"]);
const selectedEncoding = ref("utf-8");
const parsed = ref<CsvData>({ headers: [], rows: [] });
const displayError = ref<string | null>(null);
const isEncodedContent = computed(() => {
return props.content instanceof ArrayBuffer;
});
watchEffect(() => {
if (props.content !== "" && columnSeparator.value.length > 0) {
const content = isEncodedContent.value
? decode(props.content as ArrayBuffer, selectedEncoding.value)
: props.content;
parse(
content as string,
{ delimiter: columnSeparator.value, skip_empty_lines: true },
(error, output) => {
if (error) {
console.error("Failed to parse CSV:", error);
parsed.value = { headers: [], rows: [] };
displayError.value = t("files.csvLoadFailed", {
error: error.toString(),
});
} else {
parsed.value = {
headers: output[0],
rows: output.slice(1),
};
displayError.value = null;
}
}
);
}
});
const displayError = computed(() => {
// External error takes priority (e.g., file too large)
if (props.error) {
return props.error;
}
// Check for parse errors
if (
props.content &&
props.content.trim().length > 0 &&
data.value.headers.length === 0
) {
return "Failed to parse CSV file";
}
return null;
watch(selectedEncoding, () => {
isEncondingDropdownOpen.value = false;
encodingSearch.value = "";
});
</script>
@@ -213,10 +281,6 @@ const displayError = computed(() => {
padding: 0.5rem;
}
.csv-footer > :only-child {
margin-left: auto;
}
.csv-info {
display: flex;
align-items: center;
@@ -230,18 +294,32 @@ const displayError = computed(() => {
font-size: 0.875rem;
}
.column-separator {
.csv-header {
display: flex;
justify-content: space-between;
padding: 0.25rem;
}
.header-select {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
flex-direction: column;
@media (width >= 640px) {
flex-direction: row;
}
}
.column-separator > label {
.header-select > label {
font-size: small;
text-align: end;
@media (width >= 640px) {
max-width: 70px;
}
}
.column-separator > select {
.header-select > select,
.header-select > div {
margin-bottom: 0;
}
@@ -249,4 +327,40 @@ const displayError = computed(() => {
font-size: 1.2rem;
color: var(--blue);
}
.encoding-list {
max-height: 300px;
min-width: 120px;
overflow: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
touch-action: pan-y;
}
.encoding-button {
background-color: transparent;
border: none;
outline: none;
padding: 0.25rem 0.5rem;
color: var(--textPrimary);
text-align: left;
cursor: pointer;
border-radius: 0.2rem;
white-space: nowrap;
display: block;
width: 100%;
}
.encoding-button:hover {
background-color: var(--surfaceSecondary);
}
.selected-encoding {
white-space: nowrap;
text-overflow: ellipsis;
}
.message {
font-size: 1.25em;
}
</style>
+25 -12
View File
@@ -178,6 +178,10 @@ const drop = async (event: Event) => {
from: fileStore.req?.items[i].url,
to: props.url + encodeURIComponent(fileStore.req?.items[i].name),
name: fileStore.req?.items[i].name,
size: fileStore.req?.items[i].size,
modified: fileStore.req?.items[i].modified,
overwrite: false,
rename: false,
});
}
}
@@ -189,7 +193,7 @@ const drop = async (event: Event) => {
const path = el.__vue__.url;
const baseItems = (await api.fetch(path)).items;
const action = (overwrite: boolean, rename: boolean) => {
const action = (overwrite?: boolean, rename?: boolean) => {
api
.move(items, overwrite, rename)
.then(() => {
@@ -200,26 +204,35 @@ const drop = async (event: Event) => {
const conflict = upload.checkConflict(items, baseItems);
let overwrite = false;
let rename = false;
if (conflict) {
if (conflict.length > 0) {
layoutStore.showHover({
prompt: "replace-rename",
confirm: (event: Event, option: any) => {
overwrite = option == "overwrite";
rename = option == "rename";
prompt: "resolve-conflict",
props: {
conflict: conflict,
},
confirm: (event: Event, result: Array<ConflictingResource>) => {
event.preventDefault();
layoutStore.closeHovers();
action(overwrite, rename);
for (let i = result.length - 1; i >= 0; i--) {
const item = result[i];
if (item.checked.length == 2) {
items[item.index].rename = true;
} else if (item.checked.length == 1 && item.checked[0] == "origin") {
items[item.index].overwrite = true;
} else {
items.splice(item.index, 1);
}
}
if (items.length > 0) {
action();
}
},
});
return;
}
action(overwrite, rename);
action(false, false);
};
const itemClick = (event: Event | KeyboardEvent) => {
+55 -15
View File
@@ -1,21 +1,61 @@
<template>
<VueFinalModal
class="vfm-modal"
overlay-transition="vfm-fade"
content-transition="vfm-fade"
@closed="layoutStore.closeHovers"
:focus-trap="{
initialFocus: '#focus-prompt',
fallbackFocus: 'div.vfm__content',
}"
>
<slot />
</VueFinalModal>
<div id="modal-background" @click="backgroundClick">
<div ref="modalContainer">
<slot></slot>
</div>
</div>
</template>
<script setup lang="ts">
import { VueFinalModal } from "vue-final-modal";
import { useLayoutStore } from "@/stores/layout";
import { onMounted, ref } from "vue";
const layoutStore = useLayoutStore();
const emit = defineEmits(["closed"]);
const modalContainer = ref(null);
onMounted(() => {
const element = document.querySelector("#focus-prompt") as HTMLElement | null;
if (element) {
element.focus();
} else if (modalContainer.value) {
(modalContainer.value as HTMLElement).focus();
}
});
const backgroundClick = (event: Event) => {
const target = event.target as HTMLElement;
if (target.id == "modal-background") {
emit("closed");
}
};
window.addEventListener("keydown", (event) => {
if (event.key === "Escape") {
event.stopImmediatePropagation();
emit("closed");
}
});
</script>
<style scoped>
#modal-background {
position: fixed;
inset: 0;
background-color: #00000096;
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
animation: ease-in 150ms opacity-enter;
}
@keyframes opacity-enter {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
+27 -18
View File
@@ -91,6 +91,10 @@ export default {
from: this.req.items[item].url,
to: this.dest + encodeURIComponent(this.req.items[item].name),
name: this.req.items[item].name,
size: this.req.items[item].size,
modified: this.req.items[item].modified,
overwrite: false,
rename: this.$route.path === this.dest,
});
}
@@ -118,36 +122,41 @@ export default {
});
};
if (this.$route.path === this.dest) {
this.closeHovers();
action(false, true);
return;
}
const dstItems = (await api.fetch(this.dest)).items;
const conflict = upload.checkConflict(items, dstItems);
let overwrite = false;
let rename = false;
if (conflict) {
if (conflict.length > 0) {
this.showHover({
prompt: "replace-rename",
confirm: (event, option) => {
overwrite = option == "overwrite";
rename = option == "rename";
prompt: "resolve-conflict",
props: {
conflict: conflict,
},
confirm: (event, result) => {
event.preventDefault();
this.closeHovers();
action(overwrite, rename);
for (let i = result.length - 1; i >= 0; i--) {
const item = result[i];
if (item.checked.length == 2) {
items[item.index].rename = true;
} else if (
item.checked.length == 1 &&
item.checked[0] == "origin"
) {
items[item.index].overwrite = true;
} else {
items.splice(item.index, 1);
}
}
if (items.length > 0) {
action();
}
},
});
return;
}
action(overwrite, rename);
action(false, false);
},
},
};
@@ -35,12 +35,17 @@ const props = defineProps({
type: Boolean,
default: false,
},
path: {
type: String,
default: null,
},
});
const container = ref<HTMLElement | null>(null);
const path = computed(() => {
let basePath = fileStore.isFiles ? route.path : url.removeLastDir(route.path);
const routePath = props.path || route.path;
let basePath = fileStore.isFiles ? routePath : url.removeLastDir(routePath);
if (!basePath.endsWith("/")) {
basePath += "/";
}
@@ -0,0 +1,58 @@
<template>
<div class="card floating">
<div class="card-title">
<h2>{{ $t("prompts.currentPassword") }}</h2>
</div>
<div class="card-content">
<p>
{{ $t("prompts.currentPasswordMessage") }}
</p>
<input
id="focus-prompt"
class="input input--block"
type="password"
@keyup.enter="submit"
v-model="password"
/>
</div>
<div class="card-action">
<button
class="button button--flat button--grey"
@click="cancel"
:aria-label="$t('buttons.cancel')"
:title="$t('buttons.cancel')"
>
{{ $t("buttons.cancel") }}
</button>
<button
@click="submit"
class="button button--flat"
type="submit"
:aria-label="$t('buttons.ok')"
:title="$t('buttons.ok')"
>
{{ $t("buttons.ok") }}
</button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { useLayoutStore } from "@/stores/layout";
const layoutStore = useLayoutStore();
const { currentPrompt } = layoutStore;
const password = ref("");
const submit = (event: Event) => {
currentPrompt?.confirm(event, password.value);
};
const cancel = () => {
layoutStore.closeHovers();
};
</script>
+7 -1
View File
@@ -168,7 +168,13 @@ export default {
this.showHover({
prompt: "newDir",
action: null,
confirm: null,
confirm: (url) => {
const paths = url.split("/");
this.items.push({
name: paths[paths.length - 2],
url: url,
});
},
props: {
redirect: false,
base: this.current === this.$route.path ? null : this.current,
+28 -11
View File
@@ -97,6 +97,10 @@ export default {
from: this.req.items[item].url,
to: this.dest + encodeURIComponent(this.req.items[item].name),
name: this.req.items[item].name,
size: this.req.items[item].size,
modified: this.req.items[item].modified,
overwrite: false,
rename: false,
});
}
@@ -121,26 +125,39 @@ export default {
const dstItems = (await api.fetch(this.dest)).items;
const conflict = upload.checkConflict(items, dstItems);
let overwrite = false;
let rename = false;
if (conflict) {
if (conflict.length > 0) {
this.showHover({
prompt: "replace-rename",
confirm: (event, option) => {
overwrite = option == "overwrite";
rename = option == "rename";
prompt: "resolve-conflict",
props: {
conflict: conflict,
files: items,
},
confirm: (event, result) => {
event.preventDefault();
this.closeHovers();
action(overwrite, rename);
for (let i = result.length - 1; i >= 0; i--) {
const item = result[i];
if (item.checked.length == 2) {
items[item.index].rename = true;
} else if (
item.checked.length == 1 &&
item.checked[0] == "origin"
) {
items[item.index].overwrite = true;
} else {
items.splice(item.index, 1);
}
}
if (items.length > 0) {
action();
}
},
});
return;
}
action(overwrite, rename);
action(false, false);
},
},
};
+12 -13
View File
@@ -14,7 +14,7 @@
v-model.trim="name"
tabindex="1"
/>
<CreateFilePath :name="name" :is-dir="true" />
<CreateFilePath :name="name" :is-dir="true" :path="base" />
</div>
<div class="card-action">
@@ -41,7 +41,7 @@
</template>
<script setup lang="ts">
import { inject, ref } from "vue";
import { computed, inject, ref } from "vue";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
@@ -53,17 +53,13 @@ import CreateFilePath from "@/components/prompts/CreateFilePath.vue";
const $showError = inject<IToastError>("$showError")!;
const props = defineProps({
base: String,
redirect: {
type: Boolean,
default: true,
},
});
const fileStore = useFileStore();
const layoutStore = useLayoutStore();
const base = computed(() => {
return layoutStore.currentPrompt?.props?.base;
});
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
@@ -76,7 +72,7 @@ const submit = async (event: Event) => {
// Build the path of the new directory.
let uri: string;
if (props.base) uri = props.base;
if (base.value) uri = base.value;
else if (fileStore.isFiles) uri = route.path + "/";
else uri = "/";
@@ -89,12 +85,15 @@ const submit = async (event: Event) => {
try {
await api.post(uri);
if (props.redirect) {
if (layoutStore.currentPrompt?.props?.redirect) {
router.push({ path: uri });
} else if (!props.base) {
} else if (!base.value) {
const res = await api.fetch(url.removeLastDir(uri) + "/");
fileStore.updateRequest(res);
}
if (layoutStore.currentPrompt?.confirm) {
layoutStore.currentPrompt?.confirm(uri);
}
} catch (e) {
if (e instanceof Error) {
$showError(e);
+17 -24
View File
@@ -1,10 +1,13 @@
<template>
<ModalsContainer />
<base-modal v-if="modal != null" :prompt="currentPromptName" @closed="close">
<keep-alive>
<component :is="modal" />
</keep-alive>
</base-modal>
</template>
<script setup lang="ts">
import { watch } from "vue";
import { ModalsContainer, useModal } from "vue-final-modal";
import { computed } from "vue";
import { storeToRefs } from "pinia";
import { useLayoutStore } from "@/stores/layout";
@@ -20,11 +23,12 @@ import Copy from "./Copy.vue";
import NewFile from "./NewFile.vue";
import NewDir from "./NewDir.vue";
import Replace from "./Replace.vue";
import ReplaceRename from "./ReplaceRename.vue";
import Share from "./Share.vue";
import ShareDelete from "./ShareDelete.vue";
import Upload from "./Upload.vue";
import DiscardEditorChanges from "./DiscardEditorChanges.vue";
import ResolveConflict from "./ResolveConflict.vue";
import CurrentPassword from "./CurrentPassword.vue";
const layoutStore = useLayoutStore();
@@ -41,35 +45,24 @@ const components = new Map<string, any>([
["newDir", NewDir],
["download", Download],
["replace", Replace],
["replace-rename", ReplaceRename],
["share", Share],
["upload", Upload],
["share-delete", ShareDelete],
["deleteUser", DeleteUser],
["discardEditorChanges", DiscardEditorChanges],
["resolve-conflict", ResolveConflict],
["current-password", CurrentPassword],
]);
watch(currentPromptName, (newValue) => {
const modal = components.get(newValue!);
if (!modal) return;
const modal = computed(() => {
const modal = components.get(currentPromptName.value!);
if (!modal) null;
const { open, close } = useModal({
component: BaseModal,
slots: {
default: modal,
},
});
layoutStore.setCloseOnPrompt(close, newValue!);
open();
return modal;
});
window.addEventListener("keydown", (event) => {
const close = () => {
if (!layoutStore.currentPrompt) return;
if (event.key === "Escape") {
event.stopImmediatePropagation();
layoutStore.closeHovers();
}
});
layoutStore.closeHovers();
};
</script>
+14 -10
View File
@@ -6,7 +6,7 @@
<div class="card-content">
<p>
{{ $t("prompts.renameMessage") }} <code>{{ oldName() }}</code
{{ $t("prompts.renameMessage") }} <code>{{ oldName }}</code
>:
</p>
<input
@@ -33,6 +33,7 @@
type="submit"
:aria-label="$t('buttons.rename')"
:title="$t('buttons.rename')"
:disabled="name === '' || name === oldName"
>
{{ $t("buttons.rename") }}
</button>
@@ -56,7 +57,7 @@ export default {
};
},
created() {
this.name = this.oldName();
this.name = this.oldName;
},
inject: ["$showError"],
computed: {
@@ -67,25 +68,28 @@ export default {
"isListing",
]),
...mapWritableState(useFileStore, ["reload", "preselect"]),
},
methods: {
...mapActions(useLayoutStore, ["closeHovers"]),
cancel: function () {
this.closeHovers();
},
oldName: function () {
oldName() {
if (!this.isListing) {
return this.req.name;
}
if (this.selectedCount === 0 || this.selectedCount > 1) {
// This shouldn't happen.
return;
return "";
}
return this.req.items[this.selected[0]].name;
},
},
methods: {
...mapActions(useLayoutStore, ["closeHovers"]),
cancel: function () {
this.closeHovers();
},
submit: async function () {
if (this.name === "" || this.name === this.oldName) {
return;
}
let oldLink = "";
let newLink = "";
@@ -1,57 +0,0 @@
<template>
<div class="card floating">
<div class="card-title">
<h2>{{ $t("prompts.replace") }}</h2>
</div>
<div class="card-content">
<p>{{ $t("prompts.replaceMessage") }}</p>
</div>
<div class="card-action">
<button
class="button button--flat button--grey"
@click="closeHovers"
:aria-label="$t('buttons.cancel')"
:title="$t('buttons.cancel')"
tabindex="3"
>
{{ $t("buttons.cancel") }}
</button>
<button
class="button button--flat button--blue"
@click="(event) => currentPrompt.confirm(event, 'rename')"
:aria-label="$t('buttons.rename')"
:title="$t('buttons.rename')"
tabindex="2"
>
{{ $t("buttons.rename") }}
</button>
<button
id="focus-prompt"
class="button button--flat button--red"
@click="(event) => currentPrompt.confirm(event, 'overwrite')"
:aria-label="$t('buttons.replace')"
:title="$t('buttons.replace')"
tabindex="1"
>
{{ $t("buttons.replace") }}
</button>
</div>
</div>
</template>
<script>
import { mapActions, mapState } from "pinia";
import { useLayoutStore } from "@/stores/layout";
export default {
name: "replace-rename",
computed: {
...mapState(useLayoutStore, ["currentPrompt"]),
},
methods: {
...mapActions(useLayoutStore, ["closeHovers"]),
},
};
</script>
@@ -0,0 +1,307 @@
<template>
<div class="card floating">
<div class="card-title">
<h2>
{{
personalized
? $t("prompts.resolveConflict")
: $t("prompts.replaceOrSkip")
}}
</h2>
</div>
<div class="card-content">
<template v-if="personalized">
<p v-if="isUploadAction != true">
{{ $t("prompts.singleConflictResolve") }}
</p>
<div class="conflict-list-container">
<div>
<p>
<input
@change="toogleCheckAll"
type="checkbox"
:checked="originAllChecked"
value="origin"
/>
{{
isUploadAction != true
? $t("prompts.filesInOrigin")
: $t("prompts.uploadingFiles")
}}
</p>
<p>
<input
@change="toogleCheckAll"
type="checkbox"
:checked="destAllChecked"
value="dest"
/>
{{ $t("prompts.filesInDest") }}
</p>
</div>
<div>
<template v-for="(item, index) in conflict" :key="index">
<div class="conflict-file-name">
<span>{{ item.name }}</span>
<template v-if="item.checked.length == 2">
<span v-if="isUploadAction != true" class="result-rename">
{{ $t("prompts.rename") }}
</span>
<span v-else class="result-error">
{{ $t("prompts.forbiddenError") }}
</span>
</template>
<span
v-else-if="
item.checked.length == 1 && item.checked[0] == 'origin'
"
class="result-override"
>
{{ $t("prompts.override") }}
</span>
<span v-else class="result-skip">
{{ $t("prompts.skip") }}
</span>
</div>
<div>
<input v-model="item.checked" type="checkbox" value="origin" />
<div>
<p class="conflict-file-value">
{{ humanTime(item.origin.lastModified) }}
</p>
<p class="conflict-file-value">
{{ humanSize(item.origin.size) }}
</p>
</div>
</div>
<div>
<input v-model="item.checked" type="checkbox" value="dest" />
<div>
<p class="conflict-file-value">
{{ humanTime(item.dest.lastModified) }}
</p>
<p class="conflict-file-value">
{{ humanSize(item.dest.size) }}
</p>
</div>
</div>
</template>
</div>
</div>
</template>
<template v-else>
<p>
{{ $t("prompts.fastConflictResolve", { count: conflict.length }) }}
</p>
<div class="result-buttons">
<button @click="(e) => resolve(e, ['origin'])">
<i class="material-icons">done_all</i>
{{ $t("buttons.overrideAll") }}
</button>
<button
v-if="isUploadAction != true"
@click="(e) => resolve(e, ['origin', 'dest'])"
>
<i class="material-icons">folder_copy</i>
{{ $t("buttons.renameAll") }}
</button>
<button @click="(e) => resolve(e, ['dest'])">
<i class="material-icons">undo</i>
{{ $t("buttons.skipAll") }}
</button>
<button @click="personalized = true">
<i class="material-icons">checklist</i>
{{ $t("buttons.singleDecision") }}
</button>
</div>
</template>
</div>
<div class="card-action" style="display: flex; justify-content: end">
<div>
<button
class="button button--flat button--grey"
@click="close"
:aria-label="$t('buttons.cancel')"
:title="$t('buttons.cancel')"
tabindex="4"
>
{{ $t("buttons.cancel") }}
</button>
<button
v-if="personalized"
id="focus-prompt"
class="button button--flat"
@click="(event) => currentPrompt?.confirm(event, conflict)"
:aria-label="$t('buttons.ok')"
:title="$t('buttons.ok')"
tabindex="1"
>
{{ $t("buttons.ok") }}
</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from "vue";
import { useLayoutStore } from "@/stores/layout";
import { filesize } from "@/utils";
import dayjs from "dayjs";
const layoutStore = useLayoutStore();
const { currentPrompt } = layoutStore;
const conflict = ref<ConflictingResource[]>(currentPrompt?.props.conflict);
const isUploadAction = ref<boolean | undefined>(
currentPrompt?.props.isUploadAction
);
const personalized = ref(false);
const originAllChecked = computed(() => {
for (const item of conflict.value) {
if (!item.checked.includes("origin")) return false;
}
return true;
});
const destAllChecked = computed(() => {
for (const item of conflict.value) {
if (!item.checked.includes("dest")) return false;
}
return true;
});
const close = () => {
layoutStore.closeHovers();
};
const humanSize = (size: number | undefined) => {
return size == undefined ? "Unknown size" : filesize(size);
};
const humanTime = (modified: string | number | undefined) => {
if (modified == undefined) return "Unknown date";
return dayjs(modified).format("L LT");
};
const resolve = (event: Event, result: Array<"origin" | "dest">) => {
for (const item of conflict.value) {
item.checked = result;
}
currentPrompt?.confirm(event, conflict.value);
};
const toogleCheckAll = (e: Event) => {
const target = e.currentTarget as HTMLInputElement;
const value = target.value as "origin" | "dest" | "both";
const checked = target.checked;
for (const item of conflict.value) {
if (value == "both") {
item.checked = ["origin", "dest"];
} else {
if (!item.checked.includes(value)) {
if (checked) {
item.checked.push(value);
}
} else {
if (!checked) {
item.checked = value == "dest" ? ["origin"] : ["dest"];
}
}
}
}
};
</script>
<style scoped>
.conflict-list-container {
max-height: 300px;
overflow: auto;
}
.conflict-list-container > div {
display: grid;
grid-template-columns: 1fr 1fr;
border-bottom: solid 1px var(--textPrimary);
gap: 0.5rem 0.25rem;
}
.conflict-list-container > div:last-child {
border-bottom: none;
}
.conflict-list-container > div > div {
display: flex;
align-items: center;
gap: 0.5rem;
}
.conflict-file-name {
grid-column: 1 / -1;
color: var(--textPrimary);
font-size: 0.8rem;
display: flex;
justify-content: space-between;
padding: 0.5rem 0.25rem;
}
.conflict-file-value {
color: var(--textPrimary);
font-size: 0.9rem;
margin: 0;
}
.result-rename,
.result-override,
.result-error,
.result-skip {
font-size: 0.75rem;
line-height: 0.75rem;
border-radius: 0.75rem;
padding: 0.15rem 0.5rem;
}
.result-override {
background-color: var(--input-green);
}
.result-error {
background-color: var(--icon-red);
}
.result-rename {
background-color: var(--icon-orange);
}
.result-skip {
background-color: var(--icon-blue);
}
.result-buttons > button {
padding: 0.75rem;
color: var(--textPrimary);
margin: 0.25rem 0;
display: flex;
justify-content: start;
align-items: center;
gap: 0.5rem;
background: transparent;
border: solid 1px transparent;
width: 100%;
transition: all ease-in-out 200ms;
cursor: pointer;
border-radius: 0.25rem;
}
.result-buttons > button:hover {
border: solid 1px var(--icon-blue);
}
</style>
+19 -8
View File
@@ -69,18 +69,29 @@ const uploadInput = (event: Event) => {
const path = route.path.endsWith("/") ? route.path : route.path + "/";
const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
if (conflict) {
if (conflict.length > 0) {
layoutStore.showHover({
prompt: "replace",
action: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
upload.handleFiles(uploadFiles, path, false);
prompt: "resolve-conflict",
props: {
conflict: conflict,
isUploadAction: true,
},
confirm: (event: Event) => {
confirm: (event: Event, result: Array<ConflictingResource>) => {
event.preventDefault();
layoutStore.closeHovers();
upload.handleFiles(uploadFiles, path, true);
for (let i = result.length - 1; i >= 0; i--) {
const item = result[i];
if (item.checked.length == 2) {
continue;
} else if (item.checked.length == 1 && item.checked[0] == "origin") {
uploadFiles[item.index].overwrite = true;
} else {
uploadFiles.splice(item.index, 1);
}
}
if (uploadFiles.length > 0) {
upload.handleFiles(uploadFiles, path);
}
},
});
@@ -32,7 +32,8 @@ export default {
ja: "日本語",
ko: "한국어",
no: "Norsk",
"nl-be": "Dutch (Belgium)",
nl: "Nederlands (Nederland)",
"nl-be": "Nederlands (België)",
pl: "Polski",
"pt-br": "Português (Brasil)",
pt: "Português (Portugal)",
+5 -4
View File
@@ -182,10 +182,11 @@ html[dir="rtl"] .breadcrumbs a {
background: var(--textSecondary) !important;
}
.vfm-modal {
z-index: 9999999 !important;
}
body > div[style*="z-index: 9990"] {
z-index: 10000 !important;
}
#modal-background .button:focus {
outline: 1px solid #2195f32d;
outline-offset: 1px;
}
-1
View File
@@ -1,6 +1,5 @@
@import "normalize.css/normalize.css";
@import "vue-toastification/dist/index.css";
@import "vue-final-modal/style.css";
@import "./_variables.css";
@import "./_buttons.css";
@import "./_inputs.css";
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "تحديث",
"upload": "رفع",
"openFile": "فتح الملف",
"openDirect": "View raw",
"discardChanges": "إلغاء التغييرات",
"stopSearch": "توقف عن البحث",
"saveChanges": "حفظ التغييرات",
"editAsText": "تعديل على شكل نص",
"increaseFontSize": "زيادة حجم الخط",
"decreaseFontSize": "تصغير حجم الخط"
"decreaseFontSize": "تصغير حجم الخط",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "تحميل الملف",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "حدد الملف أو المجلد",
@@ -159,7 +165,17 @@
"uploadMessage": "إختر الملفات التي تريد رفعها.",
"optionalPassword": "كلمة مرور إختيارية",
"resolution": "الدقة",
"discardEditorChanges": "هل تريد بالتأكيد إلغاء التغييرات؟"
"discardEditorChanges": "هل تريد بالتأكيد إلغاء التغييرات؟",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "الصور",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Обнови",
"upload": "Качи",
"openFile": "Отвори файл",
"openDirect": "View raw",
"discardChanges": "Изчисти",
"stopSearch": "Stop searching",
"saveChanges": "Запиши промените",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Свали файл",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "избери файл или директория",
@@ -159,7 +165,17 @@
"uploadMessage": "Изберете опция за качване.",
"optionalPassword": "Опционална парола",
"resolution": "Резолюция",
"discardEditorChanges": "Сигурни ли сте, че искате да откажете направените промени?"
"discardEditorChanges": "Сигурни ли сте, че искате да откажете направените промени?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Изображения",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Actualitzar",
"upload": "Pujar",
"openFile": "Obrir fitxer",
"openDirect": "View raw",
"discardChanges": "Descartar",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Descarregar fitxer",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "seleccionar fitxer o carpeta",
@@ -159,7 +165,17 @@
"uploadMessage": "Seleccioneu una opció per pujar.",
"optionalPassword": "Contrasenya opcional",
"resolution": "Resolució",
"discardEditorChanges": "Esteu segur que voleu descartar els canvis que heu fet?"
"discardEditorChanges": "Esteu segur que voleu descartar els canvis que heu fet?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Imatges",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Aktualizovat",
"upload": "Nahrát",
"openFile": "Otevřít soubor",
"openDirect": "View raw",
"discardChanges": "Zrušit změny",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Stáhnout soubor",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "vyberte soubor nebo adresář",
@@ -159,7 +165,17 @@
"uploadMessage": "Vyberte možnost pro nahrání.",
"optionalPassword": "Volitelné heslo",
"resolution": "Rozlišení",
"discardEditorChanges": "Opravdu chcete zrušit provedené změny?"
"discardEditorChanges": "Opravdu chcete zrušit provedené změny?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Obrázky",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Aktualisieren",
"upload": "Hochladen",
"openFile": "Datei öffnen",
"openDirect": "Original anzeigen",
"discardChanges": "Verwerfen",
"stopSearch": "Suche beenden",
"saveChanges": "Änderungen speichern",
"editAsText": "Als Text bearbeiten",
"increaseFontSize": "Schrift vergrößern",
"decreaseFontSize": "Schrift verkleinern"
"decreaseFontSize": "Schrift verkleinern",
"overrideAll": "Alle Dateien im Zielordner ersetzen",
"skipAll": "Alle in Konflikt stehenden Dateien überspringen",
"renameAll": "Alle Dateien umbenennen (Kopie erstellen)",
"singleDecision": "Bei jeder Datei mit Konflikt entscheiden"
},
"download": {
"downloadFile": "Datei herunterladen",
@@ -88,7 +93,8 @@
"comma": "Komma (,)",
"semicolon": "Semikolon (;)",
"both": "Beides (,) und (;)"
}
},
"fileEncoding": "Dateikodierung"
},
"help": {
"click": "Datei oder Verzeichnis auswählen",
@@ -159,7 +165,17 @@
"uploadMessage": "Wähle eine Upload-Option.",
"optionalPassword": "Optionales Passwort",
"resolution": "Auflösung",
"discardEditorChanges": "Möchtest du deine Änderungen wirklich verwerfen?"
"discardEditorChanges": "Möchtest du deine Änderungen wirklich verwerfen?",
"replaceOrSkip": "Dateien ersetzen oder überspringen",
"resolveConflict": "Welche Dateien möchtest du behalten?",
"singleConflictResolve": "Wenn du beide Versionen auswählst, wird dem Namen der kopierten Datei eine Nummer hinzugefügt.",
"fastConflictResolve": "Der Zielordner enthält {count} Dateien mit demselben Namen.",
"uploadingFiles": "Dateien werden hochgeladen",
"filesInOrigin": "Dateien im Ursprungsordner",
"filesInDest": "Dateien im Zielordner",
"override": "Überschreiben",
"skip": "Überspringen",
"forbiddenError": "Zugriff verweigert"
},
"search": {
"images": "Bilder",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Ενημέρωση",
"upload": "Μεταφόρτωση",
"openFile": "Άνοιγμα αρχείου",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Λήψη αρχείου",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "επιλέξτε αρχείο ή φάκελο",
@@ -159,7 +165,17 @@
"uploadMessage": "Επιλέξτε μια επιλογή για τη μεταφόρτωση.",
"optionalPassword": "Προαιρετικός κωδικός πρόσβασης",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Εικόνες",
+21 -3
View File
@@ -42,12 +42,17 @@
"update": "Update",
"upload": "Upload",
"openFile": "Open file",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Download File",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "select file or directory",
@@ -159,7 +165,19 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error",
"currentPassword": "Your password",
"currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Images",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Actualizar",
"upload": "Subir",
"openFile": "Abrir archivo",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Guardar cambios",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Descargar fichero",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "seleccionar archivo o carpeta",
@@ -159,7 +165,17 @@
"uploadMessage": "Seleccione una opción para subir.",
"optionalPassword": "Contraseña opcional",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Imágenes",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "به روز سانی",
"upload": "آپلود",
"openFile": "باز کردن فایل",
"openDirect": "View raw",
"discardChanges": "لغو کردن",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "دانلود فایل",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "انتخاب فایل یا پوشه",
@@ -159,7 +165,17 @@
"uploadMessage": "یک گزینه برای آپلود انتخاب کنید.",
"optionalPassword": "رمز عبور اختیاری",
"resolution": "وضوح تصویر",
"discardEditorChanges": "آیا مطمئن هستید که می‌خواهید تغییراتی را که ایجاد کرده‌اید، لغو کنید؟"
"discardEditorChanges": "آیا مطمئن هستید که می‌خواهید تغییراتی را که ایجاد کرده‌اید، لغو کنید؟",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "تصاویر",
+20 -4
View File
@@ -42,12 +42,17 @@
"update": "Mettre à jour",
"upload": "Importer",
"openFile": "Ouvrir le fichier",
"openDirect": "View raw",
"discardChanges": "Annuler",
"stopSearch": "Arrêter recherche",
"saveChanges": "Enregistrer changements",
"editAsText": "Editer comme Texte",
"increaseFontSize": "Augmenter taille police",
"decreaseFontSize": "Réduire taille police"
"decreaseFontSize": "Réduire taille police",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Télécharger le fichier",
@@ -88,7 +93,8 @@
"comma": "Virgule (,)",
"semicolon": "Point-virgule (;)",
"both": "Les (,) et (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "Sélectionner un fichier ou dossier",
@@ -159,7 +165,17 @@
"uploadMessage": "Sélectionnez une option d'import.",
"optionalPassword": "Mot de passe optionnel",
"resolution": "Résolution",
"discardEditorChanges": "Êtes-vous sûr de vouloir annuler les modifications apportées ?"
"discardEditorChanges": "Êtes-vous sûr de vouloir annuler les modifications apportées ?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Images",
@@ -232,7 +248,7 @@
"permissions": "Permissions",
"permissionsHelp": "Vous pouvez définir l'utilisateur·ice comme étant administrateur·ice ou encore choisir les permissions individuellement. Si vous sélectionnez \"Administrateur·ice\", toutes les autres options seront automatiquement activées. La gestion des utilisateur·ices est un privilège que seul l'administrateur·ice possède.\n",
"profileSettings": "Paramètres du profil",
"redirectAfterCopyMove": "Redirect to destination after copy/move",
"redirectAfterCopyMove": "Rediriger vers la destination après une copie/déplacement",
"ruleExample1": "Bloque l'accès à tous les fichiers commençant par un point (comme par exemple .git, .gitignore) dans tous les dossiers.\n",
"ruleExample2": "Bloque l'accès au fichier nommé \"Caddyfile\" à la racine du dossier utilisateur·ice.",
"rules": "Règles",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "עדכון",
"upload": "העלאה",
"openFile": "פתח קובץ",
"openDirect": "View raw",
"discardChanges": "זריקת השינויים",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "הורד קובץ",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "בחר קובץ או תיקייה",
@@ -159,7 +165,17 @@
"uploadMessage": "בחר אפשרות העלאה.",
"optionalPassword": "סיסמא אופציונלית",
"resolution": "Resolution",
"discardEditorChanges": "האם אתה בטוח שברצונך לבטל את השינויים שביצעת?"
"discardEditorChanges": "האם אתה בטוח שברצונך לבטל את השינויים שביצעת?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "תמונות",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Ažuriraj",
"upload": "Prenesi",
"openFile": "Otvori datoteku",
"openDirect": "View raw",
"discardChanges": "Odbaci",
"stopSearch": "Stop searching",
"saveChanges": "Spremi promjene",
"editAsText": "Uredi kao tekst",
"increaseFontSize": "Povećaj veličinu fonta",
"decreaseFontSize": "Smanji veličinu fonta"
"decreaseFontSize": "Smanji veličinu fonta",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Preuzmi Datoteku",
@@ -88,7 +93,8 @@
"comma": "Zarez (,)",
"semicolon": "Točka zarez (;)",
"both": "I (,) i (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "odaberi datoteku ili mapu",
@@ -159,7 +165,17 @@
"uploadMessage": "Odaberite opciju za prijenos.",
"optionalPassword": "Opcionalna lozinka",
"resolution": "Rezolucija",
"discardEditorChanges": "Jeste li sigurni da želite odbaciti promjene koje ste napravili?"
"discardEditorChanges": "Jeste li sigurni da želite odbaciti promjene koje ste napravili?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Slike",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Frissítés",
"upload": "Feltöltés",
"openFile": "Fájl megnyitása",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Fájl letöltése",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "mappa vagy fájl kijelölése",
@@ -159,7 +165,17 @@
"uploadMessage": "Válasszon egy feltöltési módot.",
"optionalPassword": "Választható jelszó",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Képek",
+4 -1
View File
@@ -17,6 +17,7 @@ import("dayjs/locale/it");
import("dayjs/locale/ja");
import("dayjs/locale/ko");
import("dayjs/locale/nb");
import("dayjs/locale/nl");
import("dayjs/locale/nl-be");
import("dayjs/locale/pl");
import("dayjs/locale/pt-br");
@@ -110,7 +111,6 @@ export function detectLocale() {
case /^uk\b/.test(locale):
locale = "uk";
break;
case /^vi\b/.test(locale):
locale = "vi";
break;
@@ -118,6 +118,9 @@ export function detectLocale() {
case /^sv\b/.test(locale):
locale = "sv";
break;
case /^nl\b/.test(locale):
locale = "nl";
break;
case /^nl-be\b/.test(locale):
locale = "nl-be";
break;
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Vista",
"upload": "Hlaða upp",
"openFile": "Open file",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Sækja skjal",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "velja skjal eða möppu",
@@ -159,7 +165,17 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Myndir",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Aggiorna",
"upload": "Carica",
"openFile": "Apri file",
"openDirect": "View raw",
"discardChanges": "Ignora",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Scarica file",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "seleziona un file o una cartella",
@@ -159,7 +165,17 @@
"uploadMessage": "Seleziona un'opzione per il caricamento.",
"optionalPassword": "Password opzionale",
"resolution": "Risoluzione",
"discardEditorChanges": "Sei sicuro di voler scartare le modifiche apportate?"
"discardEditorChanges": "Sei sicuro di voler scartare le modifiche apportate?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Immagini",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "更新",
"upload": "アップロード",
"openFile": "ファイルを開く",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "ファイルのダウンロード",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "ファイルやフォルダーを選択",
@@ -159,7 +165,17 @@
"uploadMessage": "アップロードするオプションを選択してください。",
"optionalPassword": "パスワード(オプション)",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "画像",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "업데이트",
"upload": "업로드",
"openFile": "파일 열기",
"openDirect": "원본 보기",
"discardChanges": "변경 사항 취소",
"stopSearch": "검색 중단",
"saveChanges": "변경사항 저장",
"editAsText": "텍스트로 편집",
"increaseFontSize": "글꼴 크기 증가",
"decreaseFontSize": "글꼴 크기 감소"
"decreaseFontSize": "글꼴 크기 감소",
"overrideAll": "대상 폴더의 모든 파일을 대체",
"skipAll": "충돌하는 모든 파일을 건너뛰기",
"renameAll": "모든 파일의 이름 변경 (복사본 생성)",
"singleDecision": "충돌하는 각 파일을 확인"
},
"download": {
"downloadFile": "파일 다운로드",
@@ -88,7 +93,8 @@
"comma": "반점 (,)",
"semicolon": "쌍반점 (;)",
"both": "(,) 및 (;) 모두"
}
},
"fileEncoding": "파일 인코딩"
},
"help": {
"click": "파일 또는 디렉터리 선택",
@@ -159,7 +165,17 @@
"uploadMessage": "업로드 옵션을 선택하세요.",
"optionalPassword": "비밀번호 (선택)",
"resolution": "해상도",
"discardEditorChanges": "변경 사항을 취소하시겠습니까?"
"discardEditorChanges": "변경 사항을 취소하시겠습니까?",
"replaceOrSkip": "파일 대체 또는 건너뛰기",
"resolveConflict": "어떤 파일을 유지하시겠습니까?",
"singleConflictResolve": "모든 버전을 선택하면 복사한 파일의 이름에 번호를 추가합니다.",
"fastConflictResolve": "대상 폴더에 같은 이름을 가진 파일이 {count}개 있습니다.",
"uploadingFiles": "파일 업로드 중",
"filesInOrigin": "원본 파일",
"filesInDest": "대상 경로의 파일",
"override": "덮어쓰기",
"skip": "건너뛰기",
"forbiddenError": "권한 오류"
},
"search": {
"images": "이미지",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Atjaunināt",
"upload": "Augšupielādēt",
"openFile": "Atvērt failu",
"openDirect": "View raw",
"discardChanges": "Izmest",
"stopSearch": "Stop searching",
"saveChanges": "Saglabāt izmaiņas",
"editAsText": "Rediģēt kā tekstu",
"increaseFontSize": "Palieliniet fonta lielumu",
"decreaseFontSize": "Samaziniet fonta lielumu"
"decreaseFontSize": "Samaziniet fonta lielumu",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Lejupielādēt failu",
@@ -88,7 +93,8 @@
"comma": "Komats (,)",
"semicolon": "Semikols (;)",
"both": "Gan (,) gan (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "atlasiet failu vai direktoriju",
@@ -159,7 +165,17 @@
"uploadMessage": "Atlasiet augšupielādes opciju.",
"optionalPassword": "Izvēles parole",
"resolution": "Izšķirtspēja",
"discardEditorChanges": "Vai tiešām vēlaties atmest veiktās izmaiņas?"
"discardEditorChanges": "Vai tiešām vēlaties atmest veiktās izmaiņas?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Attēli",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Atjaunināt",
"upload": "Augšupielādēt",
"openFile": "Atvērt failu",
"openDirect": "View raw",
"discardChanges": "Izmest",
"stopSearch": "Beigt meklēšanu",
"saveChanges": "Saglabāt izmaiņas",
"editAsText": "Rediģēt kā tekstu",
"increaseFontSize": "Palieliniet fonta lielumu",
"decreaseFontSize": "Samaziniet fonta lielumu"
"decreaseFontSize": "Samaziniet fonta lielumu",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Lejupielādēt failu",
@@ -88,7 +93,8 @@
"comma": "Komats (,)",
"semicolon": "Semikols (;)",
"both": "Gan (,) gan (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "atlasiet failu vai direktoriju",
@@ -159,7 +165,17 @@
"uploadMessage": "Atlasiet augšupielādes opciju.",
"optionalPassword": "Izvēles parole",
"resolution": "Izšķirtspēja",
"discardEditorChanges": "Vai tiešām vēlaties atmest veiktās izmaiņas?"
"discardEditorChanges": "Vai tiešām vēlaties atmest veiktās izmaiņas?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Attēli",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Updaten",
"upload": "Uploaden",
"openFile": "Open file",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Bestand downloaden",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "selecteer bestand of map",
@@ -159,7 +165,17 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Afbeeldingen",
+304
View File
@@ -0,0 +1,304 @@
{
"buttons": {
"cancel": "Annuleren",
"clear": "Wissen",
"close": "Sluiten",
"continue": "Doorgaan",
"copy": "Kopiëren",
"copyFile": "Bestand kopiëren",
"copyToClipboard": "Kopiëren naar klembord",
"copyDownloadLinkToClipboard": "Download-link kopiëren naar klembord",
"create": "Aanmaken",
"delete": "Verwijderen",
"download": "Downloaden",
"file": "Bestand",
"folder": "Map",
"fullScreen": "Volledig scherm wisselen",
"hideDotfiles": "dot-bestanden verbergen",
"info": "Info",
"more": "Meer",
"move": "Verplaatsen",
"moveFile": "Bestand verplaatsen",
"new": "Nieuw",
"next": "Volgende",
"ok": "OK",
"permalink": "Permanente link verkrijgen",
"previous": "Vorige",
"preview": "Voorbeeld",
"publish": "Publiceren",
"rename": "Hernoemen",
"replace": "Vervangen",
"reportIssue": "Probleem melden",
"save": "Opslaan",
"schedule": "Plannen",
"search": "Zoeken",
"select": "Selecteren",
"selectMultiple": "Meervoudige selectie",
"share": "Delen",
"shell": "Opdrachtvenster wisselen",
"submit": "Indienen",
"switchView": "Weergave wisselen",
"toggleSidebar": "Zijbalk wisselen",
"update": "Bijwerken",
"upload": "Uploaden",
"openFile": "Bestand openen",
"openDirect": "Raw weergeven",
"discardChanges": "Weggooien",
"stopSearch": "Stoppen met zoeken",
"saveChanges": "Wijzigingen opslaan",
"editAsText": "Als tekst bewerken",
"increaseFontSize": "Lettertype vergroten",
"decreaseFontSize": "Lettertype verkleinen",
"overrideAll": "Alle bestanden in doelmap vervangen",
"skipAll": "Alle conflicterende bestanden overslaan",
"renameAll": "Alle bestanden hernoemen (een kopie maken)",
"singleDecision": "Voor elk conflicterend bestand besluiten"
},
"download": {
"downloadFile": "Bestand downloaden",
"downloadFolder": "Map downloaden",
"downloadSelected": "Selectie downloaden"
},
"upload": {
"abortUpload": "Weet u zeker dat u wilt afbreken?"
},
"errors": {
"forbidden": "U hebt hier geen toegangsrechten.",
"internal": "Er ging iets mis.",
"notFound": "Deze locatie kan niet worden bereikt.",
"connection": "De server kan niet worden bereikt."
},
"files": {
"body": "Inoud",
"closePreview": "Voorbeeld sluiten",
"files": "Bestanden",
"folders": "Mappen",
"home": "Thuis",
"lastModified": "Laatst aangepast",
"loading": "Laden...",
"lonely": "Het is hier wat leeg...",
"metadata": "Metagegevens",
"multipleSelectionEnabled": "Meervoudige selectie ingeschakeld",
"name": "Naam",
"size": "Grootte",
"sortByLastModified": "Sorteren op laatst aangepast",
"sortByName": "Sorteren op naam",
"sortBySize": "Sorteren op grootte",
"noPreview": "Geen voorbeeld beschikbaar voor dit bestand.",
"csvTooLarge": "CSV-bestand is te groot voor voorbeeld (>5MB). Download het om het te bekijken.",
"csvLoadFailed": "Laden van CSV-bestand is mislukt.",
"showingRows": "{count} rij(en) weergeven",
"columnSeparator": "Kolom-scheidingsteken",
"csvSeparators": {
"comma": "Komma (,)",
"semicolon": "Puntkomma (;)",
"both": "Beide (,) en (;)"
},
"fileEncoding": "Bestandscodering"
},
"help": {
"click": "selecteer bestand of map",
"ctrl": {
"click": "selecteer meerdere bestanden of mappen",
"f": "open zoekopdracht",
"s": "sla een bestand op of download de huidige map"
},
"del": "verwijder geselecteerde items",
"doubleClick": "open een bestand of map",
"esc": "wis de selectie en/of sluit het opdrachtvenster",
"f1": "deze informatie",
"f2": "hernoem bestand",
"help": "Hulp"
},
"login": {
"createAnAccount": "Account aanmaken",
"loginInstead": "Heeft al een account",
"password": "Wachtwoord",
"passwordConfirm": "Wachtwoord bevestigen",
"passwordsDontMatch": "Wachtwoorden komen niet overeen",
"signup": "Registeren",
"submit": "Inloggen",
"username": "Gebruikersnaam",
"usernameTaken": "Gebruikersnaam reeds in gebruik",
"wrongCredentials": "Inloggegevens zijn incorrect",
"passwordTooShort": "Wachtwoord moet minstens {min} tekens bevatten",
"logout_reasons": {
"inactivity": "U bent uitgelogd vanwege inactiviteit."
}
},
"permanent": "Permanent",
"prompts": {
"copy": "Kopiëren",
"copyMessage": "Kies een locatie om uw bestanden te kopiëren:",
"currentlyNavigating": "Navigeren op:",
"deleteMessageMultiple": "Weet u zeker dat u {count} bestand(en) wilt verwijderen?",
"deleteMessageSingle": "Weet u zeker dat u dit bestand/deze map wilt verwijderen?",
"deleteMessageShare": "Weet u zeker dat u deze gedeelde map ({path}) wilt verwijderen?",
"deleteUser": "Weet u zeker dat u deze gebruiker wilt verwijderen?",
"deleteTitle": "Bestanden verwijderen",
"displayName": "Weergavenaam:",
"download": "Bestanden downloaden",
"downloadMessage": "Kies het formaat dat u wilt downloaden.",
"error": "Er ging iets fout",
"fileInfo": "Bestandsinformatie",
"filesSelected": "{count} geselecteerde bestanden.",
"lastModified": "Laatst aangepast",
"move": "Verplaatsen",
"moveMessage": "Kies een nieuw Thuis voor uw bestand(en)/map(pen):",
"newArchetype": "Maak een nieuw bericht op basis van een archetype. Uw bestand wordt aangemaakt in de inhoudsmap.",
"newDir": "Nieuwe map",
"newDirMessage": "Voer een naam in voor de nieuwe map.",
"newFile": "Nieuw bestand",
"newFileMessage": "Voer een naam in voor het nieuwe bestand.",
"numberDirs": "Aantal mappen",
"numberFiles": "Aantal bestanden",
"rename": "Hernoemen",
"renameMessage": "Voer een nieuwe naam in voor",
"replace": "Vervangen",
"replaceMessage": "Een van de bestanden die u probeert te uploaden, geeft conflicten i.v.m. de naamgeving. Wilt u de bestaande bestanden vervangen?\n",
"schedule": "Plannen",
"scheduleMessage": "Kies een datum en tijd om de publicatie van dit bericht in te plannen.",
"show": "Weergeven",
"size": "Grootte",
"upload": "Uploaden",
"uploadFiles": "{files} bestanden uploaden...",
"uploadMessage": "Kies een optie bij de upload.",
"optionalPassword": "Optioneel wachtwoord",
"resolution": "Resolutie",
"discardEditorChanges": "Weet u zeker dat u de door u aangebrachte wijzigingen wilt weggooien?",
"replaceOrSkip": "Bestanden vervangen of overslaan",
"resolveConflict": "Welke bestanden wilt u behouden?",
"singleConflictResolve": "Als u beide versies selecteert, wordt er een nummer toegevoegd aan de naam van het gekopieerde bestand.",
"fastConflictResolve": "De doelmap daar bevat {count} bestanden met dezelfde naam.",
"uploadingFiles": "Bestanden uploaden",
"filesInOrigin": "Bestanden in origineel",
"filesInDest": "Bestanden in bestemming",
"override": "Overschrijven",
"skip": "Overslaan",
"forbiddenError": "Verboden Fout"
},
"search": {
"images": "Afbeeldingen",
"music": "Muziek",
"pdf": "PDF",
"pressToSearch": "Druk op enter om te zoeken...",
"search": "Zoeken...",
"typeToSearch": "Typ om te zoeken...",
"types": "Types",
"video": "Video"
},
"settings": {
"aceEditorTheme": "Ace editor-thema",
"admin": "Admin",
"administrator": "Beheerder",
"allowCommands": "Opdrachten uitvoeren",
"allowEdit": "Bestanden of mappen bewerken, hernoemen of verwijderen",
"allowNew": "Nieuwe bestanden of mappen aanmaken",
"allowPublish": "Nieuwe berichten en pagina's publiceren",
"allowSignup": "Gebruikers toestaan om zich te registreren",
"hideLoginButton": "De inlogknop verbergen van openbare pagina's",
"avoidChanges": "(leeg laten om wijzigingen te voorkomen)",
"branding": "Branding",
"brandingDirectoryPath": "Pad naar map met Branding",
"brandingHelp": "U kunt het uiterlijk van uw File Browser aanpassen door de naam te wijzigen, het logo te vervangen, aangepaste stijlen toe te voegen en zelfs externe links naar GitHub uit te schakelen.\nVoor meer informatie over custom branding, bekijk {0}.",
"changePassword": "Wachtwoord wijzigen",
"commandRunner": "Opdracht uitvoeren",
"commandRunnerHelp": "Hier kunt u opdrachten instellen die worden uitgevoerd in de benoemde gebeurtenissen. Noteer één opdracht per regel. De omgevingsvariabelen {0} en {1} zijn beschikbaar, waarbij {0} relatief is ten opzichte van {1}. Raadpleeg {2} voor meer informatie over deze functie en de beschikbare omgevingsvariabelen.",
"commandsUpdated": "Opdrachten bijgewerkt!",
"createUserDir": "Maak bij het aanmaken van een nieuwe gebruiker automatisch een thuismap aan",
"minimumPasswordLength": "Minimale wachtwoordlengte",
"tusUploads": "Uploads in brokken",
"tusUploadsHelp": "File Browser ondersteunt bestandsuploads in brokken, waardoor efficiënte, betrouwbare, hervatbare bestandsuploads kunnen worden verricht, zelfs over onbetrouwbare netwerken.",
"tusUploadsChunkSize": "Geeft de maximale grootte van een verzoek aan (directe uploads worden gebruikt voor kleinere uploads). U kunt een geheel getal invoeren dat de bytegrootte aangeeft, of een tekenreeks zoals 10MB, 1GB enz.",
"tusUploadsRetryCount": "Aantal nieuwe pogingen om uit te voeren als een deel niet kan worden geüpload.",
"userHomeBasePath": "Basispad voor Thuismappen van de gebruikers",
"userScopeGenerationPlaceholder": "Het bereik wordt automatisch gegenereeerd",
"createUserHomeDirectory": "Thuismap voor de gebruiker aanmaken",
"customStylesheet": "Aangepaste stylesheet",
"defaultUserDescription": "Dit zijn de standaardinstellingen voor nieuwe gebruikers.",
"disableExternalLinks": "Externe links uitschakelen (behalve documentatie)",
"disableUsedDiskPercentage": "Grafiek van gebruikte schijfruimte uitschakelen",
"documentation": "documentatie",
"examples": "Voorbeelden",
"executeOnShell": "Uitvoeren in opdrachtvenster",
"executeOnShellDescription": "File Browser voert de opdrachten standaard uit door het rechtstreeks oproepen van hun hun binaire bestanden. Als u ze in plaats daarvan wilt uitvoeren in een opdrachtvenster (zoals Bash of PowerShell), kunt u dit hier definiëren met de vereiste argumenten en vlaggen. Zo wordt de opdracht die u uitvoert, toegevoegd als een argument. Dit is van toepassing op zowel gebruikersopdrachten als event-hooks.",
"globalRules": "Dit is een algemene reeks toestaan/niet toestaan-regels welke van toepassing zijn op alle gebruikers. U kunt voor elke gebruiker specifieke regels definiëren om deze te overschrijven.",
"globalSettings": "Algemene instellingen",
"hideDotfiles": "dot-bestanden verbergen",
"insertPath": "Pad invoegen",
"insertRegex": "Regex-expressie invoegen",
"instanceName": "Naam van de instantie",
"language": "Taal",
"lockPassword": "Voorkomen dat de gebruiker het wachtwoord wijzigt",
"newPassword": "Uw nieuwe wachtwoord",
"newPasswordConfirm": "Uw nieuwe wachtwoord bevestigen",
"newUser": "Nieuwe gebruiker",
"password": "Wachtwoord",
"passwordUpdated": "Wachtwoord bijgewerkt!",
"path": "Pad",
"perm": {
"create": "Bestanden en mappen aanmaken",
"delete": "Bestanden en mappen verwijderen",
"download": "Downloaden",
"execute": "Opdrachten uitvoeren",
"modify": "Bestanden bewerken",
"rename": "Bestanden of mappen hernoemen of verplaatsen",
"share": "Bestanden delen"
},
"permissions": "Machtigingen",
"permissionsHelp": " kunt de gebruiker instellen als beheerder of de machtigingen afzonderlijk kiezen. Als u \"Beheerder\" selecteert, worden alle overige opties automatisch ingeschakeld. Het beheer van gebruikers blijft een privilege van een beheerder.\n",
"profileSettings": "Profielinstellingen",
"redirectAfterCopyMove": "Doorverwijzen naar bestemming na kopiëren/verplaatsen",
"ruleExample1": "voorkomt de toegang tot dot-bestanden (zoals .git, .gitignore) in elke map.\n",
"ruleExample2": "blokkeert de toegang tot het bestand met de naam Caddyfile in de hoofdmap van het bereik.",
"rules": "Regels",
"rulesHelp": "Hier kunt u voor deze specifieke gebruiker een reeks toestaan/niet toestaan-regels definiëren. De geblokkeerde bestanden verschijnen niet in de lijsten en zijn niet toegankelijk voor de gebruiker. Regex wordt ondersteund en paden zijn relatief ten opzichte van het bereik van gebruikers.\n",
"scope": "Bereik",
"setDateFormat": "Exacte datumformaat instellen",
"settingsUpdated": "Instellingen bijgewerkt!",
"shareDuration": "Duur van het delen",
"shareManagement": "Beheer van gedeelde mappen en bestanden",
"shareDeleted": "Delen opheffen!",
"singleClick": "Bestanden en mappen met een enkele klik openen",
"themes": {
"default": "Systeem standaard",
"dark": "Donker",
"light": "Licht",
"title": "Thema"
},
"user": "Gebruiker",
"userCommands": "Opdrachten",
"userCommandsHelp": "Een lijst met beschikbare opdrachten voor de gebruiker gescheiden door spaties. Voorbeeld:\n",
"userCreated": "Gebruiker aangemaakt!",
"userDefaults": "Standaardinstellingen van gebruiker",
"userDeleted": "Gebruiker verwijderd!",
"userManagement": "Gebruikers beheren",
"userUpdated": "Gebruiker bijgewerkt!",
"username": "Gebruikersnaam",
"users": "Gebruikers",
"currentPassword": "Uw huidige wachtwoord"
},
"sidebar": {
"help": "Hulp",
"hugoNew": "Hugo Nieuw",
"login": "Inloggen",
"logout": "Uitloggen",
"myFiles": "Mijn bestanden",
"newFile": "Nieuw bestand",
"newFolder": "Nieuwe map",
"preview": "Voorbeeld",
"settings": "Instellingen",
"signup": "Registeren",
"siteSettings": "Site-instellingen"
},
"success": {
"linkCopied": "Link gekopieerd!"
},
"time": {
"days": "Dagen",
"hours": "Uren",
"minutes": "Minuten",
"seconds": "Seconden",
"unit": "Tijdseenheid"
}
}
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Opptater",
"upload": "Last opp",
"openFile": "Open file",
"openDirect": "View raw",
"discardChanges": "Slett",
"stopSearch": "Stop searching",
"saveChanges": "Lagre Endringane ",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Nedlast filen",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "velg fil eller katalog",
@@ -159,7 +165,17 @@
"uploadMessage": "Velg et alternativ for opplasting.",
"optionalPassword": "Valgfritt passord",
"resolution": "Oppløysning",
"discardEditorChanges": "Er du sikker på at du vil forkaste endringene du har gjort?"
"discardEditorChanges": "Er du sikker på at du vil forkaste endringene du har gjort?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Bilde",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Aktualizuj",
"upload": "Wyślij",
"openFile": "Otwórz plik",
"openDirect": "Otwórz bezpośrednio",
"discardChanges": "Odrzuć",
"stopSearch": "Zatrzymaj wyszukiwanie",
"saveChanges": "Zapisz zmiany",
"editAsText": "Edytuj jako tekst",
"increaseFontSize": "Zwiększ rozmiar czcionki",
"decreaseFontSize": "Zmniejsz rozmiar czcionki"
"decreaseFontSize": "Zmniejsz rozmiar czcionki",
"overrideAll": "Zastąp wszystkie pliki w folderze docelowym",
"skipAll": "Pomiń wszystkie pliki powodujące konflikty",
"renameAll": "Zmień nazwy wszystkich plików (utwórz kopię)",
"singleDecision": "Podejmij decyzję dla każdego pliku powodującego konflikt"
},
"download": {
"downloadFile": "Pobierz plik",
@@ -88,7 +93,8 @@
"comma": "Przecinek (,)",
"semicolon": "Średnik (;)",
"both": "Zarówno (,), jak i (;)"
}
},
"fileEncoding": "Kodowanie pliku"
},
"help": {
"click": "zaznacz plik lub folder",
@@ -159,7 +165,17 @@
"uploadMessage": "Wybierz opcję przesyłania.",
"optionalPassword": "Opcjonalne hasło",
"resolution": "Rozdzielczość",
"discardEditorChanges": "Czy na pewno chcesz odrzucić wprowadzone zmiany?"
"discardEditorChanges": "Czy na pewno chcesz odrzucić wprowadzone zmiany?",
"replaceOrSkip": "Zastąp lub pomiń pliki",
"resolveConflict": "Które pliki chcesz zachować?",
"singleConflictResolve": "Jeśli wybierzesz obie wersje, do nazwy kopiowanego pliku zostanie dodany numer.",
"fastConflictResolve": "W folderze docelowym liczba plików o tej samej nazwie to {count}.",
"uploadingFiles": "Wysyłanie plików",
"filesInOrigin": "Pliki w miejscu pochodzenia",
"filesInDest": "Pliki w miejscu docelowym",
"override": "Zastąp",
"skip": "Pomiń",
"forbiddenError": "Błąd zabronionego dostępu"
},
"search": {
"images": "Obrazy",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Atualizar",
"upload": "Enviar",
"openFile": "Abrir",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Baixar arquivo",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "selecionar pasta ou arquivo",
@@ -159,7 +165,17 @@
"uploadMessage": "Selecione uma opção para enviar.",
"optionalPassword": "Senha opcional",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Imagens",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Atualizar",
"upload": "Enviar",
"openFile": "Open file",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Descarregar ficheiro",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "selecionar pasta ou ficheiro",
@@ -159,7 +165,17 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Imagens",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Actualizează",
"upload": "Încarcă",
"openFile": "Open file",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Descarcă fișier",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "alege fișier sau director",
@@ -159,7 +165,17 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Imagini",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Обновить",
"upload": "Загрузить",
"openFile": "Открыть файл",
"openDirect": "View raw",
"discardChanges": "Отказаться",
"stopSearch": "Stop searching",
"saveChanges": "Сохранить",
"editAsText": "Редактировать как текст",
"increaseFontSize": "Увеличить размер шрифта",
"decreaseFontSize": "Уменьшить размер шрифта"
"decreaseFontSize": "Уменьшить размер шрифта",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Скачать файл",
@@ -88,7 +93,8 @@
"comma": "Запятая (,)",
"semicolon": "Точка с запятой (;)",
"both": "Оба варианта — (,) и (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "выбрать файл или каталог",
@@ -159,7 +165,17 @@
"uploadMessage": "Выберите вариант для загрузки.",
"optionalPassword": "Необязательный пароль",
"resolution": "Разрешение",
"discardEditorChanges": "Вы действительно желаете отменить ваши правки?"
"discardEditorChanges": "Вы действительно желаете отменить ваши правки?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Изображения",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Aktualizovať",
"upload": "Nahrať",
"openFile": "Otvoriť súbor",
"openDirect": "View raw",
"discardChanges": "Zahodiť",
"stopSearch": "Stop searching",
"saveChanges": "Uložiť zmeny",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Stiahnuť súbor",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "vyberie súbor alebo priečinok",
@@ -159,7 +165,17 @@
"uploadMessage": "Zvoľte možnosť nahrávania.",
"optionalPassword": "Voliteľné heslo",
"resolution": "Rozlíšenie",
"discardEditorChanges": "Naozaj chcete zahodiť vykonané zmeny?"
"discardEditorChanges": "Naozaj chcete zahodiť vykonané zmeny?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Obrázky",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Uppdatera",
"upload": "Ladda upp",
"openFile": "Öppna fil",
"openDirect": "View raw",
"discardChanges": "Förkasta",
"stopSearch": "Stop searching",
"saveChanges": "Spara ändringar",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Ladda ner fil",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "välj fil eller mapp",
@@ -159,7 +165,17 @@
"uploadMessage": "Välj ett alternativ att ladda upp.",
"optionalPassword": "Valfritt lösenord",
"resolution": "Upplösning",
"discardEditorChanges": "Är du säker på att du vill förkasta ändringarna du gjort?"
"discardEditorChanges": "Är du säker på att du vill förkasta ändringarna du gjort?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Bilder",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Güncelle",
"upload": "Yükle",
"openFile": "Dosyayı aç",
"openDirect": "View raw",
"discardChanges": "Discard",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Dosyayı indir",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "dosya veya klasör seçin",
@@ -159,7 +165,17 @@
"uploadMessage": "Yüklemek için bir seçenek belirleyin.",
"optionalPassword": "İsteğe bağlı şifre",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Görseller",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Оновити",
"upload": "Вивантажити",
"openFile": "Відкрити файл",
"openDirect": "View raw",
"discardChanges": "Скасувати",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Завантажити файл",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "вибрати файл чи каталог",
@@ -159,7 +165,17 @@
"uploadMessage": "Виберіть варіант для вивантаження.",
"optionalPassword": "Необов'язковий пароль",
"resolution": "Розширення",
"discardEditorChanges": "Чи дійсно ви хочете скасувати поточні зміни?"
"discardEditorChanges": "Чи дійсно ви хочете скасувати поточні зміни?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Зображення",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "Cập nhật",
"upload": "Tải lên",
"openFile": "Mở tệp",
"openDirect": "View raw",
"discardChanges": "Hủy bỏ thay đổi",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Tải xuống tệp tin",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "chọn tập tin hoặc thư mục",
@@ -159,7 +165,17 @@
"uploadMessage": "Chọn một tùy chọn để tải lên.",
"optionalPassword": "Mật khẩu tùy chọn",
"resolution": "Độ phân giải",
"discardEditorChanges": "Bạn có chắc chắn muốn hủy bỏ các thay đổi đã thực hiện không?"
"discardEditorChanges": "Bạn có chắc chắn muốn hủy bỏ các thay đổi đã thực hiện không?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "Hình ảnh",
+20 -4
View File
@@ -42,12 +42,17 @@
"update": "更新",
"upload": "上传",
"openFile": "打开文件",
"openDirect": "View raw",
"discardChanges": "放弃更改",
"stopSearch": "停止搜索",
"saveChanges": "保存更改",
"editAsText": "以文本形式编辑",
"increaseFontSize": "增大字体大小",
"decreaseFontSize": "减小字体大小"
"decreaseFontSize": "减小字体大小",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "下载文件",
@@ -88,7 +93,8 @@
"comma": "逗号 (,)",
"semicolon": "分号 (;)",
"both": "逗号 (,) 和分号 (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "选择文件或文件夹",
@@ -159,7 +165,17 @@
"uploadMessage": "选择上传选项。",
"optionalPassword": "密码(选填,不填即无密码)",
"resolution": "分辨率",
"discardEditorChanges": "你确定要放弃所做的更改吗?"
"discardEditorChanges": "你确定要放弃所做的更改吗?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "图像",
@@ -232,7 +248,7 @@
"permissions": "权限",
"permissionsHelp": "你可以将该用户设置为管理员或单独选择各项权限。如果你选择了“管理员”,则其他的选项会被自动选中,同时该用户可以管理其他用户。\n",
"profileSettings": "个人设置",
"redirectAfterCopyMove": "Redirect to destination after copy/move",
"redirectAfterCopyMove": "复制/移动后转到目标位置",
"ruleExample1": "阻止用户访问所有文件夹下任何以 . 开头的文件(隐藏文件, 例如: .git, .gitignore)。\n",
"ruleExample2": "阻止用户访问其目录范围的根目录下名为 Caddyfile 的文件。",
"rules": "规则",
+19 -3
View File
@@ -42,12 +42,17 @@
"update": "更新",
"upload": "上傳",
"openFile": "開啟檔案",
"openDirect": "View raw",
"discardChanges": "放棄變更",
"stopSearch": "Stop searching",
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
"decreaseFontSize": "Decrease font size"
"decreaseFontSize": "Decrease font size",
"overrideAll": "Replace all files in destination folder",
"skipAll": "Skip all conflicting files",
"renameAll": "Rename all files (create a copy)",
"singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "下載檔案",
@@ -88,7 +93,8 @@
"comma": "Comma (,)",
"semicolon": "Semicolon (;)",
"both": "Both (,) and (;)"
}
},
"fileEncoding": "File Encoding"
},
"help": {
"click": "選擇檔案或目錄",
@@ -159,7 +165,17 @@
"uploadMessage": "選擇上傳項。",
"optionalPassword": "密碼(選填,不填即無密碼)",
"resolution": "解析度",
"discardEditorChanges": "你確定要放棄所做的變更嗎?"
"discardEditorChanges": "你確定要放棄所做的變更嗎?",
"replaceOrSkip": "Replace or skip files",
"resolveConflict": "Which files do you want to keep?",
"singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
"fastConflictResolve": "The destination folder there are {count} files with same name.",
"uploadingFiles": "Uploading files",
"filesInOrigin": "Files in origin",
"filesInDest": "Files in destination",
"override": "Overwrite",
"skip": "Skip",
"forbiddenError": "Forbidden Error"
},
"search": {
"images": "影像",
-3
View File
@@ -2,7 +2,6 @@ import { disableExternal } from "@/utils/constants";
import { createApp } from "vue";
import VueNumberInput from "@chenfengyuan/vue-number-input";
import VueLazyload from "vue-lazyload";
import { createVfm } from "vue-final-modal";
import Toast, { POSITION, useToast } from "vue-toastification";
import type {
ToastOptions,
@@ -27,7 +26,6 @@ dayjs.extend(relativeTime);
dayjs.extend(duration);
const pinia = createPinia(router);
const vfm = createVfm();
const app = createApp(App);
@@ -39,7 +37,6 @@ app.use(Toast, {
newestOnTop: true,
} satisfies PluginOptions);
app.use(vfm);
app.use(i18n);
app.use(pinia);
app.use(router);
+1 -1
View File
@@ -76,7 +76,7 @@ export const useLayoutStore = defineStore("layout", {
});
},
closeHovers() {
this.prompts.shift()?.close?.();
this.prompts.pop()?.close?.();
},
// easily reset state using `$reset`
clearLayout() {
+21
View File
@@ -21,6 +21,7 @@ interface Resource extends ResourceBase {
index: number;
subtitles?: string[];
content?: string;
rawContent?: ArrayBuffer;
}
interface ResourceItem extends ResourceBase {
@@ -51,9 +52,29 @@ type DownloadFormat =
interface ClipItem {
from: string;
name: string;
size?: number;
modified?: string;
}
interface BreadCrumb {
name: string;
url: string;
}
interface ConflictingItem {
lastModified: number | string | undefined;
size: number | undefined;
}
interface ConflictingResource {
index: number;
name: string;
origin: ConflictingItem;
dest: ConflictingItem;
checked: Array<"origin" | "dest">;
}
interface CsvData {
headers: string[];
rows: string[][];
}
+4
View File
@@ -10,4 +10,8 @@ declare global {
// TODO: no idea what the exact type is
__vue__: any;
}
interface HTMLElement {
clickOutsideEvent?: (event: Event) => void;
}
}
+1
View File
@@ -17,6 +17,7 @@ interface UploadEntry {
isDir: boolean;
fullPath?: string;
file?: File;
overwrite?: boolean;
}
type UploadList = UploadEntry[];
-64
View File
@@ -1,64 +0,0 @@
export interface CsvData {
headers: string[];
rows: string[][];
}
/**
* Parse CSV content into headers and rows
* Supports quoted fields and handles commas within quotes
*/
export function parseCSV(
content: string,
columnSeparator: Array<string>
): CsvData {
if (!content || content.trim().length === 0) {
return { headers: [], rows: [] };
}
const lines = content.split(/\r?\n/);
const result: string[][] = [];
for (const line of lines) {
if (line.trim().length === 0) continue;
const row: string[] = [];
let currentField = "";
let inQuotes = false;
for (let i = 0; i < line.length; i++) {
const char = line[i];
const nextChar = line[i + 1];
if (char === '"') {
if (inQuotes && nextChar === '"') {
// Escaped quote
currentField += '"';
i++; // Skip next quote
} else {
// Toggle quote state
inQuotes = !inQuotes;
}
} else if (columnSeparator.includes(char) && !inQuotes) {
// Field separator
row.push(currentField);
currentField = "";
} else {
currentField += char;
}
}
// Add the last field
row.push(currentField);
result.push(row);
}
if (result.length === 0) {
return { headers: [], rows: [] };
}
// First row is headers
const headers = result[0];
const rows = result.slice(1);
return { headers, rows };
}
+268
View File
@@ -0,0 +1,268 @@
export const availableEncodings = [
// encodings
"utf-8",
"ibm866",
"iso-8859-2",
"iso-8859-3",
"iso-8859-4",
"iso-8859-5",
"iso-8859-6",
"iso-8859-7",
"iso-8859-8",
"iso-8859-8-i",
"iso-8859-10",
"iso-8859-13",
"iso-8859-14",
"iso-8859-15",
"iso-8859-16",
"koi8-r",
"koi8-u",
"macintosh",
"windows-874",
"windows-1250",
"windows-1251",
"windows-1252",
"windows-1253",
"windows-1254",
"windows-1255",
"windows-1256",
"windows-1257",
"windows-1258",
"x-mac-cyrillic",
"gbk",
"gb18030",
"big5",
"euc-jp",
"iso-2022-jp",
"shift_jis",
"euc-kr",
"utf-16be",
"utf-16le",
// label encodings
"unicode-1-1-utf-8",
"utf8",
"866",
"cp866",
"csibm866",
"csisolatin2",
"iso-ir-101",
"iso8859-2",
"iso88592",
"iso_8859-2",
"iso_8859-2:1987",
"l2",
"latin2",
"csisolatin3",
"iso-ir-109",
"iso8859-3",
"iso88593",
"iso_8859-3",
"iso_8859-3:1988",
"l3",
"latin3",
"csisolatin4",
"iso-ir-110",
"iso8859-4",
"iso88594",
"iso_8859-4",
"iso_8859-4:1988",
"l4",
"latin4",
"csisolatincyrillic",
"cyrillic",
"iso-ir-144",
"iso88595",
"iso_8859-5",
"iso_8859-5:1988",
"arabic",
"asmo-708",
"csiso88596e",
"csiso88596i",
"csisolatinarabic",
"ecma-114",
"iso-8859-6-e",
"iso-8859-6-i",
"iso-ir-127",
"iso8859-6",
"iso88596",
"iso_8859-6",
"iso_8859-6:1987",
"csisolatingreek",
"ecma-118",
"elot_928",
"greek",
"greek8",
"iso-ir-126",
"iso8859-7",
"iso88597",
"iso_8859-7",
"iso_8859-7:1987",
"sun_eu_greek",
"csiso88598e",
"csisolatinhebrew",
"hebrew",
"iso-8859-8-e",
"iso-ir-138",
"iso8859-8",
"iso88598",
"iso_8859-8",
"iso_8859-8:1988",
"visual",
"csiso88598i",
"logical",
"csisolatin6",
"iso-ir-157",
"iso8859-10",
"iso885910",
"l6",
"latin6",
"iso8859-13",
"iso885913",
"iso8859-14",
"iso885914",
"csisolatin9",
"iso8859-15",
"iso885915",
"l9",
"latin9",
"cskoi8r",
"koi",
"koi8",
"koi8_r",
"csmacintosh",
"mac",
"x-mac-roman",
"dos-874",
"iso-8859-11",
"iso8859-11",
"iso885911",
"tis-620",
"cp1250",
"x-cp1250",
"cp1251",
"x-cp1251",
"ansi_x3.4-1968",
"ascii",
"cp1252",
"cp819",
"csisolatin1",
"ibm819",
"iso-8859-1",
"iso-ir-100",
"iso8859-1",
"iso88591",
"iso_8859-1",
"iso_8859-1:1987",
"l1",
"latin1",
"us-ascii",
"x-cp1252",
"cp1253",
"x-cp1253",
"cp1254",
"csisolatin5",
"iso-8859-9",
"iso-ir-148",
"iso8859-9",
"iso88599",
"iso_8859-9",
"iso_8859-9:1989",
"l5",
"latin5",
"x-cp1254",
"cp1255",
"x-cp1255",
"cp1256",
"x-cp1256",
"cp1257",
"x-cp1257",
"cp1258",
"x-cp1258",
"x-mac-ukrainian",
"chinese",
"csgb2312",
"csiso58gb231280",
"gb2312",
"gb_2312",
"gb_2312-80",
"iso-ir-58",
"x-gbk",
"big5-hkscs",
"cn-big5",
"csbig5",
"x-x-big5",
"cseucpkdfmtjapanese",
"x-euc-jp",
"csiso2022jp",
"csshiftjis",
"ms_kanji",
"shift-jis",
"sjis",
"windows-31j",
"x-sjis",
"cseuckr",
"csksc56011987",
"iso-ir-149",
"korean",
"ks_c_5601-1987",
"ks_c_5601-1989",
"ksc5601",
"ksc_5601",
"windows-949",
"utf-16",
];
export function decode(content: ArrayBuffer, encoding: string): string {
const decoder = new TextDecoder(encoding);
return decoder.decode(content);
}
export function isEncodableResponse(url: string): boolean {
const extensions = [".csv"];
if (typeof TextDecoder === "undefined") {
return false;
}
for (const extension of extensions) {
if (url.endsWith(extension)) {
return true;
}
}
return false;
}
export async function makeRawResource(
res: Response,
url: string
): Promise<Resource> {
const buffer = await res.arrayBuffer();
return {
items: [],
numDirs: 0,
numFiles: 0,
sorting: {} as Sorting,
index: 0,
extension: getExtension(url),
isDir: false,
isSymlink: false,
path: url,
size: buffer.byteLength,
modified: new Date().toISOString(),
name: url.split("/").pop() || "",
type: "text",
mode: 0,
url: `/files${url}`,
rawContent: buffer,
content: decode(buffer, "utf-8"),
};
}
function getExtension(url: string): string {
const lastDotIndex = url.lastIndexOf(".");
if (lastDotIndex === -1) {
return "";
}
return url.substring(lastDotIndex);
}
+22
View File
@@ -4,3 +4,25 @@ import { partial } from "filesize";
* Formats filesize as KiB/MiB/...
*/
export const filesize = partial({ base: 2 });
export const vClickOutside = {
created(el: HTMLElement, binding: any) {
el.clickOutsideEvent = (event: Event) => {
const target = event.target;
if (target instanceof Node) {
if (!el.contains(target)) {
binding.value(event);
}
}
};
document.addEventListener("click", el.clickOutsideEvent);
},
unmounted(el: HTMLElement) {
if (el.clickOutsideEvent) {
document.removeEventListener("click", el.clickOutsideEvent);
}
},
};
+35 -6
View File
@@ -3,16 +3,24 @@ import { useUploadStore } from "@/stores/upload";
import url from "@/utils/url";
export function checkConflict(
files: UploadList,
files: UploadList | Array<any>,
dest: ResourceItem[]
): boolean {
): ConflictingResource[] {
if (typeof dest === "undefined" || dest === null) {
dest = [];
}
const conflictingFiles: ConflictingResource[] = [];
const folder_upload = files[0].fullPath !== undefined;
const names = new Set<string>();
function getFile(name: string): ResourceItem | null {
for (const item of dest) {
if (item.name == name) return item;
}
return null;
}
for (let i = 0; i < files.length; i++) {
const file = files[i];
let name = file.name;
@@ -24,10 +32,25 @@ export function checkConflict(
}
}
names.add(name);
const item = getFile(name);
if (item != null) {
conflictingFiles.push({
index: i,
name: item.path,
origin: {
lastModified: file.modified || file.file?.lastModified,
size: file.size,
},
dest: {
lastModified: item.modified,
size: item.size,
},
checked: ["origin"],
});
}
}
return dest.some((d) => names.has(d.name));
return conflictingFiles;
}
export function scanFiles(dt: DataTransfer): Promise<UploadList | FileList> {
@@ -146,6 +169,12 @@ export function handleFiles(
const type = file.isDir ? "dir" : detectType((file.file as File).type);
uploadStore.upload(path, file.name, file.file ?? null, overwrite, type);
uploadStore.upload(
path,
file.name,
file.file ?? null,
file.overwrite || overwrite,
type
);
}
}
+42 -19
View File
@@ -94,6 +94,7 @@ import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
import { getEditorTheme } from "@/utils/theme";
import { marked } from "marked";
import markedKatex from "marked-katex-extension";
import { inject, onBeforeUnmount, onMounted, ref, watchEffect } from "vue";
import { useI18n } from "vue-i18n";
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
@@ -118,6 +119,11 @@ const previewContent = ref("");
const isMarkdownFile =
fileStore.req?.name.endsWith(".md") ||
fileStore.req?.name.endsWith(".markdown");
const katexOptions = {
output: "mathml" as const,
throwOnError: false,
};
marked.use(markedKatex(katexOptions));
const isSelectionEmpty = ref(true);
@@ -171,25 +177,19 @@ onMounted(() => {
`https://cdn.jsdelivr.net/npm/ace-builds@${ace_version}/src-min-noconflict/`
);
editor.value = ace.edit("editor", {
value: fileContent,
showPrintMargin: false,
readOnly: fileStore.req?.type === "textImmutable",
theme: getEditorTheme(authStore.user?.aceEditorTheme ?? ""),
mode: modelist.getModeForPath(fileStore.req!.name).mode,
wrap: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
});
editor.value.setFontSize(fontSize.value);
editor.value.focus();
editor.value.getSelection().on("changeSelection", () => {
isSelectionEmpty.value =
editor.value == null || editor.value.getSelectedText().length == 0;
});
if (!layoutStore.loading) {
initEditor(fileContent);
} else {
const unwatch = watchEffect(() => {
// Initialize editor when layout is loaded
if (!layoutStore.loading) {
setTimeout(() => {
initEditor(fileContent);
unwatch();
}, 50);
}
});
}
});
onBeforeUnmount(() => {
@@ -218,6 +218,28 @@ onBeforeRouteUpdate((to, from, next) => {
});
});
const initEditor = (fileContent: string) => {
editor.value = ace.edit("editor", {
value: fileContent,
showPrintMargin: false,
readOnly: fileStore.req?.type === "textImmutable",
theme: getEditorTheme(authStore.user?.aceEditorTheme ?? ""),
mode: modelist.getModeForPath(fileStore.req!.name).mode,
wrap: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
});
editor.value.setFontSize(fontSize.value);
editor.value.focus();
const selection = editor.value?.getSelection();
selection.on("changeSelection", function () {
isSelectionEmpty.value = selection.isEmpty();
});
};
const keyEvent = (event: KeyboardEvent) => {
if (event.code === "Escape") {
close();
@@ -279,6 +301,7 @@ const close = () => {
prompt: "discardEditorChanges",
confirm: (event: Event) => {
event.preventDefault();
editor.value?.session.getUndoManager().reset();
finishClose();
},
saveAction: async () => {
+71 -37
View File
@@ -628,6 +628,8 @@ const copyCut = (event: Event | KeyboardEvent): void => {
items.push({
from: fileStore.req.items[i].url,
name: fileStore.req.items[i].name,
size: fileStore.req.items[i].size,
modified: fileStore.req.items[i].modified,
});
}
@@ -651,7 +653,15 @@ const paste = (event: Event) => {
for (const item of clipboardStore.items) {
const from = item.from.endsWith("/") ? item.from.slice(0, -1) : item.from;
const to = route.path + encodeURIComponent(item.name);
items.push({ from, to, name: item.name });
items.push({
from,
to,
name: item.name,
size: item.size,
modified: item.modified,
overwrite: false,
rename: clipboardStore.path == route.path,
});
}
if (items.length === 0) {
@@ -660,7 +670,7 @@ const paste = (event: Event) => {
const preselect = removePrefix(route.path) + items[0].name;
let action = (overwrite: boolean, rename: boolean) => {
let action = (overwrite?: boolean, rename?: boolean) => {
api
.copy(items, overwrite, rename)
.then(() => {
@@ -683,34 +693,37 @@ const paste = (event: Event) => {
};
}
if (clipboardStore.path == route.path) {
action(false, true);
return;
}
const conflict = upload.checkConflict(items, fileStore.req!.items);
let overwrite = false;
let rename = false;
if (conflict) {
if (conflict.length > 0) {
layoutStore.showHover({
prompt: "replace-rename",
confirm: (event: Event, option: string) => {
overwrite = option == "overwrite";
rename = option == "rename";
prompt: "resolve-conflict",
props: {
conflict: conflict,
},
confirm: (event: Event, result: Array<ConflictingResource>) => {
event.preventDefault();
layoutStore.closeHovers();
action(overwrite, rename);
for (let i = result.length - 1; i >= 0; i--) {
const item = result[i];
if (item.checked.length == 2) {
items[item.index].rename = true;
} else if (item.checked.length == 1 && item.checked[0] == "origin") {
items[item.index].overwrite = true;
} else {
items.splice(item.index, 1);
}
}
if (items.length > 0) {
action();
}
},
});
return;
}
action(overwrite, rename);
action(false, false);
};
const columnsResize = () => {
@@ -806,20 +819,30 @@ const drop = async (event: DragEvent) => {
const preselect = removePrefix(path) + (files[0].fullPath || files[0].name);
if (conflict) {
if (conflict.length > 0) {
layoutStore.showHover({
prompt: "replace",
action: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
upload.handleFiles(files, path, false);
fileStore.preselect = preselect;
prompt: "resolve-conflict",
props: {
conflict: conflict,
isUploadAction: true,
},
confirm: (event: Event) => {
confirm: (event: Event, result: Array<ConflictingResource>) => {
event.preventDefault();
layoutStore.closeHovers();
upload.handleFiles(files, path, true);
fileStore.preselect = preselect;
for (let i = result.length - 1; i >= 0; i--) {
const item = result[i];
if (item.checked.length == 2) {
continue;
} else if (item.checked.length == 1 && item.checked[0] == "origin") {
files[item.index].overwrite = true;
} else {
files.splice(item.index, 1);
}
}
if (files.length > 0) {
upload.handleFiles(files, path, true);
fileStore.preselect = preselect;
}
},
});
@@ -852,18 +875,29 @@ const uploadInput = (event: Event) => {
const path = route.path.endsWith("/") ? route.path : route.path + "/";
const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
if (conflict) {
if (conflict.length > 0) {
layoutStore.showHover({
prompt: "replace",
action: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
upload.handleFiles(uploadFiles, path, false);
prompt: "resolve-conflict",
props: {
conflict: conflict,
isUploadAction: true,
},
confirm: (event: Event) => {
confirm: (event: Event, result: Array<ConflictingResource>) => {
event.preventDefault();
layoutStore.closeHovers();
upload.handleFiles(uploadFiles, path, true);
for (let i = result.length - 1; i >= 0; i--) {
const item = result[i];
if (item.checked.length == 2) {
continue;
} else if (item.checked.length == 1 && item.checked[0] == "origin") {
uploadFiles[item.index].overwrite = true;
} else {
uploadFiles.splice(item.index, 1);
}
}
if (uploadFiles.length > 0) {
upload.handleFiles(uploadFiles, path, true);
}
},
});
+26 -3
View File
@@ -46,6 +46,16 @@
:label="$t('buttons.download')"
@action="download"
/>
<action
:disabled="layoutStore.loading"
v-if="
['image', 'audio', 'video'].includes(fileStore.req?.type || '') &&
authStore.user?.perm.download
"
icon="open_in_new"
:label="t('buttons.openDirect')"
@action="openDirect"
/>
<action
:disabled="layoutStore.loading"
icon="info"
@@ -253,7 +263,7 @@ const hoverNav = ref<boolean>(false);
const autoPlay = ref<boolean>(false);
const previousRaw = ref<string>("");
const nextRaw = ref<string>("");
const csvContent = ref<string>("");
const csvContent = ref<ArrayBuffer | string>("");
const csvError = ref<string>("");
const player = ref<HTMLVideoElement | HTMLAudioElement | null>(null);
@@ -277,6 +287,10 @@ const downloadUrl = computed(() =>
fileStore.req ? api.getDownloadURL(fileStore.req, false) : ""
);
const directUrl = computed(() =>
fileStore.req ? api.getDownloadURL(fileStore.req, true) : ""
);
const previewUrl = computed(() => {
if (!fileStore.req) {
return "";
@@ -297,7 +311,11 @@ const isPdf = computed(() => fileStore.req?.extension.toLowerCase() == ".pdf");
const isEpub = computed(
() => fileStore.req?.extension.toLowerCase() == ".epub"
);
const isCsv = computed(() => fileStore.req?.extension.toLowerCase() == ".csv");
const isCsv = computed(
() =>
fileStore.req?.extension.toLowerCase() == ".csv" &&
fileStore.req.size <= CSV_MAX_SIZE
);
const isResizeEnabled = computed(() => resizePreview);
@@ -393,7 +411,11 @@ const updatePreview = async () => {
if (fileStore.req.size > CSV_MAX_SIZE) {
csvError.value = t("files.csvTooLarge");
} else {
csvContent.value = fileStore.req.content ?? "";
if (fileStore.req.rawContent != null) {
csvContent.value = fileStore.req.rawContent;
} else {
csvContent.value = fileStore.req.content ?? "";
}
}
}
@@ -466,6 +488,7 @@ const close = () => {
};
const download = () => window.open(downloadUrl.value);
const openDirect = () => window.open(directUrl.value);
const editAsText = () => {
router.push({ path: route.path, query: { edit: "true" } });
+39 -24
View File
@@ -15,19 +15,6 @@
:isDefault="false"
:isNew="isNew"
/>
<p v-if="isCurrentPasswordRequired">
<label for="currentPassword">{{
t("settings.currentPassword")
}}</label>
<input
class="input input--block"
type="password"
v-model="currentPassword"
id="currentPassword"
autocomplete="current-password"
/>
</p>
</div>
<div class="card-action">
@@ -77,7 +64,6 @@ const error = ref<StatusError>();
const originalUser = ref<IUser>();
const user = ref<IUser>();
const createUserDir = ref<boolean>(false);
const currentPassword = ref<string>("");
const isCurrentPasswordRequired = ref<boolean>(false);
const $showError = inject<IToastError>("$showError")!;
@@ -134,16 +120,30 @@ const fetchData = async () => {
}
};
const deletePrompt = () =>
layoutStore.showHover({ prompt: "deleteUser", confirm: deleteUser });
const deletePrompt = () => {
if (isCurrentPasswordRequired.value) {
layoutStore.showHover({
prompt: "current-password",
confirm: (event: Event, currentPassword: string) => {
event.preventDefault();
layoutStore.closeHovers();
deleteUser(currentPassword);
},
});
} else {
layoutStore.showHover({
prompt: "deleteUser",
confirm: () => deleteUser(""),
});
}
};
const deleteUser = async (e: Event) => {
e.preventDefault();
const deleteUser = async (currentPassword: string) => {
if (!user.value) {
return false;
}
try {
await api.remove(user.value.id, currentPassword.value);
await api.remove(user.value.id, currentPassword);
router.push({ path: "/settings/users" });
$showSuccess(t("settings.userDeleted"));
} catch (err) {
@@ -157,8 +157,25 @@ const deleteUser = async (e: Event) => {
return true;
};
const save = async (event: Event) => {
const save = (event: Event) => {
event.preventDefault();
if (isCurrentPasswordRequired.value) {
layoutStore.showHover({
prompt: "current-password",
confirm: (event: Event, currentPassword: string) => {
event.preventDefault();
layoutStore.closeHovers();
send(currentPassword);
},
});
} else {
send("");
}
return true;
};
const send = async (currentPassword: string) => {
if (!user.value) {
return false;
}
@@ -170,11 +187,11 @@ const save = async (event: Event) => {
...user.value,
};
const loc = await api.create(newUser, currentPassword.value);
const loc = await api.create(newUser, currentPassword);
router.push({ path: loc || "/settings/users" });
$showSuccess(t("settings.userCreated"));
} else {
await api.update(user.value, ["all"], currentPassword.value);
await api.update(user.value, ["all"], currentPassword);
if (user.value.id === authStore.user?.id) {
authStore.updateUser(user.value);
@@ -185,7 +202,5 @@ const save = async (event: Event) => {
} catch (e: any) {
$showError(e);
}
return true;
};
</script>
+1 -1
View File
@@ -14,7 +14,7 @@ const plugins = [
// defaults already drop IE support
targets: ["defaults"],
}),
compression({ include: /\.js$/i, deleteOriginalAssets: true }),
compression({ include: /\.js$/, deleteOriginalAssets: false }),
];
const resolve = {
+11 -10
View File
@@ -4,7 +4,7 @@ go 1.25
require (
github.com/asdine/storm/v3 v3.2.1
github.com/asticode/go-astisub v0.38.0
github.com/asticode/go-astisub v0.39.0
github.com/disintegration/imaging v1.6.2
github.com/dsoprea/go-exif/v3 v3.0.1
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568
@@ -16,18 +16,18 @@ require (
github.com/marusama/semaphore/v2 v2.5.0
github.com/mholt/archives v0.1.5
github.com/mitchellh/go-homedir v1.1.0
github.com/redis/go-redis/v9 v9.17.3
github.com/samber/lo v1.52.0
github.com/shirou/gopsutil/v4 v4.26.1
github.com/redis/go-redis/v9 v9.18.0
github.com/samber/lo v1.53.0
github.com/shirou/gopsutil/v4 v4.26.2
github.com/spf13/afero v1.15.0
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.11.1
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce
golang.org/x/crypto v0.47.0
golang.org/x/image v0.35.0
golang.org/x/text v0.33.0
golang.org/x/crypto v0.48.0
golang.org/x/image v0.36.0
golang.org/x/text v0.34.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
)
@@ -47,7 +47,7 @@ require (
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
github.com/ebitengine/purego v0.9.1 // indirect
github.com/ebitengine/purego v0.10.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
@@ -74,11 +74,12 @@ require (
github.com/ulikunitz/xz v0.5.15 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.etcd.io/bbolt v1.4.3 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/net v0.49.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/sys v0.41.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
+27 -20
View File
@@ -31,8 +31,8 @@ github.com/asticode/go-astikit v0.20.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xbl
github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
github.com/asticode/go-astikit v0.56.0 h1:DmD2p7YnvxiPdF0h+dRmos3bsejNEXbycENsY5JfBqw=
github.com/asticode/go-astikit v0.56.0/go.mod h1:fV43j20UZYfXzP9oBn33udkvCvDvCDhzjVqoLFuuYZE=
github.com/asticode/go-astisub v0.38.0 h1:Qh3IO8Cotn0wwok5maid7xqsIJTwn2DtABT1UajKJaI=
github.com/asticode/go-astisub v0.38.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8=
github.com/asticode/go-astisub v0.39.0 h1:j1/rFLRUH0TT2CW9YCtBek9lRdMp96oxaZm6vbgE96M=
github.com/asticode/go-astisub v0.39.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8=
github.com/asticode/go-astits v1.8.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ=
github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c=
github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
@@ -83,8 +83,8 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003142440-7a1927d49d9d/go.mod h1:LV
github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8=
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU=
github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
@@ -166,7 +166,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -202,8 +205,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/redis/go-redis/v9 v9.17.3 h1:fN29NdNrE17KttK5Ndf20buqfDZwGNgoUr9qjl1DQx4=
github.com/redis/go-redis/v9 v9.17.3/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs=
github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
@@ -212,10 +215,10 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/shirou/gopsutil/v4 v4.26.1 h1:TOkEyriIXk2HX9d4isZJtbjXbEjf5qyKPAzbzY0JWSo=
github.com/shirou/gopsutil/v4 v4.26.1/go.mod h1:medLI9/UNAb0dOI9Q3/7yWSqKkj00u+1tgY8nvv41pc=
github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM=
github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI=
github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik=
github.com/sorairolake/lzip-go v0.3.8/go.mod h1:JcBqGMV0frlxwrsE9sMWXDjqn3EeVf0/54YPsw66qkU=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
@@ -257,6 +260,8 @@ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3i
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
@@ -264,6 +269,8 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
@@ -276,8 +283,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -289,8 +296,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.35.0 h1:LKjiHdgMtO8z7Fh18nGY6KDcoEtVfsgLDPeLyguqb7I=
golang.org/x/image v0.35.0/go.mod h1:MwPLTVgvxSASsxdLzKrl8BRFuyqMyGhLwmC+TO1Sybk=
golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc=
golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -329,8 +336,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -370,8 +377,8 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -382,8 +389,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+1 -1
View File
@@ -56,7 +56,7 @@ var withHashFile = func(fn handleFunc) handleFunc {
filePath := ""
if file.IsDir {
basePath = filepath.Dir(basePath)
basePath = filepath.Clean(link.Path)
filePath = ifPath
}
+21
View File
@@ -36,10 +36,31 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
return errToStatus(err), err
}
encoding := r.Header.Get("X-Encoding")
if file.IsDir {
file.Sorting = d.user.Sorting
file.ApplySort()
return renderJSON(w, r, file)
} else if encoding == "true" {
if file.Type != "text" {
return renderJSON(w, r, file)
}
f, err := d.user.Fs.Open(r.URL.Path)
if err != nil {
return errToStatus(err), err
}
defer f.Close()
data, err := io.ReadAll(f)
if err != nil {
return http.StatusInternalServerError, err
}
w.Header().Set("Content-Type", "application/octet-stream")
w.WriteHeader(http.StatusOK)
_, err = w.Write(data)
return 0, err
}
if checksum := r.URL.Query().Get("checksum"); checksum != "" {
+23 -5
View File
@@ -5,6 +5,8 @@ import (
"errors"
"fmt"
"io/fs"
"io"
"compress/gzip"
"log"
"net/http"
"os"
@@ -144,16 +146,32 @@ func getStaticHandlers(store *storage.Storage, server *settings.Server, assetsFs
return 0, nil
}
fileContents, err := fs.ReadFile(assetsFs, r.URL.Path+".gz")
f, err := assetsFs.Open(r.URL.Path + ".gz")
if err != nil {
return http.StatusNotFound, err
}
defer f.Close()
w.Header().Set("Content-Encoding", "gzip")
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
acceptEncoding := r.Header.Get("Accept-Encoding")
if strings.Contains(acceptEncoding, "gzip") {
w.Header().Set("Content-Encoding", "gzip")
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
if _, err := w.Write(fileContents); err != nil {
return http.StatusInternalServerError, err
if _, err := io.Copy(w, f); err != nil {
return http.StatusInternalServerError, err
}
} else {
gzReader, err := gzip.NewReader(f)
if err != nil {
return http.StatusInternalServerError, err
}
defer gzReader.Close()
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
if _, err := io.Copy(w, gzReader); err != nil {
return http.StatusInternalServerError, err
}
}
return 0, nil
+1 -1
View File
@@ -240,7 +240,7 @@ func tusPatchHandler(cache UploadCache) handleFunc {
func tusDeleteHandler(cache UploadCache) handleFunc {
return withUser(func(_ http.ResponseWriter, r *http.Request, d *data) (int, error) {
if r.URL.Path == "/" || !d.user.Perm.Create {
if r.URL.Path == "/" || !d.user.Perm.Delete {
return http.StatusForbidden, nil
}
+1
View File
@@ -1,3 +1,4 @@
//nolint:revive
package version
var (