Found in BOS/Consulting #400 (8.0.0-alpha9), where Pietro moved theme, language and logout into the user menu of #29525/#29540.
user-menu.view.xml (tl-layout-view) builds its trigger from <avatar input="currentUser"/> and <text input="currentUser">, i.e. from the label of the tl.accounts:Person. That label is "Ferrante, Giulia", so the avatar shows the initials "FG" and the bar shows the last name first. An application that names its people first name first (Pietro: "Giulia Ferrante", "GF", BOS/Consulting #323) cannot use the view:
- A same-path overlay can append to the <menu> children but not replace the avatar or the text: the list is unkeyed, and ListOperation has no replace.
- Redefining the currentUser channel in an overlay breaks the <switch>, whose test needs the account (accountIsAnonymous()).
Pietro therefore composes the same menu again in a view of its own (views/account/account-menu.view.xml) and will switch back to the <view-ref> once this is possible.
Proposal: a separate channel for what the trigger shows, e.g.
<derived-channel name="accountName" expr="currentUser()"/>
fed to <avatar> and <text>, with currentUser kept for the switch. An application then overrides only accountName in an overlay (channels are keyed by name). Alternatively the avatar could read a configurable display name of the account.
Related, smaller: <theme-commands> offers every configured theme, including a base theme an application only extends. An application that defines its own themes beside the engine's "default" and "dark" got four entries, two of them the bare engine look; it cannot remove "default" because its themes extend it. Pietro solved it by putting its tokens into the engine's "default" and "dark" themes instead, which is fine, but a theme flag like selectable="false" (or abstract) would let an application keep its own ids.
Lösung
Kanäle einer View sind nach Namen geschlüsselt. Die <channels> einer View (ViewElement) waren eine ungeschlüsselte Liste; ein Overlay derselben View konnte einen Kanal nur anhängen, nicht umdefinieren. Die Liste ist jetzt nach dem Kanalnamen geschlüsselt:
- Deklariert ein Overlay einen Kanal gleichen Namens, wird er mit dem Kanal der Basis zusammengeführt: was das Overlay angibt (z.B. expr), gilt; was es nicht angibt (z.B. inputs), bleibt aus der Basis erhalten. Mit config:override="true" ersetzt das Overlay die Deklaration vollständig. Auch die Art des Kanals kann wechseln (<channel> ↔ <derived-channel>).
- Ein Kanal mit neuem Namen wird angehängt.
- Ein doppelter Kanalname innerhalb einer View-Datei ist ein Konfigurationsfehler.
Eigener Kanal für den angezeigten Kontonamen. user-menu.view.xml hat den Kanal
<derived-channel name="accountName" expr="currentUser()"/>
der <avatar> und <text> des Menü-Auslösers speist; die Unterscheidung angemeldet/anonym (<switch>) liest weiterhin currentUser. Ohne Overlay bleibt die Anzeige wie bisher. Eine Anwendung, die Personen mit Vorname zuerst benennt, definiert in einem Overlay WEB-INF/views/user-menu.view.xml ihres Moduls nur accountName um. Die Demo-Anwendung tl-demo-react zeigt das:
<view>
<channels>
<derived-channel name="accountName">
<expr><![CDATA[{
account = currentUser();
name = [
$account.get(`tl.accounts:Person#firstName`),
$account.get(`tl.accounts:Person#lastName`)
]
.filter(part -> !$part.trim().isEmpty())
.join(separator: " ");
$name.isEmpty() ? $account : $name
}]]></expr>
</derived-channel>
</channels>
</view>
Abstrakte Themes. Ein UI-Theme (UITheme, Konfiguration in UIThemeService) kann mit abstract="true" markiert werden; es dient dann nur als Basis für extends:
- <theme-commands> bietet es nicht an, und es zählt nicht als Auswahlmöglichkeit (ein konkretes + ein abstraktes Theme ergeben keine Einträge).
- Es ist ein Konfigurationsfehler, wenn es das Default-Theme oder als system-default markiert ist.
- Eine gespeicherte Auswahl dieses Themes wird ignoriert (Fallback auf System-/Default-Theme); SetThemeCommand mit der ID eines abstrakten oder unbekannten Themes ändert nichts (weder Speicherung noch Umschalten im Browser).
- Für ein abstraktes Theme wird kein eigener CSS-Block ausgegeben; seine Tokens stecken in den Blöcken der erweiternden Themes.
- Neue API: UIThemeService.getSelectableThemes(), UIThemeService.isSelectable(String), UITheme.isAbstract(); getThemes() liefert weiterhin alle Themes einschließlich der abstrakten.
Eine Anwendung kann so eigene Themes auf Basis von "default"/"dark" definieren, ohne dass die Basis-Themes im Menü erscheinen, indem sie die Basis-Themes in ihrer Konfiguration als abstract markiert.