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

Commit

Permalink
Extend typing capability for threads
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo committed Jun 7, 2023
1 parent 7c3f810 commit 7d57801
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 33 deletions.
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

0 comments on commit 7d57801

Please sign in to comment.