Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

feat: Extend typing capability for threads #638

Open
wants to merge 2 commits into
base: alpha
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions src/definition/accessors/INotifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,48 @@ import { IRoom } from '../rooms';
import { IUser } from '../users';
import { IMessageBuilder } from './IMessageBuilder';

export enum TypingScope {
Room = 'room',
export interface ITypingRoomOptions {
/**
* The typing scope where the typing message should be presented,
* TypingScope.Room by default.
*/
scope?: 'room';
/**
* The id of the typing scope
*
* TypingScope.Room <-> room.id
*/
id: string;
/**
* The name of the user who is typing the message
*
* **Note**: If not provided, it will use app assigned
* user's name by default.
*/
username?: string;
}

export interface ITypingOptions {
export interface ITypingThreadOptions {
/**
* The typing scope where the typing message should be presented,
* TypingScope.Room by default.
*/
scope?: TypingScope;
scope: 'thread';
/**
* The id of the typing scope
*
* TypingScope.Room <-> room.id
*/
id: string;
roomId: string;

/**
* The id of the thread
*
* TypingScope.Thread <-> thread.id
*
*/

threadId: string;
/**
* The name of the user who is typing the message
*
Expand All @@ -28,6 +54,8 @@ export interface ITypingOptions {
username?: string;
}

export type TypingThreadOptions = ITypingThreadOptions | ITypingRoomOptions;

export interface INotifier {
/**
* Notifies the provided user of the provided message.
Expand Down Expand Up @@ -56,7 +84,7 @@ export interface INotifier {
*
* @returns a cancellation function to stop typing
*/
typing(options: ITypingOptions): Promise<() => Promise<void>>;
typing(options: ITypingRoomOptions): Promise<() => Promise<void>>;

/** Gets a new message builder for building a notification message. */
getMessageBuilder(): IMessageBuilder;
Expand Down
25 changes: 10 additions & 15 deletions src/server/accessors/Notifier.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import { IMessageBuilder, INotifier } from '../../definition/accessors';
import { ITypingOptions, TypingScope } from '../../definition/accessors/INotifier';
import { TypingThreadOptions } from '../../definition/accessors/INotifier';
import { IMessage } from '../../definition/messages';
import { IRoom } from '../../definition/rooms';
import { IUser } from '../../definition/users';
import { MessageBridge, UserBridge } from '../bridges';
import { MessageBuilder } from './MessageBuilder';

export class Notifier implements INotifier {
constructor(
private readonly userBridge: UserBridge,
private readonly msgBridge: MessageBridge,
private readonly appId: string,
) { }
constructor(private readonly userBridge: UserBridge, private readonly msgBridge: MessageBridge, private readonly appId: string) {}

public async notifyUser(user: IUser, message: IMessage): Promise<void> {
if (!message.sender || !message.sender.id) {
Expand All @@ -33,17 +29,16 @@ export class Notifier implements INotifier {
await this.msgBridge.doNotifyRoom(room, message, this.appId);
}

public async typing(options: ITypingOptions): Promise<() => Promise<void>> {
options.scope = options.scope || TypingScope.Room;
public async typing(options: TypingThreadOptions): Promise<() => Promise<void>> {
const payload = {
scope: 'room' as const,
...options,
username: options.username ?? (await this.userBridge.doGetAppUser(this.appId).then((u) => u.name ?? '')),
};

if (!options.username) {
const appUser = await this.userBridge.doGetAppUser(this.appId);
options.username = appUser && appUser.name || '';
}

this.msgBridge.doTyping({ ...options, isTyping: true }, this.appId);
this.msgBridge.doTyping({ ...payload, isTyping: true }, this.appId);

return () => this.msgBridge.doTyping({ ...options, isTyping: false }, this.appId);
return () => this.msgBridge.doTyping({ ...payload, isTyping: false }, this.appId);
}

public getMessageBuilder(): IMessageBuilder {
Expand Down
43 changes: 31 additions & 12 deletions src/server/bridges/MessageBridge.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ITypingOptions } from '../../definition/accessors/INotifier';
import { ITypingRoomOptions, ITypingThreadOptions } from '../../definition/accessors/INotifier';
import { IMessage } from '../../definition/messages';
import { IRoom } from '../../definition/rooms';
import { IUser } from '../../definition/users';
Expand All @@ -7,10 +7,25 @@ import { AppPermissionManager } from '../managers/AppPermissionManager';
import { AppPermissions } from '../permissions/AppPermissions';
import { BaseBridge } from './BaseBridge';

export interface ITypingDescriptor extends ITypingOptions {
/** @deprecated use TypingDescriptor instead */
export interface ITypingDescriptor extends ITypingRoomOptions {
isTyping: boolean;
}

type WithRequiredProperty<Type, Key extends keyof Type> = Type & {
[Property in Key]-?: Type[Property];
};

type Pretty<K> = {
[P in keyof K]: K[P];
};

export type TypingDescriptor = Pretty<
WithRequiredProperty<ITypingRoomOptions | ITypingThreadOptions, 'username'> & {
isTyping: boolean;
}
>;

export abstract class MessageBridge extends BaseBridge {
public async doCreate(message: IMessage, appId: string): Promise<string> {
if (this.hasWritePermission(appId)) {
Expand All @@ -36,7 +51,7 @@ export abstract class MessageBridge extends BaseBridge {
}
}

public async doTyping(options: ITypingDescriptor, appId: string): Promise<void> {
public async doTyping(options: TypingDescriptor, appId: string): Promise<void> {
if (this.hasWritePermission(appId)) {
return this.typing(options, appId);
}
Expand All @@ -58,7 +73,7 @@ export abstract class MessageBridge extends BaseBridge {
protected abstract update(message: IMessage, appId: string): Promise<void>;
protected abstract notifyUser(user: IUser, message: IMessage, appId: string): Promise<void>;
protected abstract notifyRoom(room: IRoom, message: IMessage, appId: string): Promise<void>;
protected abstract typing(options: ITypingDescriptor, appId: string): Promise<void>;
protected abstract typing(options: TypingDescriptor, appId: string): Promise<void>;
protected abstract getById(messageId: string, appId: string): Promise<IMessage>;
protected abstract delete(message: IMessage, user: IUser, appId: string): Promise<void>;

Expand All @@ -67,10 +82,12 @@ export abstract class MessageBridge extends BaseBridge {
return true;
}

AppPermissionManager.notifyAboutError(new PermissionDeniedError({
appId,
missingPermissions: [AppPermissions.message.read],
}));
AppPermissionManager.notifyAboutError(
new PermissionDeniedError({
appId,
missingPermissions: [AppPermissions.message.read],
}),
);

return false;
}
Expand All @@ -80,10 +97,12 @@ export abstract class MessageBridge extends BaseBridge {
return true;
}

AppPermissionManager.notifyAboutError(new PermissionDeniedError({
appId,
missingPermissions: [AppPermissions.message.write],
}));
AppPermissionManager.notifyAboutError(
new PermissionDeniedError({
appId,
missingPermissions: [AppPermissions.message.write],
}),
);

return false;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/test-data/bridges/messageBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IMessage } from '../../../src/definition/messages';
import { IRoom } from '../../../src/definition/rooms';
import { IUser } from '../../../src/definition/users';
import { MessageBridge } from '../../../src/server/bridges';
import { ITypingDescriptor } from '../../../src/server/bridges/MessageBridge';
import { TypingDescriptor } from '../../../src/server/bridges/MessageBridge';

export class TestsMessageBridge extends MessageBridge {
public create(message: IMessage, appId: string): Promise<string> {
Expand All @@ -29,7 +29,7 @@ export class TestsMessageBridge extends MessageBridge {
throw new Error('Method not implemented.');
}

public typing(options: ITypingDescriptor): Promise<void> {
public typing(options: TypingDescriptor): Promise<void> {
throw new Error('Method not implemented.');
}
}