remodel
This commit is contained in:
+60
-28
@@ -3,46 +3,42 @@ import * as React from "bloatless-react";
|
|||||||
import { UDN, isConnected } from "./model";
|
import { UDN, isConnected } from "./model";
|
||||||
import { decryptString, encryptString } from "../cryptUtility";
|
import { decryptString, encryptString } from "../cryptUtility";
|
||||||
|
|
||||||
|
import { Message } from "udn-frontend";
|
||||||
import { senderName } from "./viewModel";
|
import { senderName } from "./viewModel";
|
||||||
import { storageKeys } from "../utility";
|
import { storageKeys } from "../utility";
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
// message
|
// message
|
||||||
export interface Message {
|
export interface ChatMessage {
|
||||||
channel: string;
|
channel: string;
|
||||||
sender: string;
|
sender: string;
|
||||||
body: string;
|
body: string;
|
||||||
isoDate: string;
|
isoDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Message {
|
|
||||||
constructor(
|
|
||||||
public channel: string,
|
|
||||||
public sender: string,
|
|
||||||
public body: string,
|
|
||||||
public isoDate: string
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// chat
|
// chat
|
||||||
export class Chat {
|
export class Chat {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
primaryChannel: React.State<string>;
|
isSubscribed = new React.State(false);
|
||||||
|
currentChannel = new React.State("");
|
||||||
|
|
||||||
|
primaryChannelInput: React.State<string>;
|
||||||
secondaryChannels: React.ListState<string>;
|
secondaryChannels: React.ListState<string>;
|
||||||
|
|
||||||
encryptionKey: React.State<string>;
|
encryptionKey: React.State<string>;
|
||||||
messages: React.ListState<Message>;
|
messages: React.ListState<ChatMessage>;
|
||||||
|
|
||||||
composingMessage: React.State<string>;
|
composingMessage: React.State<string>;
|
||||||
cannotSendMessage: React.State<boolean>;
|
|
||||||
|
|
||||||
newSecondaryChannelName: React.State<string>;
|
newSecondaryChannelName: React.State<string>;
|
||||||
|
|
||||||
|
cannotSendMessage: React.State<boolean>;
|
||||||
cannotAddSecondaryChannel: React.State<boolean>;
|
cannotAddSecondaryChannel: React.State<boolean>;
|
||||||
|
cannotSetChannel: React.State<boolean>;
|
||||||
|
|
||||||
// init
|
// init
|
||||||
constructor(id: string = React.UUID()) {
|
constructor(id: string = React.UUID()) {
|
||||||
this.primaryChannel = React.restoreState(
|
this.primaryChannelInput = React.restoreState(
|
||||||
storageKeys.primaryChannel(id),
|
storageKeys.primaryChannel(id),
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
@@ -60,16 +56,48 @@ export class Chat {
|
|||||||
this.newSecondaryChannelName = new React.State("");
|
this.newSecondaryChannelName = new React.State("");
|
||||||
|
|
||||||
this.cannotSendMessage = React.createProxyState(
|
this.cannotSendMessage = React.createProxyState(
|
||||||
[this.primaryChannel, this.composingMessage, isConnected],
|
[
|
||||||
|
this.primaryChannelInput,
|
||||||
|
this.composingMessage,
|
||||||
|
this.isSubscribed,
|
||||||
|
isConnected,
|
||||||
|
],
|
||||||
() =>
|
() =>
|
||||||
this.primaryChannel.value == "" ||
|
this.primaryChannelInput.value == "" ||
|
||||||
this.composingMessage.value == "" ||
|
this.composingMessage.value == "" ||
|
||||||
|
this.isSubscribed.value == false ||
|
||||||
isConnected.value == false
|
isConnected.value == false
|
||||||
);
|
);
|
||||||
this.cannotAddSecondaryChannel = React.createProxyState(
|
this.cannotAddSecondaryChannel = React.createProxyState(
|
||||||
[this.newSecondaryChannelName],
|
[this.newSecondaryChannelName],
|
||||||
() => this.newSecondaryChannelName.value == ""
|
() => this.newSecondaryChannelName.value == ""
|
||||||
);
|
);
|
||||||
|
this.cannotSetChannel = React.createProxyState(
|
||||||
|
[this.primaryChannelInput, this.currentChannel],
|
||||||
|
() =>
|
||||||
|
this.primaryChannelInput.value == "" ||
|
||||||
|
this.primaryChannelInput.value == this.currentChannel.value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlers
|
||||||
|
onmessage(data: Message): void {
|
||||||
|
if (data.messageChannel && data.messageChannel != this.currentChannel.value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data.subscribed != undefined) this.handleSubscription(data.subscribed);
|
||||||
|
|
||||||
|
if (!data.messageBody) return;
|
||||||
|
const { sender, body, channel, isoDate } = JSON.parse(data.messageBody);
|
||||||
|
this.handleMessage({ sender, body, channel, isoDate });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubscription(isSubscribed: boolean): void {
|
||||||
|
this.isSubscribed.value = isSubscribed;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMessage(chatMessage: ChatMessage): void {
|
||||||
|
this.messages.add(chatMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// messages
|
// messages
|
||||||
@@ -81,7 +109,7 @@ export class Chat {
|
|||||||
...this.secondaryChannels.value.values(),
|
...this.secondaryChannels.value.values(),
|
||||||
].map((channel) => channel);
|
].map((channel) => channel);
|
||||||
const allChannelNames: string[] = [
|
const allChannelNames: string[] = [
|
||||||
this.primaryChannel.value,
|
this.primaryChannelInput.value,
|
||||||
...secondaryChannelNames,
|
...secondaryChannelNames,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -95,12 +123,12 @@ export class Chat {
|
|||||||
|
|
||||||
// create object
|
// create object
|
||||||
const joinedChannelName = allChannelNames.join("/");
|
const joinedChannelName = allChannelNames.join("/");
|
||||||
const messageObject = new Message(
|
const messageObject: ChatMessage = {
|
||||||
joinedChannelName,
|
channel: joinedChannelName,
|
||||||
senderName.value,
|
sender: senderName.value,
|
||||||
encrypted,
|
body: encrypted,
|
||||||
new Date().toISOString()
|
isoDate: new Date().toISOString(),
|
||||||
);
|
};
|
||||||
const messageString = JSON.stringify(messageObject);
|
const messageString = JSON.stringify(messageObject);
|
||||||
|
|
||||||
// send
|
// send
|
||||||
@@ -114,17 +142,21 @@ export class Chat {
|
|||||||
this.messages.clear();
|
this.messages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteMessage(message: Message): void {
|
deleteMessage(message: ChatMessage): void {
|
||||||
this.messages.remove(message);
|
this.messages.remove(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
async decryptReceivedMessage(message: Message): Promise<void> {
|
async decryptReceivedMessage(message: ChatMessage): Promise<void> {
|
||||||
message.body = await decryptString(message.body, this.encryptionKey.value);
|
message.body = await decryptString(message.body, this.encryptionKey.value);
|
||||||
this.messages.callSubscriptions();
|
this.messages.callSubscriptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
// channel
|
// channel
|
||||||
setChannel(): void {}
|
setChannel(): void {
|
||||||
|
if (this.cannotSetChannel.value == true) return;
|
||||||
|
this.currentChannel.value = this.primaryChannelInput.value;
|
||||||
|
UDN.subscribe(this.currentChannel.value);
|
||||||
|
}
|
||||||
|
|
||||||
addSecondaryChannel(): void {
|
addSecondaryChannel(): void {
|
||||||
if (this.cannotAddSecondaryChannel.value == true) return;
|
if (this.cannotAddSecondaryChannel.value == true) return;
|
||||||
@@ -146,7 +178,7 @@ export const chats = new React.ListState<Chat>(chatArray);
|
|||||||
// METHODS
|
// METHODS
|
||||||
export function createChatWithName(name: string): void {
|
export function createChatWithName(name: string): void {
|
||||||
const newChat = new Chat();
|
const newChat = new Chat();
|
||||||
newChat.primaryChannel.value = name;
|
newChat.primaryChannelInput.value = name;
|
||||||
chatIds.add(newChat.id);
|
chatIds.add(newChat.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-11
@@ -1,17 +1,8 @@
|
|||||||
import * as React from "bloatless-react";
|
import * as React from "bloatless-react";
|
||||||
|
|
||||||
import {
|
|
||||||
arrayToUint8,
|
|
||||||
decrypt,
|
|
||||||
encrypt,
|
|
||||||
generateIV,
|
|
||||||
importKey,
|
|
||||||
uInt8ToArray,
|
|
||||||
} from "../cryptUtility";
|
|
||||||
|
|
||||||
import UDNFrontend from "udn-frontend";
|
import UDNFrontend from "udn-frontend";
|
||||||
|
import { chats } from "./chatModel";
|
||||||
import { serverAddress } from "./viewModel";
|
import { serverAddress } from "./viewModel";
|
||||||
import { translation } from "../translations";
|
|
||||||
|
|
||||||
export const UDN = new UDNFrontend();
|
export const UDN = new UDNFrontend();
|
||||||
|
|
||||||
@@ -52,7 +43,9 @@ UDN.onconnect = () => {
|
|||||||
|
|
||||||
|
|
||||||
UDN.onmessage = (data) => {
|
UDN.onmessage = (data) => {
|
||||||
|
chats.value.forEach((chat) => {
|
||||||
|
chat.onmessage(data);
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
UDN.ondisconnect = () => {
|
UDN.ondisconnect = () => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as React from "bloatless-react";
|
import * as React from "bloatless-react";
|
||||||
|
|
||||||
|
import { Chat } from "./chatModel";
|
||||||
import { translation } from "../translations";
|
import { translation } from "../translations";
|
||||||
|
|
||||||
// connection
|
// connection
|
||||||
@@ -16,6 +17,4 @@ export const isEncryptionUnavailable = window.crypto.subtle == undefined;
|
|||||||
export const senderName = React.restoreState("sender-name", "");
|
export const senderName = React.restoreState("sender-name", "");
|
||||||
|
|
||||||
// chat
|
// chat
|
||||||
export const newChatPrimaryChannelName = new React.State("");
|
export const selectedChat = new React.State<Chat | undefined>(undefined);
|
||||||
export const newChatSecondaryChannelName = new React.State("");
|
|
||||||
export const newChatSecondaryChannelNames = new React.ListState<string>();
|
|
||||||
|
|||||||
Reference in New Issue
Block a user