├── .gitignore
├── LICENSE.txt
├── README.md
├── build
├── apple-touch-icon-120x120.png
├── apple-touch-icon.png
├── assets
│ ├── fonts
│ │ ├── Exo-VariableFont_wght.ttf
│ │ └── dos-vga-9x16.ttf
│ ├── icons
│ │ ├── icon-192x192-mono.png
│ │ ├── icon-192x192.png
│ │ ├── icon-512x512-mono.png
│ │ └── icon-512x512.png
│ ├── index-CT-f2sUk.css
│ ├── index-voi2eI38.js
│ ├── lib
│ │ ├── libxm.wasm
│ │ └── zip-no-worker-inflate.min.js
│ └── music
│ │ └── tracks.zip
├── favicon.ico
├── index.html
├── manifest.webmanifest
├── registerSW.js
├── screenshots
│ ├── screenshot-395x640.png
│ ├── screenshot-535x760.png
│ ├── screenshot-app-1135x809.png
│ ├── screenshot-custom-395x640.png
│ └── screenshot-options-700x800.png
└── sw.js
├── eslint.config.mjs
├── index.html
├── package-lock.json
├── package.json
├── public
├── apple-touch-icon-120x120.png
├── apple-touch-icon.png
├── assets
│ ├── fonts
│ │ ├── Exo-VariableFont_wght.ttf
│ │ └── dos-vga-9x16.ttf
│ ├── icons
│ │ ├── icon-192x192-mono.png
│ │ ├── icon-192x192.png
│ │ ├── icon-512x512-mono.png
│ │ └── icon-512x512.png
│ ├── lib
│ │ ├── libxm.wasm
│ │ └── zip-no-worker-inflate.min.js
│ └── music
│ │ └── tracks.zip
├── favicon.ico
└── screenshots
│ ├── screenshot-395x640.png
│ ├── screenshot-535x760.png
│ ├── screenshot-app-1135x809.png
│ ├── screenshot-custom-395x640.png
│ └── screenshot-options-700x800.png
├── src
├── index.css
├── index.jsx
├── sw.js
└── zip-manager
│ ├── ZipManager.jsx
│ ├── business
│ ├── constants.js
│ ├── events.js
│ ├── features
│ │ ├── app.js
│ │ ├── clipboard.js
│ │ ├── common.js
│ │ ├── downloads.js
│ │ ├── entries.js
│ │ ├── filesystem.js
│ │ ├── folders.js
│ │ ├── highlighted-entries.js
│ │ ├── index.js
│ │ ├── misc.js
│ │ ├── options.js
│ │ └── selected-folder.js
│ ├── index.js
│ └── ui-state.js
│ ├── components
│ ├── BottomButtonBar.jsx
│ ├── Breadcrumb.jsx
│ ├── Buttons.jsx
│ ├── Downloads.jsx
│ ├── Entries.jsx
│ ├── History.jsx
│ ├── InfoBar.jsx
│ ├── NavigationBar.jsx
│ ├── TopButtonBar.jsx
│ ├── dialogs
│ │ ├── ChooseActionDialog.jsx
│ │ ├── CreateFolderDialog.jsx
│ │ ├── DeleteEntriesDialog.jsx
│ │ ├── Dialog.jsx
│ │ ├── ErrorMessageDialog.jsx
│ │ ├── ExportZipDialog.jsx
│ │ ├── ExtractDialog.jsx
│ │ ├── ImportPasswordDialog.jsx
│ │ ├── OptionsDialog.jsx
│ │ ├── RenameDialog.jsx
│ │ ├── ResetDialog.jsx
│ │ └── styles
│ │ │ └── OptionsDialog.css
│ ├── index.jsx
│ └── styles
│ │ ├── BottomButtonBar.css
│ │ ├── Downloads.css
│ │ ├── Entries.css
│ │ ├── InfoBar.css
│ │ ├── NavigationBar.css
│ │ └── TopButtonBar.css
│ ├── hooks
│ └── hooks.js
│ ├── messages
│ ├── de-DE.js
│ ├── en-US.js
│ ├── es-ES.js
│ ├── fr-FR.js
│ ├── index.js
│ ├── it-IT.js
│ └── pt-PT.js
│ ├── services
│ ├── document-service.js
│ ├── download-service.js
│ ├── environment-service.js
│ ├── file-handlers-service.js
│ ├── filesystem-service.js
│ ├── i18n-service.js
│ ├── index.js
│ ├── keyboard-service.js
│ ├── lib
│ │ ├── jsSID
│ │ │ └── jsSID.js
│ │ ├── libxm
│ │ │ └── libxm-es6.js
│ │ └── webaudio-tinysynth
│ │ │ ├── LICENSE
│ │ │ └── webaudio-tinysynth-core-es6.js
│ ├── music-service-constants.js
│ ├── music-service.js
│ ├── share-target-service-constants.js
│ ├── share-target-service.js
│ ├── storage-service.js
│ ├── stylesheet-service.js
│ ├── theme-service.js
│ ├── window-service.js
│ └── zip-service.js
│ └── styles
│ ├── Base.css
│ ├── ButtonBar.css
│ ├── Dialog.css
│ ├── ListItem.css
│ ├── Skins.css
│ ├── ZipManager.css
│ └── index.css
└── vite.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # misc
7 | .DS_Store
8 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Gildas Lormeau
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This is a PWA using the filesystem API in [zip.js](https://github.com/gildas-lormeau/zip.js).
2 |
3 | It is based on React and built with Vite.
4 |
5 | See https://gildas-lormeau.github.io/zip-manager/
6 |
7 | ## Features
8 |
9 | - installable for offline use
10 | - keyboard navigation
11 | - multi-core compression/decompression of zip entries
12 | - encrypted zip files
13 | - 4GB+ zip files (i.e. Zip64)
14 | - drag and drop files/directories from filesystem on desktop
15 | - integration in the "Open with..." menu on desktop (see https://developer.mozilla.org/en-US/docs/Web/Manifest/file_handlers)
16 | - integration with the "Share" feature on mobile (see https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target)
17 | - customizable accent color
18 | - DOS theme
19 | - integrated MIDI/XM/SID music player and visualizer
20 |
21 | ## Screenshots
22 |
23 | - Desktop
24 |
25 | 
26 |
27 | - Mobile
28 |
29 | 
30 |
--------------------------------------------------------------------------------
/build/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/build/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/apple-touch-icon.png
--------------------------------------------------------------------------------
/build/assets/fonts/Exo-VariableFont_wght.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/assets/fonts/Exo-VariableFont_wght.ttf
--------------------------------------------------------------------------------
/build/assets/fonts/dos-vga-9x16.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/assets/fonts/dos-vga-9x16.ttf
--------------------------------------------------------------------------------
/build/assets/icons/icon-192x192-mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/assets/icons/icon-192x192-mono.png
--------------------------------------------------------------------------------
/build/assets/icons/icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/assets/icons/icon-192x192.png
--------------------------------------------------------------------------------
/build/assets/icons/icon-512x512-mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/assets/icons/icon-512x512-mono.png
--------------------------------------------------------------------------------
/build/assets/icons/icon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/assets/icons/icon-512x512.png
--------------------------------------------------------------------------------
/build/assets/lib/libxm.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/assets/lib/libxm.wasm
--------------------------------------------------------------------------------
/build/assets/music/tracks.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/assets/music/tracks.zip
--------------------------------------------------------------------------------
/build/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/favicon.ico
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Zip Manager
16 |
33 |
34 |
35 |
36 |
37 |
38 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/build/manifest.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"Zip Manager","short_name":"Zip Manager","description":"Read, edit and write zip files.","start_url":"./index.html","display":"fullscreen","background_color":"#ffffff","theme_color":"#000000","lang":"en","scope":"./","orientation":"any","categories":["utilities"],"icons":[{"src":"assets/icons/icon-512x512.png","sizes":"512x512","type":"image/png","purpose":"any"},{"src":"assets/icons/icon-192x192.png","sizes":"192x192","type":"image/png","purpose":"any"},{"src":"assets/icons/icon-512x512.png","sizes":"512x512","type":"image/png","purpose":"maskable"},{"src":"assets/icons/icon-192x192.png","sizes":"192x192","type":"image/png","purpose":"maskable"},{"src":"assets/icons/icon-512x512-mono.png","sizes":"512x512","type":"image/png","purpose":"monochrome"},{"src":"./assets/icons/icon-192x192-mono.png","sizes":"192x192","type":"image/png","purpose":"monochrome"}],"file_handlers":[{"action":"./index.html","accept":{"application/zip":[".zip"],"application/vnd.openxmlformats-officedocument.wordprocessingml.document":[".docx"],"application/epub+zip":[".epub"],"application/java-archive":[".jar"],"application/vnd.oasis.opendocument.presentation":[".odp"],"application/vnd.oasis.opendocument.spreadsheet":[".ods"],"application/vnd.oasis.opendocument.text":[".odt"],"application/vnd.openxmlformats-officedocument.presentationml.presentation":[".pptx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":[".xlsx"],"application/vnd.apple.keynote":[".key"],"application/vnd.apple.pages":[".pages"],"application/vnd.apple.numbers":[".numbers"],"application/vnd.android.package-archive":[".apk"],"application/x-ios-app":[".ipa"]},"launch_type":"single-client"}],"share_target":{"action":"./shared-files","enctype":"multipart/form-data","method":"POST","params":{"files":[{"name":"shared-files","accept":["*/*"]}]}},"screenshots":[{"src":"./screenshots/screenshot-395x640.png","sizes":"395x640","type":"image/png","form_factor":"narrow","label":"Main screen on mobile"},{"src":"./screenshots/screenshot-app-1135x809.png","sizes":"1135x809","type":"image/png","form_factor":"wide","label":"Main screen on desktop"},{"src":"./screenshots/screenshot-custom-395x640.png","sizes":"395x640","type":"image/png","form_factor":"narrow","label":"Custom user interface on mobile"}]}
2 |
--------------------------------------------------------------------------------
/build/registerSW.js:
--------------------------------------------------------------------------------
1 | if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('./sw.js', { scope: './' })})}
--------------------------------------------------------------------------------
/build/screenshots/screenshot-395x640.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/screenshots/screenshot-395x640.png
--------------------------------------------------------------------------------
/build/screenshots/screenshot-535x760.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/screenshots/screenshot-535x760.png
--------------------------------------------------------------------------------
/build/screenshots/screenshot-app-1135x809.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/screenshots/screenshot-app-1135x809.png
--------------------------------------------------------------------------------
/build/screenshots/screenshot-custom-395x640.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/screenshots/screenshot-custom-395x640.png
--------------------------------------------------------------------------------
/build/screenshots/screenshot-options-700x800.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/build/screenshots/screenshot-options-700x800.png
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import js from "@eslint/js";
2 | import react from "eslint-plugin-react";
3 | import reactCompiler from "eslint-plugin-react-compiler";
4 | import reactRefresh from "eslint-plugin-react-refresh";
5 |
6 | export default [
7 | js.configs.recommended,
8 | {
9 | files: ["**/*.{js,jsx}"],
10 | plugins: {
11 | react,
12 | "react-compiler": reactCompiler,
13 | "react-refresh": reactRefresh
14 | },
15 | languageOptions: {
16 | ecmaVersion: 2020,
17 | sourceType: "module",
18 | globals: {
19 | console: "readonly"
20 | },
21 | parserOptions: {
22 | ecmaFeatures: {
23 | jsx: true
24 | }
25 | }
26 | },
27 | rules: {
28 | "react/jsx-uses-vars": "error",
29 | "react/jsx-uses-react": "error",
30 | "react-refresh/only-export-components": ["warn"],
31 | "indent": ["error", 2],
32 | "linebreak-style": ["error", "unix"],
33 | "quotes": ["error", "double"],
34 | "semi": ["warn", "always"],
35 | "no-console": "warn",
36 | "no-debugger": "warn",
37 | "no-unused-vars": "warn",
38 | "react-compiler/react-compiler": "error"
39 | },
40 | ignores: [
41 | "**/node_modules/",
42 | ".git/"
43 | ]
44 | }
45 | ];
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Zip Manager
16 |
33 |
34 |
35 |
36 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zip-manager",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "dependencies": {
6 | "@zip.js/zip.js": "^2.7.59",
7 | "react": "^19.1.0",
8 | "react-dom": "^19.1.0",
9 | "workbox-core": "^7.3.0",
10 | "workbox-precaching": "^7.3.0",
11 | "workbox-routing": "^7.3.0"
12 | },
13 | "scripts": {
14 | "start": "vite",
15 | "build": "vite build",
16 | "serve": "vite preview"
17 | },
18 | "browserslist": {
19 | "production": [
20 | ">0.2%",
21 | "not dead",
22 | "not op_mini all"
23 | ],
24 | "development": [
25 | "last 1 chrome version",
26 | "last 1 firefox version",
27 | "last 1 safari version"
28 | ]
29 | },
30 | "devDependencies": {
31 | "@vitejs/plugin-react": "^4.3.4",
32 | "babel-plugin-react-compiler": "^19.0.0-beta-aeaed83-20250323",
33 | "eslint": "^9.23.0",
34 | "eslint-plugin-react": "^7.37.4",
35 | "eslint-plugin-react-compiler": "^19.0.0-beta-aeaed83-20250323",
36 | "eslint-plugin-react-refresh": "^0.4.19",
37 | "vite": "^6.2.3",
38 | "vite-plugin-pwa": "^1.0.0"
39 | }
40 | }
--------------------------------------------------------------------------------
/public/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/assets/fonts/Exo-VariableFont_wght.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/assets/fonts/Exo-VariableFont_wght.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/dos-vga-9x16.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/assets/fonts/dos-vga-9x16.ttf
--------------------------------------------------------------------------------
/public/assets/icons/icon-192x192-mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/assets/icons/icon-192x192-mono.png
--------------------------------------------------------------------------------
/public/assets/icons/icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/assets/icons/icon-192x192.png
--------------------------------------------------------------------------------
/public/assets/icons/icon-512x512-mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/assets/icons/icon-512x512-mono.png
--------------------------------------------------------------------------------
/public/assets/icons/icon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/assets/icons/icon-512x512.png
--------------------------------------------------------------------------------
/public/assets/lib/libxm.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/assets/lib/libxm.wasm
--------------------------------------------------------------------------------
/public/assets/music/tracks.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/assets/music/tracks.zip
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/favicon.ico
--------------------------------------------------------------------------------
/public/screenshots/screenshot-395x640.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/screenshots/screenshot-395x640.png
--------------------------------------------------------------------------------
/public/screenshots/screenshot-535x760.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/screenshots/screenshot-535x760.png
--------------------------------------------------------------------------------
/public/screenshots/screenshot-app-1135x809.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/screenshots/screenshot-app-1135x809.png
--------------------------------------------------------------------------------
/public/screenshots/screenshot-custom-395x640.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/screenshots/screenshot-custom-395x640.png
--------------------------------------------------------------------------------
/public/screenshots/screenshot-options-700x800.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gildas-lormeau/zip-manager/8918543161e74e37fa92f799f8803caf0f7724f6/public/screenshots/screenshot-options-700x800.png
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: "Exo", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
4 | "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | @font-face {
11 | font-family: "Exo";
12 | src: url("/assets/fonts/Exo-VariableFont_wght.ttf");
13 | font-display: swap;
14 | }
--------------------------------------------------------------------------------
/src/index.jsx:
--------------------------------------------------------------------------------
1 | /* global document */
2 |
3 | import React from "react";
4 | import ReactDOM from "react-dom/client";
5 | import "./index.css";
6 | import App from "./zip-manager/ZipManager.jsx";
7 |
8 | const root = ReactDOM.createRoot(document.body);
9 | root.render(
10 |
11 |
12 |
13 | );
--------------------------------------------------------------------------------
/src/sw.js:
--------------------------------------------------------------------------------
1 | /* global self, URL, Response, caches, importScripts, zip */
2 | /* eslint-disable no-restricted-globals */
3 |
4 | import { cacheNames, clientsClaim } from "workbox-core";
5 | import {
6 | cleanupOutdatedCaches,
7 | precacheAndRoute,
8 | getCacheKeyForURL
9 | } from "workbox-precaching";
10 | import { registerRoute } from "workbox-routing";
11 |
12 | import {
13 | MAINPAGE_REDIRECT_PATH,
14 | SHARED_FILES_RELATIVE_PATH,
15 | SHARED_FILES_CACHE_ID,
16 | SHARED_FILES_FORM_PATH
17 | } from "./zip-manager/services/share-target-service-constants.js";
18 | import {
19 | MUSIC_TRACKS_PATH,
20 | MUSIC_TRACK_PATH_REGEXP,
21 | MUSIC_TRACK_INDEX_REGEXP,
22 | MUSIC_FILE_CONTENT_TYPES
23 | } from "./zip-manager/services/music-service-constants.js";
24 |
25 | const GET_REQUEST = "GET";
26 | const POST_REQUEST = "POST";
27 |
28 | importScripts("./assets/lib/zip-no-worker-inflate.min.js");
29 | cleanupOutdatedCaches();
30 | precacheAndRoute(self.__WB_MANIFEST);
31 | self.skipWaiting();
32 | registerRoute(SHARED_FILES_RELATIVE_PATH, getSharedFiles, GET_REQUEST);
33 | registerRoute(SHARED_FILES_RELATIVE_PATH, setSharedFiles, POST_REQUEST);
34 | registerRoute(MUSIC_TRACK_PATH_REGEXP, getMusicTrack, GET_REQUEST);
35 | clientsClaim();
36 |
37 | async function setSharedFiles({ event }) {
38 | const formData = await event.request.formData();
39 | const cache = await caches.open(SHARED_FILES_CACHE_ID);
40 | await cache.put(
41 | new URL(SHARED_FILES_FORM_PATH, self.location).href,
42 | new Response(formData)
43 | );
44 | return Response.redirect(MAINPAGE_REDIRECT_PATH, 303);
45 | }
46 |
47 | function getSharedFiles({ event }) {
48 | event.respondWith(getSharedFilesResponse());
49 | }
50 |
51 | async function getSharedFilesResponse() {
52 | const cache = await caches.open(SHARED_FILES_CACHE_ID);
53 | const response = await cache.match(SHARED_FILES_FORM_PATH);
54 | if (response) {
55 | await cache.delete(SHARED_FILES_FORM_PATH);
56 | return response;
57 | }
58 | }
59 |
60 | async function getMusicTrack({ event }) {
61 | const cache = await caches.open(cacheNames.precache);
62 | const response = await cache.match(getCacheKeyForURL(MUSIC_TRACKS_PATH));
63 | const zipReader = new zip.ZipReader(response.body);
64 | const entries = await zipReader.getEntries();
65 | const fileEntryIndex = Number(
66 | event.request.url.match(MUSIC_TRACK_INDEX_REGEXP)[0]
67 | );
68 | const fileEntry = entries[fileEntryIndex];
69 | const contentType = MUSIC_FILE_CONTENT_TYPES.find((info) =>
70 | fileEntry.filename.endsWith(info.extension)
71 | ).type;
72 | const data = await fileEntry.getData(new zip.BlobWriter(contentType));
73 | await zipReader.close();
74 | return new Response(data);
75 | }
76 |
--------------------------------------------------------------------------------
/src/zip-manager/business/constants.js:
--------------------------------------------------------------------------------
1 | const ACTION_KEY = " ";
2 | const ENTER_KEY = "Enter";
3 | const TAB_KEY = "Tab";
4 | const CUT_KEY = "x";
5 | const COPY_KEY = "c";
6 | const EXTRACT_KEY = "Enter";
7 | const RENAME_KEY = "r";
8 | const PASTE_KEY = "v";
9 | const CREATE_FOLDER_KEY = "d";
10 | const ADD_FILES_KEY = "f";
11 | const IMPORT_ZIP_KEY = "i";
12 | const EXPORT_ZIP_KEY = "e";
13 | const HIGHLIGHT_ALL_KEY = "a";
14 | const DELETE_KEYS = ["Backspace", "Delete"];
15 | const DOWN_KEY = "ArrowDown";
16 | const UP_KEY = "ArrowUp";
17 | const LEFT_KEY = "ArrowLeft";
18 | const RIGHT_KEY = "ArrowRight";
19 | const PAGE_UP_KEY = "PageUp";
20 | const PAGE_DOWN_KEY = "PageDown";
21 | const HOME_KEY = "Home";
22 | const END_KEY = "End";
23 | const BACK_KEY = "ArrowLeft";
24 | const FORWARD_KEY = "ArrowRight";
25 | const DEFAULT_MIME_TYPE = "application/octet-stream";
26 | const OPTIONS_DEFAULT_SKIN = "skin-default";
27 | const OPTIONS_DOS_SKIN = "skin-dos";
28 | const DEFAULT_OPTIONS = {
29 | accentColor: "#FF672E",
30 | skin: OPTIONS_DEFAULT_SKIN,
31 | hideNavigationBar: false,
32 | hideDownloadManager: false,
33 | hideInfobar: false,
34 | bufferedWrite: true,
35 | checkSignature: false,
36 | keepOrder: true,
37 | maxWorkers: 2,
38 | chunkSize: 512 * 1024,
39 | promptForExportPassword: true,
40 | defaultExportPassword: "",
41 | zoomFactor: 100
42 | };
43 | const ZIP_EXTENSION = ".zip";
44 | const ZIP_EXTENSIONS = [
45 | ZIP_EXTENSION,
46 | ".docx",
47 | ".epub",
48 | ".jar",
49 | ".odp",
50 | ".ods",
51 | ".odt",
52 | ".pptx",
53 | ".xlsx",
54 | ".key",
55 | ".pages",
56 | ".numbers",
57 | ".apk",
58 | ".ipa"
59 | ];
60 | const ZIP_EXTENSIONS_ACCEPT = {
61 | "application/zip": [ZIP_EXTENSION],
62 | "application/vnd.openxmlformats-officedocument.wordprocessingml.document": [
63 | ".docx"
64 | ],
65 | "application/epub+zip": [".epub"],
66 | "application/java-archive": [".jar"],
67 | "application/vnd.oasis.opendocument.presentation": [".odp"],
68 | "application/vnd.oasis.opendocument.spreadsheet": [".ods"],
69 | "application/vnd.oasis.opendocument.text": [".odt"],
70 | "application/vnd.openxmlformats-officedocument.presentationml.presentation": [
71 | ".pptx"
72 | ],
73 | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [
74 | ".xlsx"
75 | ],
76 | "application/vnd.apple.keynote": [".key"],
77 | "application/vnd.apple.pages": [".pages"],
78 | "application/vnd.apple.numbers": [".numbers"],
79 | "application/vnd.android.package-archive": [".apk"],
80 | "application/x-ios-app": [".ipa"]
81 | };
82 | const ZIP_EXTENSIONS_ACCEPT_STRING = ZIP_EXTENSIONS.join(",");
83 | const LONG_TOUCH_DELAY = 750;
84 | const CREATE_FOLDER_BUTTON_NAME = "create-folder-button";
85 | const ADD_FILES_BUTTON_NAME = "add-files-button";
86 | const IMPORT_ZIP_BUTTON_NAME = "import-zip-button";
87 | const EXPORT_ZIP_BUTTON_NAME = "export-zip-button";
88 | const COPY_BUTTON_NAME = "copy-button";
89 | const CUT_BUTTON_NAME = "cut-button";
90 | const PASTE_BUTTON_NAME = "paste-button";
91 | const EXTRACT_BUTTON_NAME = "extract-button";
92 | const HIGHLIGHT_ALL_BUTTON_NAME = "select-all";
93 | const RENAME_BUTTON_NAME = "rename-button";
94 | const DELETE_BUTTON_NAME = "delete-entry-button";
95 | const BACK_BUTTON_NAME = "back-button";
96 | const FORWARD_BUTTON_NAME = "forward-button";
97 | const OPTIONS_KEY_NAME = "options";
98 | const FONT_SIZE_PROPERTY_NAME = "font-size";
99 | const NO_ENTRIES_CUSTOM_PROPERTY_NAME = "--message-drag-and-drop-entries";
100 | const FOLDER_SEPARATOR_CUSTOM_PROPERTY_NAME = "--folder-separator";
101 | const FOLDER_SEPARATOR = "/";
102 | const APP_CLASSNAME = "main-container";
103 | const INFOBAR_HIDDEN_CLASSNAME = "hidden-footer";
104 | const DOWNLOAD_MANAGER_HIDDEN_CLASSNAME = "hidden-downloads";
105 | const APP_LOADING_ATTRIBUTE_NAME = "app-loading";
106 | const LOW_RES_FFT = 32;
107 | const HIGH_RES_FFT = 128;
108 | const FFT_RESOLUTIONS = {
109 | [OPTIONS_DEFAULT_SKIN]: HIGH_RES_FFT,
110 | [OPTIONS_DOS_SKIN]: LOW_RES_FFT
111 | };
112 |
113 | export {
114 | ACTION_KEY,
115 | ENTER_KEY,
116 | TAB_KEY,
117 | CUT_KEY,
118 | COPY_KEY,
119 | EXTRACT_KEY,
120 | RENAME_KEY,
121 | PASTE_KEY,
122 | CREATE_FOLDER_KEY,
123 | ADD_FILES_KEY,
124 | IMPORT_ZIP_KEY,
125 | EXPORT_ZIP_KEY,
126 | HIGHLIGHT_ALL_KEY,
127 | DELETE_KEYS,
128 | DOWN_KEY,
129 | UP_KEY,
130 | LEFT_KEY,
131 | RIGHT_KEY,
132 | PAGE_UP_KEY,
133 | PAGE_DOWN_KEY,
134 | HOME_KEY,
135 | END_KEY,
136 | BACK_KEY,
137 | FORWARD_KEY,
138 | DEFAULT_MIME_TYPE,
139 | DEFAULT_OPTIONS,
140 | ZIP_EXTENSION,
141 | ZIP_EXTENSIONS,
142 | ZIP_EXTENSIONS_ACCEPT,
143 | ZIP_EXTENSIONS_ACCEPT_STRING,
144 | LONG_TOUCH_DELAY,
145 | CREATE_FOLDER_BUTTON_NAME,
146 | ADD_FILES_BUTTON_NAME,
147 | IMPORT_ZIP_BUTTON_NAME,
148 | EXPORT_ZIP_BUTTON_NAME,
149 | COPY_BUTTON_NAME,
150 | CUT_BUTTON_NAME,
151 | PASTE_BUTTON_NAME,
152 | EXTRACT_BUTTON_NAME,
153 | HIGHLIGHT_ALL_BUTTON_NAME,
154 | RENAME_BUTTON_NAME,
155 | DELETE_BUTTON_NAME,
156 | BACK_BUTTON_NAME,
157 | FORWARD_BUTTON_NAME,
158 | OPTIONS_KEY_NAME,
159 | FONT_SIZE_PROPERTY_NAME,
160 | NO_ENTRIES_CUSTOM_PROPERTY_NAME,
161 | FOLDER_SEPARATOR_CUSTOM_PROPERTY_NAME,
162 | FOLDER_SEPARATOR,
163 | APP_CLASSNAME,
164 | INFOBAR_HIDDEN_CLASSNAME,
165 | DOWNLOAD_MANAGER_HIDDEN_CLASSNAME,
166 | APP_LOADING_ATTRIBUTE_NAME,
167 | OPTIONS_DEFAULT_SKIN,
168 | OPTIONS_DOS_SKIN,
169 | FFT_RESOLUTIONS
170 | };
171 |
--------------------------------------------------------------------------------
/src/zip-manager/business/events.js:
--------------------------------------------------------------------------------
1 | function getEventHandlers({
2 | entries,
3 | downloads,
4 | dialogDisplayed,
5 | onEntriesKeyUp,
6 | onFoldersKeyUp,
7 | onHighlightedEntriesKeyUp,
8 | onAppKeyUp,
9 | onEntriesKeyDown,
10 | onHighlightedEntriesKeyDown,
11 | onSelectedFolderKeyDown
12 | }) {
13 | function handleKeyUp(event) {
14 | if (!dialogDisplayed) {
15 | onEntriesKeyUp(event);
16 | onFoldersKeyUp(event);
17 | onHighlightedEntriesKeyUp(event);
18 | onAppKeyUp(event);
19 | }
20 | }
21 |
22 | function handleKeyDown(event, resetHighlightedEntryElement) {
23 | if (!dialogDisplayed) {
24 | onEntriesKeyDown(event, resetHighlightedEntryElement);
25 | onHighlightedEntriesKeyDown(event);
26 | onSelectedFolderKeyDown(event);
27 | }
28 | }
29 |
30 | function handlePageUnload(event) {
31 | if (entries.length || downloads.length) {
32 | event.preventDefault();
33 | event.returnValue = "";
34 | }
35 | }
36 |
37 | return {
38 | handlePageUnload,
39 | handleKeyUp,
40 | handleKeyDown
41 | };
42 | }
43 |
44 | export default getEventHandlers;
45 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/app.js:
--------------------------------------------------------------------------------
1 | function getAppFeatures({
2 | disabledEnterEntry,
3 | zipFilesystem,
4 | highlightedEntry,
5 | selectedFolder,
6 | hiddenInfobar,
7 | hiddenDownloadManager,
8 | modifierKeyPressed,
9 | setNavigation,
10 | setSelectedFolder,
11 | setHighlightedIds,
12 | setHistory,
13 | setClickedButtonName,
14 | goIntoFolder,
15 | openPromptExtract,
16 | refreshSelectedFolder,
17 | stylesheetService,
18 | documentService,
19 | i18nService,
20 | constants,
21 | messages
22 | }) {
23 | const {
24 | NO_ENTRIES_CUSTOM_PROPERTY_NAME,
25 | FOLDER_SEPARATOR_CUSTOM_PROPERTY_NAME,
26 | FOLDER_SEPARATOR,
27 | APP_LOADING_ATTRIBUTE_NAME,
28 | APP_CLASSNAME,
29 | INFOBAR_HIDDEN_CLASSNAME,
30 | DOWNLOAD_MANAGER_HIDDEN_CLASSNAME,
31 | ACTION_KEY
32 | } = constants;
33 |
34 | function initAppFeatures() {
35 | stylesheetService.setStyle(
36 | NO_ENTRIES_CUSTOM_PROPERTY_NAME,
37 | JSON.stringify(messages.NO_ENTRIES_LABEL)
38 | );
39 | stylesheetService.setStyle(
40 | FOLDER_SEPARATOR_CUSTOM_PROPERTY_NAME,
41 | JSON.stringify(FOLDER_SEPARATOR)
42 | );
43 | documentService.setDocumentLanguage(i18nService.getLanguageId());
44 | documentService.removeDocumentAttribute(APP_LOADING_ATTRIBUTE_NAME);
45 | }
46 |
47 | function updateZipFilesystem() {
48 | const { root } = zipFilesystem;
49 | setSelectedFolder(root);
50 | setHighlightedIds([]);
51 | setNavigation({
52 | previousHighlight: null,
53 | direction: 0
54 | });
55 | setHistory({ path: [root], index: 0 });
56 | refreshSelectedFolder(root);
57 | }
58 |
59 | function enterEntry(entry) {
60 | if (entry.directory) {
61 | goIntoFolder(entry);
62 | } else {
63 | openPromptExtract(entry);
64 | }
65 | }
66 |
67 | function resetClickedButtonName() {
68 | setClickedButtonName(null);
69 | }
70 |
71 | function getAppClassName() {
72 | const classes = [APP_CLASSNAME];
73 | if (hiddenInfobar) {
74 | classes.push(INFOBAR_HIDDEN_CLASSNAME);
75 | }
76 | if (hiddenDownloadManager) {
77 | classes.push(DOWNLOAD_MANAGER_HIDDEN_CLASSNAME);
78 | }
79 | return classes.join(" ");
80 | }
81 |
82 | function onAppKeyUp(event) {
83 | if (!event.altKey && !modifierKeyPressed(event) && !event.shiftKey) {
84 | if (event.key === ACTION_KEY && !disabledEnterEntry) {
85 | enterEntry(highlightedEntry || selectedFolder.parent);
86 | event.preventDefault();
87 | }
88 | }
89 | }
90 |
91 | return {
92 | initAppFeatures,
93 | enterEntry,
94 | updateZipFilesystem,
95 | resetClickedButtonName,
96 | getAppClassName,
97 | onAppKeyUp
98 | };
99 | }
100 |
101 | export default getAppFeatures;
102 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/clipboard.js:
--------------------------------------------------------------------------------
1 | function getClipboardFeatures({ setClipboardData }) {
2 | function resetClipboardData() {
3 | setClipboardData(null);
4 | }
5 |
6 | return {
7 | resetClipboardData
8 | };
9 | }
10 |
11 | export default getClipboardFeatures;
12 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/common.js:
--------------------------------------------------------------------------------
1 | function getCommonFeatures({
2 | dialogs,
3 | setDownloads,
4 | setDialogs,
5 | removeDownload,
6 | downloadService,
7 | filesystemService,
8 | environmentService
9 | }) {
10 | const isMacOSPlatform = environmentService.isMacOSPlatform();
11 |
12 | async function saveEntries(entries, filename, options, parentHandle) {
13 | if (filesystemService.savePickersSupported()) {
14 | try {
15 | if (!parentHandle && (entries.length > 1 || entries[0].directory)) {
16 | parentHandle = await getParentHandle();
17 | }
18 | } catch (error) {
19 | if (downloadService.downloadAborted(error)) {
20 | return;
21 | } else {
22 | throw error;
23 | }
24 | }
25 | }
26 | await Promise.all(
27 | entries.map(async (entry) =>
28 | saveFile(entry, filename, options, parentHandle)
29 | )
30 | );
31 | }
32 |
33 | async function saveFile(entry, filename, options, parentHandle) {
34 | if (!parentHandle && entry.directory) {
35 | parentHandle = await getParentHandle();
36 | }
37 | const name = filename || entry.name;
38 | let download;
39 | try {
40 | if (entry.directory) {
41 | await saveDirectoryEntry(name, entry, options, parentHandle);
42 | } else {
43 | download = {
44 | name,
45 | controller: downloadService.createAbortController(),
46 | progressValue: null,
47 | progressMax: null
48 | };
49 | await saveFileEntry(name, entry, options, download, parentHandle);
50 | }
51 | } catch (error) {
52 | if (!downloadService.downloadAborted(error)) {
53 | throw error;
54 | }
55 | } finally {
56 | if (download) {
57 | removeDownload(download);
58 | }
59 | }
60 | }
61 |
62 | async function saveDirectoryEntry(name, entry, options, parentHandle) {
63 | const directoryHandle = await parentHandle.getDirectoryHandle(name, {
64 | create: true
65 | });
66 | await saveEntries(entry.children, null, options, directoryHandle);
67 | }
68 |
69 | async function saveFileEntry(name, entry, options, download, parentHandle) {
70 | const { signal } = download.controller;
71 | const onprogress = (progressValue, progressMax) =>
72 | onDownloadProgress(download.id, progressValue, progressMax);
73 | let fileHandle, writable, blob;
74 | if (filesystemService.savePickersSupported()) {
75 | if (parentHandle) {
76 | fileHandle = await parentHandle.getFileHandle(name, {
77 | create: true
78 | });
79 | } else {
80 | fileHandle = await getFileHandle(name);
81 | download.name = fileHandle.name;
82 | }
83 | writable = await fileHandle.createWritable();
84 | } else {
85 | ({ writable, blob } = getWritableBlob());
86 | }
87 | setDownloads((downloads) => {
88 | let { nextId } = downloads;
89 | download.id = nextId;
90 | nextId = nextId + 1;
91 | return {
92 | nextId,
93 | queue: [download, ...downloads.queue]
94 | };
95 | });
96 | await entry.getWritable(writable, { signal, onprogress, ...options });
97 | if (!filesystemService.savePickersSupported() && !signal.aborted) {
98 | filesystemService.saveBlob(await blob, download.name);
99 | }
100 | }
101 |
102 | function getWritableBlob() {
103 | // eslint-disable-next-line no-undef
104 | const { readable, writable } = new TransformStream({});
105 | // eslint-disable-next-line no-undef
106 | const blob = new Response(readable).blob();
107 | return {
108 | blob,
109 | writable
110 | };
111 | }
112 |
113 | function getParentHandle() {
114 | return filesystemService.showDirectoryPicker({
115 | mode: "readwrite",
116 | startIn: "downloads"
117 | });
118 | }
119 |
120 | function getFileHandle(suggestedName) {
121 | return filesystemService.showSaveFilePicker({
122 | suggestedName,
123 | mode: "readwrite",
124 | startIn: "downloads"
125 | });
126 | }
127 |
128 | function onDownloadProgress(downloadId, progressValue, progressMax) {
129 | setDownloads((downloads) => ({
130 | ...downloads,
131 | queue: downloads.queue.map((download) => {
132 | if (download.id === downloadId) {
133 | download = {
134 | ...download,
135 | progressValue,
136 | progressMax
137 | };
138 | }
139 | return download;
140 | })
141 | }));
142 | }
143 |
144 | function openDisplayError(message) {
145 | setDialogs({
146 | ...dialogs,
147 | displayError: { message }
148 | });
149 | }
150 |
151 | function closeDisplayError() {
152 | setDialogs({
153 | ...dialogs,
154 | displayError: null
155 | });
156 | }
157 |
158 | function modifierKeyPressed(event) {
159 | return isMacOSPlatform ? event.metaKey : event.ctrlKey;
160 | }
161 |
162 | return {
163 | modifierKeyPressed,
164 | saveZipFile: saveFile,
165 | saveEntries,
166 | openDisplayError,
167 | closeDisplayError
168 | };
169 | }
170 |
171 | export default getCommonFeatures;
172 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/downloads.js:
--------------------------------------------------------------------------------
1 | function getDownloadsFeatures({ setDownloads, downloadService }) {
2 | function abortDownload(deletedDownload) {
3 | removeDownload(deletedDownload);
4 | downloadService.abortDownload(deletedDownload.controller);
5 | }
6 |
7 | function removeDownload(deletedDownload) {
8 | setDownloads((downloads) => ({
9 | ...downloads,
10 | queue: downloads.queue.filter(
11 | (download) => download.id !== deletedDownload.id
12 | )
13 | }));
14 | }
15 |
16 | return {
17 | removeDownload,
18 | abortDownload
19 | };
20 | }
21 |
22 | export default getDownloadsFeatures;
23 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/filesystem.js:
--------------------------------------------------------------------------------
1 | function getFilesystemFeatures({
2 | dialogs,
3 | setZipFilesystem,
4 | setDialogs,
5 | zipService
6 | }) {
7 | function openConfirmReset() {
8 | setDialogs({
9 | ...dialogs,
10 | reset: {}
11 | });
12 | }
13 |
14 | function reset() {
15 | setZipFilesystem(zipService.createZipFileSystem());
16 | }
17 |
18 | function closeConfirmReset() {
19 | setDialogs({
20 | ...dialogs,
21 | reset: null
22 | });
23 | }
24 |
25 | return {
26 | openConfirmReset,
27 | reset,
28 | closeConfirmReset
29 | };
30 | }
31 |
32 | export default getFilesystemFeatures;
33 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/folders.js:
--------------------------------------------------------------------------------
1 | function getFoldersFeatures({
2 | disabledBack,
3 | disabledForward,
4 | history,
5 | highlightedEntry,
6 | highlightedEntries,
7 | modifierKeyPressed,
8 | selectedFolder,
9 | setSelectedFolder,
10 | setEntries,
11 | setHistory,
12 | setHighlightedIds,
13 | setClickedButtonName,
14 | constants
15 | }) {
16 | const {
17 | LEFT_KEY,
18 | RIGHT_KEY,
19 | BACK_KEY,
20 | FORWARD_KEY,
21 | BACK_BUTTON_NAME,
22 | FORWARD_BUTTON_NAME
23 | } = constants;
24 |
25 | function goIntoFolder(entry) {
26 | const path = [...history.path];
27 | const index = history.index + 1;
28 | if (entry.isDescendantOf(selectedFolder)) {
29 | path.length = index + 1;
30 | }
31 | path[index] = entry;
32 | setHistory({
33 | index,
34 | path
35 | });
36 | highlightEntry(selectedFolder, entry);
37 | setSelectedFolder(entry);
38 | refreshSelectedFolder(entry);
39 | }
40 |
41 | function navigateBack() {
42 | navigateHistory(-1);
43 | }
44 |
45 | function navigateForward() {
46 | navigateHistory(1);
47 | }
48 |
49 | function navigateHistory(offset) {
50 | const index = history.index + offset;
51 | setHistory({
52 | ...history,
53 | index
54 | });
55 | const entry = history.path[index];
56 | highlightEntry(selectedFolder, entry);
57 | setSelectedFolder(entry);
58 | refreshSelectedFolder(entry);
59 | }
60 |
61 | function highlightEntry(selectedFolder, entry) {
62 | if (
63 | selectedFolder.children.includes(entry) ||
64 | entry.children.includes(selectedFolder)
65 | ) {
66 | setHighlightedIds([selectedFolder.id]);
67 | } else {
68 | const highlightedEntry = entry.children.find((child) =>
69 | selectedFolder.isDescendantOf(child)
70 | );
71 | setHighlightedIds(
72 | highlightedEntry ? [highlightedEntry.id] : [entry.parent.id]
73 | );
74 | }
75 | }
76 |
77 | function updateHistoryData() {
78 | let offsetIndex = 0;
79 | let previousEntry;
80 | const path = history.path.filter((entry, indexEntry) => {
81 | const entryRemoved =
82 | previousEntry === entry ||
83 | highlightedEntries.includes(entry) ||
84 | highlightedEntries.find((highlightedEntry) =>
85 | entry.isDescendantOf(highlightedEntry)
86 | );
87 | if (entryRemoved) {
88 | if (indexEntry <= history.index) {
89 | offsetIndex++;
90 | }
91 | } else {
92 | previousEntry = entry;
93 | }
94 | return !entryRemoved;
95 | });
96 | const index = history.index - offsetIndex;
97 | setHistory({
98 | path,
99 | index
100 | });
101 | }
102 |
103 | function refreshSelectedFolder(folder = selectedFolder) {
104 | if (folder) {
105 | const { parent, children } = folder;
106 | const folders = filterChildren(children, true);
107 | const files = filterChildren(children, false);
108 | const ancestors = [];
109 | if (parent) {
110 | ancestors.push(parent);
111 | }
112 | setEntries([...ancestors, ...folders, ...files]);
113 | }
114 | }
115 |
116 | function filterChildren(children, isDirectory) {
117 | return children
118 | .filter((child) => Boolean(child.directory) === isDirectory)
119 | .sort((previousChild, nextChild) =>
120 | previousChild.name.localeCompare(nextChild.name)
121 | );
122 | }
123 |
124 | function onFoldersKeyUp(event) {
125 | if (event.altKey) {
126 | if (event.key === BACK_KEY && !disabledBack) {
127 | setClickedButtonName(BACK_BUTTON_NAME);
128 | }
129 | if (event.key === FORWARD_KEY && !disabledForward) {
130 | setClickedButtonName(FORWARD_BUTTON_NAME);
131 | }
132 | }
133 | if (!event.altKey && !modifierKeyPressed(event) && !event.shiftKey) {
134 | if (event.key === LEFT_KEY && selectedFolder.parent) {
135 | goIntoFolder(selectedFolder.parent);
136 | }
137 | if (
138 | event.key === RIGHT_KEY &&
139 | highlightedEntry &&
140 | highlightedEntry.directory
141 | ) {
142 | goIntoFolder(highlightedEntry);
143 | }
144 | }
145 | }
146 |
147 | return {
148 | goIntoFolder,
149 | navigateBack,
150 | navigateForward,
151 | refreshSelectedFolder,
152 | updateHistoryData,
153 | onFoldersKeyUp
154 | };
155 | }
156 |
157 | export default getFoldersFeatures;
158 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/highlighted-entries.js:
--------------------------------------------------------------------------------
1 | function getHighlightedEntriesFeatures({
2 | disabledCopy,
3 | disabledCut,
4 | disabledExtract,
5 | disabledRename,
6 | disabledDelete,
7 | zipFilesystem,
8 | entries,
9 | highlightedIds,
10 | highlightedEntry,
11 | highlightedEntries,
12 | navigation,
13 | dialogs,
14 | modifierKeyPressed,
15 | setClipboardData,
16 | setHighlightedIds,
17 | setNavigation,
18 | setDialogs,
19 | setClickedButtonName,
20 | refreshSelectedFolder,
21 | updateHistoryData,
22 | saveEntries,
23 | getOptions,
24 | openDisplayError,
25 | filesystemService,
26 | constants
27 | }) {
28 | const {
29 | CUT_KEY,
30 | COPY_KEY,
31 | EXTRACT_KEY,
32 | RENAME_KEY,
33 | CUT_BUTTON_NAME,
34 | COPY_BUTTON_NAME,
35 | EXTRACT_BUTTON_NAME,
36 | RENAME_BUTTON_NAME,
37 | DELETE_KEYS,
38 | DELETE_BUTTON_NAME
39 | } = constants;
40 |
41 | function copy() {
42 | setClipboardData({
43 | entries: highlightedEntries.map((entry) => entry.clone(true))
44 | });
45 | }
46 |
47 | function cut() {
48 | setClipboardData({
49 | entries: highlightedEntries,
50 | cut: true
51 | });
52 | }
53 |
54 | function openPromptRename() {
55 | setDialogs({
56 | ...dialogs,
57 | rename: {
58 | filename: highlightedEntry.name
59 | }
60 | });
61 | }
62 |
63 | function rename({ filename }) {
64 | try {
65 | if (filename !== highlightedEntry.name) {
66 | highlightedEntry.rename(filename);
67 | refreshSelectedFolder();
68 | }
69 | } catch (error) {
70 | openDisplayError(error.message);
71 | }
72 | }
73 | function closePromptRename() {
74 | setDialogs({
75 | ...dialogs,
76 | rename: null
77 | });
78 | }
79 |
80 | function openConfirmDeleteEntries() {
81 | setDialogs({
82 | ...dialogs,
83 | deleteEntries: {}
84 | });
85 | }
86 |
87 | function deleteEntries() {
88 | highlightedEntries.forEach((entry) => zipFilesystem.remove(entry));
89 | if (entries.length) {
90 | const indexEntry = Math.max(
91 | ...entries
92 | .map((entry, index) => ({ entry, index }))
93 | .filter(({ entry }) => highlightedIds.includes(entry.id))
94 | .map(({ index }) => index)
95 | );
96 | let indexNextEntry = indexEntry;
97 | while (
98 | indexNextEntry < entries.length &&
99 | highlightedIds.includes(entries[indexNextEntry].id)
100 | ) {
101 | indexNextEntry++;
102 | }
103 | if (indexNextEntry === entries.length) {
104 | indexNextEntry = indexEntry;
105 | while (
106 | indexNextEntry >= 0 &&
107 | highlightedIds.includes(entries[indexNextEntry].id)
108 | ) {
109 | indexNextEntry--;
110 | }
111 | }
112 | if (entries[indexNextEntry]) {
113 | setNavigation({
114 | ...navigation,
115 | previousHighlight: entries[indexNextEntry]
116 | });
117 | setHighlightedIds([entries[indexNextEntry].id]);
118 | } else {
119 | setNavigation({
120 | ...navigation,
121 | previousHighlight: null
122 | });
123 | setHighlightedIds([]);
124 | }
125 | }
126 | updateHistoryData();
127 | refreshSelectedFolder();
128 | }
129 |
130 | function closeConfirmDeleteEntries() {
131 | setDialogs({
132 | ...dialogs,
133 | deleteEntries: null
134 | });
135 | }
136 |
137 | function openPromptExtract(entry = highlightedEntry) {
138 | const options = {
139 | entries: [entry],
140 | filename: entry.name
141 | };
142 | if (filesystemService.savePickersSupported()) {
143 | extract(options);
144 | } else {
145 | setDialogs({
146 | ...dialogs,
147 | extract: options
148 | });
149 | }
150 | }
151 |
152 | function extract({ entries = highlightedEntries, filename } = {}) {
153 | async function download() {
154 | try {
155 | const options = getOptions();
156 | filename = entries.length === 1 ? filename : null;
157 | await saveEntries(entries, filename, options);
158 | } catch (error) {
159 | openDisplayError(error.message);
160 | }
161 | }
162 |
163 | download();
164 | }
165 |
166 | function closePromptExtract() {
167 | setDialogs({
168 | ...dialogs,
169 | extract: null
170 | });
171 | }
172 |
173 | function onHighlightedEntriesKeyUp(event) {
174 | if (!event.altKey && !modifierKeyPressed(event) && !event.shiftKey) {
175 | if (DELETE_KEYS.includes(event.key) && !disabledDelete) {
176 | setClickedButtonName(DELETE_BUTTON_NAME);
177 | }
178 | }
179 | }
180 |
181 | function onHighlightedEntriesKeyDown(event) {
182 | if (modifierKeyPressed(event)) {
183 | if (event.key === COPY_KEY && !disabledCopy) {
184 | setClickedButtonName(COPY_BUTTON_NAME);
185 | event.preventDefault();
186 | }
187 | if (event.key === CUT_KEY && !disabledCut) {
188 | setClickedButtonName(CUT_BUTTON_NAME);
189 | event.preventDefault();
190 | }
191 | if (event.key === EXTRACT_KEY && !disabledExtract) {
192 | setClickedButtonName(EXTRACT_BUTTON_NAME);
193 | event.preventDefault();
194 | }
195 | if (event.key === RENAME_KEY && !disabledRename) {
196 | setClickedButtonName(RENAME_BUTTON_NAME);
197 | event.preventDefault();
198 | }
199 | }
200 | }
201 |
202 | return {
203 | copy,
204 | cut,
205 | openPromptRename,
206 | rename,
207 | closePromptRename,
208 | openConfirmDeleteEntries,
209 | deleteEntries,
210 | closeConfirmDeleteEntries,
211 | openPromptExtract,
212 | extract,
213 | closePromptExtract,
214 | onHighlightedEntriesKeyUp,
215 | onHighlightedEntriesKeyDown
216 | };
217 | }
218 |
219 | export default getHighlightedEntriesFeatures;
220 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/index.js:
--------------------------------------------------------------------------------
1 | import getCommonFeatures from "./common.js";
2 | import getEntriesFeatures from "./entries.js";
3 | import getFoldersFeatures from "./folders.js";
4 | import getSelectedFolderFeatures from "./selected-folder.js";
5 | import getHighlightedEntriesFeatures from "./highlighted-entries.js";
6 | import getAppFeatures from "./app.js";
7 | import getFilesystemFeatures from "./filesystem.js";
8 | import getDownloadsFeatures from "./downloads.js";
9 | import getClipboardFeatures from "./clipboard.js";
10 | import getOptionsFeatures from "./options.js";
11 | import getMiscFeatures from "./misc.js";
12 |
13 | export {
14 | getCommonFeatures,
15 | getEntriesFeatures,
16 | getFoldersFeatures,
17 | getSelectedFolderFeatures,
18 | getHighlightedEntriesFeatures,
19 | getAppFeatures,
20 | getFilesystemFeatures,
21 | getDownloadsFeatures,
22 | getClipboardFeatures,
23 | getOptionsFeatures,
24 | getMiscFeatures
25 | };
26 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/misc.js:
--------------------------------------------------------------------------------
1 | function getMiscFeatures({
2 | theme,
3 | setOptions,
4 | setTheme,
5 | setMusicData,
6 | setPlayerActive,
7 | getOptions,
8 | stylesheetService,
9 | themeService,
10 | musicService,
11 | constants
12 | }) {
13 | const { ACCENT_COLOR_CUSTOM_PROPERTY_NAME } = themeService;
14 |
15 | function initMiscFeatures() {
16 | const options = getOptions();
17 | const { accentColor, skin } = options;
18 | setTheme({ accentColor, skin });
19 | }
20 |
21 | function playMusic() {
22 | setPlayerActive(true);
23 | updateSkin();
24 | musicService.play({
25 | onSetFrequencyData: (frequencyData) => {
26 | setMusicData(() => ({
27 | frequencyData
28 | }));
29 | }
30 | });
31 | }
32 |
33 | function updateSkin() {
34 | if (theme.skin) {
35 | musicService.setFftSize(constants.FFT_RESOLUTIONS[theme.skin]);
36 | }
37 | }
38 |
39 | function stopMusic() {
40 | setMusicData({ frequencyData: [] });
41 | setPlayerActive(false);
42 | musicService.stop();
43 | }
44 |
45 | function updateAccentColor() {
46 | const { accentColor, skin } = theme;
47 | if (accentColor) {
48 | stylesheetService.setStyle(
49 | ACCENT_COLOR_CUSTOM_PROPERTY_NAME,
50 | theme.accentColor
51 | );
52 | themeService.setTheme({ accentColor, skin });
53 | const options = getOptions();
54 | setOptions({ ...options, accentColor });
55 | }
56 | }
57 |
58 | return {
59 | initMiscFeatures,
60 | playMusic,
61 | stopMusic,
62 | updateAccentColor,
63 | updateSkin
64 | };
65 | }
66 |
67 | export default getMiscFeatures;
68 |
--------------------------------------------------------------------------------
/src/zip-manager/business/features/options.js:
--------------------------------------------------------------------------------
1 | function getOptionsFeatures({
2 | dialogs,
3 | setDialogs,
4 | setTheme,
5 | zipService,
6 | storageService,
7 | stylesheetService,
8 | environmentService,
9 | themeService,
10 | constants
11 | }) {
12 | const { DEFAULT_OPTIONS, OPTIONS_KEY_NAME, FONT_SIZE_PROPERTY_NAME } =
13 | constants;
14 |
15 | function initOptionsFeatures() {
16 | applyOptions(getOptions());
17 | }
18 |
19 | function applyOptions(options) {
20 | configureZipService(options);
21 | configureZoomFactor(options);
22 | configureTheme(options);
23 | }
24 |
25 | function openOptions() {
26 | setDialogs({
27 | ...dialogs,
28 | options: getOptions()
29 | });
30 | }
31 |
32 | function closeOptions() {
33 | setDialogs({
34 | ...dialogs,
35 | options: null
36 | });
37 | }
38 |
39 | function resetOptions() {
40 | const options = { ...DEFAULT_OPTIONS };
41 | options.maxWorkers = environmentService.getMaximumWorkers();
42 | setDialogs({
43 | ...dialogs,
44 | options
45 | });
46 | }
47 |
48 | function setOptions(options) {
49 | const previousOptions = getOptions();
50 | options = { ...previousOptions, ...options };
51 | applyOptions(options);
52 | storageService.set(OPTIONS_KEY_NAME, options);
53 | }
54 |
55 | function getOptions() {
56 | let options = storageService.get(OPTIONS_KEY_NAME);
57 | if (!options) {
58 | options = { ...DEFAULT_OPTIONS };
59 | options.maxWorkers = environmentService.getMaximumWorkers();
60 | }
61 | if (options.hideNavigationBar === undefined) {
62 | options.hideNavigationBar = DEFAULT_OPTIONS.hideNavigationBar;
63 | }
64 | if (options.hideDownloadManager === undefined) {
65 | options.hideDownloadManager = DEFAULT_OPTIONS.hideDownloadManager;
66 | }
67 | if (options.hideInfobar === undefined) {
68 | options.hideInfobar = DEFAULT_OPTIONS.hideInfobar;
69 | }
70 | if (options.promptForExportPassword === undefined) {
71 | options.promptForExportPassword = DEFAULT_OPTIONS.promptForExportPassword;
72 | }
73 | if (options.defaultExportPassword === undefined) {
74 | options.defaultExportPassword = DEFAULT_OPTIONS.defaultExportPassword;
75 | }
76 | if (options.checkSignature === undefined) {
77 | options.checkSignature = DEFAULT_OPTIONS.checkSignature;
78 | }
79 | if (options.accentColor === undefined) {
80 | options.accentColor = DEFAULT_OPTIONS.accentColor;
81 | }
82 | if (options.zoomFactor === undefined) {
83 | options.zoomFactor = DEFAULT_OPTIONS.zoomFactor;
84 | }
85 | if (options.skin === undefined) {
86 | options.skin = DEFAULT_OPTIONS.skin;
87 | }
88 | return options;
89 | }
90 |
91 | function configureZipService(options) {
92 | const { maxWorkers, chunkSize } = options;
93 | zipService.configure({
94 | maxWorkers,
95 | chunkSize
96 | });
97 | }
98 |
99 | function configureZoomFactor({ zoomFactor }) {
100 | stylesheetService.setStyle(
101 | FONT_SIZE_PROPERTY_NAME,
102 | zoomFactor / 100 + "rem"
103 | );
104 | }
105 |
106 | function configureTheme({ accentColor, skin }) {
107 | setTheme({ accentColor, skin });
108 | themeService.setTheme({ accentColor, skin });
109 | }
110 |
111 | return {
112 | initOptionsFeatures,
113 | getOptions,
114 | setOptions,
115 | openOptions,
116 | closeOptions,
117 | resetOptions
118 | };
119 | }
120 |
121 | export default getOptionsFeatures;
122 |
--------------------------------------------------------------------------------
/src/zip-manager/business/index.js:
--------------------------------------------------------------------------------
1 | import * as constants from "./constants.js";
2 | import getUIState from "./ui-state.js";
3 | import getEventHandlers from "./events.js";
4 | import * as features from "./features/index.js";
5 |
6 | export { constants, features, getUIState, getEventHandlers };
7 |
--------------------------------------------------------------------------------
/src/zip-manager/business/ui-state.js:
--------------------------------------------------------------------------------
1 | function getUIState({
2 | entries,
3 | highlightedIds,
4 | selectedFolder,
5 | clipboardData,
6 | history,
7 | dialogs,
8 | getOptions,
9 | filesystemService
10 | }) {
11 | const entriesEmpty = !entries.length;
12 | const parentFolderHighlighted =
13 | !highlightedIds.length ||
14 | (selectedFolder.parent &&
15 | highlightedIds.includes(selectedFolder.parent.id));
16 | const subFolderHighlighted = highlightedIds.find((id) => {
17 | const entry = selectedFolder.children.find((entry) => entry.id === id);
18 | if (entry) {
19 | return entry.directory;
20 | }
21 | return false;
22 | });
23 | const clipboardDataEmpty = !clipboardData;
24 | const selectedFolderEntries = entries.filter(
25 | (entry) => entry !== selectedFolder.parent
26 | );
27 | const disabledExportZip = entriesEmpty || !selectedFolderEntries.length;
28 | const disabledReset = entriesEmpty;
29 | const disabledNavigation = entriesEmpty;
30 | const disabledBack = !history.index;
31 | const disabledForward = history.index === history.path.length - 1;
32 | const disabledCopy = parentFolderHighlighted;
33 | const disabledCut = parentFolderHighlighted;
34 | const disabledPaste =
35 | clipboardDataEmpty ||
36 | (clipboardData.cut &&
37 | clipboardData.entries.find(
38 | (entry) =>
39 | selectedFolder == entry || selectedFolder.isDescendantOf(entry)
40 | ));
41 | const disabledResetClipboardData = clipboardDataEmpty;
42 | const disabledExtract =
43 | parentFolderHighlighted ||
44 | !highlightedIds.length ||
45 | (!filesystemService.savePickersSupported() && subFolderHighlighted);
46 | const disabledHighlightAll =
47 | !selectedFolder ||
48 | !selectedFolderEntries.length ||
49 | (selectedFolderEntries.length === highlightedIds.length &&
50 | selectedFolderEntries.every((entry) =>
51 | highlightedIds.includes(entry.id)
52 | ));
53 | const disabledRename = highlightedIds.length !== 1 || parentFolderHighlighted;
54 | const disabledDelete = parentFolderHighlighted;
55 | const disabledEnterEntry = highlightedIds.length !== 1;
56 | const dialogDisplayed =
57 | dialogs.exportZip ||
58 | dialogs.extract ||
59 | dialogs.rename ||
60 | dialogs.createFolder ||
61 | dialogs.deleteEntries ||
62 | dialogs.reset ||
63 | dialogs.displayError ||
64 | dialogs.enterImportPassword ||
65 | dialogs.chooseAction ||
66 | dialogs.options;
67 | const options = getOptions();
68 | const hiddenNavigationBar = options.hideNavigationBar;
69 | const hiddenDownloadManager = options.hideDownloadManager;
70 | const hiddenInfobar = options.hideInfobar;
71 | const hiddenExportPassword = !options.promptForExportPassword;
72 | const highlightedEntries =
73 | (selectedFolder &&
74 | selectedFolder.children.filter((entry) =>
75 | highlightedIds.includes(entry.id)
76 | )) ||
77 | [];
78 | const highlightedEntry =
79 | highlightedIds.length === 1 &&
80 | selectedFolder &&
81 | selectedFolder.children.find((entry) => entry.id === highlightedIds[0]);
82 | const ancestorFolders = getAncestors(selectedFolder);
83 |
84 | return {
85 | disabledExportZip,
86 | disabledReset,
87 | disabledNavigation,
88 | disabledBack,
89 | disabledForward,
90 | disabledCopy,
91 | disabledCut,
92 | disabledPaste,
93 | disabledResetClipboardData,
94 | disabledExtract,
95 | disabledHighlightAll,
96 | disabledRename,
97 | disabledDelete,
98 | disabledEnterEntry,
99 | dialogDisplayed,
100 | hiddenNavigationBar,
101 | hiddenDownloadManager,
102 | hiddenInfobar,
103 | hiddenExportPassword,
104 | highlightedEntries,
105 | highlightedEntry,
106 | selectedFolderEntries,
107 | ancestorFolders
108 | };
109 | }
110 |
111 | function getAncestors(folder) {
112 | const ancestors = [];
113 | while (folder?.parent) {
114 | ancestors.unshift(folder);
115 | folder = folder.parent;
116 | }
117 | if (folder) {
118 | ancestors.unshift(folder);
119 | }
120 | return ancestors;
121 | }
122 |
123 | export default getUIState;
124 |
--------------------------------------------------------------------------------
/src/zip-manager/components/BottomButtonBar.jsx:
--------------------------------------------------------------------------------
1 | import "./styles/BottomButtonBar.css";
2 |
3 | import { useRef } from "react";
4 |
5 | import {
6 | CopyEntryButton,
7 | CutEntryButton,
8 | PasteEntryButton,
9 | ResetClipboardDataButton,
10 | ExtractEntryButton,
11 | HighlightAllButton,
12 | RenameEntryButton,
13 | DeleteEntriesButton
14 | } from "./Buttons.jsx";
15 |
16 | function BottomButtonBar({
17 | disabledCopyButton,
18 | disabledCutButton,
19 | disabledPasteButton,
20 | disabledResetClipboardDataButton,
21 | disabledExtractButton,
22 | disabledHighlightAllButton,
23 | disabledRenameButton,
24 | disabledDeleteButton,
25 | clickedButtonName,
26 | onCopy,
27 | onCut,
28 | onPaste,
29 | onResetClipboardData,
30 | onExtract,
31 | onHighlightAll,
32 | onRename,
33 | onRemove,
34 | onMove,
35 | onUpdateElementHeight,
36 | onClickedButton,
37 | constants,
38 | messages
39 | }) {
40 | const previousTouchClientY = useRef(0);
41 |
42 | function handleTouchMove(event) {
43 | const { clientY } = event.changedTouches[0];
44 | if (previousTouchClientY.current) {
45 | const deltaY = clientY - previousTouchClientY.current;
46 | onMove(deltaY);
47 | } else {
48 | previousTouchClientY.current = clientY;
49 | }
50 | }
51 |
52 | function handleTouchEnd() {
53 | previousTouchClientY.current = 0;
54 | onUpdateElementHeight();
55 | }
56 |
57 | return (
58 | event.preventDefault()}
65 | >
66 |
67 |
75 |
83 |
91 |
99 |
100 |
101 |
109 |
117 |
125 |
130 |
131 |
132 | );
133 | }
134 |
135 | export default BottomButtonBar;
136 |
--------------------------------------------------------------------------------
/src/zip-manager/components/Breadcrumb.jsx:
--------------------------------------------------------------------------------
1 | function Breadcrumb({
2 | folder: selectedFolder,
3 | ancestorFolders,
4 | onGoIntoFolder,
5 | constants,
6 | messages
7 | }) {
8 | return (
9 |
28 | );
29 | }
30 |
31 | function BreadcrumbItem({
32 | disabled,
33 | folder,
34 | isSelectedFolder,
35 | onGoIntoFolder,
36 | constants,
37 | messages
38 | }) {
39 | function getBreadcrumbItemClassName() {
40 | const classes = ["breadcrumb-item"];
41 | if (!disabled) {
42 | classes.push("breadcrumb-item-active");
43 | }
44 | return classes.join(" ");
45 | }
46 |
47 | function handleClick() {
48 | if (!disabled) {
49 | onGoIntoFolder(folder);
50 | }
51 | }
52 |
53 | function handleKeyUp({ event, folder }) {
54 | if (event.key === constants.ENTER_KEY) {
55 | handleClick(folder);
56 | }
57 | }
58 |
59 | return (
60 | handleKeyUp({ event, folder })}
67 | tabIndex={disabled ? null : 0}
68 | >
69 | {folder.parent ? folder.name : messages.ROOT_FOLDER_LABEL}
70 |
71 | );
72 | }
73 |
74 | export default Breadcrumb;
75 |
--------------------------------------------------------------------------------
/src/zip-manager/components/Buttons.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 |
3 | function CopyEntryButton({
4 | disabled,
5 | clickedButtonName,
6 | onCopy,
7 | onClickedButton,
8 | constants,
9 | messages
10 | }) {
11 | return (
12 |
21 | );
22 | }
23 |
24 | function CutEntryButton({
25 | disabled,
26 | clickedButtonName,
27 | onCut,
28 | onClickedButton,
29 | constants,
30 | messages
31 | }) {
32 | return (
33 |
42 | );
43 | }
44 |
45 | function PasteEntryButton({
46 | disabled,
47 | clickedButtonName,
48 | onPaste,
49 | onClickedButton,
50 | constants,
51 | messages
52 | }) {
53 | return (
54 |
63 | );
64 | }
65 |
66 | function ResetClipboardDataButton({
67 | disabled,
68 | onResetClipboardData,
69 | messages
70 | }) {
71 | return (
72 |
77 | );
78 | }
79 |
80 | function HighlightAllButton({
81 | disabled,
82 | clickedButtonName,
83 | onHighlightAll,
84 | onClickedButton,
85 | constants,
86 | messages
87 | }) {
88 | return (
89 |
98 | );
99 | }
100 |
101 | function ExtractEntryButton({
102 | disabled,
103 | clickedButtonName,
104 | onExtract,
105 | onClickedButton,
106 | constants,
107 | messages
108 | }) {
109 | return (
110 |
119 | );
120 | }
121 |
122 | function RenameEntryButton({
123 | disabled,
124 | clickedButtonName,
125 | onRename,
126 | onClickedButton,
127 | constants,
128 | messages
129 | }) {
130 | return (
131 |
140 | );
141 | }
142 |
143 | function DeleteEntriesButton({
144 | disabled,
145 | clickedButtonName,
146 | onRemove,
147 | onClickedButton,
148 | constants,
149 | messages
150 | }) {
151 | return (
152 |
161 | );
162 | }
163 |
164 | function CreateFolderButton({
165 | clickedButtonName,
166 | onCreateFolder,
167 | onClickedButton,
168 | constants,
169 | messages
170 | }) {
171 | return (
172 |
180 | );
181 | }
182 |
183 | function AddFilesButton({
184 | clickedButtonName,
185 | onShowAddFilesPicker,
186 | onClickedButton,
187 | constants,
188 | messages
189 | }) {
190 | return (
191 |
199 | );
200 | }
201 |
202 | function ImportZipButton({
203 | clickedButtonName,
204 | onShowImportZipFilePicker,
205 | onClickedButton,
206 | constants,
207 | messages
208 | }) {
209 | const { IMPORT_ZIP_BUTTON_NAME } = constants;
210 |
211 | function handleClick() {
212 | onShowImportZipFilePicker({
213 | description: messages.ZIP_FILE_DESCRIPTION_LABEL
214 | });
215 | }
216 |
217 | return (
218 |
226 | );
227 | }
228 |
229 | function ExportZipButton({
230 | disabled,
231 | clickedButtonName,
232 | onExportZip,
233 | onClickedButton,
234 | constants,
235 | messages
236 | }) {
237 | return (
238 |
247 | );
248 | }
249 |
250 | function ResetButton({ disabled, onReset, messages }) {
251 | return (
252 |
257 | );
258 | }
259 |
260 | function OptionsButton({ onOpenOptions, messages }) {
261 | return (
262 |
263 | );
264 | }
265 |
266 | function BackButton({
267 | disabled,
268 | clickedButtonName,
269 | onNavigateBack,
270 | onClickedButton,
271 | constants,
272 | messages
273 | }) {
274 | return (
275 |
285 | );
286 | }
287 |
288 | function ForwardButton({
289 | disabled,
290 | clickedButtonName,
291 | onNavigateForward,
292 | onClickedButton,
293 | constants,
294 | messages
295 | }) {
296 | return (
297 |
307 | );
308 | }
309 |
310 | function Button({
311 | name,
312 | title,
313 | label,
314 | disabled,
315 | ariaLabel,
316 | clickedButtonName,
317 | onClick,
318 | onClickedButton
319 | }) {
320 | const [className, setClassName] = useState(null);
321 |
322 | function handleAnimationEnd() {
323 | setClassName(null);
324 | onClickedButton();
325 | onClick();
326 | }
327 |
328 | useEffect(() => {
329 | if (clickedButtonName && clickedButtonName === name) {
330 | setClassName("flashing-button");
331 | }
332 | }, [name, clickedButtonName]);
333 | return (
334 |
344 | );
345 | }
346 |
347 | export {
348 | CopyEntryButton,
349 | CutEntryButton,
350 | PasteEntryButton,
351 | ResetClipboardDataButton,
352 | HighlightAllButton,
353 | ExtractEntryButton,
354 | RenameEntryButton,
355 | DeleteEntriesButton,
356 | CreateFolderButton,
357 | AddFilesButton,
358 | ImportZipButton,
359 | ExportZipButton,
360 | ResetButton,
361 | OptionsButton,
362 | BackButton,
363 | ForwardButton
364 | };
365 |
--------------------------------------------------------------------------------
/src/zip-manager/components/Downloads.jsx:
--------------------------------------------------------------------------------
1 | import "./styles/Downloads.css";
2 |
3 | function Downloads({
4 | hidden,
5 | downloads,
6 | onAbortDownload,
7 | i18n,
8 | constants,
9 | messages
10 | }) {
11 | if (hidden) {
12 | return;
13 | } else {
14 | return (
15 |
20 |
21 | {downloads.queue.map((download) => (
22 | -
23 |
30 |
31 | ))}
32 |
33 |
34 | );
35 | }
36 | }
37 |
38 | function DownloadEntry({
39 | download,
40 | onAbortDownload,
41 | i18n,
42 | constants,
43 | messages
44 | }) {
45 | return (
46 | <>
47 |
53 |
54 | >
55 | );
56 | }
57 |
58 | function DownloadEntryInfo({ download, onAbortDownload, constants, messages }) {
59 | return (
60 |
61 |
62 | {download.name}
63 |
64 |
70 |
71 | );
72 | }
73 |
74 | function DeleteDownloadEntryButton({
75 | download,
76 | onAbortDownload,
77 | constants,
78 | messages
79 | }) {
80 | function handleClick() {
81 | onAbortDownload(download);
82 | }
83 |
84 | function handleKeyUp(event) {
85 | if (event.key === constants.ENTER_KEY) {
86 | handleClick();
87 | }
88 | }
89 |
90 | return (
91 |
98 | {messages.ABORT_DOWNLOAD_BUTTON_LABEL}
99 |
100 | );
101 | }
102 |
103 | function DownloadEntryProgress({ download, i18n }) {
104 | return (
105 |
117 | );
118 | }
119 |
120 | export default Downloads;
121 |
--------------------------------------------------------------------------------
/src/zip-manager/components/History.jsx:
--------------------------------------------------------------------------------
1 | import { BackButton, ForwardButton } from "./Buttons.jsx";
2 |
3 | function History({
4 | disabledBackButton,
5 | disabledForwardButton,
6 | clickedButtonName,
7 | onNavigateBack,
8 | onNavigateForward,
9 | onClickedButton,
10 | constants,
11 | messages
12 | }) {
13 | return (
14 |
15 |
23 |
31 |
32 | );
33 | }
34 |
35 | export default History;
36 |
--------------------------------------------------------------------------------
/src/zip-manager/components/InfoBar.jsx:
--------------------------------------------------------------------------------
1 | import "./styles/InfoBar.css";
2 |
3 | import { useEffect, useRef, useState } from "react";
4 |
5 | function InfoBar({
6 | hidden,
7 | theme,
8 | musicData,
9 | playerActive,
10 | onPlayMusic,
11 | onStopMusic,
12 | onSetTheme,
13 | constants,
14 | messages
15 | }) {
16 | const PLAYER_ICON_CLASSNAME = "icon icon-music-player";
17 | const PLAYER_PAUSED_CLASSNAME = " paused";
18 | const PLAYER_PAUSED = {
19 | label: messages.PAUSED_MUSIC_ICON,
20 | className: PLAYER_ICON_CLASSNAME + PLAYER_PAUSED_CLASSNAME
21 | };
22 | const PLAYER_ACTIVE = {
23 | label: messages.PLAYING_MUSIC_ICON,
24 | className: PLAYER_ICON_CLASSNAME
25 | };
26 |
27 | const [iconPlayer, setIconPlayer] = useState(PLAYER_PAUSED);
28 |
29 | function handleChangeAccentColor(accentColor) {
30 | onSetTheme({ accentColor });
31 | }
32 |
33 | function handleChangeIconPlayer(paused) {
34 | const iconData = paused ? PLAYER_PAUSED : PLAYER_ACTIVE;
35 | setIconPlayer(iconData);
36 | }
37 |
38 | if (hidden) {
39 | return;
40 | } else {
41 | return (
42 |
112 | );
113 | }
114 | }
115 |
116 | function AccentColorPickerButton({
117 | accentColor,
118 | onSetAccentColor,
119 | children,
120 | messages
121 | }) {
122 | const colorInputRef = useRef(null);
123 |
124 | function handleChange() {
125 | onSetAccentColor(colorInputRef.current.value);
126 | }
127 |
128 | useEffect(() => {
129 | if (accentColor) {
130 | colorInputRef.current.value = accentColor;
131 | }
132 | }, [accentColor]);
133 | return (
134 | <>
135 | {children}
136 |
143 | >
144 | );
145 | }
146 |
147 | function MusicPlayerButton({
148 | playerActive,
149 | iconPlayer,
150 | onPlayMusic,
151 | onStopMusic,
152 | onSetIconPlayer
153 | }) {
154 | function handlePlayButtonClick() {
155 | if (playerActive) {
156 | onStopMusic();
157 | onSetIconPlayer(true);
158 | } else {
159 | onPlayMusic();
160 | onSetIconPlayer();
161 | }
162 | }
163 |
164 | return (
165 | <>
166 |
171 | {iconPlayer.label}
172 |
173 | >
174 | );
175 | }
176 |
177 | function MusicVisualizer({
178 | theme,
179 | musicData,
180 | playerActive,
181 | constants
182 | }) {
183 | const CANVAS_WIDTH = 128;
184 | const CANVAS_HEIGTH = 64;
185 | const CANVAS_BLOCK_OFFSET = CANVAS_HEIGTH / 8;
186 | const MAX_FFT_VALUE = 256;
187 |
188 | const [barWidth, setBarWidth] = useState(0);
189 | const canvasRef = useRef(null);
190 | const audioContextRef = useRef(null);
191 |
192 | function updateColor() {
193 | if (theme.accentColor) {
194 | const context = audioContextRef.current;
195 | const gradient = context.createLinearGradient(0, 0, 0, CANVAS_HEIGTH);
196 | gradient.addColorStop(0, theme.accentColor);
197 | gradient.addColorStop(0.7, theme.accentColor);
198 | gradient.addColorStop(1, "transparent");
199 | context.fillStyle = gradient;
200 | }
201 | }
202 |
203 | function updateBarWidth() {
204 | if (theme.skin) {
205 | setBarWidth(CANVAS_WIDTH / (constants.FFT_RESOLUTIONS[theme.skin] / 2));
206 | }
207 | }
208 |
209 | useEffect(updateBarWidth, [theme.skin]);
210 | useEffect(updateColor, [theme.accentColor]);
211 | useEffect(() => {
212 | if (canvasRef.current) {
213 | if (!audioContextRef.current) {
214 | audioContextRef.current = canvasRef.current.getContext("2d");
215 | }
216 | const context = audioContextRef.current;
217 | context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGTH);
218 | if (playerActive) {
219 | musicData.frequencyData.forEach((byteTimeDomain, index) => {
220 | const barHeight =
221 | (CANVAS_BLOCK_OFFSET - byteTimeDomain) /
222 | (MAX_FFT_VALUE / CANVAS_HEIGTH);
223 | context.fillRect(index * barWidth, CANVAS_HEIGTH, barWidth, barHeight);
224 | context.fillRect(
225 | CANVAS_WIDTH - index * barWidth - barWidth,
226 | CANVAS_HEIGTH,
227 | barWidth,
228 | barHeight
229 | );
230 | });
231 | }
232 | }
233 | }, [playerActive, musicData]);
234 | return (
235 |
240 | );
241 | }
242 |
243 | export default InfoBar;
244 |
--------------------------------------------------------------------------------
/src/zip-manager/components/NavigationBar.jsx:
--------------------------------------------------------------------------------
1 | import "./styles/NavigationBar.css";
2 |
3 | import History from "./History.jsx";
4 | import Breadcrumb from "./Breadcrumb.jsx";
5 |
6 | function NavigationBar({
7 | hidden,
8 | selectedFolder,
9 | ancestorFolders,
10 | disabledBackButton,
11 | disabledForwardButton,
12 | clickedButtonName,
13 | onNavigateBack,
14 | onNavigateForward,
15 | onGoIntoFolder,
16 | onClickedButton,
17 | constants,
18 | messages
19 | }) {
20 | if (hidden) {
21 | return;
22 | } else {
23 | return (
24 |
29 |
39 |
46 |
47 | );
48 | }
49 | }
50 |
51 | export default NavigationBar;
52 |
--------------------------------------------------------------------------------
/src/zip-manager/components/TopButtonBar.jsx:
--------------------------------------------------------------------------------
1 | import "./styles/TopButtonBar.css";
2 |
3 | import {
4 | AddFilesButton,
5 | CreateFolderButton,
6 | ImportZipButton,
7 | ExportZipButton,
8 | ResetButton,
9 | OptionsButton
10 | } from "./Buttons.jsx";
11 |
12 | function TopButtonBar({
13 | disabledExportZipButton,
14 | disabledResetButton,
15 | clickedButtonName,
16 | onCreateFolder,
17 | onImportZipFile,
18 | onExportZip,
19 | onReset,
20 | onOpenOptions,
21 | onShowImportZipFilePicker,
22 | onShowAddFilesPicker,
23 | onClickedButton,
24 | constants,
25 | messages
26 | }) {
27 | function handleDragOver(event) {
28 | event.preventDefault();
29 | }
30 |
31 | function handleDrop(event) {
32 | const file = event.dataTransfer?.files[0];
33 | if (file) {
34 | event.preventDefault();
35 | onImportZipFile(file);
36 | }
37 | }
38 |
39 | return (
40 |
47 |
63 |
64 |
71 |
79 |
80 |
81 |
86 |
87 |
88 |
89 | );
90 | }
91 |
92 | export default TopButtonBar;
93 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/ChooseActionDialog.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from "react";
2 |
3 | function ChooseActionDialog({
4 | data,
5 | onImportZipFile,
6 | onAddFiles,
7 | onClose,
8 | messages
9 | }) {
10 | const dialogRef = useRef(null);
11 |
12 | function handleClose() {
13 | onClose();
14 | }
15 |
16 | function handleImportZipClick() {
17 | onImportZipFile(data?.files[0]);
18 | }
19 |
20 | function handleAddFileClick() {
21 | onAddFiles(data?.files);
22 | }
23 |
24 | function handleReset() {
25 | dialogRef.current.close();
26 | }
27 |
28 | useEffect(() => {
29 | if (!dialogRef.current.open && data) {
30 | dialogRef.current.showModal();
31 | }
32 | }, [data]);
33 | return (
34 |
58 | );
59 | }
60 |
61 | export default ChooseActionDialog;
62 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/CreateFolderDialog.jsx:
--------------------------------------------------------------------------------
1 | import Dialog from "./Dialog.jsx";
2 |
3 | import { useState } from "react";
4 |
5 | function CreateFolderDialog({ data, onCreateFolder, onClose, messages }) {
6 | const [folderName, setFolderName] = useState("");
7 |
8 | function handleChangeFilename(event) {
9 | setFolderName(event.target.value);
10 | }
11 |
12 | function handleSubmit() {
13 | onCreateFolder({ folderName });
14 | }
15 |
16 | function handleClose() {
17 | setFolderName("");
18 | onClose();
19 | }
20 |
21 | return (
22 |
41 | );
42 | }
43 |
44 | export default CreateFolderDialog;
45 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/DeleteEntriesDialog.jsx:
--------------------------------------------------------------------------------
1 | import Dialog from "./Dialog.jsx";
2 |
3 | function DeleteEntriesDialog({ data, onDeleteEntries, onClose, messages }) {
4 | return (
5 |
15 | );
16 | }
17 |
18 | export default DeleteEntriesDialog;
19 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/Dialog.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from "react";
2 |
3 | function Dialog({
4 | className,
5 | data,
6 | title,
7 | resetLabel,
8 | cancelLabel,
9 | submitLabel,
10 | children,
11 | onOpen,
12 | onSubmit,
13 | onReset,
14 | onClose
15 | }) {
16 | const dialogRef = useRef(null);
17 |
18 | function handleButtonReset(event) {
19 | event.preventDefault();
20 | onReset();
21 | }
22 |
23 | function handleReset() {
24 | dialogRef.current.close();
25 | }
26 |
27 | useEffect(() => {
28 | if (!dialogRef.current.open && data) {
29 | if (onOpen) {
30 | onOpen();
31 | }
32 | dialogRef.current.showModal();
33 | }
34 | }, [data]);
35 | return (
36 |
55 | );
56 | }
57 |
58 | export default Dialog;
59 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/ErrorMessageDialog.jsx:
--------------------------------------------------------------------------------
1 | import Dialog from "./Dialog.jsx";
2 |
3 | function ErrorMessageDialog({ data, onClose, messages }) {
4 | return (
5 |
13 | );
14 | }
15 |
16 | export default ErrorMessageDialog;
17 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/ExportZipDialog.jsx:
--------------------------------------------------------------------------------
1 | import Dialog from "./Dialog.jsx";
2 |
3 | import { useEffect, useRef, useState } from "react";
4 |
5 | function ExportZipDialog({
6 | data,
7 | hiddenPassword,
8 | onExportZip,
9 | onClose,
10 | messages
11 | }) {
12 | const filenameInputRef = useRef(null);
13 | const filenameTextSelected = useRef(false);
14 | const [filename, setFilename] = useState("");
15 | const [password, setPassword] = useState("");
16 | const filenameHidden = data?.filenameHidden;
17 |
18 | function handleChangeFilename(event) {
19 | setFilename(event.target.value);
20 | }
21 |
22 | function handleChangePassword(event) {
23 | setPassword(event.target.value);
24 | }
25 |
26 | function onOpen() {
27 | const { filename, password } = data;
28 | setFilename(filename);
29 | setPassword(password);
30 | }
31 |
32 | function handleSubmit() {
33 | onExportZip({ filename, password });
34 | }
35 |
36 | function handleClose() {
37 | filenameTextSelected.current = false;
38 | onClose();
39 | }
40 |
41 | useEffect(() => {
42 | if (
43 | !filenameTextSelected.current &&
44 | filename &&
45 | filenameInputRef &&
46 | filenameInputRef.current
47 | ) {
48 | filenameTextSelected.current = true;
49 | let selectionEnd = filename.lastIndexOf(".");
50 | filenameInputRef.current.setSelectionRange(
51 | 0,
52 | selectionEnd === -1 ? filename.length : selectionEnd
53 | );
54 | }
55 | }, [filename]);
56 | return (
57 |
91 | );
92 | }
93 |
94 | export default ExportZipDialog;
95 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/ExtractDialog.jsx:
--------------------------------------------------------------------------------
1 | import Dialog from "./Dialog.jsx";
2 |
3 | import { useEffect, useRef, useState } from "react";
4 |
5 | function ExtractDialog({ data, onExtract, onClose, messages }) {
6 | const filenameInputRef = useRef(null);
7 | const filenameTextSelected = useRef(false);
8 | const [filename, setFilename] = useState("");
9 |
10 | function handleChangeFilename(event) {
11 | setFilename(event.target.value);
12 | }
13 |
14 | function onOpen() {
15 | setFilename(data?.filename);
16 | }
17 |
18 | function handleSubmit() {
19 | onExtract({ filename, entries: data?.entries });
20 | }
21 |
22 | function handleClose() {
23 | setFilename("");
24 | filenameTextSelected.current = false;
25 | onClose();
26 | }
27 |
28 | useEffect(() => {
29 | if (!filenameTextSelected.current && filename) {
30 | filenameTextSelected.current = true;
31 | filenameInputRef.current.select();
32 | }
33 | }, [filename]);
34 | return (
35 |
56 | );
57 | }
58 |
59 | export default ExtractDialog;
60 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/ImportPasswordDialog.jsx:
--------------------------------------------------------------------------------
1 | import Dialog from "./Dialog.jsx";
2 |
3 | import { useState } from "react";
4 |
5 | function PasswordDialog({ data, onClose, messages }) {
6 | const [password, setPassword] = useState("");
7 |
8 | function handleChangePassword(event) {
9 | setPassword(event.target.value);
10 | }
11 |
12 | function handleClose() {
13 | setPassword("");
14 | data.onSetImportPassword({ password });
15 | onClose();
16 | }
17 |
18 | return (
19 |
37 | );
38 | }
39 |
40 | export default PasswordDialog;
41 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/OptionsDialog.jsx:
--------------------------------------------------------------------------------
1 | import "./styles/OptionsDialog.css";
2 | import Dialog from "./Dialog.jsx";
3 |
4 | import { useEffect, useRef, useState } from "react";
5 | import { constants } from "../../business";
6 |
7 | function OptionsDialog({
8 | data,
9 | onSetOptions,
10 | onResetOptions,
11 | onClose,
12 | messages
13 | }) {
14 | const [zoomFactor, setZoomFactor] = useState("");
15 | const [hideNavigationBar, setHideNavigationBar] = useState(false);
16 | const [hideDownloadManager, setHideDownloadManager] = useState(false);
17 | const [hideInfobar, setHideInfobar] = useState(false);
18 | const [skin, setSkin] = useState("default");
19 | const [defaultExportPassword, setDefaultExportPassword] = useState("");
20 | const [promptForExportPassword, setPromptForExportPassword] = useState(false);
21 | const [keepOrder, setKeepOrder] = useState(false);
22 | const [checkSignature, setCheckSignature] = useState(false);
23 | const [bufferedWrite, setBufferedWrite] = useState(false);
24 | const [maxWorkers, setMaxWorkers] = useState("0");
25 | const [chunkSize, setChunkSize] = useState("0");
26 | const defaultPasswordInputRef = useRef(null);
27 |
28 | function handleChangeZoomFactor(event) {
29 | setZoomFactor(event.target.value);
30 | }
31 |
32 | function handleChangeHideNavigationBar(event) {
33 | setHideNavigationBar(event.target.checked);
34 | }
35 |
36 | function handleChangeHideDownloadManager(event) {
37 | setHideDownloadManager(event.target.checked);
38 | }
39 |
40 | function handleChangeHideInfobar(event) {
41 | setHideInfobar(event.target.checked);
42 | }
43 |
44 | function handleChangeSkin(event) {
45 | setSkin(event.target.value);
46 | }
47 |
48 | function handleChangePromptForExportPassword(event) {
49 | setPromptForExportPassword(event.target.checked);
50 | }
51 |
52 | function handleFocusDefaultExportPassword() {
53 | defaultPasswordInputRef.current.select();
54 | }
55 |
56 | function handleChangeDefaultExportPassword(event) {
57 | setDefaultExportPassword(event.target.value);
58 | }
59 |
60 | function handleChangeKeepOrder(event) {
61 | setKeepOrder(event.target.checked);
62 | }
63 |
64 | function handleChangeBufferedWrite(event) {
65 | setBufferedWrite(event.target.checked);
66 | }
67 |
68 | function handleChangeCheckSignature(event) {
69 | setCheckSignature(event.target.checked);
70 | }
71 |
72 | function handleChangeMaxWorkers(event) {
73 | setMaxWorkers(event.target.value);
74 | }
75 |
76 | function handleChangeChunkSize(event) {
77 | setChunkSize(event.target.value);
78 | }
79 |
80 | function handleSubmit() {
81 | onSetOptions({
82 | zoomFactor: Number(zoomFactor),
83 | hideNavigationBar,
84 | hideDownloadManager,
85 | hideInfobar,
86 | skin,
87 | promptForExportPassword,
88 | defaultExportPassword,
89 | keepOrder,
90 | checkSignature,
91 | bufferedWrite,
92 | maxWorkers: Number(maxWorkers),
93 | chunkSize: Number(chunkSize) * 1024
94 | });
95 | }
96 |
97 | function updateData() {
98 | if (data) {
99 | const {
100 | zoomFactor,
101 | hideNavigationBar,
102 | hideDownloadManager,
103 | hideInfobar,
104 | skin,
105 | promptForExportPassword,
106 | defaultExportPassword,
107 | keepOrder,
108 | checkSignature,
109 | bufferedWrite,
110 | maxWorkers,
111 | chunkSize
112 | } = data;
113 | setZoomFactor(zoomFactor);
114 | setHideNavigationBar(hideNavigationBar);
115 | setHideDownloadManager(hideDownloadManager);
116 | setHideInfobar(hideInfobar);
117 | setSkin(skin);
118 | setPromptForExportPassword(promptForExportPassword);
119 | setDefaultExportPassword(defaultExportPassword);
120 | setKeepOrder(keepOrder);
121 | setCheckSignature(checkSignature);
122 | setBufferedWrite(bufferedWrite);
123 | setMaxWorkers(maxWorkers);
124 | setChunkSize(chunkSize / 1024);
125 | }
126 | }
127 |
128 | useEffect(updateData, [data]);
129 | return (
130 |
254 | );
255 | }
256 |
257 | export default OptionsDialog;
258 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/RenameDialog.jsx:
--------------------------------------------------------------------------------
1 | import Dialog from "./Dialog.jsx";
2 |
3 | import { useEffect, useRef, useState } from "react";
4 |
5 | function RenameDialog({ data, onRename, onClose, messages }) {
6 | const filenameInputRef = useRef(null);
7 | const filenameTextSelected = useRef(false);
8 | const [filename, setFilename] = useState("");
9 |
10 | function handleChangeFilename(event) {
11 | setFilename(event.target.value);
12 | }
13 |
14 | function onOpen() {
15 | setFilename(data?.filename);
16 | }
17 |
18 | function handleSubmit() {
19 | onRename({ filename });
20 | }
21 |
22 | function handleClose() {
23 | setFilename("");
24 | filenameTextSelected.current = false;
25 | onClose();
26 | }
27 |
28 | useEffect(() => {
29 | if (!filenameTextSelected.current && filename) {
30 | filenameTextSelected.current = true;
31 | filenameInputRef.current.select();
32 | }
33 | }, [filename]);
34 | return (
35 |
56 | );
57 | }
58 |
59 | export default RenameDialog;
60 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/ResetDialog.jsx:
--------------------------------------------------------------------------------
1 | import Dialog from "./Dialog.jsx";
2 |
3 | function ResetDialog({ data, onReset, onClose, messages }) {
4 | return (
5 |
15 | );
16 | }
17 |
18 | export default ResetDialog;
19 |
--------------------------------------------------------------------------------
/src/zip-manager/components/dialogs/styles/OptionsDialog.css:
--------------------------------------------------------------------------------
1 | .options-dialog form p {
2 | padding-inline: var(--small-gap-inline-size);
3 | padding-block-start: var(--large-gap-block-size);
4 | }
5 |
6 | .options-dialog label {
7 | flex-direction: row;
8 | align-items: center;
9 | justify-content: space-between;
10 | min-block-size: 1.5em;
11 | }
12 |
13 | .options-dialog label span {
14 | flex: 1;
15 | }
16 |
17 | .options-dialog input,
18 | .options-dialog select {
19 | margin-inline-start: var(--gap-inline-size);
20 | }
21 |
22 | .options-dialog input[disabled] {
23 | color: var(--disabled-button-color);
24 | }
25 |
26 | .options-dialog input[type="checkbox"] {
27 | inline-size: 2ch;
28 | block-size: 1em;
29 | accent-color: var(--accent-color);
30 | margin-inline: calc(var(--outline-width));
31 | }
32 |
33 | .options-dialog input[type="password"],
34 | .options-dialog input[type="number"],
35 | .options-dialog select {
36 | inline-size: min(10ch, 100%);
37 | }
--------------------------------------------------------------------------------
/src/zip-manager/components/index.jsx:
--------------------------------------------------------------------------------
1 | import TopButtonBar from "./TopButtonBar.jsx";
2 | import NavigationBar from "./NavigationBar.jsx";
3 | import Entries from "./Entries.jsx";
4 | import BottomButtonBar from "./BottomButtonBar.jsx";
5 | import Downloads from "./Downloads.jsx";
6 | import InfoBar from "./InfoBar.jsx";
7 | import ExportZipDialog from "./dialogs/ExportZipDialog.jsx";
8 | import ExtractDialog from "./dialogs/ExtractDialog.jsx";
9 | import RenameDialog from "./dialogs/RenameDialog.jsx";
10 | import CreateFolderDialog from "./dialogs/CreateFolderDialog.jsx";
11 | import ResetDialog from "./dialogs/ResetDialog.jsx";
12 | import DeleteEntriesDialog from "./dialogs/DeleteEntriesDialog.jsx";
13 | import ErrorMessageDialog from "./dialogs/ErrorMessageDialog.jsx";
14 | import ImportPasswordDialog from "./dialogs/ImportPasswordDialog.jsx";
15 | import OptionsDialog from "./dialogs/OptionsDialog.jsx";
16 | import ChooseActionDialog from "./dialogs/ChooseActionDialog.jsx";
17 |
18 | export {
19 | TopButtonBar,
20 | NavigationBar,
21 | Entries,
22 | BottomButtonBar,
23 | Downloads,
24 | InfoBar,
25 | ExportZipDialog,
26 | ExtractDialog,
27 | RenameDialog,
28 | CreateFolderDialog,
29 | ResetDialog,
30 | DeleteEntriesDialog,
31 | ErrorMessageDialog,
32 | ImportPasswordDialog,
33 | OptionsDialog,
34 | ChooseActionDialog
35 | };
36 |
--------------------------------------------------------------------------------
/src/zip-manager/components/styles/BottomButtonBar.css:
--------------------------------------------------------------------------------
1 | .button-bar-bottom {
2 | justify-content: flex-end;
3 | touch-action: none;
4 | }
--------------------------------------------------------------------------------
/src/zip-manager/components/styles/Downloads.css:
--------------------------------------------------------------------------------
1 | .downloads {
2 | min-block-size: 5dvh;
3 | overflow-block: auto;
4 | flex: 1;
5 | }
6 |
7 | .downloads ol,
8 | .downloads li {
9 | flex-direction: column;
10 | }
11 |
12 | .downloads ol {
13 | row-gap: var(--gap-block-size);
14 | }
15 |
16 | .downloads li {
17 | row-gap: var(--small-gap-block-size);
18 | align-items: normal;
19 | }
20 |
21 | .downloads .download-entry {
22 | display: flex;
23 | }
24 |
25 | .downloads .download-entry-name {
26 | flex: 1;
27 | }
28 |
29 | .downloads li progress {
30 | inline-size: 100%;
31 | block-size: 1em;
32 | accent-color: var(--accent-color);
33 | }
--------------------------------------------------------------------------------
/src/zip-manager/components/styles/Entries.css:
--------------------------------------------------------------------------------
1 | .entries {
2 | block-size: 55dvh;
3 | min-block-size: 10dvh;
4 | resize: vertical;
5 | box-sizing: border-box;
6 | padding-block-start: 0;
7 | margin-block-start: var(--gap-block-size);
8 | }
9 |
10 | .entries ol {
11 | flex-direction: column;
12 | row-gap: var(--list-item-gap-block-size);
13 | }
14 |
15 | .entries li {
16 | padding-block: var(--list-item-padding-block-size);
17 | padding-inline: var(--list-item-padding-inline-size);
18 | outline: none;
19 | column-gap: var(--gap-inline-size);
20 | cursor: pointer;
21 | }
22 |
23 | @supports (grid-template-columns: subgrid) {
24 | .entries ol {
25 | display: grid;
26 | grid-template-columns: auto min-content min-content;
27 | grid-template-rows: repeat(auto);
28 | }
29 |
30 | .entries li {
31 | display: grid;
32 | grid-template-columns: subgrid;
33 | grid-column: 1 / 4;
34 | }
35 | }
36 |
37 | .entries .entry-select {
38 | accent-color: var(--dark-accent-color);
39 | margin: 0;
40 | padding: 0;
41 | max-block-size: 1em;
42 | margin-inline-start: var(--small-gap-inline-size);
43 | }
44 |
45 | .entries .entry-name {
46 | display: flex;
47 | user-select: none;
48 | overflow-x: hidden;
49 | overflow-inline: hidden;
50 | column-gap: var(--small-gap-inline-size);
51 | flex: 1;
52 | -webkit-tap-highlight-color: transparent;
53 | }
54 |
55 | .entries .entry-size {
56 | text-align: right;
57 | white-space: nowrap;
58 | }
59 |
60 | .entries .entry-highlighted {
61 | background-color: var(--accent-color);
62 | color: var(--highlighted-text-color);
63 | }
64 |
65 | .entries .entry-highlighted ::selection {
66 | background-color: var(--text-color);
67 | color: var(--bg-color);
68 | }
69 |
70 | .entries .directory .entry-name::after {
71 | content: var(--folder-separator);
72 | }
73 |
74 | @media (hover: hover) and (pointer: fine) {
75 | .entries ol {
76 | --no-entries-outline-width: 1px;
77 | --no-entries-outline-width-negative: calc(var(--no-entries-outline-width) * -1);
78 | }
79 |
80 | .entries ol:empty {
81 | block-size: 100%;
82 | }
83 |
84 | .entries ol:empty::after {
85 | display: flex;
86 | block-size: 100%;
87 | justify-content: center;
88 | align-items: center;
89 | text-align: center;
90 | font-weight: bold;
91 | font-size: 2em;
92 | line-height: 1.5em;
93 | text-shadow: var(--no-entries-outline-width-negative) var(--no-entries-outline-width-negative) 0 var(--accent-color),
94 | var(--no-entries-outline-width-negative) 0 0 var(--accent-color),
95 | var(--no-entries-outline-width-negative) var(--no-entries-outline-width) 0 var(--accent-color),
96 | 0 var(--no-entries-outline-width-negative) 0 var(--accent-color),
97 | 0 0 0 var(--accent-color),
98 | 0 var(--no-entries-outline-width) 0 var(--accent-color),
99 | var(--no-entries-outline-width) var(--no-entries-outline-width-negative) 0 var(--accent-color),
100 | var(--no-entries-outline-width) 0 0 var(--accent-color),
101 | var(--no-entries-outline-width) var(--no-entries-outline-width) 0 var(--accent-color);
102 | color: var(--bg-color);
103 | opacity: 0.5;
104 | }
105 |
106 | .entries.dragging-items ol:empty::after {
107 | color: var(--accent-color);
108 | text-shadow: none;
109 | }
110 |
111 | .entries ol:empty::after {
112 | content: var(--message-drag-and-drop-entries);
113 | }
114 | }
--------------------------------------------------------------------------------
/src/zip-manager/components/styles/InfoBar.css:
--------------------------------------------------------------------------------
1 | .info-bar {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | padding-block: var(--gap-block-size);
6 | margin-inline: var(--gap-inline-size);
7 | inline-size: 100%;
8 | overflow: hidden;
9 | }
10 |
11 | .info-bar .source-link {
12 | display: inline;
13 | color: var(--basic-text-color);
14 | text-align: center;
15 | position: relative;
16 | overflow: visible;
17 | }
18 |
19 | .info-bar .source-link * {
20 | font-size: 0.8rem;
21 | }
22 |
23 | .info-bar .source-link a {
24 | text-decoration: none;
25 | }
26 |
27 | .info-bar .source-link a svg {
28 | width: 1em;
29 | height: 1em;
30 | margin-bottom: -2px;
31 | }
32 |
33 | .info-bar .player-active :not(canvas) {
34 | opacity: 0.5;
35 | color: var(--basic-text-color);
36 | transition: all 0.2s;
37 | }
38 |
39 | .info-bar .player-active .label {
40 | opacity: 0;
41 | pointer-events: none;
42 | }
43 |
44 | .info-bar:hover .source-link.player-active canvas {
45 | opacity: 0.2;
46 | }
47 |
48 | .info-bar:hover .player-active * {
49 | opacity: 1;
50 | pointer-events: inherit;
51 | }
52 |
53 | .info-bar:hover .source-link.player-active .icon {
54 | color: var(--accent-color);
55 | opacity: 1;
56 | }
57 |
58 | .info-bar .icon {
59 | display: inline-block;
60 | color: var(--accent-color);
61 | inline-size: 1.75ch;
62 | user-select: none;
63 | }
64 |
65 | .info-bar .icon-music-player {
66 | inline-size: 2.25ch;
67 | }
68 |
69 | .info-bar input[type="color"],
70 | .info-bar .icon-music-player {
71 | cursor: pointer;
72 | outline-width: 0;
73 | }
74 |
75 | .icon-music-player.paused {
76 | color: inherit;
77 | }
78 |
79 | .info-bar .icon:hover {
80 | filter: brightness(var(--brightness-hover));
81 | }
82 |
83 | .info-bar input[type="color"] {
84 | position: relative;
85 | left: -1.75ch;
86 | margin-right: -1.8ch;
87 | inline-size: 1.8ch;
88 | block-size: 1.25em;
89 | padding: 0;
90 | filter: opacity(0);
91 | }
92 |
93 | .info-bar canvas {
94 | position: absolute;
95 | bottom: calc(-1 * var(--gap-block-size));
96 | left: -7.5%;
97 | z-index: -1;
98 | inline-size: 115%;
99 | block-size: calc(100% + var(--gap-block-size));
100 | opacity: 0.4;
101 | }
--------------------------------------------------------------------------------
/src/zip-manager/components/styles/NavigationBar.css:
--------------------------------------------------------------------------------
1 | .navigation-bar,
2 | .history-buttons,
3 | .breadcrumb {
4 | display: flex;
5 | }
6 |
7 | .navigation-bar {
8 | column-gap: var(--gap-inline-size);
9 | }
10 |
11 | .history-buttons,
12 | .breadcrumb li {
13 | column-gap: var(--small-gap-inline-size);
14 | }
15 |
16 | .history-buttons button {
17 | font-family: monospace;
18 | align-self: start;
19 | padding-block: var(--small-button-padding-block-size);
20 | padding-inline: var(--small-button-padding-inline-size);
21 | }
22 |
23 | .history-buttons button:not([disabled]),
24 | .breadcrumb .breadcrumb-item-active {
25 | cursor: pointer;
26 | }
27 |
28 | .breadcrumb,
29 | .breadcrumb ol,
30 | .breadcrumb li,
31 | .breadcrumb .breadcrumb-item {
32 | overflow-x: hidden;
33 | overflow-inline: hidden;
34 | }
35 |
36 | .navigation-bar,
37 | .breadcrumb ol {
38 | flex-wrap: wrap;
39 | column-gap: calc(var(--small-gap-inline-size) - var(--outline-width));
40 | row-gap: var(--small-gap-block-size);
41 | }
42 |
43 | .breadcrumb li::after {
44 | content: var(--folder-separator);
45 | }
46 |
47 | .breadcrumb .breadcrumb-item {
48 | text-decoration: underline dotted transparent var(--large-border-width);
49 | text-underline-offset: 0.25em;
50 | white-space: nowrap;
51 | text-overflow: ellipsis;
52 | -webkit-tap-highlight-color: transparent;
53 | margin: var(--outline-width);
54 | }
55 |
56 | .breadcrumb .breadcrumb-item:focus-visible {
57 | text-decoration: none;
58 | }
59 |
60 | .breadcrumb li:last-of-type .breadcrumb-item {
61 | font-weight: var(--font-weight-bolder);
62 | }
63 |
64 | .breadcrumb .breadcrumb-item-active {
65 | text-decoration-color: var(--accent-color);
66 | }
67 |
68 | .breadcrumb .breadcrumb-item-active:hover {
69 | filter: brightness(var(--brightness-hover));
70 | }
--------------------------------------------------------------------------------
/src/zip-manager/components/styles/TopButtonBar.css:
--------------------------------------------------------------------------------
1 | .button-bar-top {
2 | justify-content: flex-start;
3 | }
4 |
5 | .button-bar-top .button-group:last-of-type {
6 | flex: 1;
7 | justify-content: end;
8 | }
--------------------------------------------------------------------------------
/src/zip-manager/hooks/hooks.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | function getHooks({ keyboardService, windowService }) {
4 | function useKeyUp(handleKeyUp) {
5 | useEffect(registerKeyUpHandler);
6 |
7 | function registerKeyUpHandler() {
8 | keyboardService.addKeyUpListener(handleKeyUp);
9 | return () => keyboardService.removeKeyUpListener(handleKeyUp);
10 | }
11 | }
12 |
13 | function useKeyDown(handleKeyDown) {
14 | useEffect(registerKeyDownHandler);
15 |
16 | function registerKeyDownHandler() {
17 | keyboardService.addKeyDownListener(handleKeyDown);
18 | return () => keyboardService.removeKeyDownListener(handleKeyDown);
19 | }
20 | }
21 |
22 | function usePageUnload(handlePageUnload) {
23 | useEffect(registerPageUnloadHandler);
24 |
25 | function registerPageUnloadHandler() {
26 | windowService.addUnloadListener(handlePageUnload);
27 | return () => windowService.removeUnloadListener(handlePageUnload);
28 | }
29 | }
30 |
31 | return { useKeyUp, useKeyDown, usePageUnload };
32 | }
33 |
34 | export { getHooks };
35 |
--------------------------------------------------------------------------------
/src/zip-manager/messages/de-DE.js:
--------------------------------------------------------------------------------
1 | const PARENT_FOLDER_LABEL = "..";
2 | const ROOT_FOLDER_LABEL = "";
3 | const ROOT_ZIP_FILENAME = "Download.zip";
4 | const KEYS_SEPARATOR_LABEL = ", ";
5 | const PARENT_FOLDER_TOOLTIP = "Übergeordneter Ordner";
6 |
7 | const SHORTCUT_LABEL = "Verknüpfung: ";
8 | const CTRL_KEY_LABEL = "⌘/ctrl-";
9 | const ALT_KEY_LABEL = "alt-";
10 | const SPACE_KEY_LABEL = "Leertaste";
11 | const ARROW_LEFT_KEY_LABEL = "links";
12 | const ARROW_RIGHT_KEY_LABEL = "rechts";
13 | const SIZE_LABEL = "Größe:";
14 | const UNCOMPRESSED_SIZE_LABEL = "Unkomprimierte Größe:";
15 | const COMPRESSED_SIZE_LABEL = "Komprimierte Größe:";
16 | const LAST_MOD_DATE_LABEL = "Letzte Änderung:";
17 |
18 | const COPY_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "c";
19 | const CUT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "x";
20 | const PASTE_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "v";
21 | const EXTRACT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "Enter";
22 | const HIGHLIGHT_ALL_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "a";
23 | const RENAME_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "r";
24 | const DELETE_BUTTON_TOOLTIP =
25 | SHORTCUT_LABEL + ["Rücktaste", "Entf"].join(KEYS_SEPARATOR_LABEL);
26 | const CREATE_FOLDER_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "d";
27 | const ADD_FILES_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "f";
28 | const IMPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "i";
29 | const EXPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "e";
30 | const BACK_BUTTON_TOOLTIP =
31 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_LEFT_KEY_LABEL;
32 | const FORWARD_BUTTON_TOOLTIP =
33 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_RIGHT_KEY_LABEL;
34 |
35 | const CREATE_FOLDER_BUTTON_LABEL = "Verzeichnis erstellen";
36 | const ADD_FILES_BUTTON_LABEL = "Dateien hinzufügen";
37 | const IMPORT_ZIP_BUTTON_LABEL = "Zip importieren";
38 | const EXPORT_ZIP_BUTTON_LABEL = "Zip exportieren";
39 | const RESET_BUTTON_LABEL = "Zurücksetzen";
40 | const OPTIONS_BUTTON_LABEL = "Optionen";
41 | const BACK_BUTTON_LABEL = "<";
42 | const FORWARD_BUTTON_LABEL = ">";
43 | const DOWNLOAD_BUTTON_LABEL = "↵";
44 | const ENTER_FOLDER_BUTTON_LABEL = "↓";
45 | const COPY_BUTTON_LABEL = "Kopieren";
46 | const CUT_BUTTON_LABEL = "Ausschneiden";
47 | const PASTE_BUTTON_LABEL = "Einfügen";
48 | const RESET_CLIPBOARD_BUTTON_LABEL = "Zwischenablage zurücksetzen";
49 | const EXTRACT_BUTTON_LABEL = "Extrahieren";
50 | const HIGHLIGHT_ALL_BUTTON_LABEL = "Alles auswählen";
51 | const RENAME_BUTTON_LABEL = "Umbenennen";
52 | const DELETE_BUTTON_LABEL = "Löschen";
53 | const ABORT_DOWNLOAD_BUTTON_LABEL = "✕";
54 | const DIALOG_RESET_BUTTON_LABEL = "Zurücksetzen";
55 | const DIALOG_CANCEL_BUTTON_LABEL = "Abbrechen";
56 | const DIALOG_OK_BUTTON_LABEL = "OK";
57 | const ERROR_TITLE = "Fehler";
58 |
59 | const EXPORT_ZIP_TITLE = "Zip-Datei exportieren";
60 | const EXPORT_ZIP_FILENAME_LABEL = "Dateiname:";
61 | const EXPORT_ZIP_PASSWORD_LABEL = "Passwort:";
62 | const EXPORT_ZIP_DIALOG_BUTTON_LABEL = "Exportieren";
63 | const EXTRACT_TITLE = "Datei extrahieren";
64 | const EXTRACT_FILENAME_LABEL = "Dateiname:";
65 | const EXTRACT_DIALOG_BUTTON_LABEL = "Extrahieren";
66 | const RENAME_TITLE = "Eintrag umbenennen";
67 | const RENAME_FILENAME_LABEL = "Neuer Eintragsname:";
68 | const RENAME_DIALOG_BUTTON_LABEL = "Umbenennen";
69 | const CREATE_FOLDER_TITLE = "Verzeichnis erstellen";
70 | const CREATE_FOLDER_NAME_LABEL = "Verzeichnisname:";
71 | const CREATE_FOLDER_DIALOG_BUTTON_LABEL = "Erstellen";
72 | const RESET_TITLE = "Dateisystem zurücksetzen";
73 | const RESET_MESSAGE = "Bitte bestätigen Sie das Zurücksetzen des Dateisystems.";
74 | const RESET_DIALOG_BUTTON_LABEL = "Zurücksetzen";
75 | const DELETE_ENTRIES_TITLE = "Einträge löschen";
76 | const DELETE_ENTRIES_MESSAGE =
77 | "Bitte bestätigen Sie das Löschen der markierten Einträge.";
78 | const DELETE_ENTRIES_DIALOG_BUTTON_LABEL = "Löschen";
79 | const ZIP_FILE_DESCRIPTION_LABEL = "Zip-Datei";
80 | const IMPORT_PASSWORD_TITLE = "Passwort eingeben";
81 | const IMPORT_PASSWORD_LABEL = "Passwort:";
82 | const OPTIONS_DIALOG_BUTTON_LABEL = "Speichern";
83 | const OPTIONS_TITLE = "Optionen";
84 | const OPTIONS_ZOOM_FACTOR_LABEL = "Zoomfaktor (%):";
85 | const OPTIONS_HIDE_NAVIGATION_BAR_LABEL = "Navigationsleiste ausblenden:";
86 | const OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL = "Download-Manager ausblenden:";
87 | const OPTIONS_HIDE_INFOBAR_LABEL = "Untere Leiste ausblenden:";
88 | const OPTIONS_SELECT_SKIN_LABEL = "Thema:";
89 | const OPTIONS_DEFAULT_SKIN_LABEL = "Standard";
90 | const OPTIONS_DOS_SKIN_LABEL = "DOS";
91 | const OPTIONS_EXPORT_ZIP_PASSWORD_LABEL = "Nach Passwort fragen:";
92 | const OPTIONS_DEFAULT_PASSWORD_LABEL = "Standardpasswort:";
93 | const OPTIONS_KEEP_ORDER_LABEL = "Einträge sortieren:";
94 | const OPTIONS_CHECK_SIGNATURE_LABEL = "Daten-Signatur prüfen:";
95 | const OPTIONS_BUFFERED_WRITE_LABEL = "Mehrere Kerne verwenden:";
96 | const OPTIONS_MAX_WORKERS_LABEL = "Anzahl der Kerne:";
97 | const OPTIONS_CHUNK_SIZE_LABEL = "Chunk-Größe (kB):";
98 | const CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL = "Datei hinzufügen";
99 | const CHOOSE_ACTION_TITLE = "Aktion auswählen";
100 | const CHOOSE_ACTION_LABEL =
101 | "Eine Zip-Datei wurde ausgewählt. Bitte wählen Sie die entsprechende Aktion.";
102 | const NO_ENTRIES_LABEL = "Dateien und Verzeichnisse hierher ziehen";
103 | const INFO_LABEL = [
104 | "Quellcode auf ",
105 | " GitHub ",
106 | " Mit ",
107 | "♡",
108 | " gemacht in ",
109 | "Rennes"
110 | ];
111 | const CITY_URL = "https://de.wikipedia.org/wiki/Rennes";
112 | const HIGHLIGHTED_ENTRIES_LABEL = "Befehle für markierte Einträge";
113 | const DOWNLOADS_LABEL = "Download-Manager";
114 | const ENTRIES_LABEL = "Verzeichniseinträge";
115 | const FOLDERS_LABEL = "Navigationsverlauf";
116 | const SELECTED_FOLDER_LABEL = "Befehle für ausgewähltes Verzeichnis";
117 | const GO_INTO_FOLDER_LABEL = "In Verzeichnis wechseln";
118 | const GO_BACK_LABEL = "Zurück";
119 | const GO_FORWARD_LABEL = "Vorwärts";
120 | const ACCENT_COLOR_LABEL = "Akzentfarbe";
121 | const PLAYING_MUSIC_ICON = "▶";
122 | const PAUSED_MUSIC_ICON = "II";
123 |
124 | export {
125 | ROOT_ZIP_FILENAME,
126 | SHORTCUT_LABEL,
127 | CTRL_KEY_LABEL,
128 | SPACE_KEY_LABEL,
129 | ARROW_LEFT_KEY_LABEL,
130 | ARROW_RIGHT_KEY_LABEL,
131 | PARENT_FOLDER_TOOLTIP,
132 | CREATE_FOLDER_BUTTON_TOOLTIP,
133 | ADD_FILES_BUTTON_TOOLTIP,
134 | IMPORT_ZIP_BUTTON_TOOLTIP,
135 | EXPORT_ZIP_BUTTON_TOOLTIP,
136 | BACK_BUTTON_TOOLTIP,
137 | FORWARD_BUTTON_TOOLTIP,
138 | COPY_BUTTON_TOOLTIP,
139 | CUT_BUTTON_TOOLTIP,
140 | PASTE_BUTTON_TOOLTIP,
141 | EXTRACT_BUTTON_TOOLTIP,
142 | HIGHLIGHT_ALL_BUTTON_TOOLTIP,
143 | RENAME_BUTTON_TOOLTIP,
144 | DELETE_BUTTON_TOOLTIP,
145 | ROOT_FOLDER_LABEL,
146 | PARENT_FOLDER_LABEL,
147 | COPY_BUTTON_LABEL,
148 | CUT_BUTTON_LABEL,
149 | PASTE_BUTTON_LABEL,
150 | RESET_CLIPBOARD_BUTTON_LABEL,
151 | EXTRACT_BUTTON_LABEL,
152 | HIGHLIGHT_ALL_BUTTON_LABEL,
153 | RENAME_BUTTON_LABEL,
154 | DELETE_BUTTON_LABEL,
155 | ABORT_DOWNLOAD_BUTTON_LABEL,
156 | DOWNLOAD_BUTTON_LABEL,
157 | ENTER_FOLDER_BUTTON_LABEL,
158 | BACK_BUTTON_LABEL,
159 | FORWARD_BUTTON_LABEL,
160 | CREATE_FOLDER_BUTTON_LABEL,
161 | ADD_FILES_BUTTON_LABEL,
162 | IMPORT_ZIP_BUTTON_LABEL,
163 | EXPORT_ZIP_BUTTON_LABEL,
164 | RESET_BUTTON_LABEL,
165 | OPTIONS_BUTTON_LABEL,
166 | KEYS_SEPARATOR_LABEL,
167 | ZIP_FILE_DESCRIPTION_LABEL,
168 | SIZE_LABEL,
169 | UNCOMPRESSED_SIZE_LABEL,
170 | COMPRESSED_SIZE_LABEL,
171 | LAST_MOD_DATE_LABEL,
172 | EXPORT_ZIP_TITLE,
173 | EXPORT_ZIP_FILENAME_LABEL,
174 | EXPORT_ZIP_PASSWORD_LABEL,
175 | DIALOG_OK_BUTTON_LABEL,
176 | DIALOG_CANCEL_BUTTON_LABEL,
177 | EXTRACT_TITLE,
178 | EXTRACT_FILENAME_LABEL,
179 | RENAME_TITLE,
180 | RENAME_FILENAME_LABEL,
181 | EXPORT_ZIP_DIALOG_BUTTON_LABEL,
182 | RENAME_DIALOG_BUTTON_LABEL,
183 | EXTRACT_DIALOG_BUTTON_LABEL,
184 | CREATE_FOLDER_TITLE,
185 | CREATE_FOLDER_NAME_LABEL,
186 | CREATE_FOLDER_DIALOG_BUTTON_LABEL,
187 | RESET_TITLE,
188 | RESET_MESSAGE,
189 | RESET_DIALOG_BUTTON_LABEL,
190 | DELETE_ENTRIES_TITLE,
191 | DELETE_ENTRIES_MESSAGE,
192 | DELETE_ENTRIES_DIALOG_BUTTON_LABEL,
193 | ERROR_TITLE,
194 | IMPORT_PASSWORD_TITLE,
195 | IMPORT_PASSWORD_LABEL,
196 | DIALOG_RESET_BUTTON_LABEL,
197 | OPTIONS_TITLE,
198 | OPTIONS_DIALOG_BUTTON_LABEL,
199 | OPTIONS_ZOOM_FACTOR_LABEL,
200 | OPTIONS_HIDE_NAVIGATION_BAR_LABEL,
201 | OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL,
202 | OPTIONS_HIDE_INFOBAR_LABEL,
203 | OPTIONS_DEFAULT_SKIN_LABEL,
204 | OPTIONS_DOS_SKIN_LABEL,
205 | OPTIONS_SELECT_SKIN_LABEL,
206 | OPTIONS_EXPORT_ZIP_PASSWORD_LABEL,
207 | OPTIONS_DEFAULT_PASSWORD_LABEL,
208 | OPTIONS_KEEP_ORDER_LABEL,
209 | OPTIONS_CHECK_SIGNATURE_LABEL,
210 | OPTIONS_BUFFERED_WRITE_LABEL,
211 | OPTIONS_MAX_WORKERS_LABEL,
212 | OPTIONS_CHUNK_SIZE_LABEL,
213 | CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL,
214 | CHOOSE_ACTION_TITLE,
215 | CHOOSE_ACTION_LABEL,
216 | NO_ENTRIES_LABEL,
217 | INFO_LABEL,
218 | CITY_URL,
219 | HIGHLIGHTED_ENTRIES_LABEL,
220 | DOWNLOADS_LABEL,
221 | ENTRIES_LABEL,
222 | FOLDERS_LABEL,
223 | SELECTED_FOLDER_LABEL,
224 | GO_INTO_FOLDER_LABEL,
225 | GO_BACK_LABEL,
226 | GO_FORWARD_LABEL,
227 | ACCENT_COLOR_LABEL,
228 | PLAYING_MUSIC_ICON,
229 | PAUSED_MUSIC_ICON
230 | };
231 |
--------------------------------------------------------------------------------
/src/zip-manager/messages/en-US.js:
--------------------------------------------------------------------------------
1 | const PARENT_FOLDER_LABEL = "..";
2 | const ROOT_FOLDER_LABEL = "";
3 | const ROOT_ZIP_FILENAME = "Download.zip";
4 | const KEYS_SEPARATOR_LABEL = ", ";
5 | const PARENT_FOLDER_TOOLTIP = "Parent directory";
6 |
7 | const SHORTCUT_LABEL = "Shortcut: ";
8 | const CTRL_KEY_LABEL = "⌘/ctrl-";
9 | const ALT_KEY_LABEL = "alt-";
10 | const SPACE_KEY_LABEL = "space";
11 | const ARROW_LEFT_KEY_LABEL = "left";
12 | const ARROW_RIGHT_KEY_LABEL = "right";
13 | const SIZE_LABEL = "Size:";
14 | const UNCOMPRESSED_SIZE_LABEL = "Uncompressed size:";
15 | const COMPRESSED_SIZE_LABEL = "Compressed size:";
16 | const LAST_MOD_DATE_LABEL = "Last mod. date:";
17 |
18 | const COPY_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "c";
19 | const CUT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "x";
20 | const PASTE_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "v";
21 | const EXTRACT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "Enter";
22 | const HIGHLIGHT_ALL_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "a";
23 | const RENAME_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "r";
24 | const DELETE_BUTTON_TOOLTIP =
25 | SHORTCUT_LABEL + ["backspace", "delete"].join(KEYS_SEPARATOR_LABEL);
26 | const CREATE_FOLDER_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "d";
27 | const ADD_FILES_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "f";
28 | const IMPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "i";
29 | const EXPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "e";
30 | const BACK_BUTTON_TOOLTIP =
31 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_LEFT_KEY_LABEL;
32 | const FORWARD_BUTTON_TOOLTIP =
33 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_RIGHT_KEY_LABEL;
34 |
35 | const CREATE_FOLDER_BUTTON_LABEL = "Create directory";
36 | const ADD_FILES_BUTTON_LABEL = "Add files";
37 | const IMPORT_ZIP_BUTTON_LABEL = "Import zip";
38 | const EXPORT_ZIP_BUTTON_LABEL = "Export zip";
39 | const RESET_BUTTON_LABEL = "Reset";
40 | const OPTIONS_BUTTON_LABEL = "Options";
41 | const BACK_BUTTON_LABEL = "<";
42 | const FORWARD_BUTTON_LABEL = ">";
43 | const DOWNLOAD_BUTTON_LABEL = "↵";
44 | const ENTER_FOLDER_BUTTON_LABEL = "↓";
45 | const COPY_BUTTON_LABEL = "Copy";
46 | const CUT_BUTTON_LABEL = "Cut";
47 | const PASTE_BUTTON_LABEL = "Paste";
48 | const RESET_CLIPBOARD_BUTTON_LABEL = "Reset clipboard";
49 | const EXTRACT_BUTTON_LABEL = "Extract";
50 | const HIGHLIGHT_ALL_BUTTON_LABEL = "Select all";
51 | const RENAME_BUTTON_LABEL = "Rename";
52 | const DELETE_BUTTON_LABEL = "Delete";
53 | const ABORT_DOWNLOAD_BUTTON_LABEL = "✕";
54 | const DIALOG_RESET_BUTTON_LABEL = "Reset";
55 | const DIALOG_CANCEL_BUTTON_LABEL = "Cancel";
56 | const DIALOG_OK_BUTTON_LABEL = "OK";
57 | const ERROR_TITLE = "Error";
58 |
59 | const EXPORT_ZIP_TITLE = "Export zip file";
60 | const EXPORT_ZIP_FILENAME_LABEL = "Filename:";
61 | const EXPORT_ZIP_PASSWORD_LABEL = "Password:";
62 | const EXPORT_ZIP_DIALOG_BUTTON_LABEL = "Export";
63 | const EXTRACT_TITLE = "Extract file";
64 | const EXTRACT_FILENAME_LABEL = "Filename:";
65 | const EXTRACT_DIALOG_BUTTON_LABEL = "Extract";
66 | const RENAME_TITLE = "Rename entry";
67 | const RENAME_FILENAME_LABEL = "New entry name:";
68 | const RENAME_DIALOG_BUTTON_LABEL = "Rename";
69 | const CREATE_FOLDER_TITLE = "Create directory";
70 | const CREATE_FOLDER_NAME_LABEL = "Directory name:";
71 | const CREATE_FOLDER_DIALOG_BUTTON_LABEL = "Create";
72 | const RESET_TITLE = "Reset filesystem";
73 | const RESET_MESSAGE = "Please confirm the reset of the filesystem.";
74 | const RESET_DIALOG_BUTTON_LABEL = "Reset";
75 | const DELETE_ENTRIES_TITLE = "Delete entries";
76 | const DELETE_ENTRIES_MESSAGE =
77 | "Please confirm the deletion of the highlighted entries.";
78 | const DELETE_ENTRIES_DIALOG_BUTTON_LABEL = "Delete";
79 | const ZIP_FILE_DESCRIPTION_LABEL = "Zip file";
80 | const IMPORT_PASSWORD_TITLE = "Enter password";
81 | const IMPORT_PASSWORD_LABEL = "Password:";
82 | const OPTIONS_DIALOG_BUTTON_LABEL = "Save";
83 | const OPTIONS_TITLE = "Options";
84 | const OPTIONS_ZOOM_FACTOR_LABEL = "Zoom factor (%):";
85 | const OPTIONS_HIDE_NAVIGATION_BAR_LABEL = "Hide navigation bar:";
86 | const OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL = "Hide downloads panel:";
87 | const OPTIONS_HIDE_INFOBAR_LABEL = "Hide bottom bar:";
88 | const OPTIONS_SELECT_SKIN_LABEL = "Theme:";
89 | const OPTIONS_DEFAULT_SKIN_LABEL = "Default";
90 | const OPTIONS_DOS_SKIN_LABEL = "DOS";
91 | const OPTIONS_EXPORT_ZIP_PASSWORD_LABEL = "Prompt for password:";
92 | const OPTIONS_DEFAULT_PASSWORD_LABEL = "Default password:";
93 | const OPTIONS_KEEP_ORDER_LABEL = "Keep entries order:";
94 | const OPTIONS_CHECK_SIGNATURE_LABEL = "Check data signature:";
95 | const OPTIONS_BUFFERED_WRITE_LABEL = "Use multiple cores:";
96 | const OPTIONS_MAX_WORKERS_LABEL = "Number of cores:";
97 | const OPTIONS_CHUNK_SIZE_LABEL = "Chunk size (kB):";
98 | const CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL = "Add file";
99 | const CHOOSE_ACTION_TITLE = "Choose action";
100 | const CHOOSE_ACTION_LABEL =
101 | "A zip file has been selected, please choose the proper action.";
102 | const NO_ENTRIES_LABEL = "Drag and drop files and directories here";
103 | const INFO_LABEL = [
104 | "Source code on ",
105 | " GitHub ",
106 | " Made with ",
107 | "♡",
108 | " in ",
109 | "Rennes"
110 | ];
111 | const CITY_URL = "https://en.wikipedia.org/wiki/Rennes";
112 | const HIGHLIGHTED_ENTRIES_LABEL = "Highlighted entries commands";
113 | const DOWNLOADS_LABEL = "Downloads panel";
114 | const ENTRIES_LABEL = "Directory entries";
115 | const FOLDERS_LABEL = "Navigation history";
116 | const SELECTED_FOLDER_LABEL = "Selected directory commands";
117 | const GO_INTO_FOLDER_LABEL = "Go into folder";
118 | const GO_BACK_LABEL = "Go back";
119 | const GO_FORWARD_LABEL = "Go forward";
120 | const ACCENT_COLOR_LABEL = "Accent color";
121 | const PLAYING_MUSIC_ICON = "▶";
122 | const PAUSED_MUSIC_ICON = "II";
123 |
124 | export {
125 | ROOT_ZIP_FILENAME,
126 | SHORTCUT_LABEL,
127 | CTRL_KEY_LABEL,
128 | SPACE_KEY_LABEL,
129 | ARROW_LEFT_KEY_LABEL,
130 | ARROW_RIGHT_KEY_LABEL,
131 | PARENT_FOLDER_TOOLTIP,
132 | CREATE_FOLDER_BUTTON_TOOLTIP,
133 | ADD_FILES_BUTTON_TOOLTIP,
134 | IMPORT_ZIP_BUTTON_TOOLTIP,
135 | EXPORT_ZIP_BUTTON_TOOLTIP,
136 | BACK_BUTTON_TOOLTIP,
137 | FORWARD_BUTTON_TOOLTIP,
138 | COPY_BUTTON_TOOLTIP,
139 | CUT_BUTTON_TOOLTIP,
140 | PASTE_BUTTON_TOOLTIP,
141 | EXTRACT_BUTTON_TOOLTIP,
142 | HIGHLIGHT_ALL_BUTTON_TOOLTIP,
143 | RENAME_BUTTON_TOOLTIP,
144 | DELETE_BUTTON_TOOLTIP,
145 | ROOT_FOLDER_LABEL,
146 | PARENT_FOLDER_LABEL,
147 | COPY_BUTTON_LABEL,
148 | CUT_BUTTON_LABEL,
149 | PASTE_BUTTON_LABEL,
150 | RESET_CLIPBOARD_BUTTON_LABEL,
151 | EXTRACT_BUTTON_LABEL,
152 | HIGHLIGHT_ALL_BUTTON_LABEL,
153 | RENAME_BUTTON_LABEL,
154 | DELETE_BUTTON_LABEL,
155 | ABORT_DOWNLOAD_BUTTON_LABEL,
156 | DOWNLOAD_BUTTON_LABEL,
157 | ENTER_FOLDER_BUTTON_LABEL,
158 | BACK_BUTTON_LABEL,
159 | FORWARD_BUTTON_LABEL,
160 | CREATE_FOLDER_BUTTON_LABEL,
161 | ADD_FILES_BUTTON_LABEL,
162 | IMPORT_ZIP_BUTTON_LABEL,
163 | EXPORT_ZIP_BUTTON_LABEL,
164 | RESET_BUTTON_LABEL,
165 | OPTIONS_BUTTON_LABEL,
166 | KEYS_SEPARATOR_LABEL,
167 | ZIP_FILE_DESCRIPTION_LABEL,
168 | SIZE_LABEL,
169 | UNCOMPRESSED_SIZE_LABEL,
170 | COMPRESSED_SIZE_LABEL,
171 | LAST_MOD_DATE_LABEL,
172 | EXPORT_ZIP_TITLE,
173 | EXPORT_ZIP_FILENAME_LABEL,
174 | EXPORT_ZIP_PASSWORD_LABEL,
175 | DIALOG_OK_BUTTON_LABEL,
176 | DIALOG_CANCEL_BUTTON_LABEL,
177 | EXTRACT_TITLE,
178 | EXTRACT_FILENAME_LABEL,
179 | RENAME_TITLE,
180 | RENAME_FILENAME_LABEL,
181 | EXPORT_ZIP_DIALOG_BUTTON_LABEL,
182 | RENAME_DIALOG_BUTTON_LABEL,
183 | EXTRACT_DIALOG_BUTTON_LABEL,
184 | CREATE_FOLDER_TITLE,
185 | CREATE_FOLDER_NAME_LABEL,
186 | CREATE_FOLDER_DIALOG_BUTTON_LABEL,
187 | RESET_TITLE,
188 | RESET_MESSAGE,
189 | RESET_DIALOG_BUTTON_LABEL,
190 | DELETE_ENTRIES_TITLE,
191 | DELETE_ENTRIES_MESSAGE,
192 | DELETE_ENTRIES_DIALOG_BUTTON_LABEL,
193 | ERROR_TITLE,
194 | IMPORT_PASSWORD_TITLE,
195 | IMPORT_PASSWORD_LABEL,
196 | DIALOG_RESET_BUTTON_LABEL,
197 | OPTIONS_TITLE,
198 | OPTIONS_DIALOG_BUTTON_LABEL,
199 | OPTIONS_ZOOM_FACTOR_LABEL,
200 | OPTIONS_HIDE_NAVIGATION_BAR_LABEL,
201 | OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL,
202 | OPTIONS_HIDE_INFOBAR_LABEL,
203 | OPTIONS_DEFAULT_SKIN_LABEL,
204 | OPTIONS_DOS_SKIN_LABEL,
205 | OPTIONS_SELECT_SKIN_LABEL,
206 | OPTIONS_EXPORT_ZIP_PASSWORD_LABEL,
207 | OPTIONS_DEFAULT_PASSWORD_LABEL,
208 | OPTIONS_KEEP_ORDER_LABEL,
209 | OPTIONS_CHECK_SIGNATURE_LABEL,
210 | OPTIONS_BUFFERED_WRITE_LABEL,
211 | OPTIONS_MAX_WORKERS_LABEL,
212 | OPTIONS_CHUNK_SIZE_LABEL,
213 | CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL,
214 | CHOOSE_ACTION_TITLE,
215 | CHOOSE_ACTION_LABEL,
216 | NO_ENTRIES_LABEL,
217 | INFO_LABEL,
218 | CITY_URL,
219 | HIGHLIGHTED_ENTRIES_LABEL,
220 | DOWNLOADS_LABEL,
221 | ENTRIES_LABEL,
222 | FOLDERS_LABEL,
223 | SELECTED_FOLDER_LABEL,
224 | GO_INTO_FOLDER_LABEL,
225 | GO_BACK_LABEL,
226 | GO_FORWARD_LABEL,
227 | ACCENT_COLOR_LABEL,
228 | PLAYING_MUSIC_ICON,
229 | PAUSED_MUSIC_ICON
230 | };
231 |
--------------------------------------------------------------------------------
/src/zip-manager/messages/es-ES.js:
--------------------------------------------------------------------------------
1 | const PARENT_FOLDER_LABEL = "..";
2 | const ROOT_FOLDER_LABEL = "";
3 | const ROOT_ZIP_FILENAME = "Descarga.zip";
4 | const KEYS_SEPARATOR_LABEL = ", ";
5 | const PARENT_FOLDER_TOOLTIP = "Directorio padre";
6 |
7 | const SHORTCUT_LABEL = "Atajo: ";
8 | const CTRL_KEY_LABEL = "⌘/ctrl-";
9 | const ALT_KEY_LABEL = "alt-";
10 | const SPACE_KEY_LABEL = "espacio";
11 | const ARROW_LEFT_KEY_LABEL = "izquierda";
12 | const ARROW_RIGHT_KEY_LABEL = "derecha";
13 | const SIZE_LABEL = "Tamaño:";
14 | const UNCOMPRESSED_SIZE_LABEL = "Tamaño sin comprimir:";
15 | const COMPRESSED_SIZE_LABEL = "Tamaño comprimido:";
16 | const LAST_MOD_DATE_LABEL = "Fecha de última modificación:";
17 |
18 | const COPY_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "c";
19 | const CUT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "x";
20 | const PASTE_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "v";
21 | const EXTRACT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "Enter";
22 | const HIGHLIGHT_ALL_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "a";
23 | const RENAME_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "r";
24 | const DELETE_BUTTON_TOOLTIP =
25 | SHORTCUT_LABEL + ["backspace", "delete"].join(KEYS_SEPARATOR_LABEL);
26 | const CREATE_FOLDER_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "d";
27 | const ADD_FILES_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "f";
28 | const IMPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "i";
29 | const EXPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "e";
30 | const BACK_BUTTON_TOOLTIP =
31 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_LEFT_KEY_LABEL;
32 | const FORWARD_BUTTON_TOOLTIP =
33 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_RIGHT_KEY_LABEL;
34 |
35 | const CREATE_FOLDER_BUTTON_LABEL = "Crear directorio";
36 | const ADD_FILES_BUTTON_LABEL = "Agregar archivos";
37 | const IMPORT_ZIP_BUTTON_LABEL = "Importar zip";
38 | const EXPORT_ZIP_BUTTON_LABEL = "Exportar zip";
39 | const RESET_BUTTON_LABEL = "Reiniciar";
40 | const OPTIONS_BUTTON_LABEL = "Opciones";
41 | const BACK_BUTTON_LABEL = "<";
42 | const FORWARD_BUTTON_LABEL = ">";
43 | const DOWNLOAD_BUTTON_LABEL = "↵";
44 | const ENTER_FOLDER_BUTTON_LABEL = "↓";
45 | const COPY_BUTTON_LABEL = "Copiar";
46 | const CUT_BUTTON_LABEL = "Cortar";
47 | const PASTE_BUTTON_LABEL = "Pegar";
48 | const RESET_CLIPBOARD_BUTTON_LABEL = "Reiniciar portapapeles";
49 | const EXTRACT_BUTTON_LABEL = "Extraer";
50 | const HIGHLIGHT_ALL_BUTTON_LABEL = "Seleccionar todo";
51 | const RENAME_BUTTON_LABEL = "Renombrar";
52 | const DELETE_BUTTON_LABEL = "Eliminar";
53 | const ABORT_DOWNLOAD_BUTTON_LABEL = "✕";
54 | const DIALOG_RESET_BUTTON_LABEL = "Reiniciar";
55 | const DIALOG_CANCEL_BUTTON_LABEL = "Cancelar";
56 | const DIALOG_OK_BUTTON_LABEL = "OK";
57 | const ERROR_TITLE = "Error";
58 |
59 | const EXPORT_ZIP_TITLE = "Exportar archivo zip";
60 | const EXPORT_ZIP_FILENAME_LABEL = "Nombre de archivo:";
61 | const EXPORT_ZIP_PASSWORD_LABEL = "Contraseña:";
62 | const EXPORT_ZIP_DIALOG_BUTTON_LABEL = "Exportar";
63 | const EXTRACT_TITLE = "Extraer archivo";
64 | const EXTRACT_FILENAME_LABEL = "Nombre de archivo:";
65 | const EXTRACT_DIALOG_BUTTON_LABEL = "Extraer";
66 | const RENAME_TITLE = "Renombrar entrada";
67 | const RENAME_FILENAME_LABEL = "Nuevo nombre de entrada:";
68 | const RENAME_DIALOG_BUTTON_LABEL = "Renombrar";
69 | const CREATE_FOLDER_TITLE = "Crear directorio";
70 | const CREATE_FOLDER_NAME_LABEL = "Nombre del directorio:";
71 | const CREATE_FOLDER_DIALOG_BUTTON_LABEL = "Crear";
72 | const RESET_TITLE = "Reiniciar sistema de archivos";
73 | const RESET_MESSAGE = "Por favor, confirme el reinicio del sistema de archivos.";
74 | const RESET_DIALOG_BUTTON_LABEL = "Reiniciar";
75 | const DELETE_ENTRIES_TITLE = "Eliminar entradas";
76 | const DELETE_ENTRIES_MESSAGE =
77 | "Por favor, confirme la eliminación de las entradas resaltadas.";
78 | const DELETE_ENTRIES_DIALOG_BUTTON_LABEL = "Eliminar";
79 | const ZIP_FILE_DESCRIPTION_LABEL = "Archivo zip";
80 | const IMPORT_PASSWORD_TITLE = "Introducir contraseña";
81 | const IMPORT_PASSWORD_LABEL = "Contraseña:";
82 | const OPTIONS_DIALOG_BUTTON_LABEL = "Guardar";
83 | const OPTIONS_TITLE = "Opciones";
84 | const OPTIONS_ZOOM_FACTOR_LABEL = "Factor de zoom (%):";
85 | const OPTIONS_HIDE_NAVIGATION_BAR_LABEL = "Ocultar barra de navegación:";
86 | const OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL = "Ocultar panel de descargas:";
87 | const OPTIONS_HIDE_INFOBAR_LABEL = "Ocultar barra inferior:";
88 | const OPTIONS_SELECT_SKIN_LABEL = "Tema:";
89 | const OPTIONS_DEFAULT_SKIN_LABEL = "Predeterminado";
90 | const OPTIONS_DOS_SKIN_LABEL = "DOS";
91 | const OPTIONS_EXPORT_ZIP_PASSWORD_LABEL = "Solicitar contraseña:";
92 | const OPTIONS_DEFAULT_PASSWORD_LABEL = "Contraseña predeterminada:";
93 | const OPTIONS_KEEP_ORDER_LABEL = "Mantener orden de entradas:";
94 | const OPTIONS_CHECK_SIGNATURE_LABEL = "Verificar firma de datos:";
95 | const OPTIONS_BUFFERED_WRITE_LABEL = "Usar múltiples núcleos:";
96 | const OPTIONS_MAX_WORKERS_LABEL = "Número de núcleos:";
97 | const OPTIONS_CHUNK_SIZE_LABEL = "Tamaño de fragmento (kB):";
98 | const CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL = "Agregar archivo";
99 | const CHOOSE_ACTION_TITLE = "Elegir acción";
100 | const CHOOSE_ACTION_LABEL =
101 | "Se ha seleccionado un archivo zip, por favor elija la acción adecuada.";
102 | const NO_ENTRIES_LABEL = "Arrastre y suelte archivos y directorios aquí";
103 | const INFO_LABEL = [
104 | "Código fuente en ",
105 | " GitHub ",
106 | " Hecho con ",
107 | "♡",
108 | " en ",
109 | "Rennes"
110 | ];
111 | const CITY_URL = "https://es.wikipedia.org/wiki/Rennes";
112 | const HIGHLIGHTED_ENTRIES_LABEL = "Comandos de entradas resaltadas";
113 | const DOWNLOADS_LABEL = "Panel de descargas";
114 | const ENTRIES_LABEL = "Entradas de directorio";
115 | const FOLDERS_LABEL = "Historial de navegación";
116 | const SELECTED_FOLDER_LABEL = "Comandos de directorio seleccionado";
117 | const GO_INTO_FOLDER_LABEL = "Ir al directorio";
118 | const GO_BACK_LABEL = "Retroceder";
119 | const GO_FORWARD_LABEL = "Avanzar";
120 | const ACCENT_COLOR_LABEL = "Color de acento";
121 | const PLAYING_MUSIC_ICON = "▶";
122 | const PAUSED_MUSIC_ICON = "II";
123 |
124 | export {
125 | ROOT_ZIP_FILENAME,
126 | SHORTCUT_LABEL,
127 | CTRL_KEY_LABEL,
128 | SPACE_KEY_LABEL,
129 | ARROW_LEFT_KEY_LABEL,
130 | ARROW_RIGHT_KEY_LABEL,
131 | PARENT_FOLDER_TOOLTIP,
132 | CREATE_FOLDER_BUTTON_TOOLTIP,
133 | ADD_FILES_BUTTON_TOOLTIP,
134 | IMPORT_ZIP_BUTTON_TOOLTIP,
135 | EXPORT_ZIP_BUTTON_TOOLTIP,
136 | BACK_BUTTON_TOOLTIP,
137 | FORWARD_BUTTON_TOOLTIP,
138 | COPY_BUTTON_TOOLTIP,
139 | CUT_BUTTON_TOOLTIP,
140 | PASTE_BUTTON_TOOLTIP,
141 | EXTRACT_BUTTON_TOOLTIP,
142 | HIGHLIGHT_ALL_BUTTON_TOOLTIP,
143 | RENAME_BUTTON_TOOLTIP,
144 | DELETE_BUTTON_TOOLTIP,
145 | ROOT_FOLDER_LABEL,
146 | PARENT_FOLDER_LABEL,
147 | COPY_BUTTON_LABEL,
148 | CUT_BUTTON_LABEL,
149 | PASTE_BUTTON_LABEL,
150 | RESET_CLIPBOARD_BUTTON_LABEL,
151 | EXTRACT_BUTTON_LABEL,
152 | HIGHLIGHT_ALL_BUTTON_LABEL,
153 | RENAME_BUTTON_LABEL,
154 | DELETE_BUTTON_LABEL,
155 | ABORT_DOWNLOAD_BUTTON_LABEL,
156 | DOWNLOAD_BUTTON_LABEL,
157 | ENTER_FOLDER_BUTTON_LABEL,
158 | BACK_BUTTON_LABEL,
159 | FORWARD_BUTTON_LABEL,
160 | CREATE_FOLDER_BUTTON_LABEL,
161 | ADD_FILES_BUTTON_LABEL,
162 | IMPORT_ZIP_BUTTON_LABEL,
163 | EXPORT_ZIP_BUTTON_LABEL,
164 | RESET_BUTTON_LABEL,
165 | OPTIONS_BUTTON_LABEL,
166 | KEYS_SEPARATOR_LABEL,
167 | ZIP_FILE_DESCRIPTION_LABEL,
168 | SIZE_LABEL,
169 | UNCOMPRESSED_SIZE_LABEL,
170 | COMPRESSED_SIZE_LABEL,
171 | LAST_MOD_DATE_LABEL,
172 | EXPORT_ZIP_TITLE,
173 | EXPORT_ZIP_FILENAME_LABEL,
174 | EXPORT_ZIP_PASSWORD_LABEL,
175 | DIALOG_OK_BUTTON_LABEL,
176 | DIALOG_CANCEL_BUTTON_LABEL,
177 | EXTRACT_TITLE,
178 | EXTRACT_FILENAME_LABEL,
179 | RENAME_TITLE,
180 | RENAME_FILENAME_LABEL,
181 | EXPORT_ZIP_DIALOG_BUTTON_LABEL,
182 | RENAME_DIALOG_BUTTON_LABEL,
183 | EXTRACT_DIALOG_BUTTON_LABEL,
184 | CREATE_FOLDER_TITLE,
185 | CREATE_FOLDER_NAME_LABEL,
186 | CREATE_FOLDER_DIALOG_BUTTON_LABEL,
187 | RESET_TITLE,
188 | RESET_MESSAGE,
189 | RESET_DIALOG_BUTTON_LABEL,
190 | DELETE_ENTRIES_TITLE,
191 | DELETE_ENTRIES_MESSAGE,
192 | DELETE_ENTRIES_DIALOG_BUTTON_LABEL,
193 | ERROR_TITLE,
194 | IMPORT_PASSWORD_TITLE,
195 | IMPORT_PASSWORD_LABEL,
196 | DIALOG_RESET_BUTTON_LABEL,
197 | OPTIONS_TITLE,
198 | OPTIONS_DIALOG_BUTTON_LABEL,
199 | OPTIONS_ZOOM_FACTOR_LABEL,
200 | OPTIONS_HIDE_NAVIGATION_BAR_LABEL,
201 | OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL,
202 | OPTIONS_HIDE_INFOBAR_LABEL,
203 | OPTIONS_DEFAULT_SKIN_LABEL,
204 | OPTIONS_DOS_SKIN_LABEL,
205 | OPTIONS_SELECT_SKIN_LABEL,
206 | OPTIONS_EXPORT_ZIP_PASSWORD_LABEL,
207 | OPTIONS_DEFAULT_PASSWORD_LABEL,
208 | OPTIONS_KEEP_ORDER_LABEL,
209 | OPTIONS_CHECK_SIGNATURE_LABEL,
210 | OPTIONS_BUFFERED_WRITE_LABEL,
211 | OPTIONS_MAX_WORKERS_LABEL,
212 | OPTIONS_CHUNK_SIZE_LABEL,
213 | CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL,
214 | CHOOSE_ACTION_TITLE,
215 | CHOOSE_ACTION_LABEL,
216 | NO_ENTRIES_LABEL,
217 | INFO_LABEL,
218 | CITY_URL,
219 | HIGHLIGHTED_ENTRIES_LABEL,
220 | DOWNLOADS_LABEL,
221 | ENTRIES_LABEL,
222 | FOLDERS_LABEL,
223 | SELECTED_FOLDER_LABEL,
224 | GO_INTO_FOLDER_LABEL,
225 | GO_BACK_LABEL,
226 | GO_FORWARD_LABEL,
227 | ACCENT_COLOR_LABEL,
228 | PLAYING_MUSIC_ICON,
229 | PAUSED_MUSIC_ICON
230 | };
231 |
--------------------------------------------------------------------------------
/src/zip-manager/messages/fr-FR.js:
--------------------------------------------------------------------------------
1 | const PARENT_FOLDER_LABEL = "..";
2 | const ROOT_FOLDER_LABEL = "";
3 | const ROOT_ZIP_FILENAME = "Téléchargement.zip";
4 | const KEYS_SEPARATOR_LABEL = ", ";
5 | const PARENT_FOLDER_TOOLTIP = "Répertoire parent";
6 |
7 | const SHORTCUT_LABEL = "Raccourci : ";
8 | const CTRL_KEY_LABEL = "⌘/ctrl-";
9 | const ALT_KEY_LABEL = "alt-";
10 | const SPACE_KEY_LABEL = "espace";
11 | const ARROW_LEFT_KEY_LABEL = "gauche";
12 | const ARROW_RIGHT_KEY_LABEL = "droite";
13 | const SIZE_LABEL = "Taille :";
14 | const UNCOMPRESSED_SIZE_LABEL = "Taille non compressée :";
15 | const COMPRESSED_SIZE_LABEL = "Taille compressée :";
16 | const LAST_MOD_DATE_LABEL = "Date de dernière modification :";
17 |
18 | const COPY_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "c";
19 | const CUT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "x";
20 | const PASTE_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "v";
21 | const EXTRACT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "Entrée";
22 | const HIGHLIGHT_ALL_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "a";
23 | const RENAME_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "r";
24 | const DELETE_BUTTON_TOOLTIP =
25 | SHORTCUT_LABEL + ["retour arrière", "suppr"].join(KEYS_SEPARATOR_LABEL);
26 | const CREATE_FOLDER_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "d";
27 | const ADD_FILES_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "f";
28 | const IMPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "i";
29 | const EXPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "e";
30 | const BACK_BUTTON_TOOLTIP =
31 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_LEFT_KEY_LABEL;
32 | const FORWARD_BUTTON_TOOLTIP =
33 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_RIGHT_KEY_LABEL;
34 |
35 | const CREATE_FOLDER_BUTTON_LABEL = "Créer répertoire";
36 | const ADD_FILES_BUTTON_LABEL = "Ajouter fichiers";
37 | const IMPORT_ZIP_BUTTON_LABEL = "Importer zip";
38 | const EXPORT_ZIP_BUTTON_LABEL = "Exporter zip";
39 | const RESET_BUTTON_LABEL = "Réinitialiser";
40 | const OPTIONS_BUTTON_LABEL = "Options";
41 | const BACK_BUTTON_LABEL = "<";
42 | const FORWARD_BUTTON_LABEL = ">";
43 | const DOWNLOAD_BUTTON_LABEL = "↵";
44 | const ENTER_FOLDER_BUTTON_LABEL = "↓";
45 | const COPY_BUTTON_LABEL = "Copier";
46 | const CUT_BUTTON_LABEL = "Couper";
47 | const PASTE_BUTTON_LABEL = "Coller";
48 | const RESET_CLIPBOARD_BUTTON_LABEL = "Réinitialiser presse-papier";
49 | const EXTRACT_BUTTON_LABEL = "Extraire";
50 | const HIGHLIGHT_ALL_BUTTON_LABEL = "Selectionner tout";
51 | const RENAME_BUTTON_LABEL = "Renommer";
52 | const DELETE_BUTTON_LABEL = "Supprimer";
53 | const ABORT_DOWNLOAD_BUTTON_LABEL = "✕";
54 | const DIALOG_RESET_BUTTON_LABEL = "Réinitialiser";
55 | const DIALOG_CANCEL_BUTTON_LABEL = "Annuler";
56 | const DIALOG_OK_BUTTON_LABEL = "OK";
57 | const ERROR_TITLE = "Erreur";
58 |
59 | const EXPORT_ZIP_TITLE = "Exporter fichier zip";
60 | const EXPORT_ZIP_FILENAME_LABEL = "Nom du fichier :";
61 | const EXPORT_ZIP_PASSWORD_LABEL = "Mot de passe :";
62 | const EXPORT_ZIP_DIALOG_BUTTON_LABEL = "Export";
63 | const EXTRACT_TITLE = "Extraire fichier";
64 | const EXTRACT_FILENAME_LABEL = "Nom du fichier :";
65 | const EXTRACT_DIALOG_BUTTON_LABEL = "Extraire";
66 | const RENAME_TITLE = "Renommer entrée";
67 | const RENAME_FILENAME_LABEL = "Nouveau nom de l'entrée :";
68 | const RENAME_DIALOG_BUTTON_LABEL = "Renommer";
69 | const CREATE_FOLDER_TITLE = "Créer répertoire";
70 | const CREATE_FOLDER_NAME_LABEL = "Nom du repertoire :";
71 | const CREATE_FOLDER_DIALOG_BUTTON_LABEL = "Créer";
72 | const RESET_TITLE = "Réinitialiser système de fichiers";
73 | const RESET_MESSAGE =
74 | "Veuillez confirmer la réinitialisation du système de fichiers.";
75 | const RESET_DIALOG_BUTTON_LABEL = "Réinitialiser";
76 | const DELETE_ENTRIES_TITLE = "Supprimer les entrées";
77 | const DELETE_ENTRIES_MESSAGE =
78 | "Veuillez confirmer la suppression des entrées en surbrillance.";
79 | const DELETE_ENTRIES_DIALOG_BUTTON_LABEL = "Supprimer";
80 | const ZIP_FILE_DESCRIPTION_LABEL = "Zipper fichier";
81 | const IMPORT_PASSWORD_TITLE = "Entrer le mot de passse";
82 | const IMPORT_PASSWORD_LABEL = "Mot de passe :";
83 | const OPTIONS_DIALOG_BUTTON_LABEL = "Sauver";
84 | const OPTIONS_TITLE = "Options";
85 | const OPTIONS_ZOOM_FACTOR_LABEL = "Facteur de zoom (%) :";
86 | const OPTIONS_HIDE_NAVIGATION_BAR_LABEL = "Cacher la barre de navigation :";
87 | const OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL =
88 | "Cacher le panneau de téléchargements :";
89 | const OPTIONS_HIDE_INFOBAR_LABEL = "Cacher la barre du bas :";
90 | const OPTIONS_SELECT_SKIN_LABEL = "Thème :";
91 | const OPTIONS_DEFAULT_SKIN_LABEL = "Défaut";
92 | const OPTIONS_DOS_SKIN_LABEL = "DOS";
93 | const OPTIONS_EXPORT_ZIP_PASSWORD_LABEL = "Demander un mot de passe :";
94 | const OPTIONS_DEFAULT_PASSWORD_LABEL = "Mot de passe par défaut :";
95 | const OPTIONS_KEEP_ORDER_LABEL = "Préserver l'ordre des entrées :";
96 | const OPTIONS_CHECK_SIGNATURE_LABEL = "Vérifier la signature des données :";
97 | const OPTIONS_BUFFERED_WRITE_LABEL = "Utiliser plusieurs cœurs :";
98 | const OPTIONS_MAX_WORKERS_LABEL = "Nombre de cœurs :";
99 | const OPTIONS_CHUNK_SIZE_LABEL = "Taille des paquets (ko) :";
100 | const CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL = "Ajouter fichier";
101 | const CHOOSE_ACTION_TITLE = "Choisir l'action";
102 | const CHOOSE_ACTION_LABEL =
103 | "Un fichier zip a été selectionné, veuillez choisir l'action appropriée.";
104 | const NO_ENTRIES_LABEL =
105 | "Glissez et déposez des fichiers et des répertoires ici";
106 | const INFO_LABEL = [
107 | "Code source sur ",
108 | " GitHub ",
109 | " Fait avec ",
110 | "♡",
111 | " à ",
112 | "Rennes"
113 | ];
114 | const CITY_URL = "https://fr.wikipedia.org/wiki/Rennes";
115 | const HIGHLIGHTED_ENTRIES_LABEL = "Commandes des entrées en surbrillance";
116 | const DOWNLOADS_LABEL = "Panneau de téléchargements";
117 | const ENTRIES_LABEL = "Entrées du répertoire";
118 | const FOLDERS_LABEL = "Historique de navigation";
119 | const SELECTED_FOLDER_LABEL = "Commandes du répertoire selectionné";
120 | const GO_INTO_FOLDER_LABEL = "Naviguer dans le répertoire";
121 | const GO_BACK_LABEL = "Naviguer en arrière";
122 | const GO_FORWARD_LABEL = "Naviguer en avant";
123 | const ACCENT_COLOR_LABEL = "Couleur d'accentuation";
124 | const PLAYING_MUSIC_ICON = "▶";
125 | const PAUSED_MUSIC_ICON = "II";
126 |
127 | export {
128 | ROOT_ZIP_FILENAME,
129 | SHORTCUT_LABEL,
130 | CTRL_KEY_LABEL,
131 | SPACE_KEY_LABEL,
132 | ARROW_LEFT_KEY_LABEL,
133 | ARROW_RIGHT_KEY_LABEL,
134 | PARENT_FOLDER_TOOLTIP,
135 | CREATE_FOLDER_BUTTON_TOOLTIP,
136 | ADD_FILES_BUTTON_TOOLTIP,
137 | IMPORT_ZIP_BUTTON_TOOLTIP,
138 | EXPORT_ZIP_BUTTON_TOOLTIP,
139 | BACK_BUTTON_TOOLTIP,
140 | FORWARD_BUTTON_TOOLTIP,
141 | COPY_BUTTON_TOOLTIP,
142 | CUT_BUTTON_TOOLTIP,
143 | PASTE_BUTTON_TOOLTIP,
144 | EXTRACT_BUTTON_TOOLTIP,
145 | HIGHLIGHT_ALL_BUTTON_TOOLTIP,
146 | RENAME_BUTTON_TOOLTIP,
147 | DELETE_BUTTON_TOOLTIP,
148 | ROOT_FOLDER_LABEL,
149 | PARENT_FOLDER_LABEL,
150 | COPY_BUTTON_LABEL,
151 | CUT_BUTTON_LABEL,
152 | PASTE_BUTTON_LABEL,
153 | RESET_CLIPBOARD_BUTTON_LABEL,
154 | EXTRACT_BUTTON_LABEL,
155 | HIGHLIGHT_ALL_BUTTON_LABEL,
156 | RENAME_BUTTON_LABEL,
157 | DELETE_BUTTON_LABEL,
158 | ABORT_DOWNLOAD_BUTTON_LABEL,
159 | DOWNLOAD_BUTTON_LABEL,
160 | ENTER_FOLDER_BUTTON_LABEL,
161 | BACK_BUTTON_LABEL,
162 | FORWARD_BUTTON_LABEL,
163 | CREATE_FOLDER_BUTTON_LABEL,
164 | ADD_FILES_BUTTON_LABEL,
165 | IMPORT_ZIP_BUTTON_LABEL,
166 | EXPORT_ZIP_BUTTON_LABEL,
167 | RESET_BUTTON_LABEL,
168 | OPTIONS_BUTTON_LABEL,
169 | KEYS_SEPARATOR_LABEL,
170 | ZIP_FILE_DESCRIPTION_LABEL,
171 | SIZE_LABEL,
172 | UNCOMPRESSED_SIZE_LABEL,
173 | COMPRESSED_SIZE_LABEL,
174 | LAST_MOD_DATE_LABEL,
175 | EXPORT_ZIP_TITLE,
176 | EXPORT_ZIP_FILENAME_LABEL,
177 | EXPORT_ZIP_PASSWORD_LABEL,
178 | DIALOG_OK_BUTTON_LABEL,
179 | DIALOG_CANCEL_BUTTON_LABEL,
180 | EXTRACT_TITLE,
181 | EXTRACT_FILENAME_LABEL,
182 | RENAME_TITLE,
183 | RENAME_FILENAME_LABEL,
184 | EXPORT_ZIP_DIALOG_BUTTON_LABEL,
185 | RENAME_DIALOG_BUTTON_LABEL,
186 | EXTRACT_DIALOG_BUTTON_LABEL,
187 | CREATE_FOLDER_TITLE,
188 | CREATE_FOLDER_NAME_LABEL,
189 | CREATE_FOLDER_DIALOG_BUTTON_LABEL,
190 | RESET_TITLE,
191 | RESET_MESSAGE,
192 | RESET_DIALOG_BUTTON_LABEL,
193 | DELETE_ENTRIES_TITLE,
194 | DELETE_ENTRIES_MESSAGE,
195 | DELETE_ENTRIES_DIALOG_BUTTON_LABEL,
196 | ERROR_TITLE,
197 | IMPORT_PASSWORD_TITLE,
198 | IMPORT_PASSWORD_LABEL,
199 | DIALOG_RESET_BUTTON_LABEL,
200 | OPTIONS_TITLE,
201 | OPTIONS_DIALOG_BUTTON_LABEL,
202 | OPTIONS_ZOOM_FACTOR_LABEL,
203 | OPTIONS_HIDE_NAVIGATION_BAR_LABEL,
204 | OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL,
205 | OPTIONS_HIDE_INFOBAR_LABEL,
206 | OPTIONS_SELECT_SKIN_LABEL,
207 | OPTIONS_DEFAULT_SKIN_LABEL,
208 | OPTIONS_DOS_SKIN_LABEL,
209 | OPTIONS_EXPORT_ZIP_PASSWORD_LABEL,
210 | OPTIONS_DEFAULT_PASSWORD_LABEL,
211 | OPTIONS_KEEP_ORDER_LABEL,
212 | OPTIONS_CHECK_SIGNATURE_LABEL,
213 | OPTIONS_BUFFERED_WRITE_LABEL,
214 | OPTIONS_MAX_WORKERS_LABEL,
215 | OPTIONS_CHUNK_SIZE_LABEL,
216 | CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL,
217 | CHOOSE_ACTION_TITLE,
218 | CHOOSE_ACTION_LABEL,
219 | NO_ENTRIES_LABEL,
220 | INFO_LABEL,
221 | CITY_URL,
222 | HIGHLIGHTED_ENTRIES_LABEL,
223 | DOWNLOADS_LABEL,
224 | ENTRIES_LABEL,
225 | FOLDERS_LABEL,
226 | SELECTED_FOLDER_LABEL,
227 | GO_INTO_FOLDER_LABEL,
228 | GO_BACK_LABEL,
229 | GO_FORWARD_LABEL,
230 | ACCENT_COLOR_LABEL,
231 | PLAYING_MUSIC_ICON,
232 | PAUSED_MUSIC_ICON
233 | };
234 |
--------------------------------------------------------------------------------
/src/zip-manager/messages/index.js:
--------------------------------------------------------------------------------
1 | import * as fr_FR from "./fr-FR.js";
2 | import * as en_US from "./en-US.js";
3 | import * as de_DE from "./de-DE.js";
4 | import * as es_ES from "./es-ES.js";
5 | import * as it_IT from "./it-IT.js";
6 | import * as pt_PT from "./pt-PT.js";
7 |
8 | const LANGUAGES = {
9 | "fr-FR": fr_FR,
10 | "en-US": en_US,
11 | "de-DE": de_DE,
12 | "es-ES": es_ES,
13 | "it-IT": it_IT,
14 | "pt-PT": pt_PT
15 | };
16 |
17 | function getMessages({ i18nService }) {
18 | return LANGUAGES[i18nService.getLanguageId()];
19 | }
20 |
21 | export { getMessages };
22 |
--------------------------------------------------------------------------------
/src/zip-manager/messages/it-IT.js:
--------------------------------------------------------------------------------
1 | const PARENT_FOLDER_LABEL = "..";
2 | const ROOT_FOLDER_LABEL = "";
3 | const ROOT_ZIP_FILENAME = "Download.zip";
4 | const KEYS_SEPARATOR_LABEL = ", ";
5 | const PARENT_FOLDER_TOOLTIP = "Cartella padre";
6 |
7 | const SHORTCUT_LABEL = "Scorciatoia: ";
8 | const CTRL_KEY_LABEL = "⌘/ctrl-";
9 | const ALT_KEY_LABEL = "alt-";
10 | const SPACE_KEY_LABEL = "spazio";
11 | const ARROW_LEFT_KEY_LABEL = "sinistra";
12 | const ARROW_RIGHT_KEY_LABEL = "destra";
13 | const SIZE_LABEL = "Dimensioni:";
14 | const UNCOMPRESSED_SIZE_LABEL = "Dimensioni non compressa:";
15 | const COMPRESSED_SIZE_LABEL = "Dimensioni compressa:";
16 | const LAST_MOD_DATE_LABEL = "Data ultima modifica:";
17 |
18 | const COPY_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "c";
19 | const CUT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "x";
20 | const PASTE_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "v";
21 | const EXTRACT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "Invio";
22 | const HIGHLIGHT_ALL_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "a";
23 | const RENAME_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "r";
24 | const DELETE_BUTTON_TOOLTIP =
25 | SHORTCUT_LABEL + ["backspace", "delete"].join(KEYS_SEPARATOR_LABEL);
26 | const CREATE_FOLDER_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "d";
27 | const ADD_FILES_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "f";
28 | const IMPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "i";
29 | const EXPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "e";
30 | const BACK_BUTTON_TOOLTIP =
31 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_LEFT_KEY_LABEL;
32 | const FORWARD_BUTTON_TOOLTIP =
33 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_RIGHT_KEY_LABEL;
34 |
35 | const CREATE_FOLDER_BUTTON_LABEL = "Crea cartella";
36 | const ADD_FILES_BUTTON_LABEL = "Aggiungi file";
37 | const IMPORT_ZIP_BUTTON_LABEL = "Importa zip";
38 | const EXPORT_ZIP_BUTTON_LABEL = "Esporta zip";
39 | const RESET_BUTTON_LABEL = "Resetta";
40 | const OPTIONS_BUTTON_LABEL = "Opzioni";
41 | const BACK_BUTTON_LABEL = "<";
42 | const FORWARD_BUTTON_LABEL = ">";
43 | const DOWNLOAD_BUTTON_LABEL = "↵";
44 | const ENTER_FOLDER_BUTTON_LABEL = "↓";
45 | const COPY_BUTTON_LABEL = "Copia";
46 | const CUT_BUTTON_LABEL = "Taglia";
47 | const PASTE_BUTTON_LABEL = "Incolla";
48 | const RESET_CLIPBOARD_BUTTON_LABEL = "Resetta clipboard";
49 | const EXTRACT_BUTTON_LABEL = "Estrai";
50 | const HIGHLIGHT_ALL_BUTTON_LABEL = "Seleziona tutto";
51 | const RENAME_BUTTON_LABEL = "Rinomina";
52 | const DELETE_BUTTON_LABEL = "Elimina";
53 | const ABORT_DOWNLOAD_BUTTON_LABEL = "✕";
54 | const DIALOG_RESET_BUTTON_LABEL = "Resetta";
55 | const DIALOG_CANCEL_BUTTON_LABEL = "Annulla";
56 | const DIALOG_OK_BUTTON_LABEL = "OK";
57 | const ERROR_TITLE = "Errore";
58 |
59 | const EXPORT_ZIP_TITLE = "Esporta file zip";
60 | const EXPORT_ZIP_FILENAME_LABEL = "Nome file:";
61 | const EXPORT_ZIP_PASSWORD_LABEL = "Password:";
62 | const EXPORT_ZIP_DIALOG_BUTTON_LABEL = "Esporta";
63 | const EXTRACT_TITLE = "Estrai file";
64 | const EXTRACT_FILENAME_LABEL = "Nome file:";
65 | const EXTRACT_DIALOG_BUTTON_LABEL = "Estrai";
66 | const RENAME_TITLE = "Rinomina voce";
67 | const RENAME_FILENAME_LABEL = "Nuovo nome voce:";
68 | const RENAME_DIALOG_BUTTON_LABEL = "Rinomina";
69 | const CREATE_FOLDER_TITLE = "Crea cartella";
70 | const CREATE_FOLDER_NAME_LABEL = "Nome cartella:";
71 | const CREATE_FOLDER_DIALOG_BUTTON_LABEL = "Crea";
72 | const RESET_TITLE = "Resetta file system";
73 | const RESET_MESSAGE = "Confermi il reset del file system?";
74 | const RESET_DIALOG_BUTTON_LABEL = "Resetta";
75 | const DELETE_ENTRIES_TITLE = "Elimina voci";
76 | const DELETE_ENTRIES_MESSAGE =
77 | "Confermi l'eliminazione delle voci evidenziate?";
78 | const DELETE_ENTRIES_DIALOG_BUTTON_LABEL = "Elimina";
79 | const ZIP_FILE_DESCRIPTION_LABEL = "File zip";
80 | const IMPORT_PASSWORD_TITLE = "Inserisci password";
81 | const IMPORT_PASSWORD_LABEL = "Password:";
82 | const OPTIONS_DIALOG_BUTTON_LABEL = "Salva";
83 | const OPTIONS_TITLE = "Opzioni";
84 | const OPTIONS_ZOOM_FACTOR_LABEL = "Fattore di zoom (%):";
85 | const OPTIONS_HIDE_NAVIGATION_BAR_LABEL = "Nascondi barra di navigazione:";
86 | const OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL = "Nascondi pannello download:";
87 | const OPTIONS_HIDE_INFOBAR_LABEL = "Nascondi barra inferiore:";
88 | const OPTIONS_SELECT_SKIN_LABEL = "Tema:";
89 | const OPTIONS_DEFAULT_SKIN_LABEL = "Predefinito";
90 | const OPTIONS_DOS_SKIN_LABEL = "DOS";
91 | const OPTIONS_EXPORT_ZIP_PASSWORD_LABEL = "Richiedi password:";
92 | const OPTIONS_DEFAULT_PASSWORD_LABEL = "Password predefinita:";
93 | const OPTIONS_KEEP_ORDER_LABEL = "Mantieni ordine voci:";
94 | const OPTIONS_CHECK_SIGNATURE_LABEL = "Verifica firma dati:";
95 | const OPTIONS_BUFFERED_WRITE_LABEL = "Usa multi-core:";
96 | const OPTIONS_MAX_WORKERS_LABEL = "Numero core:";
97 | const OPTIONS_CHUNK_SIZE_LABEL = "Dimensione frammento (kB):";
98 | const CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL = "Aggiungi file";
99 | const CHOOSE_ACTION_TITLE = "Scegli azione";
100 | const CHOOSE_ACTION_LABEL =
101 | "È stato selezionato un file zip, scegli l'azione appropriata.";
102 | const NO_ENTRIES_LABEL = "Trascina qui file e cartelle";
103 | const INFO_LABEL = [
104 | "Codice sorgente su ",
105 | " GitHub ",
106 | " Creato con ",
107 | "♡",
108 | " a ",
109 | "Rennes"
110 | ];
111 | const CITY_URL = "https://it.wikipedia.org/wiki/Rennes";
112 | const HIGHLIGHTED_ENTRIES_LABEL = "Comandi voci evidenziate";
113 | const DOWNLOADS_LABEL = "Pannello download";
114 | const ENTRIES_LABEL = "Voci directory";
115 | const FOLDERS_LABEL = "Cronologia navigazione";
116 | const SELECTED_FOLDER_LABEL = "Comandi cartella selezionata";
117 | const GO_INTO_FOLDER_LABEL = "Entra nella cartella";
118 | const GO_BACK_LABEL = "Indietro";
119 | const GO_FORWARD_LABEL = "Avanti";
120 | const ACCENT_COLOR_LABEL = "Colore accentuazione";
121 | const PLAYING_MUSIC_ICON = "▶";
122 | const PAUSED_MUSIC_ICON = "II";
123 |
124 | export {
125 | ROOT_ZIP_FILENAME,
126 | SHORTCUT_LABEL,
127 | CTRL_KEY_LABEL,
128 | SPACE_KEY_LABEL,
129 | ARROW_LEFT_KEY_LABEL,
130 | ARROW_RIGHT_KEY_LABEL,
131 | PARENT_FOLDER_TOOLTIP,
132 | CREATE_FOLDER_BUTTON_TOOLTIP,
133 | ADD_FILES_BUTTON_TOOLTIP,
134 | IMPORT_ZIP_BUTTON_TOOLTIP,
135 | EXPORT_ZIP_BUTTON_TOOLTIP,
136 | BACK_BUTTON_TOOLTIP,
137 | FORWARD_BUTTON_TOOLTIP,
138 | COPY_BUTTON_TOOLTIP,
139 | CUT_BUTTON_TOOLTIP,
140 | PASTE_BUTTON_TOOLTIP,
141 | EXTRACT_BUTTON_TOOLTIP,
142 | HIGHLIGHT_ALL_BUTTON_TOOLTIP,
143 | RENAME_BUTTON_TOOLTIP,
144 | DELETE_BUTTON_TOOLTIP,
145 | ROOT_FOLDER_LABEL,
146 | PARENT_FOLDER_LABEL,
147 | COPY_BUTTON_LABEL,
148 | CUT_BUTTON_LABEL,
149 | PASTE_BUTTON_LABEL,
150 | RESET_CLIPBOARD_BUTTON_LABEL,
151 | EXTRACT_BUTTON_LABEL,
152 | HIGHLIGHT_ALL_BUTTON_LABEL,
153 | RENAME_BUTTON_LABEL,
154 | DELETE_BUTTON_LABEL,
155 | ABORT_DOWNLOAD_BUTTON_LABEL,
156 | DOWNLOAD_BUTTON_LABEL,
157 | ENTER_FOLDER_BUTTON_LABEL,
158 | BACK_BUTTON_LABEL,
159 | FORWARD_BUTTON_LABEL,
160 | CREATE_FOLDER_BUTTON_LABEL,
161 | ADD_FILES_BUTTON_LABEL,
162 | IMPORT_ZIP_BUTTON_LABEL,
163 | EXPORT_ZIP_BUTTON_LABEL,
164 | RESET_BUTTON_LABEL,
165 | OPTIONS_BUTTON_LABEL,
166 | KEYS_SEPARATOR_LABEL,
167 | ZIP_FILE_DESCRIPTION_LABEL,
168 | SIZE_LABEL,
169 | UNCOMPRESSED_SIZE_LABEL,
170 | COMPRESSED_SIZE_LABEL,
171 | LAST_MOD_DATE_LABEL,
172 | EXPORT_ZIP_TITLE,
173 | EXPORT_ZIP_FILENAME_LABEL,
174 | EXPORT_ZIP_PASSWORD_LABEL,
175 | DIALOG_OK_BUTTON_LABEL,
176 | DIALOG_CANCEL_BUTTON_LABEL,
177 | EXTRACT_TITLE,
178 | EXTRACT_FILENAME_LABEL,
179 | RENAME_TITLE,
180 | RENAME_FILENAME_LABEL,
181 | EXPORT_ZIP_DIALOG_BUTTON_LABEL,
182 | RENAME_DIALOG_BUTTON_LABEL,
183 | EXTRACT_DIALOG_BUTTON_LABEL,
184 | CREATE_FOLDER_TITLE,
185 | CREATE_FOLDER_NAME_LABEL,
186 | CREATE_FOLDER_DIALOG_BUTTON_LABEL,
187 | RESET_TITLE,
188 | RESET_MESSAGE,
189 | RESET_DIALOG_BUTTON_LABEL,
190 | DELETE_ENTRIES_TITLE,
191 | DELETE_ENTRIES_MESSAGE,
192 | DELETE_ENTRIES_DIALOG_BUTTON_LABEL,
193 | ERROR_TITLE,
194 | IMPORT_PASSWORD_TITLE,
195 | IMPORT_PASSWORD_LABEL,
196 | DIALOG_RESET_BUTTON_LABEL,
197 | OPTIONS_TITLE,
198 | OPTIONS_DIALOG_BUTTON_LABEL,
199 | OPTIONS_ZOOM_FACTOR_LABEL,
200 | OPTIONS_HIDE_NAVIGATION_BAR_LABEL,
201 | OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL,
202 | OPTIONS_HIDE_INFOBAR_LABEL,
203 | OPTIONS_DEFAULT_SKIN_LABEL,
204 | OPTIONS_DOS_SKIN_LABEL,
205 | OPTIONS_SELECT_SKIN_LABEL,
206 | OPTIONS_EXPORT_ZIP_PASSWORD_LABEL,
207 | OPTIONS_DEFAULT_PASSWORD_LABEL,
208 | OPTIONS_KEEP_ORDER_LABEL,
209 | OPTIONS_CHECK_SIGNATURE_LABEL,
210 | OPTIONS_BUFFERED_WRITE_LABEL,
211 | OPTIONS_MAX_WORKERS_LABEL,
212 | OPTIONS_CHUNK_SIZE_LABEL,
213 | CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL,
214 | CHOOSE_ACTION_TITLE,
215 | CHOOSE_ACTION_LABEL,
216 | NO_ENTRIES_LABEL,
217 | INFO_LABEL,
218 | CITY_URL,
219 | HIGHLIGHTED_ENTRIES_LABEL,
220 | DOWNLOADS_LABEL,
221 | ENTRIES_LABEL,
222 | FOLDERS_LABEL,
223 | SELECTED_FOLDER_LABEL,
224 | GO_INTO_FOLDER_LABEL,
225 | GO_BACK_LABEL,
226 | GO_FORWARD_LABEL,
227 | ACCENT_COLOR_LABEL,
228 | PLAYING_MUSIC_ICON,
229 | PAUSED_MUSIC_ICON
230 | };
231 |
--------------------------------------------------------------------------------
/src/zip-manager/messages/pt-PT.js:
--------------------------------------------------------------------------------
1 | const PARENT_FOLDER_LABEL = "..";
2 | const ROOT_FOLDER_LABEL = "";
3 | const ROOT_ZIP_FILENAME = "Download.zip";
4 | const KEYS_SEPARATOR_LABEL = ", ";
5 | const PARENT_FOLDER_TOOLTIP = "Diretório pai";
6 |
7 | const SHORTCUT_LABEL = "Atalho: ";
8 | const CTRL_KEY_LABEL = "⌘/ctrl-";
9 | const ALT_KEY_LABEL = "alt-";
10 | const SPACE_KEY_LABEL = "espaço";
11 | const ARROW_LEFT_KEY_LABEL = "esquerda";
12 | const ARROW_RIGHT_KEY_LABEL = "direita";
13 | const SIZE_LABEL = "Tamanho:";
14 | const UNCOMPRESSED_SIZE_LABEL = "Tamanho descompactado:";
15 | const COMPRESSED_SIZE_LABEL = "Tamanho compactado:";
16 | const LAST_MOD_DATE_LABEL = "Data da última modificação:";
17 |
18 | const COPY_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "c";
19 | const CUT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "x";
20 | const PASTE_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "v";
21 | const EXTRACT_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "Enter";
22 | const HIGHLIGHT_ALL_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "a";
23 | const RENAME_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "r";
24 | const DELETE_BUTTON_TOOLTIP =
25 | SHORTCUT_LABEL + ["backspace", "delete"].join(KEYS_SEPARATOR_LABEL);
26 | const CREATE_FOLDER_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "d";
27 | const ADD_FILES_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "f";
28 | const IMPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "i";
29 | const EXPORT_ZIP_BUTTON_TOOLTIP = SHORTCUT_LABEL + CTRL_KEY_LABEL + "e";
30 | const BACK_BUTTON_TOOLTIP =
31 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_LEFT_KEY_LABEL;
32 | const FORWARD_BUTTON_TOOLTIP =
33 | SHORTCUT_LABEL + ALT_KEY_LABEL + ARROW_RIGHT_KEY_LABEL;
34 |
35 | const CREATE_FOLDER_BUTTON_LABEL = "Criar diretório";
36 | const ADD_FILES_BUTTON_LABEL = "Adicionar ficheiros";
37 | const IMPORT_ZIP_BUTTON_LABEL = "Importar zip";
38 | const EXPORT_ZIP_BUTTON_LABEL = "Exportar zip";
39 | const RESET_BUTTON_LABEL = "Repor";
40 | const OPTIONS_BUTTON_LABEL = "Opções";
41 | const BACK_BUTTON_LABEL = "<";
42 | const FORWARD_BUTTON_LABEL = ">";
43 | const DOWNLOAD_BUTTON_LABEL = "↵";
44 | const ENTER_FOLDER_BUTTON_LABEL = "↓";
45 | const COPY_BUTTON_LABEL = "Copiar";
46 | const CUT_BUTTON_LABEL = "Cortar";
47 | const PASTE_BUTTON_LABEL = "Colar";
48 | const RESET_CLIPBOARD_BUTTON_LABEL = "Repor área de transferência";
49 | const EXTRACT_BUTTON_LABEL = "Extrair";
50 | const HIGHLIGHT_ALL_BUTTON_LABEL = "Selecionar tudo";
51 | const RENAME_BUTTON_LABEL = "Renomear";
52 | const DELETE_BUTTON_LABEL = "Eliminar";
53 | const ABORT_DOWNLOAD_BUTTON_LABEL = "✕";
54 | const DIALOG_RESET_BUTTON_LABEL = "Repor";
55 | const DIALOG_CANCEL_BUTTON_LABEL = "Cancelar";
56 | const DIALOG_OK_BUTTON_LABEL = "OK";
57 | const ERROR_TITLE = "Erro";
58 |
59 | const EXPORT_ZIP_TITLE = "Exportar ficheiro zip";
60 | const EXPORT_ZIP_FILENAME_LABEL = "Nome do ficheiro:";
61 | const EXPORT_ZIP_PASSWORD_LABEL = "Palavra-passe:";
62 | const EXPORT_ZIP_DIALOG_BUTTON_LABEL = "Exportar";
63 | const EXTRACT_TITLE = "Extrair ficheiro";
64 | const EXTRACT_FILENAME_LABEL = "Nome do ficheiro:";
65 | const EXTRACT_DIALOG_BUTTON_LABEL = "Extrair";
66 | const RENAME_TITLE = "Renomear entrada";
67 | const RENAME_FILENAME_LABEL = "Novo nome da entrada:";
68 | const RENAME_DIALOG_BUTTON_LABEL = "Renomear";
69 | const CREATE_FOLDER_TITLE = "Criar diretório";
70 | const CREATE_FOLDER_NAME_LABEL = "Nome do diretório:";
71 | const CREATE_FOLDER_DIALOG_BUTTON_LABEL = "Criar";
72 | const RESET_TITLE = "Repor sistema de ficheiros";
73 | const RESET_MESSAGE = "Por favor confirme a reposição do sistema de ficheiros.";
74 | const RESET_DIALOG_BUTTON_LABEL = "Repor";
75 | const DELETE_ENTRIES_TITLE = "Eliminar entradas";
76 | const DELETE_ENTRIES_MESSAGE =
77 | "Por favor confirme a eliminação das entradas selecionadas.";
78 | const DELETE_ENTRIES_DIALOG_BUTTON_LABEL = "Eliminar";
79 | const ZIP_FILE_DESCRIPTION_LABEL = "Ficheiro zip";
80 | const IMPORT_PASSWORD_TITLE = "Introduzir palavra-passe";
81 | const IMPORT_PASSWORD_LABEL = "Palavra-passe:";
82 | const OPTIONS_DIALOG_BUTTON_LABEL = "Guardar";
83 | const OPTIONS_TITLE = "Opções";
84 | const OPTIONS_ZOOM_FACTOR_LABEL = "Fator de zoom (%):";
85 | const OPTIONS_HIDE_NAVIGATION_BAR_LABEL = "Esconder barra de navegação:";
86 | const OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL = "Esconder painel de downloads:";
87 | const OPTIONS_HIDE_INFOBAR_LABEL = "Esconder barra inferior:";
88 | const OPTIONS_SELECT_SKIN_LABEL = "Tema:";
89 | const OPTIONS_DEFAULT_SKIN_LABEL = "Padrão";
90 | const OPTIONS_DOS_SKIN_LABEL = "DOS";
91 | const OPTIONS_EXPORT_ZIP_PASSWORD_LABEL = "Pedir palavra-passe:";
92 | const OPTIONS_DEFAULT_PASSWORD_LABEL = "Palavra-passe padrão:";
93 | const OPTIONS_KEEP_ORDER_LABEL = "Manter ordem das entradas:";
94 | const OPTIONS_CHECK_SIGNATURE_LABEL = "Verificar assinatura dos dados:";
95 | const OPTIONS_BUFFERED_WRITE_LABEL = "Usar múltiplos núcleos:";
96 | const OPTIONS_MAX_WORKERS_LABEL = "Número de núcleos:";
97 | const OPTIONS_CHUNK_SIZE_LABEL = "Tamanho do bloco (kB):";
98 | const CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL = "Adicionar ficheiro";
99 | const CHOOSE_ACTION_TITLE = "Escolher ação";
100 | const CHOOSE_ACTION_LABEL =
101 | "Foi selecionado um ficheiro zip, por favor escolha a ação apropriada.";
102 | const NO_ENTRIES_LABEL = "Arraste e solte ficheiros e diretórios aqui";
103 | const INFO_LABEL = [
104 | "Código-fonte em ",
105 | " GitHub",
106 | " Criado com ",
107 | "♡",
108 | " em ",
109 | "Rennes"
110 | ];
111 | const CITY_URL = "https://pt.wikipedia.org/wiki/Rennes";
112 | const HIGHLIGHTED_ENTRIES_LABEL = "Comandos para entradas selecionadas";
113 | const DOWNLOADS_LABEL = "Painel de downloads";
114 | const ENTRIES_LABEL = "Entradas do diretório";
115 | const FOLDERS_LABEL = "Histórico de navegação";
116 | const SELECTED_FOLDER_LABEL = "Comandos para diretório selecionado";
117 | const GO_INTO_FOLDER_LABEL = "Entrar no diretório";
118 | const GO_BACK_LABEL = "Voltar";
119 | const GO_FORWARD_LABEL = "Avançar";
120 | const ACCENT_COLOR_LABEL = "Cor de destaque";
121 | const PLAYING_MUSIC_ICON = "▶";
122 | const PAUSED_MUSIC_ICON = "II";
123 |
124 | export {
125 | ROOT_ZIP_FILENAME,
126 | SHORTCUT_LABEL,
127 | CTRL_KEY_LABEL,
128 | SPACE_KEY_LABEL,
129 | ARROW_LEFT_KEY_LABEL,
130 | ARROW_RIGHT_KEY_LABEL,
131 | PARENT_FOLDER_TOOLTIP,
132 | CREATE_FOLDER_BUTTON_TOOLTIP,
133 | ADD_FILES_BUTTON_TOOLTIP,
134 | IMPORT_ZIP_BUTTON_TOOLTIP,
135 | EXPORT_ZIP_BUTTON_TOOLTIP,
136 | BACK_BUTTON_TOOLTIP,
137 | FORWARD_BUTTON_TOOLTIP,
138 | COPY_BUTTON_TOOLTIP,
139 | CUT_BUTTON_TOOLTIP,
140 | PASTE_BUTTON_TOOLTIP,
141 | EXTRACT_BUTTON_TOOLTIP,
142 | HIGHLIGHT_ALL_BUTTON_TOOLTIP,
143 | RENAME_BUTTON_TOOLTIP,
144 | DELETE_BUTTON_TOOLTIP,
145 | ROOT_FOLDER_LABEL,
146 | PARENT_FOLDER_LABEL,
147 | COPY_BUTTON_LABEL,
148 | CUT_BUTTON_LABEL,
149 | PASTE_BUTTON_LABEL,
150 | RESET_CLIPBOARD_BUTTON_LABEL,
151 | EXTRACT_BUTTON_LABEL,
152 | HIGHLIGHT_ALL_BUTTON_LABEL,
153 | RENAME_BUTTON_LABEL,
154 | DELETE_BUTTON_LABEL,
155 | ABORT_DOWNLOAD_BUTTON_LABEL,
156 | DOWNLOAD_BUTTON_LABEL,
157 | ENTER_FOLDER_BUTTON_LABEL,
158 | BACK_BUTTON_LABEL,
159 | FORWARD_BUTTON_LABEL,
160 | CREATE_FOLDER_BUTTON_LABEL,
161 | ADD_FILES_BUTTON_LABEL,
162 | IMPORT_ZIP_BUTTON_LABEL,
163 | EXPORT_ZIP_BUTTON_LABEL,
164 | RESET_BUTTON_LABEL,
165 | OPTIONS_BUTTON_LABEL,
166 | KEYS_SEPARATOR_LABEL,
167 | ZIP_FILE_DESCRIPTION_LABEL,
168 | SIZE_LABEL,
169 | UNCOMPRESSED_SIZE_LABEL,
170 | COMPRESSED_SIZE_LABEL,
171 | LAST_MOD_DATE_LABEL,
172 | EXPORT_ZIP_TITLE,
173 | EXPORT_ZIP_FILENAME_LABEL,
174 | EXPORT_ZIP_PASSWORD_LABEL,
175 | DIALOG_OK_BUTTON_LABEL,
176 | DIALOG_CANCEL_BUTTON_LABEL,
177 | EXTRACT_TITLE,
178 | EXTRACT_FILENAME_LABEL,
179 | RENAME_TITLE,
180 | RENAME_FILENAME_LABEL,
181 | EXPORT_ZIP_DIALOG_BUTTON_LABEL,
182 | RENAME_DIALOG_BUTTON_LABEL,
183 | EXTRACT_DIALOG_BUTTON_LABEL,
184 | CREATE_FOLDER_TITLE,
185 | CREATE_FOLDER_NAME_LABEL,
186 | CREATE_FOLDER_DIALOG_BUTTON_LABEL,
187 | RESET_TITLE,
188 | RESET_MESSAGE,
189 | RESET_DIALOG_BUTTON_LABEL,
190 | DELETE_ENTRIES_TITLE,
191 | DELETE_ENTRIES_MESSAGE,
192 | DELETE_ENTRIES_DIALOG_BUTTON_LABEL,
193 | ERROR_TITLE,
194 | IMPORT_PASSWORD_TITLE,
195 | IMPORT_PASSWORD_LABEL,
196 | DIALOG_RESET_BUTTON_LABEL,
197 | OPTIONS_TITLE,
198 | OPTIONS_DIALOG_BUTTON_LABEL,
199 | OPTIONS_ZOOM_FACTOR_LABEL,
200 | OPTIONS_HIDE_NAVIGATION_BAR_LABEL,
201 | OPTIONS_HIDE_DOWNLOAD_MANAGER_LABEL,
202 | OPTIONS_HIDE_INFOBAR_LABEL,
203 | OPTIONS_DEFAULT_SKIN_LABEL,
204 | OPTIONS_DOS_SKIN_LABEL,
205 | OPTIONS_SELECT_SKIN_LABEL,
206 | OPTIONS_EXPORT_ZIP_PASSWORD_LABEL,
207 | OPTIONS_DEFAULT_PASSWORD_LABEL,
208 | OPTIONS_KEEP_ORDER_LABEL,
209 | OPTIONS_CHECK_SIGNATURE_LABEL,
210 | OPTIONS_BUFFERED_WRITE_LABEL,
211 | OPTIONS_MAX_WORKERS_LABEL,
212 | OPTIONS_CHUNK_SIZE_LABEL,
213 | CHOOSE_ACTION_DIALOG_ADD_FILE_BUTTON_LABEL,
214 | CHOOSE_ACTION_TITLE,
215 | CHOOSE_ACTION_LABEL,
216 | NO_ENTRIES_LABEL,
217 | INFO_LABEL,
218 | CITY_URL,
219 | HIGHLIGHTED_ENTRIES_LABEL,
220 | DOWNLOADS_LABEL,
221 | ENTRIES_LABEL,
222 | FOLDERS_LABEL,
223 | SELECTED_FOLDER_LABEL,
224 | GO_INTO_FOLDER_LABEL,
225 | GO_BACK_LABEL,
226 | GO_FORWARD_LABEL,
227 | ACCENT_COLOR_LABEL,
228 | PLAYING_MUSIC_ICON,
229 | PAUSED_MUSIC_ICON
230 | };
231 |
--------------------------------------------------------------------------------
/src/zip-manager/services/document-service.js:
--------------------------------------------------------------------------------
1 | /* global document, getComputedStyle, ResizeObserver */
2 |
3 | function scrollIntoView(element) {
4 | element.scrollIntoView({ block: "nearest" });
5 | }
6 |
7 | function getHeight(element) {
8 | return element.offsetHeight;
9 | }
10 |
11 | function getRowHeight(element) {
12 | const rowGap = parseInt(getComputedStyle(element.parentElement).rowGap, 10);
13 | return getHeight(element) + (Number.isNaN(rowGap) ? 0 : rowGap);
14 | }
15 |
16 | function removeDocumentAttribute(name) {
17 | document.documentElement.removeAttribute(name);
18 | }
19 |
20 | function addResizeObserver(element, listener) {
21 | const observer = new ResizeObserver(listener);
22 | observer.observe(element, { attributes: true });
23 | return observer;
24 | }
25 |
26 | function setDocumentLanguage(language) {
27 | document.documentElement.lang = language;
28 | }
29 |
30 | export {
31 | getHeight,
32 | getRowHeight,
33 | scrollIntoView,
34 | removeDocumentAttribute,
35 | addResizeObserver,
36 | setDocumentLanguage
37 | };
38 |
--------------------------------------------------------------------------------
/src/zip-manager/services/download-service.js:
--------------------------------------------------------------------------------
1 | /* global AbortController */
2 |
3 | const ABORT_ERROR_NAME = "AbortError";
4 | const CANCELLED_DOWNLOAD_MESSAGE = "download cancelled";
5 |
6 | function createAbortController() {
7 | return new AbortController();
8 | }
9 |
10 | function abortDownload(controller) {
11 | controller.abort(new Error(CANCELLED_DOWNLOAD_MESSAGE));
12 | }
13 |
14 | function downloadAborted(error) {
15 | const message = error.message || error;
16 | return (
17 | message === CANCELLED_DOWNLOAD_MESSAGE || error.name === ABORT_ERROR_NAME
18 | );
19 | }
20 |
21 | export { createAbortController, abortDownload, downloadAborted };
22 |
--------------------------------------------------------------------------------
/src/zip-manager/services/environment-service.js:
--------------------------------------------------------------------------------
1 | /* global navigator */
2 |
3 | const MACOS_PLATFORMS = ["Macintosh", "MacIntel", "MacPPC", "Mac68K"];
4 |
5 | function getMaximumWorkers() {
6 | return navigator.hardwareConcurrency;
7 | }
8 |
9 | function isMacOSPlatform() {
10 | const { platform } = navigator;
11 | return platform !== undefined && MACOS_PLATFORMS.includes(platform);
12 | }
13 |
14 | export { getMaximumWorkers, isMacOSPlatform };
15 |
--------------------------------------------------------------------------------
/src/zip-manager/services/file-handlers-service.js:
--------------------------------------------------------------------------------
1 | /* global window, launchQueue */
2 |
3 | function onOpenWith(callback) {
4 | if ("launchQueue" in window) {
5 | launchQueue.setConsumer((launchParams) => {
6 | getLaunchQueueConsumer(launchParams, callback);
7 | });
8 | }
9 | }
10 |
11 | async function getLaunchQueueConsumer(launchParams, callback) {
12 | if (launchParams.files.length) {
13 | await Promise.all(
14 | launchParams.files.map(async (handle) => callback(await handle.getFile()))
15 | );
16 | }
17 | }
18 |
19 | export { onOpenWith };
20 |
--------------------------------------------------------------------------------
/src/zip-manager/services/filesystem-service.js:
--------------------------------------------------------------------------------
1 | /* global window, document, URL */
2 |
3 | const FILESYSTEM_FILE_KIND = "file";
4 | const ABORT_ERROR_NAME = "AbortError";
5 |
6 | async function showOpenFilePicker({ multiple, description, accept } = {}) {
7 | const excludeAcceptAllOption = Boolean(accept);
8 | if ("showOpenFilePicker" in window) {
9 | try {
10 | const options = {
11 | excludeAcceptAllOption,
12 | multiple
13 | };
14 | if (excludeAcceptAllOption) {
15 | Object.assign(options, {
16 | types: [
17 | {
18 | description,
19 | accept
20 | }
21 | ]
22 | });
23 | }
24 | const fileHandles = await window.showOpenFilePicker(options);
25 | return Promise.all(fileHandles.map((fileHandle) => fileHandle.getFile()));
26 | } catch (error) {
27 | if (error.name === ABORT_ERROR_NAME) {
28 | return [];
29 | } else {
30 | throw error;
31 | }
32 | }
33 | } else {
34 | const fileInputElement = document.createElement("input");
35 | Object.assign(fileInputElement, {
36 | type: "file",
37 | accept: accept ? Object.keys(accept).join(",") : "",
38 | multiple
39 | });
40 | return new Promise((resolve) => {
41 | fileInputElement.onchange = ({ target }) => {
42 | if (target.files.length) {
43 | resolve(Array.from(target.files));
44 | }
45 | };
46 | fileInputElement.click();
47 | });
48 | }
49 | }
50 |
51 | function showDirectoryPicker(options) {
52 | return window.showDirectoryPicker(options);
53 | }
54 |
55 | function showSaveFilePicker(options) {
56 | return window.showSaveFilePicker(options);
57 | }
58 |
59 | function savePickersSupported() {
60 | return "showSaveFilePicker" in window && "showDirectoryPicker" in window;
61 | }
62 |
63 | function saveBlob(blob, filename) {
64 | const href = URL.createObjectURL(blob);
65 | const anchorElement = document.createElement("a");
66 | Object.assign(anchorElement, { href, download: filename });
67 | anchorElement.click();
68 | URL.revokeObjectURL(href);
69 | }
70 |
71 | export {
72 | FILESYSTEM_FILE_KIND,
73 | showOpenFilePicker,
74 | showDirectoryPicker,
75 | savePickersSupported,
76 | showSaveFilePicker,
77 | saveBlob
78 | };
79 |
--------------------------------------------------------------------------------
/src/zip-manager/services/i18n-service.js:
--------------------------------------------------------------------------------
1 | /* global navigator */
2 |
3 | const DEFAULT_LANGUAGE_ID = "en-US";
4 | const LANGUAGE_IDS = [DEFAULT_LANGUAGE_ID, "de-DE", "es-ES", "fr-FR", "it-IT", "pt-PT"];
5 |
6 | const SIZE_NUMBER_FORMATS = [
7 | "kilobyte",
8 | "megabyte",
9 | "gigabyte",
10 | "terabyte",
11 | "petabyte"
12 | ].map(
13 | (unit) =>
14 | new Intl.NumberFormat(getLanguageId(), {
15 | style: "unit",
16 | maximumFractionDigits: 1,
17 | unit
18 | })
19 | );
20 | const DATE_TIME_FORMAT = new Intl.DateTimeFormat(getLanguageId(), {
21 | dateStyle: "short",
22 | timeStyle: "short"
23 | });
24 | const PERCENT_VALUE_FORMAT = new Intl.NumberFormat(getLanguageId(), {
25 | style: "unit",
26 | maximumFractionDigits: 0,
27 | unit: "percent"
28 | });
29 |
30 | function formatSize(number) {
31 | let indexNumberFormat = 0;
32 | number = number / 1000;
33 | while (number > 1000 && indexNumberFormat < SIZE_NUMBER_FORMATS.length - 1) {
34 | number = number / 1000;
35 | indexNumberFormat++;
36 | }
37 | return SIZE_NUMBER_FORMATS[indexNumberFormat].format(number);
38 | }
39 |
40 | function formatDate(date) {
41 | return DATE_TIME_FORMAT.format(date);
42 | }
43 |
44 | function formatPercentValue(value) {
45 | return PERCENT_VALUE_FORMAT.format(value);
46 | }
47 |
48 | function getLanguageId() {
49 | return LANGUAGE_IDS.includes(navigator.language)
50 | ? navigator.language
51 | : DEFAULT_LANGUAGE_ID;
52 | }
53 |
54 | export { formatSize, formatDate, formatPercentValue, getLanguageId };
55 |
--------------------------------------------------------------------------------
/src/zip-manager/services/index.js:
--------------------------------------------------------------------------------
1 | import * as filesystemService from "./filesystem-service.js";
2 | import * as downloadService from "./download-service.js";
3 | import * as i18nService from "./i18n-service.js";
4 | import * as storageService from "./storage-service.js";
5 | import * as zipService from "./zip-service.js";
6 | import * as shareTargetService from "./share-target-service.js";
7 | import * as fileHandlersService from "./file-handlers-service.js";
8 | import * as stylesheetService from "./stylesheet-service.js";
9 | import * as environmentService from "./environment-service.js";
10 | import * as keyboardService from "./keyboard-service.js";
11 | import * as themeService from "./theme-service.js";
12 | import * as documentService from "./document-service.js";
13 | import * as windowService from "./window-service.js";
14 | import * as musicService from "./music-service.js";
15 |
16 | export {
17 | filesystemService,
18 | downloadService,
19 | i18nService,
20 | storageService,
21 | zipService,
22 | shareTargetService,
23 | fileHandlersService,
24 | stylesheetService,
25 | environmentService,
26 | keyboardService,
27 | themeService,
28 | documentService,
29 | windowService,
30 | musicService
31 | };
32 |
--------------------------------------------------------------------------------
/src/zip-manager/services/keyboard-service.js:
--------------------------------------------------------------------------------
1 | /* global addEventListener, removeEventListener */
2 |
3 | const KEYUP_EVENT_NAME = "keyup";
4 | const KEYDOWN_EVENT_NAME = "keydown";
5 |
6 | function addKeyUpListener(listener) {
7 | addEventListener(KEYUP_EVENT_NAME, listener);
8 | }
9 |
10 | function removeKeyUpListener(listener) {
11 | removeEventListener(KEYUP_EVENT_NAME, listener);
12 | }
13 |
14 | function addKeyDownListener(listener) {
15 | addEventListener(KEYDOWN_EVENT_NAME, listener);
16 | }
17 |
18 | function removeKeyDownListener(listener) {
19 | removeEventListener(KEYDOWN_EVENT_NAME, listener);
20 | }
21 |
22 | export {
23 | addKeyUpListener,
24 | removeKeyUpListener,
25 | addKeyDownListener,
26 | removeKeyDownListener
27 | };
28 |
--------------------------------------------------------------------------------
/src/zip-manager/services/music-service-constants.js:
--------------------------------------------------------------------------------
1 | const MIDI_CONTENT_TYPE = "audio/midi";
2 | const XM_CONTENT_TYPE = "audio/xm";
3 | const SID_CONTENT_TYPE = "audio/prs.sid";
4 | const MUSIC_TRACK_PATH_PREFIX = "music-track-";
5 | const MUSIC_TRACK_PATH_REGEXP = new RegExp(MUSIC_TRACK_PATH_PREFIX + ".*");
6 | const MUSIC_TRACK_INDEX_REGEXP = /\d+$/;
7 | const MUSIC_TRACKS_PATH = "./assets/music/tracks.zip";
8 | const MIDI_FILE_EXTENSION = ".mid";
9 | const XM_FILE_EXTENSION = ".xm";
10 | const SID_FILE_EXTENSION = ".sid";
11 | const MUSIC_FILE_CONTENT_TYPES = [
12 | { extension: MIDI_FILE_EXTENSION, type: MIDI_CONTENT_TYPE },
13 | { extension: XM_FILE_EXTENSION, type: XM_CONTENT_TYPE },
14 | { extension: SID_FILE_EXTENSION, type: SID_CONTENT_TYPE }
15 | ];
16 |
17 | export {
18 | MIDI_CONTENT_TYPE,
19 | XM_CONTENT_TYPE,
20 | SID_CONTENT_TYPE,
21 | MUSIC_TRACK_PATH_PREFIX,
22 | MUSIC_TRACK_PATH_REGEXP,
23 | MUSIC_TRACK_INDEX_REGEXP,
24 | MUSIC_TRACKS_PATH,
25 | MUSIC_FILE_CONTENT_TYPES
26 | };
27 |
--------------------------------------------------------------------------------
/src/zip-manager/services/music-service.js:
--------------------------------------------------------------------------------
1 | /* global document, requestAnimationFrame, fetch */
2 |
3 | import WebAudioTinySynth from "./lib/webaudio-tinysynth/webaudio-tinysynth-core-es6.js";
4 | import * as libxm from "./lib/libxm/libxm-es6.js";
5 | import * as jsSID from "./lib/jsSID/jsSID.js";
6 |
7 | import {
8 | MUSIC_TRACK_PATH_PREFIX,
9 | MIDI_CONTENT_TYPE,
10 | XM_CONTENT_TYPE,
11 | SID_CONTENT_TYPE
12 | } from "./music-service-constants.js";
13 |
14 | const MUSIC_TRACK_RELATIVE_PATH_PREFIX = "./" + MUSIC_TRACK_PATH_PREFIX;
15 | const MUSIC_TRACKS_INFO = [
16 | { masterVolume: 0.1 },
17 | { masterVolume: 0.7 },
18 | { masterVolume: 0.4 },
19 | { masterVolume: 0.1 },
20 | { masterVolume: 1.2, track: 1 },
21 | { masterVolume: 1.8 },
22 | { masterVolume: 0.6 },
23 | { masterVolume: 0.8 },
24 | { masterVolume: 1.1 },
25 | { masterVolume: 0.5 },
26 | { masterVolume: 0.7 },
27 | { masterVolume: 0.7 }
28 | ];
29 |
30 | let trackIndex = Math.floor(Math.random() * MUSIC_TRACKS_INFO.length);
31 | let midiLibrary,
32 | xmLibrary,
33 | sidLibrary,
34 | musicLibrary,
35 | playing,
36 | analyser,
37 | byteFrequencyData,
38 | callbackFrequencyData,
39 | fftSize = 128;
40 |
41 | document.onvisibilitychange = () => {
42 | if (musicLibrary && playing) {
43 | if (document.hidden) {
44 | musicLibrary.pause();
45 | } else {
46 | musicLibrary.resume();
47 | requestAnimationFrame(getByteFrequencyData);
48 | }
49 | }
50 | };
51 |
52 | async function init({ data, contentType, masterVolume, track }) {
53 | musicLibrary = null;
54 | if (contentType === MIDI_CONTENT_TYPE) {
55 | initMIDI();
56 | } else if (contentType === XM_CONTENT_TYPE) {
57 | await initXM();
58 | } else if (contentType === SID_CONTENT_TYPE) {
59 | initSID();
60 | }
61 | if (musicLibrary) {
62 | musicLibrary.play({ data, masterVolume, track });
63 | initAnalyser(fftSize);
64 | }
65 | }
66 |
67 | function initMIDI() {
68 | if (!midiLibrary) {
69 | midiLibrary = new WebAudioTinySynth({ quality: 1, useReverb: 1 });
70 | midiLibrary.setLoop(true);
71 | midiLibrary.setTimbre(1, 49, [
72 | { w: "n0", f: 150, v: 0.2, d: 0.1, r: 0.1, h: 0.05, t: 0, p: 0.1 }
73 | ]);
74 | midiLibrary.setTimbre(1, 53, [
75 | { w: "n0", f: 440, v: 0.3, d: 0.1, p: 0.9, t: 0, r: 0.1 }
76 | ]);
77 | midiLibrary.setTimbre(0, 28, [
78 | { w: "sine", v: 0.8, d: 1, f: -1 },
79 | { w: "triangle", v: 4, f: 1, d: 0.4, s: 0.5, g: 1, t: 3 }
80 | ]);
81 | midiLibrary.setTimbre(0, 38, [
82 | { w: "sine", v: 0.6, d: 0.3 },
83 | { w: "triangle", v: 4, f: 1, d: 0.4, s: 0.5, g: 1, t: 3 },
84 | { w: "sawtooth", v: 0.1, a: 0.03, d: 0.5, s: 0.3, r: 0.2 }
85 | ]);
86 | midiLibrary.setTimbre(0, 39, [
87 | { w: "sine", v: 0.5, d: 0.3 },
88 | { w: "square", v: 3, f: -1, d: 1, s: 0.7, g: 1 },
89 | { w: "sawtooth", v: 0.1, a: 0.03, d: 0.6, s: 0.3, r: 0.2 }
90 | ]);
91 | }
92 | musicLibrary = midiLibrary;
93 | }
94 |
95 | async function initXM() {
96 | if (!xmLibrary) {
97 | await libxm.init();
98 | xmLibrary = libxm;
99 | }
100 | musicLibrary = xmLibrary;
101 | }
102 |
103 | function initSID() {
104 | if (!sidLibrary) {
105 | jsSID.init();
106 | }
107 | musicLibrary = jsSID;
108 | }
109 |
110 | function initAnalyser() {
111 | analyser = musicLibrary.audioContext.createAnalyser();
112 | musicLibrary.out.connect(analyser);
113 | analyser.fftSize = fftSize;
114 | byteFrequencyData = new Uint8Array(analyser.frequencyBinCount);
115 | }
116 |
117 | async function play({ onSetFrequencyData }) {
118 | const response = await fetch(
119 | MUSIC_TRACK_RELATIVE_PATH_PREFIX + (trackIndex + 1)
120 | );
121 | const blob = await response.blob();
122 | const contentType = blob.type;
123 | const data = await blob.arrayBuffer();
124 | const { masterVolume, track } = MUSIC_TRACKS_INFO[trackIndex];
125 | trackIndex = (trackIndex + 1) % MUSIC_TRACKS_INFO.length;
126 | await init({ data, contentType, masterVolume, track });
127 | playing = true;
128 | callbackFrequencyData = onSetFrequencyData;
129 | if (musicLibrary) {
130 | requestAnimationFrame(getByteFrequencyData);
131 | }
132 | return {};
133 | }
134 |
135 | function getByteFrequencyData() {
136 | analyser.getByteFrequencyData(byteFrequencyData);
137 | if (callbackFrequencyData) {
138 | callbackFrequencyData(Array.from(byteFrequencyData));
139 | }
140 | if (playing && !document.hidden) {
141 | requestAnimationFrame(getByteFrequencyData);
142 | }
143 | }
144 |
145 | function stop() {
146 | playing = false;
147 | if (musicLibrary) {
148 | musicLibrary.pause();
149 | }
150 | }
151 |
152 | function setFftSize(value) {
153 | fftSize = value;
154 | if (analyser) {
155 | initAnalyser();
156 | }
157 | }
158 |
159 | export { play, stop, setFftSize };
160 |
--------------------------------------------------------------------------------
/src/zip-manager/services/share-target-service-constants.js:
--------------------------------------------------------------------------------
1 | const CURRENT_PATH = ".";
2 | const MAINPAGE_PATH = "/index.html";
3 | const MAINPAGE_RELATIVE_PATH = CURRENT_PATH + MAINPAGE_PATH;
4 | const SHARED_FILES_PARAMETER = "?shared-files";
5 | const MAINPAGE_REDIRECT_PATH = MAINPAGE_RELATIVE_PATH + SHARED_FILES_PARAMETER;
6 | const SHARED_FILES_PATH = "/shared-files";
7 | const SHARED_FILES_RELATIVE_PATH = CURRENT_PATH + SHARED_FILES_PATH;
8 | const SHARED_FILES_FORM_PATH = SHARED_FILES_PATH + "/form";
9 | const SHARED_FILES_CACHE_ID = "shared-files";
10 | const SHARED_FILES_FIELD_NAME = "shared-files";
11 |
12 | export {
13 | SHARED_FILES_PARAMETER,
14 | MAINPAGE_REDIRECT_PATH,
15 | SHARED_FILES_RELATIVE_PATH,
16 | SHARED_FILES_FORM_PATH,
17 | SHARED_FILES_CACHE_ID,
18 | SHARED_FILES_FIELD_NAME
19 | };
20 |
--------------------------------------------------------------------------------
/src/zip-manager/services/share-target-service.js:
--------------------------------------------------------------------------------
1 | /* global fetch, location, history */
2 |
3 | import {
4 | SHARED_FILES_PARAMETER,
5 | SHARED_FILES_RELATIVE_PATH,
6 | SHARED_FILES_FIELD_NAME
7 | } from "./share-target-service-constants.js";
8 |
9 | async function onShareFiles(callback) {
10 | const locationSearch = getLocationSearch();
11 | if (locationSearch) {
12 | resetLocationSearch();
13 | if (locationSearch === SHARED_FILES_PARAMETER) {
14 | const sharedFilesPath = SHARED_FILES_RELATIVE_PATH;
15 | const response = await fetch(sharedFilesPath);
16 | const formData = await response.formData();
17 | callback(formData.getAll(SHARED_FILES_FIELD_NAME));
18 | }
19 | }
20 | }
21 |
22 | function getLocationSearch() {
23 | return location.search;
24 | }
25 |
26 | function resetLocationSearch() {
27 | return history.replaceState(null, null, location.pathname);
28 | }
29 |
30 | export { onShareFiles };
31 |
--------------------------------------------------------------------------------
/src/zip-manager/services/storage-service.js:
--------------------------------------------------------------------------------
1 | /* global localStorage */
2 |
3 | function setValue(key, value) {
4 | localStorage.setItem(key, JSON.stringify(value));
5 | }
6 |
7 | function getValue(key) {
8 | const value = localStorage.getItem(key);
9 | try {
10 | return JSON.parse(value);
11 | // eslint-disable-next-line no-unused-vars
12 | } catch (error) {
13 | return value;
14 | }
15 | }
16 |
17 | export { setValue as set, getValue as get };
18 |
--------------------------------------------------------------------------------
/src/zip-manager/services/stylesheet-service.js:
--------------------------------------------------------------------------------
1 | /* global document */
2 |
3 | const styleElement = document.createElement("style");
4 | document.head.appendChild(styleElement);
5 |
6 | function setStyle(name, value) {
7 | const rule = Array.from(styleElement.sheet.rules).find((rule) =>
8 | rule.style.getPropertyValue(name)
9 | );
10 | if (rule) {
11 | rule.style.setProperty(name, value);
12 | } else {
13 | styleElement.sheet.insertRule(":root { " + name + ": " + value + "}");
14 | }
15 | }
16 |
17 | export { setStyle };
18 |
--------------------------------------------------------------------------------
/src/zip-manager/services/theme-service.js:
--------------------------------------------------------------------------------
1 | /* global document */
2 |
3 | const ACCENT_COLOR_CUSTOM_PROPERTY_NAME = "--accent-color";
4 |
5 | function setTheme({ accentColor, skin }) {
6 | const documentClasses = [skin];
7 | const brightNessAccentColor = getBrightNess(accentColor);
8 | if (brightNessAccentColor > 224) {
9 | documentClasses.push("dark");
10 | } else if (brightNessAccentColor < 32) {
11 | documentClasses.push("light");
12 | }
13 | document.documentElement.className = documentClasses.join(" ");
14 | }
15 |
16 | function getBrightNess(color) {
17 | const red = parseInt(color.substring(1, 3), 16);
18 | const green = parseInt(color.substring(3, 5), 16);
19 | const blue = parseInt(color.substring(5, 7), 16);
20 | // cf. https://www.w3.org/TR/AERT/#color-contrast
21 | return Math.round((red * 299 + green * 587 + blue * 114) / 1000);
22 | }
23 |
24 | export { ACCENT_COLOR_CUSTOM_PROPERTY_NAME, setTheme };
25 |
--------------------------------------------------------------------------------
/src/zip-manager/services/window-service.js:
--------------------------------------------------------------------------------
1 | /* global addEventListener, removeEventListener */
2 |
3 | const RESIZE_EVENT_NAME = "resize";
4 | const BEFORE_UNLOAD_EVENT_NAME = "beforeunload";
5 |
6 | function addUnloadListener(listener) {
7 | addEventListener(BEFORE_UNLOAD_EVENT_NAME, listener);
8 | }
9 |
10 | function removeUnloadListener(listener) {
11 | removeEventListener(BEFORE_UNLOAD_EVENT_NAME, listener);
12 | }
13 |
14 | function addResizeListener(listener) {
15 | addEventListener(RESIZE_EVENT_NAME, listener);
16 | }
17 |
18 | function removeResizeListener(listener) {
19 | removeEventListener(RESIZE_EVENT_NAME, listener);
20 | }
21 |
22 | export {
23 | addUnloadListener,
24 | removeUnloadListener,
25 | addResizeListener,
26 | removeResizeListener
27 | };
28 |
--------------------------------------------------------------------------------
/src/zip-manager/services/zip-service.js:
--------------------------------------------------------------------------------
1 | import { fs, configure } from "@zip.js/zip.js";
2 |
3 | const { FS } = fs;
4 |
5 | function createZipFileSystem() {
6 | return new FS();
7 | }
8 |
9 | export { createZipFileSystem, configure };
10 |
--------------------------------------------------------------------------------
/src/zip-manager/styles/ButtonBar.css:
--------------------------------------------------------------------------------
1 | .button-bar,
2 | .button-bar .button-group {
3 | display: flex;
4 | flex-wrap: wrap;
5 | row-gap: var(--gap-block-size);
6 | }
7 |
8 | .button-bar {
9 | column-gap: var(--gap-inline-size);
10 | }
11 |
12 | .button-bar .button-group {
13 | column-gap: var(--small-gap-inline-size);
14 | }
15 |
16 | .button-bar button:not([disabled]) {
17 | cursor: pointer;
18 | }
--------------------------------------------------------------------------------
/src/zip-manager/styles/Dialog.css:
--------------------------------------------------------------------------------
1 | dialog::backdrop {
2 | background-color: var(--basic-bg-color);
3 | opacity: 0.85;
4 | }
5 |
6 | dialog {
7 | margin-block-start: var(--dialog-margin-block-start);
8 | inline-size: var(--dialog-width);
9 | background-color: var(--page-color);
10 | color: var(--text-color);
11 | border: solid var(--accent-color) var(--large-border-width);
12 | border-radius: var(--border-radius-width);
13 | padding-inline: var(--large-gap-inline-size);
14 | padding-block: var(--large-gap-block-size);
15 | }
16 |
17 | dialog:focus {
18 | outline-width: 0;
19 | }
20 |
21 | dialog input,
22 | dialog select {
23 | background-color: var(--bg-color);
24 | color: var(--text-color);
25 | border: solid var(--accent-color) var(--border-width);
26 | block-size: 1.5em;
27 | padding-inline: var(--gap-inline-size);
28 | font-family: inherit;
29 | margin: var(--outline-width);
30 | border-radius: var(--border-radius-width);
31 | box-sizing: content-box;
32 | caret-color: var(--accent-color);
33 | align-self: baseline;
34 | inline-size: calc(100% - 2 * (var(--gap-inline-size) + var(--border-width) + var(--outline-width)));
35 | align-self: end;
36 | }
37 |
38 | dialog form,
39 | dialog form p,
40 | dialog label {
41 | display: flex;
42 | flex-direction: column;
43 | }
44 |
45 | dialog form,
46 | dialog form p {
47 | row-gap: var(--large-gap-block-size);
48 | }
49 |
50 | dialog form {
51 | max-block-size: var(--dialog-form-max-block-size);
52 | }
53 |
54 | dialog form .dialog-title {
55 | font-weight: var(--font-weight-bolder);
56 | border-block-end: solid var(--accent-color) var(--border-width);
57 | padding-block-end: var(--large-gap-block-size);
58 | }
59 |
60 | dialog form p {
61 | margin: 0;
62 | padding-block-start: var(--small-gap-block-size);
63 | padding-block-end: var(--large-gap-block-size);
64 | overflow: visible auto;
65 | }
66 |
67 | dialog label {
68 | row-gap: var(--gap-block-size);
69 | overflow: visible;
70 | }
71 |
72 | dialog .button-bar {
73 | margin-block-start: var(--gap-block-size);
74 | }
75 |
76 | dialog .button-group:first-of-type {
77 | flex: 1;
78 | }
--------------------------------------------------------------------------------
/src/zip-manager/styles/ListItem.css:
--------------------------------------------------------------------------------
1 | .list-item-button {
2 | font-family: monospace;
3 | cursor: pointer;
4 | user-select: none;
5 | }
6 |
7 | .list-item-button:hover {
8 | filter: brightness(var(--brightness-hover));
9 | }
10 |
11 | .list-item-name {
12 | overflow-x: hidden;
13 | overflow-inline: hidden;
14 | text-overflow: ellipsis;
15 | white-space: nowrap;
16 | }
--------------------------------------------------------------------------------
/src/zip-manager/styles/Skins.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "DOS-VGA-437";
3 | src: url("/assets/fonts/dos-vga-9x16.ttf");
4 | font-display: swap;
5 | }
6 |
7 | .skin-dos {
8 | --gap-inline-size: 2ch;
9 | --gap-block-size: calc(1em * 1.25);
10 | --border-width: 0;
11 | --button-padding-inline-size: var(--gap-inline-size);
12 | --button-padding-block-size: 0;
13 | --border-radius-width: 0;
14 | --list-item-padding-inline-size: 0;
15 | --list-item-padding-block-size: 0;
16 | --outline-color: var(--accent-color);
17 | --outline-width: 0;
18 | --dialog-margin-block-start: calc(var(--gap-block-size) + var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
19 | }
20 |
21 | .skin-dos * {
22 | line-height: 1.25;
23 | }
24 |
25 | .skin-dos body {
26 | font-family: "DOS-VGA-437", monospace;
27 | }
28 |
29 | .skin-dos body::after {
30 | top: 0;
31 | left: 0;
32 | width: 100%;
33 | height: 100%;
34 | }
35 |
36 | .skin-dos dialog[open] form::after {
37 | top: calc(-1 * var(--smaller-gap-inline-size));
38 | left: calc(-1 * var(--smaller-gap-block-size));
39 | width: calc(100% + 2 * var(--small-gap-inline-size));
40 | height: calc(100% + 2 * var(--small-gap-block-size));
41 | }
42 |
43 | .skin-dos main,
44 | .skin-dos dialog {
45 | position: relative;
46 | overflow: visible;
47 | border-width: var(--smaller-gap-block-size) var(--smaller-gap-inline-size);
48 | }
49 |
50 | .skin-dos main::before,
51 | .skin-dos dialog::before,
52 | .skin-dos main:after,
53 | .skin-dos dialog::after {
54 | position: absolute;
55 | content: "";
56 | background-color: var(--darker-accent-color);
57 | }
58 |
59 | .skin-dos main::before {
60 | top: var(--smaller-gap-block-size);
61 | right: calc(-1 * var(--smaller-gap-inline-size) - var(--small-gap-inline-size));
62 | inline-size: var(--small-gap-inline-size);
63 | block-size: calc(100% + var(--small-gap-block-size) - var(--smaller-gap-block-size) + var(--smaller-gap-block-size) / 2);
64 | }
65 |
66 | .skin-dos main:after {
67 | left: var(--smaller-gap-inline-size);
68 | bottom: calc(-1 * var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
69 | inline-size: calc(100% + var(--small-gap-inline-size));
70 | block-size: calc(var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
71 | }
72 |
73 | .skin-dos dialog::before {
74 | right: calc(-1 * var(--smaller-gap-inline-size) - var(--small-gap-inline-size));
75 | inline-size: var(--small-gap-inline-size);
76 | block-size: calc(100% + var(--small-gap-block-size) - var(--smaller-gap-block-size));
77 | }
78 |
79 | .skin-dos dialog::after {
80 | left: var(--smaller-gap-inline-size);
81 | bottom: calc(-1 * var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
82 | inline-size: calc(100% + var(--small-gap-inline-size));
83 | block-size: calc(var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
84 | }
85 |
86 | .skin-dos main {
87 | margin-block-start: calc(var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
88 | min-inline-size: min(85dvw, 132ch);
89 | inline-size: min(85dvw, 132ch);
90 | inline-size: min(round(up, 85dvw, 1ch), 132ch);
91 | }
92 |
93 | .skin-dos main,
94 | .skin-dos main>*,
95 | .skin-dos dialog {
96 | border-style: double;
97 | }
98 |
99 | .skin-dos main>* {
100 | padding-inline: var(--smaller-gap-inline-size);
101 | padding-block: calc(var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
102 | border-block-end-width: var(--smaller-gap-block-size);
103 | }
104 |
105 | .skin-dos button {
106 | margin: 0;
107 | }
108 |
109 | .skin-dos button:focus {
110 | filter: brightness(var(--brightness-hover));
111 | outline-width: 0;
112 | }
113 |
114 | .skin-dos .scrollable::-webkit-scrollbar {
115 | inline-size: var(--small-gap-inline-size);
116 | background-color: var(--bg-disabled-button-color);
117 | }
118 |
119 | .skin-dos .scrollable::-webkit-scrollbar-thumb,
120 | .skin-dos .scrollable::-webkit-scrollbar-track {
121 | border-radius: 0;
122 | }
123 |
124 | .skin-dos input[type="checkbox"] {
125 | font-family: "DOS-VGA-437", monospace;
126 | accent-color: var(--text-color);
127 | appearance: none;
128 | cursor: pointer;
129 | }
130 |
131 | .skin-dos input[type="checkbox"]:after {
132 | content: "[ ]";
133 | }
134 |
135 | .skin-dos input[type="checkbox"]:focus:after {
136 | background-color: var(--text-color);
137 | color: var(--bg-color);
138 | }
139 |
140 | .skin-dos input[type="checkbox"]:checked::after {
141 | content: "[■]";
142 | }
143 |
144 | .skin-dos .button-bar,
145 | .skin-dos .button-bar .button-group {
146 | row-gap: var(--small-gap-block-size);
147 | }
148 |
149 | .skin-dos .history-buttons button {
150 | font-family: "DOS-VGA-437", monospace;
151 | padding-inline: var(--button-padding-inline-size);
152 | }
153 |
154 | .skin-dos .navigation-bar {
155 | column-gap: var(--small-gap-inline-size);
156 | }
157 |
158 | .skin-dos .breadcrumb ol,
159 | .skin-dos .breadcrumb li,
160 | .skin-dos .entries .entry-name {
161 | column-gap: var(--small-gap-inline-size);
162 | }
163 |
164 | .skin-dos .breadcrumb .breadcrumb-item-active,
165 | .skin-dos .breadcrumb .breadcrumb-item-active:focus {
166 | text-decoration: underline var(--accent-color) var(--large-border-width);
167 | }
168 |
169 | .skin-dos .breadcrumb .breadcrumb-item {
170 | margin: 0;
171 | }
172 |
173 | .skin-dos .breadcrumb .breadcrumb-item-active:focus {
174 | outline: 0;
175 | filter: brightness(var(--brightness-hover));
176 | }
177 |
178 | .skin-dos .entries {
179 | padding-block-start: 0;
180 | margin-block-start: calc(var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
181 | }
182 |
183 | .skin-dos .entries li {
184 | column-gap: var(--small-gap-inline-size);
185 | }
186 |
187 | .skin-dos .entries .entry-select {
188 | color: var(--text-color);
189 | }
190 |
191 | .skin-dos .entries .entry-select:checked {
192 | color: var(--bg-color);
193 | }
194 |
195 | .skin-dos .entries .entry-select:focus:after {
196 | background-color: var(--bg-color);
197 | color: var(--text-color);
198 | }
199 |
200 | .skin-dos .entries .entry-select:checked:focus:after {
201 | background-color: var(--accent-color);
202 | color: var(--bg-color);
203 | }
204 |
205 | .skin-dos .info-bar {
206 | margin-block-end: 0;
207 | padding-block: var(--gap-block-size);
208 | min-block-size: var(--gap-block-size);
209 | font-size: 0.8em;
210 | }
211 |
212 | .skin-dos .info-bar canvas {
213 | bottom: calc(-1.25 * var(--gap-block-size));
214 | }
215 |
216 | .skin-dos dialog {
217 | min-inline-size: min(75dvw, 50ch);
218 | inline-size: min(75dvw, 50ch);
219 | inline-size: min(round(up, 75dvw, 1ch), 50ch);
220 | padding-inline: var(--smaller-gap-inline-size);
221 | padding-block: calc(var(--small-gap-block-size) - var(--smaller-gap-block-size) / 2);
222 | }
223 |
224 | .skin-dos dialog form,
225 | .skin-dos dialog form p {
226 | row-gap: 0;
227 | }
228 |
229 | .skin-dos dialog form p {
230 | margin: 0;
231 | padding-inline: var(--small-gap-inline-size);
232 | padding-block-start: var(--large-gap-block-size);
233 | }
234 |
235 | .skin-dos dialog form .dialog-title {
236 | padding-inline-start: var(--small-gap-inline-size);
237 | padding-block-end: calc(var(--small-gap-block-size) - var(--smaller-gap-block-size) / 4);
238 | border-block-end: solid var(--accent-color) calc(var(--smaller-gap-block-size) / 2);
239 | }
240 |
241 | .skin-dos dialog form p {
242 | row-gap: var(--gap-block-size);
243 | padding-block-start: calc(var(--small-gap-block-size) - var(--smaller-gap-block-size) / 4);
244 | padding-block-end: 0;
245 | }
246 |
247 | .skin-dos dialog label {
248 | row-gap: 0;
249 | }
250 |
251 | .skin-dos dialog input {
252 | appearance: textfield;
253 | caret-shape: underscore;
254 | }
255 |
256 | .skin-dos dialog select {
257 | appearance: none;
258 | }
259 |
260 | .skin-dos dialog input::-webkit-inner-spin-button {
261 | appearance: none;
262 | }
263 |
264 | .skin-dos dialog input,
265 | .skin-dos dialog select {
266 | padding: 0;
267 | block-size: var(--gap-block-size);
268 | inline-size: 100%;
269 | }
270 |
271 | .skin-dos dialog select:focus {
272 | background-color: var(--text-color);
273 | color: var(--bg-color);
274 | }
275 |
276 | .skin-dos .options-dialog label {
277 | min-block-size: auto;
278 | }
279 |
280 | .skin-dos .options-dialog form p {
281 | row-gap: 0;
282 | }
283 |
284 | .skin-dos .options-dialog input[type="checkbox"] {
285 | inline-size: inherit;
286 | block-size: inherit;
287 | accent-color: inherit;
288 | }
289 |
290 | .skin-dos .options-dialog input,
291 | .skin-dos .options-dialog select {
292 | inline-size: min(10ch, 100%);
293 | text-align: right;
294 | }
295 |
296 | .skin-dos .downloads,
297 | .main-container.hidden-downloads .button-bar-bottom {
298 | border-block-end-width: 0;
299 | }
300 |
301 | @media (display-mode: standalone) or (orientation: portrait) or (max-aspect-ratio: 7/5) {
302 |
303 | .skin-dos .main-container:not(.hidden-footer) .downloads,
304 | .main-container.hidden-downloads:not(.hidden-footer) .button-bar-bottom {
305 | border-block-end-width: var(--smaller-gap-block-size);
306 | }
307 |
308 | .skin-dos main {
309 | inline-size: 100%;
310 | inline-size: round(down, 100%, 1ch);
311 | margin-block-start: 0;
312 | border-width: 0;
313 | }
314 |
315 | .skin-dos main::before,
316 | .skin-dos main:after {
317 | content: none;
318 | }
319 |
320 | .skin-dos main> :first-child {
321 | padding-block-start: var(--small-gap-block-size);
322 | padding-inline: var(--small-gap-inline-size);
323 | }
324 |
325 | .skin-dos main>* {
326 | padding-inline: var(--small-gap-inline-size);
327 | }
328 |
329 | .skin-dos .info-bar {
330 | margin-block-start: 0;
331 | padding-block: var(--small-gap-inline-size);
332 | }
333 |
334 | .skin-dos .info-bar canvas {
335 | bottom: calc(-0.75 * var(--gap-block-size));
336 | }
337 |
338 | .skin-dos dialog {
339 | margin-block-start: calc(var(--gap-block-size) - var(--smaller-gap-block-size) / 2);
340 | }
341 | }
--------------------------------------------------------------------------------
/src/zip-manager/styles/ZipManager.css:
--------------------------------------------------------------------------------
1 | .main-container,
2 | main {
3 | display: flex;
4 | flex-direction: column;
5 | }
6 |
7 | .main-container {
8 | block-size: 100dvh;
9 | align-items: center;
10 | }
11 |
12 | main,
13 | .hidden-downloads .entries {
14 | flex: 1;
15 | }
16 |
17 | main,
18 | main>* {
19 | border-style: solid;
20 | border-color: var(--accent-color);
21 | border-width: 0;
22 | }
23 |
24 | main {
25 | background-color: var(--bg-color);
26 | color: var(--text-color);
27 | margin-inline: var(--gap-inline-size);
28 | margin-block: var(--gap-block-size);
29 | border-width: var(--border-width);
30 | inline-size: var(--app-width);
31 | min-block-size: 20em;
32 | border-radius: var(--border-radius-width);
33 | }
34 |
35 | .main-container:not(.hidden-footer) main {
36 | margin-block-end: 0;
37 | }
38 |
39 | main>* {
40 | padding-inline: var(--gap-inline-size);
41 | padding-block: var(--gap-block-size);
42 | border-block-end-width: var(--border-width);
43 | }
44 |
45 | .hidden-downloads .entries {
46 | resize: none;
47 | }
48 |
49 | .downloads,
50 | .main-container.hidden-downloads .button-bar-bottom {
51 | border-block-end-width: 0;
52 | }
53 |
54 | @media (display-mode: standalone) or (orientation: portrait) or (max-aspect-ratio: 7/5) {
55 | main {
56 | inline-size: 100dvw;
57 | margin: 0;
58 | border-width: 0;
59 | margin-block-end: 0;
60 | }
61 |
62 | .main-container:not(.hidden-footer) .downloads,
63 | .main-container.hidden-downloads:not(.hidden-footer) .button-bar-bottom {
64 | border-block-end-width: var(--border-width);
65 | }
66 | }
--------------------------------------------------------------------------------
/src/zip-manager/styles/index.css:
--------------------------------------------------------------------------------
1 | @import url(./Base.css);
2 | @import url(./ListItem.css);
3 | @import url(./ButtonBar.css);
4 | @import url(./Dialog.css);
5 | @import url(./Skins.css);
6 | @import url(./ZipManager.css);
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import { VitePWA } from "vite-plugin-pwa";
4 |
5 | export default defineConfig(() => {
6 | return {
7 | base: "./",
8 | build: {
9 | outDir: "build",
10 | target: "es2020",
11 | chunkSizeWarningLimit: 768
12 | },
13 | plugins: [
14 | react({
15 | babel: {
16 | plugins: [
17 | ["babel-plugin-react-compiler"]
18 | ]
19 | }
20 | }),
21 | VitePWA({
22 | registerType: "autoUpdate",
23 | strategies: "injectManifest",
24 | srcDir: "src",
25 | filename: "sw.js",
26 | injectManifest: {
27 | rollupFormat: "iife",
28 | globPatterns: [
29 | "./**/*.{js,css,png,ttf,wasm,zip}",
30 | "./*.{html,ico,png,js,json}"
31 | ]
32 | },
33 | includeManifestIcons: false,
34 | manifest: {
35 | "short_name": "Zip Manager",
36 | "name": "Zip Manager",
37 | "description": "Read, edit and write zip files.",
38 | "start_url": "./index.html",
39 | "display": "fullscreen",
40 | "theme_color": "#000000",
41 | "background_color": "#ffffff",
42 | "orientation": "any",
43 | "categories": [
44 | "utilities"
45 | ],
46 | "icons": [
47 | {
48 | "src": "assets/icons/icon-512x512.png",
49 | "sizes": "512x512",
50 | "type": "image/png",
51 | "purpose": "any"
52 | },
53 | {
54 | "src": "assets/icons/icon-192x192.png",
55 | "sizes": "192x192",
56 | "type": "image/png",
57 | "purpose": "any"
58 | },
59 | {
60 | "src": "assets/icons/icon-512x512.png",
61 | "sizes": "512x512",
62 | "type": "image/png",
63 | "purpose": "maskable"
64 | },
65 | {
66 | "src": "assets/icons/icon-192x192.png",
67 | "sizes": "192x192",
68 | "type": "image/png",
69 | "purpose": "maskable"
70 | },
71 | {
72 | "src": "assets/icons/icon-512x512-mono.png",
73 | "sizes": "512x512",
74 | "type": "image/png",
75 | "purpose": "monochrome"
76 | },
77 | {
78 | "src": "./assets/icons/icon-192x192-mono.png",
79 | "sizes": "192x192",
80 | "type": "image/png",
81 | "purpose": "monochrome"
82 | }
83 | ],
84 | "file_handlers": [
85 | {
86 | "action": "./index.html",
87 | "accept": {
88 | "application/zip": [
89 | ".zip"
90 | ],
91 | "application/vnd.openxmlformats-officedocument.wordprocessingml.document": [
92 | ".docx"
93 | ],
94 | "application/epub+zip": [
95 | ".epub"
96 | ],
97 | "application/java-archive": [
98 | ".jar"
99 | ],
100 | "application/vnd.oasis.opendocument.presentation": [
101 | ".odp"
102 | ],
103 | "application/vnd.oasis.opendocument.spreadsheet": [
104 | ".ods"
105 | ],
106 | "application/vnd.oasis.opendocument.text": [
107 | ".odt"
108 | ],
109 | "application/vnd.openxmlformats-officedocument.presentationml.presentation": [
110 | ".pptx"
111 | ],
112 | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [
113 | ".xlsx"
114 | ],
115 | "application/vnd.apple.keynote": [
116 | ".key"
117 | ],
118 | "application/vnd.apple.pages": [
119 | ".pages"
120 | ],
121 | "application/vnd.apple.numbers": [
122 | ".numbers"
123 | ],
124 | "application/vnd.android.package-archive": [
125 | ".apk"
126 | ],
127 | "application/x-ios-app": [
128 | ".ipa"
129 | ]
130 | },
131 | "launch_type": "single-client"
132 | }
133 | ],
134 | "share_target": {
135 | "action": "./shared-files",
136 | "enctype": "multipart/form-data",
137 | "method": "POST",
138 | "params": {
139 | "files": [
140 | {
141 | "name": "shared-files",
142 | "accept": [
143 | "*/*"
144 | ]
145 | }
146 | ]
147 | }
148 | },
149 | "screenshots": [
150 | {
151 | "src": "./screenshots/screenshot-395x640.png",
152 | "sizes": "395x640",
153 | "type": "image/png",
154 | "form_factor": "narrow",
155 | "label": "Main screen on mobile"
156 | },
157 | {
158 | "src": "./screenshots/screenshot-app-1135x809.png",
159 | "sizes": "1135x809",
160 | "type": "image/png",
161 | "form_factor": "wide",
162 | "label": "Main screen on desktop"
163 | },
164 | {
165 | "src": "./screenshots/screenshot-custom-395x640.png",
166 | "sizes": "395x640",
167 | "type": "image/png",
168 | "form_factor": "narrow",
169 | "label": "Custom user interface on mobile"
170 | }
171 | ]
172 | }
173 | })
174 | ]
175 | };
176 | });
177 |
--------------------------------------------------------------------------------