-
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(messenger): redux and weshnet connection
- Loading branch information
1 parent
3814aa7
commit 05248ec
Showing
17 changed files
with
1,434 additions
and
11 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
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/config"; | ||
import { stringFromBytes } from "../../weshnet/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.error("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.error("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; | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.