Skip to content

Commit 68b40b2

Browse files
committed
fix(core): restore backport hunks that did not apply on stable34
The lexicon entry, the gridItems gate, the initial state and the stateFor test helper were dropped by the cherry-pick, leaving a config key that nothing reads. Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
1 parent 48b3dc9 commit 68b40b2

4 files changed

Lines changed: 42 additions & 2 deletions

File tree

core/AppInfo/ConfigLexicon.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ public function getAppConfigs(): array {
103103
defaultRaw: true,
104104
definition: 'Whether on demand preview migration is enabled.'
105105
),
106+
new Entry(
107+
key: self::APPSTORE_LINK_SHOWN,
108+
type: ValueType::BOOL,
109+
defaultRaw: fn (Preset $p): bool => match ($p) {
110+
Preset::NONE, Preset::PRIVATE, Preset::FAMILY, Preset::CLUB => true,
111+
default => false,
112+
},
113+
definition: 'Show the app store link in the app menu to accounts without admin rights',
114+
note: 'When this key is not set, the link is also hidden while a valid subscription is available or while "appstoreenabled" is disabled. Setting this key explicitly takes precedence over both.',
115+
),
106116
];
107117
}
108118

core/src/components/AppMenu.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,13 @@ export default defineComponent({
196196
// "App store" (apps.nextcloud.com) for everyone else when
197197
// appstore_link_shown allows it.
198198
gridItems(): INavigationEntry[] {
199-
const tail = this.isAdmin ? this.moreAppsEntry : this.appStoreEntry
200-
return [...this.appList, tail]
199+
const tail: INavigationEntry[] = []
200+
if (this.isAdmin) {
201+
tail.push(this.moreAppsEntry)
202+
} else if (this.appStoreLinkShown) {
203+
tail.push(this.appStoreEntry)
204+
}
205+
return [...this.appList, ...tail]
201206
},
202207
},
203208

core/src/tests/components/AppMenu.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ function eightApps(activeIndex: number = -1): INavigationEntry[] {
7575
}))
7676
}
7777

78+
// AppMenu hides the app store tile when the state is absent, so a default
79+
// instance has to supply it.
80+
function stateFor(states: Record<string, unknown>) {
81+
const all: Record<string, unknown> = { appStoreLinkShown: true, ...states }
82+
return (_app: string, key: string, fallback: unknown) => key in all ? all[key] : fallback
83+
}
84+
7885
// Import AFTER mocks are registered. Static `import` would hoist above
7986
// vi.mock() and break the wiring; dynamic import in beforeAll/await is the
8087
// idiomatic Vitest workaround when you need to control mock state per test.
@@ -142,6 +149,23 @@ describe('core: AppMenu', () => {
142149
expect(moreApps).toBeTruthy()
143150
})
144151

152+
it('omits the "App store" tile when the instance does not offer it', async () => {
153+
initialState.loadState.mockImplementation(stateFor({ apps: fakeApps(), appStoreLinkShown: false }))
154+
const wrapper = mount(AppMenu, { attachTo: document.body })
155+
await openPopover(wrapper)
156+
157+
expect(gridLabels()).toEqual(['Files', 'Mail', 'Calendar'])
158+
})
159+
160+
it('keeps the "More apps" tile for admins when the app store link is hidden', async () => {
161+
initialState.loadState.mockImplementation(stateFor({ apps: fakeApps(), appStoreLinkShown: false }))
162+
auth.getCurrentUser.mockReturnValue({ isAdmin: true })
163+
const wrapper = mount(AppMenu, { attachTo: document.body })
164+
await openPopover(wrapper)
165+
166+
expect(gridLabels()).toEqual(['Files', 'Mail', 'Calendar', 'More apps'])
167+
})
168+
145169
it('ArrowRight moves the roving stop from index 0 to index 1 and focuses it', async () => {
146170
initialState.loadState.mockImplementation(stateFor({ apps: eightApps() }))
147171
const wrapper = mount(AppMenu, { attachTo: document.body })

lib/private/TemplateLayout.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public function getPageTemplate(string $renderAs, string $appId): ITemplate {
8383

8484
$this->initialState->provideInitialState('core', 'active-app', $this->navigationManager->getActiveEntry());
8585
$this->initialState->provideInitialState('core', 'apps', array_values($this->navigationManager->getAll()));
86+
$this->initialState->provideInitialState('core', 'appStoreLinkShown', Server::get(AppStoreLinkVisibility::class)->isShownToUsers());
8687

8788
$this->initialState->provideInitialState('unified-search', 'min-search-length', $this->appConfig->getValueInt(Application::APP_ID, ConfigLexicon::UNIFIED_SEARCH_MIN_SEARCH_LENGTH));
8889
if ($this->config->getSystemValueBool('unified_search.enabled', false) || !$this->config->getSystemValueBool('enable_non-accessible_features', true)) {

0 commit comments

Comments
 (0)