feat: add app store link for non-admins

-e
Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
This commit is contained in:
Peter Ringelmann 2026-05-06 11:22:05 +02:00 committed by Peter R.
parent 7ec7eb86bf
commit 8e5d02be2d
2 changed files with 26 additions and 4 deletions

View file

@ -11,6 +11,8 @@
'app-item--outlined': outlined,
}"
:href="app.href"
:target="newTab ? '_blank' : undefined"
:rel="newTab ? 'noopener noreferrer' : undefined"
:aria-current="app.active ? 'page' : undefined"
:tabindex="tabindex"
:title="app.name"
@ -41,6 +43,8 @@ import { computed } from 'vue'
const props = withDefaults(defineProps<{
app: INavigationEntry
/** When true, the link opens in a new tab with rel="noopener noreferrer". Used for external destinations (e.g. the app store). */
newTab?: boolean
/** When true, render the circle as an outline only (used for "More apps" / utility entries). */
outlined?: boolean
/**
@ -50,6 +54,7 @@ const props = withDefaults(defineProps<{
*/
tabindex?: number
}>(), {
newTab: false,
outlined: false,
tabindex: -1,
})

View file

@ -39,7 +39,8 @@
:key="item.id"
ref="items"
:app="item"
:outlined="item.id === 'more-apps'"
:outlined="item.id === 'more-apps' || item.id === 'app-store'"
:newTab="item.id === 'more-apps' || item.id === 'app-store'"
:tabindex="i === focusedIndex ? 0 : -1" />
</div>
</div>
@ -109,7 +110,9 @@ export default defineComponent({
// The current-app button lives outside the slot, so we track the
// source and restore focus manually via setReturnFocus.
openedFrom: null as 'waffle' | 'currentApp' | null,
// Synthetic admin-only tile linking to the app store; not a real nav entry.
// Synthetic tile appended to the grid: admins jump to the local
// app management page; everyone else lands on apps.nextcloud.com
// (external, opens in a new tab via the per-tile newTab flag).
moreAppsEntry: {
id: 'more-apps',
active: false,
@ -121,6 +124,17 @@ export default defineComponent({
unread: 0,
} as INavigationEntry,
appStoreEntry: {
id: 'app-store',
active: false,
order: Number.MAX_SAFE_INTEGER,
href: 'https://apps.nextcloud.com/',
icon: generateFilePath('settings', 'img', 'apps.svg'),
type: 'link',
name: t('core', 'App store'),
unread: 0,
} as INavigationEntry,
// `placement: bottom-start` swaps the anchor edge under RTL but the
// skidding sign isn't auto-mirrored, so we flip it here. Snapshot
// at init: Nextcloud's language doesn't change at runtime.
@ -133,9 +147,12 @@ export default defineComponent({
return this.appList.find((app) => app.active)
},
// Stable-ordered list that focusedIndex indexes into; adds "More apps" for admins.
// Stable-ordered list that focusedIndex indexes into. The trailing
// utility tile is "More apps" (local app management) for admins and
// "App store" (apps.nextcloud.com) for everyone else.
gridItems(): INavigationEntry[] {
return this.isAdmin ? [...this.appList, this.moreAppsEntry] : [...this.appList]
const tail = this.isAdmin ? this.moreAppsEntry : this.appStoreEntry
return [...this.appList, tail]
},
},