-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: message redux and weshent connection
- Loading branch information
1 parent
3c2f18d
commit d17bab4
Showing
14 changed files
with
1,344 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
import { createSlice, PayloadAction } from "@reduxjs/toolkit"; | ||
import { uniqBy } from "lodash"; | ||
import moment from "moment"; | ||
|
||
import { | ||
ContactRequest, | ||
Conversation, | ||
MessageList, | ||
Message, | ||
CONVERSATION_TYPES, | ||
PeerItem, | ||
} from "./../../utils/types/message"; | ||
import { weshConfig } from "../../weshnet/client"; | ||
import { stringFromBytes } from "../../weshnet/client/utils"; | ||
import { RootState } from "../store"; | ||
|
||
export interface MessageState { | ||
isWeshConnected: boolean; | ||
peerList: PeerItem[]; | ||
contactInfo: { | ||
name: string; | ||
avatar: string; | ||
publicRendezvousSeed: string; | ||
shareLink: string; | ||
}; | ||
contactRequestList: ContactRequest[]; | ||
messageList: MessageList; | ||
conversationList: { | ||
[key: string]: Conversation; | ||
}; | ||
lastIds: { | ||
[key: string]: string; | ||
}; | ||
} | ||
|
||
const initialState: MessageState = { | ||
isWeshConnected: false, | ||
contactInfo: { | ||
name: "Anon", | ||
avatar: "", | ||
publicRendezvousSeed: "", | ||
shareLink: "", | ||
}, | ||
messageList: {}, | ||
contactRequestList: [], | ||
conversationList: {}, | ||
lastIds: {}, | ||
peerList: [], | ||
}; | ||
|
||
export const selectIsWeshConnected = (state: RootState) => | ||
state.message.isWeshConnected; | ||
|
||
export const selectContactInfo = (state: RootState) => | ||
state.message.contactInfo; | ||
|
||
export const selectMessageList = (groupPk: string) => (state: RootState) => | ||
state.message.messageList[groupPk] || []; | ||
|
||
export const selectPeerList = (state: RootState) => state.message.peerList; | ||
|
||
export const selectPeerListById = (id: string) => (state: RootState) => | ||
state.message.peerList.find((item) => item.id === id); | ||
|
||
export const selectLastIdByKey = (key: string) => (state: RootState) => | ||
state.message.lastIds[key]; | ||
|
||
export const selectMessageListByGroupPk = | ||
(groupPk: string) => | ||
(state: RootState): Message[] => | ||
Object.values(state.message.messageList[groupPk] || {}) | ||
.filter((item) => item.id) | ||
.sort( | ||
(a: Message, b: Message) => | ||
moment(b.timestamp).valueOf() - moment(a.timestamp).valueOf(), | ||
); | ||
|
||
export const selectLastMessageByGroupPk = | ||
(groupPk: string) => (state: RootState) => | ||
selectMessageListByGroupPk(groupPk)(state)[0]; | ||
|
||
export const selectLastContactMessageByGroupPk = | ||
(groupPk: string) => (state: RootState) => | ||
selectMessageListByGroupPk(groupPk)(state).filter( | ||
(item) => | ||
item.senderId !== stringFromBytes(weshConfig?.config?.accountPk), | ||
)[0]; | ||
|
||
export const selectContactRequestList = (state: RootState) => | ||
state.message.contactRequestList; | ||
|
||
export const selectConversationList = | ||
(conversationType: CONVERSATION_TYPES = CONVERSATION_TYPES.ACTIVE) => | ||
(state: RootState): Conversation[] => { | ||
switch (conversationType) { | ||
case CONVERSATION_TYPES.ALL: { | ||
return Object.values(state.message.conversationList); | ||
} | ||
case CONVERSATION_TYPES.ARCHIVED: { | ||
return Object.values(state.message.conversationList).filter( | ||
(conv) => conv.status === "archived", | ||
); | ||
} | ||
case CONVERSATION_TYPES.ACTIVE: | ||
default: | ||
return Object.values(state.message.conversationList).filter( | ||
(conv) => conv.status === "active", | ||
); | ||
} | ||
}; | ||
|
||
export const selectConversationById = | ||
(id: string) => | ||
(state: RootState): Conversation => | ||
state.message.conversationList[id]; | ||
|
||
const messageSlice = createSlice({ | ||
name: "message", | ||
initialState, | ||
reducers: { | ||
setIsWeshConnected: (state, action: PayloadAction<boolean>) => { | ||
state.isWeshConnected = action.payload; | ||
}, | ||
setMessageList: ( | ||
state, | ||
action: PayloadAction<{ groupPk: string; data: Message }>, | ||
) => { | ||
if (!state.messageList[action.payload.groupPk]) { | ||
state.messageList[action.payload.groupPk] = {}; | ||
} | ||
state.messageList[action.payload.groupPk][action.payload.data.id] = | ||
action.payload.data; | ||
}, | ||
setPeerList: (state, action: PayloadAction<PeerItem[]>) => { | ||
state.peerList = action.payload; | ||
}, | ||
updateMessageReaction: ( | ||
state, | ||
action: PayloadAction<{ groupPk: string; data: Message }>, | ||
) => { | ||
if (action.payload.data.parentId) { | ||
try { | ||
state.messageList[action.payload.groupPk][ | ||
action.payload.data?.parentId | ||
].reactions = uniqBy( | ||
[ | ||
...(state.messageList[action.payload.groupPk][ | ||
action.payload.data.parentId | ||
].reactions || []), | ||
action.payload.data, | ||
], | ||
"id", | ||
); | ||
} catch (err) { | ||
console.log("update reaction failed", err); | ||
} | ||
} | ||
}, | ||
setContactRequestList: ( | ||
state, | ||
action: PayloadAction<ContactRequest | ContactRequest[]>, | ||
) => { | ||
if (Array.isArray(action.payload)) { | ||
state.contactRequestList = action.payload; | ||
} else { | ||
state.contactRequestList = [ | ||
action.payload, | ||
...state.contactRequestList, | ||
]; | ||
} | ||
}, | ||
setConversationList: (state, action: PayloadAction<Conversation>) => { | ||
state.conversationList[action.payload.id] = action.payload; | ||
}, | ||
updateConversationById: ( | ||
state, | ||
action: PayloadAction<Partial<Conversation>>, | ||
) => { | ||
if (action.payload.id) { | ||
state.conversationList[action.payload.id] = { | ||
...(state.conversationList[action.payload.id] || {}), | ||
...action.payload, | ||
}; | ||
} | ||
}, | ||
setLastId: ( | ||
state, | ||
action: PayloadAction<{ key: string; value: string }>, | ||
) => { | ||
state.lastIds[action.payload.key] = action.payload.value; | ||
}, | ||
|
||
setContactInfo: ( | ||
state, | ||
action: PayloadAction<Partial<MessageState["contactInfo"]>>, | ||
) => { | ||
state.contactInfo = { ...state.contactInfo, ...action.payload }; | ||
}, | ||
}, | ||
}); | ||
|
||
export const { | ||
setMessageList, | ||
setContactRequestList, | ||
setConversationList, | ||
updateMessageReaction, | ||
setLastId, | ||
setContactInfo, | ||
updateConversationById, | ||
setPeerList, | ||
setIsWeshConnected, | ||
} = messageSlice.actions; | ||
|
||
export const messageReducer = messageSlice.reducer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export const isElectron = () => { | ||
try { | ||
const userAgent = navigator.userAgent.toLowerCase(); | ||
if (userAgent.indexOf(" electron/") > -1) { | ||
return true; | ||
} | ||
} catch (err) { | ||
console.log("isElectron err", err); | ||
} | ||
return false; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import { RemoteFileData } from "./files"; | ||
|
||
export type MessageType = | ||
| "message" | ||
| "accept-contact" | ||
| "reject-contact" | ||
| "group-invite" | ||
| "group-join" | ||
| "group-leave" | ||
| "group-create" | ||
| "reaction" | ||
| "contact-request" | ||
| "read"; | ||
|
||
export type MessageFriendsTabItem = "friends" | "request" | "addFriend"; | ||
|
||
export type ConversationType = "contact" | "group"; | ||
|
||
export interface MessageFileData extends RemoteFileData { | ||
type: string; | ||
} | ||
|
||
interface MessagePayload { | ||
files: MessageFileData[]; | ||
message: string; | ||
metadata?: { | ||
groupName?: string; | ||
group?: any; | ||
contact?: Contact; | ||
lastReadId?: string; | ||
lastReadBy?: string; | ||
}; | ||
} | ||
|
||
export interface Message { | ||
id: string; | ||
senderId: string; | ||
groupId: string; | ||
type: MessageType; | ||
payload?: MessagePayload; | ||
timestamp: string; | ||
parentId?: string; | ||
reactions?: any[]; | ||
isRead?: boolean; | ||
} | ||
|
||
export interface Contact { | ||
id: string; | ||
tokenId?: string; | ||
name: string; | ||
avatar: string; | ||
rdvSeed: string; | ||
peerId?: string; | ||
hasLeft?: boolean; | ||
} | ||
|
||
export interface Conversation { | ||
id: string; | ||
type: ConversationType; | ||
members: Contact[]; | ||
name: string; | ||
status: "active" | "archived" | "deleted" | "blocked"; | ||
lastReadIdByMe?: string; | ||
lastReadIdByContact?: string; | ||
} | ||
|
||
export interface MessageList { | ||
[key: string]: { [key: string]: Message }; | ||
} | ||
|
||
export interface ConversationList { | ||
[key: string]: Conversation[]; | ||
} | ||
|
||
export interface ContactRequest { | ||
id: string; | ||
contactId: string; | ||
rdvSeed: string; | ||
avatar: string; | ||
name: string; | ||
peerId?: string; | ||
} | ||
|
||
export interface ReplyTo { | ||
id: string; | ||
message: string; | ||
} | ||
|
||
export enum CONVERSATION_TYPES { | ||
ACTIVE = "Active Conversations", | ||
ALL = "All Conversations", | ||
ARCHIVED = "Archived Conversations", | ||
} | ||
|
||
export interface PeerItem { | ||
id: string; | ||
isActive: boolean; | ||
} |
Oops, something went wrong.