A self hosted chat application with end-to-end encrypted messaging.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
4.8 KiB

4 years ago
4 years ago
  1. import { Subject } from "../observe/Observable";
  2. import { Observer } from "../observe/Observer";
  3. import { JsonAPI } from "../singleton/JsonAPI";
  4. import { ChatMessageViewModel } from "../viewmodel/ChatMessageViewModel";
  5. import { ChatModelHelper } from "./ChatModelHelper";
  6. import log = require('loglevel');
  7. import { ObserverData } from "../observe/ObserverData";
  8. interface Params {
  9. userName: string,
  10. data: ChatMessageViewModel[],
  11. op: string
  12. }
  13. export class ChatModel implements Subject<ChatMessageViewModel> {
  14. /**
  15. * @type {Observer[]} List of subscribers. In real life, the list of
  16. * subscribers can be stored more comprehensively (categorized by event
  17. * type, etc.).
  18. */
  19. private readonly _observers: Observer<ChatMessageViewModel>[] = [];
  20. private readonly _messagePageMap: Map<string, number>;
  21. private readonly _messagesMap: Map<string, ChatMessageViewModel[]>;
  22. private readonly _chatModelHelper: ChatModelHelper;
  23. constructor(chatModelHelper: ChatModelHelper) {
  24. this._messagePageMap = new Map();
  25. this._messagesMap = new Map();
  26. this._chatModelHelper = chatModelHelper;
  27. }
  28. /**
  29. * The subscription management methods.
  30. */
  31. public attach(observer: Observer<ChatMessageViewModel>): void {
  32. log.info('Subject: Attached an observer.');
  33. this._observers.push(observer);
  34. }
  35. public detach(observer: Observer<ChatMessageViewModel>): void {
  36. const observerIndex = this._observers.indexOf(observer);
  37. this._observers.splice(observerIndex, 1);
  38. log.info('Subject: Detached an observer.');
  39. }
  40. private storeUserMessages(username: string, messages: ChatMessageViewModel[], op: string) {
  41. switch (op) {
  42. case "clear": this._messagesMap.set(username, []);
  43. case "page": this._messagesMap.set(username, messages.concat(this.getStoredUserMessages(username))); break;
  44. // case "page": this._messagesMap.set(username, messages);
  45. case "new": this._messagesMap.set(username, this.getStoredUserMessages(username).concat(messages)); break;
  46. default: new Error("Invalid option");
  47. }
  48. }
  49. private getStoredUserMessages(username: string): ChatMessageViewModel[] {
  50. let temp = this._messagesMap.get(username);
  51. if (temp == null)
  52. return [];
  53. else {
  54. return temp;
  55. }
  56. }
  57. /**
  58. * Trigger an update in each subscriber.
  59. */
  60. public notify(p: Params): void {
  61. log.info('Subject: Notifying observers...');
  62. switch (p.op) {
  63. case "clear": {
  64. const od: ObserverData<ChatMessageViewModel> = { data: [], op: "clear" }
  65. for (const observer of this._observers) {
  66. observer.update(od);
  67. }
  68. } break;
  69. case "new": {
  70. const od: ObserverData<ChatMessageViewModel> = { data: p.data, op: p.op }
  71. for (const observer of this._observers) {
  72. observer.update(od);
  73. }
  74. } break;
  75. case "page": {
  76. const od: ObserverData<ChatMessageViewModel> = { data: p.data, op: p.op }
  77. for (const observer of this._observers) {
  78. observer.update(od);
  79. }
  80. } break;
  81. default: { log.error("error") }
  82. }
  83. }
  84. public someBusinessMethod(chatMessageList: ChatMessageViewModel[]): void {
  85. }
  86. public clear(): void {
  87. log.info("Clearing model")
  88. this._messagePageMap.set(JsonAPI.contactName!, 0);
  89. this.storeUserMessages(JsonAPI.contactName!, Array(), "clear");
  90. this.notify({ userName: "", data: [], op: "clear" })
  91. }
  92. public async getMessages(contactName: string, passphrase: string, lastMessageTime: string | null, op: string): Promise<ChatMessageViewModel[]> {
  93. if (this._messagePageMap.get(contactName) == null)
  94. this._messagePageMap.set(contactName, 0);
  95. const pageNumber = this._messagePageMap.get(contactName)
  96. const cVMs = await this._chatModelHelper.getMessages(contactName, passphrase, pageNumber!, lastMessageTime, op);
  97. if (cVMs != null) {
  98. log.info('Subject: My state has just changed')
  99. const existingMessages = this.getStoredUserMessages(contactName);
  100. log.debug('existing message:')
  101. log.debug(existingMessages);
  102. log.debug('new messages:')
  103. log.debug(cVMs);
  104. this.storeUserMessages(contactName, cVMs, op);
  105. this.notify({ userName: contactName, data: cVMs, op: op });
  106. }
  107. else {
  108. log.error('Messages were null');
  109. }
  110. if (cVMs.length != 0) {
  111. this._messagePageMap.set(contactName, this._messagePageMap.get(contactName)! + 1);
  112. }
  113. return cVMs;
  114. }
  115. }