├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ ├── feature_request.md │ └── mime_request.md ├── dependabot.yml └── workflows │ ├── block-merge-freeze.yml │ ├── block-unconventional-commits.yml │ ├── command-compile.yml │ ├── cypress-snapshot-update.yml │ ├── cypress.yml │ ├── dependabot-approve-merge.yml │ ├── fixup.yml │ ├── lint-eslint.yml │ ├── lint-php-cs.yml │ ├── lint-php.yml │ ├── lint-stylelint.yml │ ├── node.yml │ ├── npm-audit-fix.yml │ ├── pr-feedback.yml │ ├── psalm.yml │ └── reuse.yml ├── .gitignore ├── .l10nignore ├── .npmignore ├── .php-cs-fixer.dist.php ├── .stylelintignore ├── .tx └── config ├── AUTHORS.md ├── COPYING ├── LICENSES ├── AGPL-3.0-or-later.txt ├── Apache-2.0.txt ├── BSD-3-Clause.txt ├── CC0-1.0.txt ├── GPL-3.0-or-later.txt ├── ISC.txt ├── LicenseRef-NextcloudTrademarks.txt ├── LicenseRef-Unsplash.txt ├── MIT.txt └── MPL-2.0.txt ├── README.md ├── REUSE.toml ├── appinfo └── info.xml ├── composer.json ├── composer.lock ├── composer ├── autoload.php ├── composer.json └── composer │ ├── ClassLoader.php │ ├── LICENSE │ ├── autoload_classmap.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_real.php │ └── autoload_static.php ├── css ├── NcActionButton-DndYZcrz.chunk.css ├── NcActionLink-Cay-IPuV.chunk.css ├── index-DCp30a-3.chunk.css ├── init-BcY_9rzn.chunk.css ├── logger-60RCWKf0.chunk.css ├── main-BwzbmUGl.chunk.css ├── viewer-init.css └── viewer-main.css ├── cypress.config.ts ├── cypress ├── .eslintrc.json ├── e2e │ ├── a11y.cy.ts │ ├── actions │ │ ├── delete.cy.ts │ │ ├── download.cy.ts │ │ └── sidebar.cy.ts │ ├── audios │ │ ├── audio.mpeg.cy.ts │ │ ├── audio.ogg.cy.ts │ │ └── audios.cy.ts │ ├── download-forbidden.cy.ts │ ├── files.cy.ts │ ├── images │ │ ├── image-apng.cy.ts │ │ ├── image-small.png.cy.ts │ │ ├── image.gif.cy.ts │ │ ├── image.ico.cy.ts │ │ ├── image.png.cy.ts │ │ ├── image.svg.cy.ts │ │ ├── image.webp.cy.ts │ │ ├── images-custom-list-loadmore.cy.ts │ │ ├── images-custom-list.cy.ts │ │ └── images.cy.ts │ ├── mixins │ │ ├── audio.ts │ │ ├── image.ts │ │ ├── oddname.ts │ │ └── video.ts │ ├── navigation.cy.ts │ ├── non-dav-files.cy.ts │ ├── oddname │ │ ├── oddname-audio.cy.ts │ │ ├── oddname-image.cy.ts │ │ ├── oddname-sidebar.cy.ts │ │ └── oddname-video.cy.ts │ ├── sharing │ │ ├── download-share-disabled.cy.ts │ │ ├── download-share.cy.ts │ │ ├── files-shares.cy.ts │ │ └── single-file-share.cy.ts │ ├── videos │ │ ├── video.mkv.cy.ts │ │ ├── video.mp4.cy.ts │ │ ├── video.ogv.cy.ts │ │ ├── video.webm.cy.ts │ │ └── videos.cy.ts │ └── visual-regression.cy.ts ├── fixtures │ ├── audio.mp3 │ ├── audio.ogg │ ├── image-apng.png │ ├── image-small.png │ ├── image.bmp │ ├── image.gif │ ├── image.heic │ ├── image.ico │ ├── image.png │ ├── image.svg │ ├── image.webp │ ├── image1.jpg │ ├── image2.jpg │ ├── image3.jpg │ ├── image4.jpg │ ├── test-card.mp4 │ ├── test-card.png │ ├── video.mkv │ ├── video.ogv │ ├── video.webm │ ├── video1.mp4 │ └── video2.mp4 ├── snapshots │ └── base │ │ └── cypress │ │ └── e2e │ │ └── visual-regression.cy.ts │ │ ├── image.png │ │ ├── image2.png │ │ ├── non-dav.png │ │ └── video.png ├── support │ ├── commands.ts │ └── e2e.ts └── tsconfig.json ├── img ├── app.svg └── blank.mp4 ├── js ├── NcActionButton-qdAUHyGz.chunk.mjs ├── NcActionButton-qdAUHyGz.chunk.mjs.license ├── NcActionButton-qdAUHyGz.chunk.mjs.map ├── NcActionButton-qdAUHyGz.chunk.mjs.map.license ├── NcActionLink-TR7mwuor.chunk.mjs ├── NcActionLink-TR7mwuor.chunk.mjs.license ├── NcActionLink-TR7mwuor.chunk.mjs.map ├── NcActionLink-TR7mwuor.chunk.mjs.map.license ├── actionText-fFcUPi2g-gjw6zxAU.chunk.mjs ├── actionText-fFcUPi2g-gjw6zxAU.chunk.mjs.license ├── actionText-fFcUPi2g-gjw6zxAU.chunk.mjs.map ├── actionText-fFcUPi2g-gjw6zxAU.chunk.mjs.map.license ├── index-Dly6xalz.chunk.mjs.license ├── index-Dly6xalz.chunk.mjs.map.license ├── index-DtIMqdu8.chunk.mjs ├── index-DtIMqdu8.chunk.mjs.license ├── index-DtIMqdu8.chunk.mjs.map ├── index-DtIMqdu8.chunk.mjs.map.license ├── index.esm-CAkhAkGw.chunk.mjs ├── index.esm-CAkhAkGw.chunk.mjs.license ├── index.esm-CAkhAkGw.chunk.mjs.map ├── index.esm-CAkhAkGw.chunk.mjs.map.license ├── logger-Bw8oxZ_4.chunk.mjs ├── logger-Bw8oxZ_4.chunk.mjs.license ├── logger-Bw8oxZ_4.chunk.mjs.map ├── logger-Bw8oxZ_4.chunk.mjs.map.license ├── viewer-init.mjs ├── viewer-init.mjs.license ├── viewer-init.mjs.map ├── viewer-init.mjs.map.license ├── viewer-main.mjs ├── viewer-main.mjs.license ├── viewer-main.mjs.map └── viewer-main.mjs.map.license ├── l10n ├── .gitkeep ├── af.js ├── af.json ├── ar.js ├── ar.json ├── ast.js ├── ast.json ├── az.js ├── az.json ├── bg.js ├── bg.json ├── bn_BD.js ├── bn_BD.json ├── br.js ├── br.json ├── bs.js ├── bs.json ├── ca.js ├── ca.json ├── cs.js ├── cs.json ├── cy_GB.js ├── cy_GB.json ├── da.js ├── da.json ├── de.js ├── de.json ├── de_DE.js ├── de_DE.json ├── el.js ├── el.json ├── en_GB.js ├── en_GB.json ├── eo.js ├── eo.json ├── es.js ├── es.json ├── es_419.js ├── es_419.json ├── es_AR.js ├── es_AR.json ├── es_CL.js ├── es_CL.json ├── es_CO.js ├── es_CO.json ├── es_CR.js ├── es_CR.json ├── es_DO.js ├── es_DO.json ├── es_EC.js ├── es_EC.json ├── es_GT.js ├── es_GT.json ├── es_HN.js ├── es_HN.json ├── es_MX.js ├── es_MX.json ├── es_NI.js ├── es_NI.json ├── es_PA.js ├── es_PA.json ├── es_PE.js ├── es_PE.json ├── es_PR.js ├── es_PR.json ├── es_PY.js ├── es_PY.json ├── es_SV.js ├── es_SV.json ├── es_UY.js ├── es_UY.json ├── et_EE.js ├── et_EE.json ├── eu.js ├── eu.json ├── fa.js ├── fa.json ├── fi.js ├── fi.json ├── fr.js ├── fr.json ├── ga.js ├── ga.json ├── gd.js ├── gd.json ├── gl.js ├── gl.json ├── he.js ├── he.json ├── hr.js ├── hr.json ├── hu.js ├── hu.json ├── hy.js ├── hy.json ├── ia.js ├── ia.json ├── id.js ├── id.json ├── is.js ├── is.json ├── it.js ├── it.json ├── ja.js ├── ja.json ├── ka.js ├── ka.json ├── ka_GE.js ├── ka_GE.json ├── kab.js ├── kab.json ├── km.js ├── km.json ├── kn.js ├── kn.json ├── ko.js ├── ko.json ├── lb.js ├── lb.json ├── lo.js ├── lo.json ├── lt_LT.js ├── lt_LT.json ├── lv.js ├── lv.json ├── mk.js ├── mk.json ├── mn.js ├── mn.json ├── ms_MY.js ├── ms_MY.json ├── nb.js ├── nb.json ├── nl.js ├── nl.json ├── nn_NO.js ├── nn_NO.json ├── oc.js ├── oc.json ├── pl.js ├── pl.json ├── ps.js ├── ps.json ├── pt_BR.js ├── pt_BR.json ├── pt_PT.js ├── pt_PT.json ├── ro.js ├── ro.json ├── ru.js ├── ru.json ├── sc.js ├── sc.json ├── si.js ├── si.json ├── sk.js ├── sk.json ├── sl.js ├── sl.json ├── sq.js ├── sq.json ├── sr.js ├── sr.json ├── sr@latin.js ├── sr@latin.json ├── sv.js ├── sv.json ├── ta.js ├── ta.json ├── th.js ├── th.json ├── tk.js ├── tk.json ├── tr.js ├── tr.json ├── ug.js ├── ug.json ├── uk.js ├── uk.json ├── ur_PK.js ├── ur_PK.json ├── uz.js ├── uz.json ├── vi.js ├── vi.json ├── zh_CN.js ├── zh_CN.json ├── zh_HK.js ├── zh_HK.json ├── zh_TW.js └── zh_TW.json ├── lib ├── AppInfo │ └── Application.php ├── Event │ └── LoadViewer.php └── Listener │ └── LoadViewerScript.php ├── package-lock.json ├── package.json ├── psalm.xml ├── renovate.json ├── src ├── assets │ └── menu-sidebar-white.svg ├── components │ ├── Audios.vue │ ├── Error.vue │ ├── ImageEditor.vue │ ├── Images.vue │ └── Videos.vue ├── files_actions │ └── viewerAction.ts ├── global.d.ts ├── init.ts ├── main.js ├── mixins │ ├── Mime.js │ ├── Plyr.scss │ └── PreviewUrl.js ├── models │ ├── audios.js │ ├── editorTranslations.js │ ├── file.js │ ├── images.js │ └── videos.js ├── services │ ├── FileInfo.ts │ ├── FileList.ts │ ├── FileSortingConfig.ts │ ├── Viewer.js │ ├── WebdavClient.ts │ ├── logger.js │ └── mediaPreloader.ts ├── shims.d.ts ├── utils │ ├── CancelableRequest.js │ ├── canDownload.ts │ ├── fileUtils.ts │ ├── livePhotoUtils.ts │ ├── models.ts │ ├── numberUtil.ts │ └── previewUtils.ts └── views │ └── Viewer.vue ├── stylelint.config.cjs ├── tests └── psalm-baseline.xml ├── tsconfig.json └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = tab 8 | indent_size = 4 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "appName": true, 4 | "appVersion": true, 5 | "PLYR_ICONS": true, 6 | "oc_defaults": true, 7 | "__dirname": true 8 | }, 9 | "extends": [ 10 | "@nextcloud/eslint-config/typescript" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | /js/* binary 4 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | /appinfo/info.xml @skjnldsv @szaimen 2 | 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | custom: https://nextcloud.com/include/ 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 0. Needs triage, bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Browser log** 38 | ``` 39 | Open your console, reload your page and/or do the action leading to this issue and copy/paste the log in this thread. 40 | ``` 41 | 42 |
43 | How to access your browser console (Click to expand) 44 | 45 | # Chrome 46 | - Press either CTRL + SHIFT + J to open the “console” tab of the Developer Tools. 47 | - Alternative method: 48 | 1. Press either CTRL + SHIFT + I or F12 to open the Developer Tools. 49 | 2. Click the “console” tab. 50 | 51 | # Safari 52 | - Press CMD + ALT + I to open the Web Inspector. 53 | - See Chrome’s step 2. (Chrome and Safari have pretty much identical dev tools.) 54 | 55 | # IE9 56 | 1. Press F12 to open the developer tools. 57 | 2. Click the “console” tab. 58 | 59 | # Firefox 60 | - Press CTRL + SHIFT + K to open the Web console (COMMAND + SHIFT + K on Macs). 61 | - or, if Firebug is installed (recommended): 62 | 1. Press F12 to open Firebug. 63 | 2. Click on the “console” tab. 64 | 65 | # Opera 66 | 1. Press CTRL + SHIFT + I to open Dragonfly. 67 | 2. Click on the “console” tab. 68 |
69 | 70 | **Additional context** 71 | Add any other context about the problem here. 72 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Image editor feature request 4 | url: https://github.com/scaleflex/filerobot-image-editor/issues 5 | about: Please open an issue in this repository directly 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 0. Needs triage, enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/mime_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: File support request 3 | about: Request support for a file type currently not supported 4 | title: Add support for xxx files 5 | labels: enhancement, 0. Needs triage, file support request 6 | assignees: '' 7 | 8 | --- 9 | 10 | **What file type** 11 | e.g. image/jpeg 12 | 13 | **What application is using it** 14 | e.g. Gimp 15 | 16 | **Please attach a sample file here** (or a direct external link to one) 17 | [jpeg sample file](https://upload.wikimedia.org/wikipedia/commons/0/0e/Felis_silvestris_silvestris.jpg) 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | version: 2 4 | updates: 5 | - package-ecosystem: github-actions 6 | directory: "/" 7 | schedule: 8 | interval: daily 9 | timezone: Europe/Paris 10 | labels: 11 | - "3. to review" 12 | - "dependencies" 13 | 14 | - package-ecosystem: composer 15 | directory: "/" 16 | schedule: 17 | interval: weekly 18 | day: saturday 19 | time: "03:00" 20 | timezone: Europe/Paris 21 | open-pull-requests-limit: 10 22 | labels: 23 | - "3. to review" 24 | - "dependencies" 25 | -------------------------------------------------------------------------------- /.github/workflows/block-merge-freeze.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Block merges during freezes 10 | 11 | on: 12 | pull_request: 13 | types: [opened, ready_for_review, reopened, synchronize] 14 | 15 | permissions: 16 | contents: read 17 | 18 | concurrency: 19 | group: block-merge-freeze-${{ github.head_ref || github.run_id }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | block-merges-during-freeze: 24 | name: Block merges during freezes 25 | 26 | if: github.event.pull_request.draft == false 27 | 28 | runs-on: ubuntu-latest-low 29 | 30 | steps: 31 | - name: Register server reference to fallback to master branch 32 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 33 | with: 34 | github-token: ${{secrets.GITHUB_TOKEN}} 35 | script: | 36 | const baseRef = context.payload.pull_request.base.ref 37 | if (baseRef === 'main' || baseRef === 'master') { 38 | core.exportVariable('server_ref', 'master'); 39 | console.log('Setting server_ref to master'); 40 | } else { 41 | const regex = /^stable(\d+)$/ 42 | const match = baseRef.match(regex) 43 | if (match) { 44 | core.exportVariable('server_ref', match[0]); 45 | console.log('Setting server_ref to ' + match[0]); 46 | } else { 47 | console.log('Not based on master/main/stable*, so skipping freeze check'); 48 | } 49 | } 50 | 51 | - name: Download version.php from ${{ env.server_ref }} 52 | if: ${{ env.server_ref != '' }} 53 | run: curl 'https://raw.githubusercontent.com/nextcloud/server/${{ env.server_ref }}/version.php' --output version.php 54 | 55 | - name: Run check 56 | if: ${{ env.server_ref != '' }} 57 | run: cat version.php | grep 'OC_VersionString' | grep -i -v 'RC' 58 | -------------------------------------------------------------------------------- /.github/workflows/block-unconventional-commits.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Block unconventional commits 10 | 11 | on: 12 | pull_request: 13 | types: [opened, ready_for_review, reopened, synchronize] 14 | 15 | permissions: 16 | contents: read 17 | 18 | concurrency: 19 | group: block-unconventional-commits-${{ github.head_ref || github.run_id }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | block-unconventional-commits: 24 | name: Block unconventional commits 25 | 26 | runs-on: ubuntu-latest-low 27 | 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 31 | with: 32 | persist-credentials: false 33 | 34 | - uses: webiny/action-conventional-commits@8bc41ff4e7d423d56fa4905f6ff79209a78776c7 # v1.3.0 35 | with: 36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 37 | -------------------------------------------------------------------------------- /.github/workflows/cypress-snapshot-update.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: MIT 3 | name: Cypress snapshot update 4 | 5 | on: 6 | workflow_dispatch: 7 | schedule: 8 | # At 2:30 on Sundays 9 | - cron: '20 1 * * 0' 10 | 11 | jobs: 12 | update: 13 | runs-on: ubuntu-latest 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | branches: ["master", "stable30", "stable31"] 19 | 20 | name: cypress-snapshot-update-${{ matrix.branches }} 21 | 22 | steps: 23 | - name: Checkout app 24 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 25 | with: 26 | ref: ${{ matrix.branches }} 27 | 28 | - name: Read package.json node and npm engines version 29 | uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 30 | id: versions 31 | with: 32 | fallbackNode: "^20" 33 | fallbackNpm: "^10" 34 | 35 | - name: Set up node ${{ steps.versions.outputs.nodeVersion }} 36 | uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 37 | with: 38 | node-version: ${{ steps.versions.outputs.nodeVersion }} 39 | 40 | - name: Set up npm ${{ steps.versions.outputs.npmVersion }} 41 | run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}' 42 | 43 | - name: Install node dependencies & build app 44 | run: | 45 | npm ci 46 | npm run build --if-present 47 | 48 | - name: Snapshot update 49 | run: npm run cypress:update-snapshots 50 | 51 | - name: Create Pull Request 52 | if: always() 53 | uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v5 54 | with: 55 | token: ${{ secrets.COMMAND_BOT_PAT }} 56 | commit-message: "chore(deps): cypress snapshot update" 57 | committer: GitHub 58 | author: nextcloud-command 59 | signoff: true 60 | branch: automated/noid/${{ matrix.branches }}-cypress-snapshot-update 61 | title: "[${{ matrix.branches }}] Update cypress snapshots" 62 | body: | 63 | Auto-generated update of cypress snapshots 64 | labels: | 65 | dependencies 66 | 3. to review 67 | add-paths: | 68 | cypress/snapshots 69 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-approve-merge.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Dependabot 10 | 11 | on: 12 | pull_request_target: # zizmor: ignore[dangerous-triggers] 13 | branches: 14 | - main 15 | - master 16 | - stable* 17 | 18 | permissions: 19 | contents: read 20 | 21 | concurrency: 22 | group: dependabot-approve-merge-${{ github.head_ref || github.run_id }} 23 | cancel-in-progress: true 24 | 25 | jobs: 26 | auto-approve-merge: 27 | if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'renovate[bot]' 28 | runs-on: ubuntu-latest-low 29 | permissions: 30 | # for hmarr/auto-approve-action to approve PRs 31 | pull-requests: write 32 | 33 | steps: 34 | - name: Disabled on forks 35 | if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} 36 | run: | 37 | echo 'Can not approve PRs from forks' 38 | exit 1 39 | 40 | # GitHub actions bot approve 41 | - uses: hmarr/auto-approve-action@b40d6c9ed2fa10c9a2749eca7eb004418a705501 # v2 42 | with: 43 | github-token: ${{ secrets.GITHUB_TOKEN }} 44 | 45 | # Nextcloud bot approve and merge request 46 | - uses: ahmadnassri/action-dependabot-auto-merge@45fc124d949b19b6b8bf6645b6c9d55f4f9ac61a # v2 47 | with: 48 | target: minor 49 | github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }} 50 | -------------------------------------------------------------------------------- /.github/workflows/fixup.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Block fixup and squash commits 10 | 11 | on: 12 | pull_request: 13 | types: [opened, ready_for_review, reopened, synchronize] 14 | 15 | permissions: 16 | contents: read 17 | 18 | concurrency: 19 | group: fixup-${{ github.head_ref || github.run_id }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | commit-message-check: 24 | if: github.event.pull_request.draft == false 25 | 26 | permissions: 27 | pull-requests: write 28 | name: Block fixup and squash commits 29 | 30 | runs-on: ubuntu-latest-low 31 | 32 | steps: 33 | - name: Run check 34 | uses: skjnldsv/block-fixup-merge-action@c138ea99e45e186567b64cf065ce90f7158c236a # v2 35 | with: 36 | repo-token: ${{ secrets.GITHUB_TOKEN }} 37 | -------------------------------------------------------------------------------- /.github/workflows/lint-php-cs.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Lint php-cs 10 | 11 | on: pull_request 12 | 13 | permissions: 14 | contents: read 15 | 16 | concurrency: 17 | group: lint-php-cs-${{ github.head_ref || github.run_id }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | lint: 22 | runs-on: ubuntu-latest 23 | 24 | name: php-cs 25 | 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | with: 30 | persist-credentials: false 31 | 32 | - name: Get php version 33 | id: versions 34 | uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 35 | 36 | - name: Set up php${{ steps.versions.outputs.php-min }} 37 | uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1 38 | with: 39 | php-version: ${{ steps.versions.outputs.php-min }} 40 | extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite 41 | coverage: none 42 | ini-file: development 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | - name: Install dependencies 47 | run: | 48 | composer remove nextcloud/ocp --dev 49 | composer i 50 | 51 | - name: Lint 52 | run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 ) 53 | -------------------------------------------------------------------------------- /.github/workflows/lint-php.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Lint php 10 | 11 | on: pull_request 12 | 13 | permissions: 14 | contents: read 15 | 16 | concurrency: 17 | group: lint-php-${{ github.head_ref || github.run_id }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | matrix: 22 | runs-on: ubuntu-latest-low 23 | outputs: 24 | php-versions: ${{ steps.versions.outputs.php-versions }} 25 | steps: 26 | - name: Checkout app 27 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 28 | with: 29 | persist-credentials: false 30 | 31 | - name: Get version matrix 32 | id: versions 33 | uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.0.0 34 | 35 | php-lint: 36 | runs-on: ubuntu-latest 37 | needs: matrix 38 | strategy: 39 | matrix: 40 | php-versions: ${{fromJson(needs.matrix.outputs.php-versions)}} 41 | 42 | name: php-lint 43 | 44 | steps: 45 | - name: Checkout 46 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 47 | with: 48 | persist-credentials: false 49 | 50 | - name: Set up php ${{ matrix.php-versions }} 51 | uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1 52 | with: 53 | php-version: ${{ matrix.php-versions }} 54 | extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite 55 | coverage: none 56 | ini-file: development 57 | env: 58 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 59 | 60 | - name: Lint 61 | run: composer run lint 62 | 63 | summary: 64 | permissions: 65 | contents: none 66 | runs-on: ubuntu-latest-low 67 | needs: php-lint 68 | 69 | if: always() 70 | 71 | name: php-lint-summary 72 | 73 | steps: 74 | - name: Summary status 75 | run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi 76 | -------------------------------------------------------------------------------- /.github/workflows/lint-stylelint.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Lint stylelint 10 | 11 | on: pull_request 12 | 13 | permissions: 14 | contents: read 15 | 16 | concurrency: 17 | group: lint-stylelint-${{ github.head_ref || github.run_id }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | lint: 22 | runs-on: ubuntu-latest 23 | 24 | name: stylelint 25 | 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | with: 30 | persist-credentials: false 31 | 32 | - name: Read package.json node and npm engines version 33 | uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 34 | id: versions 35 | with: 36 | fallbackNode: '^20' 37 | fallbackNpm: '^10' 38 | 39 | - name: Set up node ${{ steps.versions.outputs.nodeVersion }} 40 | uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 41 | with: 42 | node-version: ${{ steps.versions.outputs.nodeVersion }} 43 | 44 | - name: Set up npm ${{ steps.versions.outputs.npmVersion }} 45 | run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}' 46 | 47 | - name: Install dependencies 48 | env: 49 | CYPRESS_INSTALL_BINARY: 0 50 | run: npm ci 51 | 52 | - name: Lint 53 | run: npm run stylelint 54 | -------------------------------------------------------------------------------- /.github/workflows/psalm.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Static analysis 10 | 11 | on: pull_request 12 | 13 | concurrency: 14 | group: psalm-${{ github.head_ref || github.run_id }} 15 | cancel-in-progress: true 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: 21 | static-analysis: 22 | runs-on: ubuntu-latest 23 | 24 | name: static-psalm-analysis 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 28 | with: 29 | persist-credentials: false 30 | 31 | - name: Get php version 32 | id: versions 33 | uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 34 | 35 | - name: Check enforcement of minimum PHP version ${{ steps.versions.outputs.php-min }} in psalm.xml 36 | run: grep 'phpVersion="${{ steps.versions.outputs.php-min }}' psalm.xml 37 | 38 | - name: Set up php${{ steps.versions.outputs.php-available }} 39 | uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1 40 | with: 41 | php-version: ${{ steps.versions.outputs.php-available }} 42 | extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite 43 | coverage: none 44 | ini-file: development 45 | # Temporary workaround for missing pcntl_* in PHP 8.3 46 | ini-values: disable_functions= 47 | env: 48 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 49 | 50 | - name: Install dependencies 51 | run: | 52 | composer remove nextcloud/ocp --dev 53 | composer i 54 | 55 | - name: Install nextcloud/ocp 56 | run: composer require --dev nextcloud/ocp:dev-${{ steps.versions.outputs.branches-max }} --ignore-platform-reqs --with-dependencies 57 | 58 | - name: Run coding standards check 59 | run: composer run psalm -- --threads=1 --monochrome --no-progress --output-format=github 60 | -------------------------------------------------------------------------------- /.github/workflows/reuse.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | # SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. 7 | # 8 | # SPDX-License-Identifier: CC0-1.0 9 | 10 | name: REUSE Compliance Check 11 | 12 | on: [pull_request] 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | reuse-compliance-check: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 23 | with: 24 | persist-credentials: false 25 | 26 | - name: REUSE Compliance Check 27 | uses: fsfe/reuse-action@bb774aa972c2a89ff34781233d275075cbddf542 # v5.0.0 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | css/fonts/ 4 | 5 | .DS_Store 6 | node_modules/ 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | 19 | .marginalia 20 | 21 | build/ 22 | coverage/ 23 | 24 | vendor 25 | .php_cs.cache 26 | 27 | # Cypress files 28 | js/*roboto* 29 | cypress/downloads 30 | cypress/screenshots 31 | cypress/snapshots 32 | cypress/videos 33 | cypress/snapshots/actual 34 | cypress/snapshots/diff 35 | 36 | # RelativeCI webpack bundle stats 37 | webpack-stats.json 38 | *.orig 39 | -------------------------------------------------------------------------------- /.l10nignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | js/ 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | node_modules -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | getFinder() 17 | ->notPath('build') 18 | ->notPath('l10n') 19 | ->notPath('src') 20 | ->notPath('vendor') 21 | ->notPath('composer') 22 | ->in(__DIR__); 23 | return $config; 24 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | src/assets -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | lang_map = fi_FI: fi, hu_HU: hu, nb_NO: nb, sk_SK: sk, th_TH: th, ja_JP: ja, bg_BG: bg, cs_CZ: cs 4 | 5 | [o:nextcloud:p:nextcloud:r:viewer] 6 | file_filter = translationfiles//viewer.po 7 | source_file = translationfiles/templates/viewer.pot 8 | source_lang = en 9 | type = PO 10 | 11 | -------------------------------------------------------------------------------- /LICENSES/BSD-3-Clause.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) . 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /LICENSES/ISC.txt: -------------------------------------------------------------------------------- 1 | ISC License: 2 | 3 | Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") 4 | Copyright (c) 1995-2003 by Internet Software Consortium 5 | 6 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 9 | -------------------------------------------------------------------------------- /LICENSES/LicenseRef-NextcloudTrademarks.txt: -------------------------------------------------------------------------------- 1 | The Nextcloud marks 2 | Nextcloud and the Nextcloud logo is a registered trademark of Nextcloud GmbH in Germany and/or other countries. 3 | These guidelines cover the following marks pertaining both to the product names and the logo: “Nextcloud” 4 | and the blue/white cloud logo with or without the word Nextcloud; the service “Nextcloud Enterprise”; 5 | and our products: “Nextcloud Files”; “Nextcloud Groupware” and “Nextcloud Talk”. 6 | This set of marks is collectively referred to as the “Nextcloud marks.” 7 | 8 | Use of Nextcloud logos and other marks is only permitted under the guidelines provided by the Nextcloud GmbH. 9 | A copy can be found at https://nextcloud.com/trademarks/ 10 | -------------------------------------------------------------------------------- /LICENSES/LicenseRef-Unsplash.txt: -------------------------------------------------------------------------------- 1 | License 2 | 3 | Unsplash visuals are made to be used freely. Our license reflects that. 4 | 5 | * All images can be downloaded and used for free 6 | * Commercial and non-commercial purposes 7 | * No permission needed (though attribution is appreciated!) 8 | 9 | What is not permitted 👎 10 | 11 | * Images cannot be sold without significant modification. 12 | * Compiling images from Unsplash to replicate a similar or competing service. 13 | 14 | 15 | Longform 16 | 17 | Unsplash grants you an irrevocable, nonexclusive, worldwide copyright license to download, copy, modify, distribute, perform, and use images from Unsplash for free, including for commercial purposes, without permission from or attributing the photographer or Unsplash. This license does not include the right to compile images from Unsplash to replicate a similar or competing service. 18 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /appinfo/info.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 8 | viewer 9 | Viewer 10 | Simple file viewer with slideshow for media 11 | 12 | 5.0.0-dev.0 13 | agpl 14 | John Molakvoæ 15 | Viewer 16 | tools 17 | https://github.com/nextcloud/viewer 18 | https://raw.githubusercontent.com/nextcloud/screenshots/master/apps/Viewer/viewer.png 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextcloud/viewer", 3 | "config": { 4 | "optimize-autoloader": true, 5 | "classmap-authoritative": true, 6 | "platform": { 7 | "php": "8.1" 8 | } 9 | }, 10 | "scripts": { 11 | "cs:fix": "php-cs-fixer fix", 12 | "cs:check": "php-cs-fixer fix --dry-run --diff", 13 | "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './composer/*' -print0 | xargs -0 -n1 php -l", 14 | "psalm": "psalm --threads=1", 15 | "psalm:update-baseline": "psalm --threads=1 --update-baseline", 16 | "psalm:clear": "psalm --clear-cache && psalm --clear-global-cache", 17 | "psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType" 18 | }, 19 | "require-dev": { 20 | "nextcloud/coding-standard": "^1.2.0", 21 | "phpunit/phpunit": "^9", 22 | "vimeo/psalm": "^5.25.0", 23 | "nextcloud/ocp": "dev-master" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /composer/autoload.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/composer/InstalledVersions.php', 10 | 'OCA\\Viewer\\AppInfo\\Application' => $baseDir . '/lib/AppInfo/Application.php', 11 | 'OCA\\Viewer\\Event\\LoadViewer' => $baseDir . '/lib/Event/LoadViewer.php', 12 | 'OCA\\Viewer\\Listener\\LoadViewerScript' => $baseDir . '/lib/Listener/LoadViewerScript.php', 13 | ); 14 | -------------------------------------------------------------------------------- /composer/composer/autoload_namespaces.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/lib'), 10 | ); 11 | -------------------------------------------------------------------------------- /composer/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | setClassMapAuthoritative(true); 33 | $loader->register(true); 34 | 35 | return $loader; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /composer/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | 11 | array ( 12 | 'OCA\\Viewer\\' => 11, 13 | ), 14 | ); 15 | 16 | public static $prefixDirsPsr4 = array ( 17 | 'OCA\\Viewer\\' => 18 | array ( 19 | 0 => __DIR__ . '/../..' . '/lib', 20 | ), 21 | ); 22 | 23 | public static $classMap = array ( 24 | 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 25 | 'OCA\\Viewer\\AppInfo\\Application' => __DIR__ . '/../..' . '/lib/AppInfo/Application.php', 26 | 'OCA\\Viewer\\Event\\LoadViewer' => __DIR__ . '/../..' . '/lib/Event/LoadViewer.php', 27 | 'OCA\\Viewer\\Listener\\LoadViewerScript' => __DIR__ . '/../..' . '/lib/Listener/LoadViewerScript.php', 28 | ); 29 | 30 | public static function getInitializer(ClassLoader $loader) 31 | { 32 | return \Closure::bind(function () use ($loader) { 33 | $loader->prefixLengthsPsr4 = ComposerStaticInitViewer::$prefixLengthsPsr4; 34 | $loader->prefixDirsPsr4 = ComposerStaticInitViewer::$prefixDirsPsr4; 35 | $loader->classMap = ComposerStaticInitViewer::$classMap; 36 | 37 | }, null, ClassLoader::class); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /css/NcActionButton-DndYZcrz.chunk.css: -------------------------------------------------------------------------------- 1 | .material-design-icon[data-v-02eeec54]{display:flex;align-self:center;justify-self:center;align-items:center;justify-content:center}li.action[data-v-02eeec54]:hover,li.action.active[data-v-02eeec54]{border-radius:6px;padding:0}li.action[data-v-02eeec54]:hover{background-color:var(--color-background-hover)}.action--disabled[data-v-02eeec54]{pointer-events:none;opacity:.5}.action--disabled[data-v-02eeec54]:hover,.action--disabled[data-v-02eeec54]:focus{cursor:default;opacity:.5}.action--disabled *[data-v-02eeec54]{opacity:1!important}.action-button[data-v-02eeec54]{display:flex;align-items:flex-start;width:100%;height:auto;margin:0;padding:0;padding-inline-end:calc((var(--default-clickable-area) - 16px) / 2);box-sizing:border-box;cursor:pointer;white-space:nowrap;color:var(--color-main-text);border:0;border-radius:0;background-color:transparent;box-shadow:none;font-weight:400;font-size:var(--default-font-size);line-height:var(--default-clickable-area)}.action-button>span[data-v-02eeec54]{cursor:pointer;white-space:nowrap}.action-button__icon[data-v-02eeec54]{width:var(--default-clickable-area);height:var(--default-clickable-area);opacity:1;background-position:calc((var(--default-clickable-area) - 16px) / 2) center;background-size:16px;background-repeat:no-repeat}.action-button[data-v-02eeec54] .material-design-icon{width:var(--default-clickable-area);height:var(--default-clickable-area);opacity:1}.action-button[data-v-02eeec54] .material-design-icon .material-design-icon__svg{vertical-align:middle}.action-button__longtext-wrapper[data-v-02eeec54],.action-button__longtext[data-v-02eeec54]{max-width:220px;line-height:1.6em;padding:calc((var(--default-clickable-area) - 1.6em) / 2) 0;cursor:pointer;text-align:start;overflow:hidden;text-overflow:ellipsis}.action-button__longtext[data-v-02eeec54]{cursor:pointer;white-space:pre-wrap!important}.action-button__name[data-v-02eeec54]{font-weight:700;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;max-width:100%;display:block}.action-button__description[data-v-02eeec54]{display:block;white-space:pre-wrap;font-size:var(--font-size-small);line-height:var(--default-line-height);color:var(--color-text-maxcontrast);cursor:pointer}.action-button__menu-icon[data-v-02eeec54],.action-button__pressed-icon[data-v-02eeec54]{margin-inline:auto calc((var(--default-clickable-area) - 16px) / 2 * -1)} 2 | -------------------------------------------------------------------------------- /css/NcActionLink-Cay-IPuV.chunk.css: -------------------------------------------------------------------------------- 1 | .material-design-icon[data-v-30c015f0]{display:flex;align-self:center;justify-self:center;align-items:center;justify-content:center}li.action[data-v-30c015f0]:hover,li.action.active[data-v-30c015f0]{border-radius:6px;padding:0}li.action[data-v-30c015f0]:hover{background-color:var(--color-background-hover)}.action-link[data-v-30c015f0]{display:flex;align-items:flex-start;width:100%;height:auto;margin:0;padding:0;padding-inline-end:calc((var(--default-clickable-area) - 16px) / 2);box-sizing:border-box;cursor:pointer;white-space:nowrap;color:var(--color-main-text);border:0;border-radius:0;background-color:transparent;box-shadow:none;font-weight:400;font-size:var(--default-font-size);line-height:var(--default-clickable-area)}.action-link>span[data-v-30c015f0]{cursor:pointer;white-space:nowrap}.action-link__icon[data-v-30c015f0]{width:var(--default-clickable-area);height:var(--default-clickable-area);opacity:1;background-position:calc((var(--default-clickable-area) - 16px) / 2) center;background-size:16px;background-repeat:no-repeat}.action-link[data-v-30c015f0] .material-design-icon{width:var(--default-clickable-area);height:var(--default-clickable-area);opacity:1}.action-link[data-v-30c015f0] .material-design-icon .material-design-icon__svg{vertical-align:middle}.action-link__longtext-wrapper[data-v-30c015f0],.action-link__longtext[data-v-30c015f0]{max-width:220px;line-height:1.6em;padding:calc((var(--default-clickable-area) - 1.6em) / 2) 0;cursor:pointer;text-align:start;overflow:hidden;text-overflow:ellipsis}.action-link__longtext[data-v-30c015f0]{cursor:pointer;white-space:pre-wrap!important}.action-link__name[data-v-30c015f0]{font-weight:700;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;max-width:100%;display:block}.action-link__description[data-v-30c015f0]{display:block;white-space:pre-wrap;font-size:var(--font-size-small);line-height:var(--default-line-height);color:var(--color-text-maxcontrast);cursor:pointer}.action-link__menu-icon[data-v-30c015f0]{margin-inline:auto calc((var(--default-clickable-area) - 16px) / 2 * -1)} 2 | -------------------------------------------------------------------------------- /css/viewer-init.css: -------------------------------------------------------------------------------- 1 | /* extracted by css-entry-points-plugin */ 2 | @import './init-BcY_9rzn.chunk.css'; 3 | @import './logger-60RCWKf0.chunk.css'; 4 | @import './NcActionButton-DndYZcrz.chunk.css'; 5 | @import './NcActionLink-Cay-IPuV.chunk.css'; -------------------------------------------------------------------------------- /css/viewer-main.css: -------------------------------------------------------------------------------- 1 | /* extracted by css-entry-points-plugin */ 2 | @import './main-BwzbmUGl.chunk.css'; 3 | @import './logger-60RCWKf0.chunk.css'; -------------------------------------------------------------------------------- /cypress/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "cypress/globals": true 4 | }, 5 | "plugins": [ 6 | "cypress" 7 | ], 8 | "extends": [ 9 | "plugin:cypress/recommended" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /cypress/e2e/actions/delete.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | describe('Delete image.png in viewer', function() { 7 | before(function() { 8 | // Init user 9 | cy.createRandomUser().then(user => { 10 | // Upload test files 11 | cy.uploadFile(user, 'image.png', 'image/png') 12 | 13 | // Visit nextcloud 14 | cy.login(user) 15 | cy.visit('/apps/files') 16 | }) 17 | }) 18 | after(function() { 19 | cy.logout() 20 | }) 21 | 22 | it('See image.png in the list', function() { 23 | cy.getFile('image.png', { timeout: 10000 }) 24 | .should('contain', 'image .png') 25 | }) 26 | 27 | it('Open the viewer on file click', function() { 28 | cy.openFile('image.png') 29 | cy.get('body > .viewer').should('be.visible') 30 | }) 31 | 32 | it('Does not see a loading animation', function() { 33 | cy.get('body > .viewer', { timeout: 10000 }) 34 | .should('be.visible') 35 | .and('have.class', 'modal-mask') 36 | .and('not.have.class', 'icon-loading') 37 | }) 38 | 39 | it('Delete the image and close viewer', function() { 40 | // open the menu 41 | cy.get('body > .viewer .modal-header button.action-item__menutoggle').click() 42 | // delete the file 43 | cy.get('.action-button:contains(\'Delete\')').click() 44 | }) 45 | 46 | it('Does not see the viewer anymore', function() { 47 | cy.get('body > .viewer', { timeout: 10000 }) 48 | .should('not.exist') 49 | }) 50 | 51 | it('Does not see image.png in the list anymore', function() { 52 | cy.visit('/apps/files') 53 | cy.getFile('image.png', { timeout: 10000 }) 54 | .should('not.exist') 55 | }) 56 | }) 57 | -------------------------------------------------------------------------------- /cypress/e2e/actions/download.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import * as path from 'path' 7 | 8 | const fileName = 'image.png' 9 | 10 | describe(`Download ${fileName} in viewer`, function() { 11 | before(function() { 12 | // Init user 13 | cy.createRandomUser().then(user => { 14 | // Upload test files 15 | cy.uploadFile(user, fileName, 'image/png') 16 | 17 | // Visit nextcloud 18 | cy.login(user) 19 | cy.visit('/apps/files') 20 | }) 21 | }) 22 | 23 | after(function() { 24 | cy.logout() 25 | }) 26 | 27 | it(`See "${fileName}" in the list`, function() { 28 | cy.getFile(fileName, { timeout: 10000 }) 29 | .should('contain', fileName.replace(/(.*)\./, '$1 .')) 30 | }) 31 | 32 | it('Open the viewer on file click', function() { 33 | cy.openFile(fileName) 34 | cy.get('body > .viewer').should('be.visible') 35 | }) 36 | 37 | it('Does not see a loading animation', function() { 38 | cy.get('body > .viewer', { timeout: 10000 }) 39 | .should('be.visible') 40 | .and('have.class', 'modal-mask') 41 | .and('not.have.class', 'icon-loading') 42 | }) 43 | 44 | it('Download the image', function() { 45 | // open the menu 46 | cy.get('body > .viewer .modal-header button.action-item__menutoggle').click() 47 | // download the file 48 | cy.get('.action-link .download-icon').click() 49 | }) 50 | 51 | it('Compare downloaded file with asset by size', function() { 52 | const downloadsFolder = Cypress.config('downloadsFolder') 53 | const fixturesFolder = Cypress.config('fixturesFolder') 54 | 55 | const downloadedFilePath = path.join(downloadsFolder, fileName) 56 | const fixtureFilePath = path.join(fixturesFolder, fileName) 57 | 58 | cy.readFile(fixtureFilePath, 'binary', { timeout: 5000 }).then(fixtureBuffer => { 59 | cy.readFile(downloadedFilePath, 'binary', { timeout: 5000 }) 60 | .should(downloadedBuffer => { 61 | if (downloadedBuffer.length !== fixtureBuffer.length) { 62 | throw new Error(`File size ${downloadedBuffer.length} is not ${fixtureBuffer.length}`) 63 | } 64 | }) 65 | }) 66 | }) 67 | }) 68 | -------------------------------------------------------------------------------- /cypress/e2e/audios/audio.mpeg.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import audioTest from '../mixins/audio' 7 | 8 | describe('Open audio.mp3 in viewer', function() { 9 | audioTest('audio.mp3', 'audio/mpeg') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/audios/audio.ogg.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import audioTest from '../mixins/audio' 6 | 7 | describe('Open audio.ogg in viewer', function() { 8 | audioTest('audio.ogg', 'audio/ogg') 9 | }) 10 | -------------------------------------------------------------------------------- /cypress/e2e/download-forbidden.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import type { User } from '@nextcloud/cypress' 7 | import { ShareType } from '@nextcloud/sharing' 8 | 9 | describe('Disable download button if forbidden', { testIsolation: true }, () => { 10 | let sharee: User 11 | 12 | before(() => { 13 | cy.createRandomUser().then((user) => { sharee = user }) 14 | cy.createRandomUser().then((user) => { 15 | // Upload test files 16 | cy.createFolder(user, '/Photos') 17 | cy.uploadFile(user, 'image1.jpg', 'image/jpeg', '/Photos/image1.jpg') 18 | 19 | cy.login(user) 20 | cy.createShare('/Photos', 21 | { shareWith: sharee.userId, shareType: ShareType.User, attributes: [{ scope: 'permissions', key: 'download', value: false }] }, 22 | ) 23 | cy.logout() 24 | }) 25 | }) 26 | 27 | beforeEach(() => { 28 | cy.login(sharee) 29 | cy.visit('/apps/files') 30 | cy.openFile('Photos') 31 | }) 32 | 33 | it('See the shared folder and images in files list', () => { 34 | cy.getFile('image1.jpg', { timeout: 10000 }) 35 | .should('contain', 'image1 .jpg') 36 | }) 37 | 38 | // TODO: Fix no-download files on server 39 | it.skip('See the image can be shown', () => { 40 | cy.getFile('image1.jpg').should('be.visible') 41 | cy.openFile('image1.jpg') 42 | cy.get('body > .viewer').should('be.visible') 43 | 44 | cy.get('body > .viewer', { timeout: 10000 }) 45 | .should('be.visible') 46 | .and('have.class', 'modal-mask') 47 | .and('not.have.class', 'icon-loading') 48 | }) 49 | 50 | it('See the title on the viewer header but not the Download nor the menu button', () => { 51 | cy.getFile('image1.jpg').should('be.visible') 52 | cy.openFile('image1.jpg') 53 | cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') 54 | 55 | cy.get('[role="dialog"]') 56 | .should('be.visible') 57 | .find('button[aria-label="Actions"]') 58 | .click() 59 | 60 | cy.get('[role="menu"]:visible') 61 | .find('button') 62 | .should('have.length', 2) 63 | .each(($el) => { 64 | expect($el.text()).to.match(/(Full screen|Open sidebar)/i) 65 | }) 66 | }) 67 | }) 68 | -------------------------------------------------------------------------------- /cypress/e2e/files.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import { User } from '@nextcloud/cypress' 7 | 8 | describe('Files default view', function() { 9 | const user = new User('admin', 'admin') 10 | 11 | before(function() { 12 | cy.login(user) 13 | }) 14 | 15 | after(function() { 16 | cy.logout() 17 | }) 18 | 19 | it('See the default files list', function() { 20 | cy.visit('/apps/files') 21 | cy.getFile('welcome.txt').should('contain', 'welcome .txt') 22 | }) 23 | 24 | it('Take screenshot', function() { 25 | cy.screenshot() 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /cypress/e2e/images/image-apng.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import imageTest from '../mixins/image' 7 | 8 | describe('Open image-apng.png in viewer', function() { 9 | imageTest('image-apng.png', 'image/png') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/images/image-small.png.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import imageTest from '../mixins/image' 7 | 8 | describe('Open image-small.png in viewer', function() { 9 | imageTest('image-small.png', 'image/png') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/images/image.gif.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import imageTest from '../mixins/image' 6 | 7 | describe('Open image.gif in viewer', function() { 8 | imageTest('image.gif', 'image/gif', '/remote.php/dav/files') 9 | }) 10 | -------------------------------------------------------------------------------- /cypress/e2e/images/image.ico.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import imageTest from '../mixins/image' 7 | 8 | describe('Open image.ico in viewer', function() { 9 | imageTest('image.ico', 'image/x-icon', '/remote.php/dav/files') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/images/image.png.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import imageTest from '../mixins/image' 7 | 8 | describe('Open image.png in viewer', function() { 9 | imageTest('image.png', 'image/png') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/images/image.svg.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import imageTest from '../mixins/image' 7 | 8 | describe('Open image.svg in viewer', function() { 9 | imageTest('image.svg', 'image/svg+xml', 'data:image/svg+xml;base64') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/images/image.webp.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import imageTest from '../mixins/image' 7 | 8 | describe('Open image.webp in viewer', function() { 9 | imageTest('image.webp', 'image/webp') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/mixins/audio.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | /** 7 | * Generate an audio cypress test 8 | * 9 | * @param {string} fileName the audio to upload and test against 10 | * @param {string} mimeType the audio mime type 11 | */ 12 | export default function(fileName = 'audio.ogg', mimeType = 'audio/ogg') { 13 | let randUser 14 | 15 | before(function() { 16 | // Init user 17 | cy.createRandomUser().then(user => { 18 | randUser = user 19 | 20 | // Upload test files 21 | cy.uploadFile(user, fileName, mimeType) 22 | 23 | // Visit nextcloud 24 | cy.login(user) 25 | cy.visit('/apps/files') 26 | }) 27 | }) 28 | after(function() { 29 | cy.logout() 30 | }) 31 | 32 | it(`See ${fileName} in the list`, function() { 33 | cy.getFile(fileName, { timeout: 10000 }) 34 | .should('contain', fileName.replace(/(.*)\./, '$1 .')) 35 | }) 36 | 37 | it('Open the viewer on file click and wait for loading to end', function() { 38 | // Match audio request 39 | cy.intercept('GET', `/remote.php/dav/files/${randUser.userId}/${fileName}`).as('source') 40 | 41 | // Open the file and check Viewer existence 42 | cy.openFile(fileName) 43 | cy.get('body > .viewer').should('be.visible') 44 | 45 | // Make sure loading is finished 46 | cy.wait('@source').its('response.statusCode').should('eq', 206) 47 | cy.get('body > .viewer', { timeout: 10000 }) 48 | .should('be.visible') 49 | .and('have.class', 'modal-mask') 50 | .and('not.have.class', 'icon-loading') 51 | }) 52 | 53 | it('See the menu icon and title on the viewer header', function() { 54 | cy.get('body > .viewer .modal-header__name').should('contain', fileName) 55 | cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') 56 | cy.get('body > .viewer .modal-header button.header-close').should('be.visible') 57 | }) 58 | 59 | it('Does not see navigation arrows', function() { 60 | cy.get('body > .viewer button.prev').should('not.be.visible') 61 | cy.get('body > .viewer button.next').should('not.be.visible') 62 | }) 63 | 64 | it('The audio source is the remote url', function() { 65 | cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active audio') 66 | .should('have.attr', 'src') 67 | .and('contain', `/remote.php/dav/files/${randUser.userId}/${fileName}`) 68 | }) 69 | } 70 | -------------------------------------------------------------------------------- /cypress/e2e/mixins/image.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | /** 7 | * Generate an image cypress test 8 | * 9 | * @param {string} fileName the image to upload and test against 10 | * @param {string} mimeType the image mime type 11 | * @param {string} source the optional custom source to check against 12 | */ 13 | export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg', source = null) { 14 | before(function() { 15 | // Init user 16 | cy.createRandomUser().then(user => { 17 | // Upload test files 18 | cy.uploadFile(user, fileName, mimeType) 19 | 20 | // Visit nextcloud 21 | cy.login(user) 22 | cy.visit('/apps/files') 23 | }) 24 | }) 25 | after(function() { 26 | cy.logout() 27 | }) 28 | 29 | it(`See ${fileName} in the list`, function() { 30 | cy.getFile(fileName, { timeout: 10000 }) 31 | .should('contain', fileName.replace(/(.*)\./, '$1 .')) 32 | }) 33 | 34 | it('Open the viewer on file click and wait for loading to end', function() { 35 | // Match image request 36 | cy.getFileId(fileName).then(fileId => { 37 | const matchRoute = source 38 | ? `/remote.php/dav/files/*/${fileName}` 39 | : `/index.php/core/preview*fileId=${fileId}*` 40 | cy.intercept('GET', matchRoute).as('image') 41 | }) 42 | 43 | // Open the file and check Viewer existence 44 | cy.openFile(fileName) 45 | cy.get('body > .viewer').should('be.visible') 46 | 47 | // Make sure loading is finished 48 | cy.wait('@image').its('response.statusCode').should('eq', 200) 49 | cy.get('body > .viewer', { timeout: 10000 }) 50 | .should('be.visible') 51 | .and('have.class', 'modal-mask') 52 | .and('not.have.class', 'icon-loading') 53 | }) 54 | 55 | it('See the menu icon and title on the viewer header', function() { 56 | cy.get('body > .viewer .modal-header__name').should('contain', fileName) 57 | cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') 58 | cy.get('body > .viewer .modal-header button.header-close').should('be.visible') 59 | }) 60 | 61 | it('Does not see navigation arrows', function() { 62 | cy.get('body > .viewer button.prev').should('not.be.visible') 63 | cy.get('body > .viewer button.next').should('not.be.visible') 64 | }) 65 | 66 | it(`The image source is the ${source ? 'remote' : 'preview'} url`, function() { 67 | cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') 68 | .should('have.attr', 'src') 69 | .and('contain', source ?? '/index.php/core/preview') 70 | }) 71 | } 72 | -------------------------------------------------------------------------------- /cypress/e2e/mixins/video.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | /** 7 | * Generate a video cypress test 8 | * 9 | * @param {string} fileName the video to upload and test against 10 | * @param {string} mimeType the video mime type 11 | */ 12 | export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg') { 13 | let randUser 14 | 15 | before(function() { 16 | // Init user 17 | cy.createRandomUser().then(user => { 18 | randUser = user 19 | 20 | // Upload test files 21 | cy.uploadFile(user, fileName, mimeType) 22 | 23 | // Visit nextcloud 24 | cy.login(user) 25 | cy.visit('/apps/files') 26 | }) 27 | }) 28 | after(function() { 29 | cy.logout() 30 | }) 31 | 32 | it(`See ${fileName} in the list`, function() { 33 | cy.getFile(fileName, { timeout: 10000 }) 34 | .should('contain', fileName.replace(/(.*)\./, '$1 .')) 35 | }) 36 | 37 | it('Open the viewer on file click and wait for loading to end', function() { 38 | // Match audio request 39 | cy.intercept('GET', `/remote.php/dav/files/${randUser.userId}/${fileName}`).as('source') 40 | 41 | // Open the file and check Viewer existence 42 | cy.openFile(fileName) 43 | cy.get('body > .viewer').should('be.visible') 44 | 45 | // Make sure loading is finished 46 | cy.wait('@source').its('response.statusCode').should('eq', 206) 47 | cy.get('body > .viewer', { timeout: 10000 }) 48 | .should('be.visible') 49 | .and('have.class', 'modal-mask') 50 | .and('not.have.class', 'icon-loading') 51 | }) 52 | 53 | it('See the menu icon and title on the viewer header', function() { 54 | cy.get('body > .viewer .modal-header__name').should('contain', fileName) 55 | cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') 56 | cy.get('body > .viewer .modal-header button.header-close').should('be.visible') 57 | }) 58 | 59 | it('Does not see navigation arrows', function() { 60 | cy.get('body > .viewer button.prev').should('not.be.visible') 61 | cy.get('body > .viewer button.next').should('not.be.visible') 62 | }) 63 | 64 | it('The video source is the remote url', function() { 65 | cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active video') 66 | .should('have.attr', 'src') 67 | .and('contain', `/remote.php/dav/files/${randUser.userId}/${fileName}`) 68 | }) 69 | } 70 | -------------------------------------------------------------------------------- /cypress/e2e/navigation.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | describe('Browser navigation', function() { 7 | before(function() { 8 | // Init user 9 | cy.createRandomUser().then(user => { 10 | // Upload test files 11 | cy.uploadFile(user, 'image.png', 'image/png', '/image1.png') 12 | 13 | // Visit nextcloud 14 | cy.login(user) 15 | cy.visit('/apps/files') 16 | }) 17 | }) 18 | after(function() { 19 | cy.logout() 20 | }) 21 | 22 | it('Navigating back to the files overview', function() { 23 | cy.getFile('image1.png', { timeout: 10000 }) 24 | cy.openFile('image1.png') 25 | cy.get('body > .viewer').should('be.visible') 26 | cy.go('back') 27 | cy.get('body > .viewer').should('not.exist') 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /cypress/e2e/non-dav-files.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import { basename as pathBasename } from '@nextcloud/paths' 7 | 8 | const source = '/apps/theming/img/background/anatoly-mikhaltsov-butterfly-wing-scale.jpg' 9 | const basename = pathBasename(source) 10 | 11 | describe('Open non-dav files in viewer', function() { 12 | before(function() { 13 | // Init user 14 | cy.createRandomUser().then(user => { 15 | // Upload test files 16 | cy.uploadFile(user, 'test-card.mp4', 'video/mp4') 17 | 18 | // Visit nextcloud 19 | cy.login(user) 20 | cy.visit('/apps/files') 21 | }) 22 | }) 23 | after(function() { 24 | cy.logout() 25 | }) 26 | 27 | it('Open background', function() { 28 | const fileInfo = { 29 | filename: source, 30 | basename, 31 | mime: 'image/jpeg', 32 | source, 33 | etag: 'abc', 34 | hasPreview: false, 35 | fileid: 123, 36 | } 37 | 38 | cy.window().then((win) => { 39 | win.OCA.Viewer.open({ 40 | fileInfo, 41 | list: [fileInfo], 42 | }) 43 | }) 44 | }) 45 | 46 | it('Does not see a loading animation', function() { 47 | cy.get('body > .viewer', { timeout: 10000 }) 48 | .should('be.visible') 49 | .and('have.class', 'modal-mask') 50 | .and('not.have.class', 'icon-loading') 51 | }) 52 | 53 | it('See the title and close button on the viewer header', function() { 54 | cy.get('body > .viewer .modal-header__name').should('contain', basename) 55 | cy.get('body > .viewer .modal-header button.header-close').should('be.visible') 56 | }) 57 | 58 | it('Does not see navigation arrows', function() { 59 | cy.get('body > .viewer button.prev').should('not.be.visible') 60 | cy.get('body > .viewer button.next').should('not.be.visible') 61 | }) 62 | 63 | it('See the menu but does not see the sidebar button', function() { 64 | // Menu exists 65 | cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') 66 | cy.get('.action-button__icon.icon-menu-sidebar').should('not.exist') 67 | }) 68 | 69 | it('The image source is the remote url', function() { 70 | cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') 71 | .should('have.attr', 'src') 72 | .and('contain', source) 73 | }) 74 | }) 75 | -------------------------------------------------------------------------------- /cypress/e2e/oddname/oddname-audio.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import runTest from '../mixins/oddname' 6 | 7 | for (const [file, type] of [ 8 | ['audio.mp3', 'audio/mpeg'], 9 | ['audio.ogg', 'audio/ogg'], 10 | ]) { 11 | runTest(file, type) 12 | } 13 | -------------------------------------------------------------------------------- /cypress/e2e/oddname/oddname-image.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import runTest from '../mixins/oddname' 6 | 7 | for (const [file, type] of [ 8 | ['image1.jpg', 'image/jpeg'], 9 | ['image.gif', 'image/gif'], 10 | ['image.png', 'image/png'], 11 | ['image-small.png', 'image/png'], 12 | ['image.svg', 'image/svg'], 13 | ]) { 14 | runTest(file, type) 15 | } 16 | -------------------------------------------------------------------------------- /cypress/e2e/oddname/oddname-sidebar.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import runTest from '../mixins/oddname' 6 | 7 | runTest('image.png', 'image/png', true) 8 | -------------------------------------------------------------------------------- /cypress/e2e/oddname/oddname-video.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import runTest from '../mixins/oddname' 6 | 7 | for (const [file, type] of [ 8 | ['video1.mp4', 'video/mp4'], 9 | ['video.mkv', 'video/mkv'], 10 | ['video.ogv', 'video/ogv'], 11 | ['video.webm', 'video/webm'], 12 | ]) { 13 | runTest(file, type) 14 | } 15 | -------------------------------------------------------------------------------- /cypress/e2e/videos/video.mkv.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import videoTest from '../mixins/video' 7 | 8 | describe('Open video.mkv in viewer', function() { 9 | videoTest('video.mkv', 'image/mkv') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/videos/video.mp4.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import videoTest from '../mixins/video' 7 | 8 | describe('Open video1.mp4 in viewer', function() { 9 | videoTest('video1.mp4', 'video/mp4') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/videos/video.ogv.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import videoTest from '../mixins/video' 7 | 8 | describe('Open video.ogv in viewer', function() { 9 | videoTest('video.ogv', 'video/ogv') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/e2e/videos/video.webm.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import videoTest from '../mixins/video' 7 | 8 | describe('Open video.webm in viewer', function() { 9 | videoTest('video.webm', 'video/webm') 10 | }) 11 | -------------------------------------------------------------------------------- /cypress/fixtures/audio.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/audio.mp3 -------------------------------------------------------------------------------- /cypress/fixtures/audio.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/audio.ogg -------------------------------------------------------------------------------- /cypress/fixtures/image-apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image-apng.png -------------------------------------------------------------------------------- /cypress/fixtures/image-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image-small.png -------------------------------------------------------------------------------- /cypress/fixtures/image.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image.bmp -------------------------------------------------------------------------------- /cypress/fixtures/image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image.gif -------------------------------------------------------------------------------- /cypress/fixtures/image.heic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image.heic -------------------------------------------------------------------------------- /cypress/fixtures/image.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image.ico -------------------------------------------------------------------------------- /cypress/fixtures/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image.png -------------------------------------------------------------------------------- /cypress/fixtures/image.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /cypress/fixtures/image.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image.webp -------------------------------------------------------------------------------- /cypress/fixtures/image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image1.jpg -------------------------------------------------------------------------------- /cypress/fixtures/image2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image2.jpg -------------------------------------------------------------------------------- /cypress/fixtures/image3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image3.jpg -------------------------------------------------------------------------------- /cypress/fixtures/image4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/image4.jpg -------------------------------------------------------------------------------- /cypress/fixtures/test-card.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/test-card.mp4 -------------------------------------------------------------------------------- /cypress/fixtures/test-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/test-card.png -------------------------------------------------------------------------------- /cypress/fixtures/video.mkv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/video.mkv -------------------------------------------------------------------------------- /cypress/fixtures/video.ogv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/video.ogv -------------------------------------------------------------------------------- /cypress/fixtures/video.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/video.webm -------------------------------------------------------------------------------- /cypress/fixtures/video1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/video1.mp4 -------------------------------------------------------------------------------- /cypress/fixtures/video2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/fixtures/video2.mp4 -------------------------------------------------------------------------------- /cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image.png -------------------------------------------------------------------------------- /cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image2.png -------------------------------------------------------------------------------- /cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/non-dav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/non-dav.png -------------------------------------------------------------------------------- /cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/video.png -------------------------------------------------------------------------------- /cypress/support/e2e.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | // *********************************************************** 6 | // This example support/index.js is processed and 7 | // loaded automatically before your test files. 8 | // 9 | // This is a great place to put global configuration and 10 | // behavior that modifies Cypress. 11 | // 12 | // You can change the location of this file or turn off 13 | // automatically serving support files with the 14 | // 'supportFile' configuration option. 15 | // 16 | // You can read more here: 17 | // https://on.cypress.io/configuration 18 | // *********************************************************** 19 | 20 | // Import commands.js using ES2015 syntax: 21 | import './commands' 22 | -------------------------------------------------------------------------------- /cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": ["../*.ts", "."], 4 | "compilerOptions": { 5 | "rootDir": "..", 6 | "types": [ 7 | "cypress", 8 | "dockerode", 9 | "node" 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /img/app.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/blank.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/img/blank.mp4 -------------------------------------------------------------------------------- /js/NcActionButton-qdAUHyGz.chunk.mjs.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: AGPL-3.0-or-later 2 | SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) 3 | 4 | This file is generated from multiple sources. Included packages: 5 | - @nextcloud/vue 6 | - version: 8.27.0 7 | - license: AGPL-3.0-or-later 8 | -------------------------------------------------------------------------------- /js/NcActionButton-qdAUHyGz.chunk.mjs.map.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: AGPL-3.0-or-later 2 | SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) 3 | 4 | This file is generated from multiple sources. Included packages: 5 | - @nextcloud/vue 6 | - version: 8.27.0 7 | - license: AGPL-3.0-or-later 8 | -------------------------------------------------------------------------------- /js/NcActionLink-TR7mwuor.chunk.mjs: -------------------------------------------------------------------------------- 1 | import{A as a}from"./actionText-fFcUPi2g-gjw6zxAU.chunk.mjs";import{n as e}from"./logger-Bw8oxZ_4.chunk.mjs";const i={name:"NcActionLink",mixins:[a],inject:{isInSemanticMenu:{from:"NcActions:isSemanticMenu",default:!1}},props:{href:{type:String,default:"#",required:!0,validator:t=>{try{return new URL(t)}catch{return t.startsWith("#")||t.startsWith("/")}}},download:{type:String,default:null},target:{type:String,default:"_self",validator:t=>t&&(!t.startsWith("_")||["_blank","_self","_parent","_top"].indexOf(t)>-1)},title:{type:String,default:null},ariaHidden:{type:Boolean,default:null}}};var s=function(){var t=this,n=t._self._c;return n("li",{staticClass:"action",attrs:{role:t.isInSemanticMenu&&"presentation"}},[n("a",{staticClass:"action-link focusable",attrs:{download:t.download,href:t.href,"aria-label":t.ariaLabel,target:t.target,title:t.title,rel:"nofollow noreferrer noopener",role:t.isInSemanticMenu&&"menuitem"},on:{click:t.onClick}},[t._t("icon",function(){return[n("span",{staticClass:"action-link__icon",class:[t.isIconUrl?"action-link__icon--url":t.icon],style:{backgroundImage:t.isIconUrl?`url(${t.icon})`:null},attrs:{"aria-hidden":"true"}})]}),t.name?n("span",{staticClass:"action-link__longtext-wrapper"},[n("strong",{staticClass:"action-link__name"},[t._v(" "+t._s(t.name)+" ")]),n("br"),n("span",{staticClass:"action-link__longtext",domProps:{textContent:t._s(t.text)}})]):t.isLongText?n("span",{staticClass:"action-link__longtext",domProps:{textContent:t._s(t.text)}}):n("span",{staticClass:"action-link__text"},[t._v(t._s(t.text))]),t._e()],2)])},l=[],o=e(i,s,l,!1,null,"30c015f0");const _=o.exports;export{_ as default}; 2 | //# sourceMappingURL=NcActionLink-TR7mwuor.chunk.mjs.map 3 | -------------------------------------------------------------------------------- /js/NcActionLink-TR7mwuor.chunk.mjs.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: AGPL-3.0-or-later 2 | SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) 3 | 4 | This file is generated from multiple sources. Included packages: 5 | - @nextcloud/vue 6 | - version: 8.27.0 7 | - license: AGPL-3.0-or-later 8 | -------------------------------------------------------------------------------- /js/NcActionLink-TR7mwuor.chunk.mjs.map.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: AGPL-3.0-or-later 2 | SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) 3 | 4 | This file is generated from multiple sources. Included packages: 5 | - @nextcloud/vue 6 | - version: 8.27.0 7 | - license: AGPL-3.0-or-later 8 | -------------------------------------------------------------------------------- /js/actionText-fFcUPi2g-gjw6zxAU.chunk.mjs: -------------------------------------------------------------------------------- 1 | const n={beforeUpdate(){this.text=this.getText()},data(){return{text:this.getText()}},computed:{isLongText(){return this.text&&this.text.trim().length>20}},methods:{getText(){return this.$slots.default?this.$slots.default[0].text.trim():""}}},o=function(i,t){let e=i.$parent;for(;e;){if(e.$options.name===t)return e;e=e.$parent}},s={mixins:[n],props:{icon:{type:String,default:""},name:{type:String,default:""},title:{type:String,default:""},closeAfterClick:{type:Boolean,default:!1},ariaLabel:{type:String,default:null},ariaHidden:{type:Boolean,default:null}},emits:["click"],computed:{isIconUrl(){try{return!!new URL(this.icon,this.icon.startsWith("/")?window.location.origin:void 0)}catch{return!1}}},methods:{onClick(i){if(this.$emit("click",i),this.closeAfterClick){const t=o(this,"NcActions");t&&t.closeMenu&&t.closeMenu(!1)}}}};export{s as A}; 2 | //# sourceMappingURL=actionText-fFcUPi2g-gjw6zxAU.chunk.mjs.map 3 | -------------------------------------------------------------------------------- /js/actionText-fFcUPi2g-gjw6zxAU.chunk.mjs.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: AGPL-3.0-or-later 2 | SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) 3 | 4 | This file is generated from multiple sources. Included packages: 5 | - @nextcloud/vue 6 | - version: 8.27.0 7 | - license: AGPL-3.0-or-later 8 | -------------------------------------------------------------------------------- /js/actionText-fFcUPi2g-gjw6zxAU.chunk.mjs.map.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: AGPL-3.0-or-later 2 | SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) 3 | 4 | This file is generated from multiple sources. Included packages: 5 | - @nextcloud/vue 6 | - version: 8.27.0 7 | - license: AGPL-3.0-or-later 8 | -------------------------------------------------------------------------------- /js/index-Dly6xalz.chunk.mjs.license: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This file is generated from multiple sources. Included packages: 5 | -------------------------------------------------------------------------------- /js/index-Dly6xalz.chunk.mjs.map.license: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This file is generated from multiple sources. Included packages: 5 | -------------------------------------------------------------------------------- /js/index-DtIMqdu8.chunk.mjs.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: 0BSD 2 | SPDX-License-Identifier: MIT 3 | SPDX-FileCopyrightText: @emotion/unitless developers 4 | SPDX-FileCopyrightText: Anton Lavrenov 5 | SPDX-FileCopyrightText: Cody Bennett (https://github.com/codyjasonbennett) 6 | SPDX-FileCopyrightText: Federico Zivolo 7 | SPDX-FileCopyrightText: Glen Maddern 8 | SPDX-FileCopyrightText: John-David Dalton 9 | SPDX-FileCopyrightText: Microsoft Corp. 10 | SPDX-FileCopyrightText: Scaleflex 11 | SPDX-FileCopyrightText: Sultan Tarimo 12 | SPDX-FileCopyrightText: The Babel Team (https://babel.dev/team) 13 | SPDX-FileCopyrightText: prop-types developers 14 | SPDX-FileCopyrightText: react developers 15 | SPDX-FileCopyrightText: react-dom developers 16 | SPDX-FileCopyrightText: react-konva developers 17 | SPDX-FileCopyrightText: react-reconciler developers 18 | SPDX-FileCopyrightText: scaleflex 19 | SPDX-FileCopyrightText: scheduler developers 20 | 21 | This file is generated from multiple sources. Included packages: 22 | - @babel/runtime 23 | - version: 7.27.4 24 | - license: MIT 25 | - @emotion/unitless 26 | - version: 0.8.1 27 | - license: MIT 28 | - @popperjs/core 29 | - version: 2.11.8 30 | - license: MIT 31 | - @scaleflex/icons 32 | - version: 2.10.27 33 | - license: MIT 34 | - @scaleflex/ui 35 | - version: 2.10.27 36 | - license: MIT 37 | - filerobot-image-editor 38 | - version: 4.8.1 39 | - license: MIT 40 | - its-fine 41 | - version: 2.0.0 42 | - license: MIT 43 | - konva 44 | - version: 9.3.6 45 | - license: MIT 46 | - konva 47 | - version: 9.3.20 48 | - license: MIT 49 | - lodash.merge 50 | - version: 4.6.2 51 | - license: MIT 52 | - prop-types 53 | - version: 15.7.2 54 | - license: MIT 55 | - react 56 | - version: 18.3.1 57 | - license: MIT 58 | - react 59 | - version: 19.1.0 60 | - license: MIT 61 | - react-dom 62 | - version: 18.3.1 63 | - license: MIT 64 | - react-dom 65 | - version: 19.1.0 66 | - license: MIT 67 | - react-filerobot-image-editor 68 | - version: 4.9.1 69 | - license: MIT 70 | - react-konva 71 | - version: 19.0.4 72 | - license: MIT 73 | - react-reconciler 74 | - version: 0.32.0 75 | - license: MIT 76 | - scheduler 77 | - version: 0.23.2 78 | - license: MIT 79 | - scheduler 80 | - version: 0.26.0 81 | - license: MIT 82 | - styled-components 83 | - version: 6.1.18 84 | - license: MIT 85 | - stylis 86 | - version: 4.3.2 87 | - license: MIT 88 | - tslib 89 | - version: 2.6.2 90 | - license: 0BSD 91 | -------------------------------------------------------------------------------- /js/index-DtIMqdu8.chunk.mjs.map.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: 0BSD 2 | SPDX-License-Identifier: MIT 3 | SPDX-FileCopyrightText: @emotion/unitless developers 4 | SPDX-FileCopyrightText: Anton Lavrenov 5 | SPDX-FileCopyrightText: Cody Bennett (https://github.com/codyjasonbennett) 6 | SPDX-FileCopyrightText: Federico Zivolo 7 | SPDX-FileCopyrightText: Glen Maddern 8 | SPDX-FileCopyrightText: John-David Dalton 9 | SPDX-FileCopyrightText: Microsoft Corp. 10 | SPDX-FileCopyrightText: Scaleflex 11 | SPDX-FileCopyrightText: Sultan Tarimo 12 | SPDX-FileCopyrightText: The Babel Team (https://babel.dev/team) 13 | SPDX-FileCopyrightText: prop-types developers 14 | SPDX-FileCopyrightText: react developers 15 | SPDX-FileCopyrightText: react-dom developers 16 | SPDX-FileCopyrightText: react-konva developers 17 | SPDX-FileCopyrightText: react-reconciler developers 18 | SPDX-FileCopyrightText: scaleflex 19 | SPDX-FileCopyrightText: scheduler developers 20 | 21 | This file is generated from multiple sources. Included packages: 22 | - @babel/runtime 23 | - version: 7.27.4 24 | - license: MIT 25 | - @emotion/unitless 26 | - version: 0.8.1 27 | - license: MIT 28 | - @popperjs/core 29 | - version: 2.11.8 30 | - license: MIT 31 | - @scaleflex/icons 32 | - version: 2.10.27 33 | - license: MIT 34 | - @scaleflex/ui 35 | - version: 2.10.27 36 | - license: MIT 37 | - filerobot-image-editor 38 | - version: 4.8.1 39 | - license: MIT 40 | - its-fine 41 | - version: 2.0.0 42 | - license: MIT 43 | - konva 44 | - version: 9.3.6 45 | - license: MIT 46 | - konva 47 | - version: 9.3.20 48 | - license: MIT 49 | - lodash.merge 50 | - version: 4.6.2 51 | - license: MIT 52 | - prop-types 53 | - version: 15.7.2 54 | - license: MIT 55 | - react 56 | - version: 18.3.1 57 | - license: MIT 58 | - react 59 | - version: 19.1.0 60 | - license: MIT 61 | - react-dom 62 | - version: 18.3.1 63 | - license: MIT 64 | - react-dom 65 | - version: 19.1.0 66 | - license: MIT 67 | - react-filerobot-image-editor 68 | - version: 4.9.1 69 | - license: MIT 70 | - react-konva 71 | - version: 19.0.4 72 | - license: MIT 73 | - react-reconciler 74 | - version: 0.32.0 75 | - license: MIT 76 | - scheduler 77 | - version: 0.23.2 78 | - license: MIT 79 | - scheduler 80 | - version: 0.26.0 81 | - license: MIT 82 | - styled-components 83 | - version: 6.1.18 84 | - license: MIT 85 | - stylis 86 | - version: 4.3.2 87 | - license: MIT 88 | - tslib 89 | - version: 2.6.2 90 | - license: 0BSD 91 | -------------------------------------------------------------------------------- /js/index.esm-CAkhAkGw.chunk.mjs.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: MIT 2 | SPDX-FileCopyrightText: Gabe Dunn 3 | 4 | This file is generated from multiple sources. Included packages: 5 | - @skjnldsv/vue-plyr 6 | - version: 7.5.0 7 | - license: MIT 8 | -------------------------------------------------------------------------------- /js/index.esm-CAkhAkGw.chunk.mjs.map.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: MIT 2 | SPDX-FileCopyrightText: Gabe Dunn 3 | 4 | This file is generated from multiple sources. Included packages: 5 | - @skjnldsv/vue-plyr 6 | - version: 7.5.0 7 | - license: MIT 8 | -------------------------------------------------------------------------------- /js/viewer-main.mjs.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: AGPL-3.0-or-later 2 | SPDX-License-Identifier: MIT 3 | SPDX-FileCopyrightText: Javier Blanco 4 | SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) 5 | SPDX-FileCopyrightText: John Molakvoæ 6 | SPDX-FileCopyrightText: Rob Cresswell 7 | 8 | This file is generated from multiple sources. Included packages: 9 | - @nextcloud/vue 10 | - version: 8.27.0 11 | - license: AGPL-3.0-or-later 12 | - path-parse 13 | - version: 1.0.7 14 | - license: MIT 15 | - viewer 16 | - version: 5.0.0-dev.0 17 | - license: AGPL-3.0-or-later 18 | - vue-material-design-icons 19 | - version: 5.3.1 20 | - license: MIT 21 | -------------------------------------------------------------------------------- /js/viewer-main.mjs.map.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: AGPL-3.0-or-later 2 | SPDX-License-Identifier: MIT 3 | SPDX-FileCopyrightText: Javier Blanco 4 | SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) 5 | SPDX-FileCopyrightText: John Molakvoæ 6 | SPDX-FileCopyrightText: Rob Cresswell 7 | 8 | This file is generated from multiple sources. Included packages: 9 | - @nextcloud/vue 10 | - version: 8.27.0 11 | - license: AGPL-3.0-or-later 12 | - path-parse 13 | - version: 1.0.7 14 | - license: MIT 15 | - viewer 16 | - version: 5.0.0-dev.0 17 | - license: AGPL-3.0-or-later 18 | - vue-material-design-icons 19 | - version: 5.3.1 20 | - license: MIT 21 | -------------------------------------------------------------------------------- /l10n/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/viewer/dc73ca59b4012b44b79568b8a5edb0b98b740660/l10n/.gitkeep -------------------------------------------------------------------------------- /l10n/af.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Bekyker", 5 | "Simple file viewer with slideshow for media" : "Kyk maklik na lêers met skyfievertonings vir media", 6 | "Your browser does not support audio." : "U blaaier ondersteun nie oudio nie.", 7 | "Error loading {name}" : "Laaifout vir {name}", 8 | "Your browser does not support videos." : "U blaaier ondersteun nie video’s nie.", 9 | "There is no plugin available to display this file type" : "Daar is geen beskikbare inprop om hierdie lêertipe te vertoon nie", 10 | "Edit" : "Wysig", 11 | "Open sidebar" : "Open kantbalk", 12 | "Download" : "Laai af", 13 | "Delete" : "Skrap", 14 | "View" : "Bekyk", 15 | "Name" : "Naam", 16 | "Save" : "Bewaar", 17 | "Back" : "Terug", 18 | "Loading …" : "Laai …", 19 | "Reset" : "Herstel", 20 | "Cancel" : "Kanselleer", 21 | "Confirm" : "Bevestig", 22 | "Original" : "Oorspronklik", 23 | "Custom" : "Eie", 24 | "Value" : "Waarde", 25 | "Text" : "Teks", 26 | "Size" : "Grootte", 27 | "Position" : "Posisie", 28 | "Quality" : "Kwaliteit", 29 | "Menu" : "Kieslys" 30 | }, 31 | "nplurals=2; plural=(n != 1);"); 32 | -------------------------------------------------------------------------------- /l10n/af.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Bekyker", 3 | "Simple file viewer with slideshow for media" : "Kyk maklik na lêers met skyfievertonings vir media", 4 | "Your browser does not support audio." : "U blaaier ondersteun nie oudio nie.", 5 | "Error loading {name}" : "Laaifout vir {name}", 6 | "Your browser does not support videos." : "U blaaier ondersteun nie video’s nie.", 7 | "There is no plugin available to display this file type" : "Daar is geen beskikbare inprop om hierdie lêertipe te vertoon nie", 8 | "Edit" : "Wysig", 9 | "Open sidebar" : "Open kantbalk", 10 | "Download" : "Laai af", 11 | "Delete" : "Skrap", 12 | "View" : "Bekyk", 13 | "Name" : "Naam", 14 | "Save" : "Bewaar", 15 | "Back" : "Terug", 16 | "Loading …" : "Laai …", 17 | "Reset" : "Herstel", 18 | "Cancel" : "Kanselleer", 19 | "Confirm" : "Bevestig", 20 | "Original" : "Oorspronklik", 21 | "Custom" : "Eie", 22 | "Value" : "Waarde", 23 | "Text" : "Teks", 24 | "Size" : "Grootte", 25 | "Position" : "Posisie", 26 | "Quality" : "Kwaliteit", 27 | "Menu" : "Kieslys" 28 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 29 | } -------------------------------------------------------------------------------- /l10n/az.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Dəyişiklik et", 5 | "Download" : "Yüklə", 6 | "Delete" : "Sil", 7 | "Name" : "Ad", 8 | "Save" : "Saxla", 9 | "Back" : "Geri", 10 | "Reset" : "Sıfırla", 11 | "Cancel" : "Dayandır", 12 | "Warning" : "Xəbərdarlıq", 13 | "Confirm" : "Təsdiq edin", 14 | "Size" : "Həcm", 15 | "Menu" : "Menyu" 16 | }, 17 | "nplurals=2; plural=(n != 1);"); 18 | -------------------------------------------------------------------------------- /l10n/az.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Dəyişiklik et", 3 | "Download" : "Yüklə", 4 | "Delete" : "Sil", 5 | "Name" : "Ad", 6 | "Save" : "Saxla", 7 | "Back" : "Geri", 8 | "Reset" : "Sıfırla", 9 | "Cancel" : "Dayandır", 10 | "Warning" : "Xəbərdarlıq", 11 | "Confirm" : "Təsdiq edin", 12 | "Size" : "Həcm", 13 | "Menu" : "Menyu" 14 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 15 | } -------------------------------------------------------------------------------- /l10n/bn_BD.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "সম্পাদনা", 5 | "Download" : "ডাউনলোড", 6 | "Delete" : "মুছে", 7 | "Name" : "নাম", 8 | "Save" : "সংরক্ষণ", 9 | "Back" : "পেছনে যাও", 10 | "Reset" : "পূণঃনির্ধানণ", 11 | "Cancel" : "বাতির", 12 | "Warning" : "সতর্কবাণী", 13 | "Size" : "আকার" 14 | }, 15 | "nplurals=2; plural=(n != 1);"); 16 | -------------------------------------------------------------------------------- /l10n/bn_BD.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "সম্পাদনা", 3 | "Download" : "ডাউনলোড", 4 | "Delete" : "মুছে", 5 | "Name" : "নাম", 6 | "Save" : "সংরক্ষণ", 7 | "Back" : "পেছনে যাও", 8 | "Reset" : "পূণঃনির্ধানণ", 9 | "Cancel" : "বাতির", 10 | "Warning" : "সতর্কবাণী", 11 | "Size" : "আকার" 12 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 13 | } -------------------------------------------------------------------------------- /l10n/br.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Gweller", 5 | "Simple file viewer with slideshow for media" : "Ur seller restroù simpl gant un diaporama evit ar mediaoù", 6 | "Error loading {name}" : "Ur fazi zo bet en ur kargañ {name}", 7 | "LIVE" : "WAR-EEUN", 8 | "Your browser does not support videos." : "Ne doug ket ho furcher ar videoioù.", 9 | "Edit" : "Cheñch", 10 | "Open sidebar" : "Digori ar varenn gostez", 11 | "Download" : "Pellgargañ", 12 | "Delete" : "Dilemel", 13 | "View" : "Gwell", 14 | "Name" : "Anv", 15 | "Save" : "Enrollañ", 16 | "Back" : "Distro", 17 | "Loading …" : "O Kargañ ...", 18 | "Cancel" : "Nullañ", 19 | "Apply" : "Lakaat", 20 | "Warning" : "Kemenadenn", 21 | "Confirm" : "Kadarnaat", 22 | "Original" : "Orin", 23 | "Text" : "Testenn", 24 | "Size" : "Ment", 25 | "Menu" : "Roll" 26 | }, 27 | "nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);"); 28 | -------------------------------------------------------------------------------- /l10n/br.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Gweller", 3 | "Simple file viewer with slideshow for media" : "Ur seller restroù simpl gant un diaporama evit ar mediaoù", 4 | "Error loading {name}" : "Ur fazi zo bet en ur kargañ {name}", 5 | "LIVE" : "WAR-EEUN", 6 | "Your browser does not support videos." : "Ne doug ket ho furcher ar videoioù.", 7 | "Edit" : "Cheñch", 8 | "Open sidebar" : "Digori ar varenn gostez", 9 | "Download" : "Pellgargañ", 10 | "Delete" : "Dilemel", 11 | "View" : "Gwell", 12 | "Name" : "Anv", 13 | "Save" : "Enrollañ", 14 | "Back" : "Distro", 15 | "Loading …" : "O Kargañ ...", 16 | "Cancel" : "Nullañ", 17 | "Apply" : "Lakaat", 18 | "Warning" : "Kemenadenn", 19 | "Confirm" : "Kadarnaat", 20 | "Original" : "Orin", 21 | "Text" : "Testenn", 22 | "Size" : "Ment", 23 | "Menu" : "Roll" 24 | },"pluralForm" :"nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);" 25 | } -------------------------------------------------------------------------------- /l10n/bs.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Izmjeni", 5 | "Download" : "Preuzmi", 6 | "Delete" : "Obriši", 7 | "Name" : "Ime", 8 | "Save" : "Spremi", 9 | "Cancel" : "Otkaži", 10 | "Warning" : "Upozorenje", 11 | "Size" : "Veličina" 12 | }, 13 | "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); 14 | -------------------------------------------------------------------------------- /l10n/bs.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Izmjeni", 3 | "Download" : "Preuzmi", 4 | "Delete" : "Obriši", 5 | "Name" : "Ime", 6 | "Save" : "Spremi", 7 | "Cancel" : "Otkaži", 8 | "Warning" : "Upozorenje", 9 | "Size" : "Veličina" 10 | },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" 11 | } -------------------------------------------------------------------------------- /l10n/cy_GB.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Golygu", 5 | "Open sidebar" : "Agor y bar ochr", 6 | "Download" : "Llwytho i lawr", 7 | "Delete" : "Dileu", 8 | "View" : "Golwg", 9 | "Name" : "Enw", 10 | "Save" : "Cadw", 11 | "Back" : "Nôl", 12 | "Loading …" : "Yn llwytho …", 13 | "Cancel" : "Diddymu", 14 | "Warning" : "Rhybudd", 15 | "Confirm" : "Cadarnhau", 16 | "Undo" : "Dadwneud", 17 | "Custom" : "Cyfaddas", 18 | "Size" : "Maint" 19 | }, 20 | "nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;"); 21 | -------------------------------------------------------------------------------- /l10n/cy_GB.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Golygu", 3 | "Open sidebar" : "Agor y bar ochr", 4 | "Download" : "Llwytho i lawr", 5 | "Delete" : "Dileu", 6 | "View" : "Golwg", 7 | "Name" : "Enw", 8 | "Save" : "Cadw", 9 | "Back" : "Nôl", 10 | "Loading …" : "Yn llwytho …", 11 | "Cancel" : "Diddymu", 12 | "Warning" : "Rhybudd", 13 | "Confirm" : "Cadarnhau", 14 | "Undo" : "Dadwneud", 15 | "Custom" : "Cyfaddas", 16 | "Size" : "Maint" 17 | },"pluralForm" :"nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;" 18 | } -------------------------------------------------------------------------------- /l10n/el.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Πρόγραμμα προβολής", 5 | "Simple file viewer with slideshow for media" : "Απλό πρόγραμμα προβολής αρχείων με παρουσίαση διαφανειών για πολυμέσα", 6 | "Your browser does not support audio." : "Το πρόγραμμα περιήγησής σας δεν υποστηρίζει ήχο.", 7 | "Error loading {name}" : "Σφάλμα φόρτωσης {name}", 8 | "Image saved" : "Η εικόνα αποθηκεύτηκε", 9 | "Your browser does not support videos." : "Ο περιηγητής σας δεν υποστηρίζει βίντεο.", 10 | "There is no plugin available to display this file type" : "Δεν υπάρχει διαθέσιμο πρόσθετο για την προβολή αυτού του τύπου αρχείου", 11 | "Edit" : "Επεξεργασία", 12 | "Open sidebar" : "Άνοιγμα πλευρικής στήλης", 13 | "Download" : "Λήψη", 14 | "Delete" : "Διαγραφή", 15 | "View" : "Προβολή", 16 | "Name" : "Όνομα", 17 | "Save" : "Αποθήκευση", 18 | "Save as" : "Αποθήκευση ως", 19 | "Back" : "Πίσω", 20 | "Loading …" : "Φόρτωση …", 21 | "Reset" : "Επαναφορά", 22 | "Cancel" : "Ακύρωση", 23 | "Apply" : "Εφαρμογή", 24 | "Warning" : "Προειδοποίηση", 25 | "Confirm" : "Επιβεβαίωση", 26 | "Undo" : "Ακύρωση ενέργειας", 27 | "Redo" : "Ξανακάντε", 28 | "Zoom in" : "Εστίαση", 29 | "Zoom out" : "Σμίκρυνση", 30 | "Adjust" : "Ρύθμιση", 31 | "Filters" : "Φίλτρα", 32 | "Watermark" : "Υδατόσημο", 33 | "Draw" : "Σχεδίαση", 34 | "Resize" : "Αλλαγή μεγέθους", 35 | "Crop" : "Περικοπή", 36 | "Original" : "Πρωτότυπο", 37 | "Custom" : "Προσαρμοσμένο", 38 | "Square" : "Τετράγωνο", 39 | "Landscape" : "Οριζόντια", 40 | "Portrait" : "Κάθετα", 41 | "Ellipse" : "Έλλειψη", 42 | "Arrow" : "Βέλος", 43 | "Brightness" : "Φωτεινότητα", 44 | "Contrast" : "Αντίθεση", 45 | "Hue" : "Απόχρωση", 46 | "Saturation" : "Κορεσμός", 47 | "Value" : "Τιμή", 48 | "Image" : "Εικόνα", 49 | "Line" : "Γραμμή", 50 | "Polygon" : "Πολύγωνο", 51 | "Rotate" : "Περιστροφή", 52 | "Text" : "Κείμενο", 53 | "Size" : "Μέγεθος", 54 | "Padding" : "Γέμισμα", 55 | "Vertical" : "Κάθετα", 56 | "Opacity" : "Διαφάνεια", 57 | "Position" : "Θέση", 58 | "Stroke" : "Πινελιά", 59 | "Save image as" : "Αποθήκευση εικόνας ως", 60 | "Extension" : "Επέκταση", 61 | "Name is required." : "Απαιτείται όνομα.", 62 | "Quality" : "Ποιότητα", 63 | "Fit size" : "Προσαρμογή στο μέγεθος", 64 | "Menu" : "Μενού", 65 | "Height" : "Ύψος" 66 | }, 67 | "nplurals=2; plural=(n != 1);"); 68 | -------------------------------------------------------------------------------- /l10n/el.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Πρόγραμμα προβολής", 3 | "Simple file viewer with slideshow for media" : "Απλό πρόγραμμα προβολής αρχείων με παρουσίαση διαφανειών για πολυμέσα", 4 | "Your browser does not support audio." : "Το πρόγραμμα περιήγησής σας δεν υποστηρίζει ήχο.", 5 | "Error loading {name}" : "Σφάλμα φόρτωσης {name}", 6 | "Image saved" : "Η εικόνα αποθηκεύτηκε", 7 | "Your browser does not support videos." : "Ο περιηγητής σας δεν υποστηρίζει βίντεο.", 8 | "There is no plugin available to display this file type" : "Δεν υπάρχει διαθέσιμο πρόσθετο για την προβολή αυτού του τύπου αρχείου", 9 | "Edit" : "Επεξεργασία", 10 | "Open sidebar" : "Άνοιγμα πλευρικής στήλης", 11 | "Download" : "Λήψη", 12 | "Delete" : "Διαγραφή", 13 | "View" : "Προβολή", 14 | "Name" : "Όνομα", 15 | "Save" : "Αποθήκευση", 16 | "Save as" : "Αποθήκευση ως", 17 | "Back" : "Πίσω", 18 | "Loading …" : "Φόρτωση …", 19 | "Reset" : "Επαναφορά", 20 | "Cancel" : "Ακύρωση", 21 | "Apply" : "Εφαρμογή", 22 | "Warning" : "Προειδοποίηση", 23 | "Confirm" : "Επιβεβαίωση", 24 | "Undo" : "Ακύρωση ενέργειας", 25 | "Redo" : "Ξανακάντε", 26 | "Zoom in" : "Εστίαση", 27 | "Zoom out" : "Σμίκρυνση", 28 | "Adjust" : "Ρύθμιση", 29 | "Filters" : "Φίλτρα", 30 | "Watermark" : "Υδατόσημο", 31 | "Draw" : "Σχεδίαση", 32 | "Resize" : "Αλλαγή μεγέθους", 33 | "Crop" : "Περικοπή", 34 | "Original" : "Πρωτότυπο", 35 | "Custom" : "Προσαρμοσμένο", 36 | "Square" : "Τετράγωνο", 37 | "Landscape" : "Οριζόντια", 38 | "Portrait" : "Κάθετα", 39 | "Ellipse" : "Έλλειψη", 40 | "Arrow" : "Βέλος", 41 | "Brightness" : "Φωτεινότητα", 42 | "Contrast" : "Αντίθεση", 43 | "Hue" : "Απόχρωση", 44 | "Saturation" : "Κορεσμός", 45 | "Value" : "Τιμή", 46 | "Image" : "Εικόνα", 47 | "Line" : "Γραμμή", 48 | "Polygon" : "Πολύγωνο", 49 | "Rotate" : "Περιστροφή", 50 | "Text" : "Κείμενο", 51 | "Size" : "Μέγεθος", 52 | "Padding" : "Γέμισμα", 53 | "Vertical" : "Κάθετα", 54 | "Opacity" : "Διαφάνεια", 55 | "Position" : "Θέση", 56 | "Stroke" : "Πινελιά", 57 | "Save image as" : "Αποθήκευση εικόνας ως", 58 | "Extension" : "Επέκταση", 59 | "Name is required." : "Απαιτείται όνομα.", 60 | "Quality" : "Ποιότητα", 61 | "Fit size" : "Προσαρμογή στο μέγεθος", 62 | "Menu" : "Μενού", 63 | "Height" : "Ύψος" 64 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 65 | } -------------------------------------------------------------------------------- /l10n/eo.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Vidigilo", 5 | "Simple file viewer with slideshow for media" : "Simpla dosiervidigilo kun lumbilda prezento por aŭdvidaĵoj", 6 | "Error loading {name}" : "Eraro dum ŝargo de {name}", 7 | "Your browser does not support videos." : "Via retumilo ne subtenas la vidaĵojn", 8 | "Edit" : "Modifi", 9 | "Open sidebar" : "Malfermi flankopanelon", 10 | "Download" : "Elŝuti", 11 | "Delete" : "Forigi", 12 | "View" : "Vidi", 13 | "Name" : "Nomo", 14 | "Save" : "Konservi", 15 | "Back" : "Antaŭen", 16 | "Loading …" : "Ŝargas …", 17 | "Reset" : "Restarigi", 18 | "Cancel" : "Nuligi", 19 | "Apply" : "Validigi", 20 | "Warning" : "Averto", 21 | "Confirm" : "Konfirmi", 22 | "Undo" : "Malfari", 23 | "Redo" : "Refari", 24 | "Custom" : "Propra", 25 | "Text" : "Teksto", 26 | "Size" : "Grando", 27 | "Position" : "Loko", 28 | "Extension" : "Dosiersufikso" 29 | }, 30 | "nplurals=2; plural=(n != 1);"); 31 | -------------------------------------------------------------------------------- /l10n/eo.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Vidigilo", 3 | "Simple file viewer with slideshow for media" : "Simpla dosiervidigilo kun lumbilda prezento por aŭdvidaĵoj", 4 | "Error loading {name}" : "Eraro dum ŝargo de {name}", 5 | "Your browser does not support videos." : "Via retumilo ne subtenas la vidaĵojn", 6 | "Edit" : "Modifi", 7 | "Open sidebar" : "Malfermi flankopanelon", 8 | "Download" : "Elŝuti", 9 | "Delete" : "Forigi", 10 | "View" : "Vidi", 11 | "Name" : "Nomo", 12 | "Save" : "Konservi", 13 | "Back" : "Antaŭen", 14 | "Loading …" : "Ŝargas …", 15 | "Reset" : "Restarigi", 16 | "Cancel" : "Nuligi", 17 | "Apply" : "Validigi", 18 | "Warning" : "Averto", 19 | "Confirm" : "Konfirmi", 20 | "Undo" : "Malfari", 21 | "Redo" : "Refari", 22 | "Custom" : "Propra", 23 | "Text" : "Teksto", 24 | "Size" : "Grando", 25 | "Position" : "Loko", 26 | "Extension" : "Dosiersufikso" 27 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 28 | } -------------------------------------------------------------------------------- /l10n/es_419.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Editar", 5 | "Download" : "Descargar", 6 | "Delete" : "Borrar", 7 | "Name" : "Nombre", 8 | "Save" : "Guardar", 9 | "Back" : "Atrás", 10 | "Reset" : "Restaurar", 11 | "Cancel" : "Cancelar", 12 | "Apply" : "Aplicar", 13 | "Confirm" : "Confirmar", 14 | "Undo" : "Deshacer", 15 | "Custom" : "Personalizado", 16 | "Value" : "Valor", 17 | "Text" : "Texto", 18 | "Size" : "Tamaño", 19 | "Position" : "Posición", 20 | "Menu" : "Menú" 21 | }, 22 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 23 | -------------------------------------------------------------------------------- /l10n/es_419.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Editar", 3 | "Download" : "Descargar", 4 | "Delete" : "Borrar", 5 | "Name" : "Nombre", 6 | "Save" : "Guardar", 7 | "Back" : "Atrás", 8 | "Reset" : "Restaurar", 9 | "Cancel" : "Cancelar", 10 | "Apply" : "Aplicar", 11 | "Confirm" : "Confirmar", 12 | "Undo" : "Deshacer", 13 | "Custom" : "Personalizado", 14 | "Value" : "Valor", 15 | "Text" : "Texto", 16 | "Size" : "Tamaño", 17 | "Position" : "Posición", 18 | "Menu" : "Menú" 19 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 20 | } -------------------------------------------------------------------------------- /l10n/es_AR.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "LIVE" : "EN VIVO", 5 | "Edit" : "Editar", 6 | "Open sidebar" : "Abrir barra lateral", 7 | "Download" : "Descargar", 8 | "Delete" : "Eliminar", 9 | "View" : "Ver", 10 | "Name" : "Nombre", 11 | "Save" : "Guardar", 12 | "Back" : "Atrás", 13 | "Loading …" : "Cargando …", 14 | "Reset" : "Restablecer", 15 | "Cancel" : "Cancelar", 16 | "Apply" : "Aplicar", 17 | "Warning" : "Advertencia", 18 | "Confirm" : "Confirmar", 19 | "Undo" : "Deshacer", 20 | "Custom" : "Personalizado", 21 | "Value" : "Valor", 22 | "Line" : "Linea", 23 | "Text" : "Texto", 24 | "Size" : "Tamaño", 25 | "Position" : "Posición", 26 | "Menu" : "Menú" 27 | }, 28 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 29 | -------------------------------------------------------------------------------- /l10n/es_AR.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "LIVE" : "EN VIVO", 3 | "Edit" : "Editar", 4 | "Open sidebar" : "Abrir barra lateral", 5 | "Download" : "Descargar", 6 | "Delete" : "Eliminar", 7 | "View" : "Ver", 8 | "Name" : "Nombre", 9 | "Save" : "Guardar", 10 | "Back" : "Atrás", 11 | "Loading …" : "Cargando …", 12 | "Reset" : "Restablecer", 13 | "Cancel" : "Cancelar", 14 | "Apply" : "Aplicar", 15 | "Warning" : "Advertencia", 16 | "Confirm" : "Confirmar", 17 | "Undo" : "Deshacer", 18 | "Custom" : "Personalizado", 19 | "Value" : "Valor", 20 | "Line" : "Linea", 21 | "Text" : "Texto", 22 | "Size" : "Tamaño", 23 | "Position" : "Posición", 24 | "Menu" : "Menú" 25 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 26 | } -------------------------------------------------------------------------------- /l10n/es_CL.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Image saved" : "Imagen guardada", 5 | "Edit" : "Editar", 6 | "Download" : "Descargar", 7 | "Delete" : "Borrar", 8 | "Name" : "Nombre", 9 | "Save" : "Guardar", 10 | "Back" : "Atrás", 11 | "Loading …" : "Cargando …", 12 | "Reset" : "Restablecer", 13 | "Cancel" : "Cancelar", 14 | "Apply" : "Aplicar", 15 | "Warning" : "Advertencia", 16 | "Confirm" : "Confirmar", 17 | "Undo" : "Deshacer", 18 | "Custom" : "Personalizado", 19 | "Value" : "Valor", 20 | "Text" : "Texto", 21 | "Size" : "Tamaño", 22 | "Position" : "Posición", 23 | "Menu" : "Menú" 24 | }, 25 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 26 | -------------------------------------------------------------------------------- /l10n/es_CL.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Image saved" : "Imagen guardada", 3 | "Edit" : "Editar", 4 | "Download" : "Descargar", 5 | "Delete" : "Borrar", 6 | "Name" : "Nombre", 7 | "Save" : "Guardar", 8 | "Back" : "Atrás", 9 | "Loading …" : "Cargando …", 10 | "Reset" : "Restablecer", 11 | "Cancel" : "Cancelar", 12 | "Apply" : "Aplicar", 13 | "Warning" : "Advertencia", 14 | "Confirm" : "Confirmar", 15 | "Undo" : "Deshacer", 16 | "Custom" : "Personalizado", 17 | "Value" : "Valor", 18 | "Text" : "Texto", 19 | "Size" : "Tamaño", 20 | "Position" : "Posición", 21 | "Menu" : "Menú" 22 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 23 | } -------------------------------------------------------------------------------- /l10n/es_CO.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Image saved" : "Imagen guardada", 5 | "Edit" : "Editar", 6 | "Download" : "Descargar", 7 | "Delete" : "Borrar", 8 | "Name" : "Nombre", 9 | "Save" : "Guardar", 10 | "Back" : "Atrás", 11 | "Reset" : "Reiniciar", 12 | "Cancel" : "Cancelar", 13 | "Apply" : "Aplicar", 14 | "Confirm" : "Confirmar", 15 | "Undo" : "Deshacer", 16 | "Custom" : "Personalizado", 17 | "Value" : "Valor", 18 | "Text" : "Texto", 19 | "Size" : "Tamaño", 20 | "Position" : "Posición", 21 | "Menu" : "Menú" 22 | }, 23 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 24 | -------------------------------------------------------------------------------- /l10n/es_CO.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Image saved" : "Imagen guardada", 3 | "Edit" : "Editar", 4 | "Download" : "Descargar", 5 | "Delete" : "Borrar", 6 | "Name" : "Nombre", 7 | "Save" : "Guardar", 8 | "Back" : "Atrás", 9 | "Reset" : "Reiniciar", 10 | "Cancel" : "Cancelar", 11 | "Apply" : "Aplicar", 12 | "Confirm" : "Confirmar", 13 | "Undo" : "Deshacer", 14 | "Custom" : "Personalizado", 15 | "Value" : "Valor", 16 | "Text" : "Texto", 17 | "Size" : "Tamaño", 18 | "Position" : "Posición", 19 | "Menu" : "Menú" 20 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 21 | } -------------------------------------------------------------------------------- /l10n/es_CR.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Image saved" : "Imagen guardada", 5 | "Edit" : "Editar", 6 | "Download" : "Descargar", 7 | "Delete" : "Borrar", 8 | "Name" : "Nombre", 9 | "Save" : "Guardar", 10 | "Back" : "Atrás", 11 | "Reset" : "Restablecer", 12 | "Cancel" : "Cancelar", 13 | "Apply" : "Aplicar", 14 | "Confirm" : "Confirmar", 15 | "Undo" : "Deshacer", 16 | "Custom" : "Personalizado", 17 | "Value" : "Valor", 18 | "Text" : "Texto", 19 | "Size" : "Tamaño", 20 | "Position" : "Posición", 21 | "Menu" : "Menú" 22 | }, 23 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 24 | -------------------------------------------------------------------------------- /l10n/es_CR.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Image saved" : "Imagen guardada", 3 | "Edit" : "Editar", 4 | "Download" : "Descargar", 5 | "Delete" : "Borrar", 6 | "Name" : "Nombre", 7 | "Save" : "Guardar", 8 | "Back" : "Atrás", 9 | "Reset" : "Restablecer", 10 | "Cancel" : "Cancelar", 11 | "Apply" : "Aplicar", 12 | "Confirm" : "Confirmar", 13 | "Undo" : "Deshacer", 14 | "Custom" : "Personalizado", 15 | "Value" : "Valor", 16 | "Text" : "Texto", 17 | "Size" : "Tamaño", 18 | "Position" : "Posición", 19 | "Menu" : "Menú" 20 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 21 | } -------------------------------------------------------------------------------- /l10n/es_DO.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Image saved" : "Imagen guardada", 5 | "Edit" : "Editar", 6 | "Download" : "Descargar", 7 | "Delete" : "Borrar", 8 | "Name" : "Nombre", 9 | "Save" : "Guardar", 10 | "Back" : "Atrás", 11 | "Reset" : "Restablecer", 12 | "Cancel" : "Cancelar", 13 | "Apply" : "Aplicar", 14 | "Confirm" : "Confirmar", 15 | "Undo" : "Deshacer", 16 | "Custom" : "Personalizado", 17 | "Value" : "Valor", 18 | "Text" : "Texto", 19 | "Size" : "Tamaño", 20 | "Position" : "Posición", 21 | "Menu" : "Menú" 22 | }, 23 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 24 | -------------------------------------------------------------------------------- /l10n/es_DO.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Image saved" : "Imagen guardada", 3 | "Edit" : "Editar", 4 | "Download" : "Descargar", 5 | "Delete" : "Borrar", 6 | "Name" : "Nombre", 7 | "Save" : "Guardar", 8 | "Back" : "Atrás", 9 | "Reset" : "Restablecer", 10 | "Cancel" : "Cancelar", 11 | "Apply" : "Aplicar", 12 | "Confirm" : "Confirmar", 13 | "Undo" : "Deshacer", 14 | "Custom" : "Personalizado", 15 | "Value" : "Valor", 16 | "Text" : "Texto", 17 | "Size" : "Tamaño", 18 | "Position" : "Posición", 19 | "Menu" : "Menú" 20 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 21 | } -------------------------------------------------------------------------------- /l10n/es_GT.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Image saved" : "Imagen guardada", 5 | "Edit" : "Editar", 6 | "Download" : "Descargar", 7 | "Delete" : "Borrar", 8 | "Name" : "Nombre", 9 | "Save" : "Guardar", 10 | "Back" : "Atrás", 11 | "Reset" : "Restablecer", 12 | "Cancel" : "Cancelar", 13 | "Apply" : "Aplicar", 14 | "Warning" : "Advertencia", 15 | "Confirm" : "Confirmar", 16 | "Undo" : "Deshacer", 17 | "Custom" : "Personalizado", 18 | "Value" : "Valor", 19 | "Text" : "Texto", 20 | "Size" : "Tamaño", 21 | "Position" : "Posición", 22 | "Menu" : "Menú" 23 | }, 24 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 25 | -------------------------------------------------------------------------------- /l10n/es_GT.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Image saved" : "Imagen guardada", 3 | "Edit" : "Editar", 4 | "Download" : "Descargar", 5 | "Delete" : "Borrar", 6 | "Name" : "Nombre", 7 | "Save" : "Guardar", 8 | "Back" : "Atrás", 9 | "Reset" : "Restablecer", 10 | "Cancel" : "Cancelar", 11 | "Apply" : "Aplicar", 12 | "Warning" : "Advertencia", 13 | "Confirm" : "Confirmar", 14 | "Undo" : "Deshacer", 15 | "Custom" : "Personalizado", 16 | "Value" : "Valor", 17 | "Text" : "Texto", 18 | "Size" : "Tamaño", 19 | "Position" : "Posición", 20 | "Menu" : "Menú" 21 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 22 | } -------------------------------------------------------------------------------- /l10n/es_HN.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Editar", 5 | "Download" : "Descargar", 6 | "Delete" : "Borrar", 7 | "Name" : "Nombre", 8 | "Save" : "Guardar", 9 | "Back" : "Atrás", 10 | "Reset" : "Restablecer", 11 | "Cancel" : "Cancelar", 12 | "Apply" : "Aplicar", 13 | "Warning" : "Advertencia", 14 | "Confirm" : "Confirmar", 15 | "Undo" : "Deshacer", 16 | "Custom" : "Personalizado", 17 | "Value" : "Valor", 18 | "Text" : "Texto", 19 | "Size" : "Tamaño", 20 | "Position" : "Posición", 21 | "Menu" : "Menú" 22 | }, 23 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 24 | -------------------------------------------------------------------------------- /l10n/es_HN.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Editar", 3 | "Download" : "Descargar", 4 | "Delete" : "Borrar", 5 | "Name" : "Nombre", 6 | "Save" : "Guardar", 7 | "Back" : "Atrás", 8 | "Reset" : "Restablecer", 9 | "Cancel" : "Cancelar", 10 | "Apply" : "Aplicar", 11 | "Warning" : "Advertencia", 12 | "Confirm" : "Confirmar", 13 | "Undo" : "Deshacer", 14 | "Custom" : "Personalizado", 15 | "Value" : "Valor", 16 | "Text" : "Texto", 17 | "Size" : "Tamaño", 18 | "Position" : "Posición", 19 | "Menu" : "Menú" 20 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 21 | } -------------------------------------------------------------------------------- /l10n/es_NI.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Editar", 5 | "Download" : "Descargar", 6 | "Delete" : "Borrar", 7 | "Name" : "Nombre", 8 | "Save" : "Guardar", 9 | "Back" : "Atrás", 10 | "Reset" : "Restablecer", 11 | "Cancel" : "Cancelar", 12 | "Apply" : "Aplicar", 13 | "Confirm" : "Confirmar", 14 | "Undo" : "Deshacer", 15 | "Custom" : "Personalizado", 16 | "Value" : "Valor", 17 | "Text" : "Texto", 18 | "Size" : "Tamaño", 19 | "Position" : "Posición", 20 | "Menu" : "Menú" 21 | }, 22 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 23 | -------------------------------------------------------------------------------- /l10n/es_NI.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Editar", 3 | "Download" : "Descargar", 4 | "Delete" : "Borrar", 5 | "Name" : "Nombre", 6 | "Save" : "Guardar", 7 | "Back" : "Atrás", 8 | "Reset" : "Restablecer", 9 | "Cancel" : "Cancelar", 10 | "Apply" : "Aplicar", 11 | "Confirm" : "Confirmar", 12 | "Undo" : "Deshacer", 13 | "Custom" : "Personalizado", 14 | "Value" : "Valor", 15 | "Text" : "Texto", 16 | "Size" : "Tamaño", 17 | "Position" : "Posición", 18 | "Menu" : "Menú" 19 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 20 | } -------------------------------------------------------------------------------- /l10n/es_PA.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Editar", 5 | "Download" : "Descargar", 6 | "Delete" : "Borrar", 7 | "Name" : "Nombre", 8 | "Save" : "Guardar", 9 | "Back" : "Atrás", 10 | "Reset" : "Restablecer", 11 | "Cancel" : "Cancelar", 12 | "Apply" : "Aplicar", 13 | "Confirm" : "Confirmar", 14 | "Undo" : "Deshacer", 15 | "Custom" : "Personalizado", 16 | "Value" : "Valor", 17 | "Text" : "Texto", 18 | "Size" : "Tamaño", 19 | "Position" : "Posición", 20 | "Menu" : "Menú" 21 | }, 22 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 23 | -------------------------------------------------------------------------------- /l10n/es_PA.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Editar", 3 | "Download" : "Descargar", 4 | "Delete" : "Borrar", 5 | "Name" : "Nombre", 6 | "Save" : "Guardar", 7 | "Back" : "Atrás", 8 | "Reset" : "Restablecer", 9 | "Cancel" : "Cancelar", 10 | "Apply" : "Aplicar", 11 | "Confirm" : "Confirmar", 12 | "Undo" : "Deshacer", 13 | "Custom" : "Personalizado", 14 | "Value" : "Valor", 15 | "Text" : "Texto", 16 | "Size" : "Tamaño", 17 | "Position" : "Posición", 18 | "Menu" : "Menú" 19 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 20 | } -------------------------------------------------------------------------------- /l10n/es_PE.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Editar", 5 | "Download" : "Descargar", 6 | "Delete" : "Borrar", 7 | "Name" : "Nombre", 8 | "Save" : "Guardar", 9 | "Back" : "Atrás", 10 | "Reset" : "Restablecer", 11 | "Cancel" : "Cancelar", 12 | "Apply" : "Aplicar", 13 | "Warning" : "Advertencia", 14 | "Confirm" : "Confirmar", 15 | "Undo" : "Deshacer", 16 | "Custom" : "Personalizado", 17 | "Value" : "Valor", 18 | "Text" : "Texto", 19 | "Size" : "Tamaño", 20 | "Position" : "Posición", 21 | "Menu" : "Menú" 22 | }, 23 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 24 | -------------------------------------------------------------------------------- /l10n/es_PE.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Editar", 3 | "Download" : "Descargar", 4 | "Delete" : "Borrar", 5 | "Name" : "Nombre", 6 | "Save" : "Guardar", 7 | "Back" : "Atrás", 8 | "Reset" : "Restablecer", 9 | "Cancel" : "Cancelar", 10 | "Apply" : "Aplicar", 11 | "Warning" : "Advertencia", 12 | "Confirm" : "Confirmar", 13 | "Undo" : "Deshacer", 14 | "Custom" : "Personalizado", 15 | "Value" : "Valor", 16 | "Text" : "Texto", 17 | "Size" : "Tamaño", 18 | "Position" : "Posición", 19 | "Menu" : "Menú" 20 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 21 | } -------------------------------------------------------------------------------- /l10n/es_PR.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Editar", 5 | "Download" : "Descargar", 6 | "Delete" : "Borrar", 7 | "Name" : "Nombre", 8 | "Save" : "Guardar", 9 | "Back" : "Atrás", 10 | "Reset" : "Restablecer", 11 | "Cancel" : "Cancelar", 12 | "Apply" : "Aplicar", 13 | "Confirm" : "Confirmar", 14 | "Undo" : "Deshacer", 15 | "Custom" : "Personalizado", 16 | "Value" : "Valor", 17 | "Text" : "Texto", 18 | "Size" : "Tamaño", 19 | "Position" : "Posición", 20 | "Menu" : "Menú" 21 | }, 22 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 23 | -------------------------------------------------------------------------------- /l10n/es_PR.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Editar", 3 | "Download" : "Descargar", 4 | "Delete" : "Borrar", 5 | "Name" : "Nombre", 6 | "Save" : "Guardar", 7 | "Back" : "Atrás", 8 | "Reset" : "Restablecer", 9 | "Cancel" : "Cancelar", 10 | "Apply" : "Aplicar", 11 | "Confirm" : "Confirmar", 12 | "Undo" : "Deshacer", 13 | "Custom" : "Personalizado", 14 | "Value" : "Valor", 15 | "Text" : "Texto", 16 | "Size" : "Tamaño", 17 | "Position" : "Posición", 18 | "Menu" : "Menú" 19 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 20 | } -------------------------------------------------------------------------------- /l10n/es_PY.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Visor", 5 | "Error loading {name}" : "Se presentó un error al cargar {name}", 6 | "Your browser does not support videos." : "Tu navegador no soporta videos.", 7 | "Edit" : "Editar", 8 | "Open sidebar" : "Abrir barra lateral", 9 | "Download" : "Descargar", 10 | "Delete" : "Borrar", 11 | "Name" : "Nombre", 12 | "Save" : "Guardar", 13 | "Back" : "Atrás", 14 | "Reset" : "Restablecer", 15 | "Cancel" : "Cancelar", 16 | "Apply" : "Aplicar", 17 | "Confirm" : "Confirmar", 18 | "Undo" : "Deshacer", 19 | "Custom" : "Personalizado", 20 | "Value" : "Valor", 21 | "Text" : "Texto", 22 | "Size" : "Tamaño", 23 | "Position" : "Posición", 24 | "Menu" : "Menú" 25 | }, 26 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 27 | -------------------------------------------------------------------------------- /l10n/es_PY.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Visor", 3 | "Error loading {name}" : "Se presentó un error al cargar {name}", 4 | "Your browser does not support videos." : "Tu navegador no soporta videos.", 5 | "Edit" : "Editar", 6 | "Open sidebar" : "Abrir barra lateral", 7 | "Download" : "Descargar", 8 | "Delete" : "Borrar", 9 | "Name" : "Nombre", 10 | "Save" : "Guardar", 11 | "Back" : "Atrás", 12 | "Reset" : "Restablecer", 13 | "Cancel" : "Cancelar", 14 | "Apply" : "Aplicar", 15 | "Confirm" : "Confirmar", 16 | "Undo" : "Deshacer", 17 | "Custom" : "Personalizado", 18 | "Value" : "Valor", 19 | "Text" : "Texto", 20 | "Size" : "Tamaño", 21 | "Position" : "Posición", 22 | "Menu" : "Menú" 23 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 24 | } -------------------------------------------------------------------------------- /l10n/es_SV.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Image saved" : "Imagen guardada", 5 | "Edit" : "Editar", 6 | "Download" : "Descargar", 7 | "Delete" : "Borrar", 8 | "Name" : "Nombre", 9 | "Save" : "Guardar", 10 | "Back" : "Atrás", 11 | "Reset" : "Restablecer", 12 | "Cancel" : "Cancelar", 13 | "Apply" : "Aplicar", 14 | "Confirm" : "Confirmar", 15 | "Undo" : "Deshacer", 16 | "Custom" : "Personalizado", 17 | "Value" : "Valor", 18 | "Text" : "Texto", 19 | "Size" : "Tamaño", 20 | "Position" : "Posición", 21 | "Menu" : "Menú" 22 | }, 23 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 24 | -------------------------------------------------------------------------------- /l10n/es_SV.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Image saved" : "Imagen guardada", 3 | "Edit" : "Editar", 4 | "Download" : "Descargar", 5 | "Delete" : "Borrar", 6 | "Name" : "Nombre", 7 | "Save" : "Guardar", 8 | "Back" : "Atrás", 9 | "Reset" : "Restablecer", 10 | "Cancel" : "Cancelar", 11 | "Apply" : "Aplicar", 12 | "Confirm" : "Confirmar", 13 | "Undo" : "Deshacer", 14 | "Custom" : "Personalizado", 15 | "Value" : "Valor", 16 | "Text" : "Texto", 17 | "Size" : "Tamaño", 18 | "Position" : "Posición", 19 | "Menu" : "Menú" 20 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 21 | } -------------------------------------------------------------------------------- /l10n/es_UY.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Editar", 5 | "Download" : "Descargar", 6 | "Delete" : "Borrar", 7 | "Name" : "Nombre", 8 | "Save" : "Guardar", 9 | "Back" : "Atrás", 10 | "Reset" : "Restablecer", 11 | "Cancel" : "Cancelar", 12 | "Apply" : "Aplicar", 13 | "Warning" : "Advertencia", 14 | "Confirm" : "Confirmar", 15 | "Undo" : "Deshacer", 16 | "Custom" : "Personalizado", 17 | "Value" : "Valor", 18 | "Text" : "Texto", 19 | "Size" : "Tamaño", 20 | "Position" : "Posición", 21 | "Menu" : "Menú" 22 | }, 23 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 24 | -------------------------------------------------------------------------------- /l10n/es_UY.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Editar", 3 | "Download" : "Descargar", 4 | "Delete" : "Borrar", 5 | "Name" : "Nombre", 6 | "Save" : "Guardar", 7 | "Back" : "Atrás", 8 | "Reset" : "Restablecer", 9 | "Cancel" : "Cancelar", 10 | "Apply" : "Aplicar", 11 | "Warning" : "Advertencia", 12 | "Confirm" : "Confirmar", 13 | "Undo" : "Deshacer", 14 | "Custom" : "Personalizado", 15 | "Value" : "Valor", 16 | "Text" : "Texto", 17 | "Size" : "Tamaño", 18 | "Position" : "Posición", 19 | "Menu" : "Menú" 20 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 21 | } -------------------------------------------------------------------------------- /l10n/gd.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Deasaich", 5 | "Open sidebar" : "Fosgail am bàr-taoibh", 6 | "Download" : "Luchdaich a-nuas", 7 | "Delete" : "Sguab às", 8 | "Name" : "Ainm", 9 | "Save" : "Sàbhail", 10 | "Back" : "Air ais", 11 | "Cancel" : "Sguir dheth", 12 | "Undo" : "Neo-dhèan" 13 | }, 14 | "nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;"); 15 | -------------------------------------------------------------------------------- /l10n/gd.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Deasaich", 3 | "Open sidebar" : "Fosgail am bàr-taoibh", 4 | "Download" : "Luchdaich a-nuas", 5 | "Delete" : "Sguab às", 6 | "Name" : "Ainm", 7 | "Save" : "Sàbhail", 8 | "Back" : "Air ais", 9 | "Cancel" : "Sguir dheth", 10 | "Undo" : "Neo-dhèan" 11 | },"pluralForm" :"nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;" 12 | } -------------------------------------------------------------------------------- /l10n/he.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "מציג", 5 | "Simple file viewer with slideshow for media" : "מציג קבצים פשוט עם תמיכה במצגות למדיה", 6 | "Your browser does not support audio." : "הדפדפן שלך אינו תומך בשמע.", 7 | "Error loading {name}" : "שגיאה בטעינת {name}", 8 | "Image saved" : "תמונה נשמרה", 9 | "Your browser does not support videos." : "הדפדפן שלך לא תומך בסרטונים.", 10 | "There is no plugin available to display this file type" : "אין תוסף זמין להצגת סוג הקובץ הזה", 11 | "Edit" : "עריכה", 12 | "Open sidebar" : "פתיחת סרגל הצד", 13 | "Download" : "הורדה", 14 | "Delete" : "מחיקה", 15 | "View" : "צפייה", 16 | "Name" : "שם", 17 | "Save" : "שמירה", 18 | "Back" : "חזרה", 19 | "Loading …" : "בטעינה…", 20 | "Reset" : "איפוס", 21 | "Cancel" : "ביטול", 22 | "Apply" : "החלה", 23 | "Warning" : "אזהרה", 24 | "Confirm" : "אישור", 25 | "Undo" : "ביטול", 26 | "Redo" : "שחזור", 27 | "Zoom in" : "התקרבות", 28 | "Custom" : "מותאם אישית", 29 | "Value" : "ערך", 30 | "Image" : "תמונה", 31 | "Text" : "טקסט", 32 | "Size" : "גודל", 33 | "Position" : "מיקום", 34 | "Extension" : "הרחבה", 35 | "Name is required." : "נדרש שם.", 36 | "Quality" : "איכות", 37 | "Menu" : "תפריט", 38 | "Height" : "גובה" 39 | }, 40 | "nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;"); 41 | -------------------------------------------------------------------------------- /l10n/he.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "מציג", 3 | "Simple file viewer with slideshow for media" : "מציג קבצים פשוט עם תמיכה במצגות למדיה", 4 | "Your browser does not support audio." : "הדפדפן שלך אינו תומך בשמע.", 5 | "Error loading {name}" : "שגיאה בטעינת {name}", 6 | "Image saved" : "תמונה נשמרה", 7 | "Your browser does not support videos." : "הדפדפן שלך לא תומך בסרטונים.", 8 | "There is no plugin available to display this file type" : "אין תוסף זמין להצגת סוג הקובץ הזה", 9 | "Edit" : "עריכה", 10 | "Open sidebar" : "פתיחת סרגל הצד", 11 | "Download" : "הורדה", 12 | "Delete" : "מחיקה", 13 | "View" : "צפייה", 14 | "Name" : "שם", 15 | "Save" : "שמירה", 16 | "Back" : "חזרה", 17 | "Loading …" : "בטעינה…", 18 | "Reset" : "איפוס", 19 | "Cancel" : "ביטול", 20 | "Apply" : "החלה", 21 | "Warning" : "אזהרה", 22 | "Confirm" : "אישור", 23 | "Undo" : "ביטול", 24 | "Redo" : "שחזור", 25 | "Zoom in" : "התקרבות", 26 | "Custom" : "מותאם אישית", 27 | "Value" : "ערך", 28 | "Image" : "תמונה", 29 | "Text" : "טקסט", 30 | "Size" : "גודל", 31 | "Position" : "מיקום", 32 | "Extension" : "הרחבה", 33 | "Name is required." : "נדרש שם.", 34 | "Quality" : "איכות", 35 | "Menu" : "תפריט", 36 | "Height" : "גובה" 37 | },"pluralForm" :"nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;" 38 | } -------------------------------------------------------------------------------- /l10n/hr.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Preglednik", 5 | "Simple file viewer with slideshow for media" : "Jednostavan preglednik datoteka s mogućnošću prezentacije medijski datoteka", 6 | "Your browser does not support audio." : "Vaš preglednik ne podržava zvuk.", 7 | "Error loading {name}" : "Pogreška pri učitavanju {name}", 8 | "Image saved" : "Slika je spremljena", 9 | "Your browser does not support videos." : "Vaš preglednik ne podržava videozapise.", 10 | "There is no plugin available to display this file type" : "Nema dostupnog dodatka za prikazivanje ove vrste datoteke", 11 | "Edit" : "Uredi", 12 | "Open sidebar" : "Otvori bočnu traku", 13 | "Download" : "Preuzmi", 14 | "Delete" : "Izbriši", 15 | "View" : "Pregledaj", 16 | "Name" : "Naziv", 17 | "Save" : "Spremi", 18 | "Back" : "Natrag", 19 | "Loading …" : "Učitavanje…", 20 | "Reset" : "Resetiraj", 21 | "Cancel" : "Odustani", 22 | "Apply" : "Potvrdi", 23 | "Warning" : "Upozorenje", 24 | "Confirm" : "Potvrdi", 25 | "Undo" : "Poništi", 26 | "Redo" : "Ponovno", 27 | "Zoom in" : "Uvećaj", 28 | "Original" : "Izvornik", 29 | "Custom" : "Prilagođeno", 30 | "Value" : "Vrijednost", 31 | "Image" : "Slika", 32 | "Text" : "Tekst", 33 | "Size" : "Veličina", 34 | "Position" : "Položaj", 35 | "Extension" : "Proširenje", 36 | "Name is required." : "Ime je obavezno.", 37 | "Quality" : "Kvaliteta", 38 | "Menu" : "Izbornik", 39 | "Height" : "Visina" 40 | }, 41 | "nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"); 42 | -------------------------------------------------------------------------------- /l10n/hr.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Preglednik", 3 | "Simple file viewer with slideshow for media" : "Jednostavan preglednik datoteka s mogućnošću prezentacije medijski datoteka", 4 | "Your browser does not support audio." : "Vaš preglednik ne podržava zvuk.", 5 | "Error loading {name}" : "Pogreška pri učitavanju {name}", 6 | "Image saved" : "Slika je spremljena", 7 | "Your browser does not support videos." : "Vaš preglednik ne podržava videozapise.", 8 | "There is no plugin available to display this file type" : "Nema dostupnog dodatka za prikazivanje ove vrste datoteke", 9 | "Edit" : "Uredi", 10 | "Open sidebar" : "Otvori bočnu traku", 11 | "Download" : "Preuzmi", 12 | "Delete" : "Izbriši", 13 | "View" : "Pregledaj", 14 | "Name" : "Naziv", 15 | "Save" : "Spremi", 16 | "Back" : "Natrag", 17 | "Loading …" : "Učitavanje…", 18 | "Reset" : "Resetiraj", 19 | "Cancel" : "Odustani", 20 | "Apply" : "Potvrdi", 21 | "Warning" : "Upozorenje", 22 | "Confirm" : "Potvrdi", 23 | "Undo" : "Poništi", 24 | "Redo" : "Ponovno", 25 | "Zoom in" : "Uvećaj", 26 | "Original" : "Izvornik", 27 | "Custom" : "Prilagođeno", 28 | "Value" : "Vrijednost", 29 | "Image" : "Slika", 30 | "Text" : "Tekst", 31 | "Size" : "Veličina", 32 | "Position" : "Položaj", 33 | "Extension" : "Proširenje", 34 | "Name is required." : "Ime je obavezno.", 35 | "Quality" : "Kvaliteta", 36 | "Menu" : "Izbornik", 37 | "Height" : "Visina" 38 | },"pluralForm" :"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;" 39 | } -------------------------------------------------------------------------------- /l10n/hy.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "մշակել", 5 | "Download" : "Ներբեռնել", 6 | "Delete" : "հեռացնել", 7 | "Name" : "Անուն", 8 | "Save" : "Պահպանել", 9 | "Cancel" : "ընդհատել", 10 | "Warning" : "Զգուշացում", 11 | "Size" : "Չափս" 12 | }, 13 | "nplurals=2; plural=(n != 1);"); 14 | -------------------------------------------------------------------------------- /l10n/hy.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "մշակել", 3 | "Download" : "Ներբեռնել", 4 | "Delete" : "հեռացնել", 5 | "Name" : "Անուն", 6 | "Save" : "Պահպանել", 7 | "Cancel" : "ընդհատել", 8 | "Warning" : "Զգուշացում", 9 | "Size" : "Չափս" 10 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 11 | } -------------------------------------------------------------------------------- /l10n/ia.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Modificar", 5 | "Download" : "Discargar", 6 | "Delete" : "Deler", 7 | "View" : "Vider", 8 | "Name" : "Nomine", 9 | "Save" : "Salveguardar", 10 | "Back" : "Retro", 11 | "Reset" : "Re-fixar", 12 | "Cancel" : "Cancellar", 13 | "Apply" : "Applicar", 14 | "Warning" : "Aviso", 15 | "Confirm" : "Confirmar", 16 | "Undo" : "Disfacer", 17 | "Custom" : "Personalisate", 18 | "Size" : "Dimension", 19 | "Menu" : "Menu" 20 | }, 21 | "nplurals=2; plural=(n != 1);"); 22 | -------------------------------------------------------------------------------- /l10n/ia.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Modificar", 3 | "Download" : "Discargar", 4 | "Delete" : "Deler", 5 | "View" : "Vider", 6 | "Name" : "Nomine", 7 | "Save" : "Salveguardar", 8 | "Back" : "Retro", 9 | "Reset" : "Re-fixar", 10 | "Cancel" : "Cancellar", 11 | "Apply" : "Applicar", 12 | "Warning" : "Aviso", 13 | "Confirm" : "Confirmar", 14 | "Undo" : "Disfacer", 15 | "Custom" : "Personalisate", 16 | "Size" : "Dimension", 17 | "Menu" : "Menu" 18 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 19 | } -------------------------------------------------------------------------------- /l10n/ka.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "LIVE" : "LIVE", 5 | "Edit" : "Edit", 6 | "Open sidebar" : "Open sidebar", 7 | "Download" : "Download", 8 | "Delete" : "Delete", 9 | "View" : "View", 10 | "Name" : "Name", 11 | "Save" : "Save", 12 | "Back" : "Back", 13 | "Loading …" : "Loading …", 14 | "Reset" : "Reset", 15 | "Cancel" : "Cancel", 16 | "Warning" : "Warning", 17 | "Confirm" : "Confirm", 18 | "Discard changes" : "Discard changes", 19 | "Undo" : "Undo", 20 | "Custom" : "Custom", 21 | "Blur" : "Blur", 22 | "Value" : "Value", 23 | "Image" : "Image", 24 | "Text" : "Text", 25 | "Size" : "Size", 26 | "Position" : "Position", 27 | "Menu" : "Menu" 28 | }, 29 | "nplurals=2; plural=(n!=1);"); 30 | -------------------------------------------------------------------------------- /l10n/ka.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "LIVE" : "LIVE", 3 | "Edit" : "Edit", 4 | "Open sidebar" : "Open sidebar", 5 | "Download" : "Download", 6 | "Delete" : "Delete", 7 | "View" : "View", 8 | "Name" : "Name", 9 | "Save" : "Save", 10 | "Back" : "Back", 11 | "Loading …" : "Loading …", 12 | "Reset" : "Reset", 13 | "Cancel" : "Cancel", 14 | "Warning" : "Warning", 15 | "Confirm" : "Confirm", 16 | "Discard changes" : "Discard changes", 17 | "Undo" : "Undo", 18 | "Custom" : "Custom", 19 | "Blur" : "Blur", 20 | "Value" : "Value", 21 | "Image" : "Image", 22 | "Text" : "Text", 23 | "Size" : "Size", 24 | "Position" : "Position", 25 | "Menu" : "Menu" 26 | },"pluralForm" :"nplurals=2; plural=(n!=1);" 27 | } -------------------------------------------------------------------------------- /l10n/ka_GE.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "შეცვლა", 5 | "Download" : "ჩამოტვირთვა", 6 | "Delete" : "წაშლა", 7 | "Name" : "სახელი", 8 | "Save" : "შენახვა", 9 | "Back" : "უკან", 10 | "Reset" : "საწყის მდოგმარეობაში დაბრუნება", 11 | "Cancel" : "უარყოფა", 12 | "Apply" : "გამოყენება", 13 | "Warning" : "გაფრთხილება", 14 | "Confirm" : "დადასტურება", 15 | "Undo" : "დაბრუნება", 16 | "Custom" : "ინდივიდუალური", 17 | "Value" : "მნიშვნელობა", 18 | "Text" : "ტექსტი", 19 | "Size" : "ზომა", 20 | "Position" : "პოზიცია", 21 | "Menu" : "მენიუ" 22 | }, 23 | "nplurals=2; plural=(n!=1);"); 24 | -------------------------------------------------------------------------------- /l10n/ka_GE.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "შეცვლა", 3 | "Download" : "ჩამოტვირთვა", 4 | "Delete" : "წაშლა", 5 | "Name" : "სახელი", 6 | "Save" : "შენახვა", 7 | "Back" : "უკან", 8 | "Reset" : "საწყის მდოგმარეობაში დაბრუნება", 9 | "Cancel" : "უარყოფა", 10 | "Apply" : "გამოყენება", 11 | "Warning" : "გაფრთხილება", 12 | "Confirm" : "დადასტურება", 13 | "Undo" : "დაბრუნება", 14 | "Custom" : "ინდივიდუალური", 15 | "Value" : "მნიშვნელობა", 16 | "Text" : "ტექსტი", 17 | "Size" : "ზომა", 18 | "Position" : "პოზიცია", 19 | "Menu" : "მენიუ" 20 | },"pluralForm" :"nplurals=2; plural=(n!=1);" 21 | } -------------------------------------------------------------------------------- /l10n/kab.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Ẓreg", 5 | "Download" : "Sider", 6 | "Delete" : "Kkes", 7 | "Name" : "Nom", 8 | "Save" : "Sekles", 9 | "Back" : "Retour", 10 | "Loading …" : "Asali ...", 11 | "Cancel" : "Sefsex", 12 | "Warning" : "Alɣu", 13 | "Confirm" : "Serggeg", 14 | "Size" : "Teɣzi" 15 | }, 16 | "nplurals=2; plural=(n != 1);"); 17 | -------------------------------------------------------------------------------- /l10n/kab.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Ẓreg", 3 | "Download" : "Sider", 4 | "Delete" : "Kkes", 5 | "Name" : "Nom", 6 | "Save" : "Sekles", 7 | "Back" : "Retour", 8 | "Loading …" : "Asali ...", 9 | "Cancel" : "Sefsex", 10 | "Warning" : "Alɣu", 11 | "Confirm" : "Serggeg", 12 | "Size" : "Teɣzi" 13 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 14 | } -------------------------------------------------------------------------------- /l10n/km.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "កែប្រែ", 5 | "Download" : "ទាញយក", 6 | "Delete" : "លុប", 7 | "Name" : "ឈ្មោះ", 8 | "Save" : "រក្សាទុក", 9 | "Back" : "ត្រឡប់ក្រោយ", 10 | "Cancel" : "បោះបង់", 11 | "Apply" : "អនុវត្ត", 12 | "Warning" : "បម្រាម", 13 | "Value" : "តម្លៃ", 14 | "Line" : "បន្ទាត់", 15 | "Size" : "ទំហំ" 16 | }, 17 | "nplurals=1; plural=0;"); 18 | -------------------------------------------------------------------------------- /l10n/km.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "កែប្រែ", 3 | "Download" : "ទាញយក", 4 | "Delete" : "លុប", 5 | "Name" : "ឈ្មោះ", 6 | "Save" : "រក្សាទុក", 7 | "Back" : "ត្រឡប់ក្រោយ", 8 | "Cancel" : "បោះបង់", 9 | "Apply" : "អនុវត្ត", 10 | "Warning" : "បម្រាម", 11 | "Value" : "តម្លៃ", 12 | "Line" : "បន្ទាត់", 13 | "Size" : "ទំហំ" 14 | },"pluralForm" :"nplurals=1; plural=0;" 15 | } -------------------------------------------------------------------------------- /l10n/kn.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "ಸಂಪಾದಿಸು", 5 | "Download" : "ಪ್ರತಿಯನ್ನು ಸ್ಥಳೀಯವಾಗಿ ಉಳಿಸಿಕೊಳ್ಳಿ", 6 | "Delete" : "ಅಳಿಸಿ", 7 | "Name" : "ಹೆಸರು", 8 | "Save" : "ಉಳಿಸಿ", 9 | "Reset" : "ಮರುಹೊಂದಿಸಿ", 10 | "Cancel" : "ರದ್ದು", 11 | "Warning" : "ಎಚ್ಚರಿಕೆ", 12 | "Size" : " ಗಾತ್ರ" 13 | }, 14 | "nplurals=2; plural=(n > 1);"); 15 | -------------------------------------------------------------------------------- /l10n/kn.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "ಸಂಪಾದಿಸು", 3 | "Download" : "ಪ್ರತಿಯನ್ನು ಸ್ಥಳೀಯವಾಗಿ ಉಳಿಸಿಕೊಳ್ಳಿ", 4 | "Delete" : "ಅಳಿಸಿ", 5 | "Name" : "ಹೆಸರು", 6 | "Save" : "ಉಳಿಸಿ", 7 | "Reset" : "ಮರುಹೊಂದಿಸಿ", 8 | "Cancel" : "ರದ್ದು", 9 | "Warning" : "ಎಚ್ಚರಿಕೆ", 10 | "Size" : " ಗಾತ್ರ" 11 | },"pluralForm" :"nplurals=2; plural=(n > 1);" 12 | } -------------------------------------------------------------------------------- /l10n/lb.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Änneren", 5 | "Download" : "Eroflueden", 6 | "Delete" : "Läschen", 7 | "Name" : "Numm", 8 | "Save" : "Späicheren", 9 | "Back" : "Zeréck", 10 | "Reset" : "Zeréck setzen", 11 | "Cancel" : "Ofbriechen", 12 | "Apply" : "Uwenden", 13 | "Warning" : "Warnung", 14 | "Confirm" : "Konfirméieren", 15 | "Custom" : "Individualiséier", 16 | "Size" : "Gréisst", 17 | "Menu" : "Menü" 18 | }, 19 | "nplurals=2; plural=(n != 1);"); 20 | -------------------------------------------------------------------------------- /l10n/lb.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Änneren", 3 | "Download" : "Eroflueden", 4 | "Delete" : "Läschen", 5 | "Name" : "Numm", 6 | "Save" : "Späicheren", 7 | "Back" : "Zeréck", 8 | "Reset" : "Zeréck setzen", 9 | "Cancel" : "Ofbriechen", 10 | "Apply" : "Uwenden", 11 | "Warning" : "Warnung", 12 | "Confirm" : "Konfirméieren", 13 | "Custom" : "Individualiséier", 14 | "Size" : "Gréisst", 15 | "Menu" : "Menü" 16 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 17 | } -------------------------------------------------------------------------------- /l10n/lo.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "ແກ້ໄຂ", 5 | "Open sidebar" : "ເປີດແທບດ້ານຂ້າງ", 6 | "Download" : "ດາວໂຫລດ", 7 | "Delete" : "ລຶບ", 8 | "Name" : "ຊື່", 9 | "Save" : "ບັນທຶກ", 10 | "Back" : "ຫຼັງ", 11 | "Loading …" : "ກຳລັງໂຫຼດ", 12 | "Cancel" : "ຍົກເລີກ", 13 | "Confirm" : "ຢືນຢັນ", 14 | "Original" : "ຕົ້ນສະບັບ", 15 | "Size" : "ຂະຫນາດ" 16 | }, 17 | "nplurals=1; plural=0;"); 18 | -------------------------------------------------------------------------------- /l10n/lo.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "ແກ້ໄຂ", 3 | "Open sidebar" : "ເປີດແທບດ້ານຂ້າງ", 4 | "Download" : "ດາວໂຫລດ", 5 | "Delete" : "ລຶບ", 6 | "Name" : "ຊື່", 7 | "Save" : "ບັນທຶກ", 8 | "Back" : "ຫຼັງ", 9 | "Loading …" : "ກຳລັງໂຫຼດ", 10 | "Cancel" : "ຍົກເລີກ", 11 | "Confirm" : "ຢືນຢັນ", 12 | "Original" : "ຕົ້ນສະບັບ", 13 | "Size" : "ຂະຫນາດ" 14 | },"pluralForm" :"nplurals=1; plural=0;" 15 | } -------------------------------------------------------------------------------- /l10n/lv.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Skatītājs", 5 | "Simple file viewer with slideshow for media" : "Vienkāršs datņu skatītājs ar slīdrādi informācijas nesējiem", 6 | "Error loading {name}" : "Kļūda ielādējot {name}", 7 | "Your browser does not support videos." : "Pārlūks nenodrošina video", 8 | "Edit" : "Labot", 9 | "Exit full screen" : "Iziet no pilnekrāna", 10 | "Open sidebar" : "Atvērt sānjoslu", 11 | "Download" : "Lejupielādēt", 12 | "Delete" : "Izdzēst", 13 | "View" : "Skats", 14 | "Name" : "Vārds", 15 | "Save" : "Saglabāt", 16 | "Save as" : "Saglabāt kā", 17 | "Back" : "Atpakaļ", 18 | "Loading …" : "Ielādē…", 19 | "Reset" : "Atiestatīt", 20 | "Cancel" : "Atcelt", 21 | "Apply" : "Apstiprināt", 22 | "Warning" : "Brīdinājums", 23 | "Confirm" : "Apstiprināt", 24 | "Undo" : "Atsaukt", 25 | "Redo" : "Atcelt atsaukšanu", 26 | "Filters" : "Filtri", 27 | "Watermark" : "Ūdenszīme", 28 | "are not images" : "nav attēli", 29 | "is not an image" : "nav attēls", 30 | "Original" : "Oriģināls", 31 | "Custom" : "Pielāgots", 32 | "Landscape" : "Ainava", 33 | "Portrait" : "Portrets", 34 | "Value" : "Vērtība", 35 | "Image" : "Attēli", 36 | "Text" : "Teksts", 37 | "Size" : "Izmērs", 38 | "Save image as" : "Saglabāt attēlu kā", 39 | "Name is required." : "Vārds ir nepieciešams.", 40 | "Quality" : "Kvalitāte", 41 | "Saved image size (width x height)" : "Saglabātā attēla izmērs (platums x augstums)", 42 | "Actual size (100%)" : "Faktiskais izmērs (100%)", 43 | "Fit size" : "Atbilst izmēram", 44 | "Menu" : "Izvēlne" 45 | }, 46 | "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"); 47 | -------------------------------------------------------------------------------- /l10n/lv.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Skatītājs", 3 | "Simple file viewer with slideshow for media" : "Vienkāršs datņu skatītājs ar slīdrādi informācijas nesējiem", 4 | "Error loading {name}" : "Kļūda ielādējot {name}", 5 | "Your browser does not support videos." : "Pārlūks nenodrošina video", 6 | "Edit" : "Labot", 7 | "Exit full screen" : "Iziet no pilnekrāna", 8 | "Open sidebar" : "Atvērt sānjoslu", 9 | "Download" : "Lejupielādēt", 10 | "Delete" : "Izdzēst", 11 | "View" : "Skats", 12 | "Name" : "Vārds", 13 | "Save" : "Saglabāt", 14 | "Save as" : "Saglabāt kā", 15 | "Back" : "Atpakaļ", 16 | "Loading …" : "Ielādē…", 17 | "Reset" : "Atiestatīt", 18 | "Cancel" : "Atcelt", 19 | "Apply" : "Apstiprināt", 20 | "Warning" : "Brīdinājums", 21 | "Confirm" : "Apstiprināt", 22 | "Undo" : "Atsaukt", 23 | "Redo" : "Atcelt atsaukšanu", 24 | "Filters" : "Filtri", 25 | "Watermark" : "Ūdenszīme", 26 | "are not images" : "nav attēli", 27 | "is not an image" : "nav attēls", 28 | "Original" : "Oriģināls", 29 | "Custom" : "Pielāgots", 30 | "Landscape" : "Ainava", 31 | "Portrait" : "Portrets", 32 | "Value" : "Vērtība", 33 | "Image" : "Attēli", 34 | "Text" : "Teksts", 35 | "Size" : "Izmērs", 36 | "Save image as" : "Saglabāt attēlu kā", 37 | "Name is required." : "Vārds ir nepieciešams.", 38 | "Quality" : "Kvalitāte", 39 | "Saved image size (width x height)" : "Saglabātā attēla izmērs (platums x augstums)", 40 | "Actual size (100%)" : "Faktiskais izmērs (100%)", 41 | "Fit size" : "Atbilst izmēram", 42 | "Menu" : "Izvēlne" 43 | },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" 44 | } -------------------------------------------------------------------------------- /l10n/mn.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "засварлах", 5 | "Download" : "Татах", 6 | "Delete" : "Устгах", 7 | "Name" : "Нэр", 8 | "Save" : "Хадгалах", 9 | "Back" : "буцах", 10 | "Loading …" : "Уншиж байна...", 11 | "Reset" : "тохируулах", 12 | "Cancel" : "болиулах", 13 | "Apply" : "хэрэглэх", 14 | "Confirm" : "Батлах", 15 | "Undo" : "буцах", 16 | "Custom" : "Дурын", 17 | "Value" : "Үнийн дүн", 18 | "Size" : "Хэмжээ", 19 | "Position" : "Байр" 20 | }, 21 | "nplurals=2; plural=(n != 1);"); 22 | -------------------------------------------------------------------------------- /l10n/mn.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "засварлах", 3 | "Download" : "Татах", 4 | "Delete" : "Устгах", 5 | "Name" : "Нэр", 6 | "Save" : "Хадгалах", 7 | "Back" : "буцах", 8 | "Loading …" : "Уншиж байна...", 9 | "Reset" : "тохируулах", 10 | "Cancel" : "болиулах", 11 | "Apply" : "хэрэглэх", 12 | "Confirm" : "Батлах", 13 | "Undo" : "буцах", 14 | "Custom" : "Дурын", 15 | "Value" : "Үнийн дүн", 16 | "Size" : "Хэмжээ", 17 | "Position" : "Байр" 18 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 19 | } -------------------------------------------------------------------------------- /l10n/ms_MY.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Sunting", 5 | "Download" : "Muat turun", 6 | "Delete" : "Padam", 7 | "Name" : "Nama", 8 | "Save" : "Simpan", 9 | "Back" : "Kembali", 10 | "Cancel" : "Batal", 11 | "Warning" : "Amaran", 12 | "Value" : "Nilai", 13 | "Size" : "Saiz" 14 | }, 15 | "nplurals=1; plural=0;"); 16 | -------------------------------------------------------------------------------- /l10n/ms_MY.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Sunting", 3 | "Download" : "Muat turun", 4 | "Delete" : "Padam", 5 | "Name" : "Nama", 6 | "Save" : "Simpan", 7 | "Back" : "Kembali", 8 | "Cancel" : "Batal", 9 | "Warning" : "Amaran", 10 | "Value" : "Nilai", 11 | "Size" : "Saiz" 12 | },"pluralForm" :"nplurals=1; plural=0;" 13 | } -------------------------------------------------------------------------------- /l10n/nn_NO.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Rediger", 5 | "Open sidebar" : "Opne sidestolpe", 6 | "Download" : "Last ned", 7 | "Delete" : "Ta bort", 8 | "Name" : "Namn", 9 | "Save" : "Lagre", 10 | "Back" : "Tilbake", 11 | "Cancel" : "Avbryt", 12 | "Apply" : "Anvend", 13 | "Warning" : "Åtvaring", 14 | "Value" : "Verdi", 15 | "Size" : "Storleik" 16 | }, 17 | "nplurals=2; plural=(n != 1);"); 18 | -------------------------------------------------------------------------------- /l10n/nn_NO.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Rediger", 3 | "Open sidebar" : "Opne sidestolpe", 4 | "Download" : "Last ned", 5 | "Delete" : "Ta bort", 6 | "Name" : "Namn", 7 | "Save" : "Lagre", 8 | "Back" : "Tilbake", 9 | "Cancel" : "Avbryt", 10 | "Apply" : "Anvend", 11 | "Warning" : "Åtvaring", 12 | "Value" : "Verdi", 13 | "Size" : "Storleik" 14 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 15 | } -------------------------------------------------------------------------------- /l10n/oc.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Visualizaira", 5 | "Simple file viewer with slideshow for media" : "Visionador de fichièrs simples amb diaporama pels mèdias", 6 | "Your browser does not support audio." : "Vòstre navigador pren pas encarga l’àudio.", 7 | "Error loading {name}" : "Error en cargant {name}", 8 | "Your browser does not support videos." : "Vòstre navigador pren pas encarga las vidèos.", 9 | "There is no plugin available to display this file type" : "I a pas cap d’extension per afichar aqueste tipe de fichièr", 10 | "Edit" : "Modificar", 11 | "Open sidebar" : "Dobrir panèl lateral", 12 | "Download" : "Telecargar", 13 | "Delete" : "Suprimir", 14 | "View" : "Vista", 15 | "Name" : "Nom", 16 | "Save" : "Enregistrar", 17 | "Back" : "Retorn", 18 | "Loading …" : "Cargament…", 19 | "Reset" : "Reïnicializar", 20 | "Cancel" : "Anullar", 21 | "Apply" : "Aplicar", 22 | "Warning" : "Avertiment", 23 | "Confirm" : "Confirmar", 24 | "Undo" : "Desfar", 25 | "Redo" : "Refar", 26 | "Custom" : "Personalizar", 27 | "Portrait" : "Retrach", 28 | "Value" : "Valor", 29 | "Line" : "Linha", 30 | "Text" : "Tèxt", 31 | "Size" : "Talha", 32 | "Position" : "Posicion", 33 | "Extension" : "Extension", 34 | "Menu" : "Menú" 35 | }, 36 | "nplurals=2; plural=(n > 1);"); 37 | -------------------------------------------------------------------------------- /l10n/oc.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Visualizaira", 3 | "Simple file viewer with slideshow for media" : "Visionador de fichièrs simples amb diaporama pels mèdias", 4 | "Your browser does not support audio." : "Vòstre navigador pren pas encarga l’àudio.", 5 | "Error loading {name}" : "Error en cargant {name}", 6 | "Your browser does not support videos." : "Vòstre navigador pren pas encarga las vidèos.", 7 | "There is no plugin available to display this file type" : "I a pas cap d’extension per afichar aqueste tipe de fichièr", 8 | "Edit" : "Modificar", 9 | "Open sidebar" : "Dobrir panèl lateral", 10 | "Download" : "Telecargar", 11 | "Delete" : "Suprimir", 12 | "View" : "Vista", 13 | "Name" : "Nom", 14 | "Save" : "Enregistrar", 15 | "Back" : "Retorn", 16 | "Loading …" : "Cargament…", 17 | "Reset" : "Reïnicializar", 18 | "Cancel" : "Anullar", 19 | "Apply" : "Aplicar", 20 | "Warning" : "Avertiment", 21 | "Confirm" : "Confirmar", 22 | "Undo" : "Desfar", 23 | "Redo" : "Refar", 24 | "Custom" : "Personalizar", 25 | "Portrait" : "Retrach", 26 | "Value" : "Valor", 27 | "Line" : "Linha", 28 | "Text" : "Tèxt", 29 | "Size" : "Talha", 30 | "Position" : "Posicion", 31 | "Extension" : "Extension", 32 | "Menu" : "Menú" 33 | },"pluralForm" :"nplurals=2; plural=(n > 1);" 34 | } -------------------------------------------------------------------------------- /l10n/ps.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "شسیب", 5 | "Download" : "ښکته کول", 6 | "Delete" : "ړنګول", 7 | "Name" : "نوم", 8 | "Save" : "ساتل", 9 | "Cancel" : "پرېښول", 10 | "Size" : "کچه" 11 | }, 12 | "nplurals=2; plural=(n != 1);"); 13 | -------------------------------------------------------------------------------- /l10n/ps.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "شسیب", 3 | "Download" : "ښکته کول", 4 | "Delete" : "ړنګول", 5 | "Name" : "نوم", 6 | "Save" : "ساتل", 7 | "Cancel" : "پرېښول", 8 | "Size" : "کچه" 9 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 10 | } -------------------------------------------------------------------------------- /l10n/pt_PT.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Visualizador", 5 | "Simple file viewer with slideshow for media" : "Um visualizador de ficheiros com diaporamas para multimédia", 6 | "Your browser does not support audio." : "O seu navegador não suporta áudio.", 7 | "Error loading {name}" : "Erro ao carregar {name}", 8 | "Image saved" : "Imagem guardada", 9 | "LIVE" : "LIVE", 10 | "Your browser does not support videos." : "O seu navegador não suporta vídeos.", 11 | "Edit" : "Editar", 12 | "Open sidebar" : "Abrir barra lateral", 13 | "Download" : "Transferir", 14 | "Delete" : "Apagar", 15 | "View" : "Ver", 16 | "Name" : "Nome", 17 | "Save" : "Guardar", 18 | "Back" : "Anterior", 19 | "Loading …" : "A carregar...", 20 | "Reset" : "Reiniciar", 21 | "Cancel" : "Cancelar", 22 | "Apply" : "Aplicar", 23 | "Warning" : "Aviso", 24 | "Confirm" : "Confirmar", 25 | "Undo" : "Desfazer", 26 | "Redo" : "Repetir", 27 | "Filters" : "Filtros", 28 | "Original" : "Original", 29 | "Custom" : "Personalizado", 30 | "Value" : "Valor", 31 | "Image" : "Imagem", 32 | "Line" : "Linha", 33 | "Text" : "Texto", 34 | "Size" : "Altura", 35 | "Name is required." : "Nome é obrigatório.", 36 | "Quality" : "Qualidade", 37 | "Menu" : "Menu", 38 | "Height" : "Altura" 39 | }, 40 | "nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 41 | -------------------------------------------------------------------------------- /l10n/pt_PT.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Visualizador", 3 | "Simple file viewer with slideshow for media" : "Um visualizador de ficheiros com diaporamas para multimédia", 4 | "Your browser does not support audio." : "O seu navegador não suporta áudio.", 5 | "Error loading {name}" : "Erro ao carregar {name}", 6 | "Image saved" : "Imagem guardada", 7 | "LIVE" : "LIVE", 8 | "Your browser does not support videos." : "O seu navegador não suporta vídeos.", 9 | "Edit" : "Editar", 10 | "Open sidebar" : "Abrir barra lateral", 11 | "Download" : "Transferir", 12 | "Delete" : "Apagar", 13 | "View" : "Ver", 14 | "Name" : "Nome", 15 | "Save" : "Guardar", 16 | "Back" : "Anterior", 17 | "Loading …" : "A carregar...", 18 | "Reset" : "Reiniciar", 19 | "Cancel" : "Cancelar", 20 | "Apply" : "Aplicar", 21 | "Warning" : "Aviso", 22 | "Confirm" : "Confirmar", 23 | "Undo" : "Desfazer", 24 | "Redo" : "Repetir", 25 | "Filters" : "Filtros", 26 | "Original" : "Original", 27 | "Custom" : "Personalizado", 28 | "Value" : "Valor", 29 | "Image" : "Imagem", 30 | "Line" : "Linha", 31 | "Text" : "Texto", 32 | "Size" : "Altura", 33 | "Name is required." : "Nome é obrigatório.", 34 | "Quality" : "Qualidade", 35 | "Menu" : "Menu", 36 | "Height" : "Altura" 37 | },"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 38 | } -------------------------------------------------------------------------------- /l10n/sc.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Visualizadore", 5 | "Simple file viewer with slideshow for media" : "Visualizadore de archìvios simpre cun presentatziones pro is media", 6 | "Your browser does not support audio." : "Su navigadore tuo non suportat s'àudio.", 7 | "Error loading {name}" : "Errore de carrigamentu de {name}", 8 | "Image saved" : "Immàgines sarvadas", 9 | "Your browser does not support videos." : "Su navigadore tuo non suportat vìdeos.", 10 | "There is no plugin available to display this file type" : "Non b'at peruna estensione pro visualizare custa genia de archìviu", 11 | "Edit" : "Modìfica", 12 | "Open sidebar" : "Aberi s'istanca laterale", 13 | "Download" : "Iscàrriga", 14 | "Delete" : "Cantzella", 15 | "View" : "Visualiza", 16 | "Name" : "Nùmene", 17 | "Save" : "Sarva", 18 | "Back" : "In segus", 19 | "Loading …" : "Carrigamentu …", 20 | "Reset" : "Ripristina", 21 | "Cancel" : "Annulla", 22 | "Apply" : "Àplica", 23 | "Warning" : "Avisu", 24 | "Confirm" : "Cunfirma", 25 | "Undo" : "Annulla", 26 | "Redo" : "Torra a fàghere", 27 | "Zoom in" : "Ammània", 28 | "Original" : "Originale", 29 | "Custom" : "Personaliza", 30 | "Value" : "Balore", 31 | "Image" : "Immàgine", 32 | "Text" : "Testu", 33 | "Size" : "Mannària", 34 | "Position" : "Positzione", 35 | "Extension" : "Estensione", 36 | "Name is required." : "Su nùmene est rechertu: ", 37 | "Quality" : "Calidade", 38 | "Menu" : "Menu", 39 | "Height" : "Altezza" 40 | }, 41 | "nplurals=2; plural=(n != 1);"); 42 | -------------------------------------------------------------------------------- /l10n/sc.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Visualizadore", 3 | "Simple file viewer with slideshow for media" : "Visualizadore de archìvios simpre cun presentatziones pro is media", 4 | "Your browser does not support audio." : "Su navigadore tuo non suportat s'àudio.", 5 | "Error loading {name}" : "Errore de carrigamentu de {name}", 6 | "Image saved" : "Immàgines sarvadas", 7 | "Your browser does not support videos." : "Su navigadore tuo non suportat vìdeos.", 8 | "There is no plugin available to display this file type" : "Non b'at peruna estensione pro visualizare custa genia de archìviu", 9 | "Edit" : "Modìfica", 10 | "Open sidebar" : "Aberi s'istanca laterale", 11 | "Download" : "Iscàrriga", 12 | "Delete" : "Cantzella", 13 | "View" : "Visualiza", 14 | "Name" : "Nùmene", 15 | "Save" : "Sarva", 16 | "Back" : "In segus", 17 | "Loading …" : "Carrigamentu …", 18 | "Reset" : "Ripristina", 19 | "Cancel" : "Annulla", 20 | "Apply" : "Àplica", 21 | "Warning" : "Avisu", 22 | "Confirm" : "Cunfirma", 23 | "Undo" : "Annulla", 24 | "Redo" : "Torra a fàghere", 25 | "Zoom in" : "Ammània", 26 | "Original" : "Originale", 27 | "Custom" : "Personaliza", 28 | "Value" : "Balore", 29 | "Image" : "Immàgine", 30 | "Text" : "Testu", 31 | "Size" : "Mannària", 32 | "Position" : "Positzione", 33 | "Extension" : "Estensione", 34 | "Name is required." : "Su nùmene est rechertu: ", 35 | "Quality" : "Calidade", 36 | "Menu" : "Menu", 37 | "Height" : "Altezza" 38 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 39 | } -------------------------------------------------------------------------------- /l10n/si.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Error loading {name}" : "{name} පූරණය කිරීමේ දෝෂයකි", 5 | "Edit" : "සංස්කරණය", 6 | "Download" : "බාගන්න", 7 | "Name" : "නම", 8 | "Save" : "සුරකින්න", 9 | "Back" : "ආපසු", 10 | "Loading …" : "පූරණය වෙමින් …", 11 | "Cancel" : "අවලංගු කරන්න", 12 | "Warning" : "අවවාදයයි", 13 | "Confirm" : "තහවුරු කරන්න", 14 | "Undo" : "පෙරසේ", 15 | "Value" : "අගය", 16 | "Size" : "ප්‍රමාණය" 17 | }, 18 | "nplurals=2; plural=(n != 1);"); 19 | -------------------------------------------------------------------------------- /l10n/si.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Error loading {name}" : "{name} පූරණය කිරීමේ දෝෂයකි", 3 | "Edit" : "සංස්කරණය", 4 | "Download" : "බාගන්න", 5 | "Name" : "නම", 6 | "Save" : "සුරකින්න", 7 | "Back" : "ආපසු", 8 | "Loading …" : "පූරණය වෙමින් …", 9 | "Cancel" : "අවලංගු කරන්න", 10 | "Warning" : "අවවාදයයි", 11 | "Confirm" : "තහවුරු කරන්න", 12 | "Undo" : "පෙරසේ", 13 | "Value" : "අගය", 14 | "Size" : "ප්‍රමාණය" 15 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 16 | } -------------------------------------------------------------------------------- /l10n/sq.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Image saved" : "Imazhi u ruajt", 5 | "Edit" : "Përpuno", 6 | "Open sidebar" : "Hapni sidebar-in", 7 | "Download" : "Shkarko", 8 | "Delete" : "Delete", 9 | "View" : "Shiko", 10 | "Name" : "Emri", 11 | "Save" : "Ruaj", 12 | "Back" : "Prapa", 13 | "Reset" : "Rivendos", 14 | "Cancel" : "Anullo", 15 | "Apply" : "Apliko", 16 | "Warning" : "Kujdes", 17 | "Confirm" : "Konfirmo", 18 | "Undo" : "Ktheje pas", 19 | "Redo" : "Ribëj", 20 | "Custom" : "E përshtatur", 21 | "Value" : "Vlerë", 22 | "Text" : "Tekst", 23 | "Size" : "Madhësi", 24 | "Position" : "Pozicion", 25 | "Name is required." : "Emri është i domosdoshëm", 26 | "Menu" : "Menu" 27 | }, 28 | "nplurals=2; plural=(n != 1);"); 29 | -------------------------------------------------------------------------------- /l10n/sq.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Image saved" : "Imazhi u ruajt", 3 | "Edit" : "Përpuno", 4 | "Open sidebar" : "Hapni sidebar-in", 5 | "Download" : "Shkarko", 6 | "Delete" : "Delete", 7 | "View" : "Shiko", 8 | "Name" : "Emri", 9 | "Save" : "Ruaj", 10 | "Back" : "Prapa", 11 | "Reset" : "Rivendos", 12 | "Cancel" : "Anullo", 13 | "Apply" : "Apliko", 14 | "Warning" : "Kujdes", 15 | "Confirm" : "Konfirmo", 16 | "Undo" : "Ktheje pas", 17 | "Redo" : "Ribëj", 18 | "Custom" : "E përshtatur", 19 | "Value" : "Vlerë", 20 | "Text" : "Tekst", 21 | "Size" : "Madhësi", 22 | "Position" : "Pozicion", 23 | "Name is required." : "Emri është i domosdoshëm", 24 | "Menu" : "Menu" 25 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 26 | } -------------------------------------------------------------------------------- /l10n/sr@latin.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Image saved" : "Slika sačuvana.", 5 | "Edit" : "Izmeni", 6 | "Open sidebar" : "Otvori bočnu traku", 7 | "Download" : "Preuzmi", 8 | "Delete" : "Obriši", 9 | "Name" : "Ime", 10 | "Save" : "Sačuvaj", 11 | "Back" : "Nazad", 12 | "Loading …" : "Učitavanje...", 13 | "Cancel" : "Otkaži", 14 | "Warning" : "Upozorenje", 15 | "Undo" : "Opozovi" 16 | }, 17 | "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); 18 | -------------------------------------------------------------------------------- /l10n/sr@latin.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Image saved" : "Slika sačuvana.", 3 | "Edit" : "Izmeni", 4 | "Open sidebar" : "Otvori bočnu traku", 5 | "Download" : "Preuzmi", 6 | "Delete" : "Obriši", 7 | "Name" : "Ime", 8 | "Save" : "Sačuvaj", 9 | "Back" : "Nazad", 10 | "Loading …" : "Učitavanje...", 11 | "Cancel" : "Otkaži", 12 | "Warning" : "Upozorenje", 13 | "Undo" : "Opozovi" 14 | },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" 15 | } -------------------------------------------------------------------------------- /l10n/ta.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "தொகுக்க", 5 | "Download" : "பதிவிறக்குக", 6 | "Delete" : "நீக்குக", 7 | "Name" : "பெயர்", 8 | "Save" : "சேமிக்க ", 9 | "Back" : "பின்னுக்கு", 10 | "Cancel" : "இரத்து செய்க", 11 | "Value" : "Value", 12 | "Size" : "அளவு" 13 | }, 14 | "nplurals=2; plural=(n != 1);"); 15 | -------------------------------------------------------------------------------- /l10n/ta.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "தொகுக்க", 3 | "Download" : "பதிவிறக்குக", 4 | "Delete" : "நீக்குக", 5 | "Name" : "பெயர்", 6 | "Save" : "சேமிக்க ", 7 | "Back" : "பின்னுக்கு", 8 | "Cancel" : "இரத்து செய்க", 9 | "Value" : "Value", 10 | "Size" : "அளவு" 11 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 12 | } -------------------------------------------------------------------------------- /l10n/th.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "แก้ไข", 5 | "Open sidebar" : "เปิดแถบด้านข้าง", 6 | "Download" : "ดาวน์โหลด", 7 | "Delete" : "ลบ", 8 | "View" : "มุมมอง", 9 | "Name" : "ชื่อ", 10 | "Save" : "บันทึก", 11 | "Back" : "ย้อนกลับ", 12 | "Reset" : "รีเซ็ต", 13 | "Cancel" : "ยกเลิก", 14 | "Apply" : "นำไปใช้", 15 | "Warning" : "คำเตือน", 16 | "Confirm" : "ยืนยัน", 17 | "Undo" : "เลิกทำ", 18 | "Custom" : "กำหนดเอง", 19 | "Text" : "ข้อความ", 20 | "Size" : "ขนาด", 21 | "Position" : "ตำแหน่ง", 22 | "Menu" : "เมนู" 23 | }, 24 | "nplurals=1; plural=0;"); 25 | -------------------------------------------------------------------------------- /l10n/th.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "แก้ไข", 3 | "Open sidebar" : "เปิดแถบด้านข้าง", 4 | "Download" : "ดาวน์โหลด", 5 | "Delete" : "ลบ", 6 | "View" : "มุมมอง", 7 | "Name" : "ชื่อ", 8 | "Save" : "บันทึก", 9 | "Back" : "ย้อนกลับ", 10 | "Reset" : "รีเซ็ต", 11 | "Cancel" : "ยกเลิก", 12 | "Apply" : "นำไปใช้", 13 | "Warning" : "คำเตือน", 14 | "Confirm" : "ยืนยัน", 15 | "Undo" : "เลิกทำ", 16 | "Custom" : "กำหนดเอง", 17 | "Text" : "ข้อความ", 18 | "Size" : "ขนาด", 19 | "Position" : "ตำแหน่ง", 20 | "Menu" : "เมนู" 21 | },"pluralForm" :"nplurals=1; plural=0;" 22 | } -------------------------------------------------------------------------------- /l10n/tk.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Redaktirläň", 5 | "Open sidebar" : "Gapdal paneli açyň", 6 | "Download" : "Göçürip almak", 7 | "Delete" : "Pozmak", 8 | "Name" : "Ady", 9 | "Save" : "Saklamak", 10 | "Back" : "Yzyna", 11 | "Cancel" : "ýatyrmak" 12 | }, 13 | "nplurals=2; plural=(n != 1);"); 14 | -------------------------------------------------------------------------------- /l10n/tk.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Redaktirläň", 3 | "Open sidebar" : "Gapdal paneli açyň", 4 | "Download" : "Göçürip almak", 5 | "Delete" : "Pozmak", 6 | "Name" : "Ady", 7 | "Save" : "Saklamak", 8 | "Back" : "Yzyna", 9 | "Cancel" : "ýatyrmak" 10 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 11 | } -------------------------------------------------------------------------------- /l10n/ur_PK.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "تدوین کریں", 5 | "Download" : "ڈاؤن لوڈ", 6 | "Delete" : "حذف کریں", 7 | "Name" : "اسم", 8 | "Save" : "حفظ", 9 | "Reset" : "ری سیٹ", 10 | "Cancel" : "منسوخ کریں", 11 | "Warning" : "انتباہ" 12 | }, 13 | "nplurals=2; plural=(n != 1);"); 14 | -------------------------------------------------------------------------------- /l10n/ur_PK.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "تدوین کریں", 3 | "Download" : "ڈاؤن لوڈ", 4 | "Delete" : "حذف کریں", 5 | "Name" : "اسم", 6 | "Save" : "حفظ", 7 | "Reset" : "ری سیٹ", 8 | "Cancel" : "منسوخ کریں", 9 | "Warning" : "انتباہ" 10 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 11 | } -------------------------------------------------------------------------------- /l10n/uz.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Edit" : "Tahrirlash", 5 | "Download" : "Download", 6 | "Delete" : "Delete", 7 | "Name" : "Name", 8 | "Save" : "Save", 9 | "Back" : "Orqaga", 10 | "Reset" : "Qayta tiklash", 11 | "Cancel" : "Cancel", 12 | "Confirm" : "Confirm", 13 | "Undo" : "Bekor qilish", 14 | "Custom" : "Boshqa", 15 | "Value" : "Qiymati", 16 | "Line" : "Chiziq", 17 | "Text" : "Matn", 18 | "Size" : "Size" 19 | }, 20 | "nplurals=1; plural=0;"); 21 | -------------------------------------------------------------------------------- /l10n/uz.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Edit" : "Tahrirlash", 3 | "Download" : "Download", 4 | "Delete" : "Delete", 5 | "Name" : "Name", 6 | "Save" : "Save", 7 | "Back" : "Orqaga", 8 | "Reset" : "Qayta tiklash", 9 | "Cancel" : "Cancel", 10 | "Confirm" : "Confirm", 11 | "Undo" : "Bekor qilish", 12 | "Custom" : "Boshqa", 13 | "Value" : "Qiymati", 14 | "Line" : "Chiziq", 15 | "Text" : "Matn", 16 | "Size" : "Size" 17 | },"pluralForm" :"nplurals=1; plural=0;" 18 | } -------------------------------------------------------------------------------- /l10n/vi.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "viewer", 3 | { 4 | "Viewer" : "Trình xem", 5 | "Simple file viewer with slideshow for media" : "Trình xem tệp đơn giản có trình chiếu phương tiện", 6 | "Your browser does not support audio." : "Trình duyệt của bạn không hỗ trợ âm thanh.", 7 | "Error loading {name}" : "Lỗi khi tải {name}", 8 | "Image saved" : "Đã lưu hình ảnh", 9 | "Your browser does not support videos." : "Trình duyệt của bạn không hỗ trợ video.", 10 | "There is no plugin available to display this file type" : "Không có plugin nào để hiển thị loại tệp này", 11 | "Edit" : "Chỉnh sửa", 12 | "Open sidebar" : "Mở thanh bên", 13 | "Download" : "Tải xuống", 14 | "Delete" : "Xóa", 15 | "View" : "Xem", 16 | "Name" : "Tên", 17 | "Save" : "Lưu", 18 | "Back" : "Quay lại", 19 | "Loading …" : "Đang tải …", 20 | "Reset" : "Đặt lại", 21 | "Cancel" : "Hủy", 22 | "Apply" : "Áp dụng", 23 | "Warning" : "Cảnh báo", 24 | "Confirm" : "Xác nhận", 25 | "Undo" : "Hoàn tác", 26 | "Redo" : "Làm lại", 27 | "Custom" : "Tùy chỉnh", 28 | "Value" : "Giá trị", 29 | "Image" : "Hình ảnh", 30 | "Line" : "Hàng", 31 | "Text" : "Văn bản", 32 | "Size" : "Kích cỡ", 33 | "Extension" : "Tiện ích", 34 | "Name is required." : "Tên là bắt buộc." 35 | }, 36 | "nplurals=1; plural=0;"); 37 | -------------------------------------------------------------------------------- /l10n/vi.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Viewer" : "Trình xem", 3 | "Simple file viewer with slideshow for media" : "Trình xem tệp đơn giản có trình chiếu phương tiện", 4 | "Your browser does not support audio." : "Trình duyệt của bạn không hỗ trợ âm thanh.", 5 | "Error loading {name}" : "Lỗi khi tải {name}", 6 | "Image saved" : "Đã lưu hình ảnh", 7 | "Your browser does not support videos." : "Trình duyệt của bạn không hỗ trợ video.", 8 | "There is no plugin available to display this file type" : "Không có plugin nào để hiển thị loại tệp này", 9 | "Edit" : "Chỉnh sửa", 10 | "Open sidebar" : "Mở thanh bên", 11 | "Download" : "Tải xuống", 12 | "Delete" : "Xóa", 13 | "View" : "Xem", 14 | "Name" : "Tên", 15 | "Save" : "Lưu", 16 | "Back" : "Quay lại", 17 | "Loading …" : "Đang tải …", 18 | "Reset" : "Đặt lại", 19 | "Cancel" : "Hủy", 20 | "Apply" : "Áp dụng", 21 | "Warning" : "Cảnh báo", 22 | "Confirm" : "Xác nhận", 23 | "Undo" : "Hoàn tác", 24 | "Redo" : "Làm lại", 25 | "Custom" : "Tùy chỉnh", 26 | "Value" : "Giá trị", 27 | "Image" : "Hình ảnh", 28 | "Line" : "Hàng", 29 | "Text" : "Văn bản", 30 | "Size" : "Kích cỡ", 31 | "Extension" : "Tiện ích", 32 | "Name is required." : "Tên là bắt buộc." 33 | },"pluralForm" :"nplurals=1; plural=0;" 34 | } -------------------------------------------------------------------------------- /lib/AppInfo/Application.php: -------------------------------------------------------------------------------- 1 | registerEventListener(LoadViewer::class, LoadViewerScript::class); 27 | } 28 | 29 | public function boot(IBootContext $context): void { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/Event/LoadViewer.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | class LoadViewerScript implements IEventListener { 24 | private IInitialState $initialStateService; 25 | private IPreview $previewManager; 26 | 27 | public function __construct( 28 | IInitialState $initialStateService, 29 | IPreview $previewManager, 30 | ) { 31 | $this->initialStateService = $initialStateService; 32 | $this->previewManager = $previewManager; 33 | } 34 | 35 | public function handle(Event $event): void { 36 | if (!($event instanceof LoadViewer || $event instanceof LoadAdditionalScriptsEvent)) { 37 | return; 38 | } 39 | 40 | Util::addStyle(Application::APP_ID, 'viewer-init'); 41 | Util::addStyle(Application::APP_ID, 'viewer-main'); 42 | Util::addInitScript(Application::APP_ID, 'viewer-init'); 43 | Util::addScript(Application::APP_ID, 'viewer-main', 'files'); 44 | $this->initialStateService->provideInitialState('enabled_preview_providers', array_keys($this->previewManager->getProviders())); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /psalm.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ], 6 | "timezone": "Europe/Berlin", 7 | "schedule": [ 8 | "every weekend" 9 | ], 10 | "reviewers": [ 11 | "skjnldsv" 12 | ], 13 | "labels": [ 14 | "dependencies", 15 | "3. to review" 16 | ], 17 | "rangeStrategy": "bump", 18 | "rebaseWhen": "conflicted", 19 | "ignoreUnstable": false, 20 | "baseBranches": [ 21 | "master", 22 | "stable31", 23 | "stable30" 24 | ], 25 | "enabledManagers": [ 26 | "npm" 27 | ], 28 | "ignoreDeps": [ 29 | "node", 30 | "npm" 31 | ], 32 | "lockFileMaintenance": { 33 | "enabled": true, 34 | "automerge": true 35 | }, 36 | "packageRules": [ 37 | { 38 | "groupName": "cypress", 39 | "matchPackageNames": [ 40 | "/^@cypress//", 41 | "/cypress/", 42 | "/eslint-plugin-cypress/" 43 | ] 44 | }, 45 | { 46 | "groupName": "nextcloud", 47 | "matchPackageNames": [ 48 | "/^@nextcloud//" 49 | ] 50 | }, 51 | { 52 | "groupName": "dockerode", 53 | "matchPackageNames": [ 54 | "@types/dockerode", 55 | "dockerode" 56 | ] 57 | }, 58 | { 59 | "groupName": "typescript", 60 | "matchPackageNames": [ 61 | "tslib", 62 | "typescript" 63 | ] 64 | }, 65 | { 66 | "matchUpdateTypes": [ 67 | "major" 68 | ], 69 | "matchBaseBranches": [ 70 | "stable31", 71 | "stable30" 72 | ], 73 | "enabled": false 74 | }, 75 | { 76 | "matchPackageNames": [ 77 | "vue" 78 | ], 79 | "allowedVersions": "<3" 80 | } 81 | ] 82 | } 83 | -------------------------------------------------------------------------------- /src/assets/menu-sidebar-white.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/components/Error.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | 15 | 27 | 28 | 35 | -------------------------------------------------------------------------------- /src/files_actions/viewerAction.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import type { Node, View } from '@nextcloud/files' 6 | 7 | import { DefaultType, FileAction, Permission, registerFileAction } from '@nextcloud/files' 8 | import { t } from '@nextcloud/l10n' 9 | import svgEye from '@mdi/svg/svg/eye.svg?raw' 10 | 11 | /** 12 | * @param node The file to open 13 | * @param view any The files view 14 | * @param dir the directory path 15 | */ 16 | function pushToHistory(node: Node, view: View, dir: string) { 17 | window.OCP.Files.Router.goToRoute( 18 | null, 19 | { view: view.id, fileid: String(node.fileid) }, 20 | { dir, openfile: 'true' }, 21 | true, 22 | ) 23 | } 24 | 25 | const onPopState = () => { 26 | if (window.OCP.Files.Router.query.openfile !== 'true') { 27 | window.OCA.Viewer.close() 28 | window.removeEventListener('popstate', onPopState) 29 | } 30 | } 31 | 32 | /** 33 | * Execute the viewer files action 34 | * @param node The active node 35 | * @param view The current view 36 | * @param dir The current path 37 | */ 38 | async function execAction(node: Node, view: View, dir: string): Promise { 39 | const onClose = () => { 40 | // This can sometime be called with the openfile set to true already. But we don't want to keep openfile when closing the viewer. 41 | const newQuery = { ...window.OCP.Files.Router.query } 42 | delete newQuery.openfile 43 | window.OCP.Files.Router.goToRoute(null, window.OCP.Files.Router.params, newQuery) 44 | } 45 | 46 | window.addEventListener('popstate', onPopState) 47 | 48 | pushToHistory(node, view, dir) 49 | window.OCA.Viewer.open({ 50 | path: node.path, 51 | onPrev(fileInfo) { 52 | pushToHistory(fileInfo, view, dir) 53 | }, 54 | onNext(fileInfo) { 55 | pushToHistory(fileInfo, view, dir) 56 | }, 57 | onClose, 58 | }) 59 | 60 | return null 61 | } 62 | 63 | /** 64 | * Register the viewer action on the files API 65 | */ 66 | export function registerViewerAction() { 67 | registerFileAction(new FileAction({ 68 | id: 'view', 69 | displayName: () => t('viewer', 'View'), 70 | iconSvgInline: () => svgEye, 71 | default: DefaultType.DEFAULT, 72 | enabled: (nodes) => { 73 | // Disable if not located in user root 74 | if (nodes.some(node => !(node.isDavRessource && node.root?.startsWith('/files')))) { 75 | return false 76 | } 77 | 78 | return nodes.every((node) => 79 | Boolean(node.permissions & Permission.READ) 80 | && window.OCA.Viewer.mimetypes.includes(node.mime), 81 | ) 82 | }, 83 | exec: execAction, 84 | })) 85 | } 86 | -------------------------------------------------------------------------------- /src/global.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | /// 6 | 7 | import type Viewer from './services/Viewer.js' 8 | 9 | declare global { 10 | interface Window { 11 | OCA: { 12 | Viewer: Viewer 13 | } 14 | OCP: Nextcloud.v29.OCP 15 | } 16 | 17 | const appVersion: string 18 | } 19 | 20 | export {} 21 | -------------------------------------------------------------------------------- /src/init.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { registerViewerAction } from './files_actions/viewerAction' 6 | import ViewerService from './services/Viewer.js' 7 | 8 | // Register the files action 9 | registerViewerAction() 10 | 11 | // Init Viewer Service 12 | window.OCA = window.OCA ?? {} 13 | window.OCA.Viewer = new ViewerService() 14 | window.OCA.Viewer.version = appVersion 15 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { translate as t } from '@nextcloud/l10n' 6 | import Vue from 'vue' 7 | 8 | import ViewerComponent from './views/Viewer.vue' 9 | 10 | Vue.mixin({ 11 | methods: { 12 | t, 13 | }, 14 | }) 15 | 16 | Vue.prototype.OC = window.OC 17 | Vue.prototype.OCA = window.OCA 18 | 19 | // Create document root 20 | const ViewerRoot = document.createElement('div') 21 | ViewerRoot.id = 'viewer' 22 | document.body.appendChild(ViewerRoot) 23 | 24 | // Put controls for video viewer 25 | // Needed as Firefox CSP blocks the loading of the svg through the normal plyr system 26 | const VideoControls = document.createElement('div') 27 | VideoControls.innerHTML = PLYR_ICONS 28 | VideoControls.style.display = 'none' 29 | document.body.appendChild(VideoControls) 30 | 31 | // Init vue 32 | export default new Vue({ 33 | el: '#viewer', 34 | // When debugging the page, it's easier to find which app 35 | // is which. Especially when there is multiple apps 36 | // roots mounted o the same page! 37 | // eslint-disable-next-line vue/match-component-file-name 38 | name: 'ViewerRoot', 39 | render: h => h(ViewerComponent), 40 | }) 41 | -------------------------------------------------------------------------------- /src/mixins/PreviewUrl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { getPreviewIfAny } from '../utils/previewUtils.ts' 6 | import { getDavPath } from '../utils/fileUtils.ts' 7 | 8 | export default { 9 | computed: { 10 | /** 11 | * Link to the preview path if the file have a preview 12 | * 13 | * @return {string} 14 | */ 15 | previewPath() { 16 | return this.getPreviewIfAny({ 17 | fileid: this.fileid, 18 | filename: this.filename, 19 | previewUrl: this.previewUrl, 20 | hasPreview: this.hasPreview, 21 | davPath: this.davPath, 22 | etag: this.$attrs.etag, 23 | }) 24 | }, 25 | 26 | /** 27 | * Absolute dav remote path of the file 28 | * 29 | * @return {string} 30 | */ 31 | davPath() { 32 | return getDavPath({ 33 | filename: this.filename, 34 | basename: this.basename, 35 | }) 36 | }, 37 | }, 38 | methods: { 39 | /** 40 | * Return the preview url if the file have an existing 41 | * preview or the absolute dav remote path if none. 42 | * 43 | * @param {object} data destructuring object 44 | * @param {string} data.fileid the file id 45 | * @param {string} [data.previewUrl] URL of the file preview 46 | * @param {boolean} data.hasPreview have the file an existing preview ? 47 | * @param {string} data.davPath the absolute dav path 48 | * @param {string} data.filename the file name 49 | * @param {string|null} data.etag the etag of the file 50 | * @return {string} the absolute url 51 | */ 52 | getPreviewIfAny(data) { 53 | return getPreviewIfAny(data) 54 | }, 55 | }, 56 | } 57 | -------------------------------------------------------------------------------- /src/models/audios.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import Audios from '../components/Audios.vue' 7 | 8 | export default { 9 | id: 'audios', 10 | group: 'media', 11 | mimes: [ 12 | 'audio/aac', 13 | 'audio/aacp', 14 | 'audio/flac', 15 | 'audio/mp4', 16 | 'audio/mpeg', 17 | 'audio/ogg', 18 | 'audio/vorbis', 19 | 'audio/wav', 20 | 'audio/webm', 21 | ], 22 | component: Audios, 23 | } 24 | -------------------------------------------------------------------------------- /src/models/file.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { getDavPath } from '../utils/fileUtils.ts' 6 | 7 | /** 8 | * @param {object} fileInfo a FileInfo object 9 | * @param {string} mime the file mime type 10 | * @param {object} component the component to render 11 | */ 12 | export default function(fileInfo, mime, component) { 13 | const data = { 14 | mime, 15 | modal: component, 16 | failed: false, 17 | loaded: false, 18 | davPath: getDavPath(fileInfo), 19 | source: fileInfo.source ?? getDavPath(fileInfo), 20 | } 21 | 22 | return Object.assign({}, fileInfo, data) 23 | } 24 | -------------------------------------------------------------------------------- /src/models/images.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import { loadState } from '@nextcloud/initial-state' 7 | import logger from '../services/logger.js' 8 | import Images from '../components/Images.vue' 9 | 10 | const enabledPreviewProviders = loadState(appName, 'enabled_preview_providers', []) 11 | 12 | /** 13 | * Those mimes needs a proper preview to be displayed 14 | * if they are not enabled on the server, let's not activate them. 15 | */ 16 | const previewSupportedMimes = [ 17 | 'image/heic', 18 | 'image/heif', 19 | 'image/tiff', 20 | 'image/x-xbitmap', 21 | 'image/emf', 22 | ] 23 | 24 | /** 25 | * Those mimes are always supported by the browser 26 | * Since we fallback to the source image if there is no 27 | * preview, we can always include them. 28 | */ 29 | const browserSupportedMimes = [ 30 | 'image/apng', 31 | 'image/bmp', 32 | 'image/gif', 33 | 'image/jpeg', 34 | 'image/png', 35 | 'image/svg+xml', 36 | 'image/webp', 37 | 'image/x-icon', 38 | ] 39 | 40 | // Filter out supported mimes that are _not_ 41 | // enabled in the preview API 42 | const filterEnabledMimes = () => { 43 | return previewSupportedMimes.filter(filter => { 44 | return enabledPreviewProviders.findIndex(mimeRegex => { 45 | // Remove leading and trailing slash from string regex 46 | const regex = new RegExp(mimeRegex.replace(/^\/|\/$/g, ''), 'i') 47 | return filter.match(regex) 48 | }) > -1 49 | }) 50 | } 51 | 52 | const enabledMimes = filterEnabledMimes() 53 | const ignoredMimes = previewSupportedMimes.filter(x => !enabledMimes.includes(x)) 54 | if (ignoredMimes.length > 0) { 55 | logger.warn('Some mimes were ignored because they are not enabled in the server previews config', { ignoredMimes }) 56 | } 57 | 58 | export default { 59 | id: 'images', 60 | group: 'media', 61 | mimes: [ 62 | ...browserSupportedMimes, 63 | ...enabledMimes, 64 | ], 65 | component: Images, 66 | } 67 | -------------------------------------------------------------------------------- /src/models/videos.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import Videos from '../components/Videos.vue' 7 | 8 | export default { 9 | id: 'videos', 10 | group: 'media', 11 | mimes: [ 12 | 'video/mpeg', 13 | 'video/ogg', 14 | 'video/webm', 15 | 'video/mp4', 16 | 'video/x-m4v', 17 | 'video/x-flv', 18 | 'video/quicktime', 19 | ], 20 | mimesAliases: { 21 | 'video/x-matroska': 'video/webm', 22 | }, 23 | component: Videos, 24 | } 25 | -------------------------------------------------------------------------------- /src/services/FileInfo.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import type { FileStat, ResponseDataDetailed } from 'webdav' 7 | 8 | import { client } from './WebdavClient' 9 | import { genFileInfo, type FileInfo } from '../utils/fileUtils' 10 | import { davGetClient, getDavNameSpaces, getDavProperties } from '@nextcloud/files' 11 | 12 | const statData = ` 13 | 14 | 15 | 16 | ${getDavProperties()} 17 | 18 | ` 19 | 20 | /** 21 | * Retrieve the files list 22 | * @param path 23 | * @param options 24 | */ 25 | export default async function(path: string, options = {}): Promise { 26 | const response = await client.stat(path, Object.assign({ 27 | data: statData, 28 | details: true, 29 | }, options)) as ResponseDataDetailed 30 | return genFileInfo(response.data) 31 | } 32 | 33 | /** 34 | * Retrieve the files list 35 | * @param origin 36 | * @param path 37 | * @param options 38 | */ 39 | export async function rawStat(origin: string, path: string, options = {}) { 40 | const response = await davGetClient(origin).stat(path, { 41 | ...options, 42 | data: statData, 43 | details: true, 44 | }) as ResponseDataDetailed 45 | 46 | return response.data 47 | } 48 | -------------------------------------------------------------------------------- /src/services/FileList.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import { getDavNameSpaces, getDavProperties } from '@nextcloud/files' 7 | import { client } from './WebdavClient' 8 | import { genFileInfo, type FileInfo } from '../utils/fileUtils' 9 | import type { FileStat, ResponseDataDetailed } from 'webdav' 10 | 11 | /** 12 | * Retrieve the files list 13 | * @param path 14 | * @param options 15 | */ 16 | export default async function(path: string, options = {}): Promise { 17 | const response = await client.getDirectoryContents(path, Object.assign({ 18 | data: ` 19 | 20 | 21 | 22 | ${getDavProperties()} 23 | 24 | `, 25 | details: true, 26 | }, options)) as ResponseDataDetailed 27 | 28 | return response.data.map(genFileInfo) 29 | } 30 | -------------------------------------------------------------------------------- /src/services/FileSortingConfig.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import axios from '@nextcloud/axios' 7 | import { generateUrl } from '@nextcloud/router' 8 | import { isPublicShare } from '@nextcloud/sharing/public' 9 | 10 | /** 11 | * @return {object} 12 | */ 13 | export default async function getSortingConfig() { 14 | const viewConfigs = await getViewConfigs() 15 | 16 | if (!viewConfigs) { 17 | return { key: 'basename', asc: true } 18 | } 19 | 20 | const keyMap = { mtime: 'lastmod' } 21 | const key = keyMap[viewConfigs.sorting_mode] || viewConfigs.sorting_mode || 'basename' 22 | const asc = viewConfigs.sorting_direction === 'asc' || !viewConfigs.sorting_direction 23 | 24 | return { key, asc } 25 | } 26 | 27 | /** 28 | * @return {object} 29 | */ 30 | async function getViewConfigs() { 31 | if (isPublicShare()) { 32 | return null 33 | } 34 | const url = generateUrl('apps/files/api/v1/views') 35 | return await axios.get(url) 36 | .then((response) => { 37 | return response.data.data?.files 38 | }) 39 | .catch(() => { 40 | return null 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /src/services/WebdavClient.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import { davGetClient, davRootPath, davGetRemoteURL } from '@nextcloud/files' 7 | 8 | const davRemote = davGetRemoteURL() 9 | 10 | export const client = davGetClient(`${davRemote}${davRootPath}`) 11 | -------------------------------------------------------------------------------- /src/services/logger.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { getLoggerBuilder } from '@nextcloud/logger' 6 | 7 | // Set up logger 8 | const logger = getLoggerBuilder() 9 | .setApp(appName) 10 | .detectUser() 11 | .build() 12 | 13 | export default logger 14 | -------------------------------------------------------------------------------- /src/services/mediaPreloader.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | /* eslint-disable jsdoc/require-jsdoc */ 7 | 8 | import type { ResponseDataDetailed, WebDAVClient } from 'webdav' 9 | 10 | import { getClient, getRootPath } from '@nextcloud/files/dav' 11 | 12 | // Manually load a WebDAV media from its filename, then expose the received Blob as an object URL. 13 | // This is needed for E2EE files that will error when loading them directly from the HTML element's src attribute. 14 | // Can be removed if we ever move the E2EE proxy to a service worker. 15 | export async function preloadMedia(filename: string): Promise { 16 | const client = getClient() as WebDAVClient 17 | const response = await client.getFileContents(`${getRootPath()}${filename}`, { details: true }) as ResponseDataDetailed 18 | return URL.createObjectURL(new Blob([response.data], { type: response.headers['content-type'] })) 19 | } 20 | -------------------------------------------------------------------------------- /src/shims.d.ts: -------------------------------------------------------------------------------- 1 | /*! 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | declare module '*.svg?raw' { 7 | const content: string 8 | export default content 9 | } 10 | -------------------------------------------------------------------------------- /src/utils/CancelableRequest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | /** 7 | * Creates a cancelable axios 'request object'. 8 | * 9 | * @param {Function} request the axios promise request 10 | * @return {object} 11 | */ 12 | const CancelableRequest = function(request) { 13 | const controller = new AbortController() 14 | 15 | /** 16 | * Execute the request 17 | * 18 | * @param {string} url the url to send the request to 19 | * @param {object} [options] optional config for the request 20 | */ 21 | const fetch = async function(url, options) { 22 | return request( 23 | url, 24 | { ...options, signal: controller.signal }, 25 | ) 26 | } 27 | return { 28 | request: fetch, 29 | cancel: () => controller.abort(), 30 | } 31 | } 32 | 33 | export default CancelableRequest 34 | -------------------------------------------------------------------------------- /src/utils/canDownload.ts: -------------------------------------------------------------------------------- 1 | /*! 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import type { FileInfo } from './fileUtils' 7 | 8 | /** 9 | * Check if download permissions are granted for a file 10 | * @param fileInfo The file info to check 11 | */ 12 | export function canDownload(fileInfo: FileInfo) { 13 | if (fileInfo.hideDownload) { 14 | return false 15 | } 16 | 17 | // TODO: This should probably be part of `@nextcloud/sharing` 18 | // check share attributes 19 | const shareAttributes = typeof fileInfo?.shareAttributes === 'string' ? JSON.parse(fileInfo.shareAttributes || '[]') : fileInfo?.shareAttributes 20 | 21 | if (shareAttributes && shareAttributes.length > 0) { 22 | const downloadAttribute = shareAttributes.find(({ scope, key }) => scope === 'permissions' && key === 'download') 23 | // We only forbid download if the attribute is *explicitly* set to 'false' 24 | return downloadAttribute?.value !== false 25 | } 26 | // otherwise return true (as the file needs read permission otherwise we would not have opened it) 27 | return true 28 | } 29 | -------------------------------------------------------------------------------- /src/utils/livePhotoUtils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import type { BasicFileInfo } from './models' 7 | 8 | const livePictureExt = ['jpg', 'jpeg', 'png'] 9 | const livePictureExtRegex = new RegExp(`\\.(${livePictureExt.join('|')})$`, 'i') 10 | 11 | /** 12 | * Return the peer live photo from a list of files based on its fileId 13 | * @param peerFileId 14 | * @param fileList 15 | */ 16 | export function findLivePhotoPeerFromFileId(peerFileId: number, fileList: BasicFileInfo[]): BasicFileInfo | undefined { 17 | return fileList.find(file => file.fileid === peerFileId) 18 | } 19 | 20 | /** 21 | * Return the peer live photo from a list of files based on the original file name. 22 | * @param referenceFile 23 | * @param fileList 24 | */ 25 | export function findLivePhotoPeerFromName(referenceFile: BasicFileInfo, fileList: BasicFileInfo[]): BasicFileInfo | undefined { 26 | return fileList.find(comparedFile => { 27 | // if same filename and extension is allowed 28 | return comparedFile.filename !== referenceFile.filename 29 | && (comparedFile.basename.startsWith(referenceFile.name) && livePictureExtRegex.test(comparedFile.basename)) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /src/utils/models.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | export interface BasicFileInfo { 7 | fileid: number // The file id 8 | filename: string // The file name, ex: /a/b/c/file.txt 9 | basename: string // The base name, ex: file.txt 10 | name: string // The name, ex: file 11 | source?: string // The source of the file, ex: https://example.org/remote.php/dav/files/userId/fileName.jpg 12 | previewUrl?: string // Optional URL of the file preview 13 | hasPreview: boolean // Does the file has an existing preview ? 14 | davPath: string // The absolute dav path 15 | etag: string|null // The etag of the file 16 | metadataFilesLivePhoto?: number // The id of the peer live photo 17 | } 18 | -------------------------------------------------------------------------------- /src/utils/numberUtil.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | const isNumber = function(num): boolean { 7 | if (!num) { 8 | return false 9 | } 10 | return Number(num).toString() === num.toString() 11 | } 12 | 13 | export { isNumber } 14 | -------------------------------------------------------------------------------- /src/utils/previewUtils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import type { BasicFileInfo } from './models' 7 | import { encodePath } from '@nextcloud/paths' 8 | import { generateUrl } from '@nextcloud/router' 9 | import { getSharingToken, isPublicShare } from '@nextcloud/sharing/public' 10 | 11 | /** 12 | * @param root0 13 | * @param root0.fileid 14 | * @param root0.filename 15 | * @param root0.previewUrl 16 | * @param root0.hasPreview 17 | * @param root0.davPath 18 | * @param root0.etag 19 | * @return the preview url if the file have an existing preview or the absolute dav remote path if none. 20 | */ 21 | export function getPreviewIfAny({ fileid, filename, previewUrl, hasPreview, davPath, etag }: BasicFileInfo): string { 22 | if (previewUrl) { 23 | return previewUrl 24 | } 25 | 26 | const searchParams = `fileId=${fileid}` 27 | + `&x=${Math.floor(screen.width * devicePixelRatio)}` 28 | + `&y=${Math.floor(screen.height * devicePixelRatio)}` 29 | + '&a=true' 30 | + (etag !== null ? `&etag=${etag.replace(/"/g, '')}` : '') 31 | 32 | if (hasPreview) { 33 | // TODO: find a nicer standard way of doing this? 34 | if (isPublicShare()) { 35 | return generateUrl(`/apps/files_sharing/publicpreview/${getSharingToken()}?file=${encodePath(filename)}&${searchParams}`) 36 | } 37 | return generateUrl(`/core/preview?${searchParams}`) 38 | } 39 | return davPath 40 | } 41 | -------------------------------------------------------------------------------- /stylelint.config.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | const stylelintConfig = require('@nextcloud/stylelint-config') 6 | 7 | // Disable nested scss import 8 | stylelintConfig.rules['no-invalid-position-at-import-rule'] = null 9 | 10 | module.exports = stylelintConfig 11 | -------------------------------------------------------------------------------- /tests/psalm-baseline.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "lib": [ 6 | "DOM", 7 | "ES2015" 8 | ], 9 | "rootDir": "src", 10 | "noImplicitAny": false, 11 | }, 12 | "vueCompilerOptions": { 13 | "target": 2.7 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { createAppConfig } from '@nextcloud/vite-config' 6 | import { readFileSync } from 'node:fs' 7 | import { join } from 'node:path' 8 | 9 | const isProduction = process.env.NODE_ENV === 'production' 10 | const plyrIcons = readFileSync( 11 | join(__dirname, 'node_modules', 'plyr', 'dist', 'plyr.svg'), 12 | { encoding: 'utf8' }, 13 | ) 14 | 15 | export default createAppConfig({ 16 | main: 'src/main.js', 17 | init: 'src/init.ts', 18 | }, { 19 | replace: { 20 | PLYR_ICONS: JSON.stringify(plyrIcons), 21 | }, 22 | minify: isProduction, 23 | // create REUSE compliant license information for compiled assets 24 | extractLicenseInformation: { 25 | includeSourceMaps: true, 26 | }, 27 | // disable BOM because we already have the `.license` files 28 | thirdPartyLicense: false, 29 | // ensure that every JS entry point has a matching CSS file 30 | createEmptyCSSEntryPoints: true, 31 | // Make sure we also clear the CSS directory 32 | emptyOutputDirectory: { 33 | additionalDirectories: ['css'], 34 | }, 35 | }) 36 | --------------------------------------------------------------------------------