diff --git a/config/widgets.php b/config/widgets.php index c65d3b52..df57e8f3 100644 --- a/config/widgets.php +++ b/config/widgets.php @@ -60,7 +60,7 @@ return [ 'title' => 'Waehrungskurse', 'icon' => 'FX', 'zone' => 'sidebar', - 'default_enabled' => false, + 'default_enabled' => true, 'supports_public_home' => false, 'summary' => 'Aktuelle FX-Kurse pruefen und bei Bedarf manuell aktualisieren.', 'content' => 'Ein API-Abruf wird nur ausgefuehrt, wenn der letzte Snapshot alt genug ist, ausser bei explizitem Force.', diff --git a/partials/desktop/shell.php b/partials/desktop/shell.php index 9ebeb87d..31aed278 100644 --- a/partials/desktop/shell.php +++ b/partials/desktop/shell.php @@ -158,7 +158,12 @@ $renderStartIcon = static function (array $profile): string {
- + diff --git a/public/assets/desktop/desktop.js b/public/assets/desktop/desktop.js index 7f2800af..74542115 100644 --- a/public/assets/desktop/desktop.js +++ b/public/assets/desktop/desktop.js @@ -1736,6 +1736,18 @@ if (payloadNode) { setAccountMenuOpen(accountMenu.hidden); }); + document.querySelectorAll('.tray-pill[data-tray-app-id]').forEach((button) => { + button.addEventListener('click', () => { + const appId = button.getAttribute('data-tray-app-id') || ''; + const app = findAppById(appId); + if (app) { + openApp(app); + setStartMenuOpen(false); + setAccountMenuOpen(false); + } + }); + }); + debugToggleNode?.addEventListener('click', () => { toggleDebugWindow(); }); diff --git a/src/App/App.php b/src/App/App.php index 158010f0..6c2ceebb 100644 --- a/src/App/App.php +++ b/src/App/App.php @@ -56,6 +56,19 @@ final class App $apps = AppIconResolver::decorate($enabledApps, $activeSkin); $windows = (new WindowManager($registry))->defaultWindows(); $activeWidgetIds = array_values(array_map('strval', (array) ($userSettings['widgets']['active_ids'] ?? DesktopState::defaultWidgetIds()))); + $trayItems = DesktopState::trayItems(); + foreach ($enabledApps as $app) { + if (empty($app['supports_tray']) || (string) ($app['app_id'] ?? '') !== 'fx-rates') { + continue; + } + + $trayItems[] = [ + 'id' => 'app-' . (string) $app['app_id'], + 'label' => (string) ($app['icon'] ?? 'FX'), + 'app_id' => (string) ($app['app_id'] ?? ''), + 'title' => (string) ($app['title'] ?? ''), + ]; + } $displayName = (string) ($authUser['name'] ?? $authUser['username'] ?? 'Gast'); $storageScope = $isAuthenticated ? strtolower((string) ($authUser['username'] ?? $authUser['sub'] ?? 'user')) @@ -94,7 +107,7 @@ final class App 'registry' => $widgetRegistry->all(), 'active_ids' => $activeWidgetIds, ], - 'tray' => DesktopState::trayItems(), + 'tray' => $trayItems, 'session' => [ 'display_name' => $displayName, 'authenticated' => $isAuthenticated, diff --git a/src/App/UserSelfManagementService.php b/src/App/UserSelfManagementService.php index 329338b9..bce06918 100644 --- a/src/App/UserSelfManagementService.php +++ b/src/App/UserSelfManagementService.php @@ -196,6 +196,10 @@ final class UserSelfManagementService static fn (array $app): string => (string) ($app['app_id'] ?? ''), $visibleApps ))); + $defaultEnabledAppIds = array_values(array_filter(array_map( + static fn (array $app): ?string => ($app['enabled_by_default'] ?? false) ? (string) ($app['app_id'] ?? '') : null, + $visibleApps + ))); $defaultWidgetIds = array_values(array_filter(array_map( static fn (array $widget): ?string => ($widget['default_enabled'] ?? false) ? (string) ($widget['widget_id'] ?? '') : null, $widgets @@ -204,13 +208,35 @@ final class UserSelfManagementService static fn (array $widget): string => (string) ($widget['widget_id'] ?? ''), $widgets ))); + $storedEnabledAppIds = array_key_exists('enabled_ids', (array) ($settings['apps'] ?? [])) + ? $this->sanitizeSelection($settings['apps']['enabled_ids'] ?? [], $visibleAppIds) + : $visibleAppIds; + $knownAppIds = $this->sanitizeSelection( + $settings['apps']['known_ids'] ?? [], + $visibleAppIds + ); + $newDefaultAppIds = array_values(array_filter( + $defaultEnabledAppIds, + static fn (string $appId): bool => !in_array($appId, $knownAppIds, true) + )); $enabledAppIds = $this->sanitizeSelection( - $settings['apps']['enabled_ids'] ?? $visibleAppIds, + array_merge($storedEnabledAppIds, $newDefaultAppIds), $visibleAppIds, [self::APP_ID] ); + $storedActiveWidgetIds = array_key_exists('active_ids', (array) ($settings['widgets'] ?? [])) + ? $this->sanitizeSelection($settings['widgets']['active_ids'] ?? [], $allWidgetIds) + : $defaultWidgetIds; + $knownWidgetIds = $this->sanitizeSelection( + $settings['widgets']['known_ids'] ?? [], + $allWidgetIds + ); + $newDefaultWidgetIds = array_values(array_filter( + $defaultWidgetIds, + static fn (string $widgetId): bool => !in_array($widgetId, $knownWidgetIds, true) + )); $activeWidgetIds = $this->sanitizeSelection( - $settings['widgets']['active_ids'] ?? $defaultWidgetIds, + array_merge($storedActiveWidgetIds, $newDefaultWidgetIds), $allWidgetIds ); $profile = []; @@ -240,9 +266,11 @@ final class UserSelfManagementService ], 'apps' => [ 'enabled_ids' => $enabledAppIds, + 'known_ids' => $visibleAppIds, ], 'widgets' => [ 'active_ids' => $activeWidgetIds, + 'known_ids' => $allWidgetIds, ], 'integration' => [ 'ldap_write_status' => 'planned',