diff options
Diffstat (limited to 'apps/settings/src/components/AppStoreDiscover/AppLink.vue')
-rw-r--r-- | apps/settings/src/components/AppStoreDiscover/AppLink.vue | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/apps/settings/src/components/AppStoreDiscover/AppLink.vue b/apps/settings/src/components/AppStoreDiscover/AppLink.vue new file mode 100644 index 00000000000..88006b1d39b --- /dev/null +++ b/apps/settings/src/components/AppStoreDiscover/AppLink.vue @@ -0,0 +1,117 @@ +<!-- + - @copyright Copyright (c) 2024 Ferdinand Thiessen <opensource@fthiessen.de> + - + - @author Ferdinand Thiessen <opensource@fthiessen.de> + - + - @license AGPL-3.0-or-later + - + - This program is free software: you can redistribute it and/or modify + - it under the terms of the GNU Affero General Public License as + - published by the Free Software Foundation, either version 3 of the + - License, or (at your option) any later version. + - + - This program is distributed in the hope that it will be useful, + - but WITHOUT ANY WARRANTY; without even the implied warranty of + - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + - GNU Affero General Public License for more details. + - + - You should have received a copy of the GNU Affero General Public License + - along with this program. If not, see <http://www.gnu.org/licenses/>. + - + --> +<template> + <a v-if="linkProps" v-bind="linkProps"> + <slot /> + </a> + <RouterLink v-else-if="routerProps" v-bind="routerProps"> + <slot /> + </RouterLink> +</template> + +<script lang="ts"> +import type { RouterLinkProps } from 'vue-router/types/router.js' + +import { loadState } from '@nextcloud/initial-state' +import { generateUrl } from '@nextcloud/router' +import { defineComponent } from 'vue' +import { RouterLink } from 'vue-router' + +const knownRoutes = Object.fromEntries( + Object.entries( + loadState<Record<string, { app?: string, href: string }>>('core', 'apps'), + ).map(([k, v]) => [v.app ?? k, v.href]), +) + +/** + * This component either shows a native link to the installed app or external size - or a router link to the appstore page of the app if not installed + */ +export default defineComponent({ + name: 'AppLink', + + components: { RouterLink }, + + props: { + href: { + type: String, + required: true, + }, + }, + + data() { + return { + routerProps: undefined as RouterLinkProps|undefined, + linkProps: undefined as Record<string, string>|undefined, + } + }, + + watch: { + href: { + immediate: true, + handler() { + const match = this.href.match(/^app:\/\/([^/]+)(\/.+)?$/) + this.routerProps = undefined + this.linkProps = undefined + + // not an app url + if (match === null) { + this.linkProps = { + href: this.href, + target: '_blank', + rel: 'noreferrer noopener', + } + return + } + + const appId = match[1] + // Check if specific route was requested + if (match[2]) { + // we do no know anything about app internal path so we only allow generic app paths + this.linkProps = { + href: generateUrl(`/apps/${appId}${match[2]}`), + } + return + } + + // If we know any route for that app we open it + if (appId in knownRoutes) { + this.linkProps = { + href: knownRoutes[appId], + } + return + } + + // Fallback to show the app store entry + this.routerProps = { + to: { + name: 'apps-details', + params: { + category: 'installed', + id: appId, + }, + }, + } + }, + }, + }, +}) +</script> |