add message notifications
This commit is contained in:
Vendored
+27
-2
@@ -340,12 +340,37 @@ body[showing-chat] #chat-page-wrapper {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
#chat-page > div > #ribbon > span {
|
#chat-page > div > #ribbon > span {
|
||||||
height: 100%;
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: end;
|
justify-content: end;
|
||||||
}
|
}
|
||||||
|
#chat-page > div > #ribbon > span.marquee {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#chat-page > div > #ribbon > span.marquee > span {
|
||||||
|
transform: rotate(270deg);
|
||||||
|
transform-origin: left;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -10px;
|
||||||
|
left: calc(var(--control-height) / 2);
|
||||||
|
height: var(--control-height);
|
||||||
|
min-width: 100vh;
|
||||||
|
overflow: visible;
|
||||||
|
text-overflow: visible;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--gap-between-tiles);
|
||||||
|
}
|
||||||
|
#chat-page > div > #ribbon > span.marquee > span > * {
|
||||||
|
animation: slide-up var(--animation-duration);
|
||||||
|
}
|
||||||
|
#chat-page > div > #ribbon > .navigation-buttons {
|
||||||
|
min-height: calc(var(--control-height) * 4);
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
#chat-page > div > #ribbon button,
|
#chat-page > div > #ribbon button,
|
||||||
#chat-page > div > #main > div > .pane-wrapper > .pane > .toolbar button {
|
#chat-page > div > #main > div > .pane-wrapper > .pane > .toolbar button {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
|||||||
Vendored
+76
-5
@@ -651,6 +651,9 @@
|
|||||||
],
|
],
|
||||||
files: (id) => [...filePaths.chat.chatBase(id), "files"]
|
files: (id) => [...filePaths.chat.chatBase(id), "files"]
|
||||||
},
|
},
|
||||||
|
notificationModel: {
|
||||||
|
base: []
|
||||||
|
},
|
||||||
settingsModel: {
|
settingsModel: {
|
||||||
username: ["user-name"],
|
username: ["user-name"],
|
||||||
firstDayOfWeek: ["first-day-of-week"]
|
firstDayOfWeek: ["first-day-of-week"]
|
||||||
@@ -1373,8 +1376,11 @@
|
|||||||
);
|
);
|
||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
|
// utility
|
||||||
|
static splitChannel(channelString) {
|
||||||
|
return channelString.split("/");
|
||||||
|
}
|
||||||
static {
|
static {
|
||||||
// utility
|
|
||||||
this.generateChatInfo = (primaryChannel) => {
|
this.generateChatInfo = (primaryChannel) => {
|
||||||
return {
|
return {
|
||||||
dataVersion: DATA_VERSION,
|
dataVersion: DATA_VERSION,
|
||||||
@@ -3024,7 +3030,7 @@
|
|||||||
// src/ViewModel/Chat/chatViewModel.ts
|
// src/ViewModel/Chat/chatViewModel.ts
|
||||||
var ChatViewModel = class {
|
var ChatViewModel = class {
|
||||||
// init
|
// init
|
||||||
constructor(coreViewModel, storageModel2, chatModel, settingsViewModel2, connectionViewModel2, chatListViewModel2) {
|
constructor(coreViewModel, storageModel2, chatModel, settingsViewModel2, notificationViewModel, connectionViewModel2, chatListViewModel2) {
|
||||||
this.coreViewModel = coreViewModel;
|
this.coreViewModel = coreViewModel;
|
||||||
// state
|
// state
|
||||||
this.displayedColor = new State("standard" /* Standard */);
|
this.displayedColor = new State("standard" /* Standard */);
|
||||||
@@ -3094,6 +3100,7 @@
|
|||||||
this.chatModel = chatModel;
|
this.chatModel = chatModel;
|
||||||
this.settingsViewModel = settingsViewModel2;
|
this.settingsViewModel = settingsViewModel2;
|
||||||
this.connectionViewModel = connectionViewModel2;
|
this.connectionViewModel = connectionViewModel2;
|
||||||
|
this.notificationViewModel = notificationViewModel;
|
||||||
this.chatListViewModel = chatListViewModel2;
|
this.chatListViewModel = chatListViewModel2;
|
||||||
this.calendarViewModel = new CalendarPageViewModel(
|
this.calendarViewModel = new CalendarPageViewModel(
|
||||||
coreViewModel,
|
coreViewModel,
|
||||||
@@ -3120,6 +3127,7 @@
|
|||||||
(chatMessage) => {
|
(chatMessage) => {
|
||||||
this.messagePageViewModel.showChatMessage(chatMessage);
|
this.messagePageViewModel.showChatMessage(chatMessage);
|
||||||
this.updateReadStatus();
|
this.updateReadStatus();
|
||||||
|
this.notificationViewModel.showNotification(chatMessage);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.loadPageSelection();
|
this.loadPageSelection();
|
||||||
@@ -3128,6 +3136,59 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// src/ViewModel/Global/notificationViewModel.ts
|
||||||
|
var NotificationViewModel = class _NotificationViewModel {
|
||||||
|
// init
|
||||||
|
constructor(chatListViewModel2) {
|
||||||
|
// data
|
||||||
|
this.seenMessageIds = /* @__PURE__ */ new Set();
|
||||||
|
this.messagesInMarquee = [];
|
||||||
|
this.marquee = new State(void 0);
|
||||||
|
this.currentIndex = 0;
|
||||||
|
this.interval = void 0;
|
||||||
|
// main
|
||||||
|
this.showNotification = (message) => {
|
||||||
|
const notification = _NotificationViewModel.createNotification(message);
|
||||||
|
if (this.seenMessageIds.has(message.id)) return;
|
||||||
|
const currentChat = this.chatListViewModel.selectedChat.value.chatModel.info.primaryChannel;
|
||||||
|
if (notification.chat == currentChat) return;
|
||||||
|
this.messagesInMarquee.push(notification);
|
||||||
|
this.startLoop();
|
||||||
|
};
|
||||||
|
// loop
|
||||||
|
this.loop = () => {
|
||||||
|
if (this.messagesInMarquee.length == 0) {
|
||||||
|
this.marquee.value = void 0;
|
||||||
|
return this.stopLoop();
|
||||||
|
}
|
||||||
|
const notification = this.messagesInMarquee.shift();
|
||||||
|
this.seenMessageIds.delete(notification.messageId);
|
||||||
|
this.marquee.value = notification;
|
||||||
|
};
|
||||||
|
this.startLoop = () => {
|
||||||
|
if (this.interval != void 0) return;
|
||||||
|
this.loop();
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
this.loop();
|
||||||
|
}, 5e3);
|
||||||
|
};
|
||||||
|
this.stopLoop = () => {
|
||||||
|
clearInterval(this.interval);
|
||||||
|
this.interval = void 0;
|
||||||
|
};
|
||||||
|
this.chatListViewModel = chatListViewModel2;
|
||||||
|
}
|
||||||
|
// util
|
||||||
|
static createNotification(message) {
|
||||||
|
return {
|
||||||
|
messageId: message.id,
|
||||||
|
chat: ChatModel.splitChannel(message.channel)[0],
|
||||||
|
sender: message.sender,
|
||||||
|
body: message.body
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// src/ViewModel/Chat/chatListViewModel.ts
|
// src/ViewModel/Chat/chatListViewModel.ts
|
||||||
var ChatListViewModel = class {
|
var ChatListViewModel = class {
|
||||||
// init
|
// init
|
||||||
@@ -3171,6 +3232,7 @@
|
|||||||
this.storageModel,
|
this.storageModel,
|
||||||
chatModel,
|
chatModel,
|
||||||
this.settingsViewModel,
|
this.settingsViewModel,
|
||||||
|
this.notificationViewModel,
|
||||||
this.connectionViewModel,
|
this.connectionViewModel,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
@@ -3200,6 +3262,7 @@
|
|||||||
this.storageModel = storageModel2;
|
this.storageModel = storageModel2;
|
||||||
this.chatListModel = chatListModel2;
|
this.chatListModel = chatListModel2;
|
||||||
this.settingsViewModel = settingsViewModel2;
|
this.settingsViewModel = settingsViewModel2;
|
||||||
|
this.notificationViewModel = new NotificationViewModel(this);
|
||||||
this.connectionViewModel = connectionViewModel2;
|
this.connectionViewModel = connectionViewModel2;
|
||||||
this.loadChats();
|
this.loadChats();
|
||||||
}
|
}
|
||||||
@@ -3680,7 +3743,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// src/View/Components/chatMessage.tsx
|
// src/View/Components/chatMessage.tsx
|
||||||
function ChatMessage2(chatMessageViewModel) {
|
function ChatMessage3(chatMessageViewModel) {
|
||||||
const statusIcon = createProxyState(
|
const statusIcon = createProxyState(
|
||||||
[chatMessageViewModel.status],
|
[chatMessageViewModel.status],
|
||||||
() => {
|
() => {
|
||||||
@@ -3726,7 +3789,7 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
var ChatMessageViewModelToView = (chatMessageViewModel) => {
|
var ChatMessageViewModelToView = (chatMessageViewModel) => {
|
||||||
return ChatMessage2(chatMessageViewModel);
|
return ChatMessage3(chatMessageViewModel);
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/View/ChatPages/messagePage.tsx
|
// src/View/ChatPages/messagePage.tsx
|
||||||
@@ -4555,6 +4618,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
const marqueeContent = createProxyState(
|
||||||
|
[chatViewModel.notificationViewModel.marquee],
|
||||||
|
() => {
|
||||||
|
const value = chatViewModel.notificationViewModel.marquee.value;
|
||||||
|
if (value == void 0) return /* @__PURE__ */ createElement("span", null);
|
||||||
|
return /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement("b", null, value.sender), /* @__PURE__ */ createElement("span", { class: "secondary" }, value.chat, ": "), /* @__PURE__ */ createElement("span", null, value.body));
|
||||||
|
}
|
||||||
|
);
|
||||||
return /* @__PURE__ */ createElement(
|
return /* @__PURE__ */ createElement(
|
||||||
"article",
|
"article",
|
||||||
{
|
{
|
||||||
@@ -4579,7 +4650,7 @@
|
|||||||
"toggle:hidden": chatViewModel.connectionViewModel.isConnected
|
"toggle:hidden": chatViewModel.connectionViewModel.isConnected
|
||||||
},
|
},
|
||||||
/* @__PURE__ */ createElement("span", { class: "icon" }, "signal_disconnected")
|
/* @__PURE__ */ createElement("span", { class: "icon" }, "signal_disconnected")
|
||||||
), /* @__PURE__ */ createElement("span", null, ChatViewToggleButton(
|
), /* @__PURE__ */ createElement("span", { class: "marquee", "children:set": marqueeContent }), /* @__PURE__ */ createElement("span", { class: "navigation-buttons" }, ChatViewToggleButton(
|
||||||
translations.chatPage.pages.calendar,
|
translations.chatPage.pages.calendar,
|
||||||
"calendar_month",
|
"calendar_month",
|
||||||
"calendar" /* Calendar */,
|
"calendar" /* Calendar */,
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export default class ChatModel {
|
|||||||
|
|
||||||
chatMessage.status = ChatMessageStatus.Received;
|
chatMessage.status = ChatMessageStatus.Received;
|
||||||
this.addMessage(chatMessage);
|
this.addMessage(chatMessage);
|
||||||
|
|
||||||
this.setReadStatus(true);
|
this.setReadStatus(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -271,6 +271,10 @@ export default class ChatModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// utility
|
// utility
|
||||||
|
static splitChannel(channelString: string): string[] {
|
||||||
|
return channelString.split("/");
|
||||||
|
}
|
||||||
|
|
||||||
static generateChatInfo = (primaryChannel: string): ChatInfo => {
|
static generateChatInfo = (primaryChannel: string): ChatInfo => {
|
||||||
return {
|
return {
|
||||||
dataVersion: DATA_VERSION,
|
dataVersion: DATA_VERSION,
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ export enum StorageModelSubPath {
|
|||||||
Chat = "chat",
|
Chat = "chat",
|
||||||
|
|
||||||
ConnectionModel = "connection",
|
ConnectionModel = "connection",
|
||||||
|
NotificationModel = "notifications",
|
||||||
SettingsModel = "settings",
|
SettingsModel = "settings",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,6 +254,10 @@ export const filePaths = {
|
|||||||
files: (id: string) => [...filePaths.chat.chatBase(id), "files"],
|
files: (id: string) => [...filePaths.chat.chatBase(id), "files"],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
notificationModel: {
|
||||||
|
base: [],
|
||||||
|
},
|
||||||
|
|
||||||
settingsModel: {
|
settingsModel: {
|
||||||
username: ["user-name"],
|
username: ["user-name"],
|
||||||
firstDayOfWeek: ["first-day-of-week"],
|
firstDayOfWeek: ["first-day-of-week"],
|
||||||
|
|||||||
+35
-4
@@ -125,15 +125,46 @@ body[showing-chat] #chat-page-wrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#chat-page > div > #ribbon > span {
|
#chat-page > div > #ribbon > span {
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: end;
|
justify-content: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#chat-page > div > #ribbon > span.marquee {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-page > div > #ribbon > span.marquee > span {
|
||||||
|
transform: rotate(270deg);
|
||||||
|
transform-origin: left;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
bottom: -10px;
|
||||||
|
left: calc(var(--control-height) / 2);
|
||||||
|
|
||||||
|
height: var(--control-height);
|
||||||
|
min-width: 100vh;
|
||||||
|
|
||||||
|
overflow: visible;
|
||||||
|
text-overflow: visible;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--gap-between-tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-page > div > #ribbon > span.marquee > span > * {
|
||||||
|
animation: slide-up var(--animation-duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-page > div > #ribbon > .navigation-buttons {
|
||||||
|
min-height: calc(var(--control-height) * 4);
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#chat-page > div > #ribbon button,
|
#chat-page > div > #ribbon button,
|
||||||
#chat-page > div > #main > div > .pane-wrapper > .pane > .toolbar button {
|
#chat-page > div > #main > div > .pane-wrapper > .pane > .toolbar button {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
|||||||
+18
-1
@@ -34,6 +34,21 @@ export function ChatPage(chatViewModel: ChatViewModel) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const marqueeContent = React.createProxyState(
|
||||||
|
[chatViewModel.notificationViewModel.marquee],
|
||||||
|
() => {
|
||||||
|
const value = chatViewModel.notificationViewModel.marquee.value;
|
||||||
|
if (value == undefined) return <span></span>;
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<b>{value.sender}</b>
|
||||||
|
<span class="secondary">{value.chat}: </span>
|
||||||
|
<span>{value.body}</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article
|
<article
|
||||||
id="chat-page"
|
id="chat-page"
|
||||||
@@ -63,7 +78,9 @@ export function ChatPage(chatViewModel: ChatViewModel) {
|
|||||||
<span class="icon">signal_disconnected</span>
|
<span class="icon">signal_disconnected</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<span>
|
<span class="marquee" children:set={marqueeContent}></span>
|
||||||
|
|
||||||
|
<span class="navigation-buttons">
|
||||||
{ChatViewToggleButton(
|
{ChatViewToggleButton(
|
||||||
translations.chatPage.pages.calendar,
|
translations.chatPage.pages.calendar,
|
||||||
"calendar_month",
|
"calendar_month",
|
||||||
|
|||||||
@@ -8,11 +8,14 @@ import { IndexManager } from "../../Model/Utility/utility";
|
|||||||
import SettingsViewModel from "../Global/settingsViewModel";
|
import SettingsViewModel from "../Global/settingsViewModel";
|
||||||
import StorageModel from "../../Model/Global/storageModel";
|
import StorageModel from "../../Model/Global/storageModel";
|
||||||
import ConnectionViewModel from "../Global/connectionViewModel";
|
import ConnectionViewModel from "../Global/connectionViewModel";
|
||||||
|
import NotificationViewModel from "../Global/notificationViewModel";
|
||||||
|
import NotificationModel from "../../Model/Global/notificationModel";
|
||||||
|
|
||||||
export default class ChatListViewModel {
|
export default class ChatListViewModel {
|
||||||
storageModel: StorageModel;
|
storageModel: StorageModel;
|
||||||
chatListModel: ChatListModel;
|
chatListModel: ChatListModel;
|
||||||
settingsViewModel: SettingsViewModel;
|
settingsViewModel: SettingsViewModel;
|
||||||
|
notificationViewModel: NotificationViewModel;
|
||||||
connectionViewModel: ConnectionViewModel;
|
connectionViewModel: ConnectionViewModel;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
@@ -63,6 +66,7 @@ export default class ChatListViewModel {
|
|||||||
this.storageModel,
|
this.storageModel,
|
||||||
chatModel,
|
chatModel,
|
||||||
this.settingsViewModel,
|
this.settingsViewModel,
|
||||||
|
this.notificationViewModel,
|
||||||
this.connectionViewModel,
|
this.connectionViewModel,
|
||||||
this,
|
this,
|
||||||
);
|
);
|
||||||
@@ -105,6 +109,7 @@ export default class ChatListViewModel {
|
|||||||
this.storageModel = storageModel;
|
this.storageModel = storageModel;
|
||||||
this.chatListModel = chatListModel;
|
this.chatListModel = chatListModel;
|
||||||
this.settingsViewModel = settingsViewModel;
|
this.settingsViewModel = settingsViewModel;
|
||||||
|
this.notificationViewModel = new NotificationViewModel(this);
|
||||||
this.connectionViewModel = connectionViewModel;
|
this.connectionViewModel = connectionViewModel;
|
||||||
|
|
||||||
this.loadChats();
|
this.loadChats();
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ import SettingsViewModel from "../Global/settingsViewModel";
|
|||||||
import TaskPageViewModel from "../Pages/taskPageViewModel";
|
import TaskPageViewModel from "../Pages/taskPageViewModel";
|
||||||
import { translations } from "../../View/translations";
|
import { translations } from "../../View/translations";
|
||||||
import ConnectionViewModel from "../Global/connectionViewModel";
|
import ConnectionViewModel from "../Global/connectionViewModel";
|
||||||
|
import NotificationViewModel from "../Global/notificationViewModel";
|
||||||
|
|
||||||
export default class ChatViewModel {
|
export default class ChatViewModel {
|
||||||
chatModel: ChatModel;
|
chatModel: ChatModel;
|
||||||
storageModel: StorageModel;
|
storageModel: StorageModel;
|
||||||
settingsViewModel: SettingsViewModel;
|
settingsViewModel: SettingsViewModel;
|
||||||
|
notificationViewModel: NotificationViewModel;
|
||||||
connectionViewModel: ConnectionViewModel;
|
connectionViewModel: ConnectionViewModel;
|
||||||
chatListViewModel: ChatListViewModel;
|
chatListViewModel: ChatListViewModel;
|
||||||
|
|
||||||
@@ -53,7 +55,7 @@ export default class ChatViewModel {
|
|||||||
this.chatListViewModel.closeChat();
|
this.chatListViewModel.closeChat();
|
||||||
};
|
};
|
||||||
|
|
||||||
closeSubPages = (): void => { };
|
closeSubPages = (): void => {};
|
||||||
|
|
||||||
setColor = (color: Color): void => {
|
setColor = (color: Color): void => {
|
||||||
this.setDisplayedColor(color);
|
this.setDisplayedColor(color);
|
||||||
@@ -104,12 +106,12 @@ export default class ChatViewModel {
|
|||||||
this.chatModel.setReadStatus(false);
|
this.chatModel.setReadStatus(false);
|
||||||
}
|
}
|
||||||
this.hasUnreadMessages.value = this.chatModel.info.hasUnreadMessages;
|
this.hasUnreadMessages.value = this.chatModel.info.hasUnreadMessages;
|
||||||
}
|
};
|
||||||
|
|
||||||
setReadStatus = (hasUnreadMessages: boolean): void => {
|
setReadStatus = (hasUnreadMessages: boolean): void => {
|
||||||
this.chatModel.setReadStatus(hasUnreadMessages);
|
this.chatModel.setReadStatus(hasUnreadMessages);
|
||||||
this.hasUnreadMessages.value = hasUnreadMessages;
|
this.hasUnreadMessages.value = hasUnreadMessages;
|
||||||
}
|
};
|
||||||
|
|
||||||
// init
|
// init
|
||||||
constructor(
|
constructor(
|
||||||
@@ -117,6 +119,7 @@ export default class ChatViewModel {
|
|||||||
storageModel: StorageModel,
|
storageModel: StorageModel,
|
||||||
chatModel: ChatModel,
|
chatModel: ChatModel,
|
||||||
settingsViewModel: SettingsViewModel,
|
settingsViewModel: SettingsViewModel,
|
||||||
|
notificationViewModel: NotificationViewModel,
|
||||||
connectionViewModel: ConnectionViewModel,
|
connectionViewModel: ConnectionViewModel,
|
||||||
chatListViewModel: ChatListViewModel,
|
chatListViewModel: ChatListViewModel,
|
||||||
) {
|
) {
|
||||||
@@ -125,6 +128,7 @@ export default class ChatViewModel {
|
|||||||
this.chatModel = chatModel;
|
this.chatModel = chatModel;
|
||||||
this.settingsViewModel = settingsViewModel;
|
this.settingsViewModel = settingsViewModel;
|
||||||
this.connectionViewModel = connectionViewModel;
|
this.connectionViewModel = connectionViewModel;
|
||||||
|
this.notificationViewModel = notificationViewModel;
|
||||||
this.chatListViewModel = chatListViewModel;
|
this.chatListViewModel = chatListViewModel;
|
||||||
|
|
||||||
// page viewModels
|
// page viewModels
|
||||||
@@ -155,6 +159,8 @@ export default class ChatViewModel {
|
|||||||
(chatMessage: ChatMessage) => {
|
(chatMessage: ChatMessage) => {
|
||||||
this.messagePageViewModel.showChatMessage(chatMessage);
|
this.messagePageViewModel.showChatMessage(chatMessage);
|
||||||
this.updateReadStatus();
|
this.updateReadStatus();
|
||||||
|
|
||||||
|
this.notificationViewModel.showNotification(chatMessage);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import * as React from "bloatless-react";
|
||||||
|
import ChatModel, { ChatMessage } from "../../Model/Chat/chatModel";
|
||||||
|
import ChatListViewModel from "../Chat/chatListViewModel";
|
||||||
|
|
||||||
|
export default class NotificationViewModel {
|
||||||
|
chatListViewModel: ChatListViewModel;
|
||||||
|
|
||||||
|
// data
|
||||||
|
seenMessageIds = new Set<string>();
|
||||||
|
messagesInMarquee: Notification[] = [];
|
||||||
|
marquee = new React.State<Notification | undefined>(undefined);
|
||||||
|
currentIndex = 0;
|
||||||
|
interval: number | undefined = undefined;
|
||||||
|
|
||||||
|
// main
|
||||||
|
showNotification = (message: ChatMessage): void => {
|
||||||
|
const notification = NotificationViewModel.createNotification(message);
|
||||||
|
if (this.seenMessageIds.has(message.id)) return;
|
||||||
|
|
||||||
|
const currentChat = this.chatListViewModel.selectedChat.value.chatModel.info.primaryChannel;
|
||||||
|
if (notification.chat == currentChat) return;
|
||||||
|
|
||||||
|
this.messagesInMarquee.push(notification);
|
||||||
|
this.startLoop();
|
||||||
|
};
|
||||||
|
|
||||||
|
// loop
|
||||||
|
loop = () => {
|
||||||
|
if (this.messagesInMarquee.length == 0) {
|
||||||
|
this.marquee.value = undefined;
|
||||||
|
return this.stopLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
const notification = this.messagesInMarquee.shift();
|
||||||
|
this.seenMessageIds.delete(notification.messageId);
|
||||||
|
this.marquee.value = notification;
|
||||||
|
};
|
||||||
|
|
||||||
|
startLoop = () => {
|
||||||
|
if (this.interval != undefined) return;
|
||||||
|
|
||||||
|
this.loop();
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
this.loop();
|
||||||
|
}, 5000);
|
||||||
|
};
|
||||||
|
|
||||||
|
stopLoop = () => {
|
||||||
|
clearInterval(this.interval);
|
||||||
|
this.interval = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
// init
|
||||||
|
constructor(chatListViewModel: ChatListViewModel) {
|
||||||
|
this.chatListViewModel = chatListViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// util
|
||||||
|
static createNotification(message: ChatMessage): Notification {
|
||||||
|
return {
|
||||||
|
messageId: message.id,
|
||||||
|
chat: ChatModel.splitChannel(message.channel)[0],
|
||||||
|
sender: message.sender,
|
||||||
|
body: message.body,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Notification {
|
||||||
|
messageId: string;
|
||||||
|
chat: string;
|
||||||
|
sender: string;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
@@ -212,7 +212,7 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
this.showTask(taskFileContent);
|
this.showTask(taskFileContent);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// initiate
|
// initiate
|
||||||
this.showToday();
|
this.showToday();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -85,4 +85,4 @@ document
|
|||||||
ConnectionModal(connectionViewModel),
|
ConnectionModal(connectionViewModel),
|
||||||
DataTransferModalWrapper(connectionViewModel, fileTransferViewModel),
|
DataTransferModalWrapper(connectionViewModel, fileTransferViewModel),
|
||||||
StorageModal(storageViewModel),
|
StorageModal(storageViewModel),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user