diff --git a/frontend/.prettierignore b/frontend/.prettierignore index 780b4555..be77aa74 100644 --- a/frontend/.prettierignore +++ b/frontend/.prettierignore @@ -1,2 +1,3 @@ # Ignore artifacts: -dist \ No newline at end of file +dist +pnpm-lock.yaml \ No newline at end of file diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index 07b4acc8..0ee268b3 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -19,14 +19,13 @@ export default [ { rules: { - "no-var": "warn", - "prefer-const": "warn", // Note: you must disable the base rule as it can report incorrect errors "no-unused-expressions": "off", - "@typescript-eslint/no-unused-expressions": "warn", - "@typescript-eslint/no-explicit-any": "warn", - "@typescript-eslint/ban-ts-comment": "warn", - "vue/block-lang": "warn", + "@typescript-eslint/no-unused-expressions": "off", + // TODO: theres too many of these from before ts + "@typescript-eslint/no-explicit-any": "off", + // TODO: finish the ts conversion + "vue/block-lang": "off", "vue/multi-word-component-names": "off", "vue/no-mutating-props": [ "error", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 895fbdf6..6f3378d3 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -4,9 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - typescript: ~5.6.3 - importers: .: @@ -1174,14 +1171,14 @@ packages: peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: ~5.6.3 + typescript: '>=4.8.4 <5.8.0' '@typescript-eslint/parser@8.21.0': resolution: {integrity: sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ~5.6.3 + typescript: '>=4.8.4 <5.8.0' '@typescript-eslint/scope-manager@8.21.0': resolution: {integrity: sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==} @@ -1192,7 +1189,7 @@ packages: engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ~5.6.3 + typescript: '>=4.8.4 <5.8.0' '@typescript-eslint/types@8.21.0': resolution: {integrity: sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==} @@ -1202,14 +1199,14 @@ packages: resolution: {integrity: sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ~5.6.3 + typescript: '>=4.8.4 <5.8.0' '@typescript-eslint/utils@8.21.0': resolution: {integrity: sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ~5.6.3 + typescript: '>=4.8.4 <5.8.0' '@typescript-eslint/visitor-keys@8.21.0': resolution: {integrity: sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==} @@ -1281,7 +1278,7 @@ packages: peerDependencies: eslint: ^9.10.0 eslint-plugin-vue: ^9.28.0 - typescript: ~5.6.3 + typescript: '>=4.8.4' peerDependenciesMeta: typescript: optional: true @@ -1289,7 +1286,7 @@ packages: '@vue/language-core@2.2.0': resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} peerDependencies: - typescript: ~5.6.3 + typescript: '*' peerDependenciesMeta: typescript: optional: true @@ -1314,7 +1311,7 @@ packages: '@vue/tsconfig@0.7.0': resolution: {integrity: sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==} peerDependencies: - typescript: ~5.6.3 + typescript: 5.x vue: ^3.4.0 peerDependenciesMeta: typescript: @@ -2175,7 +2172,7 @@ packages: pinia@2.3.1: resolution: {integrity: sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==} peerDependencies: - typescript: ~5.6.3 + typescript: '>=4.4.4' vue: ^2.7.0 || ^3.5.11 peerDependenciesMeta: typescript: @@ -2438,7 +2435,7 @@ packages: resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} engines: {node: '>=18.12'} peerDependencies: - typescript: ~5.6.3 + typescript: '>=4.8.4' tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -2463,7 +2460,7 @@ packages: engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ~5.6.3 + typescript: '>=4.8.4 <5.8.0' typescript@5.6.3: resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} @@ -2643,12 +2640,12 @@ packages: resolution: {integrity: sha512-gtmM1sUuJ8aSb0KoAFmK9yMxb8TxjewmxqTJ1aKphD5Cbu0rULFY6+UQT51zW7SpUcenfPUuflKyVwyx9Qdnxg==} hasBin: true peerDependencies: - typescript: ~5.6.3 + typescript: '>=5.0.0' vue@3.5.13: resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} peerDependencies: - typescript: ~5.6.3 + typescript: '*' peerDependenciesMeta: typescript: optional: true diff --git a/frontend/src/api/users.ts b/frontend/src/api/users.ts index a44254fb..78096b49 100644 --- a/frontend/src/api/users.ts +++ b/frontend/src/api/users.ts @@ -25,7 +25,7 @@ export async function create(user: IUser) { throw new StatusError(await res.text(), res.status); } -export async function update(user: IUser, which = ["all"]) { +export async function update(user: Partial, which = ["all"]) { await fetchURL(`/api/users/${user.id}`, { method: "PUT", body: JSON.stringify({ diff --git a/frontend/src/components/Breadcrumbs.vue b/frontend/src/components/Breadcrumbs.vue index 6da88053..b6d1a768 100644 --- a/frontend/src/components/Breadcrumbs.vue +++ b/frontend/src/components/Breadcrumbs.vue @@ -34,7 +34,7 @@ const props = defineProps<{ const items = computed(() => { const relativePath = route.path.replace(props.base, ""); - let parts = relativePath.split("/"); + const parts = relativePath.split("/"); if (parts[0] === "") { parts.shift(); @@ -44,7 +44,7 @@ const items = computed(() => { parts.pop(); } - let breadcrumbs: BreadCrumb[] = []; + const breadcrumbs: BreadCrumb[] = []; for (let i = 0; i < parts.length; i++) { if (i === 0) { diff --git a/frontend/src/components/ProgressBar.vue b/frontend/src/components/ProgressBar.vue index a31192b3..2cb9474b 100644 --- a/frontend/src/components/ProgressBar.vue +++ b/frontend/src/components/ProgressBar.vue @@ -46,7 +46,7 @@ https://raw.githubusercontent.com/dzwillia/vue-simple-progress/master/src/compon diff --git a/frontend/src/css/fonts.css b/frontend/src/css/fonts.css index c32e1e01..2e65cff6 100644 --- a/frontend/src/css/fonts.css +++ b/frontend/src/css/fonts.css @@ -63,8 +63,8 @@ local("Roboto"), local("Roboto-Regular"), url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2"); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, - U+A720-A7FF; + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, + U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -142,8 +142,8 @@ local("Roboto Medium"), local("Roboto-Medium"), url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2"); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, - U+A720-A7FF; + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, + U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -221,8 +221,8 @@ local("Roboto Bold"), local("Roboto-Bold"), url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2"); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, - U+A720-A7FF; + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, + U+2C60-2C7F, U+A720-A7FF; } @font-face { diff --git a/frontend/src/i18n/index.ts b/frontend/src/i18n/index.ts index a16a0a6a..f0b0304b 100644 --- a/frontend/src/i18n/index.ts +++ b/frontend/src/i18n/index.ts @@ -142,7 +142,7 @@ export const i18n = createI18n({ export const isRtl = (locale?: string) => { // see below - // @ts-ignore + // @ts-expect-error incorrect type when legacy return rtlLanguages.includes(locale || i18n.global.locale.value); }; @@ -150,7 +150,7 @@ export function setLocale(locale: string) { dayjs.locale(locale); // according to doc u only need .value if legacy: false but they lied // https://vue-i18n.intlify.dev/guide/essentials/scope.html#local-scope-1 - //@ts-ignore + // @ts-expect-error incorrect type when legacy i18n.global.locale.value = locale; } diff --git a/frontend/src/utils/auth.ts b/frontend/src/utils/auth.ts index a83719ce..b868d90f 100644 --- a/frontend/src/utils/auth.ts +++ b/frontend/src/utils/auth.ts @@ -24,7 +24,7 @@ export async function validateLogin() { await renew(localStorage.getItem("jwt")); } } catch (error) { - console.warn("Invalid JWT token in storage"); // eslint-disable-line + console.warn("Invalid JWT token in storage"); throw error; } } diff --git a/frontend/src/utils/buttons.ts b/frontend/src/utils/buttons.ts index 6a8ac249..30ed74f2 100644 --- a/frontend/src/utils/buttons.ts +++ b/frontend/src/utils/buttons.ts @@ -4,7 +4,7 @@ function loading(button: string) { ); if (el === undefined || el === null) { - console.log("Error getting button " + button); // eslint-disable-line + console.log("Error getting button " + button); return; } @@ -30,7 +30,7 @@ function done(button: string) { ); if (el === undefined || el === null) { - console.log("Error getting button " + button); // eslint-disable-line + console.log("Error getting button " + button); return; } @@ -51,7 +51,7 @@ function success(button: string) { ); if (el === undefined || el === null) { - console.log("Error getting button " + button); // eslint-disable-line + console.log("Error getting button " + button); return; } diff --git a/frontend/src/utils/clipboard.ts b/frontend/src/utils/clipboard.ts index 136f1ad4..23bb7895 100644 --- a/frontend/src/utils/clipboard.ts +++ b/frontend/src/utils/clipboard.ts @@ -1,39 +1,36 @@ // Based on code by the following links: // https://stackoverflow.com/a/74528564 // https://web.dev/articles/async-clipboard -export function copy(text: string) { + +interface ClipboardArgs { + text?: string; + data?: ClipboardItems; +} + +interface ClipboardOpts { + permission?: boolean; +} + +export function copy(data: ClipboardArgs, opts?: ClipboardOpts) { return new Promise((resolve, reject) => { if ( // Clipboard API requires secure context window.isSecureContext && - typeof navigator.clipboard !== "undefined" && - // @ts-ignore - navigator.permissions !== "undefined" + typeof navigator.clipboard !== "undefined" ) { - navigator.permissions - // @ts-ignore - .query({ name: "clipboard-write" }) - .then((permission) => { - if (permission.state === "granted" || permission.state === "prompt") { - // simple writeText should work for all modern browsers - navigator.clipboard.writeText(text).then(resolve).catch(reject); - } else { - reject(new Error("Permission not granted!")); - } - }) - .catch((e) => { - // Firefox doesn't support clipboard-write permission - if (navigator.userAgent.indexOf("Firefox") != -1) { - navigator.clipboard.writeText(text).then(resolve).catch(reject); - } else { - reject(e); - } - }); + if (opts?.permission) { + getPermission("clipboard-write") + .then(() => writeToClipboard(data).then(resolve).catch(reject)) + .catch(reject); + } else { + writeToClipboard(data).then(resolve).catch(reject); + } } else if ( document.queryCommandSupported && - document.queryCommandSupported("copy") + document.queryCommandSupported("copy") && + data.text // old method only supports text ) { - const textarea = createTemporaryTextarea(text); + const textarea = createTemporaryTextarea(data.text); const body = document.activeElement || document.body; try { body.appendChild(textarea); @@ -54,6 +51,35 @@ export function copy(text: string) { }); } +function getPermission(name: string) { + return new Promise((resolve, reject) => { + typeof navigator.permissions !== "undefined" && + navigator.permissions + // @ts-expect-error chrome specific api + .query({ name }) + .then((permission) => { + if (permission.state === "granted" || permission.state === "prompt") { + resolve(); + } else { + reject(new Error("Permission denied!")); + } + }); + }); +} + +function writeToClipboard(data: ClipboardArgs) { + if (data.text) { + return navigator.clipboard.writeText(data.text); + } + if (data.data) { + return navigator.clipboard.write(data.data); + } + + return new Promise((resolve, reject) => { + reject(new Error("No data was supplied!")); + }); +} + const styles = { fontSize: "12pt", position: "fixed", @@ -69,10 +95,10 @@ const styles = { background: "transparent", }; -const createTemporaryTextarea = (text: string) => { +function createTemporaryTextarea(text: string) { const textarea = document.createElement("textarea"); textarea.value = text; textarea.setAttribute("readonly", ""); Object.assign(textarea.style, styles); return textarea; -}; +} diff --git a/frontend/src/utils/css.ts b/frontend/src/utils/css.ts index d727786b..aca6c62a 100644 --- a/frontend/src/utils/css.ts +++ b/frontend/src/utils/css.ts @@ -6,13 +6,16 @@ export default function getRule(rules: string[]) { let result = null; const find = Array.prototype.find; - find.call(document.styleSheets, (styleSheet) => { - result = find.call(styleSheet.cssRules, (cssRule) => { + find.call(document.styleSheets, (styleSheet: CSSStyleSheet) => { + result = find.call(styleSheet.cssRules, (cssRule: CSSRule) => { let found = false; - if (cssRule instanceof window.CSSStyleRule) { + // faster than checking instanceof for every element + if (cssRule.constructor.name === "CSSStyleRule") { for (let i = 0; i < rules.length; i++) { - if (cssRule.selectorText.toLowerCase() === rules[i]) { + if ( + (cssRule as CSSStyleRule).selectorText.toLowerCase() === rules[i] + ) { found = true; } } @@ -24,5 +27,5 @@ export default function getRule(rules: string[]) { return result != null; }); - return result; + return result as CSSStyleRule | null; } diff --git a/frontend/src/views/Share.vue b/frontend/src/views/Share.vue index 53f0cfb1..40b940b5 100644 --- a/frontend/src/views/Share.vue +++ b/frontend/src/views/Share.vue @@ -325,6 +325,7 @@ const token = ref(""); const audio = ref(); const tag = ref(false); +const $showError = inject("$showError")!; const $showSuccess = inject("$showSuccess")!; const { t } = useI18n({}); @@ -463,9 +464,9 @@ const download = () => { if (req.value === null) return false; layoutStore.closeHovers(); - let files: string[] = []; + const files: string[] = []; - for (let i of fileStore.selected) { + for (const i of fileStore.selected) { files.push(req.value.items[i].path); } @@ -488,13 +489,23 @@ const linkSelected = () => { }; const copyToClipboard = (text: string) => { - copy(text).then( + copy({ text }).then( () => { // clipboard successfully set $showSuccess(t("success.linkCopied")); }, () => { // clipboard write failed + copy({ text }, { permission: true }).then( + () => { + // clipboard successfully set + $showSuccess(t("success.linkCopied")); + }, + (e) => { + // clipboard write failed + $showError(e); + } + ); } ); }; diff --git a/frontend/src/views/files/Editor.vue b/frontend/src/views/files/Editor.vue index 7e4d7a9b..9e9b6b68 100644 --- a/frontend/src/views/files/Editor.vue +++ b/frontend/src/views/files/Editor.vue @@ -108,7 +108,7 @@ onMounted(() => { showPrintMargin: false, readOnly: fileStore.req?.type === "textImmutable", theme: "ace/theme/chrome", - mode: modelist.getModeForPath(fileStore.req?.name).mode, + mode: modelist.getModeForPath(fileStore.req!.name).mode, wrap: true, enableBasicAutocompletion: true, enableLiveAutocompletion: true, @@ -173,7 +173,7 @@ const close = () => { fileStore.updateRequest(null); - let uri = url.removeLastDir(route.path) + "/"; + const uri = url.removeLastDir(route.path) + "/"; router.push({ path: uri }); }; diff --git a/frontend/src/views/files/FileListing.vue b/frontend/src/views/files/FileListing.vue index ec75aec5..8fa48f72 100644 --- a/frontend/src/views/files/FileListing.vue +++ b/frontend/src/views/files/FileListing.vue @@ -523,12 +523,12 @@ const keyEvent = (event: KeyboardEvent) => { break; case "a": event.preventDefault(); - for (let file of items.value.files) { + for (const file of items.value.files) { if (fileStore.selected.indexOf(file.index) === -1) { fileStore.selected.push(file.index); } } - for (let dir of items.value.dirs) { + for (const dir of items.value.dirs) { if (fileStore.selected.indexOf(dir.index) === -1) { fileStore.selected.push(dir.index); } @@ -551,9 +551,9 @@ const copyCut = (event: Event | KeyboardEvent): void => { if (fileStore.req === null) return; - let items = []; + const items = []; - for (let i of fileStore.selected) { + for (const i of fileStore.selected) { items.push({ from: fileStore.req.items[i].url, name: fileStore.req.items[i].name, @@ -575,9 +575,9 @@ const paste = (event: Event) => { if ((event.target as HTMLElement).tagName?.toLowerCase() === "input") return; // TODO router location should it be - let items: any[] = []; + const items: any[] = []; - for (let item of clipboardStore.items) { + for (const item of clipboardStore.items) { const from = item.from.endsWith("/") ? item.from.slice(0, -1) : item.from; const to = route.path + encodeURIComponent(item.name); items.push({ from, to, name: item.name }); @@ -614,7 +614,7 @@ const paste = (event: Event) => { return; } - let conflict = upload.checkConflict(items, fileStore.req!.items); + const conflict = upload.checkConflict(items, fileStore.req!.items); let overwrite = false; let rename = false; @@ -640,14 +640,13 @@ const paste = (event: Event) => { const colunmsResize = () => { // Update the columns size based on the window width. - let items_ = css(["#listing.mosaic .item", ".mosaic#listing .item"]); + const items_ = css(["#listing.mosaic .item", ".mosaic#listing .item"]); if (items_ === null) return; let columns = Math.floor( (document.querySelector("main")?.offsetWidth ?? 0) / columnWidth.value ); if (columns === 0) columns = 1; - // @ts-ignore never type error items_.style.width = `calc(${100 / columns}% - 1em)`; }; @@ -677,11 +676,10 @@ const dragEnter = () => { // When the user starts dragging an item, put every // file on the listing with 50% opacity. - let items = document.getElementsByClassName("item"); + const items = document.getElementsByClassName("item"); - // @ts-ignore - Array.from(items).forEach((file: HTMLElement) => { - file.style.opacity = "0.5"; + Array.from(items).forEach((file: Element) => { + (file as HTMLElement).style.opacity = "0.5"; }); }; @@ -698,7 +696,7 @@ const drop = async (event: DragEvent) => { dragCounter.value = 0; resetOpacity(); - let dt = event.dataTransfer; + const dt = event.dataTransfer; let el: HTMLElement | null = event.target as HTMLElement; if (fileStore.req === null || dt === null || dt.files.length <= 0) return; @@ -709,7 +707,7 @@ const drop = async (event: DragEvent) => { } } - let files: UploadList = (await upload.scanFiles(dt)) as UploadList; + const files: UploadList = (await upload.scanFiles(dt)) as UploadList; let items = fileStore.req.items; let path = route.path.endsWith("/") ? route.path : route.path + "/"; @@ -729,7 +727,7 @@ const drop = async (event: DragEvent) => { } } - let conflict = upload.checkConflict(files, items); + const conflict = upload.checkConflict(files, items); if (conflict) { layoutStore.showHover({ @@ -753,10 +751,10 @@ const drop = async (event: DragEvent) => { }; const uploadInput = (event: Event) => { - let files = (event.currentTarget as HTMLInputElement)?.files; + const files = (event.currentTarget as HTMLInputElement)?.files; if (files === null) return; - let folder_upload = !!files[0].webkitRelativePath; + const folder_upload = !!files[0].webkitRelativePath; const uploadFiles: UploadList = []; for (let i = 0; i < files.length; i++) { @@ -771,8 +769,8 @@ const uploadInput = (event: Event) => { }); } - let path = route.path.endsWith("/") ? route.path : route.path + "/"; - let conflict = upload.checkConflict(uploadFiles, fileStore.req!.items); + const path = route.path.endsWith("/") ? route.path : route.path + "/"; + const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items); if (conflict) { layoutStore.showHover({ @@ -796,7 +794,7 @@ const uploadInput = (event: Event) => { }; const resetOpacity = () => { - let items = document.getElementsByClassName("item"); + const items = document.getElementsByClassName("item"); Array.from(items).forEach((file: Element) => { (file as HTMLElement).style.opacity = "1"; @@ -822,7 +820,6 @@ const sort = async (by: string) => { try { if (authStore.user?.id) { - // @ts-ignore await users.update({ id: authStore.user?.id, sorting: { by, asc } }, [ "sorting", ]); @@ -873,10 +870,10 @@ const download = () => { confirm: (format: any) => { layoutStore.closeHovers(); - let files = []; + const files = []; if (fileStore.selectedCount > 0 && fileStore.req !== null) { - for (let i of fileStore.selected) { + for (const i of fileStore.selected) { files.push(fileStore.req.items[i].url); } } else { @@ -899,13 +896,12 @@ const switchView = async () => { const data = { id: authStore.user?.id, - viewMode: modes[authStore.user?.viewMode ?? "list"] || "list", + viewMode: (modes[authStore.user?.viewMode ?? "list"] || + "list") as ViewModeType, }; - // @ts-ignore users.update(data, ["viewMode"]).catch($showError); - // @ts-ignore authStore.updateUser(data); setItemWeight(); diff --git a/frontend/src/views/files/Preview.vue b/frontend/src/views/files/Preview.vue index a4f2cfb7..4fd3d2c8 100644 --- a/frontend/src/views/files/Preview.vue +++ b/frontend/src/views/files/Preview.vue @@ -353,7 +353,7 @@ const updatePreview = async () => { autoPlay.value = false; } - let dirs = route.fullPath.split("/"); + const dirs = route.fullPath.split("/"); name.value = decodeURIComponent(dirs[dirs.length - 1]); if (!listing.value) { @@ -422,7 +422,7 @@ const toggleNavigation = throttle(function () { const close = () => { fileStore.updateRequest(null); - let uri = url.removeLastDir(route.path) + "/"; + const uri = url.removeLastDir(route.path) + "/"; router.push({ path: uri }); }; diff --git a/frontend/src/views/settings/Global.vue b/frontend/src/views/settings/Global.vue index 0b055ee2..5bbaec7f 100644 --- a/frontend/src/views/settings/Global.vue +++ b/frontend/src/views/settings/Global.vue @@ -282,7 +282,7 @@ const formattedChunkSize = computed({ // Define funcs const capitalize = (name: string, where: string | RegExp = "_") => { if (where === "caps") where = /(?=[A-Z])/; - let split = name.split(where); + const split = name.split(where); name = ""; for (let i = 0; i < split.length; i++) { @@ -294,7 +294,7 @@ const capitalize = (name: string, where: string | RegExp = "_") => { const save = async () => { if (settings.value === null) return false; - let newSettings: ISettings = { + const newSettings: ISettings = { ...settings.value, shell: settings.value?.shell @@ -376,7 +376,7 @@ onMounted(async () => { try { layoutStore.loading = true; const original: ISettings = await api.get(); - let newSettings: ISettings = { ...original, commands: {} }; + const newSettings: ISettings = { ...original, commands: {} }; const keys = Object.keys(original.commands) as Array; for (const key of keys) { diff --git a/frontend/src/views/settings/Shares.vue b/frontend/src/views/settings/Shares.vue index 478d595c..e1076ec9 100644 --- a/frontend/src/views/settings/Shares.vue +++ b/frontend/src/views/settings/Shares.vue @@ -87,12 +87,12 @@ onMounted(async () => { layoutStore.loading = true; try { - let newLinks = await api.list(); + const newLinks = await api.list(); if (authStore.user?.perm.admin) { - let userMap = new Map(); - for (let user of await users.getAll()) + const userMap = new Map(); + for (const user of await users.getAll()) userMap.set(user.id, user.username); - for (let link of newLinks) { + for (const link of newLinks) { if (link.userID && userMap.has(link.userID)) link.username = userMap.get(link.userID); } @@ -108,13 +108,23 @@ onMounted(async () => { }); const copyToClipboard = (text: string) => { - copy(text).then( + copy({ text }).then( () => { // clipboard successfully set $showSuccess(t("success.linkCopied")); }, () => { // clipboard write failed + copy({ text }, { permission: true }).then( + () => { + // clipboard successfully set + $showSuccess(t("success.linkCopied")); + }, + (e) => { + // clipboard write failed + $showError(e); + } + ); } ); }; diff --git a/frontend/src/views/settings/User.vue b/frontend/src/views/settings/User.vue index f12d5997..a0da68ce 100644 --- a/frontend/src/views/settings/User.vue +++ b/frontend/src/views/settings/User.vue @@ -90,7 +90,7 @@ const fetchData = async () => { try { if (isNew.value) { - let { defaults, createUserDir: _createUserDir } = await settings.get(); + const { defaults, createUserDir: _createUserDir } = await settings.get(); createUserDir.value = _createUserDir; user.value = { ...defaults,