mirror of
https://github.com/immich-app/immich.git
synced 2025-04-15 03:11:28 -05:00
feat: qr code for new shared link (#16543)
This commit is contained in:
parent
6ef069b537
commit
ff19502035
5 changed files with 379 additions and 103 deletions
|
@ -394,6 +394,7 @@
|
|||
"allow_edits": "Allow edits",
|
||||
"allow_public_user_to_download": "Allow public user to download",
|
||||
"allow_public_user_to_upload": "Allow public user to upload",
|
||||
"alt_text_qr_code": "QR code image",
|
||||
"anti_clockwise": "Anti-clockwise",
|
||||
"api_key": "API Key",
|
||||
"api_key_description": "This value will only be shown once. Please be sure to copy it before closing the window.",
|
||||
|
@ -1356,6 +1357,7 @@
|
|||
"view_all": "View All",
|
||||
"view_all_users": "View all users",
|
||||
"view_in_timeline": "View in timeline",
|
||||
"view_link": "View link",
|
||||
"view_links": "View links",
|
||||
"view_name": "View",
|
||||
"view_next_asset": "View next asset",
|
||||
|
|
244
web/package-lock.json
generated
244
web/package-lock.json
generated
|
@ -27,6 +27,7 @@
|
|||
"justified-layout": "^4.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luxon": "^3.4.4",
|
||||
"qrcode": "^1.5.4",
|
||||
"socket.io-client": "~4.8.0",
|
||||
"svelte-gestures": "^5.1.3",
|
||||
"svelte-i18n": "^4.0.1",
|
||||
|
@ -50,6 +51,7 @@
|
|||
"@types/justified-layout": "^4.1.4",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
||||
"@typescript-eslint/parser": "^8.20.0",
|
||||
"@vitest/coverage-v8": "^3.0.0",
|
||||
|
@ -2526,9 +2528,7 @@
|
|||
"version": "20.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz",
|
||||
"integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/normalize-package-data": {
|
||||
"version": "2.4.4",
|
||||
|
@ -2542,6 +2542,16 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz",
|
||||
"integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA=="
|
||||
},
|
||||
"node_modules/@types/qrcode": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz",
|
||||
"integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/supercluster": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz",
|
||||
|
@ -3366,6 +3376,15 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase-css": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
|
||||
|
@ -3824,6 +3843,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/decimal.js": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
|
||||
|
@ -3920,6 +3948,12 @@
|
|||
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
|
||||
},
|
||||
"node_modules/dijkstrajs": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
|
||||
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/dlv": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
||||
|
@ -5165,7 +5199,6 @@
|
|||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
|
@ -6677,6 +6710,15 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/package-json-from-dist": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
|
||||
|
@ -6728,7 +6770,6 @@
|
|||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
@ -6851,6 +6892,15 @@
|
|||
"fflate": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pngjs": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
|
||||
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.3",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
||||
|
@ -7166,6 +7216,174 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
|
||||
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dijkstrajs": "^1.0.1",
|
||||
"pngjs": "^5.0.0",
|
||||
"yargs": "^15.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"qrcode": "bin/qrcode"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/qrcode/node_modules/find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-locate": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-try": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-limit": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/y18n": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/qrcode/node_modules/yargs": {
|
||||
"version": "15.4.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cliui": "^6.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^4.1.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^4.2.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^18.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode/node_modules/yargs-parser": {
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
|
@ -7332,11 +7550,16 @@
|
|||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
|
@ -7625,8 +7848,7 @@
|
|||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/set-cookie-parser": {
|
||||
"version": "2.6.0",
|
||||
|
@ -9664,6 +9886,12 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/which-module": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
|
||||
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/why-is-node-running": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"@types/justified-layout": "^4.1.4",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
||||
"@typescript-eslint/parser": "^8.20.0",
|
||||
"@vitest/coverage-v8": "^3.0.0",
|
||||
|
@ -83,6 +84,7 @@
|
|||
"justified-layout": "^4.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luxon": "^3.4.4",
|
||||
"qrcode": "^1.5.4",
|
||||
"socket.io-client": "~4.8.0",
|
||||
"svelte-gestures": "^5.1.3",
|
||||
"svelte-i18n": "^4.0.1",
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import { NotificationType, notificationController } from '../notification/notification';
|
||||
import SettingInputField from '../settings/setting-input-field.svelte';
|
||||
import SettingSwitch from '../settings/setting-switch.svelte';
|
||||
import QRCode from '$lib/components/shared-components/qrcode.svelte';
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
@ -41,6 +42,7 @@
|
|||
let password = $state('');
|
||||
let shouldChangeExpirationTime = $state(false);
|
||||
let enablePassword = $state(false);
|
||||
let modalWidth = $state(0);
|
||||
|
||||
const expirationOptions: [number, Intl.RelativeTimeFormatUnit][] = [
|
||||
[30, 'minutes'],
|
||||
|
@ -143,6 +145,9 @@
|
|||
};
|
||||
|
||||
const getTitle = () => {
|
||||
if (sharedLink) {
|
||||
return $t('view_link');
|
||||
}
|
||||
if (editingLink) {
|
||||
return $t('edit_link');
|
||||
}
|
||||
|
@ -150,110 +155,121 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<FullScreenModal title={getTitle()} icon={mdiLink} {onClose}>
|
||||
<section>
|
||||
{#if shareType === SharedLinkType.Album}
|
||||
{#if !editingLink}
|
||||
<div>{$t('album_with_link_access')}</div>
|
||||
{:else}
|
||||
<div class="text-sm">
|
||||
{$t('public_album')} |
|
||||
<span class="text-immich-primary dark:text-immich-dark-primary">{editingLink.album?.albumName}</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if shareType === SharedLinkType.Individual}
|
||||
{#if !editingLink}
|
||||
<div>{$t('create_link_to_share_description')}</div>
|
||||
{:else}
|
||||
<div class="text-sm">
|
||||
{$t('individual_share')} |
|
||||
<span class="text-immich-primary dark:text-immich-dark-primary">{editingLink.description || ''}</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<div class="mb-2 mt-4">
|
||||
<p class="text-xs">{$t('link_options').toUpperCase()}</p>
|
||||
</div>
|
||||
<div class="rounded-lg bg-gray-100 p-4 dark:bg-black/40 overflow-y-auto">
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-2">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.TEXT}
|
||||
label={$t('description')}
|
||||
bind:value={description}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.TEXT}
|
||||
label={$t('password')}
|
||||
bind:value={password}
|
||||
disabled={!enablePassword}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={enablePassword} title={$t('require_password')} />
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={showMetadata} title={$t('show_metadata')} />
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch
|
||||
bind:checked={allowDownload}
|
||||
title={$t('allow_public_user_to_download')}
|
||||
disabled={!showMetadata}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={allowUpload} title={$t('allow_public_user_to_upload')} />
|
||||
</div>
|
||||
|
||||
{#if editingLink}
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={shouldChangeExpirationTime} title={$t('change_expiration_time')} />
|
||||
{#if !sharedLink || editingLink}
|
||||
<FullScreenModal title={getTitle()} icon={mdiLink} {onClose}>
|
||||
<section>
|
||||
{#if shareType === SharedLinkType.Album}
|
||||
{#if !editingLink}
|
||||
<div>{$t('album_with_link_access')}</div>
|
||||
{:else}
|
||||
<div class="text-sm">
|
||||
{$t('public_album')} |
|
||||
<span class="text-immich-primary dark:text-immich-dark-primary">{editingLink.album?.albumName}</span>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="mt-3">
|
||||
<SettingSelect
|
||||
bind:value={expirationOption}
|
||||
options={expiredDateOptions}
|
||||
label={$t('expire_after')}
|
||||
disabled={editingLink && !shouldChangeExpirationTime}
|
||||
number={true}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if shareType === SharedLinkType.Individual}
|
||||
{#if !editingLink}
|
||||
<div>{$t('create_link_to_share_description')}</div>
|
||||
{:else}
|
||||
<div class="text-sm">
|
||||
{$t('individual_share')} |
|
||||
<span class="text-immich-primary dark:text-immich-dark-primary">{editingLink.description || ''}</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<div class="mb-2 mt-4">
|
||||
<p class="text-xs">{$t('link_options').toUpperCase()}</p>
|
||||
</div>
|
||||
<div class="rounded-lg bg-gray-100 p-4 dark:bg-black/40 overflow-y-auto">
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-2">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.TEXT}
|
||||
label={$t('description')}
|
||||
bind:value={description}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.TEXT}
|
||||
label={$t('password')}
|
||||
bind:value={password}
|
||||
disabled={!enablePassword}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={enablePassword} title={$t('require_password')} />
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={showMetadata} title={$t('show_metadata')} />
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch
|
||||
bind:checked={allowDownload}
|
||||
title={$t('allow_public_user_to_download')}
|
||||
disabled={!showMetadata}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={allowUpload} title={$t('allow_public_user_to_upload')} />
|
||||
</div>
|
||||
|
||||
{#if editingLink}
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={shouldChangeExpirationTime} title={$t('change_expiration_time')} />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="mt-3">
|
||||
<SettingSelect
|
||||
bind:value={expirationOption}
|
||||
options={expiredDateOptions}
|
||||
label={$t('expire_after')}
|
||||
disabled={editingLink && !shouldChangeExpirationTime}
|
||||
number={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
{#snippet stickyBottom()}
|
||||
{#if !sharedLink}
|
||||
{#snippet stickyBottom()}
|
||||
{#if editingLink}
|
||||
<Button size="sm" fullwidth onclick={handleEditLink}>{$t('confirm')}</Button>
|
||||
{:else}
|
||||
<Button size="sm" fullwidth onclick={handleCreateSharedLink}>{$t('create_link')}</Button>
|
||||
{/if}
|
||||
{:else}
|
||||
<HStack class="w-full">
|
||||
{/snippet}
|
||||
</FullScreenModal>
|
||||
{:else}
|
||||
<FullScreenModal title={getTitle()} icon={mdiLink} {onClose}>
|
||||
<div class="w-full">
|
||||
<div class="w-full py-2 px-10">
|
||||
<div bind:clientWidth={modalWidth} class="w-full">
|
||||
<QRCode value={sharedLink} width={modalWidth} />
|
||||
</div>
|
||||
</div>
|
||||
<HStack class="w-full p-3">
|
||||
<Input bind:value={sharedLink} disabled class="flex flex-row" />
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
shape="round"
|
||||
color="secondary"
|
||||
size="giant"
|
||||
icon={mdiContentCopy}
|
||||
onclick={() => (sharedLink ? copyToClipboard(sharedLink) : '')}
|
||||
aria-label={$t('copy_link_to_clipboard')}
|
||||
/>
|
||||
<div>
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
shape="round"
|
||||
color="secondary"
|
||||
size="large"
|
||||
icon={mdiContentCopy}
|
||||
onclick={() => (sharedLink ? copyToClipboard(sharedLink) : '')}
|
||||
aria-label={$t('copy_link_to_clipboard')}
|
||||
/>
|
||||
</div>
|
||||
</HStack>
|
||||
{/if}
|
||||
{/snippet}
|
||||
</FullScreenModal>
|
||||
</div>
|
||||
</FullScreenModal>
|
||||
{/if}
|
||||
|
|
28
web/src/lib/components/shared-components/qrcode.svelte
Normal file
28
web/src/lib/components/shared-components/qrcode.svelte
Normal file
|
@ -0,0 +1,28 @@
|
|||
<script lang="ts">
|
||||
import QRCode from 'qrcode';
|
||||
import { colorTheme } from '$lib/stores/preferences.store';
|
||||
import { Theme } from '$lib/constants';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
type Props = {
|
||||
value: string;
|
||||
width: number;
|
||||
alt?: string;
|
||||
};
|
||||
|
||||
const { value, width, alt = $t('alt_text_qr_code') }: Props = $props();
|
||||
|
||||
let promise = $derived(
|
||||
QRCode.toDataURL(value, {
|
||||
color: { dark: $colorTheme.value === Theme.DARK ? '#ffffffff' : '#000000ff', light: '#00000000' },
|
||||
margin: 0,
|
||||
width,
|
||||
}),
|
||||
);
|
||||
</script>
|
||||
|
||||
<div style="width: {width}px; height: {width}px">
|
||||
{#await promise then url}
|
||||
<img src={url} {alt} class="h-full w-full" />
|
||||
{/await}
|
||||
</div>
|
Loading…
Add table
Reference in a new issue