fix: Mobile style fixes and other small ui fixes
This commit is contained in:
@@ -3,6 +3,9 @@ import { Store } from '@ngrx/store';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { RealtimeSessionFacade } from '../../../../core/realtime';
|
||||
import { DatabaseService } from '../../../../infrastructure/persistence';
|
||||
import { ServerDirectoryFacade } from '../../../server-directory';
|
||||
import { resolveRoomPermission } from '../../../access-control';
|
||||
import { AttachmentFacade } from '../../../attachment';
|
||||
import { VoiceConnectionFacade } from '../../../voice-connection/application/facades/voice-connection.facade';
|
||||
import type {
|
||||
Channel,
|
||||
@@ -28,6 +31,7 @@ import type {
|
||||
PluginApiAvatarUpdate,
|
||||
PluginApiActionContext,
|
||||
PluginApiActionSource,
|
||||
PluginApiAttachmentImportRequest,
|
||||
PluginApiChannelRequest,
|
||||
PluginApiCustomStreamRequest,
|
||||
PluginApiMessageAsPluginUserRequest,
|
||||
@@ -44,11 +48,13 @@ import { PluginUiRegistryService } from './plugin-ui-registry.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PluginClientApiService {
|
||||
private readonly attachments = inject(AttachmentFacade);
|
||||
private readonly capabilities = inject(PluginCapabilityService);
|
||||
private readonly db = inject(DatabaseService);
|
||||
private readonly logger = inject(PluginLoggerService);
|
||||
private readonly messageBus = inject(PluginMessageBusService);
|
||||
private readonly realtime = inject(RealtimeSessionFacade);
|
||||
private readonly serverDirectory = inject(ServerDirectoryFacade);
|
||||
private readonly store = inject(Store);
|
||||
private readonly storage = inject(PluginStorageService);
|
||||
private readonly uiRegistry = inject(PluginUiRegistryService);
|
||||
@@ -73,6 +79,10 @@ export class PluginClientApiService {
|
||||
requireCapability('channels.manage');
|
||||
this.store.dispatch(RoomsActions.addChannel({ channel: createChannel(request, 'voice') }));
|
||||
},
|
||||
addTextChannel: (request) => {
|
||||
requireCapability('channels.manage');
|
||||
this.store.dispatch(RoomsActions.addChannel({ channel: createChannel(request, 'text') }));
|
||||
},
|
||||
addVideoChannel: (request) => {
|
||||
requireCapability('channels.manage');
|
||||
this.uiRegistry.registerChannelSection(pluginId, request.id ?? request.name, {
|
||||
@@ -143,6 +153,15 @@ export class PluginClientApiService {
|
||||
await this.storage.writeClientData(pluginId, key, value);
|
||||
}
|
||||
},
|
||||
attachments: {
|
||||
import: async (request: PluginApiAttachmentImportRequest) => {
|
||||
requireCapability('messages.sync');
|
||||
const roomId = this.requireRoomId();
|
||||
|
||||
this.attachments.rememberMessageRoom(request.messageId, roomId);
|
||||
await this.attachments.publishAttachments(request.messageId, request.files, this.currentUser()?.id);
|
||||
}
|
||||
},
|
||||
media: {
|
||||
addCustomAudioStream: async (request) => {
|
||||
requireCapability('media.addAudioStream');
|
||||
@@ -190,6 +209,10 @@ export class PluginClientApiService {
|
||||
requireCapability('messages.send');
|
||||
this.receivePluginUserMessage(pluginId, request);
|
||||
},
|
||||
import: async (messages) => {
|
||||
requireCapability('messages.sync');
|
||||
await this.importPluginMessages(pluginId, messages);
|
||||
},
|
||||
setTyping: (isTyping, channelId) => {
|
||||
requireCapability('messages.send');
|
||||
this.setTyping(pluginId, isTyping, channelId);
|
||||
@@ -301,6 +324,58 @@ export class PluginClientApiService {
|
||||
|
||||
return userId;
|
||||
},
|
||||
updateIcon: async (icon) => {
|
||||
requireCapability('server.manage');
|
||||
const room = this.currentRoom();
|
||||
const currentUser = this.currentUser();
|
||||
|
||||
if (!room) {
|
||||
throw new Error('Room not found');
|
||||
}
|
||||
|
||||
if (!currentUser) {
|
||||
throw new Error('Not logged in');
|
||||
}
|
||||
|
||||
const isOwner = room.hostId === currentUser.id || room.hostId === currentUser.oderId;
|
||||
const isServerAdmin = currentUser.role === 'admin' || currentUser.role === 'host';
|
||||
const canByRole = resolveRoomPermission(room, currentUser, 'manageIcon');
|
||||
|
||||
if (!isOwner && !isServerAdmin && !canByRole) {
|
||||
throw new Error('Permission denied');
|
||||
}
|
||||
|
||||
const iconUpdatedAt = Date.now();
|
||||
|
||||
await this.db.updateRoom(room.id, { icon, iconUpdatedAt });
|
||||
|
||||
this.store.dispatch(RoomsActions.updateServerIconSuccess({ roomId: room.id, icon, iconUpdatedAt }));
|
||||
|
||||
this.realtime.broadcastMessage({
|
||||
type: 'server-icon-update',
|
||||
roomId: room.id,
|
||||
icon,
|
||||
iconUpdatedAt
|
||||
});
|
||||
|
||||
this.realtime.sendRawMessage({
|
||||
type: 'server_icon_available',
|
||||
serverId: room.id,
|
||||
iconUpdatedAt
|
||||
});
|
||||
|
||||
this.serverDirectory.updateServer(room.id, {
|
||||
actingRole: isOwner ? 'host' : undefined,
|
||||
currentOwnerId: currentUser.id,
|
||||
icon,
|
||||
iconUpdatedAt
|
||||
}, {
|
||||
sourceId: room.sourceId,
|
||||
sourceUrl: room.sourceUrl
|
||||
}).subscribe({
|
||||
error: () => {}
|
||||
});
|
||||
},
|
||||
updatePermissions: (permissions) => {
|
||||
requireCapability('server.manage');
|
||||
this.store.dispatch(RoomsActions.updateRoomPermissions({ roomId: this.requireRoomId(), permissions }));
|
||||
@@ -648,6 +723,29 @@ export class PluginClientApiService {
|
||||
});
|
||||
}
|
||||
|
||||
private async importPluginMessages(pluginId: string, messages: Message[]): Promise<void> {
|
||||
const roomId = this.requireRoomId();
|
||||
const normalizedMessages = messages
|
||||
.filter((message) => message.roomId === roomId)
|
||||
.map((message) => ({
|
||||
...message,
|
||||
channelId: message.channelId ?? this.activeChannelId() ?? 'general',
|
||||
isDeleted: message.isDeleted === true,
|
||||
reactions: message.reactions ?? []
|
||||
}));
|
||||
|
||||
if (normalizedMessages.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const message of normalizedMessages) {
|
||||
await this.db.saveMessage(message);
|
||||
}
|
||||
|
||||
this.store.dispatch(MessagesActions.syncMessages({ messages: normalizedMessages }));
|
||||
this.logger.info(pluginId, 'Historical messages imported', { count: normalizedMessages.length });
|
||||
}
|
||||
|
||||
private persistPluginMessageUpdate(pluginId: string, messageId: string, updates: Partial<Message>): void {
|
||||
void this.db.updateMessage(messageId, updates).catch((error: unknown) => {
|
||||
this.logger.warn(pluginId, 'Failed to persist plugin message update', error);
|
||||
|
||||
Reference in New Issue
Block a user