diff --git a/package.json b/package.json index 24b43b8..a8c68f9 100644 --- a/package.json +++ b/package.json @@ -16,11 +16,13 @@ "build": "vite build", "dev": "vite build --mode development --watch", "serve": "vite --mode development --host 127.0.0.1", + "check": "pnpm run format && pnpm run lint && pnpm run typecheck", "lint": "biome lint src styles", "lint:fix": "biome lint --write src styles", "format": "biome format .", "format:fix": "biome format --write .", - "typecheck": "vue-tsc --noEmit" + "typecheck": "vue-tsc --noEmit", + "prepare": "simple-git-hooks" }, "dependencies": { "@betahuhn/feedback-js": "^2.1.25", @@ -43,11 +45,15 @@ "@nextcloud/vite-config": "^2.5.2", "@types/node": "^24.5.2", "browserslist": "^4.26.2", + "simple-git-hooks": "^2.13.1", "typescript": "^5.9.3", "vite": "^7.3.1", "vue-tsc": "^3.0.8" }, "browserslist": [ "extends @nextcloud/browserslist-config" - ] + ], + "simple-git-hooks": { + "pre-commit": "pnpm run check" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0bb0f3c..295b2d4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,6 +63,9 @@ importers: browserslist: specifier: ^4.26.2 version: 4.28.1 + simple-git-hooks: + specifier: ^2.13.1 + version: 2.13.1 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -2261,6 +2264,10 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + simple-git-hooks@2.13.1: + resolution: {integrity: sha512-WszCLXwT4h2k1ufIXAgsbiTOazqqevFCIncOuUBZJ91DdvWcC5+OFkluWRQPrcuSYd8fjq+o2y1QfWqYMoAToQ==} + hasBin: true + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -5042,6 +5049,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + simple-git-hooks@2.13.1: {} + source-map-js@1.2.1: {} source-map@0.6.1: {} diff --git a/src/app/files/actions/archive.ts b/src/app/files/actions/archive.ts index b5e912f..82ba6d5 100644 --- a/src/app/files/actions/archive.ts +++ b/src/app/files/actions/archive.ts @@ -36,6 +36,9 @@ registerFileActionCompat({ "Restore", UnarchiveSvg, ); + if (!path) { + return; + } const destination = FilesHelper.getPathParts(path) .slice(1) .join("/"); diff --git a/src/app/files/actions/export.ts b/src/app/files/actions/export.ts index ff1254f..dbcd096 100644 --- a/src/app/files/actions/export.ts +++ b/src/app/files/actions/export.ts @@ -38,7 +38,12 @@ registerFileActionCompat({ callback: async () => downloadMetadata(node), }) .build() - .show(); + .show() + .catch((error) => { + if (!FilesHelper.isDialogCancelError(error)) { + throw error; + } + }); }, }); diff --git a/src/app/files/actions/move.ts b/src/app/files/actions/move.ts index 16f5399..ece68c8 100644 --- a/src/app/files/actions/move.ts +++ b/src/app/files/actions/move.ts @@ -23,6 +23,9 @@ registerFileActionCompat({ async exec({ nodes }) { const node = nodes[0]; const path = await FilesHelper.locationPicker(node, "Move", MoveSvg); + if (!path) { + return; + } const destination = FilesHelper.getPathParts(path).slice(1).join("/"); await axios({ method: "post", diff --git a/src/app/files/actions/reference.ts b/src/app/files/actions/reference.ts index 441f9c6..85560fd 100644 --- a/src/app/files/actions/reference.ts +++ b/src/app/files/actions/reference.ts @@ -83,9 +83,49 @@ registerFileActionCompat({ variant: "secondary", icon: SvgHelper.convert(OpenSvg), callback: () => { - window.open(gatewayUrl, "_blank", "noopener,noreferrer"); + void new Dialog( + t( + "files_external_ethswarm", + "Access on Swarm Gateway?", + ), + t( + "files_external_ethswarm", + "You are about to access this file through gateway.ethswarm.org, a public Swarm gateway used to access Swarm content. Please note this opens an external link and can leave network and server access traces to your swarm reference.", + ), + [ + { + label: t("files_external_ethswarm", "Cancel"), + variant: "secondary", + callback: () => null, + }, + { + label: t("files_external_ethswarm", "Proceed"), + variant: "primary", + icon: SvgHelper.convert(OpenSvg), + callback: () => { + window.open( + gatewayUrl, + "_blank", + "noopener,noreferrer", + ); + }, + }, + ], + ) + .show() + .catch((error) => { + if (!FilesHelper.isDialogCancelError(error)) { + throw error; + } + }); }, }, - ]).show(); + ]) + .show() + .catch((error) => { + if (!FilesHelper.isDialogCancelError(error)) { + throw error; + } + }); }, }); diff --git a/src/util/FilesHelper.ts b/src/util/FilesHelper.ts index f140466..4a8dbcb 100644 --- a/src/util/FilesHelper.ts +++ b/src/util/FilesHelper.ts @@ -6,6 +6,7 @@ import SvgHelper from "@/util/SvgHelper"; const FilesHelper = { isSwarmNode: (nodes) => getMainNode(nodes).attributes["ethswarm-node"] !== undefined, + isDialogCancelError: (error) => isDialogCancelError(error), getSwarmRef: (nodes) => getSwarmRef(nodes), hasSwarmRef: (nodes) => getSwarmRef(nodes) !== undefined, canUnshareOnly: (nodes) => { @@ -93,7 +94,13 @@ const FilesHelper = { ), ) .build() - .pick(), + .pick() + .catch((error) => { + if (isDialogCancelError(error)) { + return null; + } + throw error; + }), downloadFile: (blob, filename) => { const url = URL.createObjectURL(blob); const a = document.createElement("a"); @@ -140,4 +147,26 @@ function isArchive(nodes) { return getPathParts(nodes)[1] === "Archive - HejBit"; } +function isDialogCancelError(error) { + if (error === null || typeof error === "undefined") { + return true; + } + + if (typeof error === "string") { + return /cancel|abort|dismiss|closed|no nodes selected/i.test(error); + } + + if (typeof error === "object") { + const message = "message" in error ? String(error.message ?? "") : ""; + const name = "name" in error ? String(error.name ?? "") : ""; + + return ( + /abort|cancel|dismiss|closed/i.test(name) || + /cancel|abort|dismiss|closed|no nodes selected/i.test(message) + ); + } + + return false; +} + export default FilesHelper; diff --git a/vendor-bin/sentry/composer.lock b/vendor-bin/sentry/composer.lock index bd5cc45..db07554 100644 --- a/vendor-bin/sentry/composer.lock +++ b/vendor-bin/sentry/composer.lock @@ -387,16 +387,16 @@ }, { "name": "sentry/sentry", - "version": "4.21.0", + "version": "4.22.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "2bf405fc4d38f00073a7d023cf321e59f614d54c" + "reference": "ce6ab95a7021f976a27b4628a4072e481c8acf60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/2bf405fc4d38f00073a7d023cf321e59f614d54c", - "reference": "2bf405fc4d38f00073a7d023cf321e59f614d54c", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/ce6ab95a7021f976a27b4628a4072e481c8acf60", + "reference": "ce6ab95a7021f976a27b4628a4072e481c8acf60", "shasum": "" }, "require": { @@ -462,7 +462,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.21.0" + "source": "https://github.com/getsentry/sentry-php/tree/4.22.0" }, "funding": [ { @@ -474,7 +474,7 @@ "type": "custom" } ], - "time": "2026-02-24T15:32:51+00:00" + "time": "2026-03-16T13:03:46+00:00" }, { "name": "symfony/deprecation-contracts",