Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f46641b038 | ||
|
|
23bd8f6715 | ||
|
|
506fc08577 | ||
|
|
f33076462a | ||
|
|
6c29fabdc8 | ||
|
|
0268506f80 | ||
|
|
ad864a97e9 | ||
|
|
f714e71a35 | ||
|
|
dbdbbab4d7 | ||
|
|
7c0c7820ef | ||
|
|
2741616473 | ||
|
|
ffb858e4ef | ||
|
|
0ca8059d8d | ||
|
|
8ca080422f | ||
|
|
cbb712484d | ||
|
|
8a14018861 | ||
|
|
a493ec90ff | ||
|
|
33113036cd | ||
|
|
a02b2972eb | ||
|
|
e9bb3dc243 | ||
|
|
2e26393a02 | ||
|
|
04a13f086f | ||
|
|
1cc539eb8a | ||
|
|
6ebfdcceaa | ||
|
|
db671c227b | ||
|
|
4aee14de44 | ||
|
|
0cca7d8dc0 | ||
|
|
c34c0afecf | ||
|
|
56a0f9244b | ||
|
|
56b80b6d9b | ||
|
|
d9ebd65ffc | ||
|
|
a882fb6c85 | ||
|
|
5daae69a6d | ||
|
|
54a1ae0fa0 | ||
|
|
b6b4fb5da7 | ||
|
|
6d82a27f9a | ||
|
|
31a326606d | ||
|
|
abbf203bdd | ||
|
|
e82e2392a4 | ||
|
|
f4a8420bf3 | ||
|
|
71a8f5662c | ||
|
|
48f894740f | ||
|
|
b883e287a0 | ||
|
|
5d9f0977d6 | ||
|
|
c606a01a2d | ||
|
|
54b91b8ff0 | ||
|
|
a46acba5f9 | ||
|
|
1d14798653 | ||
|
|
6d55cc59f7 | ||
|
|
495e731ee7 | ||
|
|
ff1579b950 | ||
|
|
7a48fd0c3e | ||
|
|
cfea84fd5e | ||
|
|
0ba9505a19 | ||
|
|
5355629fd1 | ||
|
|
f8a16a6aca | ||
|
|
35d1c09243 | ||
|
|
99c64c12ed | ||
|
|
3d6c5152fe | ||
|
|
ba797cda31 | ||
|
|
5300d00d2e | ||
|
|
bbdd313705 | ||
|
|
045064f8b8 | ||
|
|
252f0a7533 | ||
|
|
1194cfe009 | ||
|
|
0201f9c5c4 | ||
|
|
cc331383fb | ||
|
|
d1c84a8412 | ||
|
|
e92dbb4bb8 | ||
|
|
209acf2429 | ||
|
|
25372edb5c | ||
|
|
d51a343820 | ||
|
|
065959451d | ||
|
|
2fdea73430 |
@@ -1,5 +1,3 @@
|
|||||||
*
|
*
|
||||||
!docker/*
|
!docker/*
|
||||||
!healthcheck.sh
|
!filebrowser
|
||||||
!docker_config.json
|
|
||||||
!filebrowser
|
|
||||||
|
|||||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -2,4 +2,4 @@
|
|||||||
# Unless a later match takes precedence, @o1egl will be requested for
|
# Unless a later match takes precedence, @o1egl will be requested for
|
||||||
# review when someone opens a pull request.
|
# review when someone opens a pull request.
|
||||||
|
|
||||||
* @o1egl
|
* @o1egl @hacdias
|
||||||
|
|||||||
22
.github/ISSUE_TEMPLATE/bug_report.md
vendored
22
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
---
|
|
||||||
|
|
||||||
**Description**
|
|
||||||
<!-- A clear and concise description of what the issue is about. What are you trying to do? -->
|
|
||||||
|
|
||||||
**Expected behaviour**
|
|
||||||
<!-- What did you expect to happen? -->
|
|
||||||
|
|
||||||
**What is happening instead?**
|
|
||||||
<!-- Please, give full error messages and/or log. -->
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
<!-- Add any other context about the problem here. If applicable, add screenshots to help explain your problem. -->
|
|
||||||
|
|
||||||
**How to reproduce?**
|
|
||||||
<!-- Tell us how to reproduce this issue. How can someone who is starting from scratch reproduce this behaviour as minimally as possible? -->
|
|
||||||
|
|
||||||
**Files**
|
|
||||||
<!-- A list of relevant files for this issue. Large files can be uploaded one-by-one or in a tarball/zipfile. -->
|
|
||||||
43
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
43
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: Report a bug in FileBrowser.
|
||||||
|
labels: [bug, triage]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Please verify that you've followed these steps
|
||||||
|
options:
|
||||||
|
- label: This is a bug report, not a question.
|
||||||
|
required: true
|
||||||
|
- label: I have searched on the [issue tracker](https://github.com/filebrowser/filebrowser/issues?q=is%3Aissue) for my bug.
|
||||||
|
required: true
|
||||||
|
- label: I am running the latest [FileBrowser version](https://github.com/filebrowser/filebrowser/releases) or have an issue updating.
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Version
|
||||||
|
render: Text
|
||||||
|
description: |
|
||||||
|
Enter the version of FileBrowser you are using.
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: |
|
||||||
|
A clear and concise description of what the issue is about. What are you trying to do?
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: What did you expect to happen?
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: What actually happened?
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Reproduction Steps
|
||||||
|
description: |
|
||||||
|
Tell us how to reproduce this issue. How can someone who is starting from scratch reproduce this behavior as minimally as possible?
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Files
|
||||||
|
description: |
|
||||||
|
A list of relevant files for this issue. Large files can be uploaded one-by-one or in a tarball/zipfile.
|
||||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: GitHub Discussions
|
||||||
|
url: https://github.com/filebrowser/filebrowser/discussions
|
||||||
|
about: Please ask questions and discuss features here.
|
||||||
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
<!-- Add a clear and concise description of what the problem is. E.g. *I'm always frustrated when [...]* -->
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
<!-- Add a clear and concise description of what you want to happen. -->
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
<!-- Add a clear and concise description of any alternative solutions or features you've considered. -->
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
<!-- Add any other context or screenshots about the feature request here. -->
|
|
||||||
27
.github/PULL_REQUEST_TEMPLATE.md
vendored
27
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,19 +1,16 @@
|
|||||||
**Description**
|
## Description
|
||||||
<!--
|
|
||||||
Please explain the changes you made here.
|
|
||||||
If the feature changes current behaviour, explain why your solution is better.
|
|
||||||
-->
|
|
||||||
|
|
||||||
:rotating_light: Before submitting your PR, please indicate which issues are either fixed or closed by this PR. See [GitHub Help: Closing issues using keywords](https://help.github.com/articles/closing-issues-via-commit-messages/).
|
<!-- Please explain the changes you made here. -->
|
||||||
|
|
||||||
- [ ] DO make sure you are requesting to **pull a topic/feature/bugfix branch** (right side). Don't request your master!
|
## Additional Information
|
||||||
- [ ] DO make sure you are making a pull request against the **master branch** (left side). Also you should start *your branch* off *our master*.
|
|
||||||
- [ ] DO make sure that File Browser can be successfully built. See [builds](https://github.com/filebrowser/community/blob/master/builds.md) and [development](https://github.com/filebrowser/community/blob/master/development.md).
|
|
||||||
- [ ] AVOID breaking the continuous integration build.
|
|
||||||
|
|
||||||
**Further comments**
|
<!-- If it is a relatively large or complex change, please add more information to explain what you did, how you did it, if you considered any alternatives, etc. -->
|
||||||
<!--
|
|
||||||
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did, what alternatives you considered, etc.
|
|
||||||
|
|
||||||
:heart: Thank you!
|
## Checklist
|
||||||
-->
|
|
||||||
|
Before submitting your PR, please indicate which issues are either fixed or closed by this PR. See [GitHub Help: Closing issues using keywords](https://help.github.com/articles/closing-issues-via-commit-messages/).
|
||||||
|
|
||||||
|
- [ ] I am aware the project is currently in maintenance-only mode. See [README](https://github.com/filebrowser/community/blob/master/README.md)
|
||||||
|
- [ ] I am aware that translations MUST be made through [Transifex](https://app.transifex.com/file-browser/file-browser/) and that this PR is NOT a translation update
|
||||||
|
- [ ] I am making a PR against the `master` branch.
|
||||||
|
- [ ] I am sure File Browser can be successfully built. See [builds](https://github.com/filebrowser/community/blob/master/builds.md) and [development](https://github.com/filebrowser/community/blob/master/development.md).
|
||||||
|
|||||||
31
.github/workflows/main.yaml
vendored
31
.github/workflows/main.yaml
vendored
@@ -3,20 +3,25 @@ name: main
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- "master"
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- "v*"
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# linters
|
# linters
|
||||||
lint-frontend:
|
lint-frontend:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
package_json_file: "frontend/package.json"
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: "22.x"
|
||||||
|
cache: "pnpm"
|
||||||
|
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
||||||
- run: make lint-frontend
|
- run: make lint-frontend
|
||||||
lint-backend:
|
lint-backend:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -32,14 +37,19 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- run: echo "done"
|
- run: echo "done"
|
||||||
|
|
||||||
# tests
|
# tests
|
||||||
test-frontend:
|
test-frontend:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
package_json_file: "frontend/package.json"
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: "22.x"
|
||||||
|
cache: "pnpm"
|
||||||
|
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
||||||
- run: make test-frontend
|
- run: make test-frontend
|
||||||
test-backend:
|
test-backend:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -55,7 +65,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- run: echo "done"
|
- run: echo "done"
|
||||||
|
|
||||||
# release
|
# release
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [lint, test]
|
needs: [lint, test]
|
||||||
@@ -67,9 +77,14 @@ jobs:
|
|||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.23.0
|
go-version: 1.23.0
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
package_json_file: "frontend/package.json"
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: "22.x"
|
||||||
|
cache: "pnpm"
|
||||||
|
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v1
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
|
|||||||
24
.github/workflows/stale.yml
vendored
24
.github/workflows/stale.yml
vendored
@@ -1,24 +0,0 @@
|
|||||||
name: 'Close stale issues and PRs'
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '30 1 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v9
|
|
||||||
with:
|
|
||||||
stale-pr-message: 'This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
|
|
||||||
close-pr-message: 'This PR was closed because it has been stalled for 5 days with no activity.'
|
|
||||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
|
|
||||||
close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
|
|
||||||
days-before-stale: 30
|
|
||||||
days-before-close: 5
|
|
||||||
exempt-issue-labels: 'feature ☘,enhancement ⚙,bug 🐞'
|
|
||||||
exempt-pr-labels: 'need-help,wip'
|
|
||||||
operations-per-run: 100
|
|
||||||
@@ -19,31 +19,30 @@ builds:
|
|||||||
- freebsd
|
- freebsd
|
||||||
goarch:
|
goarch:
|
||||||
- amd64
|
- amd64
|
||||||
- 386
|
- "386"
|
||||||
- arm
|
- arm
|
||||||
- arm64
|
- arm64
|
||||||
- riscv64
|
- riscv64
|
||||||
goarm:
|
goarm:
|
||||||
- 5
|
- "5"
|
||||||
- 6
|
- "6"
|
||||||
- 7
|
- "7"
|
||||||
ignore:
|
ignore:
|
||||||
- goos: darwin
|
- goos: darwin
|
||||||
goarch: 386
|
goarch: "386"
|
||||||
- goos: freebsd
|
- goos: freebsd
|
||||||
goarch: arm
|
goarch: arm
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
-
|
- name_template: "{{.Os}}-{{.Arch}}{{if .Arm}}v{{.Arm}}{{end}}-{{ .ProjectName }}"
|
||||||
name_template: "{{.Os}}-{{.Arch}}{{if .Arm}}v{{.Arm}}{{end}}-{{ .ProjectName }}"
|
formats: ["tar.gz"]
|
||||||
format: tar.gz
|
|
||||||
format_overrides:
|
format_overrides:
|
||||||
- goos: windows
|
- goos: windows
|
||||||
format: zip
|
formats: ["zip"]
|
||||||
|
|
||||||
dockers:
|
dockers:
|
||||||
-
|
# Alpine docker images
|
||||||
dockerfile: Dockerfile
|
- dockerfile: Dockerfile
|
||||||
use: buildx
|
use: buildx
|
||||||
build_flag_templates:
|
build_flag_templates:
|
||||||
- "--pull"
|
- "--pull"
|
||||||
@@ -59,10 +58,8 @@ dockers:
|
|||||||
- "filebrowser/filebrowser:{{ .Tag }}-amd64"
|
- "filebrowser/filebrowser:{{ .Tag }}-amd64"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-amd64"
|
- "filebrowser/filebrowser:v{{ .Major }}-amd64"
|
||||||
extra_files:
|
extra_files:
|
||||||
- docker_config.json
|
- docker
|
||||||
- healthcheck.sh
|
- dockerfile: Dockerfile
|
||||||
-
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
use: buildx
|
use: buildx
|
||||||
build_flag_templates:
|
build_flag_templates:
|
||||||
- "--pull"
|
- "--pull"
|
||||||
@@ -78,10 +75,8 @@ dockers:
|
|||||||
- "filebrowser/filebrowser:{{ .Tag }}-arm64"
|
- "filebrowser/filebrowser:{{ .Tag }}-arm64"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-arm64"
|
- "filebrowser/filebrowser:v{{ .Major }}-arm64"
|
||||||
extra_files:
|
extra_files:
|
||||||
- docker_config.json
|
- docker
|
||||||
- healthcheck.sh
|
- dockerfile: Dockerfile
|
||||||
-
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
use: buildx
|
use: buildx
|
||||||
build_flag_templates:
|
build_flag_templates:
|
||||||
- "--pull"
|
- "--pull"
|
||||||
@@ -93,15 +88,13 @@ dockers:
|
|||||||
- "--platform=linux/arm/v6"
|
- "--platform=linux/arm/v6"
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: arm
|
goarch: arm
|
||||||
goarm: '6'
|
goarm: "6"
|
||||||
image_templates:
|
image_templates:
|
||||||
- "filebrowser/filebrowser:{{ .Tag }}-armv6"
|
- "filebrowser/filebrowser:{{ .Tag }}-armv6"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-armv6"
|
- "filebrowser/filebrowser:v{{ .Major }}-armv6"
|
||||||
extra_files:
|
extra_files:
|
||||||
- docker_config.json
|
- docker
|
||||||
- healthcheck.sh
|
- dockerfile: Dockerfile
|
||||||
-
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
use: buildx
|
use: buildx
|
||||||
build_flag_templates:
|
build_flag_templates:
|
||||||
- "--pull"
|
- "--pull"
|
||||||
@@ -113,16 +106,15 @@ dockers:
|
|||||||
- "--platform=linux/arm/v7"
|
- "--platform=linux/arm/v7"
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: arm
|
goarch: arm
|
||||||
goarm: '7'
|
goarm: "7"
|
||||||
image_templates:
|
image_templates:
|
||||||
- "filebrowser/filebrowser:{{ .Tag }}-armv7"
|
- "filebrowser/filebrowser:{{ .Tag }}-armv7"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-armv7"
|
- "filebrowser/filebrowser:v{{ .Major }}-armv7"
|
||||||
extra_files:
|
extra_files:
|
||||||
- docker_config.json
|
- docker
|
||||||
- healthcheck.sh
|
|
||||||
## s6 based docker images
|
## s6-overlay docker images
|
||||||
-
|
- dockerfile: Dockerfile.s6
|
||||||
dockerfile: Dockerfile.s6
|
|
||||||
use: buildx
|
use: buildx
|
||||||
build_flag_templates:
|
build_flag_templates:
|
||||||
- "--pull"
|
- "--pull"
|
||||||
@@ -138,9 +130,8 @@ dockers:
|
|||||||
- "filebrowser/filebrowser:{{ .Tag }}-amd64-s6"
|
- "filebrowser/filebrowser:{{ .Tag }}-amd64-s6"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-amd64-s6"
|
- "filebrowser/filebrowser:v{{ .Major }}-amd64-s6"
|
||||||
extra_files:
|
extra_files:
|
||||||
- docker/root
|
- docker
|
||||||
-
|
- dockerfile: Dockerfile.s6.aarch64
|
||||||
dockerfile: Dockerfile.s6.aarch64
|
|
||||||
use: buildx
|
use: buildx
|
||||||
build_flag_templates:
|
build_flag_templates:
|
||||||
- "--pull"
|
- "--pull"
|
||||||
@@ -156,7 +147,8 @@ dockers:
|
|||||||
- "filebrowser/filebrowser:{{ .Tag }}-arm64-s6"
|
- "filebrowser/filebrowser:{{ .Tag }}-arm64-s6"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-arm64-s6"
|
- "filebrowser/filebrowser:v{{ .Major }}-arm64-s6"
|
||||||
extra_files:
|
extra_files:
|
||||||
- docker/root
|
- docker
|
||||||
|
|
||||||
docker_manifests:
|
docker_manifests:
|
||||||
- name_template: "filebrowser/filebrowser:latest"
|
- name_template: "filebrowser/filebrowser:latest"
|
||||||
image_templates:
|
image_templates:
|
||||||
@@ -173,7 +165,7 @@ docker_manifests:
|
|||||||
- "filebrowser/filebrowser:v{{ .Major }}-amd64"
|
- "filebrowser/filebrowser:v{{ .Major }}-amd64"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-arm64"
|
- "filebrowser/filebrowser:v{{ .Major }}-arm64"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-armv7"
|
- "filebrowser/filebrowser:v{{ .Major }}-armv7"
|
||||||
## s6 image manifests
|
## s6 image manifests
|
||||||
- name_template: "filebrowser/filebrowser:s6"
|
- name_template: "filebrowser/filebrowser:s6"
|
||||||
image_templates:
|
image_templates:
|
||||||
- "filebrowser/filebrowser:{{ .Tag }}-amd64-s6"
|
- "filebrowser/filebrowser:{{ .Tag }}-amd64-s6"
|
||||||
@@ -186,15 +178,20 @@ docker_manifests:
|
|||||||
image_templates:
|
image_templates:
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-amd64-s6"
|
- "filebrowser/filebrowser:v{{ .Major }}-amd64-s6"
|
||||||
- "filebrowser/filebrowser:v{{ .Major }}-arm64-s6"
|
- "filebrowser/filebrowser:v{{ .Major }}-arm64-s6"
|
||||||
brews:
|
|
||||||
|
homebrew_casks:
|
||||||
- name: filebrowser
|
- name: filebrowser
|
||||||
repository:
|
repository:
|
||||||
owner: filebrowser
|
owner: filebrowser
|
||||||
name: homebrew-tap
|
name: homebrew-tap
|
||||||
directory: Formula
|
|
||||||
homepage: https://filebrowser.org
|
|
||||||
commit_author:
|
commit_author:
|
||||||
name: FileBrowser Robot
|
name: FileBrowser Robot
|
||||||
email: robot@filebrowser.org
|
email: robot@filebrowser.org
|
||||||
|
homepage: https://github.com/filebrowser/filebrowser
|
||||||
description: File Browser is a create-your-own-cloud-kind of software where you can install it on a server, direct it to a path and then access your files through a nice web interface
|
description: File Browser is a create-your-own-cloud-kind of software where you can install it on a server, direct it to a path and then access your files through a nice web interface
|
||||||
license: "MIT"
|
hooks:
|
||||||
|
post:
|
||||||
|
install: |
|
||||||
|
if system_command("/usr/bin/xattr", args: ["-h"]).exit_status == 0
|
||||||
|
system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/filebrowser"]
|
||||||
|
end
|
||||||
|
|||||||
10
.tx/config
10
.tx/config
@@ -1,10 +0,0 @@
|
|||||||
[main]
|
|
||||||
host = https://www.transifex.com
|
|
||||||
lang_map = pt_BR: pt-br, zh_CN: zh-cn, zh_HK: zh-hk, zh_TW: zh-tw, nl_BE: nl-be, sv_SE: sv-se, cz-CS: cz_cs
|
|
||||||
|
|
||||||
[file-browser.file-browser]
|
|
||||||
file_filter = frontend/src/i18n/<lang>.json
|
|
||||||
minimum_perc = 50
|
|
||||||
source_file = frontend/src/i18n/en.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
122
CHANGELOG.md
122
CHANGELOG.md
@@ -2,6 +2,128 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
|
### [2.33.6](https://github.com/filebrowser/filebrowser/compare/v2.33.5...v2.33.6) (2025-06-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove incorrect default for password flag ([23bd8f6](https://github.com/filebrowser/filebrowser/commit/23bd8f67155081d707d4799393d3b1e2bebeaa34))
|
||||||
|
|
||||||
|
### [2.33.5](https://github.com/filebrowser/filebrowser/compare/v2.33.4...v2.33.5) (2025-06-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* update languages for project File Browser ([#5190](https://github.com/filebrowser/filebrowser/issues/5190)) ([f330764](https://github.com/filebrowser/filebrowser/commit/f33076462a133935ca97fb6c7345303fe350e167))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* actually register the czech language ([#5189](https://github.com/filebrowser/filebrowser/issues/5189)) ([0268506](https://github.com/filebrowser/filebrowser/commit/0268506f80d33d2d31e38055e12530241d27a11b))
|
||||||
|
|
||||||
|
### [2.33.4](https://github.com/filebrowser/filebrowser/compare/v2.33.3...v2.33.4) (2025-06-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* translation updates for project File Browser ([#5179](https://github.com/filebrowser/filebrowser/issues/5179)) ([f714e71](https://github.com/filebrowser/filebrowser/commit/f714e71a356c2301f394d651c9b6c467440508e3))
|
||||||
|
|
||||||
|
### [2.33.3](https://github.com/filebrowser/filebrowser/compare/v2.33.2...v2.33.3) (2025-06-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* keep command behavior in Dockerfile ([7c0c782](https://github.com/filebrowser/filebrowser/commit/7c0c7820efbbed2f0499353cc76ecb85d00ff7c3))
|
||||||
|
* update search hotkey in help prompt ([#5178](https://github.com/filebrowser/filebrowser/issues/5178)) ([2741616](https://github.com/filebrowser/filebrowser/commit/2741616473636d40b7e9f14c9906ada08d328c3c))
|
||||||
|
|
||||||
|
### [2.33.2](https://github.com/filebrowser/filebrowser/compare/v2.33.1...v2.33.2) (2025-06-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* create user dir on signup ([0ca8059](https://github.com/filebrowser/filebrowser/commit/0ca8059d8dea4fe079146471ce4f24acc96021f2))
|
||||||
|
|
||||||
|
### [2.33.1](https://github.com/filebrowser/filebrowser/compare/v2.33.0...v2.33.1) (2025-06-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* downloadUrl of file preview ([#3728](https://github.com/filebrowser/filebrowser/issues/3728)) ([8a14018](https://github.com/filebrowser/filebrowser/commit/8a14018861fe581672bbd27cdc3ae5691f70a108))
|
||||||
|
* remove auth query parameter from download and preview links ([cbb7124](https://github.com/filebrowser/filebrowser/commit/cbb712484d3bdabc033acaf3b696ef4f5865813d))
|
||||||
|
* search uses ctrl+shift+f instead of hijacking browser's ctrl+f ([#4638](https://github.com/filebrowser/filebrowser/issues/4638)) ([a02b297](https://github.com/filebrowser/filebrowser/commit/a02b2972ebde2a58806ad1377bad46e748b63166))
|
||||||
|
|
||||||
|
## [2.33.0](https://github.com/filebrowser/filebrowser/compare/v2.32.3...v2.33.0) (2025-06-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* improved docker image volumes and permissions ([#5160](https://github.com/filebrowser/filebrowser/issues/5160)) ([2e26393](https://github.com/filebrowser/filebrowser/commit/2e26393a022df0eaa9e08727407aba8b997aa728))
|
||||||
|
|
||||||
|
### [2.32.3](https://github.com/filebrowser/filebrowser/compare/v2.32.2...v2.32.3) (2025-06-17)
|
||||||
|
|
||||||
|
### [2.32.2](https://github.com/filebrowser/filebrowser/compare/v2.32.1...v2.32.2) (2025-06-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* updated for project File Browser ([#5159](https://github.com/filebrowser/filebrowser/issues/5159)) ([c34c0af](https://github.com/filebrowser/filebrowser/commit/c34c0afecf3242b16ad5d5584cd90a6ad323361c))
|
||||||
|
|
||||||
|
### [2.32.1](https://github.com/filebrowser/filebrowser/compare/v2.32.0...v2.32.1) (2025-06-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add Vietnamese translation ([#3840](https://github.com/filebrowser/filebrowser/issues/3840)) ([56b80b6](https://github.com/filebrowser/filebrowser/commit/56b80b6d9b4710538765ba7df5da1f03898f6b81))
|
||||||
|
* improve pt-br translations with new keys and refinements ([#4903](https://github.com/filebrowser/filebrowser/issues/4903)) ([a882fb6](https://github.com/filebrowser/filebrowser/commit/a882fb6c85ab6ccc845ed0bf3908d8e5e60ce346))
|
||||||
|
* update translation ko.json ([#3852](https://github.com/filebrowser/filebrowser/issues/3852)) ([d9ebd65](https://github.com/filebrowser/filebrowser/commit/d9ebd65ffcf9b2166fec708d51849796d12b16e0))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* err shadowing lint ([c606a01](https://github.com/filebrowser/filebrowser/commit/c606a01a2d20932fb32ee896234d57631f8c47e4))
|
||||||
|
* generate random admin password on quick setup ([a46acba](https://github.com/filebrowser/filebrowser/commit/a46acba5f92ee044661880d6ae349e289d984328)), closes [#3646](https://github.com/filebrowser/filebrowser/issues/3646)
|
||||||
|
* imports lint ([54b91b8](https://github.com/filebrowser/filebrowser/commit/54b91b8ff0b8ee1f02f72425ab97d27a5d942fc3))
|
||||||
|
* set videojs locale ([#3742](https://github.com/filebrowser/filebrowser/issues/3742)) ([71a8f56](https://github.com/filebrowser/filebrowser/commit/71a8f5662c207e3cd4ee714a5b5a961121f510cd))
|
||||||
|
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
* **deps-dev:** bump vite from 6.0.11 to 6.1.6 in /frontend ([#3886](https://github.com/filebrowser/filebrowser/issues/3886)) ([5355629](https://github.com/filebrowser/filebrowser/commit/5355629fd1e7bd85ee3222fca22da899ba23ea95))
|
||||||
|
* **deps:** bump golang.org/x/crypto from 0.31.0 to 0.35.0 ([#3865](https://github.com/filebrowser/filebrowser/issues/3865)) ([0ba9505](https://github.com/filebrowser/filebrowser/commit/0ba9505a19cb369653fc9f8260dc02fcc6587629))
|
||||||
|
* **deps:** bump golang.org/x/net from 0.33.0 to 0.38.0 ([#3869](https://github.com/filebrowser/filebrowser/issues/3869)) ([cfea84f](https://github.com/filebrowser/filebrowser/commit/cfea84fd5e7ec9c1d2366293e5db12baaa4e3a81))
|
||||||
|
* **deps:** bump vue-i18n from 11.0.1 to 11.1.2 in /frontend ([#3786](https://github.com/filebrowser/filebrowser/issues/3786)) ([35d1c09](https://github.com/filebrowser/filebrowser/commit/35d1c092434b80b22c89a614a02122e9f5965b39))
|
||||||
|
|
||||||
|
## [2.32.0](https://github.com/filebrowser/filebrowser/compare/v2.31.2...v2.32.0) (2025-01-31)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* create user on proxy authentication if user does not exist ([#3569](https://github.com/filebrowser/filebrowser/issues/3569)) ([209acf2](https://github.com/filebrowser/filebrowser/commit/209acf2429b06e2e8d78218937c59fd7e7edd1be))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add proper healthcheck for S6 containers ([#3691](https://github.com/filebrowser/filebrowser/issues/3691)) ([045064f](https://github.com/filebrowser/filebrowser/commit/045064f8b8bf9f86058e877448085e38da8b3f2e))
|
||||||
|
* disk usage refreshing ([#3692](https://github.com/filebrowser/filebrowser/issues/3692)) ([bbdd313](https://github.com/filebrowser/filebrowser/commit/bbdd313705b8d253f0c47ad717a6e47b2f46e719))
|
||||||
|
* Fix user creation on proxy auth ([#3666](https://github.com/filebrowser/filebrowser/issues/3666)) ([5300d00](https://github.com/filebrowser/filebrowser/commit/5300d00d2e7dbb80a252aff57e100113f02506c3))
|
||||||
|
* prompts disappearing on copy / move / upload ([#3537](https://github.com/filebrowser/filebrowser/issues/3537)) ([d1c84a8](https://github.com/filebrowser/filebrowser/commit/d1c84a84123c77dede05c023b3697a432b56122c))
|
||||||
|
|
||||||
|
|
||||||
|
### Refactorings
|
||||||
|
|
||||||
|
* Fix eslint warnings ([#3698](https://github.com/filebrowser/filebrowser/issues/3698)) ([0201f9c](https://github.com/filebrowser/filebrowser/commit/0201f9c5c4dd2a4d5a3503e59cdb8045e8d3a91f)), closes [#3407](https://github.com/filebrowser/filebrowser/issues/3407)
|
||||||
|
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
* **deps:** bump cross-spawn from 7.0.3 to 7.0.6 in /tools ([#3601](https://github.com/filebrowser/filebrowser/issues/3601)) ([25372ed](https://github.com/filebrowser/filebrowser/commit/25372edb5c0e616e82b76b5f523633af57d347e0))
|
||||||
|
* **deps:** bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 ([#3574](https://github.com/filebrowser/filebrowser/issues/3574)) ([2fdea73](https://github.com/filebrowser/filebrowser/commit/2fdea73430011846276a1cda52458f1d670f5ea7))
|
||||||
|
* **deps:** bump golang.org/x/crypto from 0.26.0 to 0.31.0 ([#3634](https://github.com/filebrowser/filebrowser/issues/3634)) ([e92dbb4](https://github.com/filebrowser/filebrowser/commit/e92dbb4bb8b7894264fbf0a48a641712c3b68766))
|
||||||
|
* **deps:** bump golang.org/x/net from 0.23.0 to 0.33.0 ([#3712](https://github.com/filebrowser/filebrowser/issues/3712)) ([1194cfe](https://github.com/filebrowser/filebrowser/commit/1194cfe0097a70399c1f06cf0f514b9d70fa463c))
|
||||||
|
* **deps:** bump vue-i18n from 9.10.2 to 9.14.2 in /frontend ([#3618](https://github.com/filebrowser/filebrowser/issues/3618)) ([0659594](https://github.com/filebrowser/filebrowser/commit/065959451d3ba12019c6151274aa4e6904cdca99))
|
||||||
|
* fix go releaser ([ba797cd](https://github.com/filebrowser/filebrowser/commit/ba797cda3135eddb9b7165dc5ceb932399cb54df))
|
||||||
|
* update to node 22 and pnpm ([#3616](https://github.com/filebrowser/filebrowser/issues/3616)) ([d51a343](https://github.com/filebrowser/filebrowser/commit/d51a3438201274a1b826be1b775ca1035ade20c5))
|
||||||
|
|
||||||
### [2.31.2](https://github.com/filebrowser/filebrowser/compare/v2.31.1...v2.31.2) (2024-10-03)
|
### [2.31.2](https://github.com/filebrowser/filebrowser/compare/v2.31.1...v2.31.2) (2024-10-03)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
41
Dockerfile
41
Dockerfile
@@ -1,19 +1,32 @@
|
|||||||
FROM alpine:latest
|
FROM alpine:3.22
|
||||||
RUN apk --update add ca-certificates \
|
|
||||||
mailcap \
|
|
||||||
curl \
|
|
||||||
jq
|
|
||||||
|
|
||||||
COPY healthcheck.sh /healthcheck.sh
|
RUN apk update && \
|
||||||
RUN chmod +x /healthcheck.sh # Make the script executable
|
apk --no-cache add ca-certificates mailcap curl jq tini
|
||||||
|
|
||||||
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \
|
# Make user and create necessary directories
|
||||||
CMD /healthcheck.sh || exit 1
|
ENV UID=1000
|
||||||
|
ENV GID=1000
|
||||||
|
|
||||||
|
RUN addgroup -g $GID user && \
|
||||||
|
adduser -D -u $UID -G user user && \
|
||||||
|
mkdir -p /config /database /srv && \
|
||||||
|
chown -R user:user /config /database /srv
|
||||||
|
|
||||||
|
# Copy files and set permissions
|
||||||
|
COPY filebrowser /bin/filebrowser
|
||||||
|
COPY docker/common/ /
|
||||||
|
COPY docker/alpine/ /
|
||||||
|
|
||||||
|
RUN chown -R user:user /bin/filebrowser /defaults healthcheck.sh init.sh
|
||||||
|
|
||||||
|
# Define healthcheck script
|
||||||
|
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s CMD /healthcheck.sh
|
||||||
|
|
||||||
|
# Set the user, volumes and exposed ports
|
||||||
|
USER user
|
||||||
|
|
||||||
|
VOLUME /srv /config /database
|
||||||
|
|
||||||
VOLUME /srv
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
COPY docker_config.json /.filebrowser.json
|
ENTRYPOINT [ "tini", "--", "/init.sh", "filebrowser", "--config", "/config/settings.json" ]
|
||||||
COPY filebrowser /filebrowser
|
|
||||||
|
|
||||||
ENTRYPOINT [ "/filebrowser" ]
|
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
FROM ghcr.io/linuxserver/baseimage-alpine:3.20
|
FROM ghcr.io/linuxserver/baseimage-alpine:3.22
|
||||||
|
|
||||||
RUN apk --update add ca-certificates \
|
RUN apk update && \
|
||||||
mailcap \
|
apk --no-cache add ca-certificates mailcap curl jq
|
||||||
curl
|
|
||||||
|
|
||||||
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \
|
# Make user and create necessary directories
|
||||||
CMD curl -f http://localhost/health || exit 1
|
RUN mkdir -p /config /database /srv && \
|
||||||
|
chown -R abc:abc /config /database /srv
|
||||||
|
|
||||||
# copy local files
|
# Copy files and set permissions
|
||||||
COPY docker/root/ /
|
COPY filebrowser /bin/filebrowser
|
||||||
COPY filebrowser /usr/bin/filebrowser
|
COPY docker/common/ /
|
||||||
|
COPY docker/s6/ /
|
||||||
|
|
||||||
# ports and volumes
|
RUN chown -R abc:abc /bin/filebrowser /defaults healthcheck.sh
|
||||||
|
|
||||||
|
# Define healthcheck script
|
||||||
|
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s CMD /healthcheck.sh
|
||||||
|
|
||||||
|
# Set the volumes and exposed ports
|
||||||
VOLUME /srv /config /database
|
VOLUME /srv /config /database
|
||||||
EXPOSE 80
|
|
||||||
|
EXPOSE 80
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.20
|
FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.22
|
||||||
|
|
||||||
RUN apk --update add ca-certificates \
|
RUN apk update && \
|
||||||
mailcap \
|
apk --no-cache add ca-certificates mailcap curl jq
|
||||||
curl
|
|
||||||
|
|
||||||
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \
|
# Make user and create necessary directories
|
||||||
CMD curl -f http://localhost/health || exit 1
|
RUN mkdir -p /config /database /srv && \
|
||||||
|
chown -R abc:abc /config /database /srv
|
||||||
|
|
||||||
# copy local files
|
# Copy files and set permissions
|
||||||
COPY docker/root/ /
|
COPY filebrowser /bin/filebrowser
|
||||||
COPY filebrowser /usr/bin/filebrowser
|
COPY docker/common/ /
|
||||||
|
COPY docker/s6/ /
|
||||||
|
|
||||||
# ports and volumes
|
RUN chown -R abc:abc /bin/filebrowser /defaults healthcheck.sh
|
||||||
|
|
||||||
|
# Define healthcheck script
|
||||||
|
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s CMD /healthcheck.sh
|
||||||
|
|
||||||
|
# Set the volumes and exposed ports
|
||||||
VOLUME /srv /config /database
|
VOLUME /srv /config /database
|
||||||
EXPOSE 80
|
|
||||||
|
EXPOSE 80
|
||||||
|
|||||||
7
Makefile
7
Makefile
@@ -10,7 +10,7 @@ build: | build-frontend build-backend ## Build binary
|
|||||||
|
|
||||||
.PHONY: build-frontend
|
.PHONY: build-frontend
|
||||||
build-frontend: ## Build frontend
|
build-frontend: ## Build frontend
|
||||||
$Q cd frontend && npm ci && npm run build
|
$Q cd frontend && pnpm install --frozen-lockfile && pnpm run build
|
||||||
|
|
||||||
.PHONY: build-backend
|
.PHONY: build-backend
|
||||||
build-backend: ## Build backend
|
build-backend: ## Build backend
|
||||||
@@ -21,6 +21,7 @@ test: | test-frontend test-backend ## Run all tests
|
|||||||
|
|
||||||
.PHONY: test-frontend
|
.PHONY: test-frontend
|
||||||
test-frontend: ## Run frontend tests
|
test-frontend: ## Run frontend tests
|
||||||
|
$Q cd frontend && pnpm install --frozen-lockfile && pnpm run typecheck
|
||||||
|
|
||||||
.PHONY: test-backend
|
.PHONY: test-backend
|
||||||
test-backend: ## Run backend tests
|
test-backend: ## Run backend tests
|
||||||
@@ -31,7 +32,7 @@ lint: lint-frontend lint-backend ## Run all linters
|
|||||||
|
|
||||||
.PHONY: lint-frontend
|
.PHONY: lint-frontend
|
||||||
lint-frontend: ## Run frontend linters
|
lint-frontend: ## Run frontend linters
|
||||||
$Q cd frontend && npm ci && npm run lint
|
$Q cd frontend && pnpm install --frozen-lockfile && pnpm run lint
|
||||||
|
|
||||||
.PHONY: lint-backend
|
.PHONY: lint-backend
|
||||||
lint-backend: | $(golangci-lint) ## Run backend linters
|
lint-backend: | $(golangci-lint) ## Run backend linters
|
||||||
@@ -65,4 +66,4 @@ help: ## Show this help
|
|||||||
@awk 'BEGIN {FS = ":.*?## "} { \
|
@awk 'BEGIN {FS = ":.*?## "} { \
|
||||||
if (/^[a-zA-Z_-]+:.*?##.*$$/) {printf " ${YELLOW}%-20s${GREEN}%s${RESET}\n", $$1, $$2} \
|
if (/^[a-zA-Z_-]+:.*?##.*$$/) {printf " ${YELLOW}%-20s${GREEN}%s${RESET}\n", $$1, $$2} \
|
||||||
else if (/^## .*$$/) {printf " ${CYAN}%s${RESET}\n", substr($$1,4)} \
|
else if (/^## .*$$/) {printf " ${CYAN}%s${RESET}\n", substr($$1,4)} \
|
||||||
}' $(MAKEFILE_LIST)
|
}' $(MAKEFILE_LIST)
|
||||||
|
|||||||
37
README.md
37
README.md
@@ -12,28 +12,41 @@
|
|||||||
|
|
||||||
filebrowser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit your files. It allows the creation of multiple users and each user can have its own directory. It can be used as a standalone app.
|
filebrowser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit your files. It allows the creation of multiple users and each user can have its own directory. It can be used as a standalone app.
|
||||||
|
|
||||||
## Demo
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> This project is currently on **maintenance-only** mode, and is looking for new maintainers. For more information, please read the [discussion #4906](https://github.com/filebrowser/filebrowser/discussions/4906). Therefore, please note the following:
|
||||||
|
>
|
||||||
|
> - It can take a while until someone gets back to you. Please be patient.
|
||||||
|
> - [Issues][issues] are only being used to track bugs. Any unrelated issues will be converted into a [discussion][discussions].
|
||||||
|
> - No new features will be implemented until further notice. The priority is on triaging issues and merge bug fixes.
|
||||||
|
>
|
||||||
|
> If you're interested in maintaining this project, please reach out via the discussion above.
|
||||||
|
|
||||||
url: https://demo.filebrowser.org/
|
[issues]: https://github.com/filebrowser/filebrowser/issues
|
||||||
|
[discussions]: https://github.com/filebrowser/filebrowser/discussions
|
||||||
credentials: `demo`/`demo`
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
Please refer to our docs at [https://filebrowser.org/features](https://filebrowser.org/features)
|
File Browser is a **create-your-own-cloud-kind** of software where you can install it on a server, direct it to a path and then access your files through a nice web interface. You have many available features!
|
||||||
|
|
||||||
|
| Easy Login System | Sleek Interface | User Management |
|
||||||
|
| :----------------------: | :----------------------: | :----------------------: |
|
||||||
|
|  |  |  |
|
||||||
|
|
||||||
|
|
||||||
|
| File Editing | Custom Commands | Customization |
|
||||||
|
| :----------------------: | :----------------------: | :----------------------: |
|
||||||
|
|  |  |  |
|
||||||
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
For installation instructions please refer to our docs at [https://filebrowser.org/installation](https://filebrowser.org/installation).
|
For information on how to install File Browser, please check [docs/installation.md](./docs/installation.md).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
[Authentication Method](https://filebrowser.org/configuration/authentication-method) - You can change the way the user authenticates with the filebrowser server
|
For information on how to configure File Browser, please check [docs/configuration.md](./docs/configuration.md).
|
||||||
|
|
||||||
[Command Runner](https://filebrowser.org/configuration/command-runner) - The command runner is a feature that enables you to execute any shell command you want before or after a certain event.
|
|
||||||
|
|
||||||
[Custom Branding](https://filebrowser.org/configuration/custom-branding) - You can customize your File Browser installation by change its name to any other you want, by adding a global custom style sheet and by using your own logotype if you want.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
If you're interested in contributing to this project, our docs are best places to start [https://filebrowser.org/contributing](https://filebrowser.org/contributing).
|
For information on how to contribute to the project, including how translations are managed, please check [docs/contributing.md](./docs/contributing.md).
|
||||||
|
|||||||
26
SECURITY.md
26
SECURITY.md
@@ -1,26 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
Use this section to tell people about which versions of your project are
|
|
||||||
currently being supported with security updates.
|
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
| ------- | ------------------ |
|
|
||||||
| 2.x | :white_check_mark: |
|
|
||||||
| < 2.0 | :x: |
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
Vulnerabilities should be reported to filebrowser@googlegroups.com - which is a private, maintainer-only group. Maintainers will attempt to respond to/confirm reports within 2-3 days, but if you believe your report to be "critical" to user safety and security, please note as such in the subject. We have tens of thousands of users using our software, and take security vulnerabilities seriously.
|
|
||||||
|
|
||||||
When reporting an issue, where possible, please provide at least:
|
|
||||||
|
|
||||||
* The commit version the issue was identified at
|
|
||||||
* A proof of concept (plaintext; no binaries)
|
|
||||||
* Steps to reproduce
|
|
||||||
* Your recommended remediation(s), if any.
|
|
||||||
|
|
||||||
The FileBrowser team is a volunteer-only effort, and may reach back out for clarification.
|
|
||||||
|
|
||||||
> Note: Please do not open public issues for security issues, as GitHub does not provide facility for private issues, and deleting the issue makes it hard to triage/respond back to the reporter.
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
|
|
||||||
fbErrors "github.com/filebrowser/filebrowser/v2/errors"
|
fbErrors "github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
@@ -19,14 +19,49 @@ type ProxyAuth struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Auth authenticates the user via an HTTP header.
|
// Auth authenticates the user via an HTTP header.
|
||||||
func (a ProxyAuth) Auth(r *http.Request, usr users.Store, _ *settings.Settings, srv *settings.Server) (*users.User, error) {
|
func (a ProxyAuth) Auth(r *http.Request, usr users.Store, setting *settings.Settings, srv *settings.Server) (*users.User, error) {
|
||||||
username := r.Header.Get(a.Header)
|
username := r.Header.Get(a.Header)
|
||||||
user, err := usr.Get(srv.Root, username)
|
user, err := usr.Get(srv.Root, username)
|
||||||
if errors.Is(err, fbErrors.ErrNotExist) {
|
if errors.Is(err, fbErrors.ErrNotExist) {
|
||||||
return nil, os.ErrPermission
|
return a.createUser(usr, setting, srv, username)
|
||||||
|
}
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a ProxyAuth) createUser(usr users.Store, setting *settings.Settings, srv *settings.Server, username string) (*users.User, error) {
|
||||||
|
const passwordSize = 32
|
||||||
|
randomPasswordBytes := make([]byte, passwordSize)
|
||||||
|
_, err := rand.Read(randomPasswordBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, err
|
var hashedRandomPassword string
|
||||||
|
hashedRandomPassword, err = users.HashPwd(string(randomPasswordBytes))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
user := &users.User{
|
||||||
|
Username: username,
|
||||||
|
Password: hashedRandomPassword,
|
||||||
|
LockPassword: true,
|
||||||
|
}
|
||||||
|
setting.Defaults.Apply(user)
|
||||||
|
|
||||||
|
var userHome string
|
||||||
|
userHome, err = setting.MakeUserDir(user.Username, user.Scope, srv.Root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
user.Scope = userHome
|
||||||
|
|
||||||
|
err = usr.Save(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoginPage tells that proxy auth doesn't require a login page.
|
// LoginPage tells that proxy auth doesn't require a login page.
|
||||||
|
|||||||
10
cmd/root.go
10
cmd/root.go
@@ -48,7 +48,7 @@ func init() {
|
|||||||
persistent.StringP("database", "d", "./filebrowser.db", "database path")
|
persistent.StringP("database", "d", "./filebrowser.db", "database path")
|
||||||
flags.Bool("noauth", false, "use the noauth auther when using quick setup")
|
flags.Bool("noauth", false, "use the noauth auther when using quick setup")
|
||||||
flags.String("username", "admin", "username for the first user when using quick config")
|
flags.String("username", "admin", "username for the first user when using quick config")
|
||||||
flags.String("password", "", "hashed password for the first user when using quick config (default \"admin\")")
|
flags.String("password", "", "hashed password for the first user when using quick config")
|
||||||
|
|
||||||
addServerFlags(flags)
|
addServerFlags(flags)
|
||||||
}
|
}
|
||||||
@@ -378,7 +378,13 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
|
|||||||
password := getParam(flags, "password")
|
password := getParam(flags, "password")
|
||||||
|
|
||||||
if password == "" {
|
if password == "" {
|
||||||
password, err = users.HashPwd("admin")
|
var pwd string
|
||||||
|
pwd, err = users.RandomPwd()
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
log.Println("Generated random admin password for quick setup:", pwd)
|
||||||
|
|
||||||
|
password, err = users.HashPwd(pwd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
41
docker/alpine/init.sh
Executable file
41
docker/alpine/init.sh
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Backwards compatibility for old Docker image
|
||||||
|
if [ -f "/.filebrowser.json" ]; then
|
||||||
|
ln -s /.filebrowser.json /config/settings.json
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "!!!!!!!!!!!!!!!!!!!!! IMPORTANT INFORMATION !!!!!!!!!!!!!!!!!!!!!"
|
||||||
|
echo "Symlinking /.filebrowser.json to /config/settings.json for backwards compatibility."
|
||||||
|
echo ""
|
||||||
|
echo "The volume mount configuration has changed in the latest release."
|
||||||
|
echo "Please rename .filebrowser.json to settings.json and mount the parent directory to /config".
|
||||||
|
echo "Read more on https://github.com/filebrowser/filebrowser/blob/master/docs/installation.md#docker"
|
||||||
|
echo ""
|
||||||
|
echo "This workaround will be removed in a future release."
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backwards compatibility for old Docker image
|
||||||
|
if [ -f "/database.db" ]; then
|
||||||
|
ln -s /database.db /database/filebrowser.db
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "!!!!!!!!!!!!!!!!!!!!! IMPORTANT INFORMATION !!!!!!!!!!!!!!!!!!!!!"
|
||||||
|
echo ""
|
||||||
|
echo "The volume mount configuration has changed in the latest release."
|
||||||
|
echo "Please rename database.db to filebrowser.db and mount the parent directory to /database".
|
||||||
|
echo "Read more on https://github.com/filebrowser/filebrowser/blob/master/docs/installation.md#docker"
|
||||||
|
echo ""
|
||||||
|
echo "This workaround will be removed in a future release."
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure configuration exists
|
||||||
|
if [ ! -f "/config/settings.json" ]; then
|
||||||
|
cp -a /defaults/settings.json /config/settings.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
9
docker/common/healthcheck.sh
Executable file
9
docker/common/healthcheck.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PORT=${FB_PORT:-$(jq -r .port /config/settings.json)}
|
||||||
|
ADDRESS=${FB_ADDRESS:-$(jq -r .address /config/settings.json)}
|
||||||
|
ADDRESS=${ADDRESS:-localhost}
|
||||||
|
|
||||||
|
curl -f http://$ADDRESS:$PORT/health || exit 1
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
|
|
||||||
exec s6-setuidgid abc filebrowser -c /config/settings.json -d /database/filebrowser.db;
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
# make folders
|
# Ensure configuration exists
|
||||||
mkdir -p /database
|
|
||||||
|
|
||||||
# copy config
|
|
||||||
if [ ! -f "/config/settings.json" ]; then
|
if [ ! -f "/config/settings.json" ]; then
|
||||||
cp -a /defaults/settings.json /config/settings.json
|
cp -a /defaults/settings.json /config/settings.json
|
||||||
fi
|
fi
|
||||||
3
docker/s6/etc/services.d/filebrowser/run
Executable file
3
docker/s6/etc/services.d/filebrowser/run
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
exec s6-setuidgid abc filebrowser -c /config/settings.json;
|
||||||
BIN
docs/assets/1.jpg
Normal file
BIN
docs/assets/1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
docs/assets/2.jpg
Normal file
BIN
docs/assets/2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 116 KiB |
BIN
docs/assets/3.jpg
Normal file
BIN
docs/assets/3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 151 KiB |
BIN
docs/assets/4.jpg
Normal file
BIN
docs/assets/4.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 212 KiB |
BIN
docs/assets/5.jpg
Normal file
BIN
docs/assets/5.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
BIN
docs/assets/6.jpg
Normal file
BIN
docs/assets/6.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
46
docs/code-of-conduct.md
Normal file
46
docs/code-of-conduct.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Code of Conduct
|
||||||
|
|
||||||
|
## Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
### Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
### Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
|
### Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
### Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hacdias@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
### Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.4, available at [https://contributor-covenant.org/version/1/4](https://contributor-covenant.org/version/1/4).
|
||||||
|
|
||||||
148
docs/configuration.md
Normal file
148
docs/configuration.md
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
# Configuration
|
||||||
|
|
||||||
|
Most of the configuration can be understood through our Command Line Interface documentation. Although there are some specific topics that we want to cover on this section.
|
||||||
|
|
||||||
|
## Custom Branding
|
||||||
|
|
||||||
|
You are able to customize your File Browser installation by changing its name to any other you want, by adding a global custom style sheet and by using your own logotype if you want. To address this, there are three configuration options that can be changed:
|
||||||
|
|
||||||
|
* **Name:** which is the instance name that will show up on login and signup pages. This won't replace the version message in the sidebar.
|
||||||
|
* **Disable external links:** this will disable any external links (except the ones to this documentation).
|
||||||
|
* **Folder:** is the path to a directory that can contain two items:
|
||||||
|
* **custom.css**, containing the styles you want to apply to your installation.
|
||||||
|
* **img** a directory whose files can replace the [default logotypes](../frontend/public/img) in the application.
|
||||||
|
|
||||||
|
These options can be either set via the CLI interface using the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
filebrowser config set --branding.name "My Name" \
|
||||||
|
--branding.files "/abs/path/to/my/dir" \
|
||||||
|
--branding.disableExternal
|
||||||
|
```
|
||||||
|
Or can be set under 'Branding directory path' in **Settings → Global Settings**.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> If using Docker then remember to bind this directory, for example as `/home/username/containers/filebrowser/branding:/branding`
|
||||||
|
|
||||||
|
For custom icons to be recognized you need to create `img` and `img/icons` directories and place the svg in the `branding/img` directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
- filebrowser
|
||||||
|
- branding
|
||||||
|
- img
|
||||||
|
- icons
|
||||||
|
- logo.svg
|
||||||
|
- filebrowser.db
|
||||||
|
```
|
||||||
|
|
||||||
|
To replace the favicon you need to place this in the `img/icons` directory but also note that some of the other PNG icon types will be required too (see the default logotypes link above) as the browser will normally use the highest resolution option available (at a minimum the 16x16 and 32x32 options). You can use the [Real Favicon Generator](https://realfavicongenerator.net/) to generate these for you from your base image.
|
||||||
|
|
||||||
|
The icons are cached, to make the new ones appear more quickly open developer tools in your browser, then click on the Application tab, then Storage and then 'Clear Site Data'.
|
||||||
|
|
||||||
|
## Authentication Method
|
||||||
|
|
||||||
|
Right now, there are three possible authentication methods. Each one of them has its own capabilities and specification. If you are interested in contributing with one more authentication method, please [check the guidelines](./contributing.md).
|
||||||
|
|
||||||
|
### JSON Auth (default)
|
||||||
|
|
||||||
|
We call it JSON Authentication but it is just the default authentication method and the one that is provided by default if you don't make any changes. It is set by default, but if you've made changes before you can revert to using JSON auth:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
filebrowser config set --auth.method=json
|
||||||
|
```
|
||||||
|
|
||||||
|
This method can also be extended with **reCAPTCHA** verification during login:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
filebrowser config set --auth.method=json \
|
||||||
|
--recaptcha.key site-key \
|
||||||
|
--recaptcha.secret private-key
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, we use [Google's reCAPTCHA](https://developers.google.com/recaptcha/docs/display) service. If you live in China, or want to use other provider, you can change the host with the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
filebrowser config set --recaptcha.host https://recaptcha.net
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `https://recaptcha.net` is any provider you want.
|
||||||
|
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
>
|
||||||
|
> Note that you **always** need to set the `--auth.method` flag when changing authentication configurations and that it will completely overwrite your current settings. [This is a known issue.](https://github.com/filebrowser/filebrowser/issues/715)
|
||||||
|
|
||||||
|
### Proxy Header
|
||||||
|
|
||||||
|
If you have a reverse proxy you want to use to login your users, you do it via our `proxy` authentication method. To configure this method, your proxy must send an HTTP header containing the username of the logged in user:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
filebrowser config set --auth.method=proxy --auth.header=X-My-Header
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `X-My-Header` is the HTTP header provided by your proxy with the username.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> File Browser will blindly trust the provided header. If the proxy can be bypassed, an attacker could simply attach the header and get admin access.
|
||||||
|
|
||||||
|
### No Authentication
|
||||||
|
|
||||||
|
We also provide a no authentication mechanism for users that want to use File Browser privately such in a home network. By setting this authentication method, the user with **id 1** will be used as the default users. Creating more users won't have any effect.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
filebrowser config set --auth.method=noauth
|
||||||
|
```
|
||||||
|
|
||||||
|
## Command Runner
|
||||||
|
|
||||||
|
The command runner is a feature that enables you to execute any shell command you want before or after a certain event. Right now, these are the events:
|
||||||
|
|
||||||
|
* Copy
|
||||||
|
* Rename
|
||||||
|
* Upload
|
||||||
|
* Delete
|
||||||
|
* Save
|
||||||
|
|
||||||
|
Also, during the execution of the commands set for those hooks, there will be some environment variables available to help you perform your commands:
|
||||||
|
|
||||||
|
* `FILE` with the full absolute path to the changed file.
|
||||||
|
* `SCOPE` with the path to user's scope.
|
||||||
|
* `TRIGGER` with the name of the event.
|
||||||
|
* `USERNAME` with the user's username.
|
||||||
|
* `DESTINATION` with the absolute path to the destination. Only used for **copy** and **rename.**
|
||||||
|
|
||||||
|
At this moment, you can edit the commands via the command line interface, using the following commands \(please check the flag `--help` to know more about them\):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
filebrowser cmds add before_copy "echo $FILE"
|
||||||
|
filebrowser cmds rm before_copy 0
|
||||||
|
filebrowser cmds ls
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can use the web interface to manage them via **Settings** → **Global Settings**.
|
||||||
|
|
||||||
|
|
||||||
|
## Shell commands
|
||||||
|
|
||||||
|
Within Filebrowser you can toggle the shell (`< >` icon at the top right) and this will open a shell command window at the bottom of the screen.
|
||||||
|
|
||||||
|
**By default no commands are available as the command list is empty**
|
||||||
|
|
||||||
|
To enable commands these need to either be done on a per-user basis (including for the Admin user).
|
||||||
|
|
||||||
|
You can do this by adding them in Settings > User Management > (edit user) > Commands or to *apply to all new users created from that point forward* they can be set in Settings > Global Settings
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> If using a proxy manager then remember to enable websockets support for the Filebrowser proxy
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> If using Docker and you want to add a new command that is not in the base image then you will need to build a custom Docker image using `filebrowser/filebrowser` as a base image. For example to add 7z:
|
||||||
|
>
|
||||||
|
> ```docker
|
||||||
|
> FROM filebrowser/filebrowser
|
||||||
|
> RUN sudo apt install p7zip-full
|
||||||
|
> ```
|
||||||
91
docs/contributing.md
Normal file
91
docs/contributing.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
If you're interested in contributing to this project, this is the best place to start. Before contributing to this project, please take a bit of time to read our [Code of Conduct](./code-of-conduct.md). Also, note that this project is open-source and licensed under [Apache License 2.0](../LICENSE).
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
The backend side of the application is written in [Go](https://golang.org/), while the frontend (located on a subdirectory of the same name) is written in [Vue.js](https://vuejs.org/). Due to the tight coupling required by some features, basic knowledge of both Go and Vue.js is recommended.
|
||||||
|
|
||||||
|
* Learn Go: [https://github.com/golang/go/wiki/Learn](https://github.com/golang/go/wiki/Learn)
|
||||||
|
* Learn Vue.js: [https://vuejs.org/guide/introduction.html](https://vuejs.org/guide/introduction.html)
|
||||||
|
|
||||||
|
We encourage you to use git to manage your fork. To clone the main repository, just run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/filebrowser/filebrowser
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
We are using [Node.js](https://nodejs.org/en/) on the frontend to manage the build process. The steps to build it are:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From the root of the repo, go to frontend/
|
||||||
|
cd frontend
|
||||||
|
|
||||||
|
# Install the dependencies
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# Build the frontend
|
||||||
|
pnpm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
This will install the dependencies and build the frontend so you can then embed it into the Go app. Although, if you want to play with it, you'll get bored of building it after every change you do. So, you can run the command below to watch for changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
First of all, you need to download the required dependencies. We are using the built-in `go mod` tool for dependency management. To get the modules, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod download
|
||||||
|
```
|
||||||
|
|
||||||
|
The magic of File Browser is that the static assets are bundled into the final binary. For that, we use [Go embed.FS](https://golang.org/pkg/embed/). The files from `frontend/dist` will be embedded during the build process.
|
||||||
|
|
||||||
|
To build File Browser is just like any other Go program:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build
|
||||||
|
```
|
||||||
|
|
||||||
|
To create a development build use the "dev" tag, this way the content inside the frontend folder will not be embedded in the binary but will be reloaded at every change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -tags dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Translations
|
||||||
|
|
||||||
|
Translations are managed on Transifex, which is an online website where everyone can contribute and translate strings for our project. It automatically syncs with the main language file \(in English\) and,, for you to contribute, you just need to:
|
||||||
|
|
||||||
|
1. Go to our Transifex web page: [app.transifex.com/file-browser/file-browser](https://app.transifex.com/file-browser/file-browser/)
|
||||||
|
2. Click on **Join the project** and pick your language. We'll accept you as soon as possible. If you're language is not on the list, please request it via the interface.
|
||||||
|
|
||||||
|
Translations are automatically pushed to GitHub via an integration.
|
||||||
|
|
||||||
|
## Authentication Provider
|
||||||
|
|
||||||
|
To build a new authentication provider, you need to implement the [Auther interface](https://github.com/filebrowser/filebrowser/blob/master/auth/auth.go), whose method will be called on the login page after the user has submitted their login data.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Auther is the authentication interface.
|
||||||
|
type Auther interface {
|
||||||
|
// Auth is called to authenticate a request.
|
||||||
|
Auth(r *http.Request, s *users.Storage, root string) (*users.User, error)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After implementing the interface you should:
|
||||||
|
|
||||||
|
1. Add it to [`auth` directory](https://github.com/filebrowser/filebrowser/blob/master/auth).
|
||||||
|
2. Add it to the [configuration parser](https://github.com/filebrowser/filebrowser/blob/master/cmd/config.go) for the CLI.
|
||||||
|
3. Add it to the [`authBackend.Get`](https://github.com/filebrowser/filebrowser/blob/master/storage/bolt/auth.go).
|
||||||
|
|
||||||
|
If you need to add more flags, please update the function `addConfigFlags`.
|
||||||
|
|
||||||
80
docs/installation.md
Normal file
80
docs/installation.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Installation
|
||||||
|
|
||||||
|
File Browser is a single binary and can be used as a standalone executable. Although, some might prefer to use it with [Docker](https://www.docker.com) or [Caddy](https://caddyserver.com), which is a fantastic web server that enables HTTPS by default. Its installation is quite straightforward independently on which system you want to use.
|
||||||
|
|
||||||
|
## Quick Setup
|
||||||
|
|
||||||
|
The quickest way for beginners to start using File Browser is by opening your terminal and executing the following commands:
|
||||||
|
|
||||||
|
### Brew
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew tap filebrowser/tap
|
||||||
|
brew install filebrowser
|
||||||
|
filebrowser -r /path/to/your/files
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unix
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
|
||||||
|
filebrowser -r /path/to/your/files
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
```sh
|
||||||
|
iwr -useb https://raw.githubusercontent.com/filebrowser/get/master/get.ps1 | iex
|
||||||
|
filebrowser -r /path/to/your/files
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring
|
||||||
|
|
||||||
|
Done! It will bootstrap a database in which all the configurations and users are stored. Now, you can see on your command line the address in which your instance is running. You just need to go to that URL and use the following credentials:
|
||||||
|
|
||||||
|
* Username: `admin`
|
||||||
|
* Password: (printed in your console)
|
||||||
|
|
||||||
|
Although this is the fastest way to bootstrap an instance, we recommend you to take a look at other possible options, by checking `config init --help` and `config set --help`, to make the installation as safe and customized as it can be.
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
File Browser is available as two different Docker images, which can be found on [Docker Hub](https://hub.docker.com/r/filebrowser/filebrowser).
|
||||||
|
|
||||||
|
### Alpine
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker run \
|
||||||
|
-v /path/to/srv:/srv \
|
||||||
|
-v /path/to/database:/database \
|
||||||
|
-v /path/to/config:/config \
|
||||||
|
-p 8080:80 \
|
||||||
|
filebrowser/filebrowser
|
||||||
|
```
|
||||||
|
|
||||||
|
The default user has PID 1000 and GID 1000. Please make sure that this user has access to the different mounted volumes. To change the user running inside the Docker image, you need to use the [`--user` flag](https://docs.docker.com/engine/containers/run/#user).
|
||||||
|
|
||||||
|
### s6 overlay
|
||||||
|
|
||||||
|
The `s6` image is based on LinuxServer and leverages the [s6-overlay](https://github.com/just-containers/s6-overlay) system for a standard, highly customizable image. It should be used as follows:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run \
|
||||||
|
-v /path/to/srv:/srv \
|
||||||
|
-v /path/to/database:/database \
|
||||||
|
-v /path/to/config:/config \
|
||||||
|
-e PUID=$(id -u) \
|
||||||
|
-e PGID=$(id -g) \
|
||||||
|
-p 8080:80 \
|
||||||
|
filebrowser/filebrowser:s6
|
||||||
|
```
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
- `/path/to/srv` contains the files root directory for File Browser
|
||||||
|
- `/path/to/config` contains a `settings.json` file
|
||||||
|
- `/path/to/database` contains a `filebrowser.db` file
|
||||||
|
|
||||||
|
Both `settings.json` and `filebrowser.db` will automatically be initialized if they don't exist.
|
||||||
26
docs/security.md
Normal file
26
docs/security.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Use this section to tell people about which versions of your project are
|
||||||
|
currently being supported with security updates.
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 2.x | :white_check_mark: |
|
||||||
|
| < 2.0 | :x: |
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Vulnerabilities with critical impact should be reported on the [Security](https://github.com/filebrowser/filebrowser/security) page of this repository, which is a private way of communicating vulnerabilities to maintainers. This project is in maintenance-only mode and it can take a while until someone gets back to you.
|
||||||
|
|
||||||
|
If it is not a critical vulnerability, please open an issue and we will categorize it as a security issue. By giving visibility, we can get more help from the community at fixing such issues.
|
||||||
|
|
||||||
|
When reporting an issue, where possible, please provide at least:
|
||||||
|
|
||||||
|
* The commit version the issue was identified at
|
||||||
|
* A proof of concept (plaintext; no binaries)
|
||||||
|
* Steps to reproduce
|
||||||
|
* Your recommended remediation(s), if any.
|
||||||
|
|
||||||
|
The File Browser team is a volunteer-only effort, and may reach back out for clarification.
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"root": true,
|
|
||||||
"env": {
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"plugin:vue/vue3-essential",
|
|
||||||
"eslint:recommended",
|
|
||||||
"@vue/eslint-config-typescript",
|
|
||||||
"@vue/eslint-config-prettier"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"vue/multi-word-component-names": "off",
|
|
||||||
"vue/no-mutating-props": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"shallowOnly": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
// no-undef is already included in
|
|
||||||
// @vue/eslint-config-typescript
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": "latest",
|
|
||||||
"sourceType": "module"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
# Ignore artifacts:
|
# Ignore artifacts:
|
||||||
dist
|
dist
|
||||||
|
pnpm-lock.yaml
|
||||||
38
frontend/eslint.config.js
Normal file
38
frontend/eslint.config.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import pluginVue from "eslint-plugin-vue";
|
||||||
|
import vueTsEslintConfig from "@vue/eslint-config-typescript";
|
||||||
|
import prettierConfig from "@vue/eslint-config-prettier";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
name: "app/files-to-lint",
|
||||||
|
files: ["**/*.{ts,mts,tsx,vue}"],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "app/files-to-ignore",
|
||||||
|
ignores: ["**/dist/**", "**/dist-ssr/**", "**/coverage/**"],
|
||||||
|
},
|
||||||
|
|
||||||
|
...pluginVue.configs["flat/essential"],
|
||||||
|
...vueTsEslintConfig(),
|
||||||
|
prettierConfig,
|
||||||
|
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
// Note: you must disable the base rule as it can report incorrect errors
|
||||||
|
"no-unused-expressions": "off",
|
||||||
|
"@typescript-eslint/no-unused-expressions": "off",
|
||||||
|
// TODO: theres too many of these from before ts
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
// TODO: finish the ts conversion
|
||||||
|
"vue/block-lang": "off",
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
|
"vue/no-mutating-props": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
shallowOnly: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"include": ["src/**/*"],
|
|
||||||
"exclude": ["node_modules", "dist"]
|
|
||||||
}
|
|
||||||
7980
frontend/package-lock.json
generated
7980
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,70 +4,74 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"npm": ">=7.0.0",
|
"node": ">=22.0.0",
|
||||||
"node": ">=18.0.0"
|
"pnpm": ">=9.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "npm run typecheck && vite build",
|
"build": "pnpm run typecheck && vite build",
|
||||||
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
|
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
|
||||||
"typecheck": "vue-tsc -p ./tsconfig.json --noEmit",
|
"typecheck": "vue-tsc -p ./tsconfig.tsc.json --noEmit",
|
||||||
"lint": "npm run typecheck && eslint --ext .vue,.ts src/",
|
"lint": "eslint src/",
|
||||||
"lint:fix": "eslint --ext .vue,.ts --fix src/",
|
"lint:fix": "eslint --fix src/",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"test": "playwright test"
|
"test": "playwright test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chenfengyuan/vue-number-input": "^2.0.1",
|
"@chenfengyuan/vue-number-input": "^2.0.1",
|
||||||
"@vueuse/core": "^10.9.0",
|
"@vueuse/core": "^12.5.0",
|
||||||
"@vueuse/integrations": "^10.9.0",
|
"@vueuse/integrations": "^12.5.0",
|
||||||
"ace-builds": "^1.32.9",
|
"ace-builds": "^1.37.5",
|
||||||
"core-js": "^3.36.1",
|
"core-js": "^3.40.0",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
|
"epubjs": "^0.3.93",
|
||||||
"filesize": "^10.1.1",
|
"filesize": "^10.1.1",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"material-icons": "^1.13.12",
|
"marked": "^15.0.6",
|
||||||
"marked": "^14.1.0",
|
"material-icons": "^1.13.13",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.3.1",
|
||||||
"pretty-bytes": "^6.1.1",
|
"pretty-bytes": "^6.1.1",
|
||||||
"qrcode.vue": "^3.4.1",
|
"qrcode.vue": "^3.4.1",
|
||||||
"tus-js-client": "^4.1.0",
|
"tus-js-client": "^4.3.1",
|
||||||
"utif": "^3.1.0",
|
"utif": "^3.1.0",
|
||||||
"video.js": "^8.10.0",
|
"video.js": "^8.21.0",
|
||||||
"videojs-hotkeys": "^0.2.28",
|
"videojs-hotkeys": "^0.2.28",
|
||||||
"videojs-mobile-ui": "^1.1.1",
|
"videojs-mobile-ui": "^1.1.1",
|
||||||
"vue": "^3.4.21",
|
"vue": "^3.4.21",
|
||||||
"vue-final-modal": "^4.5.4",
|
"vue-final-modal": "^4.5.4",
|
||||||
"vue-i18n": "^9.10.2",
|
"vue-i18n": "^11.1.2",
|
||||||
"vue-lazyload": "^3.0.0",
|
"vue-lazyload": "^3.0.0",
|
||||||
"vue-reader": "^1.2.14",
|
"vue-reader": "^1.2.17",
|
||||||
"vue-router": "^4.3.0",
|
"vue-router": "^4.3.0",
|
||||||
"vue-toastification": "^2.0.0-rc.5"
|
"vue-toastification": "^2.0.0-rc.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
"@intlify/unplugin-vue-i18n": "^6.0.3",
|
||||||
"@playwright/test": "^1.42.1",
|
"@playwright/test": "^1.50.0",
|
||||||
|
"@tsconfig/node22": "^22.0.0",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.12.2",
|
"@types/node": "^22.10.10",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
"@typescript-eslint/eslint-plugin": "^8.21.0",
|
||||||
"@vitejs/plugin-legacy": "^5.3.2",
|
"@vitejs/plugin-legacy": "^6.0.0",
|
||||||
"@vitejs/plugin-vue": "^5.0.4",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"@vue/eslint-config-prettier": "^9.0.0",
|
"@vue/eslint-config-prettier": "^10.2.0",
|
||||||
"@vue/eslint-config-typescript": "^13.0.0",
|
"@vue/eslint-config-typescript": "^14.3.0",
|
||||||
|
"@vue/tsconfig": "^0.7.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^9.1.2",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^9.19.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.2.3",
|
||||||
"eslint-plugin-vue": "^9.24.0",
|
"eslint-plugin-vue": "^9.24.0",
|
||||||
"jsdom": "^24.0.0",
|
"jsdom": "^26.0.0",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.5.1",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.4.2",
|
||||||
"terser": "^5.30.0",
|
"terser": "^5.37.0",
|
||||||
"vite": "^5.4.6",
|
"vite": "^6.1.6",
|
||||||
"vite-plugin-compression2": "^1.0.0",
|
"vite-plugin-compression2": "^1.0.0",
|
||||||
"vue-tsc": "^2.0.7"
|
"vue-tsc": "^2.2.0"
|
||||||
}
|
},
|
||||||
|
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
|
||||||
}
|
}
|
||||||
|
|||||||
5426
frontend/pnpm-lock.yaml
generated
Normal file
5426
frontend/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
|||||||
import { createURL, fetchURL, removePrefix } from "./utils";
|
|
||||||
import { baseURL } from "@/utils/constants";
|
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
import { baseURL } from "@/utils/constants";
|
||||||
import { upload as postTus, useTus } from "./tus";
|
import { upload as postTus, useTus } from "./tus";
|
||||||
|
import { createURL, fetchURL, removePrefix } from "./utils";
|
||||||
|
|
||||||
export async function fetch(url: string) {
|
export async function fetch(url: string) {
|
||||||
url = removePrefix(url);
|
url = removePrefix(url);
|
||||||
@@ -74,11 +75,6 @@ export function download(format: any, ...files: string[]) {
|
|||||||
url += `algo=${format}&`;
|
url += `algo=${format}&`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
if (authStore.jwt) {
|
|
||||||
url += `auth=${authStore.jwt}&`;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.open(url);
|
window.open(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,6 +152,7 @@ function moveCopy(
|
|||||||
overwrite = false,
|
overwrite = false,
|
||||||
rename = false
|
rename = false
|
||||||
) {
|
) {
|
||||||
|
const layoutStore = useLayoutStore();
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
@@ -166,7 +163,7 @@ function moveCopy(
|
|||||||
}&destination=${to}&override=${overwrite}&rename=${rename}`;
|
}&destination=${to}&override=${overwrite}&rename=${rename}`;
|
||||||
promises.push(resourceAction(url, "PATCH"));
|
promises.push(resourceAction(url, "PATCH"));
|
||||||
}
|
}
|
||||||
|
layoutStore.closeHovers();
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,5 +71,5 @@ export function getDownloadURL(res: Resource, inline = false) {
|
|||||||
...(res.token && { token: res.token }),
|
...(res.token && { token: res.token }),
|
||||||
};
|
};
|
||||||
|
|
||||||
return createURL("api/public/dl/" + res.hash + res.path, params, false);
|
return createURL("api/public/dl/" + res.hash + res.path, params);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,5 +41,5 @@ export async function create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getShareURL(share: Share) {
|
export function getShareURL(share: Share) {
|
||||||
return createURL("share/" + share.hash, {}, false);
|
return createURL("share/" + share.hash, {});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export async function create(user: IUser) {
|
|||||||
throw new StatusError(await res.text(), res.status);
|
throw new StatusError(await res.text(), res.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function update(user: IUser, which = ["all"]) {
|
export async function update(user: Partial<IUser>, which = ["all"]) {
|
||||||
await fetchURL(`/api/users/${user.id}`, {
|
await fetchURL(`/api/users/${user.id}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|||||||
@@ -76,23 +76,13 @@ export function removePrefix(url: string): string {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createURL(endpoint: string, params = {}, auth = true): string {
|
export function createURL(endpoint: string, searchParams = {}): string {
|
||||||
const authStore = useAuthStore();
|
|
||||||
|
|
||||||
let prefix = baseURL;
|
let prefix = baseURL;
|
||||||
if (!prefix.endsWith("/")) {
|
if (!prefix.endsWith("/")) {
|
||||||
prefix = prefix + "/";
|
prefix = prefix + "/";
|
||||||
}
|
}
|
||||||
const url = new URL(prefix + encodePath(endpoint), origin);
|
const url = new URL(prefix + encodePath(endpoint), origin);
|
||||||
|
url.search = new URLSearchParams(searchParams).toString();
|
||||||
const searchParams: SearchParams = {
|
|
||||||
...(auth && { auth: authStore.jwt }),
|
|
||||||
...params,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const key in searchParams) {
|
|
||||||
url.searchParams.set(key, searchParams[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const items = computed(() => {
|
const items = computed(() => {
|
||||||
const relativePath = route.path.replace(props.base, "");
|
const relativePath = route.path.replace(props.base, "");
|
||||||
let parts = relativePath.split("/");
|
const parts = relativePath.split("/");
|
||||||
|
|
||||||
if (parts[0] === "") {
|
if (parts[0] === "") {
|
||||||
parts.shift();
|
parts.shift();
|
||||||
@@ -44,7 +44,7 @@ const items = computed(() => {
|
|||||||
parts.pop();
|
parts.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
let breadcrumbs: BreadCrumb[] = [];
|
const breadcrumbs: BreadCrumb[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < parts.length; i++) {
|
for (let i = 0; i < parts.length; i++) {
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ https://raw.githubusercontent.com/dzwillia/vue-simple-progress/master/src/compon
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
// We're leaving this untouched as you can read in the beginning
|
// We're leaving this untouched as you can read in the beginning
|
||||||
var isNumber = function (n) {
|
const isNumber = function (n) {
|
||||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
pct() {
|
pct() {
|
||||||
var pct = (this.val / this.max) * 100;
|
let pct = (this.val / this.max) * 100;
|
||||||
pct = pct.toFixed(2);
|
pct = pct.toFixed(2);
|
||||||
return Math.min(pct, this.max);
|
return Math.min(pct, this.max);
|
||||||
},
|
},
|
||||||
@@ -160,7 +160,7 @@ export default {
|
|||||||
return isNumber(this.fontSize) ? this.fontSize : 13;
|
return isNumber(this.fontSize) ? this.fontSize : 13;
|
||||||
},
|
},
|
||||||
progress_style() {
|
progress_style() {
|
||||||
var style = {
|
const style = {
|
||||||
background: this.bgColor,
|
background: this.bgColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ export default {
|
|||||||
return style;
|
return style;
|
||||||
},
|
},
|
||||||
bar_style() {
|
bar_style() {
|
||||||
var style = {
|
const style = {
|
||||||
background: this.barColor,
|
background: this.barColor,
|
||||||
width: this.pct + "%",
|
width: this.pct + "%",
|
||||||
height: this.size_px + "px",
|
height: this.size_px + "px",
|
||||||
@@ -198,7 +198,7 @@ export default {
|
|||||||
return style;
|
return style;
|
||||||
},
|
},
|
||||||
text_style() {
|
text_style() {
|
||||||
var style = {
|
const style = {
|
||||||
color: this.textFgColor,
|
color: this.textFgColor,
|
||||||
"font-size": this.text_font_size + "px",
|
"font-size": this.text_font_size + "px",
|
||||||
"text-align": this.textAlign,
|
"text-align": this.textAlign,
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ import { useFileStore } from "@/stores/file";
|
|||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
import { commands } from "@/api";
|
import { commands } from "@/api";
|
||||||
import { throttle } from "lodash";
|
import { throttle } from "lodash-es";
|
||||||
import { theme } from "@/utils/constants";
|
import { theme } from "@/utils/constants";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -163,7 +163,7 @@ export default {
|
|||||||
this.canInput = false;
|
this.canInput = false;
|
||||||
event.target.innerHTML = "";
|
event.target.innerHTML = "";
|
||||||
|
|
||||||
let results = {
|
const results = {
|
||||||
text: `${cmd}\n\n`,
|
text: `${cmd}\n\n`,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ export default {
|
|||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
results.text = results.text
|
results.text = results.text
|
||||||
// eslint-disable-next-line no-control-regex
|
|
||||||
.replace(/\u001b\[[0-9;]+m/g, "") // Filter ANSI color for now
|
.replace(/\u001b\[[0-9;]+m/g, "") // Filter ANSI color for now
|
||||||
.trimEnd();
|
.trimEnd();
|
||||||
this.canInput = true;
|
this.canInput = true;
|
||||||
|
|||||||
@@ -101,7 +101,7 @@
|
|||||||
href="https://github.com/filebrowser/filebrowser"
|
href="https://github.com/filebrowser/filebrowser"
|
||||||
>File Browser</a
|
>File Browser</a
|
||||||
>
|
>
|
||||||
<span> {{ ' ' }} {{ version }}</span>
|
<span> {{ " " }} {{ version }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<a @click="help">{{ $t("sidebar.help") }}</a>
|
<a @click="help">{{ $t("sidebar.help") }}</a>
|
||||||
@@ -158,7 +158,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
...mapActions(useLayoutStore, ["closeHovers", "showHover"]),
|
...mapActions(useLayoutStore, ["closeHovers", "showHover"]),
|
||||||
async fetchUsage() {
|
async fetchUsage() {
|
||||||
let path = this.$route.path.endsWith("/")
|
const path = this.$route.path.endsWith("/")
|
||||||
? this.$route.path
|
? this.$route.path
|
||||||
: this.$route.path + "/";
|
: this.$route.path + "/";
|
||||||
let usageStats = USAGE_DEFAULT;
|
let usageStats = USAGE_DEFAULT;
|
||||||
@@ -166,7 +166,7 @@ export default {
|
|||||||
return Object.assign(this.usage, usageStats);
|
return Object.assign(this.usage, usageStats);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let usage = await api.usage(path);
|
const usage = await api.usage(path);
|
||||||
usageStats = {
|
usageStats = {
|
||||||
used: prettyBytes(usage.used, { binary: true }),
|
used: prettyBytes(usage.used, { binary: true }),
|
||||||
total: prettyBytes(usage.total, { binary: true }),
|
total: prettyBytes(usage.total, { binary: true }),
|
||||||
@@ -191,8 +191,13 @@ export default {
|
|||||||
logout: auth.logout,
|
logout: auth.logout,
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
isFiles(newValue) {
|
$route: {
|
||||||
newValue && this.fetchUsage();
|
handler(to) {
|
||||||
|
if (to.path.includes("/files")) {
|
||||||
|
this.fetchUsage();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import throttle from "lodash/throttle";
|
import { throttle } from "lodash-es";
|
||||||
import UTIF from "utif";
|
import UTIF from "utif";
|
||||||
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
|
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
src: string;
|
src: string;
|
||||||
moveDisabledTime: number;
|
moveDisabledTime?: number;
|
||||||
classList: any[];
|
classList?: any[];
|
||||||
zoomStep: number;
|
zoomStep?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<IProps>(), {
|
const props = withDefaults(defineProps<IProps>(), {
|
||||||
@@ -102,10 +102,11 @@ const decodeUTIF = () => {
|
|||||||
if (document?.location?.pathname === undefined) {
|
if (document?.location?.pathname === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let suff = document.location.pathname.split(".")?.pop()?.toLowerCase() ?? "";
|
const suff =
|
||||||
|
document.location.pathname.split(".")?.pop()?.toLowerCase() ?? "";
|
||||||
|
|
||||||
if (sufs.indexOf(suff) == -1) return false;
|
if (sufs.indexOf(suff) == -1) return false;
|
||||||
let xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
UTIF._xhrs.push(xhr);
|
UTIF._xhrs.push(xhr);
|
||||||
UTIF._imgs.push(imgex.value);
|
UTIF._imgs.push(imgex.value);
|
||||||
xhr.open("GET", props.src);
|
xhr.open("GET", props.src);
|
||||||
@@ -230,7 +231,7 @@ const touchMove = (event: TouchEvent) => {
|
|||||||
if (imgex.value === null) {
|
if (imgex.value === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let step = imgex.value.width / 5;
|
const step = imgex.value.width / 5;
|
||||||
if (event.targetTouches.length === 2) {
|
if (event.targetTouches.length === 2) {
|
||||||
moveDisabled.value = true;
|
moveDisabled.value = true;
|
||||||
if (disabledTimer.value) clearTimeout(disabledTimer.value);
|
if (disabledTimer.value) clearTimeout(disabledTimer.value);
|
||||||
@@ -239,9 +240,9 @@ const touchMove = (event: TouchEvent) => {
|
|||||||
props.moveDisabledTime
|
props.moveDisabledTime
|
||||||
);
|
);
|
||||||
|
|
||||||
let p1 = event.targetTouches[0];
|
const p1 = event.targetTouches[0];
|
||||||
let p2 = event.targetTouches[1];
|
const p2 = event.targetTouches[1];
|
||||||
let touchDistance = Math.sqrt(
|
const touchDistance = Math.sqrt(
|
||||||
Math.pow(p2.pageX - p1.pageX, 2) + Math.pow(p2.pageY - p1.pageY, 2)
|
Math.pow(p2.pageX - p1.pageX, 2) + Math.pow(p2.pageY - p1.pageY, 2)
|
||||||
);
|
);
|
||||||
if (!lastTouchDistance.value) {
|
if (!lastTouchDistance.value) {
|
||||||
@@ -253,8 +254,8 @@ const touchMove = (event: TouchEvent) => {
|
|||||||
setZoom();
|
setZoom();
|
||||||
} else if (event.targetTouches.length === 1) {
|
} else if (event.targetTouches.length === 1) {
|
||||||
if (moveDisabled.value) return;
|
if (moveDisabled.value) return;
|
||||||
let x = event.targetTouches[0].pageX - (lastX.value ?? 0);
|
const x = event.targetTouches[0].pageX - (lastX.value ?? 0);
|
||||||
let y = event.targetTouches[0].pageY - (lastY.value ?? 0);
|
const y = event.targetTouches[0].pageY - (lastY.value ?? 0);
|
||||||
if (Math.abs(x) >= step && Math.abs(y) >= step) return;
|
if (Math.abs(x) >= step && Math.abs(y) >= step) return;
|
||||||
lastX.value = event.targetTouches[0].pageX;
|
lastX.value = event.targetTouches[0].pageX;
|
||||||
lastY.value = event.targetTouches[0].pageY;
|
lastY.value = event.targetTouches[0].pageY;
|
||||||
@@ -268,8 +269,8 @@ const doMove = (x: number, y: number) => {
|
|||||||
}
|
}
|
||||||
const style = imgex.value.style;
|
const style = imgex.value.style;
|
||||||
|
|
||||||
let posX = pxStringToNumber(style.left) + x;
|
const posX = pxStringToNumber(style.left) + x;
|
||||||
let posY = pxStringToNumber(style.top) + y;
|
const posY = pxStringToNumber(style.top) + y;
|
||||||
|
|
||||||
style.left = posX + "px";
|
style.left = posX + "px";
|
||||||
style.top = posY + "px";
|
style.top = posY + "px";
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ const isDraggable = computed(
|
|||||||
const canDrop = computed(() => {
|
const canDrop = computed(() => {
|
||||||
if (!props.isDir || props.readOnly) return false;
|
if (!props.isDir || props.readOnly) return false;
|
||||||
|
|
||||||
for (let i of fileStore.selected) {
|
for (const i of fileStore.selected) {
|
||||||
if (fileStore.req?.items[i].url === props.url) {
|
if (fileStore.req?.items[i].url === props.url) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -156,9 +156,9 @@ const drop = async (event: Event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let items: any[] = [];
|
const items: any[] = [];
|
||||||
|
|
||||||
for (let i of fileStore.selected) {
|
for (const i of fileStore.selected) {
|
||||||
if (fileStore.req) {
|
if (fileStore.req) {
|
||||||
items.push({
|
items.push({
|
||||||
from: fileStore.req?.items[i].url,
|
from: fileStore.req?.items[i].url,
|
||||||
@@ -172,10 +172,10 @@ const drop = async (event: Event) => {
|
|||||||
if (el === null) {
|
if (el === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let path = el.__vue__.url;
|
const path = el.__vue__.url;
|
||||||
let baseItems = (await api.fetch(path)).items;
|
const baseItems = (await api.fetch(path)).items;
|
||||||
|
|
||||||
let action = (overwrite: boolean, rename: boolean) => {
|
const action = (overwrite: boolean, rename: boolean) => {
|
||||||
api
|
api
|
||||||
.move(items, overwrite, rename)
|
.move(items, overwrite, rename)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -184,7 +184,7 @@ const drop = async (event: Event) => {
|
|||||||
.catch($showError);
|
.catch($showError);
|
||||||
};
|
};
|
||||||
|
|
||||||
let conflict = upload.checkConflict(items, baseItems);
|
const conflict = upload.checkConflict(items, baseItems);
|
||||||
|
|
||||||
let overwrite = false;
|
let overwrite = false;
|
||||||
let rename = false;
|
let rename = false;
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ const initVideoPlayer = async () => {
|
|||||||
const languagePack = await (
|
const languagePack = await (
|
||||||
languageImports[lang] || languageImports.en
|
languageImports[lang] || languageImports.en
|
||||||
)?.();
|
)?.();
|
||||||
videojs.addLanguage("videoPlayerLocal", languagePack.default);
|
const code = languageImports[lang] ? lang : "en";
|
||||||
|
videojs.addLanguage(code, languagePack.default);
|
||||||
sourceType.value = "";
|
sourceType.value = "";
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -70,14 +71,19 @@ const initVideoPlayer = async () => {
|
|||||||
|
|
||||||
const srcOpt = { sources: { src: props.source, type: sourceType.value } };
|
const srcOpt = { sources: { src: props.source, type: sourceType.value } };
|
||||||
//Supporting localized language display.
|
//Supporting localized language display.
|
||||||
const langOpt = { language: "videoPlayerLocal" };
|
const langOpt = { language: code };
|
||||||
// support for playback at different speeds.
|
// support for playback at different speeds.
|
||||||
const playbackRatesOpt = { playbackRates: [0.5, 1, 1.5, 2, 2.5, 3] };
|
const playbackRatesOpt = { playbackRates: [0.5, 1, 1.5, 2, 2.5, 3] };
|
||||||
let options = getOptions(props.options, langOpt, srcOpt, playbackRatesOpt);
|
const options = getOptions(
|
||||||
|
props.options,
|
||||||
|
langOpt,
|
||||||
|
srcOpt,
|
||||||
|
playbackRatesOpt
|
||||||
|
);
|
||||||
player.value = videojs(videoPlayer.value!, options, () => {});
|
player.value = videojs(videoPlayer.value!, options, () => {});
|
||||||
|
|
||||||
// TODO: need to test on mobile
|
// TODO: need to test on mobile
|
||||||
// @ts-ignore
|
// @ts-expect-error no ts definition for mobileUi
|
||||||
player.value!.mobileUi();
|
player.value!.mobileUi();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error initializing video player:", error);
|
console.error("Error initializing video player:", error);
|
||||||
@@ -120,7 +126,7 @@ const subLabel = (subUrl: string) => {
|
|||||||
let url: URL;
|
let url: URL;
|
||||||
try {
|
try {
|
||||||
url = new URL(subUrl);
|
url = new URL(subUrl);
|
||||||
} catch (_) {
|
} catch {
|
||||||
// treat it as a relative url
|
// treat it as a relative url
|
||||||
// we only need this for filename
|
// we only need this for filename
|
||||||
url = new URL(subUrl, window.location.origin);
|
url = new URL(subUrl, window.location.origin);
|
||||||
|
|||||||
@@ -82,10 +82,10 @@ export default {
|
|||||||
...mapActions(useLayoutStore, ["showHover", "closeHovers"]),
|
...mapActions(useLayoutStore, ["showHover", "closeHovers"]),
|
||||||
copy: async function (event) {
|
copy: async function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let items = [];
|
const items = [];
|
||||||
|
|
||||||
// Create a new promise for each file.
|
// Create a new promise for each file.
|
||||||
for (let item of this.selected) {
|
for (const item of this.selected) {
|
||||||
items.push({
|
items.push({
|
||||||
from: this.req.items[item].url,
|
from: this.req.items[item].url,
|
||||||
to: this.dest + encodeURIComponent(this.req.items[item].name),
|
to: this.dest + encodeURIComponent(this.req.items[item].name),
|
||||||
@@ -93,7 +93,7 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let action = async (overwrite, rename) => {
|
const action = async (overwrite, rename) => {
|
||||||
buttons.loading("copy");
|
buttons.loading("copy");
|
||||||
|
|
||||||
await api
|
await api
|
||||||
@@ -122,8 +122,8 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dstItems = (await api.fetch(this.dest)).items;
|
const dstItems = (await api.fetch(this.dest)).items;
|
||||||
let conflict = upload.checkConflict(items, dstItems);
|
const conflict = upload.checkConflict(items, dstItems);
|
||||||
|
|
||||||
let overwrite = false;
|
let overwrite = false;
|
||||||
let rename = false;
|
let rename = false;
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let promises = [];
|
const promises = [];
|
||||||
for (let index of this.selected) {
|
for (const index of this.selected) {
|
||||||
promises.push(api.remove(this.req.items[index].url));
|
promises.push(api.remove(this.req.items[index].url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default {
|
|||||||
submit: async function () {
|
submit: async function () {
|
||||||
this.updateRequest(null);
|
this.updateRequest(null);
|
||||||
|
|
||||||
let uri = url.removeLastDir(this.$route.path) + "/";
|
const uri = url.removeLastDir(this.$route.path) + "/";
|
||||||
this.$router.push({ path: uri });
|
this.$router.push({ path: uri });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export default {
|
|||||||
|
|
||||||
// Otherwise we add every directory to the
|
// Otherwise we add every directory to the
|
||||||
// move options.
|
// move options.
|
||||||
for (let item of req.items) {
|
for (const item of req.items) {
|
||||||
if (!item.isDir) continue;
|
if (!item.isDir) continue;
|
||||||
|
|
||||||
this.items.push({
|
this.items.push({
|
||||||
@@ -93,12 +93,12 @@ export default {
|
|||||||
// Retrieves the URL of the directory the user
|
// Retrieves the URL of the directory the user
|
||||||
// just clicked in and fill the options with its
|
// just clicked in and fill the options with its
|
||||||
// content.
|
// content.
|
||||||
let uri = event.currentTarget.dataset.url;
|
const uri = event.currentTarget.dataset.url;
|
||||||
|
|
||||||
files.fetch(uri).then(this.fillOptions).catch(this.$showError);
|
files.fetch(uri).then(this.fillOptions).catch(this.$showError);
|
||||||
},
|
},
|
||||||
touchstart(event) {
|
touchstart(event) {
|
||||||
let url = event.currentTarget.dataset.url;
|
const url = event.currentTarget.dataset.url;
|
||||||
|
|
||||||
// In 300 milliseconds, we shall reset the count.
|
// In 300 milliseconds, we shall reset the count.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<li><strong>DEL</strong> - {{ $t("help.del") }}</li>
|
<li><strong>DEL</strong> - {{ $t("help.del") }}</li>
|
||||||
<li><strong>ESC</strong> - {{ $t("help.esc") }}</li>
|
<li><strong>ESC</strong> - {{ $t("help.esc") }}</li>
|
||||||
<li><strong>CTRL + S</strong> - {{ $t("help.ctrl.s") }}</li>
|
<li><strong>CTRL + S</strong> - {{ $t("help.ctrl.s") }}</li>
|
||||||
<li><strong>CTRL + F</strong> - {{ $t("help.ctrl.f") }}</li>
|
<li><strong>CTRL + SHIFT + F</strong> - {{ $t("help.ctrl.f") }}</li>
|
||||||
<li><strong>CTRL + Click</strong> - {{ $t("help.ctrl.click") }}</li>
|
<li><strong>CTRL + Click</strong> - {{ $t("help.ctrl.click") }}</li>
|
||||||
<li><strong>Click</strong> - {{ $t("help.click") }}</li>
|
<li><strong>Click</strong> - {{ $t("help.click") }}</li>
|
||||||
<li><strong>Double click</strong> - {{ $t("help.doubleClick") }}</li>
|
<li><strong>Double click</strong> - {{ $t("help.doubleClick") }}</li>
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export default {
|
|||||||
|
|
||||||
let sum = 0;
|
let sum = 0;
|
||||||
|
|
||||||
for (let selected of this.selected) {
|
for (const selected of this.selected) {
|
||||||
sum += this.req.items[selected].size;
|
sum += this.req.items[selected].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,9 +81,9 @@ export default {
|
|||||||
...mapActions(useLayoutStore, ["showHover", "closeHovers"]),
|
...mapActions(useLayoutStore, ["showHover", "closeHovers"]),
|
||||||
move: async function (event) {
|
move: async function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let items = [];
|
const items = [];
|
||||||
|
|
||||||
for (let item of this.selected) {
|
for (const item of this.selected) {
|
||||||
items.push({
|
items.push({
|
||||||
from: this.req.items[item].url,
|
from: this.req.items[item].url,
|
||||||
to: this.dest + encodeURIComponent(this.req.items[item].name),
|
to: this.dest + encodeURIComponent(this.req.items[item].name),
|
||||||
@@ -91,7 +91,7 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let action = async (overwrite, rename) => {
|
const action = async (overwrite, rename) => {
|
||||||
buttons.loading("move");
|
buttons.loading("move");
|
||||||
|
|
||||||
await api
|
await api
|
||||||
@@ -106,8 +106,8 @@ export default {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let dstItems = (await api.fetch(this.dest)).items;
|
const dstItems = (await api.fetch(this.dest)).items;
|
||||||
let conflict = upload.checkConflict(items, dstItems);
|
const conflict = upload.checkConflict(items, dstItems);
|
||||||
|
|
||||||
let overwrite = false;
|
let overwrite = false;
|
||||||
let rename = false;
|
let rename = false;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from "vue";
|
import { watch } from "vue";
|
||||||
import { ModalsContainer, useModal } from "vue-final-modal";
|
import { ModalsContainer, useModal } from "vue-final-modal";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
@@ -30,8 +30,6 @@ const layoutStore = useLayoutStore();
|
|||||||
|
|
||||||
const { currentPromptName } = storeToRefs(layoutStore);
|
const { currentPromptName } = storeToRefs(layoutStore);
|
||||||
|
|
||||||
const closeModal = ref<() => Promise<string>>();
|
|
||||||
|
|
||||||
const components = new Map<string, any>([
|
const components = new Map<string, any>([
|
||||||
["info", Info],
|
["info", Info],
|
||||||
["help", Help],
|
["help", Help],
|
||||||
@@ -52,11 +50,6 @@ const components = new Map<string, any>([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
watch(currentPromptName, (newValue) => {
|
watch(currentPromptName, (newValue) => {
|
||||||
if (closeModal.value) {
|
|
||||||
closeModal.value();
|
|
||||||
closeModal.value = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const modal = components.get(newValue!);
|
const modal = components.get(newValue!);
|
||||||
if (!modal) return;
|
if (!modal) return;
|
||||||
|
|
||||||
@@ -67,7 +60,7 @@ watch(currentPromptName, (newValue) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
closeModal.value = close;
|
layoutStore.setCloseOnPrompt(close, newValue!);
|
||||||
open();
|
open();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -196,13 +196,23 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
...mapActions(useLayoutStore, ["closeHovers"]),
|
||||||
copyToClipboard: function (text) {
|
copyToClipboard: function (text) {
|
||||||
copy(text).then(
|
copy({ text }).then(
|
||||||
() => {
|
() => {
|
||||||
// clipboard successfully set
|
// clipboard successfully set
|
||||||
this.$showSuccess(this.$t("success.linkCopied"));
|
this.$showSuccess(this.$t("success.linkCopied"));
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
// clipboard write failed
|
// clipboard write failed
|
||||||
|
copy({ text }, { permission: true }).then(
|
||||||
|
() => {
|
||||||
|
// clipboard successfully set
|
||||||
|
this.$showSuccess(this.$t("success.linkCopied"));
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
// clipboard write failed
|
||||||
|
this.$showError(e);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -48,12 +48,10 @@ const layoutStore = useLayoutStore();
|
|||||||
|
|
||||||
// TODO: this is a copy of the same function in FileListing.vue
|
// TODO: this is a copy of the same function in FileListing.vue
|
||||||
const uploadInput = (event: Event) => {
|
const uploadInput = (event: Event) => {
|
||||||
layoutStore.closeHovers();
|
const files = (event.currentTarget as HTMLInputElement)?.files;
|
||||||
|
|
||||||
let files = (event.currentTarget as HTMLInputElement)?.files;
|
|
||||||
if (files === null) return;
|
if (files === null) return;
|
||||||
|
|
||||||
let folder_upload = !!files[0].webkitRelativePath;
|
const folder_upload = !!files[0].webkitRelativePath;
|
||||||
|
|
||||||
const uploadFiles: UploadList = [];
|
const uploadFiles: UploadList = [];
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
@@ -68,8 +66,8 @@ const uploadInput = (event: Event) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = route.path.endsWith("/") ? route.path : route.path + "/";
|
const path = route.path.endsWith("/") ? route.path : route.path + "/";
|
||||||
let conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
|
const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
|
||||||
|
|
||||||
if (conflict) {
|
if (conflict) {
|
||||||
layoutStore.showHover({
|
layoutStore.showHover({
|
||||||
|
|||||||
@@ -13,12 +13,13 @@ export default {
|
|||||||
name: "languages",
|
name: "languages",
|
||||||
props: ["locale"],
|
props: ["locale"],
|
||||||
data() {
|
data() {
|
||||||
let dataObj = {};
|
const dataObj = {};
|
||||||
const locales = {
|
const locales = {
|
||||||
he: "עברית",
|
he: "עברית",
|
||||||
hu: "Magyar",
|
hu: "Magyar",
|
||||||
ar: "العربية",
|
ar: "العربية",
|
||||||
ca: "Català",
|
ca: "Català",
|
||||||
|
cs: "Čeština",
|
||||||
de: "Deutsch",
|
de: "Deutsch",
|
||||||
el: "Ελληνικά",
|
el: "Ελληνικά",
|
||||||
en: "English",
|
en: "English",
|
||||||
@@ -38,6 +39,7 @@ export default {
|
|||||||
"sv-se": "Swedish (Sweden)",
|
"sv-se": "Swedish (Sweden)",
|
||||||
tr: "Türkçe",
|
tr: "Türkçe",
|
||||||
uk: "Українська",
|
uk: "Українська",
|
||||||
|
vi: "Tiếng Việt",
|
||||||
"zh-cn": "中文 (简体)",
|
"zh-cn": "中文 (简体)",
|
||||||
"zh-tw": "中文 (繁體)",
|
"zh-tw": "中文 (繁體)",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
remove(event, index) {
|
remove(event, index) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let rules = [...this.rules];
|
const rules = [...this.rules];
|
||||||
rules.splice(index, 1);
|
rules.splice(index, 1);
|
||||||
this.$emit("update:rules", [...rules]);
|
this.$emit("update:rules", [...rules]);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SelectHTMLAttributes } from "vue";
|
import type { SelectHTMLAttributes } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -17,7 +17,6 @@ defineProps<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
(e: "update:theme", val: string | null): void;
|
(e: "update:theme", val: string | null): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ watch(createUserDirData, () => {
|
|||||||
if (props.user?.scope) {
|
if (props.user?.scope) {
|
||||||
props.user.scope = createUserDirData.value
|
props.user.scope = createUserDirData.value
|
||||||
? ""
|
? ""
|
||||||
: originalUserScope.value ?? "";
|
: (originalUserScope.value ?? "");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -63,8 +63,8 @@
|
|||||||
local("Roboto"),
|
local("Roboto"),
|
||||||
local("Roboto-Regular"),
|
local("Roboto-Regular"),
|
||||||
url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2");
|
url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2");
|
||||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F,
|
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
|
||||||
U+A720-A7FF;
|
U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -142,8 +142,8 @@
|
|||||||
local("Roboto Medium"),
|
local("Roboto Medium"),
|
||||||
local("Roboto-Medium"),
|
local("Roboto-Medium"),
|
||||||
url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2");
|
url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2");
|
||||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F,
|
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
|
||||||
U+A720-A7FF;
|
U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -221,8 +221,8 @@
|
|||||||
local("Roboto Bold"),
|
local("Roboto Bold"),
|
||||||
local("Roboto-Bold"),
|
local("Roboto-Bold"),
|
||||||
url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2");
|
url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2");
|
||||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F,
|
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
|
||||||
U+A720-A7FF;
|
U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"permalink": "Získat trvalý odkaz",
|
"permalink": "Získat trvalý odkaz",
|
||||||
"previous": "Předchozí",
|
"previous": "Předchozí",
|
||||||
|
"preview": "Preview",
|
||||||
"publish": "Publikovat",
|
"publish": "Publikovat",
|
||||||
"rename": "Přejmenovat",
|
"rename": "Přejmenovat",
|
||||||
"replace": "Nahradit",
|
"replace": "Nahradit",
|
||||||
@@ -3,14 +3,17 @@
|
|||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
"clear": "Schließen",
|
"clear": "Schließen",
|
||||||
"close": "Schließen",
|
"close": "Schließen",
|
||||||
|
"continue": "Fortfahren",
|
||||||
"copy": "Kopieren",
|
"copy": "Kopieren",
|
||||||
"copyFile": "Kopiere Datei",
|
"copyFile": "Kopiere Datei",
|
||||||
"copyToClipboard": "In Zwischenablage kopieren",
|
"copyToClipboard": "In Zwischenablage kopieren",
|
||||||
|
"copyDownloadLinkToClipboard": "Download-Link in die Zwischenablage kopieren",
|
||||||
"create": "Neu",
|
"create": "Neu",
|
||||||
"delete": "Löschen",
|
"delete": "Löschen",
|
||||||
"download": "Herunterladen",
|
"download": "Herunterladen",
|
||||||
"file": "Datei",
|
"file": "Datei",
|
||||||
"folder": "Ordner",
|
"folder": "Ordner",
|
||||||
|
"fullScreen": "Vollbildmodus umschalten",
|
||||||
"hideDotfiles": "Versteckte Dateien ausblenden",
|
"hideDotfiles": "Versteckte Dateien ausblenden",
|
||||||
"info": "Info",
|
"info": "Info",
|
||||||
"more": "mehr",
|
"more": "mehr",
|
||||||
@@ -21,6 +24,7 @@
|
|||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"permalink": "permanenten Verweis anzeigen",
|
"permalink": "permanenten Verweis anzeigen",
|
||||||
"previous": "vorherige",
|
"previous": "vorherige",
|
||||||
|
"preview": "Vorschau",
|
||||||
"publish": "Veröffentlichen",
|
"publish": "Veröffentlichen",
|
||||||
"rename": "umbenennen",
|
"rename": "umbenennen",
|
||||||
"replace": "Ersetzen",
|
"replace": "Ersetzen",
|
||||||
@@ -37,13 +41,17 @@
|
|||||||
"toggleSidebar": "Seitenleiste anzeigen",
|
"toggleSidebar": "Seitenleiste anzeigen",
|
||||||
"update": "Update",
|
"update": "Update",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"openFile": "Datei öffnen"
|
"openFile": "Datei öffnen",
|
||||||
|
"discardChanges": "Verwerfen"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Download Datei",
|
"downloadFile": "Download Datei",
|
||||||
"downloadFolder": "Download Ordner",
|
"downloadFolder": "Download Ordner",
|
||||||
"downloadSelected": "Auswahl herunterladen"
|
"downloadSelected": "Auswahl herunterladen"
|
||||||
},
|
},
|
||||||
|
"upload": {
|
||||||
|
"abortUpload": "Sind Sie sicher, dass Sie den Vorgang abbrechen möchten?"
|
||||||
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "Sie haben keine Berechtigung dies abzurufen.",
|
"forbidden": "Sie haben keine Berechtigung dies abzurufen.",
|
||||||
"internal": "Etwas ist schiefgelaufen.",
|
"internal": "Etwas ist schiefgelaufen.",
|
||||||
@@ -102,6 +110,7 @@
|
|||||||
"deleteMessageMultiple": "Sind Sie sicher, dass Sie {count} Datei(en) löschen möchten?",
|
"deleteMessageMultiple": "Sind Sie sicher, dass Sie {count} Datei(en) löschen möchten?",
|
||||||
"deleteMessageSingle": "Sind Sie sicher, dass Sie diesen Ordner/diese Datei löschen möchten?",
|
"deleteMessageSingle": "Sind Sie sicher, dass Sie diesen Ordner/diese Datei löschen möchten?",
|
||||||
"deleteMessageShare": "Sind Sie sicher, dass Sie diese Freigabe löschen möchten ({path})?",
|
"deleteMessageShare": "Sind Sie sicher, dass Sie diese Freigabe löschen möchten ({path})?",
|
||||||
|
"deleteUser": "Sind Sie sicher, dass Sie diesen Benutzer löschen möchten?",
|
||||||
"deleteTitle": "Lösche Dateien",
|
"deleteTitle": "Lösche Dateien",
|
||||||
"displayName": "Anzeigename:",
|
"displayName": "Anzeigename:",
|
||||||
"download": "Lade Dateien",
|
"download": "Lade Dateien",
|
||||||
@@ -130,7 +139,9 @@
|
|||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"uploadFiles": "Upload von {files} Dateien...",
|
"uploadFiles": "Upload von {files} Dateien...",
|
||||||
"uploadMessage": "Wählen Sie eine Upload-Methode",
|
"uploadMessage": "Wählen Sie eine Upload-Methode",
|
||||||
"optionalPassword": "Optionales Passwort"
|
"optionalPassword": "Optionales Passwort",
|
||||||
|
"resolution": "Auflösung",
|
||||||
|
"discardEditorChanges": "Möchten Sie die vorgenommenen Änderungen wirklich verwerfen?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "Bilder",
|
"images": "Bilder",
|
||||||
@@ -163,6 +174,9 @@
|
|||||||
"tusUploadsHelp": "File Browser unterstützt das Hochladen von gestückelten Dateien und ermöglicht so einen effizienten, zuverlässigen, fortsetzbaren und gestückelten Datei-Upload auch in unzuverlässigen Netzwerken.",
|
"tusUploadsHelp": "File Browser unterstützt das Hochladen von gestückelten Dateien und ermöglicht so einen effizienten, zuverlässigen, fortsetzbaren und gestückelten Datei-Upload auch in unzuverlässigen Netzwerken.",
|
||||||
"tusUploadsChunkSize": "Gibt die maximale Größe pro Anfrage an (direkte Uploads werden für kleinere Uploads verwendet). Bitte geben Sie eine Byte-Angabe oder eine Zeichenfolge wie 10 MB, 1 GB usw. an",
|
"tusUploadsChunkSize": "Gibt die maximale Größe pro Anfrage an (direkte Uploads werden für kleinere Uploads verwendet). Bitte geben Sie eine Byte-Angabe oder eine Zeichenfolge wie 10 MB, 1 GB usw. an",
|
||||||
"tusUploadsRetryCount": "Anzahl der Wiederholungsversuche, wenn das Hochladen eines Stückes fehlschlägt.",
|
"tusUploadsRetryCount": "Anzahl der Wiederholungsversuche, wenn das Hochladen eines Stückes fehlschlägt.",
|
||||||
|
"userHomeBasePath": "Basispfad für Benutzer-Home-Verzeichnisse",
|
||||||
|
"userScopeGenerationPlaceholder": "Scope wird automatisch generiert",
|
||||||
|
"createUserHomeDirectory": "Benutzer-Home-Verzeichnis erstellen",
|
||||||
"customStylesheet": "Individuelles Stylesheet",
|
"customStylesheet": "Individuelles Stylesheet",
|
||||||
"defaultUserDescription": "Das sind die Standardeinstellung für Benutzer",
|
"defaultUserDescription": "Das sind die Standardeinstellung für Benutzer",
|
||||||
"disableExternalLinks": "Externe Links deaktivieren (außer Dokumentation)",
|
"disableExternalLinks": "Externe Links deaktivieren (außer Dokumentation)",
|
||||||
@@ -209,6 +223,7 @@
|
|||||||
"shareDeleted": "Freigabe gelöscht!",
|
"shareDeleted": "Freigabe gelöscht!",
|
||||||
"singleClick": "Einfacher Klick zum Öffnen von Dateien und Ordnern",
|
"singleClick": "Einfacher Klick zum Öffnen von Dateien und Ordnern",
|
||||||
"themes": {
|
"themes": {
|
||||||
|
"default": "Systemstandard",
|
||||||
"dark": "Dunkel",
|
"dark": "Dunkel",
|
||||||
"light": "Hell",
|
"light": "Hell",
|
||||||
"title": "Erscheinungsbild"
|
"title": "Erscheinungsbild"
|
||||||
|
|||||||
@@ -173,7 +173,7 @@
|
|||||||
"executeOnShellDescription": "Por defecto, FileBrowser ejecuta los comandos llamando directamente a sus binarios. Si quieres ejecutarlos en un shell en su lugar (como Bash o PowerShell), puedes definirlo aquí con los argumentos y banderas (flags) necesarios. Si se define, el comando que se ejecuta se añadirá como argumento. Esto se aplica tanto a los comandos de usuario como a los ganchos de eventos.",
|
"executeOnShellDescription": "Por defecto, FileBrowser ejecuta los comandos llamando directamente a sus binarios. Si quieres ejecutarlos en un shell en su lugar (como Bash o PowerShell), puedes definirlo aquí con los argumentos y banderas (flags) necesarios. Si se define, el comando que se ejecuta se añadirá como argumento. Esto se aplica tanto a los comandos de usuario como a los ganchos de eventos.",
|
||||||
"globalRules": "Se trata de un conjunto global de reglas de permiso y rechazo. Se aplican a todos los usuarios. Puedes definir reglas específicas en la configuración de cada usuario para anular estas.",
|
"globalRules": "Se trata de un conjunto global de reglas de permiso y rechazo. Se aplican a todos los usuarios. Puedes definir reglas específicas en la configuración de cada usuario para anular estas.",
|
||||||
"globalSettings": "Ajustes globales",
|
"globalSettings": "Ajustes globales",
|
||||||
"hideDotfiles": "",
|
"hideDotfiles": "Ocultar archivos empezados por punto",
|
||||||
"insertPath": "Introduce la ruta",
|
"insertPath": "Introduce la ruta",
|
||||||
"insertRegex": "Introducir expresión regular",
|
"insertRegex": "Introducir expresión regular",
|
||||||
"instanceName": "Nombre de la instancia",
|
"instanceName": "Nombre de la instancia",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"file": "Fichier",
|
"file": "Fichier",
|
||||||
"folder": "Dossier",
|
"folder": "Dossier",
|
||||||
"fullScreen": "Plein écran",
|
"fullScreen": "Plein écran",
|
||||||
"hideDotfiles": "Masquer les dotfiles",
|
"hideDotfiles": "Masquer les fichiers cachés",
|
||||||
"info": "Info",
|
"info": "Info",
|
||||||
"more": "Plus",
|
"more": "Plus",
|
||||||
"move": "Déplacer",
|
"move": "Déplacer",
|
||||||
@@ -22,15 +22,16 @@
|
|||||||
"new": "Nouveau",
|
"new": "Nouveau",
|
||||||
"next": "Suivant",
|
"next": "Suivant",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"permalink": "Obtenir un lien permanent",
|
"permalink": "Obtenir le lien permanent",
|
||||||
"previous": "Précédent",
|
"previous": "Précédent",
|
||||||
|
"preview": "Prévisualiser",
|
||||||
"publish": "Publier",
|
"publish": "Publier",
|
||||||
"rename": "Renommer",
|
"rename": "Renommer",
|
||||||
"replace": "Remplacer",
|
"replace": "Remplacer",
|
||||||
"reportIssue": "Rapport d'erreur",
|
"reportIssue": "Signaler un problème",
|
||||||
"save": "Enregistrer",
|
"save": "Enregistrer",
|
||||||
"schedule": "Fixer la date",
|
"schedule": "Planifier",
|
||||||
"search": "Chercher",
|
"search": "Rechercher",
|
||||||
"select": "Sélectionner",
|
"select": "Sélectionner",
|
||||||
"selectMultiple": "Sélection multiple",
|
"selectMultiple": "Sélection multiple",
|
||||||
"share": "Partager",
|
"share": "Partager",
|
||||||
@@ -40,18 +41,22 @@
|
|||||||
"toggleSidebar": "Afficher/Masquer la barre latérale",
|
"toggleSidebar": "Afficher/Masquer la barre latérale",
|
||||||
"update": "Mettre à jour",
|
"update": "Mettre à jour",
|
||||||
"upload": "Importer",
|
"upload": "Importer",
|
||||||
"openFile": "Ouvrir le fichier"
|
"openFile": "Ouvrir le fichier",
|
||||||
|
"discardChanges": "Annuler"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Télécharger le fichier",
|
"downloadFile": "Télécharger le fichier",
|
||||||
"downloadFolder": "Télécharger le dossier",
|
"downloadFolder": "Télécharger le dossier",
|
||||||
"downloadSelected": "Télécharger la selection"
|
"downloadSelected": "Télécharger la sélection"
|
||||||
|
},
|
||||||
|
"upload": {
|
||||||
|
"abortUpload": "Êtes-vous sûr de vouloir annuler ?"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "Vous n'avez pas la permission d'accéder à cela.",
|
"forbidden": "Vous n'avez pas la permission d'accéder à cela.",
|
||||||
"internal": "Aïe ! Quelque chose s'est mal passé.",
|
"internal": "Aïe ! Quelque chose s'est mal passé.",
|
||||||
"notFound": "Impossible d'accéder à cet emplacement.",
|
"notFound": "Impossible d'accéder à cet emplacement.",
|
||||||
"connection": "Le serveur n'est pas accessible."
|
"connection": "Le serveur est injoignable."
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"body": "Corps",
|
"body": "Corps",
|
||||||
@@ -61,15 +66,15 @@
|
|||||||
"home": "Accueil",
|
"home": "Accueil",
|
||||||
"lastModified": "Dernière modification",
|
"lastModified": "Dernière modification",
|
||||||
"loading": "Chargement...",
|
"loading": "Chargement...",
|
||||||
"lonely": "Il semble qu'il n'y ait rien par ici...",
|
"lonely": "C'est un peu désert ici...",
|
||||||
"metadata": "Metadonnées",
|
"metadata": "Métadonnées",
|
||||||
"multipleSelectionEnabled": "Sélection multiple activée",
|
"multipleSelectionEnabled": "Sélection multiple activée",
|
||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"size": "Taille",
|
"size": "Taille",
|
||||||
"sortByLastModified": "Trier par date de dernière modification",
|
"sortByLastModified": "Trier par date de modification",
|
||||||
"sortByName": "Trier par nom",
|
"sortByName": "Trier par nom",
|
||||||
"sortBySize": "Trier par taille",
|
"sortBySize": "Trier par taille",
|
||||||
"noPreview": "Il n'y a pas de prévisualisation pour ce fichier."
|
"noPreview": "L'aperçu n'est pas disponible pour ce fichier."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "Sélectionner un élément",
|
"click": "Sélectionner un élément",
|
||||||
@@ -105,6 +110,7 @@
|
|||||||
"deleteMessageMultiple": "Êtes-vous sûr de vouloir supprimer ces {count} élément(s) ?",
|
"deleteMessageMultiple": "Êtes-vous sûr de vouloir supprimer ces {count} élément(s) ?",
|
||||||
"deleteMessageSingle": "Êtes-vous sûr de vouloir supprimer cet élément ?",
|
"deleteMessageSingle": "Êtes-vous sûr de vouloir supprimer cet élément ?",
|
||||||
"deleteMessageShare": "Êtes-vous sûr de vouloir supprimer ce partage ({path}) ?",
|
"deleteMessageShare": "Êtes-vous sûr de vouloir supprimer ce partage ({path}) ?",
|
||||||
|
"deleteUser": "Êtes-vous sûr de vouloir supprimer cet utilisateur ?",
|
||||||
"deleteTitle": "Supprimer",
|
"deleteTitle": "Supprimer",
|
||||||
"displayName": "Nom :",
|
"displayName": "Nom :",
|
||||||
"download": "Télécharger",
|
"download": "Télécharger",
|
||||||
@@ -125,31 +131,33 @@
|
|||||||
"rename": "Renommer",
|
"rename": "Renommer",
|
||||||
"renameMessage": "Nouveau nom pour",
|
"renameMessage": "Nouveau nom pour",
|
||||||
"replace": "Remplacer",
|
"replace": "Remplacer",
|
||||||
"replaceMessage": "Un des fichiers que vous êtes en train d'importer a le même nom qu'un autre déjà présent. Voulez-vous remplacer le fichier actuel par le nouveau ?\n",
|
"replaceMessage": "L'un des fichiers que vous êtes en train d'importer a le même nom qu'un autre déjà présent. Voulez-vous remplacer le fichier actuel par le nouveau ?\n",
|
||||||
"schedule": "Fixer la date",
|
"schedule": "Planifier",
|
||||||
"scheduleMessage": "Choisissez une date pour planifier la publication de ce post",
|
"scheduleMessage": "Choisissez une date pour planifier la publication de ce post",
|
||||||
"show": "Montrer",
|
"show": "Montrer",
|
||||||
"size": "Taille",
|
"size": "Taille",
|
||||||
"upload": "Importer",
|
"upload": "Importer",
|
||||||
"uploadFiles": "Importation de {files} fichiers...",
|
"uploadFiles": "Importation de {files} fichiers...",
|
||||||
"uploadMessage": "Séléctionnez une option d'import.",
|
"uploadMessage": "Sélectionnez une option d'import.",
|
||||||
"optionalPassword": "Mot de passe optionnel"
|
"optionalPassword": "Mot de passe optionnel",
|
||||||
|
"resolution": "Résolution",
|
||||||
|
"discardEditorChanges": "Êtes-vous sûr de vouloir annuler les modifications apportées ?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "Images",
|
"images": "Images",
|
||||||
"music": "Musique",
|
"music": "Musique",
|
||||||
"pdf": "PDF",
|
"pdf": "PDF",
|
||||||
"pressToSearch": "Appuyez du entrée pour chercher...",
|
"pressToSearch": "Appuyez sur Entrée pour rechercher...",
|
||||||
"search": "Recherche en cours...",
|
"search": "Recherche en cours...",
|
||||||
"typeToSearch": "Écrivez pour chercher...",
|
"typeToSearch": "Écrivez pour rechercher...",
|
||||||
"types": "Types",
|
"types": "Types",
|
||||||
"video": "Video"
|
"video": "Vidéo"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrateur",
|
"administrator": "Administrateur",
|
||||||
"allowCommands": "Exécuter des commandes",
|
"allowCommands": "Exécuter des commandes",
|
||||||
"allowEdit": "Editer, renommer et supprimer des fichiers ou des dossiers",
|
"allowEdit": "Éditer, renommer et supprimer des fichiers ou des dossiers",
|
||||||
"allowNew": "Créer de nouveaux fichiers et dossiers",
|
"allowNew": "Créer de nouveaux fichiers et dossiers",
|
||||||
"allowPublish": "Publier de nouveaux posts et pages",
|
"allowPublish": "Publier de nouveaux posts et pages",
|
||||||
"allowSignup": "Autoriser les utilisateurs à s'inscrire",
|
"allowSignup": "Autoriser les utilisateurs à s'inscrire",
|
||||||
@@ -158,32 +166,39 @@
|
|||||||
"brandingDirectoryPath": "Chemin du dossier d'image de marque",
|
"brandingDirectoryPath": "Chemin du dossier d'image de marque",
|
||||||
"brandingHelp": "Vous pouvez personnaliser l'apparence de votre instance de File Browser en changeant son nom, en remplaçant le logo, en ajoutant des styles personnalisés et même en désactivant les liens externes vers GitHub.\nPour plus d'informations sur la personnalisation de l'image de marque, veuillez consulter la {0}.",
|
"brandingHelp": "Vous pouvez personnaliser l'apparence de votre instance de File Browser en changeant son nom, en remplaçant le logo, en ajoutant des styles personnalisés et même en désactivant les liens externes vers GitHub.\nPour plus d'informations sur la personnalisation de l'image de marque, veuillez consulter la {0}.",
|
||||||
"changePassword": "Modifier le mot de passe",
|
"changePassword": "Modifier le mot de passe",
|
||||||
"commandRunner": "Command runner",
|
"commandRunner": "Exécuteur de commandes",
|
||||||
"commandRunnerHelp": "Ici, vous pouvez définir les commandes qui sont exécutées pour les événements nommés précédemments. Vous devez en écrire une par ligne. Les variables d'environnement {0} et {1} seront disponibles, {0} étant relatif à {1}. Pour plus d'informations sur cette fonctionnalité et les variables d'environnement disponibles, veuillez lire la {2}.",
|
"commandRunnerHelp": "Ici, vous pouvez définir les commandes qui seront exécutées lors des événements nommés précédemments. Vous devez en écrire une par ligne. Les variables d'environnement {0} et {1} seront disponibles, {0} étant relatif à {1}. Pour plus d'informations sur cette fonctionnalité et les variables d'environnement disponibles, veuillez lire la {2}.",
|
||||||
"commandsUpdated": "Commandes mises à jour !",
|
"commandsUpdated": "Commandes mises à jour !",
|
||||||
"createUserDir": "Créer automatiquement un dossier pour l'utilisateur",
|
"createUserDir": "Créer automatiquement un dossier pour l'utilisateur",
|
||||||
|
"tusUploads": "Uploads segmentés",
|
||||||
|
"tusUploadsHelp": "File Browser prend en charge les uploads segmentés afin de permettre une gestion efficace, fiable et reprenable sur des réseaux instables.",
|
||||||
|
"tusUploadsChunkSize": "Taille maximale autorisée par segment (les uploads directs seront utilisés pour les fichiers plus petits). Vous pouvez entrer un entier en octets ou une chaîne telle que 10MB, 1GB, etc.",
|
||||||
|
"tusUploadsRetryCount": "Nombre de tentatives en cas d'échec d'un segment.",
|
||||||
|
"userHomeBasePath": "Chemin de base pour les répertoires personnels des utilisateurs",
|
||||||
|
"userScopeGenerationPlaceholder": "Le périmètre sera généré automatiquement",
|
||||||
|
"createUserHomeDirectory": "Créer le répertoire personnel de l'utilisateur",
|
||||||
"customStylesheet": "Feuille de style personnalisée",
|
"customStylesheet": "Feuille de style personnalisée",
|
||||||
"defaultUserDescription": "Paramètres par défaut pour les nouveaux utilisateurs.",
|
"defaultUserDescription": "Paramètres par défaut pour les nouveaux utilisateurs.",
|
||||||
"disableExternalLinks": "Désactiver les liens externes (sauf la documentation)",
|
"disableExternalLinks": "Désactiver les liens externes (sauf la documentation)",
|
||||||
"disableUsedDiskPercentage": "Disable used disk percentage graph",
|
"disableUsedDiskPercentage": "Désactiver le graphique de pourcentage d'utilisation du disque",
|
||||||
"documentation": "documentation",
|
"documentation": "documentation",
|
||||||
"examples": "Exemples",
|
"examples": "Exemples",
|
||||||
"executeOnShell": "Exécuter dans le shell",
|
"executeOnShell": "Exécuter dans le shell",
|
||||||
"executeOnShellDescription": "Par défaut, File Browser exécute les commandes en appelant directement leurs binaires. Si vous voulez les exécuter sur un shell à la place (comme Bash ou PowerShell), vous pouvez le définir ici avec les arguments et les drapeaux requis. S'il est défini, la commande que vous exécutez sera ajoutée en tant qu'argument. Cela s'applique à la fois aux commandes utilisateur et aux crochets d'événements.",
|
"executeOnShellDescription": "Par défaut, File Browser exécute les commandes en appelant directement leurs binaires. Si vous voulez les exécuter sur un shell à la place (comme Bash ou PowerShell), vous pouvez le définir ici avec les arguments et les drapeaux requis. S'il est défini, la commande que vous exécutez sera ajoutée en tant qu'argument. Cela s'applique à la fois aux commandes utilisateur et aux crochets d'événements.",
|
||||||
"globalRules": "Il s'agit d'un ensemble global de règles d'autorisation et d'interdiction. Elles s'appliquent à tous les utilisateurs. Vous pouvez définir des règles spécifiques sur les paramètres de chaque utilisateur pour remplacer celles-ci.",
|
"globalRules": "Il s'agit d'un ensemble global de règles d'autorisation et d'interdiction. Elles s'appliquent à tous les utilisateurs. Vous pouvez définir des règles spécifiques sur les paramètres de chaque utilisateur pour remplacer celles-ci.",
|
||||||
"globalSettings": "Paramètres généraux",
|
"globalSettings": "Paramètres globaux",
|
||||||
"hideDotfiles": "Cacher les fichiers de configuration utilisateur (dotfiles)",
|
"hideDotfiles": "Cacher les fichiers de configuration utilisateur (dotfiles)",
|
||||||
"insertPath": "Insérez le chemin",
|
"insertPath": "Insérer le chemin",
|
||||||
"insertRegex": "Insérez l'expression régulière",
|
"insertRegex": "Insérer une expression régulière",
|
||||||
"instanceName": "Nom de l'instance",
|
"instanceName": "Nom de l'instance",
|
||||||
"language": "Langue",
|
"language": "Langue",
|
||||||
"lockPassword": "Empêcher l'utilisateur de changer son mot de passe",
|
"lockPassword": "Empêcher l'utilisateur de changer son mot de passe",
|
||||||
"newPassword": "Votre nouveau mot de passe",
|
"newPassword": "Votre nouveau mot de passe",
|
||||||
"newPasswordConfirm": "Confirmation du nouveau mot de passe",
|
"newPasswordConfirm": "Confirmation du nouveau mot de passe",
|
||||||
"newUser": "Nouvel Utilisateur",
|
"newUser": "Nouvel utilisateur",
|
||||||
"password": "Mot de passe",
|
"password": "Mot de passe",
|
||||||
"passwordUpdated": "Mot de passe mis à jour !",
|
"passwordUpdated": "Mot de passe mis à jour !",
|
||||||
"path": "",
|
"path": "Chemin",
|
||||||
"perm": {
|
"perm": {
|
||||||
"create": "Créer des fichiers et des dossiers",
|
"create": "Créer des fichiers et des dossiers",
|
||||||
"delete": "Supprimer des fichiers et des dossiers",
|
"delete": "Supprimer des fichiers et des dossiers",
|
||||||
@@ -209,14 +224,14 @@
|
|||||||
"singleClick": "Utiliser un simple clic pour ouvrir les fichiers et les dossiers",
|
"singleClick": "Utiliser un simple clic pour ouvrir les fichiers et les dossiers",
|
||||||
"themes": {
|
"themes": {
|
||||||
"dark": "Sombre",
|
"dark": "Sombre",
|
||||||
"light": "Lumineux",
|
"light": "Clair",
|
||||||
"title": "Thème"
|
"title": "Thème"
|
||||||
},
|
},
|
||||||
"user": "Utilisateur",
|
"user": "Utilisateur",
|
||||||
"userCommands": "Commandes",
|
"userCommands": "Commandes",
|
||||||
"userCommandsHelp": "Une liste séparée par des espaces des commandes permises pour l'utilisateur. Exemple :",
|
"userCommandsHelp": "Une liste séparée par des espaces des commandes permises pour l'utilisateur. Exemple :\n",
|
||||||
"userCreated": "Utilisateur créé !",
|
"userCreated": "Utilisateur créé !",
|
||||||
"userDefaults": "User default settings",
|
"userDefaults": "Paramètres par défaut de l'utilisateur",
|
||||||
"userDeleted": "Utilisateur supprimé !",
|
"userDeleted": "Utilisateur supprimé !",
|
||||||
"userManagement": "Gestion des utilisateurs",
|
"userManagement": "Gestion des utilisateurs",
|
||||||
"userUpdated": "Utilisateur mis à jour !",
|
"userUpdated": "Utilisateur mis à jour !",
|
||||||
@@ -237,7 +252,7 @@
|
|||||||
"siteSettings": "Paramètres du site"
|
"siteSettings": "Paramètres du site"
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
"linkCopied": "Lien copié!"
|
"linkCopied": "Lien copié !"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"days": "Jours",
|
"days": "Jours",
|
||||||
|
|||||||
@@ -23,8 +23,10 @@ import("dayjs/locale/sk");
|
|||||||
import("dayjs/locale/sv");
|
import("dayjs/locale/sv");
|
||||||
import("dayjs/locale/tr");
|
import("dayjs/locale/tr");
|
||||||
import("dayjs/locale/uk");
|
import("dayjs/locale/uk");
|
||||||
|
import("dayjs/locale/vi");
|
||||||
import("dayjs/locale/zh-cn");
|
import("dayjs/locale/zh-cn");
|
||||||
import("dayjs/locale/zh-tw");
|
import("dayjs/locale/zh-tw");
|
||||||
|
import("dayjs/locale/cs");
|
||||||
|
|
||||||
// All i18n resources specified in the plugin `include` option can be loaded
|
// All i18n resources specified in the plugin `include` option can be loaded
|
||||||
// at once using the import syntax
|
// at once using the import syntax
|
||||||
@@ -103,6 +105,9 @@ export function detectLocale() {
|
|||||||
case /^uk\b/.test(locale):
|
case /^uk\b/.test(locale):
|
||||||
locale = "uk";
|
locale = "uk";
|
||||||
break;
|
break;
|
||||||
|
case /^vi\b/.test(locale):
|
||||||
|
locale = "vi";
|
||||||
|
break;
|
||||||
case /^sv-se\b/.test(locale):
|
case /^sv-se\b/.test(locale):
|
||||||
case /^sv\b/.test(locale):
|
case /^sv\b/.test(locale):
|
||||||
locale = "sv";
|
locale = "sv";
|
||||||
@@ -142,7 +147,7 @@ export const i18n = createI18n({
|
|||||||
|
|
||||||
export const isRtl = (locale?: string) => {
|
export const isRtl = (locale?: string) => {
|
||||||
// see below
|
// see below
|
||||||
// @ts-ignore
|
// @ts-expect-error incorrect type when legacy
|
||||||
return rtlLanguages.includes(locale || i18n.global.locale.value);
|
return rtlLanguages.includes(locale || i18n.global.locale.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -150,7 +155,7 @@ export function setLocale(locale: string) {
|
|||||||
dayjs.locale(locale);
|
dayjs.locale(locale);
|
||||||
// according to doc u only need .value if legacy: false but they lied
|
// according to doc u only need .value if legacy: false but they lied
|
||||||
// https://vue-i18n.intlify.dev/guide/essentials/scope.html#local-scope-1
|
// https://vue-i18n.intlify.dev/guide/essentials/scope.html#local-scope-1
|
||||||
//@ts-ignore
|
// @ts-expect-error incorrect type when legacy
|
||||||
i18n.global.locale.value = locale;
|
i18n.global.locale.value = locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,47 +3,60 @@
|
|||||||
"cancel": "취소",
|
"cancel": "취소",
|
||||||
"clear": "지우기",
|
"clear": "지우기",
|
||||||
"close": "닫기",
|
"close": "닫기",
|
||||||
|
"continue": "계속",
|
||||||
"copy": "복사",
|
"copy": "복사",
|
||||||
"copyFile": "파일 복사",
|
"copyFile": "파일 복사",
|
||||||
"copyToClipboard": "클립보드 복사",
|
"copyToClipboard": "클립보드에 복사",
|
||||||
|
"copyDownloadLinkToClipboard": "다운로드 링크 클립보드에 복사",
|
||||||
"create": "생성",
|
"create": "생성",
|
||||||
"delete": "삭제",
|
"delete": "삭제",
|
||||||
"download": "다운로드",
|
"download": "다운로드",
|
||||||
"hideDotfiles": "",
|
"file": "파일",
|
||||||
|
"folder": "폴더",
|
||||||
|
"fullScreen": "전체 화면 전환",
|
||||||
|
"hideDotfiles": "숨김 파일 숨기기",
|
||||||
"info": "정보",
|
"info": "정보",
|
||||||
"more": "더보기",
|
"more": "더 보기",
|
||||||
"move": "이동",
|
"move": "이동",
|
||||||
"moveFile": "파일 이동",
|
"moveFile": "파일 이동",
|
||||||
"new": "신규",
|
"new": "새로 만들기",
|
||||||
"next": "다음",
|
"next": "다음",
|
||||||
"ok": "확인",
|
"ok": "확인",
|
||||||
"permalink": "링크 얻기",
|
"permalink": "영구 링크 받기",
|
||||||
"previous": "이전",
|
"previous": "이전",
|
||||||
|
"preview": "미리보기",
|
||||||
"publish": "게시",
|
"publish": "게시",
|
||||||
"rename": "이름 바꾸기",
|
"rename": "이름 바꾸기",
|
||||||
"replace": "대체",
|
"replace": "바꾸기",
|
||||||
"reportIssue": "이슈 보내기",
|
"reportIssue": "문제 보고",
|
||||||
"save": "저장",
|
"save": "저장",
|
||||||
"schedule": "일정",
|
"schedule": "예약",
|
||||||
"search": "검색",
|
"search": "검색",
|
||||||
"select": "선택",
|
"select": "선택",
|
||||||
"selectMultiple": "다중 선택",
|
"selectMultiple": "다중 선택",
|
||||||
"share": "공유",
|
"share": "공유",
|
||||||
"shell": "쉘 전환",
|
"shell": "셸 전환",
|
||||||
|
"submit": "제출",
|
||||||
"switchView": "보기 전환",
|
"switchView": "보기 전환",
|
||||||
"toggleSidebar": "사이드바 전환",
|
"toggleSidebar": "사이드바 전환",
|
||||||
"update": "업데이트",
|
"update": "업데이트",
|
||||||
"upload": "업로드"
|
"upload": "업로드",
|
||||||
|
"openFile": "파일 열기",
|
||||||
|
"discardChanges": "변경 사항 취소"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "파일 다운로드",
|
"downloadFile": "파일 다운로드",
|
||||||
"downloadFolder": "폴더 다운로드",
|
"downloadFolder": "폴더 다운로드",
|
||||||
"downloadSelected": ""
|
"downloadSelected": "선택 항목 다운로드"
|
||||||
|
},
|
||||||
|
"upload": {
|
||||||
|
"abortUpload": "업로드를 중단하시겠습니까?"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "접근 권한이 없습니다.",
|
"forbidden": "이곳에 접근할 권한이 없습니다.",
|
||||||
"internal": "오류가 발생하였습니다.",
|
"internal": "문제가 발생했습니다.",
|
||||||
"notFound": "해당 경로를 찾을 수 없습니다."
|
"notFound": "이 위치에 접근할 수 없습니다.",
|
||||||
|
"connection": "서버에 연결할 수 없습니다."
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"body": "본문",
|
"body": "본문",
|
||||||
@@ -51,175 +64,192 @@
|
|||||||
"files": "파일",
|
"files": "파일",
|
||||||
"folders": "폴더",
|
"folders": "폴더",
|
||||||
"home": "홈",
|
"home": "홈",
|
||||||
"lastModified": "최종 수정",
|
"lastModified": "마지막 수정일",
|
||||||
"loading": "로딩중...",
|
"loading": "로딩 중...",
|
||||||
"lonely": "폴더가 비어 있습니다...",
|
"lonely": "여기에 아무것도 없네요...",
|
||||||
"metadata": "메타데이터",
|
"metadata": "메타데이터",
|
||||||
"multipleSelectionEnabled": "다중 선택 켜짐",
|
"multipleSelectionEnabled": "다중 선택 활성화됨",
|
||||||
"name": "이름",
|
"name": "이름",
|
||||||
"size": "크기",
|
"size": "크기",
|
||||||
"sortByLastModified": "수정시간순 정렬",
|
"sortByLastModified": "마지막 수정일 순 정렬",
|
||||||
"sortByName": "이름순",
|
"sortByName": "이름 순 정렬",
|
||||||
"sortBySize": "크기순"
|
"sortBySize": "크기 순 정렬",
|
||||||
|
"noPreview": "이 파일은 미리보기를 사용할 수 없습니다."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "파일이나 디렉토리를 선택해주세요.",
|
"click": "파일 또는 디렉터리 선택",
|
||||||
"ctrl": {
|
"ctrl": {
|
||||||
"click": "여러 개의 파일이나 디렉토리를 선택해주세요.",
|
"click": "여러 파일 또는 디렉터리 선택",
|
||||||
"f": "검색창 열기",
|
"f": "검색 열기",
|
||||||
"s": "파일 또는 디렉토리 다운로드"
|
"s": "파일 저장 또는 현재 디렉터리 다운로드"
|
||||||
},
|
},
|
||||||
"del": "선택된 파일 삭제",
|
"del": "선택한 항목 삭제",
|
||||||
"doubleClick": "파일 또는 디렉토리 열기",
|
"doubleClick": "파일 또는 디렉터리 열기",
|
||||||
"esc": "선택 취소/프롬프트 닫기",
|
"esc": "선택 취소 및/또는 프롬프트 닫기",
|
||||||
"f1": "정보",
|
"f1": "이 정보",
|
||||||
"f2": "파일 이름 변경",
|
"f2": "파일 이름 바꾸기",
|
||||||
"help": "도움말"
|
"help": "도움말"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"createAnAccount": "계정 생성",
|
"createAnAccount": "계정 만들기",
|
||||||
"loginInstead": "이미 계정이 있습니다",
|
"loginInstead": "이미 계정이 있습니다",
|
||||||
"password": "비밀번호",
|
"password": "비밀번호",
|
||||||
"passwordConfirm": "비밀번호 확인",
|
"passwordConfirm": "비밀번호 확인",
|
||||||
"passwordsDontMatch": "비밀번호가 일치하지 않습니다",
|
"passwordsDontMatch": "비밀번호가 일치하지 않습니다",
|
||||||
"signup": "가입하기",
|
"signup": "가입",
|
||||||
"submit": "로그인",
|
"submit": "로그인",
|
||||||
"username": "사용자 이름",
|
"username": "사용자 이름",
|
||||||
"usernameTaken": "사용자 이름이 존재합니다",
|
"usernameTaken": "이미 사용 중인 사용자 이름입니다",
|
||||||
"wrongCredentials": "사용자 이름 또는 비밀번호를 확인하십시오"
|
"wrongCredentials": "잘못된 자격 증명"
|
||||||
},
|
},
|
||||||
"permanent": "영구",
|
"permanent": "영구",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
"copy": "복사",
|
"copy": "복사",
|
||||||
"copyMessage": "복사할 디렉토리:",
|
"copyMessage": "파일을 복사할 위치를 선택하세요:",
|
||||||
"currentlyNavigating": "현재 위치:",
|
"currentlyNavigating": "현재 탐색 중:",
|
||||||
"deleteMessageMultiple": "{count} 개의 파일을 삭제하시겠습니까?",
|
"deleteMessageMultiple": "{count}개의 파일을 삭제하시겠습니까?",
|
||||||
"deleteMessageSingle": "파일 혹은 디렉토리를 삭제하시겠습니까?",
|
"deleteMessageSingle": "이 파일/폴더를 삭제하시겠습니까?",
|
||||||
|
"deleteMessageShare": "이 공유({path})를 삭제하시겠습니까?",
|
||||||
|
"deleteUser": "이 사용자를 삭제하시겠습니까?",
|
||||||
"deleteTitle": "파일 삭제",
|
"deleteTitle": "파일 삭제",
|
||||||
"displayName": "게시 이름:",
|
"displayName": "표시 이름:",
|
||||||
"download": "파일 다운로드",
|
"download": "파일 다운로드",
|
||||||
"downloadMessage": "다운로드 포맷 설정.",
|
"downloadMessage": "다운로드할 형식을 선택하세요.",
|
||||||
"error": "에러 발생!",
|
"error": "문제가 발생했습니다",
|
||||||
"fileInfo": "파일 정보",
|
"fileInfo": "파일 정보",
|
||||||
"filesSelected": "{count} 개의 파일이 선택되었습니다.",
|
"filesSelected": "{count}개의 파일 선택됨.",
|
||||||
"lastModified": "최종 수정",
|
"lastModified": "마지막 수정일",
|
||||||
"move": "이동",
|
"move": "이동",
|
||||||
"moveMessage": "이동할 화일 또는 디렉토리를 선택하세요:",
|
"moveMessage": "파일/폴더의 새 위치를 선택하세요:",
|
||||||
"newArchetype": "원형을 유지하는 포스트를 생성합니다. 파일은 컨텐트 폴더에 생성됩니다.",
|
"newArchetype": "아키타입을 기반으로 새 게시물을 만듭니다. 파일은 content 폴더에 생성됩니다.",
|
||||||
"newDir": "새 디렉토리",
|
"newDir": "새 디렉터리",
|
||||||
"newDirMessage": "새 디렉토리 이름을 입력해주세요.",
|
"newDirMessage": "새 디렉터리 이름을 지정하세요.",
|
||||||
"newFile": "새 파일",
|
"newFile": "새 파일",
|
||||||
"newFileMessage": "새 파일 이름을 입력해주세요.",
|
"newFileMessage": "새 파일 이름을 지정하세요.",
|
||||||
"numberDirs": "디렉토리 수",
|
"numberDirs": "디렉터리 수",
|
||||||
"numberFiles": "파일 수",
|
"numberFiles": "파일 수",
|
||||||
"rename": "이름 변경",
|
"rename": "이름 바꾸기",
|
||||||
"renameMessage": "새로운 이름을 입력하세요.",
|
"renameMessage": "새 이름을 입력하세요:",
|
||||||
"replace": "대체하기",
|
"replace": "바꾸기",
|
||||||
"replaceMessage": "동일한 파일 이름이 존재합니다. 현재 파일을 덮어쓸까요?\n",
|
"replaceMessage": "업로드하려는 파일 중 이름이 충돌하는 파일이 있습니다. 이 파일을 건너뛰고 업로드를 계속하거나 기존 파일을 바꾸시겠습니까?\n",
|
||||||
"schedule": "일정",
|
"schedule": "예약",
|
||||||
"scheduleMessage": "이 글을 공개할 시간을 알려주세요.",
|
"scheduleMessage": "이 게시물의 게시를 예약할 날짜와 시간을 선택하세요.",
|
||||||
"show": "보기",
|
"show": "표시",
|
||||||
"size": "크기",
|
"size": "크기",
|
||||||
"upload": "",
|
"upload": "업로드",
|
||||||
"uploadMessage": ""
|
"uploadFiles": "{files}개의 파일 업로드 중...",
|
||||||
|
"uploadMessage": "업로드할 옵션을 선택하세요.",
|
||||||
|
"optionalPassword": "선택적 비밀번호",
|
||||||
|
"resolution": "해상도",
|
||||||
|
"discardEditorChanges": "변경 사항을 취소하시겠습니까?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "이미지",
|
"images": "이미지",
|
||||||
"music": "음악",
|
"music": "음악",
|
||||||
"pdf": "PDF",
|
"pdf": "PDF",
|
||||||
"pressToSearch": "검색하려면 엔터를 입력하세요",
|
"pressToSearch": "Enter 키를 눌러 검색...",
|
||||||
"search": "검색...",
|
"search": "검색...",
|
||||||
"typeToSearch": "검색어 입력...",
|
"typeToSearch": "검색어 입력...",
|
||||||
"types": "Types",
|
"types": "유형",
|
||||||
"video": "비디오"
|
"video": "비디오"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"admin": "관리자",
|
"admin": "관리자",
|
||||||
"administrator": "관리자",
|
"administrator": "관리자",
|
||||||
"allowCommands": "명령 실행",
|
"allowCommands": "명령 실행 허용",
|
||||||
"allowEdit": "파일/디렉토리의 수정/변경/삭제 허용",
|
"allowEdit": "파일 또는 디렉터리 편집, 이름 바꾸기, 삭제 허용",
|
||||||
"allowNew": "파일/디렉토리 생성 허용",
|
"allowNew": "새 파일 및 디렉터리 생성 허용",
|
||||||
"allowPublish": "새 포스트/페이지 생성 허용",
|
"allowPublish": "새 게시물 및 페이지 게시 허용",
|
||||||
"allowSignup": "사용자 가입 허용",
|
"allowSignup": "사용자 가입 허용",
|
||||||
"avoidChanges": "(수정하지 않으면 비워두세요)",
|
"avoidChanges": "(변경하지 않으려면 비워두세요)",
|
||||||
"branding": "브랜딩",
|
"branding": "브랜딩",
|
||||||
"brandingDirectoryPath": "브랜드 디렉토리 경로",
|
"brandingDirectoryPath": "브랜딩 디렉터리 경로",
|
||||||
"brandingHelp": "File Browser 인스턴스는 이름, 로고, 스타일 등을 변경할 수 있습니다. 자세한 사항은 여기{0}에서 확인하세요.",
|
"brandingHelp": "File Browser 인스턴스의 이름 변경, 로고 교체, 사용자 정의 스타일 추가, GitHub 외부 링크 비활성화를 통해 모양과 느낌을 사용자 지정할 수 있습니다.\n사용자 정의 브랜딩에 대한 자세한 내용은 {0}을(를) 확인하세요.",
|
||||||
"changePassword": "비밀번호 변경",
|
"changePassword": "비밀번호 변경",
|
||||||
"commandRunner": "명령 실행기",
|
"commandRunner": "명령어 실행기",
|
||||||
"commandRunnerHelp": "이벤트에 해당하는 명령을 설정하세요. 줄당 1개의 명령을 적으세요. 환경 변수{0} 와 {1}이 사용가능하며, {0} 은 {1}에 상대 경로 입니다. 자세한 사항은 {2} 를 참조하세요.",
|
"commandRunnerHelp": "여기서 지정된 이벤트에서 실행될 명령어를 설정할 수 있습니다. 한 줄에 하나씩 작성해야 합니다. 환경 변수 {0} 및 {1}을(를) 사용할 수 있으며, {0}은(는) {1}에 상대적입니다. 이 기능과 사용 가능한 환경 변수에 대한 자세한 내용은 {2}을(를) 읽어보세요.",
|
||||||
"commandsUpdated": "명령 수정됨!",
|
"commandsUpdated": "명령어가 업데이트되었습니다!",
|
||||||
"createUserDir": "Auto create user home dir while adding new user",
|
"createUserDir": "새 사용자 추가 시 사용자 홈 디렉터리 자동 생성",
|
||||||
"customStylesheet": "커스텀 스타일시트",
|
"tusUploads": "청크 업로드",
|
||||||
"defaultUserDescription": "아래 사항은 신규 사용자들에 대한 기본 설정입니다.",
|
"tusUploadsHelp": "File Browser는 청크 파일 업로드를 지원하여 불안정한 네트워크에서도 효율적이고 안정적이며 재개 가능하고 분할된 파일 업로드를 가능하게 합니다.",
|
||||||
"disableExternalLinks": "외부 링크 감추기",
|
"tusUploadsChunkSize": "요청의 최대 크기를 나타냅니다 (더 작은 업로드에는 직접 업로드가 사용됩니다). 바이트 크기를 나타내는 일반 정수 또는 10MB, 1GB 등과 같은 문자열을 입력할 수 있습니다.",
|
||||||
"disableUsedDiskPercentage": "Disable used disk percentage graph",
|
"tusUploadsRetryCount": "청크 업로드 실패 시 재시도 횟수.",
|
||||||
|
"userHomeBasePath": "사용자 홈 디렉터리의 기본 경로",
|
||||||
|
"userScopeGenerationPlaceholder": "범위가 자동으로 생성됩니다",
|
||||||
|
"createUserHomeDirectory": "사용자 홈 디렉터리 생성",
|
||||||
|
"customStylesheet": "사용자 정의 스타일시트",
|
||||||
|
"defaultUserDescription": "새 사용자의 기본 설정입니다.",
|
||||||
|
"disableExternalLinks": "외부 링크 비활성화 (문서 제외)",
|
||||||
|
"disableUsedDiskPercentage": "사용된 디스크 비율 그래프 비활성화",
|
||||||
"documentation": "문서",
|
"documentation": "문서",
|
||||||
"examples": "예",
|
"examples": "예시",
|
||||||
"executeOnShell": "쉘에서 실행",
|
"executeOnShell": "셸에서 실행",
|
||||||
"executeOnShellDescription": "기본적으로 File Browser 는 바이너리를 명령어로 호출하여 실행합니다. 쉘을 통해 실행하기를 원한다면, Bash 또는 PowerShell 에 필요한 인수와 플래그를 설정하세요. 사용자 명령어와 이벤트 훅에 모두 적용됩니다.",
|
"executeOnShellDescription": "기본적으로 File Browser는 바이너리를 직접 호출하여 명령을 실행합니다. 대신 셸(예: Bash 또는 PowerShell)에서 실행하려면 필요한 인수 및 플래그와 함께 여기에 정의할 수 있습니다. 설정된 경우 실행하는 명령이 인수로 추가됩니다. 이는 사용자 명령과 이벤트 후크 모두에 적용됩니다.",
|
||||||
"globalRules": "규칙에 대한 전역설정으로 모든 사용자에게 적용됩니다. 지정된 규칙은 사용자 설정을 덮어쓰기 합니다.",
|
"globalRules": "이것은 전역 허용 및 차단 규칙 세트입니다. 모든 사용자에게 적용됩니다. 각 사용자 설정에서 특정 규칙을 정의하여 이 규칙을 재정의할 수 있습니다.",
|
||||||
"globalSettings": "전역 설정",
|
"globalSettings": "전역 설정",
|
||||||
"hideDotfiles": "",
|
"hideDotfiles": "숨김 파일 숨기기",
|
||||||
"insertPath": "경로 입력",
|
"insertPath": "경로 삽입",
|
||||||
"insertRegex": "정규식 입력",
|
"insertRegex": "정규식 표현 삽입",
|
||||||
"instanceName": "인스턴스 이름",
|
"instanceName": "인스턴스 이름",
|
||||||
"language": "언어",
|
"language": "언어",
|
||||||
"lockPassword": "사용자에 의한 비밀번호 변경을 허용하지 않음",
|
"lockPassword": "사용자가 비밀번호를 변경하지 못하도록 잠금",
|
||||||
"newPassword": "새로운 비밀번호",
|
"newPassword": "새 비밀번호",
|
||||||
"newPasswordConfirm": "새로운 비밀번호 확인",
|
"newPasswordConfirm": "새 비밀번호 확인",
|
||||||
"newUser": "새로운 사용자",
|
"newUser": "새 사용자",
|
||||||
"password": "비밀번호",
|
"password": "비밀번호",
|
||||||
"passwordUpdated": "비밀번호 수정 완료!",
|
"passwordUpdated": "비밀번호가 업데이트되었습니다!",
|
||||||
"path": "",
|
"path": "경로",
|
||||||
"perm": {
|
"perm": {
|
||||||
"create": "파일이나 디렉토리 생성하기",
|
"create": "파일 및 디렉터리 생성",
|
||||||
"delete": "화일이나 디렉토리 삭제하기",
|
"delete": "파일 및 디렉터리 삭제",
|
||||||
"download": "다운로드",
|
"download": "다운로드",
|
||||||
"execute": "명령 실행",
|
"execute": "명령 실행",
|
||||||
"modify": "파일 편집",
|
"modify": "파일 편집",
|
||||||
"rename": "파일 이름 변경 또는 디렉토리 이동",
|
"rename": "파일 및 디렉터리 이름 바꾸기 또는 이동",
|
||||||
"share": "파일 공유하기"
|
"share": "파일 공유"
|
||||||
},
|
},
|
||||||
"permissions": "권한",
|
"permissions": "권한",
|
||||||
"permissionsHelp": "사용자를 관리자로 만들거나 권한을 부여할 수 있습니다. 관리자를 선택하면, 모든 옵션이 자동으로 선택됩니다. 사용자 관리는 현재 관리자만 할 수 있습니다.\n",
|
"permissionsHelp": "사용자를 관리자로 설정하거나 개별적으로 권한을 선택할 수 있습니다. \"관리자\"를 선택하면 다른 모든 옵션이 자동으로 선택됩니다. 사용자 관리는 관리자의 권한으로 유지됩니다.\n",
|
||||||
"profileSettings": "프로필 설정",
|
"profileSettings": "프로필 설정",
|
||||||
"ruleExample1": "점(.)으로 시작하는 모든 파일의 접근을 방지합니다.(예 .git, .gitignore)\n",
|
"ruleExample1": "모든 폴더에서 모든 숨김 파일(예: .git, .gitignore)에 대한 액세스를 방지합니다.\n",
|
||||||
"ruleExample2": "Caddyfile파일의 접근을 방지합니다.",
|
"ruleExample2": "범위의 루트에 있는 Caddyfile이라는 파일에 대한 액세스를 차단합니다.",
|
||||||
"rules": "룰",
|
"rules": "규칙",
|
||||||
"rulesHelp": "사용자별로 규칙을 허용/방지를 지정할 수 있습니다. 방지된 파일은 보이지 않고 사용자들은 접근할 수 없습니다. 사용자의 접근 허용 범위와 관련해 정규표현식(regex)과 경로를 지원합니다.\n",
|
"rulesHelp": "여기서 이 특정 사용자에 대한 허용 및 차단 규칙 세트를 정의할 수 있습니다. 차단된 파일은 목록에 표시되지 않으며 사용자가 액세스할 수 없습니다. 사용자의 범위에 상대적인 정규식 및 경로를 지원합니다.\n",
|
||||||
"scope": "범위",
|
"scope": "범위",
|
||||||
"settingsUpdated": "설정 수정됨!",
|
"setDateFormat": "정확한 날짜 형식 설정",
|
||||||
"shareDuration": "",
|
"settingsUpdated": "설정이 업데이트되었습니다!",
|
||||||
"shareManagement": "",
|
"shareDuration": "공유 기간",
|
||||||
"singleClick": "",
|
"shareManagement": "공유 관리",
|
||||||
|
"shareDeleted": "공유가 삭제되었습니다!",
|
||||||
|
"singleClick": "파일 및 디렉터리를 열 때 한 번 클릭 사용",
|
||||||
"themes": {
|
"themes": {
|
||||||
"dark": "",
|
"default": "시스템 기본값",
|
||||||
"light": "",
|
"dark": "어둡게",
|
||||||
"title": ""
|
"light": "밝게",
|
||||||
|
"title": "테마"
|
||||||
},
|
},
|
||||||
"user": "사용자",
|
"user": "사용자",
|
||||||
"userCommands": "명령어",
|
"userCommands": "명령어",
|
||||||
"userCommandsHelp": "사용에게 허용할 명령어를 공백으로 구분하여 입력하세요. 예:\n",
|
"userCommandsHelp": "이 사용자가 사용할 수 있는 명령어 목록 (공백으로 구분). 예:\n",
|
||||||
"userCreated": "사용자 생성됨!",
|
"userCreated": "사용자가 생성되었습니다!",
|
||||||
"userDefaults": "사용자 기본 설정",
|
"userDefaults": "사용자 기본 설정",
|
||||||
"userDeleted": "사용자 삭제됨!",
|
"userDeleted": "사용자가 삭제되었습니다!",
|
||||||
"userManagement": "사용자 관리",
|
"userManagement": "사용자 관리",
|
||||||
"userUpdated": "사용자 수정됨!",
|
"userUpdated": "사용자가 업데이트되었습니다!",
|
||||||
"username": "사용자 이름",
|
"username": "사용자 이름",
|
||||||
"users": "사용자"
|
"users": "사용자"
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"help": "도움말",
|
"help": "도움말",
|
||||||
"hugoNew": "Hugo New",
|
"hugoNew": "Hugo 새로 만들기",
|
||||||
"login": "로그인",
|
"login": "로그인",
|
||||||
"logout": "로그아웃",
|
"logout": "로그아웃",
|
||||||
"myFiles": "내 파일",
|
"myFiles": "내 파일",
|
||||||
"newFile": "새로운 파일",
|
"newFile": "새 파일",
|
||||||
"newFolder": "새로운 폴더",
|
"newFolder": "새 폴더",
|
||||||
"preview": "미리보기",
|
"preview": "미리보기",
|
||||||
"settings": "설정",
|
"settings": "설정",
|
||||||
"signup": "가입하기",
|
"signup": "가입",
|
||||||
"siteSettings": "사이트 설정"
|
"siteSettings": "사이트 설정"
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
@@ -227,9 +257,9 @@
|
|||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"days": "일",
|
"days": "일",
|
||||||
"hours": "시",
|
"hours": "시간",
|
||||||
"minutes": "분",
|
"minutes": "분",
|
||||||
"seconds": "초",
|
"seconds": "초",
|
||||||
"unit": "Time Unit"
|
"unit": "시간 단위"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,133 +3,153 @@
|
|||||||
"cancel": "Anuluj",
|
"cancel": "Anuluj",
|
||||||
"clear": "Wyczyść",
|
"clear": "Wyczyść",
|
||||||
"close": "Zamknij",
|
"close": "Zamknij",
|
||||||
|
"continue": "Kontynuuj",
|
||||||
"copy": "Kopiuj",
|
"copy": "Kopiuj",
|
||||||
"copyFile": "Kopiuj plik",
|
"copyFile": "Kopiuj plik",
|
||||||
"copyToClipboard": "kopiuj do schowka",
|
"copyToClipboard": "Kopiuj do schowka",
|
||||||
|
"copyDownloadLinkToClipboard": "Kopiuj link pobierania do schowka",
|
||||||
"create": "Utwórz",
|
"create": "Utwórz",
|
||||||
"delete": "Usuń",
|
"delete": "Usuń",
|
||||||
"download": "Pobierz",
|
"download": "Pobierz",
|
||||||
"hideDotfiles": "",
|
"file": "Plik",
|
||||||
"info": "Informacja",
|
"folder": "Folder",
|
||||||
"more": "Więce",
|
"fullScreen": "Przełącz tryb pełnoekranowy",
|
||||||
|
"hideDotfiles": "Ukryj pliki poprzedzone kropką",
|
||||||
|
"info": "Informacje",
|
||||||
|
"more": "Więcej",
|
||||||
"move": "Przenieś",
|
"move": "Przenieś",
|
||||||
"moveFile": "Przenieś plik",
|
"moveFile": "Przenieś plik",
|
||||||
"new": "Nowy",
|
"new": "Nowy",
|
||||||
"next": "Następny",
|
"next": "Następny",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"permalink": "Uzyskaj link bezpośredni (permalink)",
|
"permalink": "Uzyskaj stały link",
|
||||||
"previous": "Poprzedni",
|
"previous": "Poprzedni",
|
||||||
|
"preview": "Podgląd",
|
||||||
"publish": "Opublikuj",
|
"publish": "Opublikuj",
|
||||||
"rename": "Zmień nazwę",
|
"rename": "Zmień nazwę",
|
||||||
"replace": "Zamień",
|
"replace": "Zamień",
|
||||||
"reportIssue": "Zgłoś problem",
|
"reportIssue": "Zgłoś problem",
|
||||||
"save": "Zapisz",
|
"save": "Zapisz",
|
||||||
"schedule": "Grafik",
|
"schedule": "Harmonogram",
|
||||||
"search": "Szukaj",
|
"search": "Szukaj",
|
||||||
"select": "Wybierz",
|
"select": "Zaznacz",
|
||||||
"selectMultiple": "Zaznacz wiele",
|
"selectMultiple": "Zaznacz wiele",
|
||||||
"share": "Udostępnij",
|
"share": "Udostępnij",
|
||||||
"shell": "Pokaż/ukryj powłokę",
|
"shell": "Przełącz powłokę",
|
||||||
|
"submit": "Prześlij",
|
||||||
"switchView": "Zmień widok",
|
"switchView": "Zmień widok",
|
||||||
"toggleSidebar": "Pokaż/ukryj panel boczny",
|
"toggleSidebar": "Przełącz pasek boczny",
|
||||||
"update": "Aktualizuj",
|
"update": "Aktualizuj",
|
||||||
"upload": "Wgraj"
|
"upload": "Wyślij",
|
||||||
|
"openFile": "Otwórz plik",
|
||||||
|
"discardChanges": "Odrzuć"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Pobierz plik",
|
"downloadFile": "Pobierz plik",
|
||||||
"downloadFolder": "Pobierz folder",
|
"downloadFolder": "Pobierz folder",
|
||||||
"downloadSelected": "Pobierz zaznaczone"
|
"downloadSelected": "Pobierz zaznaczone"
|
||||||
},
|
},
|
||||||
|
"upload": {
|
||||||
|
"abortUpload": "Czy na pewno chcesz przerwać?"
|
||||||
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "Nie posiadasz uprawnień potrzebnych, by uzyskać do tego dostęp.",
|
"forbidden": "Nie masz zezwolenia na dostęp do tego.",
|
||||||
"internal": "Pojawił się poważny problem.",
|
"internal": "Pojawił się poważny problem.",
|
||||||
"notFound": "Ten adres nie jest poprawny."
|
"notFound": "Ta lokalizacja jest nieosiągalna.",
|
||||||
|
"connection": "Serwer jest nieosiągalny."
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"body": "Body",
|
"body": "Zawartość",
|
||||||
"closePreview": "Zamknij poprzednie",
|
"closePreview": "Zamknij podgląd",
|
||||||
"files": "Pliki",
|
"files": "Pliki",
|
||||||
"folders": "Foldery",
|
"folders": "Foldery",
|
||||||
"home": "Katalog domowy",
|
"home": "Główny",
|
||||||
"lastModified": "Ostatnio modyfikowane",
|
"lastModified": "Ostatnio zmodyfikowano",
|
||||||
"loading": "Ładowanie...",
|
"loading": "Ładowanie...",
|
||||||
"lonely": "Smutno gdy tak pusto...",
|
"lonely": "Smutno, gdy tak pusto...",
|
||||||
"metadata": "Metadane",
|
"metadata": "Metadane",
|
||||||
"multipleSelectionEnabled": "Zaznaczenie wielu włączone",
|
"multipleSelectionEnabled": "Włączono zaznaczenie wielokrotne",
|
||||||
"name": "Nazwa",
|
"name": "Nazwa",
|
||||||
"size": "Rozmiar",
|
"size": "Rozmiar",
|
||||||
"sortByLastModified": "Sortuj wg. daty modyfikacji",
|
"sortByLastModified": "Sortuj wg ostatniej modyfikacji",
|
||||||
"sortByName": "Sortuj wg. nazwy",
|
"sortByName": "Sortuj wg nazwy",
|
||||||
"sortBySize": "Sortuj wg. rozmiaru"
|
"sortBySize": "Sortuj wg rozmiaru",
|
||||||
|
"noPreview": "Podgląd tego pliku jest niedostępny."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "wybierz plik lub foler",
|
"click": "zaznacz plik lub folder",
|
||||||
"ctrl": {
|
"ctrl": {
|
||||||
"click": "wybierz wiele plików lub folderów",
|
"click": "zaznacz wiele plików lub folderów",
|
||||||
"f": "otwórz wyszukiwarkę",
|
"f": "otwórz wyszukiwarkę",
|
||||||
"s": "pobierz aktywny plik lub folder"
|
"s": "pobierz aktywny plik lub folder"
|
||||||
},
|
},
|
||||||
"del": "usuń zaznaczone",
|
"del": "usuń zaznaczone elementy",
|
||||||
"doubleClick": "otwórz plik lub folder",
|
"doubleClick": "otwórz plik lub folder",
|
||||||
"esc": "wyczyść zaznaczenie i/lub zamknij okno z powiadomieniem",
|
"esc": "wyczyść zaznaczenie i/lub zamknij monit",
|
||||||
"f1": "ta informacja",
|
"f1": "te informacje",
|
||||||
"f2": "zmień nazwę pliku",
|
"f2": "zmień nazwę pliku",
|
||||||
"help": "Pomoc"
|
"help": "Pomoc"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"createAnAccount": "Utwórz konto",
|
"createAnAccount": "Utwórz konto",
|
||||||
"loginInstead": "Takie konto już istnieje",
|
"loginInstead": "Mam już konto",
|
||||||
"password": "Hasło",
|
"password": "Hasło",
|
||||||
"passwordConfirm": "Potwierdzenie hasła",
|
"passwordConfirm": "Potwierdzenie hasła",
|
||||||
"passwordsDontMatch": "Hasła różnią się",
|
"passwordsDontMatch": "Hasła nie pasują do siebie",
|
||||||
"signup": "Rejestracja",
|
"signup": "Rejestracja",
|
||||||
"submit": "Logowanie",
|
"submit": "Zaloguj",
|
||||||
"username": "Nazwa użytkownika",
|
"username": "Nazwa użytkownika",
|
||||||
"usernameTaken": "Nazwa użytkownika już zajęta",
|
"usernameTaken": "Ta nazwa użytkownika jest zajęta",
|
||||||
"wrongCredentials": "Błędne dane logowania"
|
"wrongCredentials": "Błędne dane logowania"
|
||||||
},
|
},
|
||||||
"permanent": "Permanentny",
|
"permanent": "Permanentny",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
"copy": "Kopiuj",
|
"copy": "Kopiuj",
|
||||||
"copyMessage": "Wybierz lokalizację do której mają być skopiowane wybrane pliki",
|
"copyMessage": "Wybierz lokalizację docelową:",
|
||||||
"currentlyNavigating": "Obecnie przeglądasz:",
|
"currentlyNavigating": "Aktualnie poruszasz się po:",
|
||||||
"deleteMessageMultiple": "Czy jesteś pewien że chcesz usunąć {count} plik(ów)?",
|
"deleteMessageMultiple": "Czy na pewno chcesz usunąć pliki: {count}?",
|
||||||
"deleteMessageSingle": "Czy jesteś pewien, że chcesz usunąć ten plik/folder?",
|
"deleteMessageSingle": "Czy na pewno chcesz usunąć ten plik/folder?",
|
||||||
|
"deleteMessageShare": "Czy na pewno chcesz usunąć ten udział ({path})?",
|
||||||
|
"deleteUser": "Czy na pewno chcesz usunąć tego użytkownika?",
|
||||||
"deleteTitle": "Usuń pliki",
|
"deleteTitle": "Usuń pliki",
|
||||||
"displayName": "Wyświetlana Nazwa:",
|
"displayName": "Wyświetlana nazwa:",
|
||||||
"download": "Pobierz pliki",
|
"download": "Pobierz pliki",
|
||||||
"downloadMessage": "Wybierz format, jaki chesz pobrać.",
|
"downloadMessage": "Wybierz format, w którym chcesz pobrać.",
|
||||||
"error": "Pojawił się nieznany błąd",
|
"error": "Pojawił się jakiś błąd",
|
||||||
"fileInfo": "Informacje o pliku",
|
"fileInfo": "Informacje o pliku",
|
||||||
"filesSelected": "{count} plików zostało zaznaczonych.",
|
"filesSelected": "Zaznaczone pliki: {count}",
|
||||||
"lastModified": "Osatnio Zmodyfikowane",
|
"lastModified": "Ostatnio zmodyfikowano",
|
||||||
"move": "Przenieś",
|
"move": "Przenieś",
|
||||||
"moveMessage": "Wybierz nową lokalizację dla swoich plik(ów)/folder(ów):",
|
"moveMessage": "Wybierz nową lokalizację dla swoich plików/folderów:",
|
||||||
"newArchetype": "Utwórz nowy wpis na bazie wybranego wzorca. Twój plik będzie utworzony w wybranym folderze.",
|
"newArchetype": "Utwórz nowy wpis na bazie wybranego wzorca. Twój plik będzie utworzony w wybranym folderze.",
|
||||||
"newDir": "Nowy folder",
|
"newDir": "Nowy folder",
|
||||||
"newDirMessage": "Podaj nazwę tworzonego folderu.",
|
"newDirMessage": "Nazwij nowy folder.",
|
||||||
"newFile": "Nowy plik",
|
"newFile": "Nowy plik",
|
||||||
"newFileMessage": "Podaj nazwętworzonego pliku.",
|
"newFileMessage": "Nazwij nowy plik.",
|
||||||
"numberDirs": "Ilość katalogów",
|
"numberDirs": "Liczba folderów",
|
||||||
"numberFiles": "Ilość plików",
|
"numberFiles": "Liczba plików",
|
||||||
"rename": "Zmień nazwę",
|
"rename": "Zmień nazwę",
|
||||||
"renameMessage": "Podaj nową nazwę dla",
|
"renameMessage": "Podaj nową nazwę dla",
|
||||||
"replace": "Zamień",
|
"replace": "Zamień",
|
||||||
"replaceMessage": "Jednen z plików który próbujesz wrzucić próbje nadpisać plik o tej samej nazwie. Czy chcesz nadpisać poprzedni plik?\n",
|
"replaceMessage": "Jeden z przesyłanych plików chce nadpisać istniejący plik o tej samej nazwie. Chcesz pominąć ten plik i kontynuować przesyłanie reszty plików, czy nadpisać istniejący plik?\n",
|
||||||
"schedule": "Grafi",
|
"schedule": "Grafik",
|
||||||
"scheduleMessage": "Wybierz datę i czas dla publikacji tego wpisu.",
|
"scheduleMessage": "Wybierz datę i czas dla publikacji tego wpisu.",
|
||||||
"show": "Pokaż",
|
"show": "Pokaż",
|
||||||
"size": "Rozmiar",
|
"size": "Rozmiar",
|
||||||
"upload": "Prześlij",
|
"upload": "Wyślij",
|
||||||
"uploadMessage": "Proszę wybrać metodę przesyłania"
|
"uploadFiles": "Wysyłam pliki: {files}...",
|
||||||
|
"uploadMessage": "Wybierz opcję przesyłania.",
|
||||||
|
"optionalPassword": "Opcjonalne hasło",
|
||||||
|
"resolution": "Rozdzielczość",
|
||||||
|
"discardEditorChanges": "Czy na pewno chcesz odrzucić wprowadzone zmiany?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "Zdjęcia",
|
"images": "Obrazy",
|
||||||
"music": "Muzyka",
|
"music": "Muzyka",
|
||||||
"pdf": "PDF",
|
"pdf": "PDF",
|
||||||
"pressToSearch": "Wciśnij enter, aby wyszukać...",
|
"pressToSearch": "Naciśnij Enter, aby wyszukać...",
|
||||||
"search": "Szukaj...",
|
"search": "Szukaj...",
|
||||||
"typeToSearch": "Zacznij pisać, aby wyszukać...",
|
"typeToSearch": "Typ plików do wyszukania...",
|
||||||
"types": "Typy",
|
"types": "Typy",
|
||||||
"video": "Wideo"
|
"video": "Wideo"
|
||||||
},
|
},
|
||||||
@@ -137,70 +157,80 @@
|
|||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrator",
|
"administrator": "Administrator",
|
||||||
"allowCommands": "Wykonaj polecenie",
|
"allowCommands": "Wykonaj polecenie",
|
||||||
"allowEdit": "Edycja, zmiana nazwy i usuniecie plików lub folderów",
|
"allowEdit": "Edycja, zmiana nazwy i usuniecie plików lub folderów",
|
||||||
"allowNew": "Tworzenie nowych plików lub folderów",
|
"allowNew": "Tworzenie nowych plików lub folderów",
|
||||||
"allowPublish": "Tworzenie nowych wpisów i stron",
|
"allowPublish": "Tworzenie nowych wpisów i stron",
|
||||||
"allowSignup": "Zezwól na rejestrację użytkowników",
|
"allowSignup": "Pozwól użytkownikom na rejestrację",
|
||||||
"avoidChanges": "(pozostaw puste aby nie zosatało zmienione)",
|
"avoidChanges": "(pozostaw puste, aby uniknąć zmian)",
|
||||||
"branding": "Branding",
|
"branding": "Personalizacja",
|
||||||
"brandingDirectoryPath": "Folder brandingowy",
|
"brandingDirectoryPath": "Ścieżka do folderu personalizacji",
|
||||||
"brandingHelp": "Możesz dostosować wygląd i doznania użytkownika swojej instancji File Browser poprzez zmianę jej nazwy, zmianę logo, dodanie własnych stylów, a nawet wyłączyć linki zewnętrzne do GitHuba.\nW celu pozyskania większej ilości informacji nt. osobistego brandingu, zapoznaj się z {0}.",
|
"brandingHelp": "Możesz zmodyfikować wygląd instancji File Browser poprzez zmianę nazwy, logo, dodanie własnych stylów graficznych, a nawet usunięcia linków do serwisu GitHub. Więcej informacji o modyfikacji wyglądu znajdziesz w {0}.",
|
||||||
"changePassword": "Zmień Hasło",
|
"changePassword": "Zmień hasło",
|
||||||
"commandRunner": "Narzędzie do wykonywania poleceń",
|
"commandRunner": "Narzędzie do wykonywania poleceń",
|
||||||
"commandRunnerHelp": "Tu możesz ustawić komendy, które będą wykonywane przy danych zdarzeniach. Musisz wpisywać po jednej na linjkę. Zmienne środowiskowe {0} i {1} będą dostępne, gdzie {0} jest względne wobec {1}. Więcej informacji o tej funkcji i dostępnych zmiennych środowiskowych znajdziesz tutaj: {2}.",
|
"commandRunnerHelp": "Tu możesz ustawić polecenia, które będą wykonywane przy danych zdarzeniach. Musisz wpisywać po jednym na wiersz. Zmienne środowiskowe {0} i {1} będą dostępne, gdzie {0} jest względne wobec {1}. Więcej informacji o tej funkcji i dostępnych zmiennych środowiskowych znajdziesz w {2}.",
|
||||||
"commandsUpdated": "Polecenie zaktualizowane!",
|
"commandsUpdated": "Polecenie zaktualizowane!",
|
||||||
"createUserDir": "Automatycznie utwórz katalog domowy użytkownika podczas dodania nowego użytkownika",
|
"createUserDir": "Automatycznie twórz katalog domowy podczas dodawania użytkownika",
|
||||||
"customStylesheet": "Własny arkusz stylów",
|
"tusUploads": "Przesyłanie we fragmentach",
|
||||||
"defaultUserDescription": "Oto domyślne ustawienia dla nowych użytkowników.",
|
"tusUploadsHelp": "File Browser wspiera przesyłanie plików we fragmentach, co pozwala na proces przesyłania, który jest wydajny, pewny i możliwy do wznowienia nawet w sieciach o wątpliwej stabilności przesyłu danych.",
|
||||||
"disableExternalLinks": "Wyłącz linki zewnętrzne (z wyjątkiem dokumentacji)",
|
"tusUploadsChunkSize": "Oznacza maksymalny rozmiar przesyłanych plików (dla mniejszych plików użyte zostanie przesyłanie bezpośrednie). Możesz ustawić tę wartość zarówno zapisaną samymi cyframi w bajtach, jak i podać ją w formie skróconej, np. poprzez 10MB, 1GB itp.",
|
||||||
"disableUsedDiskPercentage": "Disable used disk percentage graph",
|
"tusUploadsRetryCount": "Liczba prób ponowienia transferu w przypadku wystapienia problemu z przesyłem.",
|
||||||
"documentation": "dokumentacja",
|
"userHomeBasePath": "Ścieżka podstawowa dla katalogów domowych użytkowników",
|
||||||
|
"userScopeGenerationPlaceholder": "Zakres zostanie wygenerowany automatycznie",
|
||||||
|
"createUserHomeDirectory": "Utwórz katalog domowy użytkownika",
|
||||||
|
"customStylesheet": "Własny arkusz stylu",
|
||||||
|
"defaultUserDescription": "To są domyślne ustawienia dla nowych użytkowników.",
|
||||||
|
"disableExternalLinks": "Wyłącz linki zewnętrzne (z wyjątkiem dokumentacji)",
|
||||||
|
"disableUsedDiskPercentage": "Wyłącz wykres procentowy używanego dysku",
|
||||||
|
"documentation": "dokumentacji",
|
||||||
"examples": "Przykłady",
|
"examples": "Przykłady",
|
||||||
"executeOnShell": "Wykonaj w powłoce",
|
"executeOnShell": "Wykonaj w powłoce",
|
||||||
"executeOnShellDescription": "Domyślnie File Browser wykonuje polecenia wywołując ich pliki binarne bezpośrednio. Jesli preferujesz wykonywanie ich w powłoce (jak np. Bash czy PowerShell), możesz zdefiniować to tutaj wraz z wymaganymi flagami i argumentami. Jeśli to ustawienie jest aktywne, polecenie które wykonarz zostanie dodane jako argument. Stosuje się to zarówno do poleceń użytkownika jak i zaczepów zdarzeń.",
|
"executeOnShellDescription": "Domyślnie File Browser wykonuje polecenia poprzez bezpośrednie uruchomienie odpowiednich plików binarnych. Jeśli chcesz uruchamiać polecenia z poziomu powłoki (np. Bash lub PowerShell), możesz zdefiniować je tutaj, z wykorzystaniem odpowiednich argumentów i flag. Gdy się na to zdecydujesz, wykonywane polecenie będzie załączone jako argument. Tyczy się to tak poleceń użytkownika, jak i zaczepów zdarzeń.",
|
||||||
"globalRules": "To jest globalne zestawienie reguł zezwalających i zabraniających. Stosują się one do każdego użytkownika. Możesz zdefiniować indywidualne zasady w ustawieniach każdego użytkownika, by zignorować te reguły.",
|
"globalRules": "Globalny zestaw reguł zezwalających i zakazujących. Dotyczą każdego użytkownika. Aby zastąpić ustawienia globalne, możesz zdefiniować określone reguły indywidualnie dla każdego użytkownika.",
|
||||||
"globalSettings": "Ustawienia Globalne",
|
"globalSettings": "Ustawienia globalne",
|
||||||
"hideDotfiles": "Ukryj ukryte pliki",
|
"hideDotfiles": "Ukryj pliki poprzedzone kropką",
|
||||||
"insertPath": "Wstaw ścieżkę",
|
"insertPath": "Wstaw ścieżkę",
|
||||||
"insertRegex": "Wstaw wyrażenie regularne",
|
"insertRegex": "Wstaw wyrażenie regularne",
|
||||||
"instanceName": "Nazwa instancji",
|
"instanceName": "Nazwa instancji",
|
||||||
"language": "Język",
|
"language": "Język",
|
||||||
"lockPassword": "Zablokuj użytkownikowi możliwość zmiany hasła",
|
"lockPassword": "Zablokuj użytkownikowi możliwość zmiany hasła",
|
||||||
"newPassword": "Twoje nowe hasło",
|
"newPassword": "Nowe hasło",
|
||||||
"newPasswordConfirm": "Potwierdź swoje hasło",
|
"newPasswordConfirm": "Potwierdź nowe hasło",
|
||||||
"newUser": "Nowy Użytkownik",
|
"newUser": "Nowy użytkownik",
|
||||||
"password": "Hasło",
|
"password": "Hasło",
|
||||||
"passwordUpdated": "Hasło zostało zapisane!",
|
"passwordUpdated": "Hasło zostało zaktualizowane!",
|
||||||
"path": "Ścieżka",
|
"path": "Ścieżka",
|
||||||
"perm": {
|
"perm": {
|
||||||
"create": "Tworzenie plików i katalogów",
|
"create": "Tworzenie plików i folderów",
|
||||||
"delete": "Usuwanie plików i katalogów",
|
"delete": "Usuwanie plików i folderów",
|
||||||
"download": "Pobieranie",
|
"download": "Pobieranie",
|
||||||
"execute": "Wykonywanie poleceń",
|
"execute": "Wykonywanie poleceń",
|
||||||
"modify": "Edycja plików",
|
"modify": "Edytowanie plików",
|
||||||
"rename": "Zmiana nazw lub przenoszenie plików i katalogów",
|
"rename": "Zmienianie nazwy lub przenoszenie plików i katalogów",
|
||||||
"share": "Udostępnianie plików"
|
"share": "Udostępnianie plików"
|
||||||
},
|
},
|
||||||
"permissions": "Uprawnienia",
|
"permissions": "Uprawnienia",
|
||||||
"permissionsHelp": "Możesz uczynić użytkownika administratorem, lub wybrać uprawnienia indywidualnie. Jeśli zaznaczysz opcję \"Administrator\", wszystkie pozostałe opcje zostaną automatycznie zaznaczone. Zarządzanie użytkownikami pozostaje przywilejem administratora.\n",
|
"permissionsHelp": "Możesz ustawić użytkownika jako administratora lub wybrać uprawnienia indywidualnie. Jeśli wybierzesz „Administrator”, wszystkie pozostałe opcje zostaną automatycznie zaznaczone. Zarządzanie użytkownikami pozostaje przywilejem administratora.\n",
|
||||||
"profileSettings": "Twój profil",
|
"profileSettings": "Twój profil",
|
||||||
"ruleExample1": "uniemożliwia dostęp do któregokolwiek z ukrytych plików (takich jak .git, .gitignore) w każdym folderze.\n",
|
"ruleExample1": "uniemożliwia dostęp do plików poprzedzonych kropką (takich jak .git, .gitignore) we wszystkich folderach.\n",
|
||||||
"ruleExample2": "blokuje dostęp do pliku Caddyfile w głównym katalogu zakresu.",
|
"ruleExample2": "blokuje dostęp do pliku o nazwie Caddyfile w katalogu głównym zakresu.",
|
||||||
"rules": "Uprawnienia",
|
"rules": "Uprawnienia",
|
||||||
"rulesHelp": "Tu możesz zdefiniować zestawienie reguł zezwalających i zabraniających dla tego konkretnego użytkownika. Zablokowane pliki nie będą widoczne na listach i nie będą dostępne dla użytkownika. Wspierane są wyrażenia regularne i ścieżki względne wobec zakresu użytkownika.\n",
|
"rulesHelp": "Tutaj możesz zdefiniować zestaw reguł zezwalających i zakazujących dla tego użytkownika. Zablokowane pliki nie pojawią się na listach i nie będą dostępne dla użytkownika. Obsługujemy wyrażenia regularne i ścieżki względne w stosunku do zakresu użytkownika.\n",
|
||||||
"scope": "Zakres",
|
"scope": "Zakres",
|
||||||
"settingsUpdated": "Uprawnienia Zapisane!",
|
"setDateFormat": "Ustaw dokładny format daty",
|
||||||
|
"settingsUpdated": "Ustawienia zaktualizowane!",
|
||||||
"shareDuration": "Okres udostępniania",
|
"shareDuration": "Okres udostępniania",
|
||||||
"shareManagement": "Zarządzanie udostępnianiem",
|
"shareManagement": "Zarządzanie udostępnianiem",
|
||||||
"singleClick": "Pojedyncze kliknięcie",
|
"shareDeleted": "Udostępnienie usunięte!",
|
||||||
|
"singleClick": "Używaj pojedynczych kliknięć, aby otwierać pliki i foldery",
|
||||||
"themes": {
|
"themes": {
|
||||||
"dark": "ciemny",
|
"default": "Domyślny systemowy",
|
||||||
"light": "jasny",
|
"dark": "Ciemny",
|
||||||
"title": "Motywy"
|
"light": "Jasny",
|
||||||
|
"title": "Motyw"
|
||||||
},
|
},
|
||||||
"user": "Użytkownik",
|
"user": "Użytkownik",
|
||||||
"userCommands": "Polecenia",
|
"userCommands": "Polecenia",
|
||||||
"userCommandsHelp": "Lista oddzielonych spacjami poleceń dostępnych dla tego użytkownika. Przykład:\n",
|
"userCommandsHelp": "Oddzielona spacjami lista z dostępnymi poleceniami dla tego użytkownika. Przykład:\n",
|
||||||
"userCreated": "Użytkownik zapisany!",
|
"userCreated": "Użytkownik zapisany!",
|
||||||
"userDefaults": "Domyślne ustawienia użytkownika",
|
"userDefaults": "Domyślne ustawienia użytkownika",
|
||||||
"userDeleted": "Użytkownik usunięty!",
|
"userDeleted": "Użytkownik usunięty!",
|
||||||
@@ -211,8 +241,8 @@
|
|||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"help": "Pomoc",
|
"help": "Pomoc",
|
||||||
"hugoNew": "Hugo New",
|
"hugoNew": "Nowy Hugo",
|
||||||
"login": "Login",
|
"login": "Zaloguj",
|
||||||
"logout": "Wyloguj",
|
"logout": "Wyloguj",
|
||||||
"myFiles": "Moje pliki",
|
"myFiles": "Moje pliki",
|
||||||
"newFile": "Nowy plik",
|
"newFile": "Nowy plik",
|
||||||
@@ -220,10 +250,10 @@
|
|||||||
"preview": "Podgląd",
|
"preview": "Podgląd",
|
||||||
"settings": "Ustawienia",
|
"settings": "Ustawienia",
|
||||||
"signup": "Rejestracja",
|
"signup": "Rejestracja",
|
||||||
"siteSettings": "Ustawienia Strony"
|
"siteSettings": "Ustawienia strony"
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
"linkCopied": "Link Skopiowany!"
|
"linkCopied": "Link skopiowany!"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"days": "Dni",
|
"days": "Dni",
|
||||||
|
|||||||
@@ -38,13 +38,20 @@
|
|||||||
"toggleSidebar": "Alternar barra lateral",
|
"toggleSidebar": "Alternar barra lateral",
|
||||||
"update": "Atualizar",
|
"update": "Atualizar",
|
||||||
"upload": "Enviar",
|
"upload": "Enviar",
|
||||||
"openFile": "Abrir"
|
"openFile": "Abrir",
|
||||||
|
"copyDownloadLinkToClipboard": "Copiar link de download para a área de transferência",
|
||||||
|
"fullScreen": "Alternar tela cheia",
|
||||||
|
"preview": "Pré-visualizar",
|
||||||
|
"discardChanges": "Descartar"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Baixar arquivo",
|
"downloadFile": "Baixar arquivo",
|
||||||
"downloadFolder": "Baixar pasta",
|
"downloadFolder": "Baixar pasta",
|
||||||
"downloadSelected": "Baixar selecionado"
|
"downloadSelected": "Baixar selecionado"
|
||||||
},
|
},
|
||||||
|
"upload": {
|
||||||
|
"abortUpload": "Tem certeza de que deseja abortar o upload?"
|
||||||
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "Você não tem permissões para acessar isto.",
|
"forbidden": "Você não tem permissões para acessar isto.",
|
||||||
"internal": "Ops! Algum erro ocorreu.",
|
"internal": "Ops! Algum erro ocorreu.",
|
||||||
@@ -58,8 +65,8 @@
|
|||||||
"folders": "Pastas",
|
"folders": "Pastas",
|
||||||
"home": "Início",
|
"home": "Início",
|
||||||
"lastModified": "Última modificação",
|
"lastModified": "Última modificação",
|
||||||
"loading": "Carregando. Aguarde, por favor.",
|
"loading": "Carregando...",
|
||||||
"lonely": "Não existe nada aqui.",
|
"lonely": "Não há nada aqui...",
|
||||||
"metadata": "Metadados",
|
"metadata": "Metadados",
|
||||||
"multipleSelectionEnabled": "Seleção múltipla ativada",
|
"multipleSelectionEnabled": "Seleção múltipla ativada",
|
||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
@@ -73,12 +80,12 @@
|
|||||||
"click": "selecionar pasta ou arquivo",
|
"click": "selecionar pasta ou arquivo",
|
||||||
"ctrl": {
|
"ctrl": {
|
||||||
"click": "selecionar várias pastas e arquivos",
|
"click": "selecionar várias pastas e arquivos",
|
||||||
"f": "pesquisar",
|
"f": "abrir pesquisa",
|
||||||
"s": "salvar um arquivo ou baixar a pasta que você está"
|
"s": "salvar um arquivo ou baixar a pasta que você está"
|
||||||
},
|
},
|
||||||
"del": "apagar os arquivos selecionados",
|
"del": "apagar os arquivos selecionados",
|
||||||
"doubleClick": "abrir pasta ou arquivo",
|
"doubleClick": "abrir pasta ou arquivo",
|
||||||
"esc": "limpar seleção e/ou fechar menu",
|
"esc": "limpar seleção e/ou fechar prompt",
|
||||||
"f1": "esta informação",
|
"f1": "esta informação",
|
||||||
"f2": "renomear arquivo",
|
"f2": "renomear arquivo",
|
||||||
"help": "Ajuda"
|
"help": "Ajuda"
|
||||||
@@ -123,7 +130,7 @@
|
|||||||
"rename": "Renomear",
|
"rename": "Renomear",
|
||||||
"renameMessage": "Insira um novo nome para",
|
"renameMessage": "Insira um novo nome para",
|
||||||
"replace": "Substituir",
|
"replace": "Substituir",
|
||||||
"replaceMessage": "Já existe um arquivo com nome igual a um dos que está tentando enviar. Deseja substituir?\n",
|
"replaceMessage": "Um dos arquivos que você está tentando enviar possui um nome conflitante. Deseja pular este arquivo e continuar o envio ou substituir o existente?\n",
|
||||||
"schedule": "Agendar",
|
"schedule": "Agendar",
|
||||||
"scheduleMessage": "Escolha uma data para agendar a publicação deste post.",
|
"scheduleMessage": "Escolha uma data para agendar a publicação deste post.",
|
||||||
"show": "Mostrar",
|
"show": "Mostrar",
|
||||||
@@ -131,7 +138,10 @@
|
|||||||
"upload": "Enviar",
|
"upload": "Enviar",
|
||||||
"uploadFiles": "Enviando {files} arquivos...",
|
"uploadFiles": "Enviando {files} arquivos...",
|
||||||
"uploadMessage": "Selecione uma opção para enviar.",
|
"uploadMessage": "Selecione uma opção para enviar.",
|
||||||
"optionalPassword": "Senha opcional"
|
"optionalPassword": "Senha opcional",
|
||||||
|
"deleteUser": "Tem certeza de que deseja apagar este usuário?",
|
||||||
|
"resolution": "Resolução",
|
||||||
|
"discardEditorChanges": "Tem certeza de que deseja descartar as alterações feitas?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "Imagens",
|
"images": "Imagens",
|
||||||
@@ -159,7 +169,7 @@
|
|||||||
"commandRunner": "Execução de comandos",
|
"commandRunner": "Execução de comandos",
|
||||||
"commandRunnerHelp": "Aqui você pode definir comandos que serão executados nos eventos descritos. Escreva um por linha. As variáveis de ambiente {0} e {1} estão disponíveis, sendo {0} relativo a {1}. Para mais informações sobre esta função e as variáveis de ambiente disponíveis, leia a {2}.",
|
"commandRunnerHelp": "Aqui você pode definir comandos que serão executados nos eventos descritos. Escreva um por linha. As variáveis de ambiente {0} e {1} estão disponíveis, sendo {0} relativo a {1}. Para mais informações sobre esta função e as variáveis de ambiente disponíveis, leia a {2}.",
|
||||||
"commandsUpdated": "Comandos atualizados!",
|
"commandsUpdated": "Comandos atualizados!",
|
||||||
"createUserDir": "Criar diretório Home para novos usuários",
|
"createUserDir": "Criar diretório Home do usuário automaticamente ao adicionar novo usuário",
|
||||||
"userHomeBasePath": "Caminho base para diretórios de usuários",
|
"userHomeBasePath": "Caminho base para diretórios de usuários",
|
||||||
"userScopeGenerationPlaceholder": "O escopo será gerado automaticamente",
|
"userScopeGenerationPlaceholder": "O escopo será gerado automaticamente",
|
||||||
"createUserHomeDirectory": "Criar diretório Home de usuário",
|
"createUserHomeDirectory": "Criar diretório Home de usuário",
|
||||||
@@ -184,7 +194,7 @@
|
|||||||
"newUser": "Novo usuário",
|
"newUser": "Novo usuário",
|
||||||
"password": "Senha",
|
"password": "Senha",
|
||||||
"passwordUpdated": "Senha atualizada!",
|
"passwordUpdated": "Senha atualizada!",
|
||||||
"path": "",
|
"path": "Caminho",
|
||||||
"perm": {
|
"perm": {
|
||||||
"create": "Criar arquivos e diretórios",
|
"create": "Criar arquivos e diretórios",
|
||||||
"delete": "Apagar arquivos e diretórios",
|
"delete": "Apagar arquivos e diretórios",
|
||||||
@@ -209,6 +219,7 @@
|
|||||||
"shareDeleted": "Compartilhamento apagado!",
|
"shareDeleted": "Compartilhamento apagado!",
|
||||||
"singleClick": "Usar clique único para abrir arquivos e diretórios",
|
"singleClick": "Usar clique único para abrir arquivos e diretórios",
|
||||||
"themes": {
|
"themes": {
|
||||||
|
"default": "Padrão do sistema",
|
||||||
"dark": "Escuro",
|
"dark": "Escuro",
|
||||||
"light": "Claro",
|
"light": "Claro",
|
||||||
"title": "Tema"
|
"title": "Tema"
|
||||||
@@ -229,7 +240,7 @@
|
|||||||
"hugoNew": "Hugo New",
|
"hugoNew": "Hugo New",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
"logout": "Sair",
|
"logout": "Sair",
|
||||||
"myFiles": "Arquivos",
|
"myFiles": "Meus arquivos",
|
||||||
"newFile": "Novo arquivo",
|
"newFile": "Novo arquivo",
|
||||||
"newFolder": "Nova pasta",
|
"newFolder": "Nova pasta",
|
||||||
"preview": "Pré-visualizar",
|
"preview": "Pré-visualizar",
|
||||||
@@ -245,6 +256,6 @@
|
|||||||
"hours": "Horas",
|
"hours": "Horas",
|
||||||
"minutes": "Minutos",
|
"minutes": "Minutos",
|
||||||
"seconds": "Segundos",
|
"seconds": "Segundos",
|
||||||
"unit": "Unidades de Tempo"
|
"unit": "Unidade de tempo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,17 @@
|
|||||||
"cancel": "Отмена",
|
"cancel": "Отмена",
|
||||||
"clear": "Очистить",
|
"clear": "Очистить",
|
||||||
"close": "Закрыть",
|
"close": "Закрыть",
|
||||||
|
"continue": "Продолжить",
|
||||||
"copy": "Копировать",
|
"copy": "Копировать",
|
||||||
"copyFile": "Скопировать файл",
|
"copyFile": "Скопировать файл",
|
||||||
"copyToClipboard": "Скопировать в буфер",
|
"copyToClipboard": "Скопировать в буфер",
|
||||||
|
"copyDownloadLinkToClipboard": "Скопировать ссылку в буфер",
|
||||||
"create": "Создать",
|
"create": "Создать",
|
||||||
"delete": "Удалить",
|
"delete": "Удалить",
|
||||||
"download": "Скачать",
|
"download": "Скачать",
|
||||||
"file": "Файл",
|
"file": "Файл",
|
||||||
"folder": "Папка",
|
"folder": "Папка",
|
||||||
|
"fullScreen": " Развернуть на весь экран",
|
||||||
"hideDotfiles": "Скрыть точечные файлы",
|
"hideDotfiles": "Скрыть точечные файлы",
|
||||||
"info": "Инфо",
|
"info": "Инфо",
|
||||||
"more": "Еще",
|
"more": "Еще",
|
||||||
@@ -21,6 +24,7 @@
|
|||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"permalink": "Получить постоянную ссылку",
|
"permalink": "Получить постоянную ссылку",
|
||||||
"previous": "Назад",
|
"previous": "Назад",
|
||||||
|
"preview": "Предпросмотр",
|
||||||
"publish": "Опубликовать",
|
"publish": "Опубликовать",
|
||||||
"rename": "Переименовать",
|
"rename": "Переименовать",
|
||||||
"replace": "Перезаписать",
|
"replace": "Перезаписать",
|
||||||
@@ -37,13 +41,17 @@
|
|||||||
"toggleSidebar": "Боковая панель",
|
"toggleSidebar": "Боковая панель",
|
||||||
"update": "Обновить",
|
"update": "Обновить",
|
||||||
"upload": "Загрузить",
|
"upload": "Загрузить",
|
||||||
"openFile": "Открыть файл"
|
"openFile": "Открыть файл",
|
||||||
|
"discardChanges": "Отказаться"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Скачать файл",
|
"downloadFile": "Скачать файл",
|
||||||
"downloadFolder": "Загрузить папку",
|
"downloadFolder": "Загрузить папку",
|
||||||
"downloadSelected": "Скачать выбранное"
|
"downloadSelected": "Скачать выбранное"
|
||||||
},
|
},
|
||||||
|
"upload": {
|
||||||
|
"abortUpload": "Вы действительно, что хотите прервать операцию?"
|
||||||
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "У вас нет прав доступа к этому.",
|
"forbidden": "У вас нет прав доступа к этому.",
|
||||||
"internal": "Что-то пошло не так.",
|
"internal": "Что-то пошло не так.",
|
||||||
@@ -72,7 +80,7 @@
|
|||||||
"click": "выбрать файл или каталог",
|
"click": "выбрать файл или каталог",
|
||||||
"ctrl": {
|
"ctrl": {
|
||||||
"click": "выбрать несколько файлов или каталогов",
|
"click": "выбрать несколько файлов или каталогов",
|
||||||
"f": "открыть поиск",
|
"f": "открытые поиски",
|
||||||
"s": "скачать файл или текущий каталог"
|
"s": "скачать файл или текущий каталог"
|
||||||
},
|
},
|
||||||
"del": "удалить выбранные элементы",
|
"del": "удалить выбранные элементы",
|
||||||
@@ -102,6 +110,7 @@
|
|||||||
"deleteMessageMultiple": "Удалить эти файлы ({count})?",
|
"deleteMessageMultiple": "Удалить эти файлы ({count})?",
|
||||||
"deleteMessageSingle": "Удалить этот файл/каталог?",
|
"deleteMessageSingle": "Удалить этот файл/каталог?",
|
||||||
"deleteMessageShare": "Удалить этот общий файл/каталог ({path})?",
|
"deleteMessageShare": "Удалить этот общий файл/каталог ({path})?",
|
||||||
|
"deleteUser": "Вы действительно, хотите удалить пользователя?",
|
||||||
"deleteTitle": "Удалить файлы",
|
"deleteTitle": "Удалить файлы",
|
||||||
"displayName": "Отображаемое имя:",
|
"displayName": "Отображаемое имя:",
|
||||||
"download": "Скачать файлы",
|
"download": "Скачать файлы",
|
||||||
@@ -111,7 +120,7 @@
|
|||||||
"filesSelected": "Файлов выбрано: {count}.",
|
"filesSelected": "Файлов выбрано: {count}.",
|
||||||
"lastModified": "Последнее изменение",
|
"lastModified": "Последнее изменение",
|
||||||
"move": "Переместить",
|
"move": "Переместить",
|
||||||
"moveMessage": "Переместить в:",
|
"moveMessage": "Выберите новый домашний каталог для ваших файлов/папок:",
|
||||||
"newArchetype": "Создайте новую запись на основе архетипа. Файл будет создан в каталоге.",
|
"newArchetype": "Создайте новую запись на основе архетипа. Файл будет создан в каталоге.",
|
||||||
"newDir": "Новый каталог",
|
"newDir": "Новый каталог",
|
||||||
"newDirMessage": "Имя нового каталога.",
|
"newDirMessage": "Имя нового каталога.",
|
||||||
@@ -128,8 +137,11 @@
|
|||||||
"show": "Показать",
|
"show": "Показать",
|
||||||
"size": "Размер",
|
"size": "Размер",
|
||||||
"upload": "Загрузить",
|
"upload": "Загрузить",
|
||||||
|
"uploadFiles": "Загружаю {files} файлы...",
|
||||||
"uploadMessage": "Выберите вариант для загрузки.",
|
"uploadMessage": "Выберите вариант для загрузки.",
|
||||||
"optionalPassword": "Необязательный пароль"
|
"optionalPassword": "Необязательный пароль",
|
||||||
|
"resolution": "Разрешение",
|
||||||
|
"discardEditorChanges": "Вы действительно желаете отменить ваши правки?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "Изображения",
|
"images": "Изображения",
|
||||||
@@ -158,6 +170,13 @@
|
|||||||
"commandRunnerHelp": "Здесь вы можете установить команды, которые будут выполняться в указанных событиях. Вы должны указать по одной команде в каждой строке. Переменные среды {0} и {1} будут доступны, будучи {0} относительно {1}. Дополнительные сведения об этой функции и доступных переменных среды см. В {2}.",
|
"commandRunnerHelp": "Здесь вы можете установить команды, которые будут выполняться в указанных событиях. Вы должны указать по одной команде в каждой строке. Переменные среды {0} и {1} будут доступны, будучи {0} относительно {1}. Дополнительные сведения об этой функции и доступных переменных среды см. В {2}.",
|
||||||
"commandsUpdated": "Команды обновлены!",
|
"commandsUpdated": "Команды обновлены!",
|
||||||
"createUserDir": "Автоматическое создание домашнего каталога пользователя при добавлении нового пользователя",
|
"createUserDir": "Автоматическое создание домашнего каталога пользователя при добавлении нового пользователя",
|
||||||
|
"tusUploads": "Загруженные файлы",
|
||||||
|
"tusUploadsHelp": " File Browser поддерживает загрузку файлов по частям, что позволяет работать в сетях низкого качества.",
|
||||||
|
"tusUploadsChunkSize": "Указывает максимальный размер запроса (мелкие загрузки пойдут напрямую). Вы можете ввести простое целое число, обозначающее размер ввода в байтах, или строку, например 10MB, 1GB и т. д.",
|
||||||
|
"tusUploadsRetryCount": "Количество повторных попыток, которые необходимо выполнить, если фрагмент не удалось загрузить.",
|
||||||
|
"userHomeBasePath": "Путь к домашнему каталогу пользователя",
|
||||||
|
"userScopeGenerationPlaceholder": "Область действия будет сгенерирована автоматически",
|
||||||
|
"createUserHomeDirectory": "Создать домашний каталог пользователя",
|
||||||
"customStylesheet": "Свой стиль",
|
"customStylesheet": "Свой стиль",
|
||||||
"defaultUserDescription": "Это настройки по умолчанию для новых пользователей.",
|
"defaultUserDescription": "Это настройки по умолчанию для новых пользователей.",
|
||||||
"disableExternalLinks": "Отключить внешние ссылки (кроме документации)",
|
"disableExternalLinks": "Отключить внешние ссылки (кроме документации)",
|
||||||
@@ -196,7 +215,7 @@
|
|||||||
"ruleExample2": "блокирует доступ к файлу с именем Caddyfile в корневой области.",
|
"ruleExample2": "блокирует доступ к файлу с именем Caddyfile в корневой области.",
|
||||||
"rules": "Права",
|
"rules": "Права",
|
||||||
"rulesHelp": "Здесь вы можете определить набор разрешающих и запрещающих правил для этого конкретного пользователь. Блокированные файлы не будут отображаться в списках, и не будут доступны для пользователя. Есть поддержка регулярных выражений и относительных путей.\n",
|
"rulesHelp": "Здесь вы можете определить набор разрешающих и запрещающих правил для этого конкретного пользователь. Блокированные файлы не будут отображаться в списках, и не будут доступны для пользователя. Есть поддержка регулярных выражений и относительных путей.\n",
|
||||||
"scope": "Корень",
|
"scope": "Область",
|
||||||
"setDateFormat": "Установить точный формат даты",
|
"setDateFormat": "Установить точный формат даты",
|
||||||
"settingsUpdated": "Настройки применены!",
|
"settingsUpdated": "Настройки применены!",
|
||||||
"shareDuration": "Время расшаренной ссылки",
|
"shareDuration": "Время расшаренной ссылки",
|
||||||
@@ -204,6 +223,7 @@
|
|||||||
"shareDeleted": "Расшаренная ссылка удалена!",
|
"shareDeleted": "Расшаренная ссылка удалена!",
|
||||||
"singleClick": "Открытие файлов и каталогов одним кликом",
|
"singleClick": "Открытие файлов и каталогов одним кликом",
|
||||||
"themes": {
|
"themes": {
|
||||||
|
"default": " Системные настройки по умолчанию",
|
||||||
"dark": "Темная",
|
"dark": "Темная",
|
||||||
"light": "Светлая",
|
"light": "Светлая",
|
||||||
"title": "Тема"
|
"title": "Тема"
|
||||||
|
|||||||
265
frontend/src/i18n/vi.json
Normal file
265
frontend/src/i18n/vi.json
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
{
|
||||||
|
"buttons": {
|
||||||
|
"cancel": "Hủy",
|
||||||
|
"clear": "Xóa",
|
||||||
|
"close": "Đóng",
|
||||||
|
"continue": "Tiếp tục",
|
||||||
|
"copy": "Sao chép",
|
||||||
|
"copyFile": "Sao chép tập tin",
|
||||||
|
"copyToClipboard": "Sao chép vào clipboard",
|
||||||
|
"copyDownloadLinkToClipboard": "Sao chép liên kết tải xuống vào clipboard",
|
||||||
|
"create": "Tạo",
|
||||||
|
"delete": "Xóa",
|
||||||
|
"download": "Tải xuống",
|
||||||
|
"file": "Tập tin",
|
||||||
|
"folder": "Thư mục",
|
||||||
|
"fullScreen": "Toàn màn hình",
|
||||||
|
"hideDotfiles": "Ẩn tập tin ẩn",
|
||||||
|
"info": "Thông tin",
|
||||||
|
"more": "Thêm",
|
||||||
|
"move": "Di chuyển",
|
||||||
|
"moveFile": "Di chuyển tập tin",
|
||||||
|
"new": "Mới",
|
||||||
|
"next": "Tiếp theo",
|
||||||
|
"ok": "OK",
|
||||||
|
"permalink": "Lấy liên kết vĩnh viễn",
|
||||||
|
"previous": "Trước",
|
||||||
|
"preview": "Xem trước",
|
||||||
|
"publish": "Xuất bản",
|
||||||
|
"rename": "Đổi tên",
|
||||||
|
"replace": "Thay thế",
|
||||||
|
"reportIssue": "Báo cáo sự cố",
|
||||||
|
"save": "Lưu",
|
||||||
|
"schedule": "Lên lịch",
|
||||||
|
"search": "Tìm kiếm",
|
||||||
|
"select": "Chọn",
|
||||||
|
"selectMultiple": "Chọn nhiều",
|
||||||
|
"share": "Chia sẻ",
|
||||||
|
"shell": "Chuyển đổi shell",
|
||||||
|
"submit": "Gửi",
|
||||||
|
"switchView": "Chuyển chế độ xem",
|
||||||
|
"toggleSidebar": "Thanh bên",
|
||||||
|
"update": "Cập nhật",
|
||||||
|
"upload": "Tải lên",
|
||||||
|
"openFile": "Mở tệp",
|
||||||
|
"discardChanges": "Hủy bỏ thay đổi"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"downloadFile": "Tải xuống tệp tin",
|
||||||
|
"downloadFolder": "Tải xuống thư mục",
|
||||||
|
"downloadSelected": "Tải xuống đã chọn"
|
||||||
|
},
|
||||||
|
"upload": {
|
||||||
|
"abortUpload": "Bạn có chắc chắn muốn hủy tải lên không?"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"forbidden": "Bạn không có quyền truy cập vào nội dung này.",
|
||||||
|
"internal": "Đã xảy ra lỗi nghiêm trọng.",
|
||||||
|
"notFound": "Không thể truy cập vị trí này.",
|
||||||
|
"connection": "Không thể kết nối đến máy chủ."
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"body": "Nội dung",
|
||||||
|
"closePreview": "Đóng xem trước",
|
||||||
|
"files": "Tập tin",
|
||||||
|
"folders": "Thư mục",
|
||||||
|
"home": "Trang chủ",
|
||||||
|
"lastModified": "Sửa đổi lần cuối",
|
||||||
|
"loading": "Đang tải...",
|
||||||
|
"lonely": "Không có gì ở đây...",
|
||||||
|
"metadata": "Siêu dữ liệu",
|
||||||
|
"multipleSelectionEnabled": "Đã bật chọn nhiều",
|
||||||
|
"name": "Tên",
|
||||||
|
"size": "Kích thước",
|
||||||
|
"sortByLastModified": "Sắp xếp theo ngày sửa đổi",
|
||||||
|
"sortByName": "Sắp xếp theo tên",
|
||||||
|
"sortBySize": "Sắp xếp theo kích thước",
|
||||||
|
"noPreview": "Không có bản xem trước cho tập tin này."
|
||||||
|
},
|
||||||
|
"help": {
|
||||||
|
"click": "chọn tập tin hoặc thư mục",
|
||||||
|
"ctrl": {
|
||||||
|
"click": "chọn nhiều tập tin hoặc thư mục",
|
||||||
|
"f": "mở tìm kiếm",
|
||||||
|
"s": "lưu tập tin hoặc tải thư mục hiện tại"
|
||||||
|
},
|
||||||
|
"del": "xóa các mục đã chọn",
|
||||||
|
"doubleClick": "mở tập tin hoặc thư mục",
|
||||||
|
"esc": "hủy chọn và/hoặc đóng hộp thoại",
|
||||||
|
"f1": "mở trợ giúp này",
|
||||||
|
"f2": "đổi tên tập tin",
|
||||||
|
"help": "Trợ giúp"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"createAnAccount": "Tạo tài khoản",
|
||||||
|
"loginInstead": "Đã có tài khoản",
|
||||||
|
"password": "Mật khẩu",
|
||||||
|
"passwordConfirm": "Xác nhận mật khẩu",
|
||||||
|
"passwordsDontMatch": "Mật khẩu không khớp",
|
||||||
|
"signup": "Đăng ký",
|
||||||
|
"submit": "Đăng nhập",
|
||||||
|
"username": "Tên người dùng",
|
||||||
|
"usernameTaken": "Tên người dùng đã tồn tại",
|
||||||
|
"wrongCredentials": "Thông tin đăng nhập không đúng"
|
||||||
|
},
|
||||||
|
"permanent": "Vĩnh viễn",
|
||||||
|
"prompts": {
|
||||||
|
"copy": "Sao chép",
|
||||||
|
"copyMessage": "Chọn vị trí để sao chép tệp của bạn:",
|
||||||
|
"currentlyNavigating": "Đang điều hướng tại:",
|
||||||
|
"deleteMessageMultiple": "Bạn có chắc chắn muốn xóa {count} tệp không?",
|
||||||
|
"deleteMessageSingle": "Bạn có chắc chắn muốn xóa tệp/thư mục này không?",
|
||||||
|
"deleteMessageShare": "Bạn có chắc chắn muốn xóa chia sẻ này ({path}) không?",
|
||||||
|
"deleteUser": "Bạn có chắc chắn muốn xóa người dùng này không?",
|
||||||
|
"deleteTitle": "Xóa tệp",
|
||||||
|
"displayName": "Tên hiển thị:",
|
||||||
|
"download": "Tải xuống tệp",
|
||||||
|
"downloadMessage": "Chọn định dạng bạn muốn tải xuống.",
|
||||||
|
"error": "Đã xảy ra lỗi",
|
||||||
|
"fileInfo": "Thông tin tệp",
|
||||||
|
"filesSelected": "{count} tệp đã được chọn.",
|
||||||
|
"lastModified": "Chỉnh sửa lần cuối",
|
||||||
|
"move": "Di chuyển",
|
||||||
|
"moveMessage": "Chọn vị trí mới cho tệp/thư mục của bạn:",
|
||||||
|
"newArchetype": "Tạo một bài viết mới dựa trên nguyên mẫu. Tệp của bạn sẽ được tạo trong thư mục nội dung.",
|
||||||
|
"newDir": "Thư mục mới",
|
||||||
|
"newDirMessage": "Đặt tên cho thư mục mới của bạn.",
|
||||||
|
"newFile": "Tệp mới",
|
||||||
|
"newFileMessage": "Đặt tên cho tệp mới của bạn.",
|
||||||
|
"numberDirs": "Số lượng thư mục",
|
||||||
|
"numberFiles": "Số lượng tệp",
|
||||||
|
"rename": "Đổi tên",
|
||||||
|
"renameMessage": "Nhập tên mới cho",
|
||||||
|
"replace": "Thay thế",
|
||||||
|
"replaceMessage": "Một trong những tệp bạn đang cố tải lên có tên trùng lặp. Bạn có muốn bỏ qua tệp này và tiếp tục tải lên hay thay thế tệp hiện có?\n",
|
||||||
|
"schedule": "Lên lịch",
|
||||||
|
"scheduleMessage": "Chọn ngày và giờ để lên lịch xuất bản bài viết này.",
|
||||||
|
"show": "Hiển thị",
|
||||||
|
"size": "Kích thước",
|
||||||
|
"upload": "Tải lên",
|
||||||
|
"uploadFiles": "Đang tải lên {files} tệp...",
|
||||||
|
"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?"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"images": "Hình ảnh",
|
||||||
|
"music": "Nhạc",
|
||||||
|
"pdf": "PDF",
|
||||||
|
"pressToSearch": "Nhấn Enter để tìm kiếm...",
|
||||||
|
"search": "Tìm kiếm...",
|
||||||
|
"typeToSearch": "Nhập để tìm kiếm...",
|
||||||
|
"types": "Loại",
|
||||||
|
"video": "Video"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"admin": "Quản trị viên",
|
||||||
|
"administrator": "Người quản trị",
|
||||||
|
"allowCommands": "Thực thi lệnh",
|
||||||
|
"allowEdit": "Chỉnh sửa, đổi tên và xóa tệp hoặc thư mục",
|
||||||
|
"allowNew": "Tạo tệp và thư mục mới",
|
||||||
|
"allowPublish": "Xuất bản bài viết và trang mới",
|
||||||
|
"allowSignup": "Cho phép người dùng đăng ký",
|
||||||
|
"avoidChanges": "(để trống để tránh thay đổi)",
|
||||||
|
"branding": "Thương hiệu",
|
||||||
|
"brandingDirectoryPath": "Đường dẫn thư mục thương hiệu",
|
||||||
|
"brandingHelp": "Bạn có thể tùy chỉnh giao diện và trải nghiệm của File Browser bằng cách thay đổi tên, thay thế logo, thêm kiểu tùy chỉnh và thậm chí vô hiệu hóa các liên kết bên ngoài đến GitHub.\nĐể biết thêm thông tin về tùy chỉnh thương hiệu, vui lòng xem {0}.",
|
||||||
|
"changePassword": "Đổi mật khẩu",
|
||||||
|
"commandRunner": "Trình chạy lệnh",
|
||||||
|
"commandRunnerHelp": "Tại đây, bạn có thể thiết lập các lệnh được thực thi trong các sự kiện đã định. Bạn phải viết một lệnh trên mỗi dòng. Các biến môi trường {0} và {1} sẽ có sẵn, trong đó {0} tương đối với {1}. Để biết thêm thông tin về tính năng này và các biến môi trường có sẵn, vui lòng đọc {2}.",
|
||||||
|
"commandsUpdated": "Lệnh đã được cập nhật!",
|
||||||
|
"createUserDir": "Tự động tạo thư mục chính của người dùng khi thêm người dùng mới",
|
||||||
|
"tusUploads": "Tải lên theo phân đoạn",
|
||||||
|
"tusUploadsHelp": "File Browser hỗ trợ tải lên tệp theo phân đoạn, giúp việc tải lên trở nên hiệu quả, đáng tin cậy, có thể tiếp tục và phù hợp với mạng không ổn định.",
|
||||||
|
"tusUploadsChunkSize": "Kích thước tối đa của một yêu cầu (tải lên trực tiếp sẽ được sử dụng cho các tệp nhỏ hơn). Bạn có thể nhập một số nguyên biểu thị kích thước theo byte hoặc một chuỗi như 10MB, 1GB, v.v.",
|
||||||
|
"tusUploadsRetryCount": "Số lần thử lại nếu một phân đoạn tải lên thất bại.",
|
||||||
|
"userHomeBasePath": "Đường dẫn cơ bản của thư mục chính người dùng",
|
||||||
|
"userScopeGenerationPlaceholder": "Phạm vi sẽ được tạo tự động",
|
||||||
|
"createUserHomeDirectory": "Tạo thư mục chính của người dùng",
|
||||||
|
"customStylesheet": "Bảng định dạng tùy chỉnh",
|
||||||
|
"defaultUserDescription": "Đây là cài đặt mặc định cho người dùng mới.",
|
||||||
|
"disableExternalLinks": "Vô hiệu hóa các liên kết bên ngoài (trừ tài liệu)",
|
||||||
|
"disableUsedDiskPercentage": "Vô hiệu hóa biểu đồ phần trăm dung lượng đã sử dụng",
|
||||||
|
"documentation": "tài liệu",
|
||||||
|
"examples": "Ví dụ",
|
||||||
|
"executeOnShell": "Thực thi trên shell",
|
||||||
|
"executeOnShellDescription": "Theo mặc định, File Browser thực thi lệnh bằng cách gọi trực tiếp các tệp nhị phân của chúng. Nếu bạn muốn chạy chúng trên shell (chẳng hạn như Bash hoặc PowerShell), bạn có thể định nghĩa tại đây cùng với các tham số và cờ cần thiết. Nếu được đặt, lệnh bạn thực thi sẽ được thêm làm đối số. Điều này áp dụng cho cả lệnh người dùng và hook sự kiện.",
|
||||||
|
"globalRules": "Đây là tập hợp quy tắc chung về quyền cho phép và từ chối. Chúng áp dụng cho mọi người dùng. Bạn có thể đặt quy tắc riêng cho từng người dùng để ghi đè các quy tắc chung này.",
|
||||||
|
"globalSettings": "Cài đặt chung",
|
||||||
|
"hideDotfiles": "Ẩn tệp ẩn (dotfiles)",
|
||||||
|
"insertPath": "Nhập đường dẫn",
|
||||||
|
"insertRegex": "Nhập biểu thức regex",
|
||||||
|
"instanceName": "Tên phiên bản",
|
||||||
|
"language": "Ngôn ngữ",
|
||||||
|
"lockPassword": "Ngăn người dùng thay đổi mật khẩu",
|
||||||
|
"newPassword": "Mật khẩu mới của bạn",
|
||||||
|
"newPasswordConfirm": "Xác nhận mật khẩu mới",
|
||||||
|
"newUser": "Người dùng mới",
|
||||||
|
"password": "Mật khẩu",
|
||||||
|
"passwordUpdated": "Mật khẩu đã được cập nhật!",
|
||||||
|
"path": "Đường dẫn",
|
||||||
|
"perm": {
|
||||||
|
"create": "Tạo tệp và thư mục",
|
||||||
|
"delete": "Xóa tệp và thư mục",
|
||||||
|
"download": "Tải xuống",
|
||||||
|
"execute": "Thực thi lệnh",
|
||||||
|
"modify": "Chỉnh sửa tệp",
|
||||||
|
"rename": "Đổi tên hoặc di chuyển tệp và thư mục",
|
||||||
|
"share": "Chia sẻ tệp"
|
||||||
|
},
|
||||||
|
"permissions": "Quyền",
|
||||||
|
"permissionsHelp": "Bạn có thể đặt người dùng làm quản trị viên hoặc chọn quyền riêng lẻ. Nếu chọn \"Người quản trị\", tất cả các tùy chọn khác sẽ tự động được chọn. Việc quản lý người dùng vẫn là đặc quyền của quản trị viên.\n",
|
||||||
|
"profileSettings": "Cài đặt hồ sơ",
|
||||||
|
"ruleExample1": "ngăn truy cập vào bất kỳ tệp ẩn nào (chẳng hạn như .git, .gitignore) trong mọi thư mục.\n",
|
||||||
|
"ruleExample2": "chặn truy cập vào tệp có tên Caddyfile trong thư mục gốc của phạm vi.",
|
||||||
|
"rules": "Quy tắc",
|
||||||
|
"rulesHelp": "Tại đây, bạn có thể xác định một tập hợp quy tắc cho phép hoặc từ chối cho người dùng cụ thể này. Các tệp bị chặn sẽ không hiển thị trong danh sách và người dùng không thể truy cập chúng. Chúng tôi hỗ trợ regex và đường dẫn tương đối với phạm vi của người dùng.\n",
|
||||||
|
"scope": "Phạm vi",
|
||||||
|
"setDateFormat": "Đặt định dạng ngày chính xác",
|
||||||
|
"settingsUpdated": "Cài đặt đã được cập nhật!",
|
||||||
|
"shareDuration": "Thời gian chia sẻ",
|
||||||
|
"shareManagement": "Quản lý chia sẻ",
|
||||||
|
"shareDeleted": "Chia sẻ đã bị xóa!",
|
||||||
|
"singleClick": "Dùng một lần nhấp để mở tệp và thư mục",
|
||||||
|
"themes": {
|
||||||
|
"default": "Mặc định hệ thống",
|
||||||
|
"dark": "Tối",
|
||||||
|
"light": "Sáng",
|
||||||
|
"title": "Chủ đề"
|
||||||
|
},
|
||||||
|
"user": "Người dùng",
|
||||||
|
"userCommands": "Lệnh",
|
||||||
|
"userCommandsHelp": "Danh sách lệnh được phân tách bằng khoảng trắng dành cho người dùng này. Ví dụ:\n",
|
||||||
|
"userCreated": "Người dùng đã được tạo!",
|
||||||
|
"userDefaults": "Cài đặt mặc định của người dùng",
|
||||||
|
"userDeleted": "Người dùng đã bị xóa!",
|
||||||
|
"userManagement": "Quản lý người dùng",
|
||||||
|
"userUpdated": "Người dùng đã được cập nhật!",
|
||||||
|
"username": "Tên người dùng",
|
||||||
|
"users": "Người dùng"
|
||||||
|
},
|
||||||
|
"sidebar": {
|
||||||
|
"help": "Trợ giúp",
|
||||||
|
"hugoNew": "Hugo New",
|
||||||
|
"login": "Đăng nhập",
|
||||||
|
"logout": "Đăng xuất",
|
||||||
|
"myFiles": "Tập tin của tôi",
|
||||||
|
"newFile": "Tập tin mới",
|
||||||
|
"newFolder": "Thư mục mới",
|
||||||
|
"preview": "Xem trước",
|
||||||
|
"settings": "Cài đặt",
|
||||||
|
"signup": "Đăng ký",
|
||||||
|
"siteSettings": "Cài đặt trang"
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
"linkCopied": "Liên kết đã được sao chép!"
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"days": "Ngày",
|
||||||
|
"hours": "Giờ",
|
||||||
|
"minutes": "Phút",
|
||||||
|
"seconds": "Giây",
|
||||||
|
"unit": "Đơn vị"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import VueNumberInput from "@chenfengyuan/vue-number-input";
|
|||||||
import VueLazyload from "vue-lazyload";
|
import VueLazyload from "vue-lazyload";
|
||||||
import { createVfm } from "vue-final-modal";
|
import { createVfm } from "vue-final-modal";
|
||||||
import Toast, { POSITION, useToast } from "vue-toastification";
|
import Toast, { POSITION, useToast } from "vue-toastification";
|
||||||
import {
|
import type {
|
||||||
ToastOptions,
|
ToastOptions,
|
||||||
PluginOptions,
|
PluginOptions,
|
||||||
} from "vue-toastification/dist/types/types";
|
} from "vue-toastification/dist/types/types";
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { RouteLocation, createRouter, createWebHistory } from "vue-router";
|
import type { RouteLocation } from "vue-router";
|
||||||
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
import Login from "@/views/Login.vue";
|
import Login from "@/views/Login.vue";
|
||||||
import Layout from "@/views/Layout.vue";
|
import Layout from "@/views/Layout.vue";
|
||||||
import Files from "@/views/Files.vue";
|
import Files from "@/views/Files.vue";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createPinia as _createPinia } from "pinia";
|
import { createPinia as _createPinia } from "pinia";
|
||||||
import { markRaw } from "vue";
|
import { markRaw } from "vue";
|
||||||
import { Router } from "vue-router";
|
import type { Router } from "vue-router";
|
||||||
|
|
||||||
export default function createPinia(router: Router) {
|
export default function createPinia(router: Router) {
|
||||||
const pinia = _createPinia();
|
const pinia = _createPinia();
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ export const useLayoutStore = defineStore("layout", {
|
|||||||
toggleShell() {
|
toggleShell() {
|
||||||
this.showShell = !this.showShell;
|
this.showShell = !this.showShell;
|
||||||
},
|
},
|
||||||
|
setCloseOnPrompt(closeFunction: () => Promise<string>, onPrompt: string) {
|
||||||
|
const prompt = this.prompts.find((prompt) => prompt.prompt === onPrompt);
|
||||||
|
if (prompt) {
|
||||||
|
prompt.close = closeFunction;
|
||||||
|
}
|
||||||
|
},
|
||||||
showHover(value: PopupProps | string) {
|
showHover(value: PopupProps | string) {
|
||||||
if (typeof value !== "object") {
|
if (typeof value !== "object") {
|
||||||
this.prompts.push({
|
this.prompts.push({
|
||||||
@@ -36,6 +42,7 @@ export const useLayoutStore = defineStore("layout", {
|
|||||||
confirm: null,
|
confirm: null,
|
||||||
action: undefined,
|
action: undefined,
|
||||||
props: null,
|
props: null,
|
||||||
|
close: null,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -45,6 +52,7 @@ export const useLayoutStore = defineStore("layout", {
|
|||||||
confirm: value?.confirm,
|
confirm: value?.confirm,
|
||||||
action: value?.action,
|
action: value?.action,
|
||||||
props: value?.props,
|
props: value?.props,
|
||||||
|
close: value?.close,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showError() {
|
showError() {
|
||||||
@@ -53,6 +61,7 @@ export const useLayoutStore = defineStore("layout", {
|
|||||||
confirm: null,
|
confirm: null,
|
||||||
action: undefined,
|
action: undefined,
|
||||||
props: null,
|
props: null,
|
||||||
|
close: null,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showSuccess() {
|
showSuccess() {
|
||||||
@@ -61,10 +70,11 @@ export const useLayoutStore = defineStore("layout", {
|
|||||||
confirm: null,
|
confirm: null,
|
||||||
action: undefined,
|
action: undefined,
|
||||||
props: null,
|
props: null,
|
||||||
|
close: null,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
closeHovers() {
|
closeHovers() {
|
||||||
this.prompts.pop();
|
this.prompts.shift()?.close?.();
|
||||||
},
|
},
|
||||||
// easily reset state using `$reset`
|
// easily reset state using `$reset`
|
||||||
clearLayout() {
|
clearLayout() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { useFileStore } from "./file";
|
import { useFileStore } from "./file";
|
||||||
import { files as api } from "@/api";
|
import { files as api } from "@/api";
|
||||||
import throttle from "lodash/throttle";
|
import { throttle } from "lodash-es";
|
||||||
import buttons from "@/utils/buttons";
|
import buttons from "@/utils/buttons";
|
||||||
|
|
||||||
// TODO: make this into a user setting
|
// TODO: make this into a user setting
|
||||||
|
|||||||
1
frontend/src/types/layout.d.ts
vendored
1
frontend/src/types/layout.d.ts
vendored
@@ -3,6 +3,7 @@ interface PopupProps {
|
|||||||
confirm?: any;
|
confirm?: any;
|
||||||
action?: PopupAction;
|
action?: PopupAction;
|
||||||
props?: any;
|
props?: any;
|
||||||
|
close?: (() => Promise<string>) | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PopupAction = (e: Event) => void;
|
type PopupAction = (e: Event) => void;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import { JwtPayload, jwtDecode } from "jwt-decode";
|
import type { JwtPayload } from "jwt-decode";
|
||||||
|
import { jwtDecode } from "jwt-decode";
|
||||||
import { baseURL, noAuth } from "./constants";
|
import { baseURL, noAuth } from "./constants";
|
||||||
import { StatusError } from "@/api/utils";
|
import { StatusError } from "@/api/utils";
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ export async function validateLogin() {
|
|||||||
await renew(<string>localStorage.getItem("jwt"));
|
await renew(<string>localStorage.getItem("jwt"));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("Invalid JWT token in storage"); // eslint-disable-line
|
console.warn("Invalid JWT token in storage");
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ function loading(button: string) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (el === undefined || el === null) {
|
if (el === undefined || el === null) {
|
||||||
console.log("Error getting button " + button); // eslint-disable-line
|
console.log("Error getting button " + button);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ function done(button: string) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (el === undefined || el === null) {
|
if (el === undefined || el === null) {
|
||||||
console.log("Error getting button " + button); // eslint-disable-line
|
console.log("Error getting button " + button);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ function success(button: string) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (el === undefined || el === null) {
|
if (el === undefined || el === null) {
|
||||||
console.log("Error getting button " + button); // eslint-disable-line
|
console.log("Error getting button " + button);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,36 @@
|
|||||||
// Based on code by the following links:
|
// Based on code by the following links:
|
||||||
// https://stackoverflow.com/a/74528564
|
// https://stackoverflow.com/a/74528564
|
||||||
// https://web.dev/articles/async-clipboard
|
// https://web.dev/articles/async-clipboard
|
||||||
export function copy(text: string) {
|
|
||||||
|
interface ClipboardArgs {
|
||||||
|
text?: string;
|
||||||
|
data?: ClipboardItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ClipboardOpts {
|
||||||
|
permission?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function copy(data: ClipboardArgs, opts?: ClipboardOpts) {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
if (
|
if (
|
||||||
// Clipboard API requires secure context
|
// Clipboard API requires secure context
|
||||||
window.isSecureContext &&
|
window.isSecureContext &&
|
||||||
typeof navigator.clipboard !== "undefined" &&
|
typeof navigator.clipboard !== "undefined"
|
||||||
// @ts-ignore
|
|
||||||
navigator.permissions !== "undefined"
|
|
||||||
) {
|
) {
|
||||||
navigator.permissions
|
if (opts?.permission) {
|
||||||
// @ts-ignore
|
getPermission("clipboard-write")
|
||||||
.query({ name: "clipboard-write" })
|
.then(() => writeToClipboard(data).then(resolve).catch(reject))
|
||||||
.then((permission) => {
|
.catch(reject);
|
||||||
if (permission.state === "granted" || permission.state === "prompt") {
|
} else {
|
||||||
// simple writeText should work for all modern browsers
|
writeToClipboard(data).then(resolve).catch(reject);
|
||||||
navigator.clipboard.writeText(text).then(resolve).catch(reject);
|
}
|
||||||
} else {
|
|
||||||
reject(new Error("Permission not granted!"));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
// Firefox doesn't support clipboard-write permission
|
|
||||||
if (navigator.userAgent.indexOf("Firefox") != -1) {
|
|
||||||
navigator.clipboard.writeText(text).then(resolve).catch(reject);
|
|
||||||
} else {
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (
|
} else if (
|
||||||
document.queryCommandSupported &&
|
document.queryCommandSupported &&
|
||||||
document.queryCommandSupported("copy")
|
document.queryCommandSupported("copy") &&
|
||||||
|
data.text // old method only supports text
|
||||||
) {
|
) {
|
||||||
const textarea = createTemporaryTextarea(text);
|
const textarea = createTemporaryTextarea(data.text);
|
||||||
const body = document.activeElement || document.body;
|
const body = document.activeElement || document.body;
|
||||||
try {
|
try {
|
||||||
body.appendChild(textarea);
|
body.appendChild(textarea);
|
||||||
@@ -54,6 +51,35 @@ export function copy(text: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPermission(name: string) {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
typeof navigator.permissions !== "undefined" &&
|
||||||
|
navigator.permissions
|
||||||
|
// @ts-expect-error chrome specific api
|
||||||
|
.query({ name })
|
||||||
|
.then((permission) => {
|
||||||
|
if (permission.state === "granted" || permission.state === "prompt") {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(new Error("Permission denied!"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeToClipboard(data: ClipboardArgs) {
|
||||||
|
if (data.text) {
|
||||||
|
return navigator.clipboard.writeText(data.text);
|
||||||
|
}
|
||||||
|
if (data.data) {
|
||||||
|
return navigator.clipboard.write(data.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
reject(new Error("No data was supplied!"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
fontSize: "12pt",
|
fontSize: "12pt",
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
@@ -69,10 +95,10 @@ const styles = {
|
|||||||
background: "transparent",
|
background: "transparent",
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTemporaryTextarea = (text: string) => {
|
function createTemporaryTextarea(text: string) {
|
||||||
const textarea = document.createElement("textarea");
|
const textarea = document.createElement("textarea");
|
||||||
textarea.value = text;
|
textarea.value = text;
|
||||||
textarea.setAttribute("readonly", "");
|
textarea.setAttribute("readonly", "");
|
||||||
Object.assign(textarea.style, styles);
|
Object.assign(textarea.style, styles);
|
||||||
return textarea;
|
return textarea;
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -6,13 +6,16 @@ export default function getRule(rules: string[]) {
|
|||||||
let result = null;
|
let result = null;
|
||||||
const find = Array.prototype.find;
|
const find = Array.prototype.find;
|
||||||
|
|
||||||
find.call(document.styleSheets, (styleSheet) => {
|
find.call(document.styleSheets, (styleSheet: CSSStyleSheet) => {
|
||||||
result = find.call(styleSheet.cssRules, (cssRule) => {
|
result = find.call(styleSheet.cssRules, (cssRule: CSSRule) => {
|
||||||
let found = false;
|
let found = false;
|
||||||
|
|
||||||
if (cssRule instanceof window.CSSStyleRule) {
|
// faster than checking instanceof for every element
|
||||||
|
if (cssRule.constructor.name === "CSSStyleRule") {
|
||||||
for (let i = 0; i < rules.length; i++) {
|
for (let i = 0; i < rules.length; i++) {
|
||||||
if (cssRule.selectorText.toLowerCase() === rules[i]) {
|
if (
|
||||||
|
(cssRule as CSSStyleRule).selectorText.toLowerCase() === rules[i]
|
||||||
|
) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,5 +27,5 @@ export default function getRule(rules: string[]) {
|
|||||||
return result != null;
|
return result != null;
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result as CSSStyleRule | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
import { useUploadStore } from "@/stores/upload";
|
import { useUploadStore } from "@/stores/upload";
|
||||||
import url from "@/utils/url";
|
import url from "@/utils/url";
|
||||||
|
|
||||||
@@ -126,6 +127,9 @@ export function handleFiles(
|
|||||||
overwrite = false
|
overwrite = false
|
||||||
) {
|
) {
|
||||||
const uploadStore = useUploadStore();
|
const uploadStore = useUploadStore();
|
||||||
|
const layoutStore = useLayoutStore();
|
||||||
|
|
||||||
|
layoutStore.closeHovers();
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const id = uploadStore.id;
|
const id = uploadStore.id;
|
||||||
|
|||||||
@@ -325,6 +325,7 @@ const token = ref<string>("");
|
|||||||
const audio = ref<HTMLAudioElement>();
|
const audio = ref<HTMLAudioElement>();
|
||||||
const tag = ref<boolean>(false);
|
const tag = ref<boolean>(false);
|
||||||
|
|
||||||
|
const $showError = inject<IToastError>("$showError")!;
|
||||||
const $showSuccess = inject<IToastSuccess>("$showSuccess")!;
|
const $showSuccess = inject<IToastSuccess>("$showSuccess")!;
|
||||||
|
|
||||||
const { t } = useI18n({});
|
const { t } = useI18n({});
|
||||||
@@ -463,9 +464,9 @@ const download = () => {
|
|||||||
if (req.value === null) return false;
|
if (req.value === null) return false;
|
||||||
layoutStore.closeHovers();
|
layoutStore.closeHovers();
|
||||||
|
|
||||||
let files: string[] = [];
|
const files: string[] = [];
|
||||||
|
|
||||||
for (let i of fileStore.selected) {
|
for (const i of fileStore.selected) {
|
||||||
files.push(req.value.items[i].path);
|
files.push(req.value.items[i].path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,13 +489,23 @@ const linkSelected = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const copyToClipboard = (text: string) => {
|
const copyToClipboard = (text: string) => {
|
||||||
copy(text).then(
|
copy({ text }).then(
|
||||||
() => {
|
() => {
|
||||||
// clipboard successfully set
|
// clipboard successfully set
|
||||||
$showSuccess(t("success.linkCopied"));
|
$showSuccess(t("success.linkCopied"));
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
// clipboard write failed
|
// clipboard write failed
|
||||||
|
copy({ text }, { permission: true }).then(
|
||||||
|
() => {
|
||||||
|
// clipboard successfully set
|
||||||
|
$showSuccess(t("success.linkCopied"));
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
// clipboard write failed
|
||||||
|
$showError(e);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ onMounted(() => {
|
|||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
readOnly: fileStore.req?.type === "textImmutable",
|
readOnly: fileStore.req?.type === "textImmutable",
|
||||||
theme: "ace/theme/chrome",
|
theme: "ace/theme/chrome",
|
||||||
mode: modelist.getModeForPath(fileStore.req?.name).mode,
|
mode: modelist.getModeForPath(fileStore.req!.name).mode,
|
||||||
wrap: true,
|
wrap: true,
|
||||||
enableBasicAutocompletion: true,
|
enableBasicAutocompletion: true,
|
||||||
enableLiveAutocompletion: true,
|
enableLiveAutocompletion: true,
|
||||||
@@ -173,7 +173,7 @@ const close = () => {
|
|||||||
|
|
||||||
fileStore.updateRequest(null);
|
fileStore.updateRequest(null);
|
||||||
|
|
||||||
let uri = url.removeLastDir(route.path) + "/";
|
const uri = url.removeLastDir(route.path) + "/";
|
||||||
router.push({ path: uri });
|
router.push({ path: uri });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ import { users, files as api } from "@/api";
|
|||||||
import { enableExec } from "@/utils/constants";
|
import { enableExec } from "@/utils/constants";
|
||||||
import * as upload from "@/utils/upload";
|
import * as upload from "@/utils/upload";
|
||||||
import css from "@/utils/css";
|
import css from "@/utils/css";
|
||||||
import throttle from "lodash/throttle";
|
import { throttle } from "lodash-es";
|
||||||
import { Base64 } from "js-base64";
|
import { Base64 } from "js-base64";
|
||||||
|
|
||||||
import HeaderBar from "@/components/header/HeaderBar.vue";
|
import HeaderBar from "@/components/header/HeaderBar.vue";
|
||||||
@@ -511,8 +511,11 @@ const keyEvent = (event: KeyboardEvent) => {
|
|||||||
|
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case "f":
|
case "f":
|
||||||
event.preventDefault();
|
case "F":
|
||||||
layoutStore.showHover("search");
|
if (event.shiftKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
layoutStore.showHover("search");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "c":
|
case "c":
|
||||||
case "x":
|
case "x":
|
||||||
@@ -523,12 +526,12 @@ const keyEvent = (event: KeyboardEvent) => {
|
|||||||
break;
|
break;
|
||||||
case "a":
|
case "a":
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
for (let file of items.value.files) {
|
for (const file of items.value.files) {
|
||||||
if (fileStore.selected.indexOf(file.index) === -1) {
|
if (fileStore.selected.indexOf(file.index) === -1) {
|
||||||
fileStore.selected.push(file.index);
|
fileStore.selected.push(file.index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let dir of items.value.dirs) {
|
for (const dir of items.value.dirs) {
|
||||||
if (fileStore.selected.indexOf(dir.index) === -1) {
|
if (fileStore.selected.indexOf(dir.index) === -1) {
|
||||||
fileStore.selected.push(dir.index);
|
fileStore.selected.push(dir.index);
|
||||||
}
|
}
|
||||||
@@ -551,9 +554,9 @@ const copyCut = (event: Event | KeyboardEvent): void => {
|
|||||||
|
|
||||||
if (fileStore.req === null) return;
|
if (fileStore.req === null) return;
|
||||||
|
|
||||||
let items = [];
|
const items = [];
|
||||||
|
|
||||||
for (let i of fileStore.selected) {
|
for (const i of fileStore.selected) {
|
||||||
items.push({
|
items.push({
|
||||||
from: fileStore.req.items[i].url,
|
from: fileStore.req.items[i].url,
|
||||||
name: fileStore.req.items[i].name,
|
name: fileStore.req.items[i].name,
|
||||||
@@ -575,9 +578,9 @@ const paste = (event: Event) => {
|
|||||||
if ((event.target as HTMLElement).tagName?.toLowerCase() === "input") return;
|
if ((event.target as HTMLElement).tagName?.toLowerCase() === "input") return;
|
||||||
|
|
||||||
// TODO router location should it be
|
// TODO router location should it be
|
||||||
let items: any[] = [];
|
const items: any[] = [];
|
||||||
|
|
||||||
for (let item of clipboardStore.items) {
|
for (const item of clipboardStore.items) {
|
||||||
const from = item.from.endsWith("/") ? item.from.slice(0, -1) : item.from;
|
const from = item.from.endsWith("/") ? item.from.slice(0, -1) : item.from;
|
||||||
const to = route.path + encodeURIComponent(item.name);
|
const to = route.path + encodeURIComponent(item.name);
|
||||||
items.push({ from, to, name: item.name });
|
items.push({ from, to, name: item.name });
|
||||||
@@ -614,7 +617,7 @@ const paste = (event: Event) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let conflict = upload.checkConflict(items, fileStore.req!.items);
|
const conflict = upload.checkConflict(items, fileStore.req!.items);
|
||||||
|
|
||||||
let overwrite = false;
|
let overwrite = false;
|
||||||
let rename = false;
|
let rename = false;
|
||||||
@@ -640,14 +643,13 @@ const paste = (event: Event) => {
|
|||||||
|
|
||||||
const colunmsResize = () => {
|
const colunmsResize = () => {
|
||||||
// Update the columns size based on the window width.
|
// Update the columns size based on the window width.
|
||||||
let items_ = css(["#listing.mosaic .item", ".mosaic#listing .item"]);
|
const items_ = css(["#listing.mosaic .item", ".mosaic#listing .item"]);
|
||||||
if (items_ === null) return;
|
if (items_ === null) return;
|
||||||
|
|
||||||
let columns = Math.floor(
|
let columns = Math.floor(
|
||||||
(document.querySelector("main")?.offsetWidth ?? 0) / columnWidth.value
|
(document.querySelector("main")?.offsetWidth ?? 0) / columnWidth.value
|
||||||
);
|
);
|
||||||
if (columns === 0) columns = 1;
|
if (columns === 0) columns = 1;
|
||||||
// @ts-ignore never type error
|
|
||||||
items_.style.width = `calc(${100 / columns}% - 1em)`;
|
items_.style.width = `calc(${100 / columns}% - 1em)`;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -677,11 +679,10 @@ const dragEnter = () => {
|
|||||||
|
|
||||||
// When the user starts dragging an item, put every
|
// When the user starts dragging an item, put every
|
||||||
// file on the listing with 50% opacity.
|
// file on the listing with 50% opacity.
|
||||||
let items = document.getElementsByClassName("item");
|
const items = document.getElementsByClassName("item");
|
||||||
|
|
||||||
// @ts-ignore
|
Array.from(items).forEach((file: Element) => {
|
||||||
Array.from(items).forEach((file: HTMLElement) => {
|
(file as HTMLElement).style.opacity = "0.5";
|
||||||
file.style.opacity = "0.5";
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -698,7 +699,7 @@ const drop = async (event: DragEvent) => {
|
|||||||
dragCounter.value = 0;
|
dragCounter.value = 0;
|
||||||
resetOpacity();
|
resetOpacity();
|
||||||
|
|
||||||
let dt = event.dataTransfer;
|
const dt = event.dataTransfer;
|
||||||
let el: HTMLElement | null = event.target as HTMLElement;
|
let el: HTMLElement | null = event.target as HTMLElement;
|
||||||
|
|
||||||
if (fileStore.req === null || dt === null || dt.files.length <= 0) return;
|
if (fileStore.req === null || dt === null || dt.files.length <= 0) return;
|
||||||
@@ -709,7 +710,7 @@ const drop = async (event: DragEvent) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let files: UploadList = (await upload.scanFiles(dt)) as UploadList;
|
const files: UploadList = (await upload.scanFiles(dt)) as UploadList;
|
||||||
let items = fileStore.req.items;
|
let items = fileStore.req.items;
|
||||||
let path = route.path.endsWith("/") ? route.path : route.path + "/";
|
let path = route.path.endsWith("/") ? route.path : route.path + "/";
|
||||||
|
|
||||||
@@ -729,7 +730,7 @@ const drop = async (event: DragEvent) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let conflict = upload.checkConflict(files, items);
|
const conflict = upload.checkConflict(files, items);
|
||||||
|
|
||||||
if (conflict) {
|
if (conflict) {
|
||||||
layoutStore.showHover({
|
layoutStore.showHover({
|
||||||
@@ -753,12 +754,10 @@ const drop = async (event: DragEvent) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const uploadInput = (event: Event) => {
|
const uploadInput = (event: Event) => {
|
||||||
layoutStore.closeHovers();
|
const files = (event.currentTarget as HTMLInputElement)?.files;
|
||||||
|
|
||||||
let files = (event.currentTarget as HTMLInputElement)?.files;
|
|
||||||
if (files === null) return;
|
if (files === null) return;
|
||||||
|
|
||||||
let folder_upload = !!files[0].webkitRelativePath;
|
const folder_upload = !!files[0].webkitRelativePath;
|
||||||
|
|
||||||
const uploadFiles: UploadList = [];
|
const uploadFiles: UploadList = [];
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
@@ -773,8 +772,8 @@ const uploadInput = (event: Event) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = route.path.endsWith("/") ? route.path : route.path + "/";
|
const path = route.path.endsWith("/") ? route.path : route.path + "/";
|
||||||
let conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
|
const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
|
||||||
|
|
||||||
if (conflict) {
|
if (conflict) {
|
||||||
layoutStore.showHover({
|
layoutStore.showHover({
|
||||||
@@ -798,7 +797,7 @@ const uploadInput = (event: Event) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resetOpacity = () => {
|
const resetOpacity = () => {
|
||||||
let items = document.getElementsByClassName("item");
|
const items = document.getElementsByClassName("item");
|
||||||
|
|
||||||
Array.from(items).forEach((file: Element) => {
|
Array.from(items).forEach((file: Element) => {
|
||||||
(file as HTMLElement).style.opacity = "1";
|
(file as HTMLElement).style.opacity = "1";
|
||||||
@@ -824,7 +823,6 @@ const sort = async (by: string) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (authStore.user?.id) {
|
if (authStore.user?.id) {
|
||||||
// @ts-ignore
|
|
||||||
await users.update({ id: authStore.user?.id, sorting: { by, asc } }, [
|
await users.update({ id: authStore.user?.id, sorting: { by, asc } }, [
|
||||||
"sorting",
|
"sorting",
|
||||||
]);
|
]);
|
||||||
@@ -875,10 +873,10 @@ const download = () => {
|
|||||||
confirm: (format: any) => {
|
confirm: (format: any) => {
|
||||||
layoutStore.closeHovers();
|
layoutStore.closeHovers();
|
||||||
|
|
||||||
let files = [];
|
const files = [];
|
||||||
|
|
||||||
if (fileStore.selectedCount > 0 && fileStore.req !== null) {
|
if (fileStore.selectedCount > 0 && fileStore.req !== null) {
|
||||||
for (let i of fileStore.selected) {
|
for (const i of fileStore.selected) {
|
||||||
files.push(fileStore.req.items[i].url);
|
files.push(fileStore.req.items[i].url);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -901,13 +899,12 @@ const switchView = async () => {
|
|||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
id: authStore.user?.id,
|
id: authStore.user?.id,
|
||||||
viewMode: modes[authStore.user?.viewMode ?? "list"] || "list",
|
viewMode: (modes[authStore.user?.viewMode ?? "list"] ||
|
||||||
|
"list") as ViewModeType,
|
||||||
};
|
};
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
users.update(data, ["viewMode"]).catch($showError);
|
users.update(data, ["viewMode"]).catch($showError);
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
authStore.updateUser(data);
|
authStore.updateUser(data);
|
||||||
|
|
||||||
setItemWeight();
|
setItemWeight();
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ import { files as api } from "@/api";
|
|||||||
import { createURL } from "@/api/utils";
|
import { createURL } from "@/api/utils";
|
||||||
import { resizePreview } from "@/utils/constants";
|
import { resizePreview } from "@/utils/constants";
|
||||||
import url from "@/utils/url";
|
import url from "@/utils/url";
|
||||||
import throttle from "lodash/throttle";
|
import { throttle } from "lodash-es";
|
||||||
import HeaderBar from "@/components/header/HeaderBar.vue";
|
import HeaderBar from "@/components/header/HeaderBar.vue";
|
||||||
import Action from "@/components/header/Action.vue";
|
import Action from "@/components/header/Action.vue";
|
||||||
import ExtendedImage from "@/components/files/ExtendedImage.vue";
|
import ExtendedImage from "@/components/files/ExtendedImage.vue";
|
||||||
@@ -253,7 +253,7 @@ const hasPrevious = computed(() => previousLink.value !== "");
|
|||||||
const hasNext = computed(() => nextLink.value !== "");
|
const hasNext = computed(() => nextLink.value !== "");
|
||||||
|
|
||||||
const downloadUrl = computed(() =>
|
const downloadUrl = computed(() =>
|
||||||
fileStore.req ? api.getDownloadURL(fileStore.req, true) : ""
|
fileStore.req ? api.getDownloadURL(fileStore.req, false) : ""
|
||||||
);
|
);
|
||||||
|
|
||||||
const raw = computed(() => {
|
const raw = computed(() => {
|
||||||
@@ -262,7 +262,7 @@ const raw = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isEpub.value) {
|
if (isEpub.value) {
|
||||||
return createURL("api/raw" + fileStore.req?.path, {}, false);
|
return createURL("api/raw" + fileStore.req?.path, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
return downloadUrl.value;
|
return downloadUrl.value;
|
||||||
@@ -353,7 +353,7 @@ const updatePreview = async () => {
|
|||||||
autoPlay.value = false;
|
autoPlay.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dirs = route.fullPath.split("/");
|
const dirs = route.fullPath.split("/");
|
||||||
name.value = decodeURIComponent(dirs[dirs.length - 1]);
|
name.value = decodeURIComponent(dirs[dirs.length - 1]);
|
||||||
|
|
||||||
if (!listing.value) {
|
if (!listing.value) {
|
||||||
@@ -422,7 +422,7 @@ const toggleNavigation = throttle(function () {
|
|||||||
const close = () => {
|
const close = () => {
|
||||||
fileStore.updateRequest(null);
|
fileStore.updateRequest(null);
|
||||||
|
|
||||||
let uri = url.removeLastDir(route.path) + "/";
|
const uri = url.removeLastDir(route.path) + "/";
|
||||||
router.push({ path: uri });
|
router.push({ path: uri });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
<a
|
<a
|
||||||
class="link"
|
class="link"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://filebrowser.org/configuration/custom-branding"
|
href="https://github.com/filebrowser/filebrowser/blob/master/docs/configuration.md#custom-branding"
|
||||||
>{{ t("settings.documentation") }}</a
|
>{{ t("settings.documentation") }}</a
|
||||||
>
|
>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
<a
|
<a
|
||||||
class="link"
|
class="link"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://filebrowser.org/configuration/command-runner"
|
href="https://github.com/filebrowser/filebrowser/blob/master/docs/configuration.md#command-runner"
|
||||||
>{{ t("settings.documentation") }}</a
|
>{{ t("settings.documentation") }}</a
|
||||||
>
|
>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
@@ -282,7 +282,7 @@ const formattedChunkSize = computed({
|
|||||||
// Define funcs
|
// Define funcs
|
||||||
const capitalize = (name: string, where: string | RegExp = "_") => {
|
const capitalize = (name: string, where: string | RegExp = "_") => {
|
||||||
if (where === "caps") where = /(?=[A-Z])/;
|
if (where === "caps") where = /(?=[A-Z])/;
|
||||||
let split = name.split(where);
|
const split = name.split(where);
|
||||||
name = "";
|
name = "";
|
||||||
|
|
||||||
for (let i = 0; i < split.length; i++) {
|
for (let i = 0; i < split.length; i++) {
|
||||||
@@ -294,7 +294,7 @@ const capitalize = (name: string, where: string | RegExp = "_") => {
|
|||||||
|
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
if (settings.value === null) return false;
|
if (settings.value === null) return false;
|
||||||
let newSettings: ISettings = {
|
const newSettings: ISettings = {
|
||||||
...settings.value,
|
...settings.value,
|
||||||
shell:
|
shell:
|
||||||
settings.value?.shell
|
settings.value?.shell
|
||||||
@@ -376,7 +376,7 @@ onMounted(async () => {
|
|||||||
try {
|
try {
|
||||||
layoutStore.loading = true;
|
layoutStore.loading = true;
|
||||||
const original: ISettings = await api.get();
|
const original: ISettings = await api.get();
|
||||||
let newSettings: ISettings = { ...original, commands: {} };
|
const newSettings: ISettings = { ...original, commands: {} };
|
||||||
|
|
||||||
const keys = Object.keys(original.commands) as Array<keyof SettingsCommand>;
|
const keys = Object.keys(original.commands) as Array<keyof SettingsCommand>;
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
|
|||||||
@@ -87,12 +87,12 @@ onMounted(async () => {
|
|||||||
layoutStore.loading = true;
|
layoutStore.loading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let newLinks = await api.list();
|
const newLinks = await api.list();
|
||||||
if (authStore.user?.perm.admin) {
|
if (authStore.user?.perm.admin) {
|
||||||
let userMap = new Map<number, string>();
|
const userMap = new Map<number, string>();
|
||||||
for (let user of await users.getAll())
|
for (const user of await users.getAll())
|
||||||
userMap.set(user.id, user.username);
|
userMap.set(user.id, user.username);
|
||||||
for (let link of newLinks) {
|
for (const link of newLinks) {
|
||||||
if (link.userID && userMap.has(link.userID))
|
if (link.userID && userMap.has(link.userID))
|
||||||
link.username = userMap.get(link.userID);
|
link.username = userMap.get(link.userID);
|
||||||
}
|
}
|
||||||
@@ -108,13 +108,23 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const copyToClipboard = (text: string) => {
|
const copyToClipboard = (text: string) => {
|
||||||
copy(text).then(
|
copy({ text }).then(
|
||||||
() => {
|
() => {
|
||||||
// clipboard successfully set
|
// clipboard successfully set
|
||||||
$showSuccess(t("success.linkCopied"));
|
$showSuccess(t("success.linkCopied"));
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
// clipboard write failed
|
// clipboard write failed
|
||||||
|
copy({ text }, { permission: true }).then(
|
||||||
|
() => {
|
||||||
|
// clipboard successfully set
|
||||||
|
$showSuccess(t("success.linkCopied"));
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
// clipboard write failed
|
||||||
|
$showError(e);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const fetchData = async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (isNew.value) {
|
if (isNew.value) {
|
||||||
let { defaults, createUserDir: _createUserDir } = await settings.get();
|
const { defaults, createUserDir: _createUserDir } = await settings.get();
|
||||||
createUserDir.value = _createUserDir;
|
createUserDir.value = _createUserDir;
|
||||||
user.value = {
|
user.value = {
|
||||||
...defaults,
|
...defaults,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user