Compare commits
1 Commits
main
...
fix/init-s
Author | SHA1 | Date | |
---|---|---|---|
|
9e91e45c70 |
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added: Quick history window user options
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added support setting hotkeys with up to 3-key combinations
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
refactor: update terminology for history window split to open
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Auto-activate search in quick paste window when typing any letter or number
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added single-click copy/paste option in user preferences
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added detect and select language modal on first app run
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': minor
|
||||
---
|
||||
|
||||
Added keyboard shortcuts to improve navigation efficiency within the application
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added: history item preview max lines user setting
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added protected collection with PIN access
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added Special copy/paste for history items context menu and settings
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added global templates in user preferences for saved clips
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added: customizable tray icon behavior on Windows as user settings
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Fix: enhance value preview logic to fix text overflow
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added deleting menu folders with children by moving submenus up one level
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added settings to preserve pinned and starred items when clearing clipboard history
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Added option "Show Always on Top" for main window
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'pastebar-app-ui': patch
|
||||
---
|
||||
|
||||
Support for notes matching in global search
|
@ -49,9 +49,6 @@ npm run format
|
||||
|
||||
# Version management
|
||||
npm run version:sync
|
||||
|
||||
# Translation audit
|
||||
npm run translation-audit
|
||||
```
|
||||
|
||||
### Frontend Development (packages/pastebar-app-ui/)
|
||||
@ -206,4 +203,4 @@ src-tauri/src/
|
||||
|
||||
- Use Diesel migrations for schema changes
|
||||
- Place migration files in `migrations/` directory
|
||||
- Run migrations with `npm run diesel:migration:run`
|
||||
- Run migrations with `npm run diesel:migration:run`
|
||||
|
423
package-lock.json
generated
423
package-lock.json
generated
@ -141,7 +141,6 @@
|
||||
"@types/codemirror": "^5.60.15",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/events": "^3.0.3",
|
||||
"@types/html-to-text": "^9.0.4",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/linkify-it": "^3.0.5",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
@ -169,6 +168,7 @@
|
||||
"tailwind-merge": "^2.0.0",
|
||||
"tailwindcss": "^3.3.5",
|
||||
"taze": "^0.12.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.0.6",
|
||||
"vite-plugin-tauri": "^4.0.0"
|
||||
@ -2658,6 +2658,28 @@
|
||||
"node": ">=0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "0.3.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.0.3",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@dnd-kit/accessibility": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.0.tgz",
|
||||
@ -6306,19 +6328,6 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@selderee/plugin-htmlparser2": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
|
||||
"integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domhandler": "^5.0.3",
|
||||
"selderee": "^0.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/@sigstore/bundle": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.0.tgz",
|
||||
@ -7295,6 +7304,30 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
|
||||
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node12": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node14": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node16": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tufjs/canonical-json": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz",
|
||||
@ -7482,13 +7515,6 @@
|
||||
"integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/html-to-text": {
|
||||
"version": "9.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-to-text/-/html-to-text-9.0.4.tgz",
|
||||
"integrity": "sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||
@ -7813,6 +7839,18 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
@ -9208,6 +9246,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
@ -9700,6 +9744,15 @@
|
||||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
@ -11152,41 +11205,6 @@
|
||||
"void-elements": "3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-to-text": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
|
||||
"integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@selderee/plugin-htmlparser2": "^0.11.0",
|
||||
"deepmerge": "^4.3.1",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"htmlparser2": "^8.0.2",
|
||||
"selderee": "^0.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
@ -12053,15 +12071,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/leac": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
|
||||
"integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||
@ -12185,6 +12194,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/make-fetch-happen": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz",
|
||||
@ -13453,19 +13468,6 @@
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
||||
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
|
||||
},
|
||||
"node_modules/parseley": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz",
|
||||
"integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"leac": "^0.6.0",
|
||||
"peberminta": "^0.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/pastebar-app-ui": {
|
||||
"resolved": "packages/pastebar-app-ui",
|
||||
"link": true
|
||||
@ -13536,15 +13538,6 @@
|
||||
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/peberminta": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
|
||||
"integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
@ -15124,18 +15117,6 @@
|
||||
"resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz",
|
||||
"integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg=="
|
||||
},
|
||||
"node_modules/selderee": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
|
||||
"integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"parseley": "^0.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
@ -16198,6 +16179,55 @@
|
||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
"@tsconfig/node12": "^1.0.7",
|
||||
"@tsconfig/node14": "^1.0.0",
|
||||
"@tsconfig/node16": "^1.0.2",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"arg": "^4.1.0",
|
||||
"create-require": "^1.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"v8-compile-cache-lib": "^3.0.1",
|
||||
"yn": "3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"ts-node": "dist/bin.js",
|
||||
"ts-node-cwd": "dist/bin-cwd.js",
|
||||
"ts-node-esm": "dist/bin-esm.js",
|
||||
"ts-node-script": "dist/bin-script.js",
|
||||
"ts-node-transpile-only": "dist/bin-transpile.js",
|
||||
"ts-script": "dist/bin-script-deprecated.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/core": ">=1.2.50",
|
||||
"@swc/wasm": ">=1.2.50",
|
||||
"@types/node": "*",
|
||||
"typescript": ">=2.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@swc/wasm": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node/node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
|
||||
@ -16632,6 +16662,12 @@
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
@ -17114,6 +17150,15 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/youtube-player": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz",
|
||||
@ -17262,7 +17307,6 @@
|
||||
"framer-motion": "^10.16.5",
|
||||
"garbados-crypt": "^3.0.0-beta",
|
||||
"glob-all": "^3.3.1",
|
||||
"html-to-text": "^9.0.5",
|
||||
"i18next": "^23.10.0",
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"idb-keyval": "^6.2.1",
|
||||
@ -19862,6 +19906,27 @@
|
||||
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
|
||||
"optional": true
|
||||
},
|
||||
"@cspotcode/source-map-support": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/trace-mapping": "0.3.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/resolve-uri": "^3.0.3",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@dnd-kit/accessibility": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.0.tgz",
|
||||
@ -22128,15 +22193,6 @@
|
||||
"integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==",
|
||||
"optional": true
|
||||
},
|
||||
"@selderee/plugin-htmlparser2": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
|
||||
"integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
|
||||
"requires": {
|
||||
"domhandler": "^5.0.3",
|
||||
"selderee": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"@sigstore/bundle": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.0.tgz",
|
||||
@ -22641,6 +22697,30 @@
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA=="
|
||||
},
|
||||
"@tsconfig/node10": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
|
||||
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
|
||||
"dev": true
|
||||
},
|
||||
"@tsconfig/node12": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||
"dev": true
|
||||
},
|
||||
"@tsconfig/node14": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||
"dev": true
|
||||
},
|
||||
"@tsconfig/node16": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||
"dev": true
|
||||
},
|
||||
"@tufjs/canonical-json": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz",
|
||||
@ -22818,12 +22898,6 @@
|
||||
"integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/html-to-text": {
|
||||
"version": "9.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-to-text/-/html-to-text-9.0.4.tgz",
|
||||
"integrity": "sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||
@ -23099,6 +23173,15 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^8.11.0"
|
||||
}
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
@ -24116,6 +24199,12 @@
|
||||
"yaml": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
@ -24451,6 +24540,12 @@
|
||||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
|
||||
"dev": true
|
||||
},
|
||||
"diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"dev": true
|
||||
},
|
||||
"dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
@ -25543,29 +25638,6 @@
|
||||
"void-elements": "3.1.0"
|
||||
}
|
||||
},
|
||||
"html-to-text": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
|
||||
"integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
|
||||
"requires": {
|
||||
"@selderee/plugin-htmlparser2": "^0.11.0",
|
||||
"deepmerge": "^4.3.1",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"htmlparser2": "^8.0.2",
|
||||
"selderee": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"http-cache-semantics": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
@ -26174,11 +26246,6 @@
|
||||
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
||||
"dev": true
|
||||
},
|
||||
"leac": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
|
||||
"integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="
|
||||
},
|
||||
"lilconfig": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||
@ -26286,6 +26353,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true
|
||||
},
|
||||
"make-fetch-happen": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz",
|
||||
@ -27262,15 +27335,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"parseley": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz",
|
||||
"integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==",
|
||||
"requires": {
|
||||
"leac": "^0.6.0",
|
||||
"peberminta": "^0.9.0"
|
||||
}
|
||||
},
|
||||
"pastebar-app-ui": {
|
||||
"version": "file:packages/pastebar-app-ui",
|
||||
"requires": {
|
||||
@ -27371,7 +27435,6 @@
|
||||
"framer-motion": "^10.16.5",
|
||||
"garbados-crypt": "^3.0.0-beta",
|
||||
"glob-all": "^3.3.1",
|
||||
"html-to-text": "^9.0.5",
|
||||
"i18next": "^23.10.0",
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"idb-keyval": "^6.2.1",
|
||||
@ -27820,11 +27883,6 @@
|
||||
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
|
||||
"dev": true
|
||||
},
|
||||
"peberminta": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
|
||||
"integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
@ -28838,14 +28896,6 @@
|
||||
"resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz",
|
||||
"integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg=="
|
||||
},
|
||||
"selderee": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
|
||||
"integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
|
||||
"requires": {
|
||||
"parseley": "^0.12.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
@ -29636,6 +29686,35 @@
|
||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
||||
"dev": true
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
"@tsconfig/node12": "^1.0.7",
|
||||
"@tsconfig/node14": "^1.0.0",
|
||||
"@tsconfig/node16": "^1.0.2",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"arg": "^4.1.0",
|
||||
"create-require": "^1.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"v8-compile-cache-lib": "^3.0.1",
|
||||
"yn": "3.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tsconfig-paths": {
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
|
||||
@ -29930,6 +30009,12 @@
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
|
||||
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="
|
||||
},
|
||||
"v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
||||
"dev": true
|
||||
},
|
||||
"validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
@ -30258,6 +30343,12 @@
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true
|
||||
},
|
||||
"yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"youtube-player": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz",
|
||||
|
@ -20,7 +20,7 @@
|
||||
"changeset": "changeset",
|
||||
"version:sync": "node scripts/sync-version.js",
|
||||
"version": "changeset version && npm run version:sync",
|
||||
"translation-audit": "npx tsx scripts/translation-audit.ts"
|
||||
"translation-audit": "ts-node scripts/translation-audit.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codastic/react-positioning-portal": "^0.7.0",
|
||||
@ -156,7 +156,6 @@
|
||||
"@types/codemirror": "^5.60.15",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/events": "^3.0.3",
|
||||
"@types/html-to-text": "^9.0.4",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/linkify-it": "^3.0.5",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
@ -184,6 +183,7 @@
|
||||
"tailwind-merge": "^2.0.0",
|
||||
"tailwindcss": "^3.3.5",
|
||||
"taze": "^0.12.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.0.6",
|
||||
"vite-plugin-tauri": "^4.0.0"
|
||||
|
@ -82,7 +82,6 @@
|
||||
"framer-motion": "^10.16.5",
|
||||
"garbados-crypt": "^3.0.0-beta",
|
||||
"glob-all": "^3.3.1",
|
||||
"html-to-text": "^9.0.5",
|
||||
"i18next": "^23.10.0",
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"idb-keyval": "^6.2.1",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { listen } from '@tauri-apps/api/event'
|
||||
import { register, unregisterAll } from '@tauri-apps/api/globalShortcut'
|
||||
@ -10,7 +10,6 @@ import { useAtomValue } from 'jotai'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
|
||||
|
||||
import LanguageSelectionModal from '~/components/organisms/modals/language-selection-modal'
|
||||
import { ThemeProvider } from '~/components/theme-provider'
|
||||
|
||||
import useKeyPressAlt from '~/hooks/use-keypress-alt'
|
||||
@ -34,8 +33,6 @@ import {
|
||||
settingsStoreAtom,
|
||||
themeStoreAtom,
|
||||
uiStoreAtom,
|
||||
DEFAULT_SPECIAL_PASTE_OPERATIONS,
|
||||
DEFAULT_SPECIAL_PASTE_CATEGORIES,
|
||||
} from './store'
|
||||
|
||||
const appIdleEvents = ['mousemove', 'keydown', 'scroll', 'keypress', 'mousedown']
|
||||
@ -55,17 +52,6 @@ function App() {
|
||||
const { i18n, t } = useTranslation()
|
||||
const { toast } = useToast()
|
||||
const historyWindowOpening = useSignal(false)
|
||||
const showLanguageSelectionModal = useSignal(false)
|
||||
const permissionsTrustedSignal = useSignal<boolean | null>(null)
|
||||
|
||||
const handleLanguageSelected = useCallback(
|
||||
(languageCode: string) => {
|
||||
settingsStore.updateSetting('userSelectedLanguage', languageCode)
|
||||
settingsStore.updateSetting('isFirstRun', false)
|
||||
showLanguageSelectionModal.value = false
|
||||
},
|
||||
[settingsStore]
|
||||
)
|
||||
|
||||
const handleActivity = useCallback(
|
||||
debounce(() => {
|
||||
@ -96,12 +82,7 @@ function App() {
|
||||
if (res === null) return
|
||||
|
||||
try {
|
||||
const {
|
||||
constants,
|
||||
settings,
|
||||
permissionstrusted: initialPermissionsTrusted,
|
||||
} = JSON.parse(res)
|
||||
permissionsTrustedSignal.value = initialPermissionsTrusted
|
||||
const { constants, settings, permissionstrusted } = JSON.parse(res)
|
||||
|
||||
const {
|
||||
app_dev_data_dir: appDevDataDir,
|
||||
@ -131,7 +112,6 @@ function App() {
|
||||
isCustomDbPathValid: null,
|
||||
customDbPathError: null,
|
||||
dbRelocationInProgress: false,
|
||||
historyPreviewLineLimit: settings.historyPreviewLineLimit?.valueInt ?? null,
|
||||
appLastUpdateVersion: settings.appLastUpdateVersion?.valueText,
|
||||
appLastUpdateDate: settings.appLastUpdateDate?.valueText,
|
||||
isHideMacOSDockIcon: settings.isHideMacOSDockIcon?.valueBool,
|
||||
@ -215,39 +195,7 @@ function App() {
|
||||
isHistoryPanelVisibleOnly: settings.isHistoryPanelVisibleOnly?.valueBool,
|
||||
isSavedClipsPanelVisibleOnly: settings.isSavedClipsPanelVisibleOnly?.valueBool,
|
||||
isSimplifiedLayout: settings.isSimplifiedLayout?.valueBool ?? true,
|
||||
isMainWindowOnTop: settings.isMainWindowOnTop?.valueBool ?? false,
|
||||
isQuickPasteCopyOnly: settings.isQuickPasteCopyOnly?.valueBool ?? false,
|
||||
isQuickPasteAutoClose: settings.isQuickPasteAutoClose?.valueBool ?? true,
|
||||
isSingleClickToCopyPaste: settings.isSingleClickToCopyPaste?.valueBool ?? false,
|
||||
hasPinProtectedCollections:
|
||||
settings.hasPinProtectedCollections?.valueBool ?? false,
|
||||
protectedCollections: settings.protectedCollections?.valueText
|
||||
? settings.protectedCollections.valueText.split(',').filter(Boolean)
|
||||
: [],
|
||||
isSingleClickToCopyPasteQuickWindow:
|
||||
settings.isSingleClickToCopyPasteQuickWindow?.valueBool ?? false,
|
||||
isKeepPinnedOnClearEnabled:
|
||||
settings.isKeepPinnedOnClearEnabled?.valueBool ?? false,
|
||||
isKeepStarredOnClearEnabled:
|
||||
settings.isKeepStarredOnClearEnabled?.valueBool ?? false,
|
||||
isDoubleClickTrayToOpenEnabledOnWindows:
|
||||
settings.isDoubleClickTrayToOpenEnabledOnWindows?.valueBool ?? false,
|
||||
isLeftClickTrayDisabledOnWindows:
|
||||
settings.isLeftClickTrayDisabledOnWindows?.valueBool ?? false,
|
||||
isLeftClickTrayToOpenEnabledOnWindows:
|
||||
settings.isLeftClickTrayToOpenEnabledOnWindows?.valueBool ?? false,
|
||||
globalTemplatesEnabled: settings.globalTemplatesEnabled?.valueBool ?? true, // Default to true
|
||||
globalTemplates: settings.globalTemplates?.valueText
|
||||
? settings.globalTemplates.valueText // Will be parsed by initSettings in store
|
||||
: [], // Default to empty array
|
||||
isSpecialCopyPasteHistoryEnabled:
|
||||
settings.isSpecialCopyPasteHistoryEnabled?.valueBool ?? true,
|
||||
enabledSpecialPasteOperations: settings.enabledSpecialPasteOperations?.valueText
|
||||
? settings.enabledSpecialPasteOperations.valueText.split(',').filter(Boolean)
|
||||
: [...DEFAULT_SPECIAL_PASTE_OPERATIONS],
|
||||
specialPasteCategoriesOrder: settings.specialPasteCategoriesOrder?.valueText
|
||||
? settings.specialPasteCategoriesOrder.valueText.split(',').filter(Boolean)
|
||||
: [...DEFAULT_SPECIAL_PASTE_CATEGORIES],
|
||||
showTrayIcon: settings.showTrayIcon?.valueBool ?? true, // Added line
|
||||
isAppReady: true,
|
||||
})
|
||||
settingsStore.initConstants({
|
||||
@ -263,7 +211,7 @@ function App() {
|
||||
|
||||
if (settings.isFirstRun?.valueBool) {
|
||||
appWindow.setSize(new LogicalSize(1105, 710))
|
||||
showLanguageSelectionModal.value = true
|
||||
settingsStore.updateSetting('isFirstRun', false)
|
||||
}
|
||||
|
||||
if (
|
||||
@ -313,7 +261,60 @@ function App() {
|
||||
}
|
||||
}
|
||||
|
||||
// Welcome tour logic moved to a separate useEffect
|
||||
if (
|
||||
!settings.appToursCompletedList?.valueText
|
||||
.split(',')
|
||||
.includes(APP_TOURS.historyPanelTour) &&
|
||||
!settings.appToursSkippedList?.valueText
|
||||
.split(',')
|
||||
.includes(APP_TOURS.historyPanelTour) &&
|
||||
permissionstrusted
|
||||
) {
|
||||
const welcomeTour = toast({
|
||||
title: `${t('Welcome to PasteBar', { ns: 'help' })} 🎉`,
|
||||
id: 'welcome-tour',
|
||||
duration: 0,
|
||||
description: (
|
||||
<>
|
||||
{t(`WelcomeDescription`, { ns: 'help' })}
|
||||
<Flex className="mt-3">{t(`WelcomeTour`, { ns: 'help' })}</Flex>
|
||||
<Flex className="justify-between">
|
||||
<Button
|
||||
className="bg-blue-500 dark:bg-blue-700 dark:hover:bg-blue-800 hover:bg-blue-600 px-4 mt-3 text-white"
|
||||
onClick={() => {
|
||||
openOnBoardingTourName.value = APP_TOURS.historyPanelTour
|
||||
welcomeTour?.dismiss()
|
||||
}}
|
||||
>
|
||||
{t('Start Tour', { ns: 'help' })}
|
||||
</Button>
|
||||
<Flex className="gap-3">
|
||||
<Button
|
||||
variant="light"
|
||||
className="text-gray-800 px-4 mt-3 dark:bg-slate-800 dark:text-gray-400 hover:dark:text-gray-300"
|
||||
onClick={() => {
|
||||
welcomeTour?.dismiss()
|
||||
}}
|
||||
>
|
||||
{t('Later', { ns: 'help' })}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="text-gray-800 px-4 mt-3"
|
||||
onClick={() => {
|
||||
welcomeTour?.dismiss()
|
||||
const tours = Object.values(APP_TOURS)
|
||||
settingsStore.setAppToursSkippedList([...tours])
|
||||
}}
|
||||
>
|
||||
{t('Skip All Tours', { ns: 'help' })}
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
if (!settings.isSkipAutoStartPrompt?.valueBool) {
|
||||
invoke('is_autostart_enabled').then(async isAutoStartEnabled => {
|
||||
@ -327,7 +328,9 @@ function App() {
|
||||
})
|
||||
}
|
||||
|
||||
// OSX Permissions modal logic moved to a separate useEffect
|
||||
if (permissionstrusted === false) {
|
||||
openOSXSystemPermissionsModal.value = true
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
@ -534,142 +537,6 @@ function App() {
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Effect to show OSX System Permissions Modal
|
||||
useEffect(() => {
|
||||
// Wait until permissions status is known and settings are initialized
|
||||
if (permissionsTrustedSignal.value === null || !settingsStore.isAppReady) {
|
||||
return
|
||||
}
|
||||
|
||||
// If it's the first run and the language selection modal is active,
|
||||
// wait for it to be closed before checking/showing the permissions modal.
|
||||
if (settingsStore.isFirstRun && showLanguageSelectionModal.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// Proceed if:
|
||||
// - It's not the first run OR
|
||||
// - It was the first run AND the language modal is now closed.
|
||||
if (permissionsTrustedSignal.value === false) {
|
||||
if (!openOSXSystemPermissionsModal.value) {
|
||||
openOSXSystemPermissionsModal.value = true
|
||||
}
|
||||
} else if (permissionsTrustedSignal.value === true) {
|
||||
// If permissions are trusted, ensure the modal is not trying to be shown.
|
||||
// This can be useful if the modal was opened and then permissions were granted.
|
||||
if (openOSXSystemPermissionsModal.value) {
|
||||
openOSXSystemPermissionsModal.value = false
|
||||
}
|
||||
}
|
||||
}, [
|
||||
permissionsTrustedSignal.value,
|
||||
showLanguageSelectionModal.value,
|
||||
settingsStore.isFirstRun,
|
||||
settingsStore.isAppReady,
|
||||
// openOSXSystemPermissionsModal // signal itself, stable reference
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
permissionsTrustedSignal.value === false &&
|
||||
openOSXSystemPermissionsModal.value === false
|
||||
) {
|
||||
permissionsTrustedSignal.value = true
|
||||
}
|
||||
}, [openOSXSystemPermissionsModal.value])
|
||||
|
||||
// Effect to show Welcome Tour toast
|
||||
useEffect(() => {
|
||||
let welcomeTourToast: { dismiss: () => void } | undefined
|
||||
|
||||
// Ensure all prerequisites are met: settings ready, permission status known,
|
||||
// and relevant modals (language, OSX permissions) are not active.
|
||||
if (
|
||||
!settingsStore.isAppReady ||
|
||||
permissionsTrustedSignal.value === null ||
|
||||
(settingsStore.isFirstRun && showLanguageSelectionModal.value) ||
|
||||
openOSXSystemPermissionsModal.value === true
|
||||
) {
|
||||
return () => {
|
||||
welcomeTourToast?.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
// If we've passed the early exit, language and permissions modals are closed.
|
||||
// Now, only show the tour if permissions are actually trusted.
|
||||
if (permissionsTrustedSignal.value) {
|
||||
const tourCompleted = settingsStore.appToursCompletedList?.includes(
|
||||
APP_TOURS.historyPanelTour
|
||||
)
|
||||
const tourSkipped = settingsStore.appToursSkippedList?.includes(
|
||||
APP_TOURS.historyPanelTour
|
||||
)
|
||||
|
||||
if (!tourCompleted && !tourSkipped) {
|
||||
welcomeTourToast = toast({
|
||||
title: `${t('Welcome to PasteBar', { ns: 'help' })} 🎉`,
|
||||
id: 'welcome-tour',
|
||||
duration: 0, // Stays until dismissed
|
||||
description: (
|
||||
<>
|
||||
{t(`WelcomeDescription`, { ns: 'help' })}
|
||||
<Flex className="mt-3">{t(`WelcomeTour`, { ns: 'help' })}</Flex>
|
||||
<Flex className="justify-between">
|
||||
<Button
|
||||
className="bg-blue-500 dark:bg-blue-700 dark:hover:bg-blue-800 hover:bg-blue-600 px-4 mt-3 text-white"
|
||||
onClick={() => {
|
||||
openOnBoardingTourName.value = APP_TOURS.historyPanelTour
|
||||
welcomeTourToast?.dismiss()
|
||||
}}
|
||||
>
|
||||
{t('Start Tour', { ns: 'help' })}
|
||||
</Button>
|
||||
<Flex className="gap-3">
|
||||
<Button
|
||||
variant="light"
|
||||
className="text-gray-800 px-4 mt-3 dark:bg-slate-800 dark:text-gray-400 hover:dark:text-gray-300"
|
||||
onClick={() => {
|
||||
welcomeTourToast?.dismiss()
|
||||
}}
|
||||
>
|
||||
{t('Later', { ns: 'help' })}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="text-gray-800 px-4 mt-3"
|
||||
onClick={() => {
|
||||
welcomeTourToast?.dismiss()
|
||||
const tours = Object.values(APP_TOURS)
|
||||
settingsStore.setAppToursSkippedList([...tours])
|
||||
}}
|
||||
>
|
||||
{t('Skip All Tours', { ns: 'help' })}
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</>
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
welcomeTourToast?.dismiss() // Dismiss if this effect instance created it
|
||||
}
|
||||
}, [
|
||||
settingsStore.isAppReady,
|
||||
showLanguageSelectionModal.value,
|
||||
settingsStore.isFirstRun,
|
||||
permissionsTrustedSignal.value,
|
||||
openOSXSystemPermissionsModal.value, // Added dependency
|
||||
settingsStore.appToursCompletedList,
|
||||
settingsStore.appToursSkippedList,
|
||||
settingsStore, // For setAppToursSkippedList and accessing properties
|
||||
t,
|
||||
toast,
|
||||
openOnBoardingTourName,
|
||||
])
|
||||
|
||||
const uiState = useAtomValue(uiStoreAtom)
|
||||
|
||||
useEffect(() => {
|
||||
@ -719,16 +586,6 @@ function App() {
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
{settingsStore.isFirstRun && (
|
||||
<LanguageSelectionModal
|
||||
open={showLanguageSelectionModal.value}
|
||||
onClose={() => {
|
||||
showLanguageSelectionModal.value = false
|
||||
settingsStore.updateSetting('isFirstRun', false)
|
||||
}}
|
||||
onLanguageSelected={handleLanguageSelected}
|
||||
/>
|
||||
)}
|
||||
</ThemeProvider>
|
||||
</>
|
||||
)
|
||||
|
@ -45,11 +45,8 @@ function QuickPasteApp() {
|
||||
i18n.changeLanguage(i18n.resolvedLanguage)
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
settingsStore.initSettings({
|
||||
appDataDir: '',
|
||||
isSingleClickToCopyPaste: settings.isSingleClickToCopyPaste?.valueBool,
|
||||
historyPreviewLineLimit: settings.historyPreviewLineLimit?.valueInt ?? null,
|
||||
appLastUpdateVersion: settings.appLastUpdateVersion?.valueText,
|
||||
appLastUpdateDate: settings.appLastUpdateDate?.valueText,
|
||||
isHideMacOSDockIcon: settings.isHideMacOSDockIcon?.valueBool,
|
||||
@ -125,10 +122,6 @@ function QuickPasteApp() {
|
||||
userSelectedLanguage: settings.userSelectedLanguage?.valueText,
|
||||
clipTextMinLength: settings.clipTextMinLength?.valueInt,
|
||||
clipTextMaxLength: settings.clipTextMaxLength?.valueInt,
|
||||
isQuickPasteCopyOnly: settings.isQuickPasteCopyOnly?.valueBool ?? false,
|
||||
isQuickPasteAutoClose: settings.isQuickPasteAutoClose?.valueBool ?? true,
|
||||
isSingleClickToCopyPasteQuickWindow:
|
||||
settings.isSingleClickToCopyPasteQuickWindow?.valueBool ?? false,
|
||||
isAppReady: true,
|
||||
})
|
||||
|
||||
|
@ -14,9 +14,6 @@ import {
|
||||
} from 'react'
|
||||
import { UniqueIdentifier } from '@dnd-kit/core'
|
||||
import { bbCode } from '~/libs/bbcode'
|
||||
import { settingsStoreAtom } from '~/store'
|
||||
import { useAtomValue } from 'jotai'
|
||||
import { Check } from 'lucide-react'
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'
|
||||
|
||||
import { ensureUrlPrefix, escapeRegExp, maskValue } from '~/lib/utils'
|
||||
@ -25,9 +22,8 @@ import { LinkMetadata } from '~/types/history'
|
||||
|
||||
import LinkCard from '../atoms/link-card/link-card'
|
||||
import mergeRefs from '../atoms/merge-refs'
|
||||
import ToolTip from '../atoms/tooltip'
|
||||
import { CardSocialEmbed } from '../social-embend/CardSocialEmbed'
|
||||
import { Badge, Box, TextNormal } from '../ui'
|
||||
import { Box, TextNormal } from '../ui'
|
||||
import YoutubeEmbed from '../video-player/YoutubeEmbed'
|
||||
|
||||
const highlightSearchTermInNode = (
|
||||
@ -103,47 +99,6 @@ const highlightSearchTermInNode = (
|
||||
}
|
||||
}
|
||||
|
||||
const renderWithGlobalTemplateBadges = (
|
||||
value: string,
|
||||
globalTemplates: any[] = []
|
||||
): ReactNode[] => {
|
||||
const templateFieldRegex = /\{\{\s*(.*?)\s*\}\}/g
|
||||
const parts = value.split(templateFieldRegex)
|
||||
|
||||
return parts.map((part: string, index: number): ReactNode => {
|
||||
// Check if this is a template reference (odd indices are matches from regex split)
|
||||
if (index % 2 === 1) {
|
||||
const matchedGlobalTemplate = globalTemplates.find(
|
||||
gt => gt.isEnabled && gt.name?.toLowerCase() === part.toLowerCase()
|
||||
)
|
||||
|
||||
if (matchedGlobalTemplate) {
|
||||
// Render as a badge for existing global templates
|
||||
return (
|
||||
<ToolTip
|
||||
key={index}
|
||||
text={matchedGlobalTemplate.value || part}
|
||||
isCompact
|
||||
side="top"
|
||||
className="bg-purple-50 dark:bg-purple-900 text-purple-600 dark:text-purple-300"
|
||||
>
|
||||
<Badge className="inline-flex items-center gap-1 bg-purple-100 text-purple-700 dark:bg-purple-800 dark:text-purple-300 hover:bg-purple-200 dark:hover:bg-purple-700 cursor-default">
|
||||
<Check size={12} className="text-purple-600 dark:text-purple-400" />
|
||||
<span className="text-xs font-medium">{part}</span>
|
||||
</Badge>
|
||||
</ToolTip>
|
||||
)
|
||||
} else {
|
||||
// Template reference doesn't exist - return the full {{templateName}} format
|
||||
return <span key={index}>{`{{${part}}}`}</span>
|
||||
}
|
||||
}
|
||||
|
||||
// Return the plain text part
|
||||
return <span key={index}>{part}</span>
|
||||
})
|
||||
}
|
||||
|
||||
interface CardValueViewerProps {
|
||||
isWrapped: boolean
|
||||
valuePreview: string
|
||||
@ -189,24 +144,6 @@ export const CardValueViewer: FC<CardValueViewerProps> = ({
|
||||
}) => {
|
||||
const highlightedRefs = useRef<React.RefObject<HTMLElement>[]>([])
|
||||
const wrapped = isLink || isVideo || isPath || isWrapped
|
||||
const settings = useAtomValue(settingsStoreAtom)
|
||||
|
||||
// Get global templates from settings
|
||||
const globalTemplatesEnabled = settings.globalTemplatesEnabled || false
|
||||
const globalTemplates = useMemo(() => {
|
||||
if (!globalTemplatesEnabled) return []
|
||||
try {
|
||||
if (typeof settings.globalTemplates === 'string') {
|
||||
return JSON.parse(settings.globalTemplates || '[]')
|
||||
}
|
||||
if (Array.isArray(settings.globalTemplates)) {
|
||||
return settings.globalTemplates
|
||||
}
|
||||
return []
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}, [settings.globalTemplates, globalTemplatesEnabled])
|
||||
|
||||
const isTwitter =
|
||||
metadataLinkByItemId?.linkDomain === 'x.com' ||
|
||||
@ -217,41 +154,17 @@ export const CardValueViewer: FC<CardValueViewerProps> = ({
|
||||
|
||||
const valuePreviewParsed = useMemo(() => {
|
||||
if (!isImageData && !isCode && !isImage && valuePreview) {
|
||||
const processedValue = isMasked
|
||||
return isMasked
|
||||
? maskValue(bbCode.remove(valuePreview))
|
||||
: bbCode.parse(valuePreview)
|
||||
|
||||
// Apply global template badges if enabled and templates exist
|
||||
if (
|
||||
globalTemplatesEnabled &&
|
||||
globalTemplates.length > 0 &&
|
||||
typeof processedValue === 'string'
|
||||
) {
|
||||
return renderWithGlobalTemplateBadges(processedValue, globalTemplates)
|
||||
}
|
||||
|
||||
return processedValue
|
||||
}
|
||||
}, [valuePreview, globalTemplatesEnabled, globalTemplates, isMasked])
|
||||
}, [valuePreview])
|
||||
|
||||
const valueParsed = useMemo(() => {
|
||||
if (!isImageData && !isCode && !isImage && textValue) {
|
||||
const processedValue = isMasked
|
||||
? maskValue(bbCode.remove(textValue))
|
||||
: bbCode.parse(textValue)
|
||||
|
||||
// Apply global template badges if enabled and templates exist
|
||||
if (
|
||||
globalTemplatesEnabled &&
|
||||
globalTemplates.length > 0 &&
|
||||
typeof processedValue === 'string'
|
||||
) {
|
||||
return renderWithGlobalTemplateBadges(processedValue, globalTemplates)
|
||||
}
|
||||
|
||||
return processedValue
|
||||
return isMasked ? maskValue(bbCode.remove(textValue)) : bbCode.parse(textValue)
|
||||
}
|
||||
}, [textValue, globalTemplatesEnabled, globalTemplates, isMasked])
|
||||
}, [textValue])
|
||||
|
||||
const highlightedContent = useMemo(() => {
|
||||
if (searchTerm.length > 1) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { createRef, FC, memo, useEffect, useRef, useState } from 'react'
|
||||
import CodeMirror from 'codemirror'
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { escapeRegExp } from '~/lib/utils'
|
||||
|
||||
@ -44,6 +45,7 @@ export const CodeViewer: FC<CodeViewerProps> = ({
|
||||
}) => {
|
||||
const [elements, setElements] = useState<JSX.Element[]>([])
|
||||
const [isModeLoaded, setModeLoaded] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
const mdShowFormat = useSignal<'html' | 'markdown'>('html')
|
||||
|
||||
const highlightedRefs = useRef<React.RefObject<HTMLElement>[]>([])
|
||||
@ -181,7 +183,7 @@ export const CodeViewer: FC<CodeViewerProps> = ({
|
||||
return (
|
||||
<Box className="relative">
|
||||
<OverlayScrollbarsComponent
|
||||
className={`${isShowMore ? 'code-scroll-x' : ''}`}
|
||||
className={`${isShowMore ? 'code-scroll-x pb-2' : ''}`}
|
||||
options={{
|
||||
overflow: {
|
||||
x: !isShowMore ? 'hidden' : 'scroll',
|
||||
|
@ -54,5 +54,4 @@ export type SplitPanePrimaryProps = { children: ReactNode } & DOMProps & {
|
||||
export type SplitPaneSecondaryProps = { children: ReactNode } & DOMProps & {
|
||||
isSplitPanelView?: boolean
|
||||
isFullWidth?: boolean
|
||||
disabled?: boolean // Added disabled prop
|
||||
}
|
||||
|
@ -1,13 +1,8 @@
|
||||
// import clsx from 'clsx'
|
||||
import { ReactElement } from 'react'
|
||||
import {
|
||||
collectionsStoreAtom,
|
||||
openProtectedContentModal,
|
||||
pendingProtectedCollectionId,
|
||||
settingsStoreAtom,
|
||||
} from '~/store'
|
||||
import { collectionsStoreAtom, settingsStoreAtom } from '~/store'
|
||||
import { useAtomValue } from 'jotai'
|
||||
import { LockKeyhole, Settings } from 'lucide-react'
|
||||
import { Settings } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
@ -23,7 +18,6 @@ import {
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
Flex,
|
||||
} from '../../ui'
|
||||
|
||||
export default function CollectionsDropDown({ children }: { children: ReactElement }) {
|
||||
@ -32,11 +26,7 @@ export default function CollectionsDropDown({ children }: { children: ReactEleme
|
||||
const navigate = useNavigate()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const {
|
||||
protectedCollections,
|
||||
hasPinProtectedCollections,
|
||||
isShowDisabledCollectionsOnNavBarMenu,
|
||||
} = useAtomValue(settingsStoreAtom)
|
||||
const { isShowDisabledCollectionsOnNavBarMenu } = useAtomValue(settingsStoreAtom)
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
@ -54,7 +44,7 @@ export default function CollectionsDropDown({ children }: { children: ReactEleme
|
||||
height: 'auto',
|
||||
maxHeight: '400px',
|
||||
width: '100%',
|
||||
minWidth: '220px',
|
||||
minWidth: '200px',
|
||||
}}
|
||||
autoHide={false}
|
||||
>
|
||||
@ -80,38 +70,14 @@ export default function CollectionsDropDown({ children }: { children: ReactEleme
|
||||
value={collectionId}
|
||||
disabled={!isEnabled}
|
||||
onClick={() => {
|
||||
const isProtectedCollection =
|
||||
hasPinProtectedCollections &&
|
||||
protectedCollections.includes(collectionId)
|
||||
|
||||
if (isProtectedCollection) {
|
||||
pendingProtectedCollectionId.value = collectionId
|
||||
openProtectedContentModal.value = true
|
||||
} else {
|
||||
selectCollectionById({
|
||||
selectCollection: { collectionId },
|
||||
})
|
||||
}
|
||||
selectCollectionById({
|
||||
selectCollection: {
|
||||
collectionId,
|
||||
},
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
className={`${
|
||||
isSelected ? 'font-semibold' : ''
|
||||
} items-center justify-start gap-2`}
|
||||
>
|
||||
{hasPinProtectedCollections &&
|
||||
protectedCollections.includes(collectionId) ? (
|
||||
<>
|
||||
<span className="truncate max-w-[150px]">{title}</span>
|
||||
<LockKeyhole
|
||||
size={12}
|
||||
className="text-gray-600 dark:text-gray-500 flex-shrink-0"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<span className="truncate max-w-[210px]">{title}</span>
|
||||
)}
|
||||
</Flex>
|
||||
<span className={isSelected ? 'font-semibold' : ''}>{title}</span>
|
||||
</DropdownMenuRadioItem>
|
||||
))}
|
||||
</DropdownMenuRadioGroup>
|
||||
|
@ -1,141 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { LANGUAGES } from '~/locales/languges'
|
||||
import { X } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import Modal from '~/components/molecules/modal'
|
||||
import { Button, Flex, Text } from '~/components/ui'
|
||||
|
||||
type Props = {
|
||||
open: boolean
|
||||
onLanguageSelected: (languageCode: string) => void
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
const detectBrowserLanguage = (): string => {
|
||||
const browserLang = navigator.language || navigator.languages?.[0] || 'en'
|
||||
|
||||
const langMappings: Record<string, string> = {
|
||||
en: 'en',
|
||||
'en-US': 'en',
|
||||
'en-GB': 'en',
|
||||
es: 'esES',
|
||||
'es-ES': 'esES',
|
||||
'es-MX': 'esES',
|
||||
de: 'de',
|
||||
'de-DE': 'de',
|
||||
fr: 'fr',
|
||||
'fr-FR': 'fr',
|
||||
it: 'it',
|
||||
'it-IT': 'it',
|
||||
tr: 'tr',
|
||||
'tr-TR': 'tr',
|
||||
ru: 'ru',
|
||||
'ru-RU': 'ru',
|
||||
uk: 'uk',
|
||||
'uk-UA': 'uk',
|
||||
zh: 'zhCN',
|
||||
'zh-CN': 'zhCN',
|
||||
'zh-Hans': 'zhCN',
|
||||
}
|
||||
|
||||
const mappedLang = langMappings[browserLang] || langMappings[browserLang.split('-')[0]]
|
||||
|
||||
const supportedCodes = LANGUAGES.map(lang => lang.code)
|
||||
return supportedCodes.includes(mappedLang) ? mappedLang : 'en'
|
||||
}
|
||||
|
||||
export default function LanguageSelectionModal({
|
||||
open,
|
||||
onLanguageSelected,
|
||||
onClose = () => {},
|
||||
}: Props) {
|
||||
const { t, i18n } = useTranslation()
|
||||
const [selectedLanguage, setSelectedLanguage] = useState<string>('en')
|
||||
const [detectedLanguage, setDetectedLanguage] = useState<string>('en')
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
const detected = detectBrowserLanguage()
|
||||
setDetectedLanguage(detected)
|
||||
setSelectedLanguage(detected)
|
||||
|
||||
if (detected !== i18n.language) {
|
||||
i18n.changeLanguage(detected)
|
||||
}
|
||||
}
|
||||
}, [open, i18n])
|
||||
|
||||
const handleLanguageChange = useCallback(
|
||||
(languageCode: string) => {
|
||||
setSelectedLanguage(languageCode)
|
||||
i18n.changeLanguage(languageCode)
|
||||
},
|
||||
[i18n]
|
||||
)
|
||||
|
||||
const handleStartApp = useCallback(() => {
|
||||
onLanguageSelected(selectedLanguage)
|
||||
}, [selectedLanguage, onLanguageSelected])
|
||||
|
||||
// Sort languages to put detected language first, then the rest
|
||||
const sortedLanguages = [...LANGUAGES].sort((a, b) => {
|
||||
if (a.code === detectedLanguage) return -1
|
||||
if (b.code === detectedLanguage) return 1
|
||||
return 0
|
||||
})
|
||||
|
||||
return (
|
||||
<Modal open={open} handleClose={() => {}} positionTop={true}>
|
||||
<Modal.Body className="min-w-[400px] max-w-[500px] relative">
|
||||
<Button
|
||||
variant="link"
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="hover:bg-slate-200 ring-0 focus-visible:ring-0 px-2 outline-none absolute right-1.5 top-1.5 text-slate-400 dark:text-slate-500 hover:text-slate-600 hover:dark:text-slate-400 hover:bg-transparent dark:hover:bg-transparent z-10"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</Button>
|
||||
<Modal.Content className="max-h-[400px]">
|
||||
<Flex className="w-full flex-col gap-3 mt-2 justify-center">
|
||||
<div className="text-center">
|
||||
<Text className="font-semibold text-2xl mb-2 justify-center">
|
||||
{t('Welcome to PasteBar', { ns: 'common2' })}
|
||||
</Text>
|
||||
<Text className="text-gray-600 dark:text-gray-400 justify-center">
|
||||
{t('Please select your preferred language', { ns: 'common2' })}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<Flex className="gap-3 flex-wrap items-start justify-evenly">
|
||||
{sortedLanguages.map(({ code, name, flag }) => (
|
||||
<Button
|
||||
key={code}
|
||||
variant="ghost"
|
||||
onClick={() => handleLanguageChange(code)}
|
||||
className={`text-sm font-normal bg-slate-50 dark:bg-slate-950 ${
|
||||
selectedLanguage === code
|
||||
? 'ring-2 ring-blue-400 dark:ring-blue-500 bg-slate-300 font-semibold dark:bg-slate-600 text-dark dark:text-slate-200 hover:dark:bg-slate-600 hover:bg-slate-300'
|
||||
: ''
|
||||
} dark:text-slate-200 px-3 !py-0.5`}
|
||||
>
|
||||
<span className="flags mr-3">{flag}</span> {name}
|
||||
</Button>
|
||||
))}
|
||||
</Flex>
|
||||
</div>
|
||||
</Flex>
|
||||
</Modal.Content>
|
||||
<Modal.Footer className="flex justify-center !pt-4 !pb-5">
|
||||
<Button
|
||||
onClick={handleStartApp}
|
||||
className="bg-blue-500 hover:bg-blue-600 text-white px-8 py-2"
|
||||
>
|
||||
{t('Start using PasteBar', { ns: 'common2' })}
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
)
|
||||
}
|
@ -42,7 +42,7 @@ type Props = {
|
||||
|
||||
export default function ModalLockScreenConfirmationWithPasscodeOrPassword({
|
||||
open,
|
||||
title = 'Confirm Passcode',
|
||||
title = 'Unlock Application Screen',
|
||||
isLockScreen = false,
|
||||
showPasscode = true,
|
||||
onConfirmSuccess,
|
||||
@ -171,16 +171,6 @@ export default function ModalLockScreenConfirmationWithPasscodeOrPassword({
|
||||
setFocusField(confirmPasscodeCurrentFocus.value)
|
||||
}, [confirmPasscodeCurrentFocus.value])
|
||||
|
||||
// Set initial focus when modal opens
|
||||
useEffect(() => {
|
||||
if (open && showPasscode && screenLockPassCode) {
|
||||
setTimeout(() => {
|
||||
confirmPasscodeCurrentFocus.value = 0
|
||||
setFocusField(0)
|
||||
}, 100)
|
||||
}
|
||||
}, [open, showPasscode])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
@ -326,7 +316,7 @@ export default function ModalLockScreenConfirmationWithPasscodeOrPassword({
|
||||
) : (
|
||||
<Text>
|
||||
<Trans
|
||||
i18nKey="Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode"
|
||||
i18nKey="Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode"
|
||||
values={{ screenLockPassCodeLength }}
|
||||
ns="settings"
|
||||
/>
|
||||
|
@ -3,67 +3,36 @@ import * as TabsPrimitive from '@radix-ui/react-tabs'
|
||||
|
||||
import { cn } from '~/lib/utils'
|
||||
|
||||
// Create a context to share the setting from TabsList to TabsTrigger
|
||||
const TabsContext = React.createContext({
|
||||
disableKeyboardNavigation: false,
|
||||
})
|
||||
|
||||
const Tabs = TabsPrimitive.Root
|
||||
|
||||
const TabsList = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.List>,
|
||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> & {
|
||||
disableKeyboardNavigation?: boolean
|
||||
}
|
||||
>(({ className, children, disableKeyboardNavigation = false, ...props }, ref) => (
|
||||
// The provider makes the 'disableKeyboardNavigation' value available to all child components
|
||||
<TabsContext.Provider value={{ disableKeyboardNavigation }}>
|
||||
<TabsPrimitive.List
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'inline-flex items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</TabsPrimitive.List>
|
||||
</TabsContext.Provider>
|
||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<TabsPrimitive.List
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'inline-flex items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsList.displayName = TabsPrimitive.List.displayName
|
||||
|
||||
const TabsTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
||||
>(({ className, onKeyDown, ...props }, ref) => {
|
||||
// Consume the context to get the setting from the parent TabsList
|
||||
const { disableKeyboardNavigation } = React.useContext(TabsContext)
|
||||
|
||||
// Create a new keydown handler
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {
|
||||
// If the feature is enabled, prevent arrow key navigation (with or without modifiers)
|
||||
if (disableKeyboardNavigation && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation() // Also stop propagation to prevent other handlers from running
|
||||
}
|
||||
|
||||
// IMPORTANT: Still call any original onKeyDown function that was passed in props
|
||||
onKeyDown?.(e)
|
||||
}
|
||||
|
||||
return (
|
||||
<TabsPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all data-[state=active]:bg-background dark:data-[state=active]:bg-gray-600 data-[state=active]:text-foreground data-[state=active]:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset disabled:pointer-events-none disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
// Conditionally apply our new handler ONLY if the prop is set
|
||||
onKeyDown={disableKeyboardNavigation ? handleKeyDown : onKeyDown}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
>(({ className, ...props }, ref) => (
|
||||
<TabsPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all data-[state=active]:bg-background dark:data-[state=active]:bg-gray-600 data-[state=active]:text-foreground data-[state=active]:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset disabled:pointer-events-none disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
||||
|
||||
const TabsContent = React.forwardRef<
|
||||
|
@ -372,12 +372,7 @@ export function useDeleteClipboardHistoryByIds() {
|
||||
export function useClearClipboardHistoryOlderThan() {
|
||||
const queryClient = useQueryClient()
|
||||
const { mutate: clearClipboardHistoryOlderThan } = useInvokeMutation<
|
||||
{
|
||||
durationType: string
|
||||
olderThen: string
|
||||
keepPinned?: boolean
|
||||
keepStarred?: boolean
|
||||
},
|
||||
{ durationType: string; olderThen: string },
|
||||
UniqueIdentifier
|
||||
>('clear_clipboard_history_older_than', {
|
||||
onSuccess: data => {
|
||||
@ -403,12 +398,7 @@ export function useClearClipboardHistoryOlderThan() {
|
||||
export function useClearRecentClipboardHistory() {
|
||||
const queryClient = useQueryClient()
|
||||
const { mutate: clearRecentClipboardHistory } = useInvokeMutation<
|
||||
{
|
||||
durationType: string
|
||||
duration: string
|
||||
keepPinned?: boolean
|
||||
keepStarred?: boolean
|
||||
},
|
||||
{ durationType: string; duration: string },
|
||||
UniqueIdentifier
|
||||
>('clear_recent_clipboard_history', {
|
||||
onSuccess: data => {
|
||||
|
@ -13,7 +13,7 @@ const useDeleteConfirmationTimer = ({
|
||||
onConfirmedDelete: () => Promise<void>
|
||||
onConfirmedReset?: () => void
|
||||
selectedHistoryItems: UniqueIdentifier[]
|
||||
hoveringHistoryRowId: Signal<UniqueIdentifier | null>
|
||||
hoveringHistoryRowId: Signal<UniqueIdentifier | null> | null
|
||||
timerDuration?: number
|
||||
}) => {
|
||||
const timerRef = useRef(null) as React.MutableRefObject<NodeJS.Timeout | null>
|
||||
@ -34,17 +34,15 @@ const useDeleteConfirmationTimer = ({
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current)
|
||||
}
|
||||
|
||||
if (selectedHistoryItems.length === 0) {
|
||||
if (hoveringHistoryRowId?.value && selectedHistoryItems.length === 0) {
|
||||
seHoveringHistoryIdDelete(hoveringHistoryRowId.value)
|
||||
}
|
||||
|
||||
setShowConfirmation(true)
|
||||
|
||||
timerRef.current = setTimeout(() => {
|
||||
resetTimer()
|
||||
}, timerDuration)
|
||||
}, [timerDuration, resetTimer, selectedHistoryItems, hoveringHistoryRowId])
|
||||
}, [timerDuration, resetTimer, selectedHistoryItems])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
|
@ -1,102 +0,0 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { UniqueIdentifier } from '@dnd-kit/core'
|
||||
import { Signal } from '@preact/signals-react'
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
|
||||
const useKeyboardDeleteConfirmation = ({
|
||||
onConfirmedDelete,
|
||||
keyboardSelectedItemId,
|
||||
onConfirmedReset,
|
||||
selectedHistoryItems,
|
||||
timerDuration = 3000,
|
||||
}: {
|
||||
onConfirmedDelete: () => Promise<void>
|
||||
onConfirmedReset?: () => void
|
||||
selectedHistoryItems: UniqueIdentifier[]
|
||||
keyboardSelectedItemId: Signal<UniqueIdentifier | null>
|
||||
timerDuration?: number
|
||||
}) => {
|
||||
const timerRef = useRef(null) as React.MutableRefObject<NodeJS.Timeout | null>
|
||||
const [showConfirmation, setShowConfirmation] = useState(false)
|
||||
const [keyboardItemIdDelete, setKeyboardItemIdDelete] =
|
||||
useState<UniqueIdentifier | null>(null)
|
||||
|
||||
const resetTimer = useCallback(() => {
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current)
|
||||
}
|
||||
setKeyboardItemIdDelete(null)
|
||||
setShowConfirmation(false)
|
||||
onConfirmedReset?.()
|
||||
}, [onConfirmedReset])
|
||||
|
||||
const startTimer = useCallback(() => {
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current)
|
||||
}
|
||||
|
||||
// Only proceed if there's a keyboard selected item and no multi-selection
|
||||
if (!keyboardSelectedItemId.value || selectedHistoryItems.length > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
setKeyboardItemIdDelete(keyboardSelectedItemId.value)
|
||||
setShowConfirmation(true)
|
||||
|
||||
timerRef.current = setTimeout(() => {
|
||||
resetTimer()
|
||||
}, timerDuration)
|
||||
}, [timerDuration, resetTimer, selectedHistoryItems, keyboardSelectedItemId])
|
||||
|
||||
// Reset confirmation when the keyboard selected item changes
|
||||
useEffect(() => {
|
||||
if (showConfirmation && keyboardItemIdDelete !== keyboardSelectedItemId.value) {
|
||||
resetTimer()
|
||||
}
|
||||
}, [keyboardSelectedItemId.value, showConfirmation, keyboardItemIdDelete, resetTimer])
|
||||
|
||||
// Reset confirmation when there are selected items (multi-selection mode)
|
||||
useEffect(() => {
|
||||
if (showConfirmation && selectedHistoryItems.length > 0) {
|
||||
resetTimer()
|
||||
}
|
||||
}, [selectedHistoryItems.length, showConfirmation, resetTimer])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
useHotkeys(
|
||||
['delete', 'backspace'],
|
||||
async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
// Only handle keyboard delete when there's a keyboard selected item and no multi-selection
|
||||
if (!keyboardSelectedItemId.value || selectedHistoryItems.length > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (showConfirmation) {
|
||||
await onConfirmedDelete()
|
||||
resetTimer()
|
||||
} else {
|
||||
startTimer()
|
||||
}
|
||||
},
|
||||
{
|
||||
enableOnFormTags: false,
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
showConfirmation,
|
||||
keyboardItemIdDelete,
|
||||
resetTimer,
|
||||
}
|
||||
}
|
||||
|
||||
export default useKeyboardDeleteConfirmation
|
@ -27,7 +27,7 @@ export function useLongPress(
|
||||
delay = 600,
|
||||
threshold = 10,
|
||||
cancelOnMove = true,
|
||||
preventDefault = true,
|
||||
preventDefault = true
|
||||
} = options
|
||||
|
||||
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
@ -64,7 +64,7 @@ export function useLongPress(
|
||||
const touch = 'touches' in e ? e.touches[0] : e
|
||||
startPositionRef.current = {
|
||||
x: touch.clientX,
|
||||
y: touch.clientY,
|
||||
y: touch.clientY
|
||||
}
|
||||
|
||||
if (preventDefault) {
|
||||
@ -120,11 +120,14 @@ export function useLongPress(
|
||||
}, [clear])
|
||||
|
||||
// Prevent context menu on long press
|
||||
const handleContextMenu = useCallback((e: React.MouseEvent) => {
|
||||
if (isLongPressTriggeredRef.current || timeoutRef.current) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}, [])
|
||||
const handleContextMenu = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
if (isLongPressTriggeredRef.current || timeoutRef.current) {
|
||||
e.preventDefault()
|
||||
}
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
return {
|
||||
onMouseDown: start as (e: React.MouseEvent) => void,
|
||||
@ -135,7 +138,7 @@ export function useLongPress(
|
||||
onTouchEnd: end as (e: React.TouchEvent) => void,
|
||||
onTouchMove: move as (e: React.TouchEvent) => void,
|
||||
onTouchCancel: cancel,
|
||||
onContextMenu: preventDefault ? handleContextMenu : undefined,
|
||||
onContextMenu: preventDefault ? handleContextMenu : undefined
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,4 +147,4 @@ export function useLongPressHOF() {
|
||||
return function (callback: () => void, options?: LongPressOptions) {
|
||||
return useLongPress(callback, options)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
import { useCallback, useRef } from 'react'
|
||||
import { UniqueIdentifier } from '@dnd-kit/core/dist/types'
|
||||
import { signal } from '@preact/signals-react'
|
||||
import { invoke } from '@tauri-apps/api/tauri'
|
||||
import { settingsStoreAtom } from '~/store'
|
||||
import { useAtomValue } from 'jotai'
|
||||
|
||||
import { applyTransform, TEXT_TRANSFORMS } from '~/lib/text-transforms'
|
||||
|
||||
// Signals for tracking special copy/paste operations
|
||||
export const specialCopiedItem = signal<UniqueIdentifier>('')
|
||||
export const specialPastedItem = signal<UniqueIdentifier>('')
|
||||
export const specialPastedItemCountDown = signal<number>(0)
|
||||
|
||||
interface UseSpecialCopyPasteOptions {
|
||||
delay?: number
|
||||
}
|
||||
|
||||
export const useSpecialCopyPasteHistoryItem = ({
|
||||
delay = 800,
|
||||
}: UseSpecialCopyPasteOptions = {}) => {
|
||||
const { copyPasteDelay } = useAtomValue(settingsStoreAtom)
|
||||
const countdownRef = useRef<NodeJS.Timeout>()
|
||||
|
||||
// Special copy function - applies transformation and copies to clipboard
|
||||
const specialCopy = async (
|
||||
historyId: UniqueIdentifier,
|
||||
value: string,
|
||||
transformId: string
|
||||
): Promise<void> => {
|
||||
try {
|
||||
if (!value || !historyId) {
|
||||
console.warn('No value or historyId to copy')
|
||||
return
|
||||
}
|
||||
|
||||
// Set the signal to show UI feedback
|
||||
specialCopiedItem.value = historyId
|
||||
|
||||
// Apply the text transformation - this will throw if it fails
|
||||
const transformedText = await applyTransform(value, transformId)
|
||||
|
||||
// Only copy if transformation was successful
|
||||
setTimeout(() => {
|
||||
invoke('copy_text', { text: transformedText })
|
||||
.then(res => {
|
||||
if (res === 'ok') {
|
||||
requestAnimationFrame(() => {
|
||||
specialCopiedItem.value = ''
|
||||
})
|
||||
} else {
|
||||
specialCopiedItem.value = ''
|
||||
console.error('Failed to copy transformed text', res)
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
specialCopiedItem.value = ''
|
||||
console.error('Failed to copy transformed text', err)
|
||||
})
|
||||
}, delay)
|
||||
} catch (error) {
|
||||
// Clear UI feedback immediately on transformation error
|
||||
specialCopiedItem.value = ''
|
||||
console.error('Failed to special copy - transformation error:', error)
|
||||
// Don't copy anything to clipboard when transformation fails
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Countdown helper for paste operations
|
||||
const pasteCountdown = useCallback(
|
||||
(initialCount: number, intervalMs = 1000): Promise<void> => {
|
||||
clearInterval(countdownRef.current)
|
||||
return new Promise(resolve => {
|
||||
specialPastedItemCountDown.value = initialCount
|
||||
countdownRef.current = setInterval(() => {
|
||||
if (specialPastedItemCountDown.value > 0) {
|
||||
if (specialPastedItemCountDown.value === 1) {
|
||||
resolve()
|
||||
}
|
||||
specialPastedItemCountDown.value -= 1
|
||||
} else {
|
||||
clearInterval(countdownRef.current)
|
||||
}
|
||||
}, intervalMs)
|
||||
})
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
// Execute paste action with transformed text
|
||||
const executePasteAction = (text: string, delay = 0): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
invoke('copy_paste', { text, delay })
|
||||
.then(res => {
|
||||
if (res === 'ok') {
|
||||
resolve()
|
||||
} else {
|
||||
console.error('Failed to paste transformed text', res)
|
||||
reject()
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Failed to paste transformed text', err)
|
||||
reject()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Special paste function - applies transformation and pastes directly
|
||||
const specialPaste = async (
|
||||
historyId: UniqueIdentifier,
|
||||
value: string,
|
||||
transformId: string,
|
||||
delaySeconds?: number
|
||||
): Promise<void> => {
|
||||
try {
|
||||
delaySeconds = delaySeconds ?? copyPasteDelay
|
||||
|
||||
if (!value || !historyId) {
|
||||
console.warn('No value or historyId to paste')
|
||||
return
|
||||
}
|
||||
|
||||
// Set the signal to show UI feedback
|
||||
specialPastedItem.value = historyId
|
||||
|
||||
// Apply the text transformation - this will throw if it fails
|
||||
const transformedText = await applyTransform(value, transformId)
|
||||
|
||||
// Handle countdown if delay is specified (only if transformation succeeded)
|
||||
if (delaySeconds > 0) {
|
||||
await pasteCountdown(delaySeconds)
|
||||
}
|
||||
|
||||
// Execute paste with transformed text (only if transformation succeeded)
|
||||
await executePasteAction(transformedText, 0)
|
||||
|
||||
// Clear the signal after a short delay
|
||||
setTimeout(() => {
|
||||
requestAnimationFrame(() => {
|
||||
specialPastedItem.value = ''
|
||||
specialPastedItemCountDown.value = 0
|
||||
})
|
||||
}, delay)
|
||||
} catch (error) {
|
||||
// Clear UI feedback immediately on transformation error
|
||||
specialPastedItem.value = ''
|
||||
specialPastedItemCountDown.value = 0
|
||||
console.error('Failed to special paste - transformation error:', error)
|
||||
// Don't paste anything when transformation fails
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
specialCopy,
|
||||
specialPaste,
|
||||
availableTransforms: TEXT_TRANSFORMS,
|
||||
specialCopiedItem: specialCopiedItem.value,
|
||||
specialPastedItem: specialPastedItem.value,
|
||||
specialPastedItemCountDown: specialPastedItemCountDown.value,
|
||||
}
|
||||
}
|
@ -16,12 +16,9 @@ import {
|
||||
onBoardingTourSingleElements,
|
||||
openAboutPasteBarModal,
|
||||
openActionConfirmModal,
|
||||
openAddSelectedTextModal,
|
||||
openContactUsFormModal,
|
||||
openOnBoardingTourName,
|
||||
openOSXSystemPermissionsModal,
|
||||
openProtectedContentModal,
|
||||
pendingProtectedCollectionId,
|
||||
playerStoreAtom,
|
||||
resetPassCodeNextDelayInSeconds,
|
||||
resetPassCodeNumberOfTried,
|
||||
@ -33,7 +30,6 @@ import {
|
||||
showUpdateChecking,
|
||||
uiStore,
|
||||
uiStoreAtom,
|
||||
visibilityCopyPopup,
|
||||
} from '~/store'
|
||||
import { clsx } from 'clsx'
|
||||
import { useAtomValue } from 'jotai'
|
||||
@ -58,9 +54,9 @@ import ModalLockScreenConfirmationWithPasscodeOrPassword from '~/components/orga
|
||||
import ModalOSXSystemPermissions from '~/components/organisms/modals/system-permissions-osx-modal'
|
||||
import { Box, Button, Flex, Text } from '~/components/ui'
|
||||
|
||||
import { useSelectCollectionById } from '~/hooks/queries/use-collections'
|
||||
import { useClipboardPaste, useCopyPaste } from '~/hooks/use-copypaste'
|
||||
import { useLocalStorage } from '~/hooks/use-localstorage'
|
||||
import { useSignal } from '~/hooks/use-signal'
|
||||
|
||||
import { CreateDashboardItemType } from '~/types/menu'
|
||||
|
||||
@ -91,7 +87,6 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
|
||||
const { historyListSimpleBar, clipboardHistory } = useAtomValue(
|
||||
clipboardHistoryStoreAtom
|
||||
)
|
||||
const { selectCollectionById } = useSelectCollectionById()
|
||||
|
||||
const {
|
||||
appToursCompletedList,
|
||||
@ -110,6 +105,8 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
|
||||
|
||||
const [isCopied, copyToClipboard] = useCopyPaste({})
|
||||
const [pastedText, pastedItemCountDown, pasteToClipboard] = useClipboardPaste({})
|
||||
const visibilityCopyPopup = useSignal(false)
|
||||
const openAddSelectedTextModal = useSignal(false)
|
||||
|
||||
const [positionCopyPopup, setPositionCopyPopup] = useState({ top: 0, left: 0 })
|
||||
|
||||
@ -126,7 +123,7 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
|
||||
const refRect = mainContentRef.current
|
||||
? mainContentRef.current.getBoundingClientRect()
|
||||
: new DOMRect(0)
|
||||
const top = rect.top - refRect.top - 10
|
||||
const top = rect.top - refRect.top
|
||||
const left =
|
||||
maxWidth > 0
|
||||
? rect.left + rect.width / 2 - refRect.left > maxWidth
|
||||
@ -546,7 +543,10 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
|
||||
)}
|
||||
{openActionConfirmModal.value && (
|
||||
<ModalLockScreenConfirmationWithPasscodeOrPassword
|
||||
title={actionNameForConfirmModal.value ?? undefined}
|
||||
title={t('Confirm {{action}}', {
|
||||
ns: 'common',
|
||||
action: actionNameForConfirmModal.value,
|
||||
})}
|
||||
open
|
||||
onClose={() => {
|
||||
openActionConfirmModal.value = false
|
||||
@ -615,30 +615,6 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
|
||||
element={onBoardingTourSingleElements.value}
|
||||
/>
|
||||
)}
|
||||
{openProtectedContentModal.value && (
|
||||
<ModalLockScreenConfirmationWithPasscodeOrPassword
|
||||
open={openProtectedContentModal.value}
|
||||
// no need to translate this will be done in the modal
|
||||
title="Enter PIN to Access Protected Collection"
|
||||
isLockScreen={false}
|
||||
showPasscode={true}
|
||||
onConfirmSuccess={() => {
|
||||
openProtectedContentModal.value = false
|
||||
if (pendingProtectedCollectionId.value) {
|
||||
selectCollectionById({
|
||||
selectCollection: {
|
||||
collectionId: pendingProtectedCollectionId.value,
|
||||
},
|
||||
})
|
||||
pendingProtectedCollectionId.value = null
|
||||
}
|
||||
}}
|
||||
onClose={() => {
|
||||
openProtectedContentModal.value = false
|
||||
pendingProtectedCollectionId.value = null
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ import {
|
||||
openAboutPasteBarModal,
|
||||
openContactUsFormModal,
|
||||
openOnBoardingTourName,
|
||||
openProtectedContentModal,
|
||||
pendingProtectedCollectionId,
|
||||
playerStoreAtom,
|
||||
settingsStoreAtom,
|
||||
showInvalidTrackWarningAddSong,
|
||||
@ -46,11 +44,9 @@ import {
|
||||
ExternalLink,
|
||||
FileCog,
|
||||
LibrarySquare,
|
||||
LockKeyhole,
|
||||
Maximize,
|
||||
Minus,
|
||||
Pause,
|
||||
PinOff,
|
||||
Play,
|
||||
Plus,
|
||||
RefreshCw,
|
||||
@ -94,7 +90,6 @@ import { Badge, Box, Button, Flex, Shortcut, Text } from '~/components/ui'
|
||||
import { useSelectCollectionById } from '~/hooks/queries/use-collections'
|
||||
import { useDeleteClipboardHistoryByIds } from '~/hooks/queries/use-history-items'
|
||||
import { useDeleteItemById } from '~/hooks/queries/use-items'
|
||||
import { useSignal } from '~/hooks/use-signal'
|
||||
|
||||
import { PlayerMenu } from '../components/audio-player/PlayerMenu'
|
||||
import Logo from './Logo'
|
||||
@ -130,16 +125,6 @@ export function NavBar() {
|
||||
const { selectCollectionById } = useSelectCollectionById()
|
||||
const isDark = themeDark()
|
||||
|
||||
const onTopWindow = () => {
|
||||
appWindow?.setAlwaysOnTop(true)
|
||||
setIsMainWindowOnTop(true)
|
||||
}
|
||||
|
||||
const offTopWindow = () => {
|
||||
appWindow?.setAlwaysOnTop(false)
|
||||
setIsMainWindowOnTop(false)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
invoke('is_autostart_enabled').then(isEnabled => {
|
||||
setIsAutoStartEnabled(Boolean(isEnabled))
|
||||
@ -215,10 +200,6 @@ export function NavBar() {
|
||||
setIsSavedClipsPanelVisibleOnly,
|
||||
isSimplifiedLayout,
|
||||
setIsSimplifiedLayout,
|
||||
isMainWindowOnTop,
|
||||
setIsMainWindowOnTop,
|
||||
hasPinProtectedCollections,
|
||||
protectedCollections,
|
||||
} = useAtomValue(settingsStoreAtom)
|
||||
|
||||
const {
|
||||
@ -237,13 +218,6 @@ export function NavBar() {
|
||||
isSwapPanels,
|
||||
} = useAtomValue(uiStoreAtom)
|
||||
|
||||
// Restore window always-on-top state on startup
|
||||
useEffect(() => {
|
||||
if (isMainWindowOnTop) {
|
||||
appWindow?.setAlwaysOnTop(true)
|
||||
}
|
||||
}, [isMainWindowOnTop])
|
||||
|
||||
useHotkeys(['alt+b', 'ctrl+b', 'meta+b'], () => {
|
||||
navigate('/history', { replace: true })
|
||||
})
|
||||
@ -876,7 +850,7 @@ export function NavBar() {
|
||||
>
|
||||
{isSplitPanelView
|
||||
? t('Close History Window', { ns: 'common' })
|
||||
: t('Open History Window', { ns: 'common' })}
|
||||
: t('Split History Window', { ns: 'common' })}
|
||||
<MenubarShortcut className="ml-2">
|
||||
<Shortcut keys="CTRL+N" />
|
||||
</MenubarShortcut>
|
||||
@ -1110,19 +1084,6 @@ export function NavBar() {
|
||||
{t('Show Disabled Collections', { ns: 'settings' })}
|
||||
</MenubarCheckboxItem>
|
||||
|
||||
<MenubarCheckboxItem
|
||||
checked={isMainWindowOnTop}
|
||||
onClick={() => {
|
||||
if (!isMainWindowOnTop) {
|
||||
onTopWindow()
|
||||
} else {
|
||||
offTopWindow()
|
||||
}
|
||||
}}
|
||||
>
|
||||
{t('Show Always on Top', { ns: 'navbar' })}
|
||||
</MenubarCheckboxItem>
|
||||
|
||||
<MenubarSeparator />
|
||||
|
||||
<MenubarCheckboxItem
|
||||
@ -1269,7 +1230,7 @@ export function NavBar() {
|
||||
height: 'auto',
|
||||
maxHeight: '400px',
|
||||
width: '100%',
|
||||
minWidth: '220px',
|
||||
minWidth: '200px',
|
||||
}}
|
||||
autoHide={false}
|
||||
>
|
||||
@ -1296,40 +1257,16 @@ export function NavBar() {
|
||||
value={collectionId}
|
||||
disabled={!isEnabled}
|
||||
onClick={() => {
|
||||
const isProtectedCollection =
|
||||
hasPinProtectedCollections &&
|
||||
protectedCollections.includes(collectionId)
|
||||
|
||||
if (isProtectedCollection) {
|
||||
pendingProtectedCollectionId.value = collectionId
|
||||
openProtectedContentModal.value = true
|
||||
} else {
|
||||
selectCollectionById({
|
||||
selectCollection: {
|
||||
collectionId,
|
||||
},
|
||||
})
|
||||
}
|
||||
selectCollectionById({
|
||||
selectCollection: {
|
||||
collectionId,
|
||||
},
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
className={`${
|
||||
isSelected ? 'font-semibold' : ''
|
||||
} items-center justify-start gap-2`}
|
||||
>
|
||||
{hasPinProtectedCollections &&
|
||||
protectedCollections.includes(collectionId) ? (
|
||||
<>
|
||||
<span className="truncate max-w-[150px]">{title}</span>
|
||||
<LockKeyhole
|
||||
size={12}
|
||||
className="text-gray-600 dark:text-gray-500 flex-shrink-0"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<span className="truncate max-w-[210px]">{title}</span>
|
||||
)}
|
||||
</Flex>
|
||||
<span className={isSelected ? 'font-semibold' : ''}>
|
||||
{title}
|
||||
</span>
|
||||
</MenubarRadioItem>
|
||||
))}
|
||||
</MenubarRadioGroup>
|
||||
@ -1369,7 +1306,7 @@ export function NavBar() {
|
||||
toggleIsSplitPanelView()
|
||||
}}
|
||||
id="navbar-toggle-history-split"
|
||||
title={t('Open History Window', { ns: 'common' })}
|
||||
title={t('Split History Window', { ns: 'common' })}
|
||||
variant="ghost"
|
||||
className="relative h-7 focus:outline-none px-2 mr-0 ml-2 !bg-slate-50 text-slate-400 dark:!bg-slate-900 dark:hover:!bg-slate-800 hover:text-slate-600 dark:text-slate-400"
|
||||
>
|
||||
@ -2022,31 +1959,16 @@ export function NavBar() {
|
||||
<Icons.minimize className="h-3 w-3" />
|
||||
</Button>
|
||||
{!isHistoryPanelVisibleOnly && (
|
||||
<>
|
||||
{!isMainWindowOnTop ? (
|
||||
<Button
|
||||
onClick={maximizeWindow}
|
||||
title={t('Window:::Maximize Window', { ns: 'navbar' })}
|
||||
variant="ghost"
|
||||
className={`h-8 focus:outline-none ${
|
||||
isShowNavBarItems ? 'opacity-1' : 'opacity-0'
|
||||
}`}
|
||||
>
|
||||
<Maximize className="h-4 w-4" />
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
onClick={offTopWindow}
|
||||
title={t('Window:::UnPin Window', { ns: 'navbar' })}
|
||||
variant="ghost"
|
||||
className={`h-8 focus:outline-none ${
|
||||
isShowNavBarItems ? 'opacity-1' : 'opacity-0'
|
||||
}`}
|
||||
>
|
||||
<PinOff className="stroke-[1.8px] h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
<Button
|
||||
onClick={maximizeWindow}
|
||||
title={t('Window:::Maximize Window', { ns: 'navbar' })}
|
||||
variant="ghost"
|
||||
className={`h-8 focus:outline-none ${
|
||||
isShowNavBarItems ? 'opacity-1' : 'opacity-0'
|
||||
}`}
|
||||
>
|
||||
<Maximize className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={hideWindow}
|
||||
|
@ -1,505 +0,0 @@
|
||||
/**
|
||||
* Text transformation utilities for special copy/paste operations
|
||||
* Organized by categories with enable/disable controls
|
||||
*/
|
||||
|
||||
import DOMPurify from 'dompurify'
|
||||
|
||||
export interface TextTransform {
|
||||
id: string
|
||||
label: string
|
||||
transform: (text: string) => string | Promise<string>
|
||||
}
|
||||
|
||||
export interface TransformCategory {
|
||||
id: string
|
||||
label: string
|
||||
transforms?: TextTransform[]
|
||||
subcategories?: TransformSubcategory[]
|
||||
}
|
||||
|
||||
export interface TransformSubcategory {
|
||||
id: string
|
||||
label: string
|
||||
transforms: TextTransform[]
|
||||
}
|
||||
|
||||
// Transform functions for Text Case
|
||||
const toUpperCase = (text: string): string => text.toUpperCase()
|
||||
const toLowerCase = (text: string): string => text.toLowerCase()
|
||||
const toTitleCase = (text: string): string =>
|
||||
text.replace(/\b\w/g, char => char.toUpperCase()) // Renamed from toCapitalize
|
||||
const toSentenceCase = (text: string): string =>
|
||||
text.charAt(0).toUpperCase() + text.slice(1).toLowerCase() // Keep as is, assumes single string capitalization
|
||||
const toInvertCase = (text: string): string =>
|
||||
text.replace(/[a-zA-Z]/g, char =>
|
||||
char === char.toUpperCase() ? char.toLowerCase() : char.toUpperCase()
|
||||
)
|
||||
|
||||
// Transform functions for Code Formatting
|
||||
const toCamelCase = (text: string): string => {
|
||||
const normalized = text.replace(/[^a-zA-Z0-9]+/g, ' ').trim() // Normalize spaces/delimiters
|
||||
return normalized
|
||||
.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) =>
|
||||
index === 0 ? word.toLowerCase() : word.toUpperCase()
|
||||
)
|
||||
.replace(/\s+/g, '')
|
||||
}
|
||||
|
||||
const toSnakeCase = (text: string): string => {
|
||||
return text
|
||||
.replace(/([a-z0-9])([A-Z])/g, '$1_$2') // Add underscore before capital letters (camelCase to snake_case part)
|
||||
.replace(/[^a-zA-Z0-9]+/g, '_') // Replace non-alphanumeric with underscore
|
||||
.toLowerCase()
|
||||
.replace(/^_|_$/g, '') // Remove leading/trailing underscores
|
||||
}
|
||||
|
||||
const toKebabCase = (text: string): string => {
|
||||
return text
|
||||
.replace(/([a-z0-9])([A-Z])/g, '$1-$2') // Add hyphen before capital letters
|
||||
.replace(/[^a-zA-Z0-9]+/g, '-') // Replace non-alphanumeric with hyphen
|
||||
.toLowerCase()
|
||||
.replace(/^-|-$/g, '') // Remove leading/trailing hyphens
|
||||
}
|
||||
|
||||
const toPascalCase = (text: string): string => {
|
||||
const normalized = text.replace(/[^a-zA-Z0-9]+/g, ' ').trim() // Normalize spaces/delimiters
|
||||
return normalized
|
||||
.replace(/(?:^\w|[A-Z]|\b\w)/g, word => word.toUpperCase())
|
||||
.replace(/\s+/g, '')
|
||||
}
|
||||
|
||||
// Transform functions for Whitespace & Lines
|
||||
const trimWhiteSpace = (text: string): string => text.trim()
|
||||
const removeLineFeeds = (
|
||||
text: string
|
||||
): string => // More aggressive removal of multiple line feeds to single space
|
||||
text
|
||||
.replace(/\r?\n|\r/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
const addOneLineFeed = (text: string): string => text + '\n'
|
||||
const addTwoLineFeeds = (text: string): string => text + '\n\n'
|
||||
const removeExtraSpaces = (text: string): string => text.replace(/\s+/g, ' ')
|
||||
const sortLinesAlphabetically = (text: string): string => {
|
||||
const lines = text.split(/\r?\n|\r/)
|
||||
return lines.sort((a, b) => a.localeCompare(b)).join('\n')
|
||||
}
|
||||
const removeDuplicateLines = (text: string): string => {
|
||||
const lines = text.split(/\r?\n|\r/)
|
||||
const uniqueLines = [...new Set(lines)]
|
||||
return uniqueLines.join('\n')
|
||||
}
|
||||
const addLineNumbers = (text: string): string => {
|
||||
const lines = text.split(/\r?\n|\r/)
|
||||
return lines.map((line, index) => `${index + 1}. ${line}`).join('\n')
|
||||
}
|
||||
|
||||
// Transform functions for Encoding & Security
|
||||
const toBase64Encode = (text: string): string => {
|
||||
try {
|
||||
// This is generally the most robust method for UTF-8 in browsers without polyfills
|
||||
return btoa(String.fromCharCode(...new TextEncoder().encode(text)))
|
||||
} catch (e) {
|
||||
console.error('Base64 encode error:', e)
|
||||
return text
|
||||
}
|
||||
}
|
||||
const toBase64Decode = (text: string): string => {
|
||||
try {
|
||||
// This is generally the most robust method for UTF-8 in browsers without polyfills
|
||||
return new TextDecoder().decode(
|
||||
Uint8Array.from(atob(text), charCode => charCode.charCodeAt(0))
|
||||
)
|
||||
} catch (e) {
|
||||
console.error('Base64 decode error:', e)
|
||||
return text
|
||||
}
|
||||
}
|
||||
const toUrlEncode = (text: string): string => encodeURIComponent(text)
|
||||
const toUrlDecode = (text: string): string => {
|
||||
try {
|
||||
return decodeURIComponent(text)
|
||||
} catch (e) {
|
||||
console.error('URL decode error:', e)
|
||||
return text
|
||||
}
|
||||
}
|
||||
|
||||
function toHtmlEncode(str: string): string {
|
||||
// Ensure the input is a string
|
||||
if (typeof str !== 'string') {
|
||||
console.warn('Input to encodeHtmlSpecialChars was not a string:', str)
|
||||
return '' // Or throw an error, depending on desired behavior
|
||||
}
|
||||
|
||||
return str.replace(/[&<>"']/g, function (char) {
|
||||
switch (char) {
|
||||
case '&':
|
||||
return '&' // Ampersand
|
||||
case '<':
|
||||
return '<' // Less than
|
||||
case '>':
|
||||
return '>' // Greater than
|
||||
case '"':
|
||||
return '"' // Double quote
|
||||
case "'":
|
||||
return ''' // Single quote (apostrophe)
|
||||
default:
|
||||
return char // Should not happen with the given regex, but good practice
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const toHtmlDecode = (text: string): string => {
|
||||
const sanitized = DOMPurify.sanitize(text, { RETURN_DOM: true })
|
||||
return sanitized.textContent || ''
|
||||
}
|
||||
|
||||
// Transform functions for Text Tools
|
||||
const reverseText = (text: string): string => text.split('').reverse().join('')
|
||||
const addCurrentDateTime = (text: string): string => {
|
||||
const now = new Date()
|
||||
return text + '\n' + now.toLocaleString()
|
||||
}
|
||||
const countCharacters = (text: string): string => {
|
||||
const count = text.length
|
||||
return `Character count: ${count}`
|
||||
}
|
||||
const countWords = (text: string): string => {
|
||||
const words = text
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
.filter(word => word.length > 0)
|
||||
const count = words.length
|
||||
return `Word count: ${count}`
|
||||
}
|
||||
const countLines = (text: string): string => {
|
||||
const lines = text.split(/\r?\n|\r/)
|
||||
const count = lines.length
|
||||
return `Line count: ${count}`
|
||||
}
|
||||
const countSentences = (text: string): string => {
|
||||
const sentences = text.split(/[.!?]+/).filter(sentence => sentence.trim().length > 0)
|
||||
const count = sentences.length
|
||||
return `Sentence count: ${count}`
|
||||
}
|
||||
const toJsonStringify = (text: string): string => {
|
||||
try {
|
||||
const parsed = JSON.parse(text)
|
||||
return JSON.stringify(parsed, null, 2)
|
||||
} catch {
|
||||
return JSON.stringify(text) // If not valid JSON, stringify the text itself
|
||||
}
|
||||
}
|
||||
|
||||
// Format Converter subcategories - organized by source format
|
||||
const formatConverterSubcategories = [
|
||||
{
|
||||
id: 'html',
|
||||
label: 'HTML',
|
||||
transforms: [
|
||||
{
|
||||
id: 'htmlToMarkdown',
|
||||
label: 'HTML to Markdown',
|
||||
transform: (text: string) => convertFormat(text, 'html_to_markdown'),
|
||||
},
|
||||
{
|
||||
id: 'htmlToReact',
|
||||
label: 'HTML to React JSX',
|
||||
transform: (text: string) => convertFormat(text, 'html_to_react'),
|
||||
},
|
||||
{
|
||||
id: 'htmlToReactComponent',
|
||||
label: 'HTML to React Component',
|
||||
transform: (text: string) => convertFormat(text, 'html_to_react_components'),
|
||||
},
|
||||
{
|
||||
id: 'htmlToText',
|
||||
label: 'HTML to Text',
|
||||
transform: (text: string) => convertFormat(text, 'html_to_text'),
|
||||
},
|
||||
{
|
||||
id: 'htmlToPlainText',
|
||||
label: 'HTML to Plain Text',
|
||||
transform: async (text: string) => {
|
||||
// dynamic import for html-to-text
|
||||
const { convert } = await import('html-to-text')
|
||||
return convert(text, {
|
||||
wordwrap: 130,
|
||||
preserveNewlines: false,
|
||||
// selectors: [{ selector: 'a', format: }],
|
||||
})
|
||||
.replace(/\n{3,}/g, '\n\n') // Replace 3+ newlines with double newline
|
||||
.trim() // Remove leading and trailing whitespace
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'markdown',
|
||||
label: 'Markdown',
|
||||
transforms: [
|
||||
{
|
||||
id: 'markdownToHtml',
|
||||
label: 'Markdown to HTML',
|
||||
transform: (text: string) => convertFormat(text, 'markdown_to_html'),
|
||||
},
|
||||
{
|
||||
id: 'markdownToText',
|
||||
label: 'Markdown to Text',
|
||||
transform: (text: string) => convertFormat(text, 'markdown_to_text'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'json',
|
||||
label: 'JSON',
|
||||
transforms: [
|
||||
{
|
||||
id: 'jsonToCsv',
|
||||
label: 'JSON to CSV',
|
||||
transform: (text: string) => convertFormat(text, 'json_to_csv'),
|
||||
},
|
||||
{
|
||||
id: 'jsonToYaml',
|
||||
label: 'JSON to YAML',
|
||||
transform: (text: string) => convertFormat(text, 'json_to_yaml'),
|
||||
},
|
||||
{
|
||||
id: 'jsonToXml',
|
||||
label: 'JSON to XML',
|
||||
transform: (text: string) => convertFormat(text, 'json_to_xml'),
|
||||
},
|
||||
{
|
||||
id: 'jsonToToml',
|
||||
label: 'JSON to TOML',
|
||||
transform: (text: string) => convertFormat(text, 'json_to_toml'),
|
||||
},
|
||||
{
|
||||
id: 'jsonToTable',
|
||||
label: 'JSON to Markdown Table',
|
||||
transform: (text: string) => convertFormat(text, 'json_to_table'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'csv',
|
||||
label: 'CSV',
|
||||
transforms: [
|
||||
{
|
||||
id: 'csvToJson',
|
||||
label: 'CSV to JSON',
|
||||
transform: (text: string) => convertFormat(text, 'csv_to_json'),
|
||||
},
|
||||
{
|
||||
id: 'csvToTable',
|
||||
label: 'CSV to Markdown Table',
|
||||
transform: (text: string) => convertFormat(text, 'csv_to_table'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'yaml',
|
||||
label: 'YAML',
|
||||
transforms: [
|
||||
{
|
||||
id: 'yamlToJson',
|
||||
label: 'YAML to JSON',
|
||||
transform: (text: string) => convertFormat(text, 'yaml_to_json'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'xml',
|
||||
label: 'XML',
|
||||
transforms: [
|
||||
{
|
||||
id: 'xmlToJson',
|
||||
label: 'XML to JSON',
|
||||
transform: (text: string) => convertFormat(text, 'xml_to_json'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'toml',
|
||||
label: 'TOML',
|
||||
transforms: [
|
||||
{
|
||||
id: 'tomlToJson',
|
||||
label: 'TOML to JSON',
|
||||
transform: (text: string) => convertFormat(text, 'toml_to_json'),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// Helper function to call Rust format conversion
|
||||
function convertFormat(text: string, conversionType: string): Promise<string> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const { invoke } = await import('@tauri-apps/api/tauri')
|
||||
const result = await invoke('format_convert', { text, conversionType })
|
||||
resolve(result as string)
|
||||
} catch (error) {
|
||||
console.error(`Format conversion failed for ${conversionType}:`, error)
|
||||
|
||||
// Show error dialog to user
|
||||
try {
|
||||
const { message } = await import('@tauri-apps/api/dialog')
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
|
||||
// Clean up the error message for better user experience
|
||||
const cleanErrorMessage = errorMessage
|
||||
.replace(/^Error: /, '')
|
||||
.replace(/^format_convert returned an error: /, '')
|
||||
|
||||
await message(`${cleanErrorMessage}`, {
|
||||
title: 'Format Conversion Error',
|
||||
type: 'error',
|
||||
})
|
||||
} catch (dialogError) {
|
||||
console.error('Failed to show error dialog:', dialogError)
|
||||
}
|
||||
|
||||
// Reject the promise so the error propagates and prevents copy/paste
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Special Convert category will be implemented in Rust later for better performance
|
||||
|
||||
// Categorized transformations
|
||||
export const TRANSFORM_CATEGORIES: TransformCategory[] = [
|
||||
{
|
||||
id: 'textCase',
|
||||
label: 'Text Case',
|
||||
transforms: [
|
||||
{ id: 'upperCase', label: 'UPPER CASE', transform: toUpperCase },
|
||||
{ id: 'lowerCase', label: 'lower case', transform: toLowerCase },
|
||||
{ id: 'titleCase', label: 'Title Case', transform: toTitleCase },
|
||||
{ id: 'sentenceCase', label: 'Sentence case', transform: toSentenceCase },
|
||||
{ id: 'invertCase', label: 'iNVERT cASE', transform: toInvertCase },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'codeFormatting',
|
||||
label: 'Code Formatting',
|
||||
transforms: [
|
||||
{ id: 'camelCase', label: 'camelCase', transform: toCamelCase },
|
||||
{ id: 'snakeCase', label: 'snake_case', transform: toSnakeCase },
|
||||
{ id: 'kebabCase', label: 'kebab-case', transform: toKebabCase },
|
||||
{ id: 'pascalCase', label: 'PascalCase', transform: toPascalCase },
|
||||
{ id: 'jsonStringify', label: 'JSON Stringify', transform: toJsonStringify },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'whitespaceLines',
|
||||
label: 'Whitespace & Lines',
|
||||
transforms: [
|
||||
{ id: 'trimWhiteSpace', label: 'Trim White Space', transform: trimWhiteSpace },
|
||||
{ id: 'removeLineFeeds', label: 'Remove Line Feeds', transform: removeLineFeeds },
|
||||
{ id: 'addOneLineFeed', label: 'Add One Line Feed', transform: addOneLineFeed },
|
||||
{ id: 'addTwoLineFeeds', label: 'Add Two Line Feeds', transform: addTwoLineFeeds },
|
||||
{
|
||||
id: 'removeExtraSpaces',
|
||||
label: 'Remove Extra Spaces',
|
||||
transform: removeExtraSpaces,
|
||||
},
|
||||
{
|
||||
id: 'sortLinesAlphabetically',
|
||||
label: 'Sort Lines Alphabetically',
|
||||
transform: sortLinesAlphabetically,
|
||||
},
|
||||
{
|
||||
id: 'removeDuplicateLines',
|
||||
label: 'Remove Duplicate Lines',
|
||||
transform: removeDuplicateLines,
|
||||
},
|
||||
{ id: 'addLineNumbers', label: 'Add Line Numbers', transform: addLineNumbers },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'encodingSecurity',
|
||||
label: 'Encode/Decode',
|
||||
transforms: [
|
||||
{ id: 'base64Encode', label: 'Base64 Encode', transform: toBase64Encode },
|
||||
{ id: 'base64Decode', label: 'Base64 Decode', transform: toBase64Decode },
|
||||
{ id: 'urlEncode', label: 'URL Encode', transform: toUrlEncode },
|
||||
{ id: 'urlDecode', label: 'URL Decode', transform: toUrlDecode },
|
||||
{ id: 'htmlEncode', label: 'HTML Encode', transform: toHtmlEncode },
|
||||
{ id: 'htmlDecode', label: 'HTML Decode', transform: toHtmlDecode },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'textTools',
|
||||
label: 'Text Tools',
|
||||
transforms: [
|
||||
{ id: 'reverseText', label: 'Reverse Text', transform: reverseText },
|
||||
{
|
||||
id: 'addCurrentDateTime',
|
||||
label: 'Add Current Date/Time',
|
||||
transform: addCurrentDateTime,
|
||||
},
|
||||
{ id: 'countCharacters', label: 'Count Characters', transform: countCharacters },
|
||||
{ id: 'countWords', label: 'Count Words', transform: countWords },
|
||||
{ id: 'countLines', label: 'Count Lines', transform: countLines },
|
||||
{ id: 'countSentences', label: 'Count Sentences', transform: countSentences },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'formatConverter',
|
||||
label: 'Format Converter',
|
||||
subcategories: formatConverterSubcategories,
|
||||
},
|
||||
]
|
||||
|
||||
// Flat list of all transformations for backward compatibility
|
||||
export const TEXT_TRANSFORMS: TextTransform[] = TRANSFORM_CATEGORIES.flatMap(category => {
|
||||
if (category.subcategories) {
|
||||
// For categories with subcategories, flatten all transforms from all subcategories
|
||||
return category.subcategories.flatMap(subcategory => subcategory.transforms)
|
||||
} else {
|
||||
// For categories with direct transforms
|
||||
return category.transforms || []
|
||||
}
|
||||
})
|
||||
|
||||
// Helper to get a transform by ID
|
||||
export const getTransformById = (id: string): TextTransform | undefined =>
|
||||
TEXT_TRANSFORMS.find(t => t.id === id)
|
||||
|
||||
// Helper to get a category by ID
|
||||
export const getCategoryById = (id: string): TransformCategory | undefined =>
|
||||
TRANSFORM_CATEGORIES.find(c => c.id === id)
|
||||
|
||||
// Helper to apply a transform by ID
|
||||
export const applyTransform = async (
|
||||
text: string,
|
||||
transformId: string
|
||||
): Promise<string> => {
|
||||
const transform = getTransformById(transformId)
|
||||
if (!transform) {
|
||||
throw new Error(`Transform not found: ${transformId}`)
|
||||
}
|
||||
|
||||
try {
|
||||
const result = transform.transform(text)
|
||||
// Handle both sync and async transforms
|
||||
return await Promise.resolve(result)
|
||||
} catch (error) {
|
||||
console.error(`Transform failed for ${transformId}:`, error)
|
||||
// Re-throw the error so calling functions can handle it
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to get all category IDs
|
||||
export const getAllCategoryIds = (): string[] => TRANSFORM_CATEGORIES.map(c => c.id)
|
||||
|
||||
// Helper to get all transform IDs in a category
|
||||
export const getTransformIdsInCategory = (categoryId: string): string[] => {
|
||||
const category = getCategoryById(categoryId)
|
||||
return category ? category.transforms?.map(t => t.id) ?? [] : []
|
||||
}
|
@ -1,25 +1,9 @@
|
||||
import { UniqueIdentifier } from '@dnd-kit/core'
|
||||
import createBoardTree from '~/libs/create-board-tree'
|
||||
import { clsx, type ClassValue } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
import {
|
||||
currentBoardIndex,
|
||||
currentNavigationContext,
|
||||
keyboardSelectedBoardId,
|
||||
keyboardSelectedClipId,
|
||||
} from '~/store/signalStore'
|
||||
|
||||
import { MenuItem } from '~/types/menu'
|
||||
|
||||
// Navigation types and helper functions
|
||||
interface NavigationItem {
|
||||
id: UniqueIdentifier
|
||||
type: 'history' | 'board'
|
||||
parentId?: UniqueIdentifier | null
|
||||
depth: number
|
||||
}
|
||||
|
||||
const EMOJIREGEX =
|
||||
/(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/gm
|
||||
|
||||
@ -70,217 +54,6 @@ export function absoluteUrl(path: string) {
|
||||
return `${process.env.NEXT_PUBLIC_APP_URL}${path}`
|
||||
}
|
||||
|
||||
// Build a flattened navigation order that includes boards and sub-boards
|
||||
// Only boards are included in Left/Right navigation - clips are navigated with Up/Down within boards
|
||||
export function buildNavigationOrder(
|
||||
clipItems: any[],
|
||||
currentTab: string
|
||||
): NavigationItem[] {
|
||||
const navigationOrder: NavigationItem[] = []
|
||||
|
||||
// Add history placeholder - actual history navigation is handled by ClipboardHistoryPage
|
||||
navigationOrder.push({ id: 'history', type: 'history', depth: 0 })
|
||||
|
||||
// Get all boards and clips in the current tab
|
||||
const allItems = clipItems.filter(item => item.tabId === currentTab)
|
||||
|
||||
// Build board tree for proper nesting
|
||||
const boardTree = createBoardTree(clipItems, currentTab, null)
|
||||
|
||||
// Recursively add boards (but not clips - clips are navigated with Up/Down within boards)
|
||||
function addBoardAndContents(boardId: UniqueIdentifier, depth: number) {
|
||||
const board = allItems.find(item => item.itemId === boardId && item.isBoard)
|
||||
if (!board) return
|
||||
|
||||
// Add the board itself to navigation order
|
||||
navigationOrder.push({
|
||||
id: boardId,
|
||||
type: 'board',
|
||||
parentId: board.parentId,
|
||||
depth,
|
||||
})
|
||||
|
||||
// Get direct child boards (not clips) sorted by order
|
||||
const childBoards = allItems
|
||||
.filter(item => item.parentId === boardId && item.isBoard)
|
||||
.sort((a, b) => a.orderNumber - b.orderNumber)
|
||||
|
||||
// Add child boards recursively
|
||||
childBoards.forEach(child => {
|
||||
addBoardAndContents(child.itemId, depth + 1)
|
||||
})
|
||||
}
|
||||
|
||||
// Start with top-level boards
|
||||
const topLevelBoards = allItems
|
||||
.filter(item => item.isBoard && item.parentId === null)
|
||||
.sort((a, b) => a.orderNumber - b.orderNumber)
|
||||
|
||||
topLevelBoards.forEach(board => {
|
||||
addBoardAndContents(board.itemId, 1)
|
||||
})
|
||||
|
||||
return navigationOrder
|
||||
}
|
||||
|
||||
// Find current position in navigation order
|
||||
export function findCurrentNavigationIndex(navigationOrder: NavigationItem[]): number {
|
||||
if (currentNavigationContext.value === 'history') {
|
||||
return 0 // History is always at index 0
|
||||
} else if (currentNavigationContext.value === 'board') {
|
||||
if (keyboardSelectedBoardId.value) {
|
||||
// Find board position - since clips are not in navigation order,
|
||||
// we find the board that contains the selected clip
|
||||
return navigationOrder.findIndex(
|
||||
item => item.type === 'board' && item.id === keyboardSelectedBoardId.value
|
||||
)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Find the next non-empty board in the navigation order (skipping empty boards)
|
||||
export function findNextNonEmptyBoard(
|
||||
navigationOrder: NavigationItem[],
|
||||
startIndex: number,
|
||||
direction: 'forward' | 'backward',
|
||||
clipItems: any[],
|
||||
currentTab: string
|
||||
): NavigationItem | null {
|
||||
const maxAttempts = navigationOrder.length // Prevent infinite loops
|
||||
let currentIndex = startIndex
|
||||
|
||||
for (let i = 0; i < maxAttempts; i++) {
|
||||
// Move in the specified direction
|
||||
if (direction === 'forward') {
|
||||
currentIndex = currentIndex + 1
|
||||
// If we've gone past the end, wrap to history (index 0) or return null for no more boards
|
||||
if (currentIndex >= navigationOrder.length) {
|
||||
return null // Let caller handle going back to history
|
||||
}
|
||||
} else {
|
||||
currentIndex = currentIndex - 1
|
||||
// If we've gone before the beginning, return null for going to history
|
||||
if (currentIndex < 1) {
|
||||
// Index 0 is history, so < 1 means we should go to history
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const candidateItem = navigationOrder[currentIndex]
|
||||
|
||||
// Skip history item (only boards should be checked)
|
||||
if (candidateItem.type === 'history') {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if this board has actual navigable clips (with non-null itemIds)
|
||||
const hasNavigableClips = clipItems.some(
|
||||
clipItem =>
|
||||
clipItem.isClip &&
|
||||
clipItem.parentId === candidateItem.id &&
|
||||
clipItem.tabId === currentTab &&
|
||||
clipItem.itemId != null // Crucial check: ensure the clip itself is navigable
|
||||
)
|
||||
|
||||
// If board has navigable clips, return it
|
||||
if (hasNavigableClips) {
|
||||
return candidateItem
|
||||
}
|
||||
}
|
||||
|
||||
// If no non-empty board found, return null
|
||||
return null
|
||||
}
|
||||
|
||||
// Navigate to specific item in the navigation order
|
||||
export function navigateToItem(
|
||||
item: NavigationItem,
|
||||
clipItems: any[],
|
||||
currentTab: string
|
||||
) {
|
||||
if (item.type === 'history') {
|
||||
currentNavigationContext.value = 'history'
|
||||
keyboardSelectedBoardId.value = null
|
||||
keyboardSelectedClipId.value = null
|
||||
currentBoardIndex.value = 0
|
||||
// History item selection (e.g., selecting the first history item)
|
||||
// is typically handled by the calling component (ClipboardHistoryPage)
|
||||
// when currentNavigationContext.value changes to 'history'.
|
||||
} else if (item.type === 'board') {
|
||||
const clipsInBoard = clipItems
|
||||
.filter(
|
||||
clipItem =>
|
||||
clipItem.isClip &&
|
||||
clipItem.parentId === item.id &&
|
||||
clipItem.tabId === currentTab
|
||||
)
|
||||
.sort((a, b) => a.orderNumber - b.orderNumber)
|
||||
|
||||
currentNavigationContext.value = 'board' // We are attempting to navigate to a board context
|
||||
keyboardSelectedBoardId.value = item.id // Select the target board ID
|
||||
|
||||
// Find the first clip in the sorted list that has a valid itemId.
|
||||
// The 'item' (board) passed to this function should be guaranteed by
|
||||
// findNextNonEmptyBoard to have at least one such clip.
|
||||
const firstValidClip = clipsInBoard.find(clip => clip.itemId != null)
|
||||
|
||||
if (firstValidClip) {
|
||||
// Board has at least one navigable clip, select it.
|
||||
keyboardSelectedClipId.value = firstValidClip.itemId
|
||||
} else {
|
||||
// This case should ideally not be reached if findNextNonEmptyBoard works correctly,
|
||||
// as it implies the board was deemed "non-empty" but no valid clips were found here.
|
||||
// For safety, ensure no clip is selected. The calling hotkey logic in
|
||||
// ClipboardHistoryPage (the while loops) will then continue to the next board.
|
||||
keyboardSelectedClipId.value = null
|
||||
}
|
||||
|
||||
// Update board index (for UI, e.g., highlighting the top-level board tab)
|
||||
// This logic finds the root parent of the selected board.
|
||||
const topLevelBoards = clipItems
|
||||
.filter(
|
||||
boardItem =>
|
||||
boardItem.isBoard &&
|
||||
boardItem.parentId === null &&
|
||||
boardItem.tabId === currentTab
|
||||
)
|
||||
.sort((a, b) => a.orderNumber - b.orderNumber)
|
||||
|
||||
const currentBoardData = clipItems.find(boardItem => boardItem.itemId === item.id)
|
||||
if (currentBoardData) {
|
||||
let rootParent = currentBoardData
|
||||
// Traverse up to find the root parent board
|
||||
while (rootParent.parentId !== null) {
|
||||
const parentBoard = clipItems.find(
|
||||
boardItem =>
|
||||
boardItem.itemId === rootParent.parentId &&
|
||||
boardItem.isBoard &&
|
||||
boardItem.tabId === currentTab
|
||||
)
|
||||
if (!parentBoard) {
|
||||
// Parent not found, treat current as root (should ideally not happen with consistent data)
|
||||
break
|
||||
}
|
||||
rootParent = parentBoard
|
||||
}
|
||||
currentBoardIndex.value = topLevelBoards.findIndex(
|
||||
board => board.itemId === rootParent.itemId
|
||||
)
|
||||
} else {
|
||||
// Fallback if currentBoardData is not found (e.g., item.id is invalid)
|
||||
// This might reset or clear the board index, or default to the first top-level board.
|
||||
// For now, if the board itself isn't found, the index might become -1 or an existing value.
|
||||
// Consider if a default (e.g., 0 or -1) is more appropriate if item.id is not a valid board.
|
||||
const directMatchIndex = topLevelBoards.findIndex(board => board.itemId === item.id)
|
||||
if (directMatchIndex !== -1) {
|
||||
currentBoardIndex.value = directMatchIndex
|
||||
}
|
||||
// If not a top-level board and data is missing, currentBoardIndex might remain unchanged or be -1.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const findNewChildrenOrderByParentIdAndDragId = (
|
||||
items: MenuItem[],
|
||||
dragId: string,
|
||||
@ -532,16 +305,19 @@ export function bgColor(
|
||||
) {
|
||||
const colorNameToUse = colorName || 'slate'
|
||||
|
||||
let darkColorCode: string
|
||||
if (darkCode) {
|
||||
darkColorCode = darkCode
|
||||
} else if (colorCode === '200' && colorNameToUse === 'slate') {
|
||||
darkColorCode = '700'
|
||||
} else if (colorNameToUse !== 'slate') {
|
||||
darkColorCode = '900'
|
||||
} else {
|
||||
darkColorCode = '300'
|
||||
}
|
||||
const darkColorCode = darkCode
|
||||
? darkCode
|
||||
: colorCode === '200' && colorNameToUse === 'slate'
|
||||
? '700'
|
||||
: colorNameToUse !== 'slate'
|
||||
? '900'
|
||||
: '300'
|
||||
? '600'
|
||||
: '400'
|
||||
? '500'
|
||||
: '600'
|
||||
? '700'
|
||||
: '300'
|
||||
|
||||
const type = isBorder ? 'border' : 'bg'
|
||||
|
||||
|
@ -12,9 +12,6 @@ export default function createFilteredFlatBoardTreeWithClips(
|
||||
const findTabById = (tabId: string | undefined) =>
|
||||
allTabs.filter(tab => tab.tabId === tabId)
|
||||
|
||||
// Pre-compute lowercase search term
|
||||
const lowerFind = find.toLowerCase()
|
||||
|
||||
const findChildrenClips = (parentId: string | null) =>
|
||||
items
|
||||
.filter(item => {
|
||||
@ -22,15 +19,13 @@ export default function createFilteredFlatBoardTreeWithClips(
|
||||
return false
|
||||
}
|
||||
|
||||
const nameMatches = item.name.toLowerCase().includes(lowerFind)
|
||||
const nameMatches = item.name.toLowerCase().includes(find.toLowerCase())
|
||||
|
||||
const valueMatches =
|
||||
!isSearchNameOrLabelOnly && item.value?.toLowerCase().includes(lowerFind)
|
||||
!isSearchNameOrLabelOnly &&
|
||||
item.value?.toLowerCase().includes(find.toLowerCase())
|
||||
|
||||
const descriptionMatches =
|
||||
!isSearchNameOrLabelOnly && item.description?.toLowerCase().includes(lowerFind)
|
||||
|
||||
return nameMatches || valueMatches || descriptionMatches
|
||||
return nameMatches || valueMatches
|
||||
})
|
||||
.map(item => ({ ...item, type: CLIP, id: item.itemId.toString() }))
|
||||
|
||||
@ -65,7 +60,7 @@ export default function createFilteredFlatBoardTreeWithClips(
|
||||
})
|
||||
.filter(board => board !== null)
|
||||
: allBoards
|
||||
.filter(board => board.name.toLowerCase().includes(lowerFind))
|
||||
.filter(board => board.name.toLowerCase().includes(find.toLowerCase()))
|
||||
.map(board => {
|
||||
const children = findAllChildrenClips(board.itemId.toString())
|
||||
return {
|
||||
|
@ -17,9 +17,3 @@ Show collection name on the navbar: Sammlungsnamen in der Navigationsleiste anze
|
||||
Switch collections: Sammlungen wechseln
|
||||
You can add the selected text to your clips or menu. Please select the option below.: Sie können den ausgewählten Text zu Ihren Clips oder Menü hinzufügen. Bitte wählen Sie die Option unten.
|
||||
You need to select a different collection before deleting the current one.: Sie müssen eine andere Sammlung auswählen, bevor Sie die aktuelle löschen.
|
||||
Choose which collections require PIN entry for access.: Wählen Sie, welche Sammlungen eine PIN-Eingabe erfordern.
|
||||
Pin Protected Collections: Mit PIN geschützte Sammlungen
|
||||
Protect Collections with PIN: Sammlungen mit PIN schützen
|
||||
Protected Collection: Geschützte Sammlung
|
||||
Select Collections: Sammlungen auswählen
|
||||
Select protected collections: Geschützte Sammlungen auswählen
|
||||
|
@ -55,9 +55,11 @@ Confirm Passcode: Passcode bestätigen
|
||||
Confirm Password: Passwort bestätigen
|
||||
Confirm Remove: Entfernen bestätigen
|
||||
Confirm Your Passcode: Ihren Passcode bestätigen
|
||||
Confirm Passcode Reset: Passcode-Zurücksetzung bestätigen
|
||||
Confirm Password Reset: Passwort-Zurücksetzung bestätigen
|
||||
Confirm passcode reset: Passcode-Zurücksetzung bestätigen
|
||||
Confirm password reset: Passwort-Zurücksetzung bestätigen
|
||||
Confirm password reset action: Passwort-Zurücksetzung bestätigen
|
||||
Confirm your action: Ihre Aktion bestätigen
|
||||
Confirm {{action}}: '{{action}} bestätigen'
|
||||
Contact Form: Kontaktformular
|
||||
Copied: Kopiert
|
||||
Copy: Kopieren
|
||||
@ -98,7 +100,6 @@ Enter Passcode: Passcode eingeben
|
||||
Enter Password: Passwort eingeben
|
||||
Enter Recovery Password: Wiederherstellungspasswort eingeben
|
||||
Enter passcode or password to unlock: Passcode oder Passwort zum Entsperren eingeben
|
||||
Enter PIN to Access Protected Collection: Geben Sie die PIN ein, um auf die geschützte Sammlung zuzugreifen
|
||||
Error: Fehler
|
||||
Errors:
|
||||
Error loading link: Fehler beim Laden des Links
|
||||
@ -153,6 +154,7 @@ Number of lines: Anzahl der Zeilen
|
||||
Ok, but later: Ok, aber später
|
||||
Open: Öffnen
|
||||
Open Accessibility: Bedienungshilfen öffnen
|
||||
Open History Window: Verlaufsfenster öffnen
|
||||
Open Window: Fenster öffnen
|
||||
Open contact form in browser: Kontaktformular im Browser öffnen
|
||||
Open payment in browser: Zahlung im Browser öffnen
|
||||
@ -235,7 +237,7 @@ Show Large View: Große Ansicht anzeigen
|
||||
Show all: Alle anzeigen
|
||||
Size: Größe
|
||||
Source: Quelle
|
||||
Open History Window: Verlaufsfenster öffnen
|
||||
Split History Window: Geteiltes Verlaufsfenster
|
||||
Star: Stern
|
||||
Star Selected: Ausgewählte markieren
|
||||
Stay here: Hier bleiben
|
||||
@ -351,7 +353,3 @@ second: Sekunde
|
||||
seconds: Sekunden
|
||||
show less: weniger anzeigen
|
||||
www.site: www.pastebar.app
|
||||
Confirm Add To Protected Collections: Hinzufügen zu geschützten Sammlungen bestätigen
|
||||
Confirm Disable PIN Protection: Deaktivierung des PIN-Schutzes bestätigen
|
||||
Confirm Remove From Protected Collections: Entfernen aus geschützten Sammlungen bestätigen
|
||||
Confirm Enable PIN Protection: PIN-Schutz aktivieren bestätigen
|
||||
|
@ -1,4 +0,0 @@
|
||||
Please select your preferred language: Bitte wählen Sie Ihre bevorzugte Sprache aus
|
||||
Start using PasteBar: Beginnen Sie mit der Nutzung von PasteBar
|
||||
Submenus will move up one level after delete: Untermenüs werden eine Ebene nach oben verschoben
|
||||
Welcome to PasteBar: Willkommen bei PasteBar
|
@ -21,7 +21,8 @@ Add Section: Abschnitt hinzufügen
|
||||
Add Tab: Tab hinzufügen
|
||||
Add Template Field: Vorlagenfeld hinzufügen
|
||||
Add a Tab: Tab hinzufügen
|
||||
Add field {{name}} into the template: Feld {{name}} zur Vorlage hinzufügen
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Feld <b>{{<b>{{name}}</b>}}</b> zur Vorlage hinzufügen
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Feld <b>{{<b>{{name}}</b>}}</b> zur Vorlage hinzufügen
|
||||
Add image: Bild hinzufügen
|
||||
Add note: Notiz hinzufügen
|
||||
Add to Board: Zum Board hinzufügen
|
||||
@ -82,7 +83,7 @@ Delete field: Feld löschen
|
||||
Delete tab: Tab löschen
|
||||
Detect Template Fields: Vorlagenfelder erkennen
|
||||
Detect for Template Fields: Nach Vorlagenfeldern suchen
|
||||
Disabled field {{name}} has been found in the template: Deaktiviertes Feld {{name}} wurde in der Vorlage gefunden
|
||||
Disabled field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Deaktiviertes Feld <b>{{<b>{{name}}</b>}}</b> wurde in der Vorlage gefunden
|
||||
Done Create Clip: Clip-Erstellung abgeschlossen
|
||||
Done Edit: Bearbeitung abgeschlossen
|
||||
Done Edit Tabs: Tab-Bearbeitung abgeschlossen
|
||||
@ -134,7 +135,7 @@ FILTERED_TYPES:
|
||||
RegEx Replace: RegEx Ersetzen
|
||||
Remove Quotes: Anführungszeichen entfernen
|
||||
Field: Feld
|
||||
Field {{name}} has been found in the template: Feld {{name}} wurde in der Vorlage gefunden
|
||||
Field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Feld <b>{{<b>{{name}}</b>}}</b> wurde in der Vorlage gefunden
|
||||
Field Options: Feldoptionen
|
||||
Fields Value: Feldwert
|
||||
File, folder or app path does not exist: Datei-, Ordner- oder App-Pfad existiert nicht
|
||||
|
@ -69,7 +69,7 @@ Tabs and Layout Menu: Tabs und Layout-Menü
|
||||
Title on Popover: Titel im Popover
|
||||
Toggle Inactive Menu Items: Inaktive Menüelemente umschalten
|
||||
Toggle Pinned Board: Angeheftetes Board umschalten
|
||||
Toggle History Window: Verlaufsfenster umschalten
|
||||
Toggle Split History Window: Geteiltes Verlaufsfenster umschalten
|
||||
Tour Completed: Tour abgeschlossen
|
||||
Tour Skipped: Tour übersprungen
|
||||
Tour completed: Tour abgeschlossen
|
||||
|
@ -10,7 +10,6 @@ Clear History: Verlauf löschen
|
||||
Confirm Clear All History: Gesamten Verlauf löschen bestätigen
|
||||
Do you really want to remove ALL clipboard history items?: Möchten Sie wirklich ALLE Zwischenablage-Verlaufselemente entfernen?
|
||||
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: Möchten Sie Zwischenablage-Verlaufselemente älter als {{olderThen}} {{durationType}} entfernen?
|
||||
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: Möchten Sie alle kürzlichen Zwischenablage-Verlaufselemente entfernen, die älter als {{olderThen}} {{durationType}} sind?
|
||||
Enable Capture History: Verlaufserfassung aktivieren
|
||||
Enable Image Capture: Bilderfassung aktivieren
|
||||
Filters:
|
||||
|
@ -23,7 +23,6 @@ Lock Screen: Bildschirm sperren
|
||||
Open PasteBar: PasteBar öffnen
|
||||
Options: Optionen
|
||||
Player: Player
|
||||
Show Always on Top: Immer im Vordergrund anzeigen
|
||||
Show Both Panels: Beide Panels anzeigen
|
||||
Show Clips Panel Only: Nur Clips-Panel anzeigen
|
||||
Show Collections Name: Sammlungsnamen anzeigen
|
||||
|
@ -87,7 +87,7 @@ Enable screen unlock requirement on app launch for enhanced security, safeguardi
|
||||
Enter Passcode length: Passcode-Länge eingeben
|
||||
Enter new directory path or leave empty for default on next revert: Neuen Verzeichnispfad eingeben oder für Standard beim nächsten Zurücksetzen leer lassen
|
||||
Enter recovery password to reset passcode.: Wiederherstellungspasswort eingeben, um Passcode zurückzusetzen.
|
||||
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Geben Sie Ihren <strong>{{screenLockPassCodeLength}}-stelligen</strong> Passcode ein
|
||||
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Geben Sie Ihren <strong>{{screenLockPassCodeLength}}-stelligen</strong> Passcode ein
|
||||
Entered Passcode is invalid: Eingegebener Passcode ist ungültig
|
||||
Excluded Apps List: Liste ausgeschlossener Apps
|
||||
Execute Web Requests: Web-Anfragen ausführen
|
||||
|
@ -15,19 +15,13 @@ Press keys: Tasten drücken
|
||||
Quick Paste Window: Schnelleinfügen-Fenster
|
||||
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: PasteBar-App-Symbol aus dem macOS Dock entfernen, während die App im Hintergrund läuft. Die App bleibt über das Menüleistensymbol zugänglich. Erfordert einen App-Neustart, um wirksam zu werden.
|
||||
Set: Festlegen
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.: System-Tastenkombinationen zum Anzeigen/Verbergen des Hauptfensters und des Schnelleinfügen-Fensters festlegen. Unterstützt bis zu 3-Tasten-Kombinationen.
|
||||
'How to set hotkeys:': 'So stellen Sie Hotkeys ein:'
|
||||
Click Set/Change button to start recording: Klicken Sie auf die Schaltfläche Festlegen/Ändern, um die Aufzeichnung zu starten
|
||||
Press your desired key combination (e.g., Ctrl+Shift+V): Drücken Sie Ihre gewünschte Tastenkombination (z.B. Ctrl+Shift+V)
|
||||
Press Enter to confirm or Escape to cancel: Drücken Sie Enter zum Bestätigen oder Escape zum Abbrechen
|
||||
Press Backspace/Delete to clear the hotkey: Drücken Sie Backspace/Delete, um den Hotkey zu löschen
|
||||
Press your key combination...: Drücken Sie Ihre Tastenkombination...
|
||||
Recording...: Aufzeichnen...
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window: System-Tastenkombinationen zum Anzeigen/Verbergen des Hauptfensters und des Schnelleinfügen-Fensters festlegen
|
||||
Show Navbar Items Hover: Navigationsleistenelemente bei Hover anzeigen
|
||||
Show collections menu on the navbar: Sammlungsmenü in der Navigationsleiste anzeigen
|
||||
Show navbar elements on hover only: Navigationsleistenelemente nur bei Hover anzeigen
|
||||
Show/Hide Main App Window: Hauptfenster anzeigen/verbergen
|
||||
Show/Hide Quick Paste Window: Schnelleinfügen-Fenster anzeigen/verbergen
|
||||
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: Wenn aktiviert, wird beim Klicken auf Menüelemente der Inhalt nur in die Zwischenablage kopiert, anstatt automatisch eingefügt zu werden. Dies gibt Ihnen mehr Kontrolle darüber, wann und wo Inhalte eingefügt werden.
|
||||
Show Note Icons on Clips: Notiz-Symbole auf Clips anzeigen
|
||||
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Dauerhafte Symbole auf Clips mit Notizen anzeigen, um die visuelle Organisation zu verbessern und Notizen leichter auffindbar zu machen.
|
||||
Default Note Icon Type: Standard-Notiz-Symbol-Typ
|
||||
@ -44,26 +38,3 @@ Show Both Panels: Beide Panels anzeigen
|
||||
Show History Panel Only: Nur Verlauf-Panel anzeigen
|
||||
Show Simplified Layout: Vereinfachtes Layout anzeigen
|
||||
Simplified Panel Layout: Vereinfachtes Panel-Layout
|
||||
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Einfachklick zum Kopieren/Einfügen von Zwischenablage-Verlauf und gespeicherten Clips aktivieren, anstatt Doppelklick zu erfordern.
|
||||
Single Click Copy/Paste action: Einfachklick Kopieren/Einfügen-Aktion
|
||||
Single Click Copy/Paste: Einfachklick Kopieren/Einfügen
|
||||
Quick Paste Window Options: Schnelleinfügen-Fenster-Optionen
|
||||
Configure how the system tray icon responds to mouse clicks: Konfigurieren Sie, wie das Systemtray-Symbol auf Mausklicks reagiert
|
||||
Configure the behavior of the Quick Paste window when selecting items: Konfigurieren Sie das Verhalten des Schnelleinfügen-Fensters beim Auswählen von Elementen
|
||||
Disable left-click context menu: Linksklick-Kontextmenü deaktivieren
|
||||
Double-click toggles app visibility: Doppelklick schaltet App-Sichtbarkeit um
|
||||
Double-clicking the tray icon shows or hides the main application window: Doppelklick auf das Tray-Symbol zeigt oder verbirgt das Hauptanwendungsfenster
|
||||
Enabling either left-click option will disable the context menu to ensure proper functionality.: Das Aktivieren einer der beiden Linksklick-Optionen deaktiviert das Kontextmenü, um ordnungsgemäße Funktionalität sicherzustellen.
|
||||
Left-click toggles app visibility: Linksklick schaltet App-Sichtbarkeit um
|
||||
Left-clicking the tray icon shows or hides the main application window: Linksklick auf das Tray-Symbol zeigt oder verbirgt das Hauptanwendungsfenster
|
||||
Prevents the context menu from appearing when left-clicking the tray icon: Verhindert, dass das Kontextmenü beim Linksklick auf das Tray-Symbol erscheint
|
||||
Tray Icon Behavior on Windows: Tray-Symbol-Verhalten unter Windows
|
||||
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Konfigurieren Sie, welche Elemente beim Löschen des Zwischenablageverlaufs beibehalten werden sollen (sowohl manuell als auch automatisch).
|
||||
Keep Items on Clear: Elemente beim Löschen beibehalten
|
||||
Keep Pinned Items: Angehängte Elemente beibehalten
|
||||
Keep Starred Items: Mit Stern markierte Elemente beibehalten
|
||||
Preserve pinned items when clearing history: Angehängte Elemente beim Löschen des Verlaufs beibehalten
|
||||
Preserve starred items when clearing history: Mit Stern markierte Elemente beim Löschen des Verlaufs beibehalten
|
||||
History Item Preview Max Lines: Maximale Vorschauzeilenanzahl für Verlaufselemente
|
||||
Set the maximum number of lines to display in the preview of a history item: Maximale Anzahl der Zeilen für die Vorschau eines Verlaufselements festlegen
|
||||
Preview Max Lines: Vorschauzeilen
|
||||
|
@ -1,73 +0,0 @@
|
||||
Add Current Date/Time: Aktuelles Datum/Uhrzeit hinzufügen
|
||||
Add Line Numbers: Zeilennummern hinzufügen
|
||||
Add One Line Feed: Einen Zeilenvorschub hinzufügen
|
||||
Add Two Line Feeds: Zwei Zeilenvorschübe hinzufügen
|
||||
Base64 Decode: Base64 dekodieren
|
||||
Base64 Encode: Base64 kodieren
|
||||
CSV: CSV
|
||||
CSV to JSON: CSV zu JSON
|
||||
CSV to Markdown Table: CSV zu Markdown-Tabelle
|
||||
Capitalize Case: Erster Buchstabe groß
|
||||
Code Formatting: Code-Formatierung
|
||||
Count Characters: Zeichen zählen
|
||||
Count Lines: Zeilen zählen
|
||||
Count Sentences: Sätze zählen
|
||||
Count Words: Wörter zählen
|
||||
Data Conversion: Datenkonvertierung
|
||||
Drag and drop category to prioritize its order in the special copy/paste menu.: Ziehe eine Kategorie per Drag & Drop, um ihre Reihenfolge im speziellen Kopieren/Einfügen-Menü zu priorisieren.
|
||||
Enable All: Alle aktivieren
|
||||
Enable special text transformation options for clipboard history items: Spezielle Textumwandlungsoptionen für Zwischenablage-Verlaufselemente aktivieren
|
||||
Enabled Operations: Aktivierte Operationen
|
||||
Encode/Decode: Kodieren/Dekodieren
|
||||
Format Converter: Formatkonverter
|
||||
HTML: HTML
|
||||
HTML Decode: HTML dekodieren
|
||||
HTML Encode: HTML kodieren
|
||||
HTML to Markdown: HTML zu Markdown
|
||||
HTML to Plain Text: HTML zu reinem Text
|
||||
HTML to React Component: HTML zu React-Komponente
|
||||
HTML to React JSX: HTML zu React JSX
|
||||
HTML to Text: HTML zu Text
|
||||
JSON: JSON
|
||||
JSON Stringify: JSON Stringify
|
||||
JSON to CSV: JSON zu CSV
|
||||
JSON to Markdown Table: JSON zu Markdown-Tabelle
|
||||
JSON to TOML: JSON zu TOML
|
||||
JSON to XML: JSON zu XML
|
||||
JSON to YAML: JSON zu YAML
|
||||
Markdown: Markdown
|
||||
Markdown to HTML: Markdown zu HTML
|
||||
Markdown to Text: Markdown zu Text
|
||||
Operations: Operationen
|
||||
PascalCase: PascalCase
|
||||
Prioritize Category Order: Kategorie-Reihenfolge priorisieren
|
||||
Remove Duplicate Lines: Doppelte Zeilen entfernen
|
||||
Remove Extra Spaces: Zusätzliche Leerzeichen entfernen
|
||||
Remove Line Feeds: Zeilenvorschübe entfernen
|
||||
Reverse Text: Text umkehren
|
||||
Select Operations: Operationen auswählen
|
||||
Sentence case: Satzbau
|
||||
Sort Lines Alphabetically: Zeilen alphabetisch sortieren
|
||||
Special Copy: Spezielles Kopieren
|
||||
Special Copy/Paste Operations: Spezielle Kopier-/Einfüge-Operationen
|
||||
Special Paste: Spezielles Einfügen
|
||||
Special Settings: Spezielle Einstellungen
|
||||
TOML: TOML
|
||||
TOML to JSON: TOML zu JSON
|
||||
Text Case: Groß-/Kleinschreibung
|
||||
Text Tools: Textwerkzeuge
|
||||
Title Case: Titel-Fall
|
||||
Trim White Space: Leerzeichen entfernen
|
||||
UPPER CASE: GROSSBUCHSTABEN
|
||||
URL Decode: URL dekodieren
|
||||
URL Encode: URL kodieren
|
||||
Whitespace & Lines: Leerraum & Zeilen
|
||||
XML: XML
|
||||
XML to JSON: XML zu JSON
|
||||
YAML: YAML
|
||||
YAML to JSON: YAML zu JSON
|
||||
camelCase: camelCase
|
||||
iNVERT cASE: gROSS/kLEIN uMKEHREN
|
||||
kebab-case: kebab-case
|
||||
lower case: kleinbuchstaben
|
||||
snake_case: snake_case
|
@ -1,24 +0,0 @@
|
||||
Create New Template: Neue Vorlage erstellen
|
||||
Create Template: Vorlage erstellen
|
||||
Enter template content...: Vorlageninhalt eingeben...
|
||||
Enter template name (e.g., "signature", "email"): Vorlagenname eingeben (z.B. "Signatur", "E-Mail")
|
||||
Global: Global
|
||||
Global Template: Globale Vorlage
|
||||
Global Templates: Globale Vorlagen
|
||||
Preview usage: Verwendung vorschau
|
||||
Template Usage: Vorlagen-Verwendung
|
||||
Template name already exists: Vorlagenname existiert bereits. Bitte wählen Sie einen anderen Namen.
|
||||
Template name cannot be changed after creation. Delete and recreate to change name.: Der Vorlagenname kann nach der Erstellung nicht geändert werden. Löschen und neu erstellen, um den Namen zu ändern.
|
||||
Use Global Template: Globale Vorlage verwenden
|
||||
addTemplateButton: Vorlage hinzufügen
|
||||
confirmDeleteTemplateMessage: "Sind Sie sicher, dass Sie die globale Vorlage '{{name}}' löschen möchten?"
|
||||
confirmDeleteTemplateTitle: Löschen bestätigen
|
||||
deleteTemplateButtonTooltip: Vorlage löschen
|
||||
enableGlobalTemplatesLabel: Globale Vorlagen aktivieren
|
||||
globalTemplatesDescription: Verwalten Sie wiederverwendbare Textfragmente, die mit {{template_name}} in jeden Clip eingefügt werden können.
|
||||
globalTemplatesTitle: Globale Vorlagen
|
||||
localTemplateConflictWarning: "Eine globale Vorlage namens '{{label}}' existiert ebenfalls. Die lokale Vorlage hat Vorrang innerhalb dieses Clip-Formulars."
|
||||
noGlobalTemplatesYet: Noch keine globalen Vorlagen definiert. Klicken Sie auf 'Vorlage hinzufügen', um eine zu erstellen.
|
||||
templateEnabledLabel: Aktiviert
|
||||
templateNameLabel: Name
|
||||
templateValueLabel: Wert
|
@ -2,24 +2,17 @@ Add Collection: Add Collection
|
||||
Add a description for your collection: Add a description for your collection
|
||||
Add default menu, tab and board: Add default menu, tab and board
|
||||
Are you sure you want to delete this collection?: Are you sure you want to delete this collection?
|
||||
Choose which collections require PIN entry for access.: Choose which collections require PIN entry for access.
|
||||
Collection Options: Collection Options
|
||||
Collection Title: Collection Title
|
||||
Collections: Collections
|
||||
Current Collection: Current Collection
|
||||
Delete Collection: Delete Collection
|
||||
Delete all menu items within this collection: Delete all menu items within this collection
|
||||
? Deleting the collection will remove it permanently. You can also choose to delete all menu and clips items within the collection by checking the box below.
|
||||
: Deleting the collection will remove it permanently. You can also choose to delete all menu and clips items within the collection by checking the box below.
|
||||
Deleting the collection will remove it permanently. You can also choose to delete all menu and clips items within the collection by checking the box below.: Deleting the collection will remove it permanently. You can also choose to delete all menu and clips items within the collection by checking the box below.
|
||||
Description: Description
|
||||
Display full name of selected collection on the navigation bar: Display full name of selected collection on the navigation bar
|
||||
Enter collection title: Enter collection title
|
||||
Manage Collections: Manage Collections
|
||||
Pin Protected Collections: Pin Protected Collections
|
||||
Protect Collections with PIN: Protect Collections with PIN
|
||||
Protected Collection: Protected Collection
|
||||
Select Collections: Select Collections
|
||||
Select protected collections: Select protected collections
|
||||
Show collection name on the navbar: Show collection name on the navbar
|
||||
Switch collections: Switch collections
|
||||
You can add the selected text to your clips or menu. Please select the option below.: You can add the selected text to your clips or menu. Please select the option below.
|
||||
|
@ -2,8 +2,7 @@
|
||||
' This permission ensures PasteBar can access the clipboard and perform copy and paste operations across applications.': ' This permission ensures PasteBar can access the clipboard and perform copy and paste operations across applications.'
|
||||
About PasteBar: About PasteBar
|
||||
Action Menu: Action Menu
|
||||
? Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
: Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template: Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
Add Clip: Add Clip
|
||||
Add First Option: Add First Option
|
||||
Add Link Card: Add Link Card
|
||||
@ -24,6 +23,7 @@ Are you sure you want to delete?: Are you sure you want to delete?
|
||||
Are you sure?: Are you sure?
|
||||
Attach History Window: Attach History Window
|
||||
Back: Back
|
||||
Browse...: Browse...
|
||||
Build on {{buildDate}}: Build on {{buildDate}}
|
||||
Cancel: Cancel
|
||||
Cancel Reset: Cancel Reset
|
||||
@ -55,12 +55,11 @@ Confirm Passcode: Confirm Passcode
|
||||
Confirm Password: Confirm Password
|
||||
Confirm Remove: Confirm Remove
|
||||
Confirm Your Passcode: Confirm Your Passcode
|
||||
Confirm Passcode Reset: Confirm Passcode Reset
|
||||
Confirm Password Reset: Confirm Password Reset
|
||||
Confirm Add To Protected Collections: Confirm add to protected collections
|
||||
Confirm Disable PIN Protection: Confirm disable PIN protection
|
||||
Confirm Remove From Protected Collections: Confirm remove from protected collections
|
||||
Confirm Enable PIN Protection: Confirm enable PIN protection
|
||||
Confirm passcode reset: Confirm passcode reset
|
||||
Confirm password reset: Confirm password reset
|
||||
Confirm password reset action: Confirm password reset action
|
||||
Confirm your action: Confirm your action
|
||||
Confirm {{action}}: Confirm {{action}}
|
||||
Contact Form: Contact Form
|
||||
Copied: Copied
|
||||
Copy: Copy
|
||||
@ -97,7 +96,6 @@ Enabled: Enabled
|
||||
Enter Current Passcode: Enter Current Passcode
|
||||
Enter Digits Only Passcode: Enter Digits Only Passcode
|
||||
Enter Email: Enter Email
|
||||
Enter PIN to Access Protected Collection: Enter PIN to Access Protected Collection
|
||||
Enter Passcode: Enter Passcode
|
||||
Enter Password: Enter Password
|
||||
Enter Recovery Password: Enter Recovery Password
|
||||
@ -109,8 +107,7 @@ Errors:
|
||||
Something went wrong! {{err}} Please try again.: Something went wrong! {{err}} Please try again.
|
||||
Expand Edit: Expand Edit
|
||||
Expires on {{proExpiresOn}}: Expires on {{proExpiresOn}}
|
||||
? Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
: Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template: Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
Field is not found in the template: Field is not found in the template
|
||||
Find Clip: Find Clip
|
||||
Find History: Find History
|
||||
@ -175,8 +172,7 @@ Pasted: Pasted
|
||||
Path: Path
|
||||
Pause: Pause
|
||||
Pause Playing: Pause Playing
|
||||
? 'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.'
|
||||
: 'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.'
|
||||
'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.': 'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.'
|
||||
Pin Selected: Pin Selected
|
||||
Pinned: Pinned
|
||||
Play: Play
|
||||
@ -241,6 +237,7 @@ Show Large View: Show Large View
|
||||
Show all: Show all
|
||||
Size: Size
|
||||
Source: Source
|
||||
Split History Window: Split History Window
|
||||
Star: Star
|
||||
Star Selected: Star Selected
|
||||
Stay here: Stay here
|
||||
@ -341,8 +338,7 @@ View Edit: View Edit
|
||||
Views:
|
||||
Paste Menu: Paste Menu
|
||||
We apologize but you found a bug. Please report this issue to us and try again: We apologize but you found a bug. Please report this issue to us and try again
|
||||
? We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.
|
||||
: We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.
|
||||
We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.: We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.
|
||||
Yes: Yes
|
||||
Yes, activate: Yes, activate
|
||||
chars: chars
|
||||
|
@ -1,4 +0,0 @@
|
||||
Please select your preferred language: Please select your preferred language
|
||||
Start using PasteBar: Start using PasteBar
|
||||
Submenus will move up one level after delete: Submenus will move up one level after delete
|
||||
Welcome to PasteBar: Welcome to PasteBar
|
@ -21,7 +21,8 @@ Add Section: Add Section
|
||||
Add Tab: Add Tab
|
||||
Add Template Field: Add Template Field
|
||||
Add a Tab: Add a Tab
|
||||
Add field {{name}} into the template: Add field {{name}} into the template
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Add field <b>{{<b>{{name}}</b>}}</b> into the template
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Add field <b>{{<b>{{name}}</b>}}</b> into the template
|
||||
Add image: Add image
|
||||
Add note: Add note
|
||||
Add to Board: Add to Board
|
||||
@ -82,7 +83,7 @@ Delete field: Delete field
|
||||
Delete tab: Delete tab
|
||||
Detect Template Fields: Detect Template Fields
|
||||
Detect for Template Fields: Detect for Template Fields
|
||||
Disabled field {{name}} has been found in the template: Disabled field {{name}} has been found in the template
|
||||
Disabled field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Disabled field <b>{{<b>{{name}}</b>}}</b> has been found in the template
|
||||
Done Create Clip: Done Create Clip
|
||||
Done Edit: Done Edit
|
||||
Done Edit Tabs: Done Edit Tabs
|
||||
@ -134,8 +135,8 @@ FILTERED_TYPES:
|
||||
RegEx Replace: RegEx Replace
|
||||
Remove Quotes: Remove Quotes
|
||||
Field: Field
|
||||
Field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Field <b>{{<b>{{name}}</b>}}</b> has been found in the template
|
||||
Field Options: Field Options
|
||||
Field {{name}} has been found in the template: Field {{name}} has been found in the template
|
||||
Fields Value: Fields Value
|
||||
File, folder or app path does not exist: File, folder or app path does not exist
|
||||
File, folder or app path is valid: File, folder or app path is valid
|
||||
@ -146,10 +147,8 @@ Filter's Value: Filter's Value
|
||||
Find in Clip: Find in Clip
|
||||
Find in clip: Find in clip
|
||||
Find in history: Find in history
|
||||
Flex Layout: Flex Layout
|
||||
Form Fields: Form Fields
|
||||
General Fields: General Fields
|
||||
Grid Layout: Grid Layout
|
||||
HTML: HTML
|
||||
Headers: Headers
|
||||
Hide Label: Hide Label
|
||||
|
@ -69,7 +69,7 @@ Tabs and Layout Menu: Tabs and Layout Menu
|
||||
Title on Popover: Title on Popover
|
||||
Toggle Inactive Menu Items: Toggle Inactive Menu Items
|
||||
Toggle Pinned Board: Toggle Pinned Board
|
||||
Toggle History Window: Toggle History Window
|
||||
Toggle Split History Window: Toggle Split History Window
|
||||
Tour Completed: Tour Completed
|
||||
Tour Skipped: Tour Skipped
|
||||
Tour completed: Tour completed
|
||||
|
@ -9,7 +9,6 @@ Clear All History: Clear All History
|
||||
Clear History: Clear History
|
||||
Confirm Clear All History: Confirm Clear All History
|
||||
Do you really want to remove ALL clipboard history items?: Do you really want to remove ALL clipboard history items?
|
||||
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}
|
||||
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}
|
||||
Enable Capture History: Enable Capture History
|
||||
Enable Image Capture: Enable Image Capture
|
||||
|
@ -23,7 +23,6 @@ Lock Screen: Lock Screen
|
||||
Open PasteBar: Open PasteBar
|
||||
Options: Options
|
||||
Player: Player
|
||||
Show Always on Top: Show Always on Top
|
||||
Show Both Panels: Show Both Panels
|
||||
Show Clips Panel Only: Show Clips Panel Only
|
||||
Show Collections Name: Show Collections Name
|
||||
|
@ -1,61 +1,30 @@
|
||||
App restart required: Restart required
|
||||
Application Starts with Main Window Hidden: Application Starts with Main Window Hidden
|
||||
Auto-close window after action: Auto-close window after action
|
||||
Boards, saved clips and menu items panel visible: Boards, saved clips and menu items panel visible
|
||||
Both clipboard history and saved clips panels visible: Both clipboard history and saved clips panels visible
|
||||
Change: Change
|
||||
Click Set/Change button to start recording: Click Set/Change button to start recording
|
||||
Clipboard history panel visible: Clipboard history panel visible
|
||||
Configure how the system tray icon responds to mouse clicks: Configure how the system tray icon responds to mouse clicks
|
||||
Configure the behavior of the Quick Paste window when selecting items: Configure the behavior of the Quick Paste window when selecting items
|
||||
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).
|
||||
Control which panels are visible in the main window: Control which panels are visible in the main window
|
||||
Copy items only (no auto-paste): Copy items only (no auto-paste)
|
||||
Copy only from menu items: Copy only from menu items
|
||||
Default Note Icon Type: Default Note Icon Type
|
||||
Disable left-click context menu: Disable left-click context menu
|
||||
Display navbar items only when the mouse hovers over the navigation bar to minimize visible UI elements: Display navbar items only when the mouse hovers over the navigation bar to minimize visible UI elements
|
||||
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.
|
||||
Double-click toggles app visibility: Double-click toggles app visibility
|
||||
Double-clicking the tray icon shows or hides the main application window: Double-clicking the tray icon shows or hides the main application window
|
||||
Enable simplified, less boxy layout for a cleaner and more streamlined interface design: Enable simplified, less boxy layout for a cleaner and more streamlined interface design
|
||||
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.
|
||||
Enabling either left-click option will disable the context menu to ensure proper functionality.: Enabling either left-click option will disable the context menu to ensure proper functionality.
|
||||
Global System OS Hotkeys: Global System OS Hotkeys
|
||||
Hide Collections Navbar: Hide Collections Navbar
|
||||
Hide collections menu dropdown on the navigation bar: Hide collections menu dropdown on the navigation bar
|
||||
Hide collections menu on the navbar: Hide collections menu on the navbar
|
||||
Hide the App Dock Icon: Hide the App Dock Icon
|
||||
History Item Preview Max Lines: History Item Preview Max Lines
|
||||
'How to set hotkeys:': 'How to set hotkeys:'
|
||||
Keep Items on Clear: Keep Items on Clear
|
||||
Keep Pinned Items: Keep Pinned Items
|
||||
Keep Starred Items: Keep Starred Items
|
||||
? Keep the main application window hidden when the app restarts. You can reopen it using the menu bar or taskbar menu, or using global hotkeys.
|
||||
: Keep the main application window hidden when the app restarts. You can reopen it using the menu bar or taskbar menu, or using global hotkeys.
|
||||
Left-click toggles app visibility: Left-click toggles app visibility
|
||||
Left-clicking the tray icon shows or hides the main application window: Left-clicking the tray icon shows or hides the main application window
|
||||
Keep the main application window hidden when the app restarts. You can reopen it using the menu bar or taskbar menu, or using global hotkeys.: Keep the main application window hidden when the app restarts. You can reopen it using the menu bar or taskbar menu, or using global hotkeys.
|
||||
No keys set: No keys set
|
||||
'Note: At least one panel must remain visible in main window.': 'Note: At least one panel must remain visible in main window.'
|
||||
Panel Visibility: Panel Visibility
|
||||
PasteBar Quick Paste: PasteBar Quick Paste
|
||||
Preserve pinned items when clearing history: Preserve pinned items when clearing history
|
||||
Preserve starred items when clearing history: Preserve starred items when clearing history
|
||||
Press Backspace/Delete to clear the hotkey: Press Backspace/Delete to clear the hotkey
|
||||
Press Enter to confirm or Escape to cancel: Press Enter to confirm or Escape to cancel
|
||||
Press keys: Press keys
|
||||
Press your desired key combination (e.g., Ctrl+Shift+V): Press your desired key combination (e.g., Ctrl+Shift+V)
|
||||
Press your key combination...: Press your key combination...
|
||||
Prevents the context menu from appearing when left-clicking the tray icon: Prevents the context menu from appearing when left-clicking the tray icon
|
||||
Preview Max Lines: Preview Max Lines
|
||||
Quick Paste Window: Quick Paste Window
|
||||
Quick Paste Window Options: Quick Paste Window Options
|
||||
Recording...: Recording...
|
||||
? Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.
|
||||
: Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.
|
||||
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.
|
||||
Set: Set
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.: Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.
|
||||
Set the maximum number of lines to display in the preview of a history item: Set the maximum number of lines to display in the preview of a history item
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window: Set system OS hotkeys to show/hide the main app window and quick paste window
|
||||
Show Boards and Clips Panel Only: Show Boards and Clips Panel Only
|
||||
Show Both Panels: Show Both Panels
|
||||
Show History Panel Only: Show History Panel Only
|
||||
@ -67,14 +36,5 @@ Show navbar elements on hover only: Show navbar elements on hover only
|
||||
Show/Hide Main App Window: Show/Hide Main App Window
|
||||
Show/Hide Quick Paste Window: Show/Hide Quick Paste Window
|
||||
Simplified Panel Layout: Simplified Panel Layout
|
||||
Single Click Copy/Paste: Single Click Copy/Paste
|
||||
Single Click Copy/Paste action: Single Click Copy/Paste action
|
||||
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.
|
||||
Tray Icon Behavior on Windows: Tray Icon Behavior on Windows
|
||||
? When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
|
||||
: When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
|
||||
? When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
|
||||
: When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
|
||||
? When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
|
||||
: When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
|
||||
When enabled, the Quick Paste window will automatically close after copying or pasting an item.: When enabled, the Quick Paste window will automatically close after copying or pasting an item.
|
||||
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
|
||||
|
@ -1 +0,0 @@
|
||||
Special Settings: Special Settings
|
@ -1,74 +0,0 @@
|
||||
Add Current Date/Time: Add Current Date/Time
|
||||
Add Line Numbers: Add Line Numbers
|
||||
Add One Line Feed: Add One Line Feed
|
||||
Add Two Line Feeds: Add Two Line Feeds
|
||||
Base64 Decode: Base64 Decode
|
||||
Base64 Encode: Base64 Encode
|
||||
CSV: CSV
|
||||
CSV to JSON: CSV to JSON
|
||||
CSV to Markdown Table: CSV to Markdown Table
|
||||
Capitalize Case: Capitalize Case
|
||||
Code Formatting: Code Formatting
|
||||
Count Characters: Count Characters
|
||||
Count Lines: Count Lines
|
||||
Count Sentences: Count Sentences
|
||||
Count Words: Count Words
|
||||
Data Conversion: Data Conversion
|
||||
Drag and drop category to prioritize its order in the special copy/paste menu.: Drag and drop category to prioritize its order in the special copy/paste menu.
|
||||
Enable All: Enable All
|
||||
Enable special text transformation options for clipboard history items: Enable special text transformation options for clipboard history items
|
||||
Enabled Operations: Enabled Operations
|
||||
Encode/Decode: Encode/Decode
|
||||
Format Converter: Format Converter
|
||||
HTML: HTML
|
||||
HTML Decode: HTML Decode
|
||||
HTML Encode: HTML Encode
|
||||
HTML to Markdown: HTML to Markdown
|
||||
HTML to Plain Text: HTML to Plain Text
|
||||
HTML to React Component: HTML to React Component
|
||||
HTML to React JSX: HTML to React JSX
|
||||
HTML to Text: HTML to Text
|
||||
JSON: JSON
|
||||
JSON Stringify: JSON Stringify
|
||||
JSON to CSV: JSON to CSV
|
||||
JSON to Markdown Table: JSON to Markdown Table
|
||||
JSON to TOML: JSON to TOML
|
||||
JSON to XML: JSON to XML
|
||||
JSON to YAML: JSON to YAML
|
||||
Markdown: Markdown
|
||||
Markdown to HTML: Markdown to HTML
|
||||
Markdown to Text: Markdown to Text
|
||||
Operations: Operations
|
||||
PascalCase: PascalCase
|
||||
Prioritize Category Order: Prioritize Category Order
|
||||
PrioritizeCategoryOrderNote: PrioritizeCategoryOrderNote
|
||||
Remove Duplicate Lines: Remove Duplicate Lines
|
||||
Remove Extra Spaces: Remove Extra Spaces
|
||||
Remove Line Feeds: Remove Line Feeds
|
||||
Reverse Text: Reverse Text
|
||||
Select Operations: Select Operations
|
||||
Sentence case: Sentence case
|
||||
Sort Lines Alphabetically: Sort Lines Alphabetically
|
||||
Special Copy: Special Copy
|
||||
Special Copy/Paste Operations: Special Copy/Paste Operations
|
||||
Special Paste: Special Paste
|
||||
Special Settings: Special Settings
|
||||
TOML: TOML
|
||||
TOML to JSON: TOML to JSON
|
||||
Text Case: Text Case
|
||||
Text Tools: Text Tools
|
||||
Title Case: Title Case
|
||||
Trim White Space: Trim White Space
|
||||
UPPER CASE: UPPER CASE
|
||||
URL Decode: URL Decode
|
||||
URL Encode: URL Encode
|
||||
Whitespace & Lines: Whitespace & Lines
|
||||
XML: XML
|
||||
XML to JSON: XML to JSON
|
||||
YAML: YAML
|
||||
YAML to JSON: YAML to JSON
|
||||
camelCase: camelCase
|
||||
iNVERT cASE: iNVERT cASE
|
||||
kebab-case: kebab-case
|
||||
lower case: lower case
|
||||
snake_case: snake_case
|
@ -1,24 +0,0 @@
|
||||
Create New Template: Create New Template
|
||||
Create Template: Create Template
|
||||
Enter template content...: Enter template content...
|
||||
Enter template name (e.g., "signature", "email"): Enter template name (e.g., "signature", "email")
|
||||
Global: Global
|
||||
Global Template: Global Template
|
||||
Global Templates: Global Templates
|
||||
Preview usage: Preview usage
|
||||
Template Usage: Template Usage
|
||||
Template name already exists: Template name already exists. Please choose a different name.
|
||||
Template name cannot be changed after creation. Delete and recreate to change name.: Template name cannot be changed after creation. Delete and recreate to change name.
|
||||
Use Global Template: Use Global Template
|
||||
addTemplateButton: Add Template
|
||||
confirmDeleteTemplateMessage: Are you sure you want to delete the global template '{{name}}'?
|
||||
confirmDeleteTemplateTitle: Confirm Delete
|
||||
deleteTemplateButtonTooltip: Delete Template
|
||||
enableGlobalTemplatesLabel: Enable Global Templates
|
||||
globalTemplatesDescription: Manage reusable text snippets that can be inserted into any clip using {{template_name}}.
|
||||
globalTemplatesTitle: Global Templates
|
||||
localTemplateConflictWarning: A global template named '{{label}}' also exists. The local template will take precedence within this clip's form.
|
||||
noGlobalTemplatesYet: No global templates defined yet. Click 'Add Template' to create one.
|
||||
templateEnabledLabel: Enabled
|
||||
templateNameLabel: Name
|
||||
templateValueLabel: Value
|
@ -179,7 +179,7 @@ NAVBAR_TOUR:
|
||||
prefferedSide: bottom
|
||||
- element: '#navbar-toggle-history-split'
|
||||
popover:
|
||||
title: Toggle History Window
|
||||
title: Toggle Split History Window
|
||||
description: Click this icon to open or close the clipboard history in a separate window. Use this feature to manage your clipboard history independently from the main window.
|
||||
alignment: center
|
||||
preferredSide: bottom
|
||||
|
@ -17,9 +17,3 @@ Show collection name on the navbar: Mostrar el nombre de la colección en la bar
|
||||
Switch collections: Cambiar colecciones
|
||||
You can add the selected text to your clips or menu. Please select the option below.: Puedes añadir el texto seleccionado a tus clips o menú. Por favor, selecciona la opción de abajo.
|
||||
You need to select a different collection before deleting the current one.: Necesitas seleccionar una colección diferente antes de eliminar la actual.
|
||||
Choose which collections require PIN entry for access.: Elige qué colecciones requieren entrada de PIN para acceder.
|
||||
Pin Protected Collections: Colecciones protegidas con PIN
|
||||
Protect Collections with PIN: Proteger colecciones con PIN
|
||||
Protected Collection: Colección protegida
|
||||
Select Collections: Seleccionar colecciones
|
||||
Select protected collections: Seleccionar colecciones protegidas
|
||||
|
@ -54,8 +54,9 @@ Confirm Passcode: Confirmar Código de Acceso
|
||||
Confirm Password: Confirmar Contraseña
|
||||
Confirm Remove: Confirmar Eliminación
|
||||
Confirm Your Passcode: Confirma tu Código de Acceso
|
||||
Confirm Passcode Reset: Confirmar reinicio del código de acceso
|
||||
Confirm Password Reset: Confirmar reinicio de contraseña
|
||||
Confirm passcode reset: Confirmar reinicio del código de acceso
|
||||
Confirm password reset: Confirmar reinicio de contraseña
|
||||
Confirm password reset action: Confirmar acción de reinicio de contraseña
|
||||
Confirm your action: Confirma tu acción
|
||||
Confirm {{action}}: Confirmar {{action}}
|
||||
Contact Form: Formulario de Contacto
|
||||
@ -98,7 +99,6 @@ Enter Passcode: Introduce el Código de Acceso
|
||||
Enter Password: Introduce la Contraseña
|
||||
Enter Recovery Password: Introduce la Contraseña de Recuperación
|
||||
Enter passcode or password to unlock: Introduce el código de acceso o la contraseña para desbloquear
|
||||
Enter PIN to Access Protected Collection: Introduce el PIN para acceder a la colección protegida
|
||||
Errors:
|
||||
Error loading link: Error al cargar el enlace
|
||||
Cant save to file: No se puede guardar en el archivo
|
||||
@ -152,6 +152,7 @@ Number of lines: Número de líneas
|
||||
Ok, but later: De acuerdo, pero más tarde
|
||||
Open: Abrir
|
||||
Open Accessibility: Abrir Accesibilidad
|
||||
Open History Window: Abrir Ventana de Historial
|
||||
Open Window: Abrir Ventana
|
||||
Open contact form in browser: Abrir formulario de contacto en el navegador
|
||||
Open payment in browser: Abrir pago en el navegador
|
||||
@ -233,7 +234,7 @@ Set Password: Establecer Contraseña
|
||||
Show Large View: Mostrar Vista Grande
|
||||
Show all: Mostrar todo
|
||||
Source: Fuente
|
||||
Open History Window: Abrir Ventana de Historial
|
||||
Split History Window: Dividir Ventana de Historial
|
||||
Star: Destacar
|
||||
Star Selected: Destacar Seleccionados
|
||||
Stay here: Quedarse aquí
|
||||
@ -350,7 +351,3 @@ seconds: segundos
|
||||
show less: mostrar menos
|
||||
www.site: www.pastebar.app
|
||||
Size: Tamaño
|
||||
Confirm Add To Protected Collections: Confirmar agregar a colecciones protegidas
|
||||
Confirm Disable PIN Protection: Confirmar deshabilitar protección con PIN
|
||||
Confirm Remove From Protected Collections: Confirmar eliminar de colecciones protegidas
|
||||
Confirm Enable PIN Protection: Confirmar habilitar protección con PIN
|
||||
|
@ -1,4 +0,0 @@
|
||||
Please select your preferred language: Por favor seleccione su idioma preferido
|
||||
Start using PasteBar: Comience a usar PasteBar
|
||||
Submenus will move up one level after delete: Los submenús subirán un nivel tras eliminar
|
||||
Welcome to PasteBar: Bienvenido a PasteBar
|
@ -21,7 +21,8 @@ Add Section: Añadir Sección
|
||||
Add Tab: Añadir Pestaña
|
||||
Add Template Field: Añadir Campo de Plantilla
|
||||
Add a Tab: Añadir una Pestaña
|
||||
Add field {{name}} into the template: Añadir campo {{name}} a la plantilla
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Añadir campo <b>{{<b>{{name}}</b>}}</b> a la plantilla
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Añadir campo <b>{{<b>{{name}}</b>}}</b> a la plantilla
|
||||
Add image: Añadir imagen
|
||||
Add note: Añadir nota
|
||||
Add to Board: Añadir al Tablero
|
||||
@ -82,7 +83,7 @@ Delete field: Eliminar campo
|
||||
Delete tab: Eliminar pestaña
|
||||
Detect Template Fields: Detectar Campos de Plantilla
|
||||
Detect for Template Fields: Detectar Campos de Plantilla
|
||||
Disabled field {{name}} has been found in the template: Se ha encontrado el campo deshabilitado {{name}} en la plantilla
|
||||
Disabled field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Se ha encontrado el campo deshabilitado <b>{{<b>{{name}}</b>}}</b> en la plantilla
|
||||
Done Create Clip: Clip Creado
|
||||
Done Edit: Edición Completada
|
||||
Done Edit Tabs: Edición de Pestañas Completada
|
||||
@ -134,7 +135,7 @@ FILTERED_TYPES:
|
||||
RegEx Replace: Reemplazo RegEx
|
||||
Remove Quotes: Eliminar Comillas
|
||||
Field: Campo
|
||||
Field {{name}} has been found in the template: Se ha encontrado el campo {{name}} en la plantilla
|
||||
Field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Se ha encontrado el campo <b>{{<b>{{name}}</b>}}</b> en la plantilla
|
||||
Field Options: Opciones de Campo
|
||||
Fields Value: Valor de Campos
|
||||
File, folder or app path does not exist: La ruta del archivo, carpeta o aplicación no existe
|
||||
|
@ -69,7 +69,7 @@ Tabs and Layout Menu: Menú de Pestañas y Diseño
|
||||
Title on Popover: Título en Ventana Emergente
|
||||
Toggle Inactive Menu Items: Alternar Elementos Inactivos
|
||||
Toggle Pinned Board: Alternar Tablero Fijado
|
||||
Toggle History Window: Alternar Ventana de Historial
|
||||
Toggle Split History Window: Alternar Ventana de Historial
|
||||
Tour Completed: Tour Completado
|
||||
Tour Skipped: Tour Omitido
|
||||
Tour completed: Tour completado
|
||||
|
@ -10,7 +10,6 @@ Clear History: Borrar Historial
|
||||
Confirm Clear All History: Confirmar Borrar Todo el Historial
|
||||
Do you really want to remove ALL clipboard history items?: ¿Realmente quieres eliminar TODOS los elementos del historial?
|
||||
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: ¿Quieres eliminar los elementos del historial más antiguos que {{olderThen}} {{durationType}}?
|
||||
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: ¿Quieres eliminar todos los elementos recientes del historial del portapapeles anteriores a {{olderThen}} {{durationType}}?
|
||||
Enable Capture History: Habilitar Captura de Historial
|
||||
Enable Image Capture: Habilitar Captura de Imágenes
|
||||
Filters:
|
||||
|
@ -23,7 +23,6 @@ Lock Screen: Bloquear Pantalla
|
||||
Open PasteBar: Abrir PasteBar
|
||||
Options: Opciones
|
||||
Player: Reproductor
|
||||
Show Always on Top: Mostrar siempre en primer plano
|
||||
Show Both Panels: Mostrar Ambos Paneles
|
||||
Show Clips Panel Only: Mostrar Solo Panel de Clips
|
||||
Show Collections Name: Mostrar Nombre de Colecciones
|
||||
|
@ -64,7 +64,7 @@ Enable screen unlock requirement on app launch for enhanced security, safeguardi
|
||||
Enhance security by automatically locking the application screen after a set period of user inactivity.: Mejora la seguridad bloqueando automáticamente la pantalla de la aplicación después de un período de inactividad del usuario.
|
||||
Enter Passcode length: Ingresa la longitud del código de acceso
|
||||
Enter recovery password to reset passcode.: Ingresa la contraseña de recuperación para restablecer el código de acceso.
|
||||
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Ingresa tu código de <strong>{{screenLockPassCodeLength}} dígitos</strong>
|
||||
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Ingresa tu código de <strong>{{screenLockPassCodeLength}} dígitos</strong>
|
||||
Entered Passcode is invalid: El código de acceso ingresado no es válido
|
||||
Excluded Apps List: Lista de Apps Excluidas
|
||||
Execute Web Requests: Ejecutar Solicitudes Web
|
||||
|
@ -14,23 +14,18 @@ PasteBar Quick Paste: Pegado rápido PasteBar
|
||||
Press keys: Presiona las teclas
|
||||
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: Eliminar el icono de PasteBar del Dock de macOS mientras mantiene la aplicación ejecutándose en segundo plano. La aplicación permanece accesible a través del icono de la barra de menú. Requiere reiniciar la aplicación para que tenga efecto.
|
||||
Set: Establecer
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.: Establecer atajos de teclado del sistema para mostrar/ocultar la ventana principal y la ventana de pegado rápido. Admite hasta combinaciones de 3 teclas.
|
||||
'How to set hotkeys:': 'Cómo establecer atajos de teclado:'
|
||||
Click Set/Change button to start recording: Haz clic en el botón Establecer/Cambiar para comenzar a grabar
|
||||
Press your desired key combination (e.g., Ctrl+Shift+V): Presiona tu combinación de teclas deseada (ej. Ctrl+Shift+V)
|
||||
Press Enter to confirm or Escape to cancel: Presiona Enter para confirmar o Escape para cancelar
|
||||
Press Backspace/Delete to clear the hotkey: Presiona Backspace/Delete para borrar el atajo de teclado
|
||||
Press your key combination...: Presiona tu combinación de teclas...
|
||||
Recording...: Grabando...
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window: Establecer atajos de teclado del sistema para mostrar/ocultar la ventana principal y la ventana de pegado rápido
|
||||
Show Navbar Items Hover: Mostrar elementos de barra al pasar el ratón
|
||||
Show collections menu on the navbar: Mostrar menú de colecciones en la barra de navegación
|
||||
Show navbar elements on hover only: Mostrar elementos de la barra solo al pasar el ratón
|
||||
Show/Hide Main App Window: Mostrar/Ocultar ventana principal
|
||||
Show/Hide Quick Paste Window: Mostrar/Ocultar ventana de pegado rápido
|
||||
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: Cuando está habilitado, hacer clic en elementos del menú solo copiará el contenido al portapapeles en lugar de pegarlo automáticamente. Esto te da más control sobre cuándo y dónde se pega el contenido.
|
||||
Quick Paste Window: Ventana de pegado rápido
|
||||
Show Note Icons on Clips: Mostrar iconos de notas en clips
|
||||
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Mostrar iconos persistentes en clips que tienen notas para mejorar la organización visual y hacer que las notas sean más fáciles de descubrir.
|
||||
Default Note Icon Type: Tipo de icono de nota predeterminado
|
||||
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Esto establece el tipo de icono predeterminado para nuevos clips con notas. Puedes personalizar clips individuales a través del menú contextual.
|
||||
Boards, saved clips and menu items panel visible: Panel de tableros, clips guardados y elementos de menú visible
|
||||
Both clipboard history and saved clips panels visible: Ambos paneles de historial del portapapeles y clips guardados visibles
|
||||
Clipboard history panel visible: Panel de historial del portapapeles visible
|
||||
@ -43,33 +38,3 @@ Show Both Panels: Mostrar ambos paneles
|
||||
Show History Panel Only: Mostrar solo panel de historial
|
||||
Show Simplified Layout: Mostrar diseño simplificado
|
||||
Simplified Panel Layout: Diseño de panel simplificado
|
||||
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Habilitar clic simple para copiar/pegar elementos del historial del portapapeles y clips guardados en lugar de requerir doble clic.
|
||||
Single Click Copy/Paste action: Acción de clic simple Copiar/Pegar
|
||||
Single Click Copy/Paste: Clic simple Copiar/Pegar
|
||||
Quick Paste Window Options: Opciones de la ventana de pegado rápido
|
||||
Configure the behavior of the Quick Paste window when selecting items: Configurar el comportamiento de la ventana de pegado rápido al seleccionar elementos
|
||||
Configure how the system tray icon responds to mouse clicks: Configurar cómo responde el icono de la bandeja del sistema a los clics del ratón
|
||||
Disable left-click context menu: Deshabilitar menú contextual del clic izquierdo
|
||||
Double-click toggles app visibility: El doble clic alterna la visibilidad de la aplicación
|
||||
Double-clicking the tray icon shows or hides the main application window: Hacer doble clic en el icono de la bandeja muestra u oculta la ventana principal de la aplicación
|
||||
Enabling either left-click option will disable the context menu to ensure proper functionality.: Habilitar cualquiera de las opciones de clic izquierdo deshabilitará el menú contextual para asegurar el funcionamiento adecuado.
|
||||
Left-click toggles app visibility: El clic izquierdo alterna la visibilidad de la aplicación
|
||||
Left-clicking the tray icon shows or hides the main application window: Hacer clic izquierdo en el icono de la bandeja muestra u oculta la ventana principal de la aplicación
|
||||
Prevents the context menu from appearing when left-clicking the tray icon: Previene que aparezca el menú contextual al hacer clic izquierdo en el icono de la bandeja
|
||||
Tray Icon Behavior on Windows: Comportamiento del icono de la bandeja en Windows
|
||||
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Esto establece el tipo de icono predeterminado para nuevos clips con notas. Puedes personalizar clips individuales a través del menú contextual.
|
||||
? When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
|
||||
: Cuando está habilitado, hacer clic en elementos del menú solo copiará el contenido al portapapeles en lugar de pegarlo automáticamente. Esto te da más control sobre cuándo y dónde se pega el contenido.
|
||||
? When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
|
||||
: Cuando está habilitado, hacer clic o presionar Enter en elementos de la ventana de pegado rápido solo los copiará al portapapeles sin pegarlos automáticamente.
|
||||
? When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
|
||||
: Cuando está habilitado, el clic simple copiará/pegará elementos en la ventana de pegado rápido. Si el clic simple global también está habilitado, ambas configuraciones funcionan juntas.
|
||||
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Configure qué elementos conservar al borrar el historial del portapapeles (tanto manual como automáticamente).
|
||||
Keep Items on Clear: Conservar elementos al borrar
|
||||
Keep Pinned Items: Conservar elementos fijados
|
||||
Keep Starred Items: Conservar elementos destacados
|
||||
Preserve pinned items when clearing history: Conservar elementos fijados al borrar el historial
|
||||
Preserve starred items when clearing history: Conservar elementos destacados al borrar el historial
|
||||
History Item Preview Max Lines: Límite máximo de líneas de vista previa de elementos del historial
|
||||
Set the maximum number of lines to display in the preview of a history item: Establecer el número máximo de líneas para mostrar en la vista previa de un elemento del historial
|
||||
Preview Max Lines: Líneas de vista previa
|
||||
|
@ -1,73 +0,0 @@
|
||||
Add Current Date/Time: Agregar Fecha/Hora Actual
|
||||
Add Line Numbers: Agregar Números de Línea
|
||||
Add One Line Feed: Agregar un Salto de Línea
|
||||
Add Two Line Feeds: Agregar dos Saltos de Línea
|
||||
Base64 Decode: Decodificar Base64
|
||||
Base64 Encode: Codificar Base64
|
||||
CSV: CSV
|
||||
CSV to JSON: CSV a JSON
|
||||
CSV to Markdown Table: CSV a Tabla Markdown
|
||||
Capitalize Case: Poner en Mayúscula
|
||||
Code Formatting: Formateo de Código
|
||||
Count Characters: Contar Caracteres
|
||||
Count Lines: Contar Líneas
|
||||
Count Sentences: Contar Oraciones
|
||||
Count Words: Contar Palabras
|
||||
Data Conversion: Conversión de Datos
|
||||
Drag and drop category to prioritize its order in the special copy/paste menu.: Arrastra y suelta la categoría para priorizar su orden en el menú especial de copiar/pegar.
|
||||
Enable All: Habilitar Todo
|
||||
Enable special text transformation options for clipboard history items: Habilitar opciones especiales de transformación de texto para elementos del historial del portapapeles
|
||||
Enabled Operations: Operaciones Habilitadas
|
||||
Encode/Decode: Codificar/Decodificar
|
||||
Format Converter: Convertidor de Formato
|
||||
HTML: HTML
|
||||
HTML Decode: Decodificar HTML
|
||||
HTML Encode: Codificar HTML
|
||||
HTML to Markdown: HTML a Markdown
|
||||
HTML to Plain Text: HTML a Texto Plano
|
||||
HTML to React Component: HTML a Componente React
|
||||
HTML to React JSX: HTML a React JSX
|
||||
HTML to Text: HTML a Texto
|
||||
JSON: JSON
|
||||
JSON Stringify: JSON a Cadena
|
||||
JSON to CSV: JSON a CSV
|
||||
JSON to Markdown Table: JSON a Tabla Markdown
|
||||
JSON to TOML: JSON a TOML
|
||||
JSON to XML: JSON a XML
|
||||
JSON to YAML: JSON a YAML
|
||||
Markdown: Markdown
|
||||
Markdown to HTML: Markdown a HTML
|
||||
Markdown to Text: Markdown a Texto
|
||||
Operations: Operaciones
|
||||
PascalCase: PascalCase
|
||||
Prioritize Category Order: Priorizar Orden de Categorías
|
||||
Remove Duplicate Lines: Eliminar Líneas Duplicadas
|
||||
Remove Extra Spaces: Eliminar Espacios Extra
|
||||
Remove Line Feeds: Eliminar Saltos de Línea
|
||||
Reverse Text: Invertir Texto
|
||||
Select Operations: Seleccionar Operaciones
|
||||
Sentence case: Tipo oración
|
||||
Sort Lines Alphabetically: Ordenar Líneas Alfabéticamente
|
||||
Special Copy: Copia Especial
|
||||
Special Copy/Paste Operations: Operaciones Especiales de Copiar/Pegar
|
||||
Special Paste: Pegado Especial
|
||||
Special Settings: Ajustes Especiales
|
||||
TOML: TOML
|
||||
TOML to JSON: TOML a JSON
|
||||
Text Case: Mayúsculas/Minúsculas
|
||||
Text Tools: Herramientas de Texto
|
||||
Title Case: Tipo Título
|
||||
Trim White Space: Recortar Espacios en Blanco
|
||||
UPPER CASE: MAYÚSCULAS
|
||||
URL Decode: Decodificar URL
|
||||
URL Encode: Codificar URL
|
||||
Whitespace & Lines: Espacios y Líneas
|
||||
XML: XML
|
||||
XML to JSON: XML a JSON
|
||||
YAML: YAML
|
||||
YAML to JSON: YAML a JSON
|
||||
camelCase: camelCase
|
||||
iNVERT cASE: iNVERTIR cASO
|
||||
kebab-case: kebab-case
|
||||
lower case: minúsculas
|
||||
snake_case: snake_case
|
@ -1,24 +0,0 @@
|
||||
Create New Template: Crear Nueva Plantilla
|
||||
Create Template: Crear Plantilla
|
||||
Enter template content...: Introduce el contenido de la plantilla...
|
||||
Enter template name (e.g., "signature", "email"): Introduce el nombre de la plantilla (ej., "firma", "email")
|
||||
Global: Global
|
||||
Global Template: Plantilla Global
|
||||
Global Templates: Plantillas Globales
|
||||
Preview usage: Vista previa de uso
|
||||
Template Usage: Uso de Plantilla
|
||||
Template name already exists: El nombre de la plantilla ya existe. Por favor, elige un nombre diferente.
|
||||
Template name cannot be changed after creation. Delete and recreate to change name.: El nombre de la plantilla no se puede cambiar después de la creación. Elimina y vuelve a crear para cambiar el nombre.
|
||||
Use Global Template: Usar Plantilla Global
|
||||
addTemplateButton: Agregar Plantilla
|
||||
confirmDeleteTemplateMessage: ¿Estás seguro de que quieres eliminar la plantilla global '{{name}}'?
|
||||
confirmDeleteTemplateTitle: Confirmar Eliminación
|
||||
deleteTemplateButtonTooltip: Eliminar Plantilla
|
||||
enableGlobalTemplatesLabel: Habilitar Plantillas Globales
|
||||
globalTemplatesDescription: Gestiona fragmentos de texto reutilizables que se pueden insertar en cualquier clip usando {{template_name}}.
|
||||
globalTemplatesTitle: Plantillas Globales
|
||||
localTemplateConflictWarning: También existe una plantilla global llamada '{{label}}'. La plantilla local tendrá prioridad dentro del formulario de este clip.
|
||||
noGlobalTemplatesYet: No hay plantillas globales definidas aún. Haz clic en 'Agregar Plantilla' para crear una.
|
||||
templateEnabledLabel: Habilitado
|
||||
templateNameLabel: Nombre
|
||||
templateValueLabel: Valor
|
@ -17,9 +17,3 @@ Show collection name on the navbar: Afficher le nom de la collection dans la bar
|
||||
Switch collections: Changer de collection
|
||||
You can add the selected text to your clips or menu. Please select the option below.: Vous pouvez ajouter le texte sélectionné à vos clips ou à votre menu. Veuillez sélectionner l'option ci-dessous.
|
||||
You need to select a different collection before deleting the current one.: Vous devez sélectionner une collection différente avant de supprimer celle actuelle.
|
||||
Choose which collections require PIN entry for access.: Choisissez quelles collections nécessitent une entrée PIN pour y accéder.
|
||||
Pin Protected Collections: Collections protégées par PIN
|
||||
Protect Collections with PIN: Protéger les collections avec un PIN
|
||||
Protected Collection: Collection protégée
|
||||
Select Collections: Sélectionner des collections
|
||||
Select protected collections: Sélectionner des collections protégées
|
||||
|
@ -54,12 +54,11 @@ Confirm Passcode: Confirmer le code d'accès
|
||||
Confirm Password: Confirmer le mot de passe
|
||||
Confirm Remove: Confirmer la suppression
|
||||
Confirm Your Passcode: Confirmer votre code d'accès
|
||||
Confirm Passcode Reset: Confirmer la réinitialisation du code d'accès
|
||||
Confirm Password Reset: Confirmer la réinitialisation du mot de passe
|
||||
Confirm Add To Protected Collections: Confirmer l'ajout aux collections protégées
|
||||
Confirm Disable PIN Protection: Confirmer la désactivation de la protection par PIN
|
||||
Confirm Remove From Protected Collections: Confirmer la suppression des collections protégées
|
||||
Confirm Enable PIN Protection: Confirmer l'activation de la protection par PIN
|
||||
Confirm passcode reset: Confirmer la réinitialisation du code d'accès
|
||||
Confirm password reset: Confirmer la réinitialisation du mot de passe
|
||||
Confirm password reset action: Confirmer l'action de réinitialisation du mot de passe
|
||||
Confirm your action: Confirmer votre action
|
||||
Confirm {{action}}: Confirmer {{action}}
|
||||
Contact Form: Formulaire de contact
|
||||
Copied: Copié
|
||||
Copy: Copier
|
||||
@ -100,7 +99,6 @@ Enter Passcode: Entrer le code d'accès
|
||||
Enter Password: Entrer le mot de passe
|
||||
Enter Recovery Password: Entrer le mot de passe de récupération
|
||||
Enter passcode or password to unlock: Entrer le code d'accès ou le mot de passe pour déverrouiller
|
||||
Enter PIN to Access Protected Collection: Entrez le PIN pour accéder à la collection protégée
|
||||
Errors:
|
||||
Error loading link: Erreur lors du chargement du lien
|
||||
Cant save to file: Impossible d'enregistrer dans le fichier
|
||||
@ -236,6 +234,7 @@ Set Password: Définir le mot de passe
|
||||
Show Large View: Afficher la vue large
|
||||
Show all: Afficher tout
|
||||
Source: Source
|
||||
Split History Window: Diviser la fenêtre d'historique
|
||||
Star: Étoile
|
||||
Star Selected: Étoile sélectionnée
|
||||
Stay here: Rester ici
|
||||
|
@ -1,4 +0,0 @@
|
||||
Please select your preferred language: Veuillez sélectionner votre langue préférée
|
||||
Start using PasteBar: Commencez à utiliser PasteBar
|
||||
Submenus will move up one level after delete: Les sous-menus remonteront d'un niveau après suppression
|
||||
Welcome to PasteBar: Bienvenue sur PasteBar
|
@ -21,7 +21,8 @@ Add Section: Ajouter une section
|
||||
Add Tab: Ajouter un onglet
|
||||
Add Template Field: Ajouter un champ de modèle
|
||||
Add a Tab: Ajouter un onglet
|
||||
Add field {{name}} into the template: Ajouter le champ {{name}} dans le modèle
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Ajouter le champ <b>{{<b>{{name}}</b>}}</b> dans le modèle
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Ajouter le champ <b>{{<b>{{name}}</b>}}</b> dans le modèle
|
||||
Add image: Ajouter une image
|
||||
Add note: Ajouter une note
|
||||
Add to Board: Ajouter au tableau
|
||||
@ -82,7 +83,7 @@ Delete field: Supprimer le champ
|
||||
Delete tab: Supprimer l'onglet
|
||||
Detect Template Fields: Détecter les champs du modèle
|
||||
Detect for Template Fields: Détecter les champs du modèle
|
||||
Disabled field {{name}} has been found in the template: Le champ désactivé {{name}} a été trouvé dans le modèle
|
||||
Disabled field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Le champ désactivé <b>{{<b>{{name}}</b>}}</b> a été trouvé dans le modèle
|
||||
Done Create Clip: Création du clip terminée
|
||||
Done Edit: Édition terminée
|
||||
Done Edit Tabs: Édition des onglets terminée
|
||||
@ -134,7 +135,7 @@ FILTERED_TYPES:
|
||||
RegEx Replace: Remplacement par expression régulière
|
||||
Remove Quotes: Supprimer les guillemets
|
||||
Field: Champ
|
||||
Field {{name}} has been found in the template: Le champ {{name}} a été trouvé dans le modèle
|
||||
Field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Le champ <b>{{<b>{{name}}</b>}}</b> a été trouvé dans le modèle
|
||||
Field Options: Options du champ
|
||||
Fields Value: Valeur des champs
|
||||
File, folder or app path does not exist: Le chemin du fichier, dossier ou application n'existe pas
|
||||
|
@ -69,7 +69,7 @@ Tabs and Layout Menu: Menu des onglets et de la disposition
|
||||
Title on Popover: Titre sur la fenêtre contextuelle
|
||||
Toggle Inactive Menu Items: Basculer les éléments de menu inactifs
|
||||
Toggle Pinned Board: Basculer le tableau épinglé
|
||||
Toggle History Window: Fenêtre d'historique
|
||||
Toggle Split History Window: Fenêtre d'historique fractionnée
|
||||
Tour Completed: Visite terminée
|
||||
Tour Skipped: Visite passée
|
||||
Tour completed: Visite terminée
|
||||
|
@ -10,7 +10,6 @@ Clear History: Effacer l'historique
|
||||
Confirm Clear All History: Confirmer l'effacement de tout l'historique
|
||||
Do you really want to remove ALL clipboard history items?: Voulez-vous vraiment supprimer TOUS les éléments de l'historique du presse-papier ?
|
||||
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: Voulez-vous supprimer les éléments de l'historique du presse-papier antérieurs à {{olderThen}} {{durationType}}
|
||||
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: Voulez-vous supprimer tous les éléments récents de l'historique du presse-papiers antérieurs à {{olderThen}} {{durationType}} ?
|
||||
Enable Capture History: Activer la capture de l'historique
|
||||
Enable Image Capture: Activer la capture d'images
|
||||
Filters:
|
||||
|
@ -23,7 +23,6 @@ Lock Screen: Écran de verrouillage
|
||||
Open PasteBar: Ouvrir PasteBar
|
||||
Options: Options
|
||||
Player: Lecteur
|
||||
Show Always on Top: Toujours au premier plan
|
||||
Show Both Panels: Afficher les deux panneaux
|
||||
Show Clips Panel Only: Afficher seulement le panneau clips
|
||||
Show Collections Name: Afficher le nom des collections
|
||||
|
@ -64,7 +64,7 @@ Enable screen unlock requirement on app launch for enhanced security, safeguardi
|
||||
Enhance security by automatically locking the application screen after a set period of user inactivity.: Renforcez la sécurité en verrouillant automatiquement l'écran de l'application après une période déterminée d'inactivité de l'utilisateur.
|
||||
Enter Passcode length: Saisir la longueur du code d'accès
|
||||
Enter recovery password to reset passcode.: Saisir le mot de passe de récupération pour réinitialiser le code d'accès.
|
||||
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Entrez votre code à <strong>{{screenLockPassCodeLength}} chiffres</strong>
|
||||
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Entrez votre code à <strong>{{screenLockPassCodeLength}} chiffres</strong>
|
||||
Entered Passcode is invalid: Code saisi non valide
|
||||
Excluded Apps List: Liste applicationss exclues
|
||||
Execute Web Requests: Exécuter requêtes web
|
||||
|
@ -15,22 +15,17 @@ Press keys: Appuyez sur les touches
|
||||
Quick Paste Window: Fenêtre de collage rapide
|
||||
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: Supprimer l'icône PasteBar du Dock macOS tout en gardant l'app en cours d'exécution en arrière-plan. L'app reste accessible via l'icône de la barre de menu. Nécessite un redémarrage de l'app pour prendre effet.
|
||||
Set: Définir
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.: Définir les raccourcis clavier du système pour afficher/masquer la fenêtre principale et la fenêtre de collage rapide. Prend en charge jusqu'à 3 combinaisons de touches.
|
||||
'How to set hotkeys:': 'Comment définir les raccourcis clavier :'
|
||||
Click Set/Change button to start recording: Cliquez sur le bouton Définir/Modifier pour commencer l'enregistrement
|
||||
Press your desired key combination (e.g., Ctrl+Shift+V): Appuyez sur votre combinaison de touches souhaitée (ex. Ctrl+Shift+V)
|
||||
Press Enter to confirm or Escape to cancel: Appuyez sur Entrée pour confirmer ou Échap pour annuler
|
||||
Press Backspace/Delete to clear the hotkey: Appuyez sur Retour arrière/Supprimer pour effacer le raccourci clavier
|
||||
Press your key combination...: Appuyez sur votre combinaison de touches...
|
||||
Recording...: Enregistrement...
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window: Définir les raccourcis clavier du système pour afficher/masquer la fenêtre principale et la fenêtre de collage rapide
|
||||
Show Navbar Items Hover: Afficher éléments barre au survol
|
||||
Show collections menu on the navbar: Afficher le menu des collections dans la barre de navigation
|
||||
Show navbar elements on hover only: Afficher les éléments de la barre uniquement au survol
|
||||
Show/Hide Quick Paste Window: Afficher/Masquer fenêtre de collage rapide
|
||||
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: Lorsqu'activé, cliquer sur les éléments du menu copiera uniquement le contenu dans le presse-papiers au lieu de le coller automatiquement. Cela vous donne plus de contrôle sur le moment et l'endroit où le contenu est collé.
|
||||
Show/Hide Main App Window: Afficher/Masquer la fenêtre principale de l'application
|
||||
Show Note Icons on Clips: Afficher les icônes de notes sur les clips
|
||||
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Afficher des icônes persistantes sur les clips qui ont des notes pour améliorer l'organisation visuelle et faciliter la découverte des notes.
|
||||
Default Note Icon Type: Type d'icône de note par défaut
|
||||
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Cela définit le type d'icône par défaut pour les nouveaux clips avec des notes. Vous pouvez personnaliser les clips individuels via le menu contextuel.
|
||||
Boards, saved clips and menu items panel visible: Panneau des tableaux, clips sauvegardés et éléments de menu visible
|
||||
Both clipboard history and saved clips panels visible: Les deux panneaux d'historique du presse-papiers et de clips sauvegardés visibles
|
||||
Clipboard history panel visible: Panneau d'historique du presse-papiers visible
|
||||
@ -43,36 +38,3 @@ Show Both Panels: Afficher les deux panneaux
|
||||
Show History Panel Only: Afficher uniquement le panneau historique
|
||||
Show Simplified Layout: Afficher la mise en page simplifiée
|
||||
Simplified Panel Layout: Mise en page de panneau simplifiée
|
||||
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Activer le clic simple pour copier/coller les éléments de l'historique du presse-papiers et les clips sauvegardés au lieu d'exiger un double-clic.
|
||||
Single Click Copy/Paste action: Action clic simple Copier/Coller
|
||||
Single Click Copy/Paste: Clic simple Copier/Coller
|
||||
Quick Paste Window Options: Options de la fenêtre de collage rapide
|
||||
Configure the behavior of the Quick Paste window when selecting items: Configurer le comportement de la fenêtre de collage rapide lors de la sélection d'éléments
|
||||
Copy items only (no auto-paste): Copier uniquement les éléments (pas de collage automatique)
|
||||
Auto-close window after action: Fermer automatiquement la fenêtre après l'action
|
||||
When enabled, the Quick Paste window will automatically close after copying or pasting an item.: Lorsqu'activé, la fenêtre de collage rapide se fermera automatiquement après avoir copié ou collé un élément.
|
||||
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Cela définit le type d'icône par défaut pour les nouveaux clips avec des notes. Vous pouvez personnaliser les clips individuels via le menu contextuel.
|
||||
? When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
|
||||
: Lorsqu'activé, cliquer sur les éléments du menu copiera uniquement le contenu dans le presse-papiers au lieu de le coller automatiquement. Cela vous donne plus de contrôle sur le moment et l'endroit où le contenu est collé.
|
||||
? When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
|
||||
: Lorsqu'activé, cliquer ou appuyer sur Entrée sur les éléments dans la fenêtre de collage rapide les copiera uniquement dans le presse-papiers sans les coller automatiquement.
|
||||
? When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
|
||||
: Lorsqu'activé, un clic simple copiera/collera les éléments dans la fenêtre de collage rapide. Si le clic simple global est également activé, les deux paramètres fonctionnent ensemble.
|
||||
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Configurez les éléments à conserver lors de l'effacement de l'historique du presse-papiers (manuellement ou automatiquement).
|
||||
Keep Items on Clear: Conserver les éléments lors de l'effacement
|
||||
Keep Pinned Items: Conserver les éléments épinglés
|
||||
Keep Starred Items: Conserver les éléments favoris
|
||||
Preserve pinned items when clearing history: Conserver les éléments épinglés lors de l'effacement de l'historique
|
||||
Preserve starred items when clearing history: Conserver les éléments favoris lors de l'effacement de l'historique
|
||||
History Item Preview Max Lines: Limite maximale de lignes d'aperçu des éléments de l'historique
|
||||
Set the maximum number of lines to display in the preview of a history item: Définir le nombre maximal de lignes à afficher dans l'aperçu d'un élément de l'historique
|
||||
Preview Max Lines: Lignes d'aperçu
|
||||
Configure how the system tray icon responds to mouse clicks: Configurer comment l'icône de la barre système répond aux clics de souris
|
||||
Disable left-click context menu: Désactiver le menu contextuel du clic gauche
|
||||
Double-click toggles app visibility: Le double-clic bascule la visibilité de l'application
|
||||
Double-clicking the tray icon shows or hides the main application window: Double-cliquer sur l'icône de la barre système affiche ou masque la fenêtre principale de l'application
|
||||
Enabling either left-click option will disable the context menu to ensure proper functionality.: L'activation de l'une ou l'autre des options de clic gauche désactivera le menu contextuel pour assurer un bon fonctionnement.
|
||||
Left-click toggles app visibility: Le clic gauche bascule la visibilité de l'application
|
||||
Left-clicking the tray icon shows or hides the main application window: Cliquer gauche sur l'icône de la barre système affiche ou masque la fenêtre principale de l'application
|
||||
Prevents the context menu from appearing when left-clicking the tray icon: Empêche le menu contextuel d'apparaître lors du clic gauche sur l'icône de la barre système
|
||||
Tray Icon Behavior on Windows: Comportement de l'icône de la barre système sur Windows
|
||||
|
@ -1,73 +0,0 @@
|
||||
Add Current Date/Time: Ajouter Date/Heure Actuelle
|
||||
Add Line Numbers: Ajouter Numéros de Ligne
|
||||
Add One Line Feed: Ajouter un Saut de Ligne
|
||||
Add Two Line Feeds: Ajouter deux Sauts de Ligne
|
||||
Base64 Decode: Décoder Base64
|
||||
Base64 Encode: Encoder Base64
|
||||
CSV: CSV
|
||||
CSV to JSON: CSV vers JSON
|
||||
CSV to Markdown Table: CSV vers Tableau Markdown
|
||||
Capitalize Case: Mettre en Capitale
|
||||
Code Formatting: Formatage de Code
|
||||
Count Characters: Compter les Caractères
|
||||
Count Lines: Compter les Lignes
|
||||
Count Sentences: Compter les Phrases
|
||||
Count Words: Compter les Mots
|
||||
Data Conversion: Conversion de Données
|
||||
Drag and drop category to prioritize its order in the special copy/paste menu.: Glissez-déposez la catégorie pour prioriser son ordre dans le menu spécial copier/coller.
|
||||
Enable All: Activer Tout
|
||||
Enable special text transformation options for clipboard history items: Activer les options de transformation de texte spéciales pour les éléments de l'historique du presse-papiers
|
||||
Enabled Operations: Opérations Activées
|
||||
Encode/Decode: Encoder/Décoder
|
||||
Format Converter: Convertisseur de Format
|
||||
HTML: HTML
|
||||
HTML Decode: Décoder HTML
|
||||
HTML Encode: Encoder HTML
|
||||
HTML to Markdown: HTML vers Markdown
|
||||
HTML to Plain Text: HTML vers Texte Brut
|
||||
HTML to React Component: HTML vers Composant React
|
||||
HTML to React JSX: HTML vers React JSX
|
||||
HTML to Text: HTML vers Texte
|
||||
JSON: JSON
|
||||
JSON Stringify: JSON Stringify
|
||||
JSON to CSV: JSON vers CSV
|
||||
JSON to Markdown Table: JSON vers Tableau Markdown
|
||||
JSON to TOML: JSON vers TOML
|
||||
JSON to XML: JSON vers XML
|
||||
JSON to YAML: JSON vers YAML
|
||||
Markdown: Markdown
|
||||
Markdown to HTML: Markdown vers HTML
|
||||
Markdown to Text: Markdown vers Texte
|
||||
Operations: Opérations
|
||||
PascalCase: PascalCase
|
||||
Prioritize Category Order: Prioriser l'Ordre des Catégories
|
||||
Remove Duplicate Lines: Supprimer Lignes Doubles
|
||||
Remove Extra Spaces: Supprimer Espaces Superflus
|
||||
Remove Line Feeds: Supprimer Sauts de Ligne
|
||||
Reverse Text: Inverser le Texte
|
||||
Select Operations: Sélectionner Opérations
|
||||
Sentence case: Cas de la phrase
|
||||
Sort Lines Alphabetically: Trier Lignes par Ordre Alphabétique
|
||||
Special Copy: Copie Spéciale
|
||||
Special Copy/Paste Operations: Opérations Spéciales Copier/Coller
|
||||
Special Paste: Collage Spécial
|
||||
Special Settings: Paramètres Spéciaux
|
||||
TOML: TOML
|
||||
TOML to JSON: TOML vers JSON
|
||||
Text Case: Casse du Texte
|
||||
Text Tools: Outils Texte
|
||||
Title Case: Cas du Titre
|
||||
Trim White Space: Supprimer Espaces Blancs
|
||||
UPPER CASE: MAJUSCULES
|
||||
URL Decode: Décoder URL
|
||||
URL Encode: Encoder URL
|
||||
Whitespace & Lines: Espaces & Lignes
|
||||
XML: XML
|
||||
XML to JSON: XML vers JSON
|
||||
YAML: YAML
|
||||
YAML to JSON: YAML vers JSON
|
||||
camelCase: camelCase
|
||||
iNVERT cASE: iNVERSER cASSE
|
||||
kebab-case: kebab-case
|
||||
lower case: minuscules
|
||||
snake_case: snake_case
|
@ -1,24 +0,0 @@
|
||||
Create New Template: Créer un Nouveau Modèle
|
||||
Create Template: Créer un Modèle
|
||||
Enter template content...: Saisir le contenu du modèle...
|
||||
Enter template name (e.g., "signature", "email"): Saisir le nom du modèle (ex. "signature", "email")
|
||||
Global: Global
|
||||
Global Template: Modèle Global
|
||||
Global Templates: Modèles Globaux
|
||||
Preview usage: Aperçu d'utilisation
|
||||
Template Usage: Utilisation du Modèle
|
||||
Template name already exists: Le nom du modèle existe déjà. Veuillez choisir un nom différent.
|
||||
Template name cannot be changed after creation. Delete and recreate to change name.: Le nom du modèle ne peut pas être modifié après création. Supprimez et recréez pour changer le nom.
|
||||
Use Global Template: Utiliser le Modèle Global
|
||||
addTemplateButton: Ajouter un Modèle
|
||||
confirmDeleteTemplateMessage: Êtes-vous sûr de vouloir supprimer le modèle global '{{name}}' ?
|
||||
confirmDeleteTemplateTitle: Confirmer la Suppression
|
||||
deleteTemplateButtonTooltip: Supprimer le Modèle
|
||||
enableGlobalTemplatesLabel: Activer les Modèles Globaux
|
||||
globalTemplatesDescription: Gérez des fragments de texte réutilisables qui peuvent être insérés dans n'importe quel clip en utilisant {{template_name}}.
|
||||
globalTemplatesTitle: Modèles Globaux
|
||||
localTemplateConflictWarning: Un modèle global nommé '{{label}}' existe également. Le modèle local aura la priorité dans le formulaire de ce clip.
|
||||
noGlobalTemplatesYet: Aucun modèle global défini pour le moment. Cliquez sur 'Ajouter un Modèle' pour en créer un.
|
||||
templateEnabledLabel: Activé
|
||||
templateNameLabel: Nom
|
||||
templateValueLabel: Valeur
|
@ -17,9 +17,3 @@ Show collection name on the navbar: Mostra il nome della collezione sulla barra
|
||||
Switch collections: Cambia collezione
|
||||
You can add the selected text to your clips or menu. Please select the option below.: Puoi aggiungere il testo selezionato ai tuoi clip o al menu. Seleziona l'opzione qui sotto.
|
||||
You need to select a different collection before deleting the current one.: Devi selezionare una collezione diversa prima di eliminare quella corrente.
|
||||
Choose which collections require PIN entry for access.: Scegli quali collezioni richiedono l'inserimento del PIN per l'accesso.
|
||||
Pin Protected Collections: Collezioni protette con PIN
|
||||
Protect Collections with PIN: Proteggi le collezioni con PIN
|
||||
Protected Collection: Collezione protetta
|
||||
Select Collections: Seleziona collezioni
|
||||
Select protected collections: Seleziona collezioni protette
|
||||
|
@ -51,13 +51,10 @@ Confirm Password: Conferma Password
|
||||
Confirm Remove: Conferma Rimozione
|
||||
Confirm Your Passcode: Conferma il Tuo Codice di Accesso
|
||||
Confirm action: Conferma azione
|
||||
Confirm Password Reset: Conferma reset password
|
||||
Confirm password reset: Conferma reset password
|
||||
Confirm password reset action: Conferma azione di reset password
|
||||
Confirm your action: Conferma la tua azione
|
||||
Confirm {{action}}: Conferma {{action}}
|
||||
Confirm Add To Protected Collections: Conferma aggiunta alle collezioni protette
|
||||
Confirm Disable PIN Protection: Conferma disabilitazione protezione con PIN
|
||||
Confirm Remove From Protected Collections: Conferma rimozione dalle collezioni protette
|
||||
Confirm Enable PIN Protection: Conferma abilitazione protezione con PIN
|
||||
Contact Form: Modulo di Contatto
|
||||
Copied: Copiato
|
||||
Copy: Copia
|
||||
@ -98,7 +95,6 @@ Enter Passcode: Inserisci Codice di Accesso
|
||||
Enter Password: Inserisci Password
|
||||
Enter Recovery Password: Inserisci Password di Recupero
|
||||
Enter passcode or password to unlock: Inserisci codice di accesso o password per sbloccare
|
||||
Enter PIN to Access Protected Collection: Inserisci il PIN per accedere alla collezione protetta
|
||||
Errors:
|
||||
Error loading link: Errore nel caricamento del link
|
||||
Cant save file: Impossibile salvare il file
|
||||
@ -235,7 +231,7 @@ Show Large View: Mostra Vista Grande
|
||||
Show all: Mostra tutto
|
||||
Something goes wrong! Please try again.: Qualcosa è andato storto! Per favore riprova.
|
||||
Source: Fonte
|
||||
Open History Window: Apri Finestra Cronologia
|
||||
Split History Window: Dividi Finestra Cronologia
|
||||
Star: Stella
|
||||
Star Selected: Aggiungi Stella ai Selezionati
|
||||
Stay here: Rimani qui
|
||||
|
@ -1,4 +0,0 @@
|
||||
Please select your preferred language: Seleziona la tua lingua preferita
|
||||
Start using PasteBar: Inizia a usare PasteBar
|
||||
Submenus will move up one level after delete: I sottomenu saliranno di un livello dopo l'eliminazione
|
||||
Welcome to PasteBar: Benvenuto su PasteBar
|
@ -21,7 +21,8 @@ Add Section: Aggiungi Sezione
|
||||
Add Tab: Aggiungi Scheda
|
||||
Add Template Field: Aggiungi Campo Modello
|
||||
Add a Tab: Aggiungi una Scheda
|
||||
Add field {{name}} into the template: Aggiungi il campo {{name}} al modello
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Aggiungi il campo <b>{{<b>{{name}}</b>}}</b> al modello
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Aggiungi il campo <b>{{<b>{{name}}</b>}}</b> al modello
|
||||
Add image: Aggiungi immagine
|
||||
Add note: Aggiungi nota
|
||||
Add to Board: Aggiungi alla Bacheca
|
||||
@ -84,7 +85,7 @@ Delete field: Elimina campo
|
||||
Delete tab: Elimina scheda
|
||||
Detect Template Fields: Rileva Campi del Modello
|
||||
Detect for Template Fields: Rileva Campi del Modello
|
||||
Disabled field {{name}} has been found in the template: Il campo disabilitato {{name}} è stato trovato nel modello
|
||||
Disabled field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Il campo disabilitato <b>{{<b>{{name}}</b>}}</b> è stato trovato nel modello
|
||||
Done Create Clip: Creazione Clip Completata
|
||||
Done Edit: Modifica Completata
|
||||
Done Edit Tabs: Modifica Schede Completata
|
||||
@ -136,7 +137,7 @@ FILTERED_TYPES:
|
||||
RegEx Replace: Sostituzione con Espressione Regolare
|
||||
Remove Quotes: Rimuovi Virgolette
|
||||
Field: Campo
|
||||
Field {{name}} has been found in the template: Il campo {{name}} è stato trovato nel modello
|
||||
Field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Il campo <b>{{<b>{{name}}</b>}}</b> è stato trovato nel modello
|
||||
Field Options: Opzioni Campo
|
||||
Fields Value: Valore Campi
|
||||
File, folder or app path does not exist: Il percorso del file, cartella o app non esiste
|
||||
|
@ -69,7 +69,7 @@ Tabs and Layout Menu: Menu Schede e Layout
|
||||
Title on Popover: Titolo su Popover
|
||||
Toggle Inactive Menu Items: Attiva/Disattiva Voci di Menu Inattive
|
||||
Toggle Pinned Board: Attiva/Disattiva Bacheca Fissata
|
||||
Toggle History Window: Attiva/Disattiva Finestra Cronologia
|
||||
Toggle Split History Window: Attiva/Disattiva Finestra Cronologia Divisa
|
||||
Tour Completed: Tour Completato
|
||||
Tour Skipped: Tour Saltato
|
||||
Tour completed: Tour completato
|
||||
|
@ -10,7 +10,6 @@ Clear History: Cancella Cronologia
|
||||
Confirm Clear All History: Conferma Cancellazione di Tutta la Cronologia
|
||||
Do you really want to remove ALL clipboard history items?: Vuoi davvero rimuovere TUTTI gli elementi della cronologia degli appunti?
|
||||
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: Vuoi rimuovere gli elementi della cronologia degli appunti più vecchi di {{olderThen}} {{durationType}}
|
||||
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: Vuoi rimuovere tutti gli elementi recenti della cronologia degli appunti più vecchi di {{olderThen}} {{durationType}}?
|
||||
Enable Capture History: Abilita Cattura Cronologia
|
||||
Enable Image Capture: Abilita Cattura Immagini
|
||||
Filters:
|
||||
|
@ -23,7 +23,6 @@ Lock Screen: Blocca Schermo
|
||||
Open PasteBar: Apri PasteBar
|
||||
Options: Opzioni
|
||||
Player: Lettore
|
||||
Show Always on Top: Mostra sempre in primo piano
|
||||
Show Both Panels: Mostra Entrambi i Pannelli
|
||||
Show Clips Panel Only: Mostra Solo Pannello Clip
|
||||
Show Collections Name: Mostra Nome Collezioni
|
||||
|
@ -63,7 +63,7 @@ Enable screen unlock requirement on app launch for enhanced security, safeguardi
|
||||
Enhance security by automatically locking the application screen after a set period of user inactivity.: Migliora la sicurezza bloccando automaticamente lo schermo dell'applicazione dopo un periodo impostato di inattività dell'utente.
|
||||
Enter Passcode length: Inserisci la lunghezza del codice di accesso
|
||||
Enter recovery password to reset passcode.: Inserisci la password di recupero per reimpostare il codice di accesso.
|
||||
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Inserisci il tuo codice di accesso di <strong>{{screenLockPassCodeLength}}cifre</strong>
|
||||
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Inserisci il tuo codice di accesso di <strong>{{screenLockPassCodeLength}} cifre</strong>
|
||||
Entered Passcode is invalid: Il codice di accesso inserito non è valido
|
||||
Excluded Apps List: Lista delle App Escluse
|
||||
Execute Web Requests: Esegui Richieste Web
|
||||
|
@ -1,13 +1,8 @@
|
||||
App restart required: Riavvio necessario
|
||||
Application Starts with Main Window Hidden: L'applicazione si avvia con la finestra principale nascosta
|
||||
Change: Modifica
|
||||
Configure how the system tray icon responds to mouse clicks: Configura come l'icona della barra di sistema risponde ai clic del mouse
|
||||
Copy only from menu items: Copia solo dagli elementi del menu
|
||||
Disable left-click context menu: Disabilita menu contestuale clic sinistro
|
||||
Display navbar items only when the mouse hovers over the navigation bar to minimize visible UI elements: Mostra gli elementi della barra di navigazione solo al passaggio del mouse per minimizzare gli elementi visibili dell'interfaccia
|
||||
Double-click toggles app visibility: Il doppio clic commuta la visibilità dell'app
|
||||
Double-clicking the tray icon shows or hides the main application window: Fare doppio clic sull'icona della barra di sistema mostra o nasconde la finestra principale dell'applicazione
|
||||
Enabling either left-click option will disable the context menu to ensure proper functionality.: L'abilitazione di una delle opzioni di clic sinistro disabiliterà il menu contestuale per garantire il corretto funzionamento.
|
||||
Global System OS Hotkeys: Tasti di scelta rapida globali del sistema
|
||||
Hide Collections Navbar: Nascondi barra delle collezioni
|
||||
Hide collections menu dropdown on the navigation bar: Nascondi il menu a discesa delle collezioni nella barra di navigazione
|
||||
@ -20,22 +15,17 @@ Press keys: Premi i tasti
|
||||
Quick Paste Window: Finestra incolla rapido
|
||||
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: Rimuovi l'icona di PasteBar dal Dock di macOS mantenendo l'app in esecuzione in background. L'app rimane accessibile tramite l'icona della barra dei menu. Richiede un riavvio dell'app per avere effetto.
|
||||
Set: Imposta
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window: Imposta i tasti di scelta rapida del sistema per mostrare/nascondere la finestra principale e la finestra incolla rapido. Supporta combinazioni fino a 3 tasti.
|
||||
'How to set hotkeys:': 'Come impostare i tasti di scelta rapida:'
|
||||
Click Set/Change button to start recording: Fai clic sul pulsante Imposta/Modifica per iniziare la registrazione
|
||||
Press your desired key combination (e.g., Ctrl+Shift+V): Premi la combinazione di tasti desiderata (ad esempio, Ctrl+Shift+V)
|
||||
Press Enter to confirm or Escape to cancel: Premi Invio per confermare o Esc per annullare
|
||||
Press Backspace/Delete to clear the hotkey: Premi Backspace/Canc per cancellare il tasto di scelta rapida
|
||||
Press your key combination...: Premi la tua combinazione di tasti...
|
||||
Recording...: Registrazione...
|
||||
Set system OS hotkeys to show/hide the main app window and quick paste window: Imposta i tasti di scelta rapida del sistema per mostrare/nascondere la finestra principale e la finestra incolla rapido
|
||||
Show Navbar Items Hover: Mostra elementi barra al passaggio del mouse
|
||||
Show collections menu on the navbar: Mostra il menu delle collezioni nella barra di navigazione
|
||||
Show navbar elements on hover only: Mostra elementi della barra solo al passaggio del mouse
|
||||
Show/Hide Quick Paste Window: Mostra/Nascondi finestra incolla rapido
|
||||
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: Quando abilitato, cliccando sugli elementi del menu si copierà solo il contenuto negli appunti invece di incollarlo automaticamente. Questo ti dà maggior controllo su quando e dove incollare il contenuto.
|
||||
Show/Hide Main App Window: Mostra/Nascondi la finestra principale dell'applicazione
|
||||
Show Note Icons on Clips: Mostra icone delle note sui clip
|
||||
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Visualizza icone persistenti sui clip che hanno note per migliorare l'organizzazione visiva e rendere le note più facili da scoprire.
|
||||
Default Note Icon Type: Tipo di icona nota predefinito
|
||||
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Questo imposta il tipo di icona predefinito per i nuovi clip con note. Puoi personalizzare i singoli clip tramite il menu contestuale.
|
||||
Boards, saved clips and menu items panel visible: Pannello di bacheche, clip salvati e elementi menu visibile
|
||||
Both clipboard history and saved clips panels visible: Entrambi i pannelli cronologia appunti e clip salvati visibili
|
||||
Clipboard history panel visible: Pannello cronologia appunti visibile
|
||||
@ -48,27 +38,3 @@ Show Both Panels: Mostra entrambi i pannelli
|
||||
Show History Panel Only: Mostra solo pannello cronologia
|
||||
Show Simplified Layout: Mostra layout semplificato
|
||||
Simplified Panel Layout: Layout pannello semplificato
|
||||
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Abilita clic singolo per copiare/incollare elementi della cronologia appunti e clip salvati invece di richiedere doppio clic.
|
||||
Single Click Copy/Paste action: Azione clic singolo Copia/Incolla
|
||||
Single Click Copy/Paste: Clic singolo Copia/Incolla
|
||||
Quick Paste Window Options: Opzioni finestra incolla rapido
|
||||
Configure the behavior of the Quick Paste window when selecting items: Configura il comportamento della finestra incolla rapido quando si selezionano elementi
|
||||
Copy items only (no auto-paste): Copia solo elementi (nessun incolla automatico)
|
||||
Auto-close window after action: Chiudi automaticamente finestra dopo l'azione
|
||||
When enabled, the Quick Paste window will automatically close after copying or pasting an item.: Quando abilitato, la finestra incolla rapido si chiuderà automaticamente dopo aver copiato o incollato un elemento.
|
||||
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Questo imposta il tipo di icona predefinito per i nuovi clip con note. Puoi personalizzare i singoli clip tramite il menu contestuale.
|
||||
? When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
|
||||
: Quando abilitato, cliccando sugli elementi del menu si copierà solo il contenuto negli appunti invece di incollarlo automaticamente. Questo ti dà maggior controllo su quando e dove incollare il contenuto.
|
||||
? When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
|
||||
: Quando abilitato, cliccando o premendo Invio sugli elementi nella finestra incolla rapido li copierà solo negli appunti senza incollarli automaticamente.
|
||||
? When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
|
||||
: Quando abilitato, il clic singolo copierà/incollerà elementi nella finestra incolla rapido. Se anche il clic singolo globale è abilitato, entrambe le impostazioni funzionano insieme.
|
||||
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Configura quali elementi conservare durante la cancellazione della cronologia degli appunti (sia manuale che automatica).
|
||||
Keep Items on Clear: Conserva elementi durante la cancellazione
|
||||
Keep Pinned Items: Conserva elementi fissati
|
||||
Keep Starred Items: Conserva elementi preferiti
|
||||
Preserve pinned items when clearing history: Conserva elementi fissati durante la cancellazione della cronologia
|
||||
Preserve starred items when clearing history: Conserva elementi preferiti durante la cancellazione della cronologia
|
||||
History Item Preview Max Lines: Limite massimo di righe di anteprima degli elementi della cronologia
|
||||
Set the maximum number of lines to display in the preview of a history item: Imposta il numero massimo di righe da visualizzare nell'anteprima di un elemento della cronologia
|
||||
Preview Max Lines: Righe di anteprima
|
||||
|
@ -1,73 +0,0 @@
|
||||
Add Current Date/Time: Aggiungi Data/Ora Attuale
|
||||
Add Line Numbers: Aggiungi Numeri di Riga
|
||||
Add One Line Feed: Aggiungi un a Capo
|
||||
Add Two Line Feeds: Aggiungi due a Capo
|
||||
Base64 Decode: Decodifica Base64
|
||||
Base64 Encode: Codifica Base64
|
||||
CSV: CSV
|
||||
CSV to JSON: CSV in JSON
|
||||
CSV to Markdown Table: CSV in Tabella Markdown
|
||||
Capitalize Case: Maiuscolo Iniziale
|
||||
Code Formatting: Formattazione Codice
|
||||
Count Characters: Conta Caratteri
|
||||
Count Lines: Conta Righe
|
||||
Count Sentences: Conta Frasi
|
||||
Count Words: Conta Parole
|
||||
Data Conversion: Conversione Dati
|
||||
Drag and drop category to prioritize its order in the special copy/paste menu.: Trascina e rilascia la categoria per dare priorità al suo ordine nel menu speciale di copia/incolla.
|
||||
Enable All: Abilita Tutto
|
||||
Enable special text transformation options for clipboard history items: Abilita opzioni speciali di trasformazione del testo per gli elementi della cronologia degli appunti
|
||||
Enabled Operations: Operazioni Abilitate
|
||||
Encode/Decode: Codifica/Decodifica
|
||||
Format Converter: Convertitore di Formato
|
||||
HTML: HTML
|
||||
HTML Decode: Decodifica HTML
|
||||
HTML Encode: Codifica HTML
|
||||
HTML to Markdown: HTML in Markdown
|
||||
HTML to Plain Text: HTML in Testo Semplice
|
||||
HTML to React Component: HTML in Componente React
|
||||
HTML to React JSX: HTML in React JSX
|
||||
HTML to Text: HTML in Testo
|
||||
JSON: JSON
|
||||
JSON Stringify: JSON Stringify
|
||||
JSON to CSV: JSON in CSV
|
||||
JSON to Markdown Table: JSON in Tabella Markdown
|
||||
JSON to TOML: JSON in TOML
|
||||
JSON to XML: JSON in XML
|
||||
JSON to YAML: JSON in YAML
|
||||
Markdown: Markdown
|
||||
Markdown to HTML: Markdown in HTML
|
||||
Markdown to Text: Markdown in Testo
|
||||
Operations: Operazioni
|
||||
PascalCase: PascalCase
|
||||
Prioritize Category Order: Priorità Ordine Categorie
|
||||
Remove Duplicate Lines: Rimuovi Righe Duplicate
|
||||
Remove Extra Spaces: Rimuovi Spazi Extra
|
||||
Remove Line Feeds: Rimuovi a Capo
|
||||
Reverse Text: Inverti Testo
|
||||
Select Operations: Seleziona Operazioni
|
||||
Sentence case: Maiuscolo a inizio frase
|
||||
Sort Lines Alphabetically: Ordina Righe Alfabeticamente
|
||||
Special Copy: Copia Speciale
|
||||
Special Copy/Paste Operations: Operazioni Speciali di Copia/Incolla
|
||||
Special Paste: Incolla Speciale
|
||||
Special Settings: Impostazioni Speciali
|
||||
TOML: TOML
|
||||
TOML to JSON: TOML in JSON
|
||||
Text Case: Maiuscole/Minuscole
|
||||
Text Tools: Strumenti Testo
|
||||
Title Case: Maiuscolo a Inizio Parola
|
||||
Trim White Space: Taglia Spazi Bianchi
|
||||
UPPER CASE: MAIUSCOLO
|
||||
URL Decode: Decodifica URL
|
||||
URL Encode: Codifica URL
|
||||
Whitespace & Lines: Spazi & Righe
|
||||
XML: XML
|
||||
XML to JSON: XML in JSON
|
||||
YAML: YAML
|
||||
YAML to JSON: YAML in JSON
|
||||
camelCase: camelCase
|
||||
iNVERT cASE: iNVERTI cASO
|
||||
kebab-case: kebab-case
|
||||
lower case: minuscolo
|
||||
snake_case: snake_case
|
@ -1,24 +0,0 @@
|
||||
Create New Template: Crea Nuovo Modello
|
||||
Create Template: Crea Modello
|
||||
Enter template content...: Inserisci il contenuto del modello...
|
||||
Enter template name (e.g., "signature", "email"): Inserisci il nome del modello (es. "firma", "email")
|
||||
Global: Globale
|
||||
Global Template: Modello Globale
|
||||
Global Templates: Modelli Globali
|
||||
Preview usage: Anteprima utilizzo
|
||||
Template Usage: Utilizzo del Modello
|
||||
Template name already exists: Il nome del modello esiste già. Scegli un nome diverso.
|
||||
Template name cannot be changed after creation. Delete and recreate to change name.: Il nome del modello non può essere modificato dopo la creazione. Elimina e ricrea per cambiare il nome.
|
||||
Use Global Template: Usa Modello Globale
|
||||
addTemplateButton: Aggiungi Modello
|
||||
confirmDeleteTemplateMessage: Sei sicuro di voler eliminare il modello globale '{{name}}'?
|
||||
confirmDeleteTemplateTitle: Conferma Eliminazione
|
||||
deleteTemplateButtonTooltip: Elimina Modello
|
||||
enableGlobalTemplatesLabel: Abilita Modelli Globali
|
||||
globalTemplatesDescription: Gestisci frammenti di testo riutilizzabili che possono essere inseriti in qualsiasi clip usando {{template_name}}.
|
||||
globalTemplatesTitle: Modelli Globali
|
||||
localTemplateConflictWarning: Esiste anche un modello globale chiamato '{{label}}'. Il modello locale avrà la precedenza nel modulo di questo clip.
|
||||
noGlobalTemplatesYet: Nessun modello globale definito ancora. Clicca su 'Aggiungi Modello' per crearne uno.
|
||||
templateEnabledLabel: Abilitato
|
||||
templateNameLabel: Nome
|
||||
templateValueLabel: Valore
|
@ -17,9 +17,3 @@ Show collection name on the navbar: Показывать название кол
|
||||
Switch collections: Переключить коллекции
|
||||
You can add the selected text to your clips or menu. Please select the option below.: Вы можете добавить выделенный текст в свои клипы или меню. Пожалуйста, выберите ниже.
|
||||
You need to select a different collection before deleting the current one.: Вам нужно выбрать другую коллекцию перед удалением текущей.
|
||||
Choose which collections require PIN entry for access.: Выберите, для каких коллекций требуется ввод PIN для доступа.
|
||||
Pin Protected Collections: Коллекции, защищенные PIN
|
||||
Protect Collections with PIN: Защитить коллекции с помощью PIN
|
||||
Protected Collection: Защищенная коллекция
|
||||
Select Collections: Выбрать коллекции
|
||||
Select protected collections: Выбрать защищенные коллекции
|
||||
|
@ -3,8 +3,6 @@
|
||||
About PasteBar: О PasteBar
|
||||
Action Menu: Контекстное меню
|
||||
Activation Error: Ошибка активации
|
||||
? Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
: Добавьте поле <b>{{Clipboard}}</b> в шаблон. Это позволит копировать текст в буфер обмена, и он будет вставлен в шаблон
|
||||
Add Clip: Добавить Клип
|
||||
Add First Option: Добавить первый вариант
|
||||
Add Link Card: Добавить карточку ссылки
|
||||
@ -18,6 +16,7 @@ Add to Clips or Menu: Добавить в Клипы или Меню
|
||||
Add to Menu: Добавить в Меню
|
||||
Add to clip or menu: Добавить в клипы или меню
|
||||
Add to template fields: Добавить в поля шаблона
|
||||
Add {{Clipboard}} field to template. This allows you to copy text to the clipboard, and it will be inserted into the template: Добавьте поле <b>{{Clipboard}}</b> в шаблон. Это позволит копировать текст в буфер обмена, и он будет вставлен в шаблон
|
||||
Added: Добавлено
|
||||
Adding this file to the player is not recommended unless you trust the source.: Добавление этого файла в плеер не рекомендуется, если вы не доверяете источнику.
|
||||
Allow PasteBar to Copy and Paste from Clipboard: Разрешить PasteBar копировать и вставлять из буфера обмена
|
||||
@ -31,7 +30,6 @@ Check: Проверить
|
||||
Check / Done: Проверить / Готово
|
||||
Check and Close: Проверить и закрыть
|
||||
Check and Done: Проверить и готово
|
||||
Clear History: Очистить историю
|
||||
Clear Tracks: Очистить треки
|
||||
Clear found results and filters: Очистить найденные результаты и фильтры
|
||||
Click to Confirm: Нажмите подтвердить
|
||||
@ -51,24 +49,19 @@ Confirm Delete: Подтвердить удаление
|
||||
Confirm Email: Подтвердить удаление
|
||||
Confirm Passcode: Подтвердите код
|
||||
Confirm Password: Подтвердите пароль
|
||||
Confirm Password Reset: Подтвердить сброс пароля
|
||||
Confirm Password Reset Action: Подтвердить действие сброса пароля
|
||||
Confirm Remove: Подтвердить удаление
|
||||
Confirm Your Passcode: Подтвердите ваш код доступа
|
||||
Confirm action: Подтвердить действие
|
||||
Confirm password reset: Подтвердить сброс пароля
|
||||
Confirm password reset action: Подтвердить действие сброса пароля
|
||||
Confirm your action: Подтвердите ваше действие
|
||||
Confirm {{action}}: Подтвердить {{action}}
|
||||
Confirm Add To Protected Collections: Подтвердить добавление в защищенные коллекции
|
||||
Confirm Disable PIN Protection: Подтвердить отключение защиты PIN
|
||||
Confirm Remove From Protected Collections: Подтвердить удаление из защищенных коллекций
|
||||
Confirm Enable PIN Protection: Подтвердить включение защиты PIN
|
||||
Contact Form: Форма связи
|
||||
Copied: Скопировано
|
||||
Copy: Копировать
|
||||
Copy & Paste: Копировать и вставить
|
||||
Copy and Paste: Копировать и вставить
|
||||
Copy of: Копия
|
||||
'Copy of ': 'Копия '
|
||||
Copy to Clipboard: Копировать в буфер обмена
|
||||
Create: Создать
|
||||
Created: Создано
|
||||
@ -99,22 +92,17 @@ Enabled: Включено
|
||||
Enter Current Passcode: Введите текущий код доступа
|
||||
Enter Digits Only Passcode: Введите код доступа, состоящий только из цифр
|
||||
Enter Email: Введите email
|
||||
Enter PIN to Access Protected Collection: Введите PIN для доступа к защищенной коллекции
|
||||
Enter Passcode: Введите код доступа
|
||||
Enter Password: Введите пароль
|
||||
Enter Recovery Password: Введите пароль восстановления
|
||||
Enter passcode or password to unlock: Введите код доступа или пароль для разблокировки
|
||||
Error: Ошибка
|
||||
Errors:
|
||||
Error loading link: Ошибка загрузки ссылки
|
||||
Cant save file: Невозможно сохранить файл
|
||||
Something went wrong! {{err}} Please try again.: Что-то пошло не так! {{err}} Пожалуйста, попробуйте еще раз.
|
||||
Expand Edit: Развернуть редактирование
|
||||
? Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
: Поле <b>{{Clipboard}}</b> найдено в шаблоне. Это позволяет копировать текст в буфер обмена, и он будет вставлен в шаблон
|
||||
Field is not found in the template: Поле не найдено в шаблоне
|
||||
? Field {{Clipboard}} has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
|
||||
: Поле <b>{{Clipboard}}</b> найдено в шаблоне. Это позволяет копировать текст в буфер обмена, и он будет вставлен в шаблон
|
||||
Field {{Clipboard}} has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template: Поле <b>{{Clipboard}}</b> найдено в шаблоне. Это позволяет копировать текст в буфер обмена, и он будет вставлен в шаблон
|
||||
Find Clip: Найти клип
|
||||
Find History: Найти в истории
|
||||
Found in template but missing from fields definition: Найдено в шаблоне, но отсутствует в определении полей
|
||||
@ -157,7 +145,6 @@ Number of lines: Количество строк
|
||||
Ok, but later: Хорошо, но позже
|
||||
Open: Открыть
|
||||
Open Accessibility: Открыть Специальные возможности
|
||||
Open History Window: Открыть окно с историей буфера
|
||||
Open Window: Открыть окно
|
||||
Open contact form in browser: Открыть форму связи в браузере
|
||||
Open payment in browser: Открыть платеж в браузере
|
||||
@ -175,8 +162,7 @@ Pasted: Вставлено
|
||||
Path: Путь
|
||||
Pause: Пауза
|
||||
Pause Playing: Пауза
|
||||
? 'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.'
|
||||
: 'Ошибка проверки: PasteBar не был успешно добавлен в настройки Специальных возможностей. Пожалуйста, предоставьте необходимые разрешения и нажмите «Готово» еще раз.'
|
||||
'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.': 'Ошибка проверки: PasteBar не был успешно добавлен в настройки Специальных возможностей. Пожалуйста, предоставьте необходимые разрешения и нажмите «Готово» еще раз.'
|
||||
Pin Selected: Закрепить выбранное
|
||||
Pinned: Закреплённый
|
||||
Pinned_few: Закреплённых
|
||||
@ -244,9 +230,9 @@ Set: Установить
|
||||
Set Password: Установить пароль
|
||||
Show Large View: Увеличенный вид
|
||||
Show all: Показать все
|
||||
Size: Размер
|
||||
Something goes wrong! Please try again.: Что-то пошло не так! Пожалуйста, попробуйте еще раз.
|
||||
Source: Источник
|
||||
Split History Window: Разделить окно с историей буфера
|
||||
Star: Избранное
|
||||
Star Selected: Добавить в избранное
|
||||
Stay here: Остаться
|
||||
@ -334,7 +320,6 @@ Unlock Pro features: Разблокировать функции Pro
|
||||
Unlock Screen: Разблокировать экран
|
||||
Unlock all features: Разблокировать все функции
|
||||
Unsaved label: Несохраненное название
|
||||
Update Error: Ошибка обновления
|
||||
Update history list: Обновить список истории
|
||||
Updated: Обновлено
|
||||
Upgrade to Pro: Перейти на Pro
|
||||
@ -350,8 +335,7 @@ View Edit: Редактирование в увеличенном виде
|
||||
Views:
|
||||
Paste Menu: Меню вставки
|
||||
We apologize but you found a bug. Please report this issue to us and try again: Приносим извинения, но вы обнаружили ошибку. Пожалуйста, сообщите нам об этой проблеме и повторите попытку
|
||||
? We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.
|
||||
: Мы не смогли подтвердить безопасность этого файла. Не удалось проверить ID3-теги и целостность файла. MP3-файлы могут потенциально содержать вредоносные код. Пожалуйста, будьте осторожны.
|
||||
We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.: Мы не смогли подтвердить безопасность этого файла. Не удалось проверить ID3-теги и целостность файла. MP3-файлы могут потенциально содержать вредоносные код. Пожалуйста, будьте осторожны.
|
||||
Yes: Да
|
||||
Yes, activate: Да, активировать
|
||||
chars: символов
|
||||
@ -366,3 +350,10 @@ second: секунда
|
||||
seconds: секунды
|
||||
show less: показать меньше
|
||||
www.site: www.pastebar.ru
|
||||
Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template: Добавьте поле <b>{{Clipboard}}</b> в шаблон. Это позволит копировать текст в буфер обмена, и он будет вставлен в шаблон
|
||||
Clear History: Очистить историю
|
||||
'Copy of ': 'Копия '
|
||||
Error: Ошибка
|
||||
Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template: Поле <b>{{Clipboard}}</b> найдено в шаблоне. Это позволяет копировать текст в буфер обмена, и он будет вставлен в шаблон
|
||||
Size: Размер
|
||||
Update Error: Ошибка обновления
|
||||
|
@ -1,4 +0,0 @@
|
||||
Please select your preferred language: Пожалуйста, выберите предпочитаемый язык
|
||||
Start using PasteBar: Начните использовать PasteBar
|
||||
Submenus will move up one level after delete: Подменю переместятся на уровень выше после удаления
|
||||
Welcome to PasteBar: Добро пожаловать в PasteBar
|
@ -21,7 +21,8 @@ Add Section: Добавить раздел
|
||||
Add Tab: Добавить вкладку
|
||||
Add Template Field: Добавить поле шаблона
|
||||
Add a Tab: Добавить вкладку
|
||||
Add field {{name}} into the template: Добавить поле {{name}} в шаблон
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Добавить поле <b>{{<b>{{name}}</b>}}</b> в шаблон
|
||||
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Добавить поле <b>{{<b>{{name}}</b>}}</b> в шаблон
|
||||
Add image: Добавить изображение
|
||||
Add note: Добавить заметку
|
||||
Add to Board: Добавить на доску
|
||||
@ -84,7 +85,7 @@ Delete field: Удалить поле
|
||||
Delete tab: Удалить вкладку
|
||||
Detect Template Fields: Обнаружить поля шаблона
|
||||
Detect for Template Fields: Обнаружить поля шаблона
|
||||
Disabled field {{name}} has been found in the template: Отключенное поле {{name}} найдено в шаблоне
|
||||
Disabled field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Отключенное поле <b>{{<b>{{name}}</b>}}</b> найдено в шаблоне
|
||||
Done Create Clip: Завершить
|
||||
Done Edit: Завершить
|
||||
Done Edit Tabs: Завершить
|
||||
@ -136,7 +137,7 @@ FILTERED_TYPES:
|
||||
RegEx Replace: Замена регулярного выражения
|
||||
Remove Quotes: Удалить кавычки
|
||||
Field: Поле
|
||||
Field {{name}} has been found in the template: Поле {{name}} найдено в шаблоне
|
||||
Field <b>{{<b>{{name}}</b>}}</b> has been found in the template: Поле <b>{{<b>{{name}}<b>{{<b> найдено в шаблоне
|
||||
Field Options: Параметры поля
|
||||
Fields Value: Значение полей
|
||||
File, folder or app path does not exist: Путь к файлу, папке или приложению не существует
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user