feat: plugins v1.5

This commit is contained in:
2026-04-29 01:14:30 +02:00
parent 6920f93b41
commit eabbc08896
59 changed files with 2197 additions and 352 deletions

View File

@@ -34,7 +34,7 @@
<!-- Channels View -->
@if (panelMode() === 'channels') {
<div class="flex-1 overflow-auto">
<div class="min-h-0 flex-1 overflow-auto">
<!-- Text Channels -->
<section
appThemeNode="roomTextChannelsSection"
@@ -276,7 +276,7 @@
@if (pluginSidePanels().length > 0) {
<div class="mt-3 space-y-2">
@for (record of pluginSidePanels(); track record.id) {
<article class="rounded-md border border-border bg-background/40 p-2">
<article class="max-h-64 overflow-auto rounded-md border border-border bg-background/40 p-2">
<p class="mb-2 truncate text-xs font-medium text-muted-foreground">{{ record.contribution.label }}</p>
<app-plugin-render-host [render]="record.contribution.render" />
</article>

View File

@@ -136,7 +136,7 @@
General
}
@case ('plugins') {
Plugins
Client Plugins
}
@case ('network') {
Network
@@ -162,6 +162,9 @@
@case ('server') {
Server Settings
}
@case ('serverPlugins') {
Server Plugins
}
@case ('members') {
Members
}
@@ -197,7 +200,10 @@
<app-general-settings />
}
@case ('plugins') {
<app-plugin-manager (closed)="navigate('general')" />
<app-plugin-manager
scope="client"
(closed)="navigate('general')"
/>
}
@case ('network') {
<app-network-settings />
@@ -306,6 +312,21 @@
[isAdmin]="isSelectedServerOwner()"
/>
}
@case ('serverPlugins') {
@if (currentRoom()) {
<app-plugin-manager
scope="server"
(closed)="navigate('server')"
/>
} @else {
<section class="rounded-lg border border-border bg-card p-5">
<h4 class="text-sm font-semibold text-foreground">Open this server to manage plugins</h4>
<p class="mt-2 text-sm text-muted-foreground">
Server plugin installs and activation are shown for the currently open chat server. Select or open {{ selectedServer()?.name || 'this server' }} in the app, then return here.
</p>
</section>
}
}
@case ('members') {
<app-members-settings
[server]="selectedServer()"

View File

@@ -121,7 +121,7 @@ export class SettingsModalComponent {
readonly globalPages: { id: SettingsPage; label: string; icon: string }[] = [
{ id: 'general', label: 'General', icon: 'lucideSettings' },
{ id: 'plugins', label: 'Plugins', icon: 'lucidePackage' },
{ id: 'plugins', label: 'Client plugins', icon: 'lucidePackage' },
{ id: 'theme', label: 'Theme Studio', icon: 'lucidePalette' },
{ id: 'network', label: 'Network', icon: 'lucideGlobe' },
{ id: 'notifications', label: 'Notifications', icon: 'lucideBell' },
@@ -132,6 +132,7 @@ export class SettingsModalComponent {
];
readonly serverPages: { id: SettingsPage; label: string; icon: string }[] = [
{ id: 'server', label: 'Server', icon: 'lucideSettings' },
{ id: 'serverPlugins', label: 'Server plugins', icon: 'lucidePackage' },
{ id: 'members', label: 'Members', icon: 'lucideUsers' },
{ id: 'bans', label: 'Bans', icon: 'lucideBan' },
{ id: 'permissions', label: 'Permissions', icon: 'lucideShield' }
@@ -143,8 +144,15 @@ export class SettingsModalComponent {
if (!user)
return [];
return this.savedRooms().filter((room) => {
const viewedRoom = this.currentRoom()?.id === room.id ? (this.currentRoom() ?? room) : room;
const roomsById = new Map(this.savedRooms().map((room) => [room.id, room]));
const currentRoom = this.currentRoom();
if (currentRoom) {
roomsById.set(currentRoom.id, currentRoom);
}
return Array.from(roomsById.values()).filter((room) => {
const viewedRoom = currentRoom?.id === room.id ? currentRoom : room;
const role = resolveLegacyRole(viewedRoom, user);
return (
@@ -162,11 +170,12 @@ export class SettingsModalComponent {
selectedServerId = signal<string | null>(null);
selectedServer = computed<Room | null>(() => {
const id = this.selectedServerId();
const currentRoom = this.currentRoom();
if (!id)
return null;
return this.manageableRooms().find((room) => room.id === id) ?? null;
return currentRoom?.id === id ? currentRoom : (this.manageableRooms().find((room) => room.id === id) ?? null);
});
showServerTabs = computed(() => {
@@ -238,6 +247,13 @@ export class SettingsModalComponent {
return this.selectedServerRole() === 'host';
});
isSelectedServerCurrent = computed(() => {
const selectedServerId = this.selectedServerId();
const currentRoomId = this.currentRoom()?.id ?? null;
return !!selectedServerId && selectedServerId === currentRoomId;
});
animating = signal(false);
showThirdPartyLicenses = signal(false);