refactor: rename contact with user
This commit is contained in:
Vendored
+2
-2
@@ -8,8 +8,8 @@ const tables = [
|
||||
description: "store channel list"
|
||||
},
|
||||
{
|
||||
storeName: "contacts",
|
||||
description: "store contact list"
|
||||
storeName: "users",
|
||||
description: "store user list"
|
||||
},
|
||||
{
|
||||
storeName: "messageDM",
|
||||
|
||||
Vendored
+5
-5
@@ -6,7 +6,7 @@ import { fullfillMessage } from "../slices/message";
|
||||
import { fullfillChannelMsg } from "../slices/message.channel";
|
||||
import { fullfillUserMsg } from "../slices/message.user";
|
||||
import { fullfillChannels } from "../slices/channels";
|
||||
import { fullfillContacts } from "../slices/contacts";
|
||||
import { fullfillContacts } from "../slices/users";
|
||||
import { fullfillFootprint } from "../slices/footprint";
|
||||
import { fullfillFileMessage } from "../slices/message.file";
|
||||
import { fullfillUI } from "../slices/ui";
|
||||
@@ -17,7 +17,7 @@ const useRehydrate = () => {
|
||||
const rehydrate = async () => {
|
||||
const rehydrateData = {
|
||||
channels: [],
|
||||
contacts: [],
|
||||
users: [],
|
||||
fileMessage: {},
|
||||
channelMessage: {},
|
||||
userMessage: {},
|
||||
@@ -38,9 +38,9 @@ const useRehydrate = () => {
|
||||
rehydrateData.channels.push(data);
|
||||
}
|
||||
break;
|
||||
case "contacts":
|
||||
case "users":
|
||||
if (data) {
|
||||
rehydrateData.contacts.push(data);
|
||||
rehydrateData.users.push(data);
|
||||
}
|
||||
break;
|
||||
case "footprint":
|
||||
@@ -75,7 +75,7 @@ const useRehydrate = () => {
|
||||
})
|
||||
);
|
||||
batch(() => {
|
||||
dispatch(fullfillContacts(rehydrateData.contacts));
|
||||
dispatch(fullfillContacts(rehydrateData.users));
|
||||
dispatch(fullfillServer(rehydrateData.server));
|
||||
console.log("fullfill channels from indexedDB");
|
||||
dispatch(fullfillChannels(rehydrateData.channels));
|
||||
|
||||
+4
-4
@@ -1,17 +1,17 @@
|
||||
import clearTable from "./clear.handler";
|
||||
|
||||
export default async function handler({ operation, data, payload }) {
|
||||
const table = window.CACHE["contacts"];
|
||||
const table = window.CACHE["users"];
|
||||
if (operation.startsWith("reset")) {
|
||||
clearTable("contacts");
|
||||
clearTable("users");
|
||||
return;
|
||||
}
|
||||
switch (operation) {
|
||||
case "fullfillContacts":
|
||||
{
|
||||
const contacts = payload;
|
||||
const users = payload;
|
||||
await Promise.all(
|
||||
contacts.map(({ uid, ...rest }) => {
|
||||
users.map(({ uid, ...rest }) => {
|
||||
return table.setItem(uid + "", { uid, ...rest });
|
||||
})
|
||||
);
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createListenerMiddleware } from "@reduxjs/toolkit";
|
||||
import rtkqHandler from "./handler.rtkq";
|
||||
import channelsHandler from "./handler.channels";
|
||||
import contactsHandler from "./handler.contacts";
|
||||
import usersHandler from "./handler.users";
|
||||
import channelMsgHandler from "./handler.channel.msg";
|
||||
import dmMsgHandler from "./handler.dm.msg";
|
||||
import serverHandler from "./handler.server";
|
||||
@@ -15,7 +15,7 @@ const operations = [
|
||||
"__rtkq",
|
||||
"channels",
|
||||
"channelMessage",
|
||||
"contacts",
|
||||
"users",
|
||||
"userMessage",
|
||||
"reactionMessage",
|
||||
"fileMessage",
|
||||
@@ -65,9 +65,9 @@ listenerMiddleware.startListening({
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "contacts":
|
||||
case "users":
|
||||
{
|
||||
await contactsHandler({
|
||||
await usersHandler({
|
||||
operation,
|
||||
payload,
|
||||
data: state
|
||||
|
||||
@@ -3,6 +3,7 @@ import toast from "react-hot-toast";
|
||||
import dayjs from "dayjs";
|
||||
import { updateToken, resetAuthData } from "../slices/auth.data";
|
||||
import BASE_URL, { tokenHeader } from "../config";
|
||||
import { RootState } from "../store";
|
||||
|
||||
const whiteList = [
|
||||
"login",
|
||||
@@ -28,7 +29,7 @@ const baseQuery = fetchBaseQuery({
|
||||
baseUrl: BASE_URL,
|
||||
prepareHeaders: (headers, { getState, endpoint }) => {
|
||||
console.log("req", endpoint);
|
||||
const { token } = getState().authData;
|
||||
const { token } = (getState() as RootState).authData;
|
||||
if (token && !whiteList.includes(endpoint)) {
|
||||
headers.set(tokenHeader, token);
|
||||
}
|
||||
|
||||
+12
-11
@@ -9,19 +9,20 @@ import { removeChannelSession } from "../slices/message.channel";
|
||||
import { removeReactionMessage } from "../slices/message.reaction";
|
||||
import { onMessageSendStarted } from "./handlers";
|
||||
import handleChatMessage from "../../common/hook/useStreaming/chat.handler";
|
||||
|
||||
import { Channel, CreateChannelDTO } from "../../types/channel";
|
||||
import { RootState } from "../store";
|
||||
export const channelApi = createApi({
|
||||
reducerPath: "channelApi",
|
||||
baseQuery,
|
||||
refetchOnFocus: true,
|
||||
endpoints: (builder) => ({
|
||||
getChannels: builder.query({
|
||||
getChannels: builder.query<Channel[], void>({
|
||||
query: () => ({ url: `group` })
|
||||
}),
|
||||
getChannel: builder.query({
|
||||
getChannel: builder.query<Channel, number>({
|
||||
query: (id) => ({ url: `group/${id}` })
|
||||
}),
|
||||
leaveChannel: builder.query({
|
||||
leaveChannel: builder.query<void, number>({
|
||||
query: (id) => ({ url: `group/${id}/leave` }),
|
||||
async onQueryStarted(gid, { dispatch, queryFulfilled }) {
|
||||
try {
|
||||
@@ -32,7 +33,7 @@ export const channelApi = createApi({
|
||||
}
|
||||
}
|
||||
}),
|
||||
createChannel: builder.mutation({
|
||||
createChannel: builder.mutation<number, CreateChannelDTO>({
|
||||
query: (data) => ({
|
||||
url: "group",
|
||||
method: "POST",
|
||||
@@ -66,7 +67,7 @@ export const channelApi = createApi({
|
||||
const { data: messages } = await queryFulfilled;
|
||||
if (messages?.length) {
|
||||
messages.forEach((msg) => {
|
||||
handleChatMessage(msg, dispatch, getState());
|
||||
handleChatMessage(msg, dispatch, getState() as RootState);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -80,15 +81,15 @@ export const channelApi = createApi({
|
||||
url: gid
|
||||
? `/group/create_reg_magic_link?expired_in=3600&max_times=1&gid=${gid}`
|
||||
: `/group/create_reg_magic_link?expired_in=3600&max_times=1`,
|
||||
responseHandler: (response) => response.text()
|
||||
responseHandler: (response: Response) => response.text()
|
||||
}),
|
||||
transformResponse: (link) => {
|
||||
transformResponse: (link: string) => {
|
||||
// 替换掉域名
|
||||
const invite = new URL(link);
|
||||
return `${location.origin}${invite.pathname}${invite.search}${invite.hash}`;
|
||||
}
|
||||
}),
|
||||
removeChannel: builder.query({
|
||||
removeChannel: builder.query<void, number>({
|
||||
query: (id) => ({
|
||||
url: `group/${id}`,
|
||||
method: "DELETE"
|
||||
@@ -99,7 +100,7 @@ export const channelApi = createApi({
|
||||
ui: {
|
||||
remeberedNavs: { chat: remeberedPath }
|
||||
}
|
||||
} = getState();
|
||||
} = getState() as RootState;
|
||||
try {
|
||||
await queryFulfilled;
|
||||
// 删掉该channel下的所有消息&reaction
|
||||
@@ -161,7 +162,7 @@ export const channelApi = createApi({
|
||||
await queryFulfilled;
|
||||
dispatch(
|
||||
updateChannel({
|
||||
id: gid,
|
||||
gid,
|
||||
icon: `${BASE_URL}/resource/group_avatar?gid=${gid}&t=${+new Date()}`
|
||||
})
|
||||
);
|
||||
|
||||
+24
-18
@@ -11,7 +11,16 @@ import { onMessageSendStarted } from "./handlers";
|
||||
import { normalizeArchiveData } from "../../common/utils";
|
||||
// import { updateMessage } from "../slices/message";
|
||||
import baseQuery from "./base.query";
|
||||
|
||||
import { OG } from "../../types/common";
|
||||
type UploadFileResponse = {
|
||||
path: string;
|
||||
size: number;
|
||||
hash: string;
|
||||
image_properties: {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
};
|
||||
export const messageApi = createApi({
|
||||
reducerPath: "messageApi",
|
||||
baseQuery,
|
||||
@@ -25,25 +34,22 @@ export const messageApi = createApi({
|
||||
method: "PUT",
|
||||
body: content
|
||||
})
|
||||
// async onQueryStarted({mid,content},{dispatch}){
|
||||
// dispatch()
|
||||
// }
|
||||
}),
|
||||
reactMessage: builder.mutation({
|
||||
reactMessage: builder.mutation<number, { mid: number; action: string }>({
|
||||
query: ({ mid, action }) => ({
|
||||
url: `/message/${mid}/like`,
|
||||
method: "PUT",
|
||||
body: { action }
|
||||
})
|
||||
}),
|
||||
deleteMessage: builder.query({
|
||||
deleteMessage: builder.query<number, number>({
|
||||
query: (mid) => ({
|
||||
url: `/message/${mid}`,
|
||||
method: "DELETE"
|
||||
})
|
||||
}),
|
||||
prepareUploadFile: builder.mutation({
|
||||
query: (meta = {}) => ({
|
||||
prepareUploadFile: builder.mutation<string, { content_type: string; filename: string }>({
|
||||
query: (meta = { content_type: "", filename: "" }) => ({
|
||||
url: `/resource/file/prepare`,
|
||||
method: "POST",
|
||||
body: meta
|
||||
@@ -56,21 +62,18 @@ export const messageApi = createApi({
|
||||
body: { mid_list: mids }
|
||||
})
|
||||
}),
|
||||
uploadFile: builder.mutation({
|
||||
uploadFile: builder.mutation<UploadFileResponse | {}, FormData>({
|
||||
query: (formData) => ({
|
||||
// headers: {
|
||||
// "content-type": ContentTypes.formData,
|
||||
// },
|
||||
url: `/resource/file/upload`,
|
||||
method: "POST",
|
||||
body: formData
|
||||
}),
|
||||
transformResponse: (data) => {
|
||||
transformResponse: (data: UploadFileResponse | null) => {
|
||||
console.log("upload file response", data);
|
||||
return data ? data : {};
|
||||
}
|
||||
}),
|
||||
getOGInfo: builder.query({
|
||||
getOGInfo: builder.query<OG, string>({
|
||||
query: (url) => ({
|
||||
url: `/resource/open_graphic_parse?url=${encodeURIComponent(url)}`
|
||||
})
|
||||
@@ -80,14 +83,14 @@ export const messageApi = createApi({
|
||||
url: `/resource/archive?file_path=${encodeURIComponent(file_path)}`
|
||||
})
|
||||
}),
|
||||
pinMessage: builder.mutation({
|
||||
pinMessage: builder.mutation<void, { gid: number; mid: number }>({
|
||||
query: ({ gid, mid }) => ({
|
||||
url: `/group/${gid}/pin`,
|
||||
method: "POST",
|
||||
body: { mid }
|
||||
})
|
||||
}),
|
||||
unpinMessage: builder.mutation({
|
||||
unpinMessage: builder.mutation<void, { gid: number; mid: number }>({
|
||||
query: ({ gid, mid }) => ({
|
||||
url: `/group/${gid}/unpin`,
|
||||
method: "POST",
|
||||
@@ -111,7 +114,7 @@ export const messageApi = createApi({
|
||||
}
|
||||
}
|
||||
}),
|
||||
removeFavorite: builder.query({
|
||||
removeFavorite: builder.query<void, number>({
|
||||
query: (id) => ({
|
||||
url: `/favorite/${id}`,
|
||||
method: "DELETE"
|
||||
@@ -170,7 +173,10 @@ export const messageApi = createApi({
|
||||
await onMessageSendStarted.call(this, param1, param2, param1.context);
|
||||
}
|
||||
}),
|
||||
readMessage: builder.mutation({
|
||||
readMessage: builder.mutation<
|
||||
void,
|
||||
{ users?: [{ uid: number; mid: number }]; groups?: [{ gid: number; mid: number }] }
|
||||
>({
|
||||
query: (data) => ({
|
||||
url: `/user/read-index`,
|
||||
method: "POST",
|
||||
|
||||
@@ -4,14 +4,14 @@ import { KEY_UID } from "../config";
|
||||
import baseQuery from "./base.query";
|
||||
import { resetAuthData } from "../slices/auth.data";
|
||||
import { updateMute } from "../slices/footprint";
|
||||
import { fullfillContacts } from "../slices/contacts";
|
||||
import { fullfillContacts } from "../slices/users";
|
||||
import BASE_URL, { ContentTypes } from "../config";
|
||||
import { onMessageSendStarted } from "./handlers";
|
||||
import handleChatMessage from "../../common/hook/useStreaming/chat.handler";
|
||||
import { User } from "../../types/auth";
|
||||
|
||||
export const contactApi = createApi({
|
||||
reducerPath: "contactApi",
|
||||
export const userApi = createApi({
|
||||
reducerPath: "userApi",
|
||||
baseQuery,
|
||||
endpoints: (builder) => ({
|
||||
getContacts: builder.query({
|
||||
@@ -30,21 +30,21 @@ export const contactApi = createApi({
|
||||
async onQueryStarted(data, { dispatch, queryFulfilled }) {
|
||||
const local_uid = localStorage.getItem(KEY_UID);
|
||||
try {
|
||||
const { data: contacts } = await queryFulfilled;
|
||||
const matchedUser = contacts.find((c) => c.uid == local_uid);
|
||||
console.log("wtf", contacts, matchedUser);
|
||||
const { data: users } = await queryFulfilled;
|
||||
const matchedUser = users.find((c) => c.uid == local_uid);
|
||||
console.log("wtf", users, matchedUser);
|
||||
if (!matchedUser) {
|
||||
// 用户已注销或被禁用
|
||||
console.log("no matched user, redirect to login");
|
||||
dispatch(resetAuthData());
|
||||
} else {
|
||||
const markedContacts = contacts.map((u) => {
|
||||
const markedContacts = users.map((u) => {
|
||||
return u.uid == matchedUser.uid ? { ...u, online: true } : u;
|
||||
});
|
||||
dispatch(fullfillContacts(markedContacts));
|
||||
}
|
||||
} catch {
|
||||
console.log("get contact list error");
|
||||
console.log("get user list error");
|
||||
}
|
||||
}
|
||||
}),
|
||||
@@ -135,4 +135,4 @@ export const {
|
||||
useGetContactsQuery,
|
||||
useLazyGetContactsQuery,
|
||||
useSendMsgMutation
|
||||
} = contactApi;
|
||||
} = userApi;
|
||||
@@ -18,7 +18,7 @@ export interface State {
|
||||
draftMixedText: { [key: string]: any };
|
||||
remeberedNavs: {
|
||||
chat: null | string;
|
||||
contact: null | string;
|
||||
user: null | string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ const initialState: State = {
|
||||
// todo: typo
|
||||
remeberedNavs: {
|
||||
chat: null,
|
||||
contact: null
|
||||
user: null
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -19,18 +19,18 @@ const initialState: State = {
|
||||
byId: {}
|
||||
};
|
||||
|
||||
const contactsSlice = createSlice({
|
||||
name: "contacts",
|
||||
const usersSlice = createSlice({
|
||||
name: "users",
|
||||
initialState,
|
||||
reducers: {
|
||||
resetContacts() {
|
||||
return initialState;
|
||||
},
|
||||
fullfillContacts(state, action: PayloadAction<StoredUser[]>) {
|
||||
const contacts = action.payload || [];
|
||||
state.ids = contacts.map(({ uid }) => uid);
|
||||
const users = action.payload || [];
|
||||
state.ids = users.map(({ uid }) => uid);
|
||||
state.byId = Object.fromEntries(
|
||||
contacts.map((c) => {
|
||||
users.map((c) => {
|
||||
const { uid } = c;
|
||||
return [uid, c];
|
||||
})
|
||||
@@ -100,5 +100,5 @@ const contactsSlice = createSlice({
|
||||
});
|
||||
|
||||
export const { resetContacts, fullfillContacts, updateUsersByLogs, updateUsersStatus } =
|
||||
contactsSlice.actions;
|
||||
export default contactsSlice.reducer;
|
||||
usersSlice.actions;
|
||||
export default usersSlice.reducer;
|
||||
+24
-24
@@ -1,24 +1,24 @@
|
||||
import { combineReducers, configureStore } from '@reduxjs/toolkit';
|
||||
import { setupListeners } from '@reduxjs/toolkit/query';
|
||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
|
||||
import listenerMiddleware from './listener.middleware';
|
||||
import authDataReducer from './slices/auth.data';
|
||||
import footprintReducer from './slices/footprint';
|
||||
import serverReducer from './slices/server';
|
||||
import uiReducer from './slices/ui';
|
||||
import channelsReducer from './slices/channels';
|
||||
import contactsReducer from './slices/contacts';
|
||||
import reactionMsgReducer from './slices/message.reaction';
|
||||
import channelMsgReducer from './slices/message.channel';
|
||||
import userMsgReducer from './slices/message.user';
|
||||
import favoritesReducer from './slices/favorites';
|
||||
import fileMsgReducer from './slices/message.file';
|
||||
import messageReducer from './slices/message';
|
||||
import { authApi } from './services/auth';
|
||||
import { contactApi } from './services/contact';
|
||||
import { channelApi } from './services/channel';
|
||||
import { messageApi } from './services/message';
|
||||
import { serverApi } from './services/server';
|
||||
import { combineReducers, configureStore } from "@reduxjs/toolkit";
|
||||
import { setupListeners } from "@reduxjs/toolkit/query";
|
||||
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
|
||||
import listenerMiddleware from "./listener.middleware";
|
||||
import authDataReducer from "./slices/auth.data";
|
||||
import footprintReducer from "./slices/footprint";
|
||||
import serverReducer from "./slices/server";
|
||||
import uiReducer from "./slices/ui";
|
||||
import channelsReducer from "./slices/channels";
|
||||
import usersReducer from "./slices/users";
|
||||
import reactionMsgReducer from "./slices/message.reaction";
|
||||
import channelMsgReducer from "./slices/message.channel";
|
||||
import userMsgReducer from "./slices/message.user";
|
||||
import favoritesReducer from "./slices/favorites";
|
||||
import fileMsgReducer from "./slices/message.file";
|
||||
import messageReducer from "./slices/message";
|
||||
import { authApi } from "./services/auth";
|
||||
import { userApi } from "./services/user";
|
||||
import { channelApi } from "./services/channel";
|
||||
import { messageApi } from "./services/message";
|
||||
import { serverApi } from "./services/server";
|
||||
|
||||
const reducer = combineReducers({
|
||||
authData: authDataReducer,
|
||||
@@ -26,7 +26,7 @@ const reducer = combineReducers({
|
||||
footprint: footprintReducer,
|
||||
server: serverReducer,
|
||||
favorites: favoritesReducer,
|
||||
contacts: contactsReducer,
|
||||
users: usersReducer,
|
||||
channels: channelsReducer,
|
||||
reactionMessage: reactionMsgReducer,
|
||||
userMessage: userMsgReducer,
|
||||
@@ -35,7 +35,7 @@ const reducer = combineReducers({
|
||||
message: messageReducer,
|
||||
[authApi.reducerPath]: authApi.reducer,
|
||||
[messageApi.reducerPath]: messageApi.reducer,
|
||||
[contactApi.reducerPath]: contactApi.reducer,
|
||||
[userApi.reducerPath]: userApi.reducer,
|
||||
[channelApi.reducerPath]: channelApi.reducer,
|
||||
[serverApi.reducerPath]: serverApi.reducer
|
||||
});
|
||||
@@ -46,7 +46,7 @@ const store = configureStore({
|
||||
getDefaultMiddleware()
|
||||
.concat(
|
||||
authApi.middleware,
|
||||
contactApi.middleware,
|
||||
userApi.middleware,
|
||||
channelApi.middleware,
|
||||
serverApi.middleware,
|
||||
messageApi.middleware
|
||||
|
||||
|
Before Width: | Height: | Size: 669 B After Width: | Height: | Size: 669 B |
@@ -6,7 +6,7 @@ import IconInvite from "../../assets/icons/add.person.svg";
|
||||
import IconMention from "../../assets/icons/mention.svg";
|
||||
import ChannelIcon from "./ChannelIcon";
|
||||
import ChannelModal from "./ChannelModal";
|
||||
import ContactsModal from "./ContactsModal";
|
||||
import ContactsModal from "./UsersModal";
|
||||
import InviteModal from "./InviteModal";
|
||||
|
||||
const Styled = styled.ul`
|
||||
@@ -47,7 +47,7 @@ export default function AddEntriesMenu() {
|
||||
const [inviteModalVisible, setInviteModalVisible] = useState(false);
|
||||
|
||||
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
||||
const [contactsModalVisible, setContactsModalVisible] = useState(false);
|
||||
const [usersModalVisible, setContactsModalVisible] = useState(false);
|
||||
const toggleInviteModalVisible = () => {
|
||||
setInviteModalVisible((prev) => {
|
||||
if (!prev) {
|
||||
@@ -96,7 +96,7 @@ export default function AddEntriesMenu() {
|
||||
</li>
|
||||
</Styled>
|
||||
{channelModalVisible && <ChannelModal personal={isPrivate} closeModal={handleCloseModal} />}
|
||||
{contactsModalVisible && <ContactsModal closeModal={toggleContactsModalVisible} />}
|
||||
{usersModalVisible && <ContactsModal closeModal={toggleContactsModalVisible} />}
|
||||
{inviteModalVisible && <InviteModal closeModal={toggleInviteModalVisible} />}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import IconChat from "../../assets/icons/placeholder.chat.svg";
|
||||
import IconAsk from "../../assets/icons/placeholder.question.svg";
|
||||
import IconInvite from "../../assets/icons/placeholder.invite.svg";
|
||||
import IconDownload from "../../assets/icons/placeholder.download.svg";
|
||||
import ContactsModal from "./ContactsModal";
|
||||
import ContactsModal from "./UsersModal";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
const Styled = styled.div`
|
||||
@@ -75,7 +75,7 @@ const BlankPlaceholder: FC<Props> = ({ type = "chat" }) => {
|
||||
const server = useAppSelector((store) => store.server);
|
||||
const [inviteModalVisible, setInviteModalVisible] = useState(false);
|
||||
const [createChannelVisible, setCreateChannelVisible] = useState(false);
|
||||
const [contactListVisible, setContactListVisible] = useState(false);
|
||||
const [userListVisible, setContactListVisible] = useState(false);
|
||||
const toggleChannelModalVisible = () => {
|
||||
setCreateChannelVisible((prev) => !prev);
|
||||
};
|
||||
@@ -121,7 +121,7 @@ const BlankPlaceholder: FC<Props> = ({ type = "chat" }) => {
|
||||
{createChannelVisible && (
|
||||
<ChannelModal personal={true} closeModal={toggleChannelModalVisible} />
|
||||
)}
|
||||
{contactListVisible && <ContactsModal closeModal={toggleContactListVisible} />}
|
||||
{userListVisible && <ContactsModal closeModal={toggleContactListVisible} />}
|
||||
{inviteModalVisible && <InviteModal closeModal={toggleInviteModalVisible} />}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -58,7 +58,7 @@ const Channel: FC<Props> = ({ interactive = true, id, compact = false, avatarSiz
|
||||
const { channel, totalMemberCount } = useAppSelector((store) => {
|
||||
return {
|
||||
channel: store.channels.byId[id],
|
||||
totalMemberCount: store.contacts.ids.length
|
||||
totalMemberCount: store.users.ids.length
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useNavigate } from "react-router-dom";
|
||||
import Modal from "../Modal";
|
||||
import Button from "../styled/Button";
|
||||
import ChannelIcon from "../ChannelIcon";
|
||||
import Contact from "../Contact";
|
||||
import User from "../User";
|
||||
import StyledWrapper from "./styled";
|
||||
import StyledCheckbox from "../styled/Checkbox";
|
||||
import StyledToggle from "../../component/styled/Toggle";
|
||||
@@ -19,8 +19,8 @@ interface Props {
|
||||
}
|
||||
|
||||
const ChannelModal: FC<Props> = ({ personal = false, closeModal }) => {
|
||||
const { contactsData, loginUid } = useAppSelector((store) => {
|
||||
return { contactsData: store.contacts.byId, loginUid: store.authData.user?.uid };
|
||||
const { usersData, loginUid } = useAppSelector((store) => {
|
||||
return { usersData: store.users.byId, loginUid: store.authData.user?.uid };
|
||||
});
|
||||
const navigateTo = useNavigate();
|
||||
const [data, setData] = useState<CreateChannelDTO>({
|
||||
@@ -30,7 +30,7 @@ const ChannelModal: FC<Props> = ({ personal = false, closeModal }) => {
|
||||
is_public: !personal
|
||||
});
|
||||
|
||||
const { contacts, input, updateInput } = useFilteredUsers();
|
||||
const { users, input, updateInput } = useFilteredUsers();
|
||||
const [createChannel, { isSuccess, isError, isLoading, data: newChannelId }] =
|
||||
useCreateChannelMutation();
|
||||
|
||||
@@ -85,7 +85,7 @@ const ChannelModal: FC<Props> = ({ personal = false, closeModal }) => {
|
||||
};
|
||||
|
||||
if (!loginUid) return null;
|
||||
const loginUser = contactsData[Number(loginUid)];
|
||||
const loginUser = usersData[Number(loginUid)];
|
||||
if (!loginUser) return null;
|
||||
const { name, members, is_public } = data;
|
||||
|
||||
@@ -101,9 +101,9 @@ const ChannelModal: FC<Props> = ({ personal = false, closeModal }) => {
|
||||
placeholder="Type Username to search"
|
||||
/>
|
||||
</div>
|
||||
{contacts && (
|
||||
{users && (
|
||||
<ul className="users">
|
||||
{contacts.map((u) => {
|
||||
{users.map((u) => {
|
||||
const { uid } = u;
|
||||
const checked = members ? members.includes(uid) : false;
|
||||
return (
|
||||
@@ -120,7 +120,7 @@ const ChannelModal: FC<Props> = ({ personal = false, closeModal }) => {
|
||||
name="cb"
|
||||
id="cb"
|
||||
/>
|
||||
<Contact uid={uid} interactive={false} />
|
||||
<User uid={uid} interactive={false} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -84,7 +84,7 @@ const FileBox: FC<Props> = ({
|
||||
from_uid,
|
||||
content
|
||||
}) => {
|
||||
const fromUser = useAppSelector((store) => store.contacts.byId[from_uid]);
|
||||
const fromUser = useAppSelector((store) => store.users.byId[from_uid]);
|
||||
const icon = getFileIcon(file_type, name);
|
||||
if (!content || !fromUser || !name) return null;
|
||||
const previewContent = renderPreview({ file_type, content, name });
|
||||
|
||||
@@ -60,7 +60,7 @@ const FileMessage: FC<Props> = ({
|
||||
to
|
||||
});
|
||||
const { stopUploading, data, uploadFile, progress, isSuccess: uploadSuccess } = useUploadFile();
|
||||
const fromUser = useAppSelector((store) => store.contacts.byId[from_uid]);
|
||||
const fromUser = useAppSelector((store) => store.users.byId[from_uid]);
|
||||
const { size, name, content_type } = properties ?? {};
|
||||
useEffect(() => {
|
||||
const handleUpSend = async ({
|
||||
|
||||
@@ -4,7 +4,7 @@ import Modal from "../Modal";
|
||||
import Button from "../styled/Button";
|
||||
import Input from "../styled/Input";
|
||||
import Channel from "../Channel";
|
||||
import Contact from "../Contact";
|
||||
import User from "../User";
|
||||
// import Channel from "../Channel";
|
||||
import Reply from "../Message/Reply";
|
||||
import StyledWrapper from "./styled";
|
||||
@@ -27,7 +27,7 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
// input: channelInput,
|
||||
updateInput: updateChannelInput
|
||||
} = useFilteredChannels();
|
||||
const { contacts, input, updateInput } = useFilteredUsers();
|
||||
const { users, input, updateInput } = useFilteredUsers();
|
||||
const toggleCheck = ({ currentTarget }: MouseEvent<HTMLLIElement>) => {
|
||||
const { id, type = "user" } = currentTarget.dataset;
|
||||
const ids = type == "user" ? selectedMembers : selectedChannels;
|
||||
@@ -100,8 +100,8 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
{contacts &&
|
||||
contacts.map((u) => {
|
||||
{users &&
|
||||
users.map((u) => {
|
||||
const { uid } = u;
|
||||
const checked = selectedMembers.includes(uid);
|
||||
console.log({ checked });
|
||||
@@ -114,7 +114,7 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
onClick={toggleCheck}
|
||||
>
|
||||
<StyledCheckbox readOnly checked={checked} name="cb" id="cb" />
|
||||
<Contact uid={uid} interactive={false} />
|
||||
<User uid={uid} interactive={false} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
@@ -142,7 +142,7 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
{selectedMembers.map((uid) => {
|
||||
return (
|
||||
<li key={uid} className="item">
|
||||
<Contact
|
||||
<User
|
||||
key={uid}
|
||||
uid={uid}
|
||||
interactive={false}
|
||||
|
||||
@@ -56,7 +56,7 @@ const GithubLoginButton: FC<Props> = ({ type = "login", client_id }) => {
|
||||
switch (error.status) {
|
||||
case 410:
|
||||
toast.error(
|
||||
"No associated account found, please contact admin for an invitation link to join."
|
||||
"No associated account found, please user admin for an invitation link to join."
|
||||
);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -54,7 +54,7 @@ const GoogleLoginInner: FC<Props> = ({ type = "login", loaded, loadError }) => {
|
||||
switch (error.status) {
|
||||
case 410:
|
||||
toast.error(
|
||||
"No associated account found, please contact admin for an invitation link to join."
|
||||
"No associated account found, please user admin for an invitation link to join."
|
||||
);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -3,7 +3,7 @@ import styled from "styled-components";
|
||||
import toast from "react-hot-toast";
|
||||
import Button from "../styled/Button";
|
||||
import Input from "../styled/Input";
|
||||
import Contact from "../Contact";
|
||||
import User from "../User";
|
||||
import StyledCheckbox from "../styled/Checkbox";
|
||||
import { useAddMembersMutation } from "../../../app/services/channel";
|
||||
import CloseIcon from "../../../assets/icons/close.svg";
|
||||
@@ -105,10 +105,10 @@ interface Props {
|
||||
const AddMembers: FC<Props> = ({ cid, closeModal }) => {
|
||||
const [addMembers, { isLoading: isAdding, isSuccess }] = useAddMembersMutation();
|
||||
const [selects, setSelects] = useState([]);
|
||||
const { channel, contactData } = useAppSelector((store) => {
|
||||
const { channel, userData } = useAppSelector((store) => {
|
||||
return {
|
||||
channel: store.channels.byId[cid],
|
||||
contactData: store.contacts.byId
|
||||
userData: store.users.byId
|
||||
};
|
||||
});
|
||||
useEffect(() => {
|
||||
@@ -121,7 +121,7 @@ const AddMembers: FC<Props> = ({ cid, closeModal }) => {
|
||||
const handleAddMembers = () => {
|
||||
addMembers({ id: cid, members: selects });
|
||||
};
|
||||
const { input, updateInput, contacts = [] } = useFilteredUsers();
|
||||
const { input, updateInput, users = [] } = useFilteredUsers();
|
||||
|
||||
const toggleCheckMember = ({ currentTarget }: MouseEvent<SVGSVGElement | HTMLLIElement>) => {
|
||||
const { uid } = currentTarget.dataset;
|
||||
@@ -140,7 +140,7 @@ const AddMembers: FC<Props> = ({ cid, closeModal }) => {
|
||||
|
||||
if (!channel) return null;
|
||||
const { members: uids } = channel;
|
||||
const contactIds = contacts.map(({ uid }) => uid);
|
||||
const userIds = users.map(({ uid }) => uid);
|
||||
|
||||
return (
|
||||
<Styled>
|
||||
@@ -150,7 +150,7 @@ const AddMembers: FC<Props> = ({ cid, closeModal }) => {
|
||||
{selects.map((uid) => {
|
||||
return (
|
||||
<li className="select" key={uid}>
|
||||
{contactData[uid].name}
|
||||
{userData[uid].name}
|
||||
<CloseIcon data-uid={uid} onClick={toggleCheckMember} className="close" />
|
||||
</li>
|
||||
);
|
||||
@@ -166,7 +166,7 @@ const AddMembers: FC<Props> = ({ cid, closeModal }) => {
|
||||
{/* )} */}
|
||||
</div>
|
||||
<ul className="users">
|
||||
{contactIds.map((uid) => {
|
||||
{userIds.map((uid) => {
|
||||
const added = uids.includes(uid);
|
||||
return (
|
||||
<li
|
||||
@@ -182,7 +182,7 @@ const AddMembers: FC<Props> = ({ cid, closeModal }) => {
|
||||
name="cb"
|
||||
id="cb"
|
||||
/>
|
||||
<Contact uid={uid} interactive={false} />
|
||||
<User uid={uid} interactive={false} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -6,7 +6,7 @@ import Modal from "../Modal";
|
||||
import useLeaveChannel from "../../hook/useLeaveChannel";
|
||||
import StyledModal from "../styled/Modal";
|
||||
import Button from "../styled/Button";
|
||||
import Contact from "../Contact";
|
||||
import User from "../User";
|
||||
|
||||
const UserList = styled.ul`
|
||||
display: flex;
|
||||
@@ -97,7 +97,7 @@ const TransferOwnerModal: FC<Props> = ({ id, closeModal, withLeave = true }) =>
|
||||
className={`user ${uid == id ? "selected" : ""}`}
|
||||
onClick={handleSelectUser.bind(null, id)}
|
||||
>
|
||||
<Contact uid={id} interactive={false} />
|
||||
<User uid={id} interactive={false} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -3,8 +3,8 @@ import styled from "styled-components";
|
||||
import Tippy from "@tippyjs/react";
|
||||
import { hideAll } from "tippy.js";
|
||||
import toast from "react-hot-toast";
|
||||
import { useUpdateContactMutation } from "../../app/services/contact";
|
||||
import Contact from "./Contact";
|
||||
import { useUpdateContactMutation } from "../../app/services/user";
|
||||
import User from "./User";
|
||||
import StyledMenu from "./styled/Menu";
|
||||
import InviteLink from "./InviteLink";
|
||||
import moreIcon from "../../assets/icons/more.svg?url";
|
||||
@@ -119,9 +119,9 @@ interface Props {
|
||||
cid?: number;
|
||||
}
|
||||
const ManageMembers: FC<Props> = ({ cid }) => {
|
||||
const { contacts, channels, loginUser } = useAppSelector((store) => {
|
||||
const { users, channels, loginUser } = useAppSelector((store) => {
|
||||
return {
|
||||
contacts: store.contacts,
|
||||
users: store.users,
|
||||
channels: store.channels,
|
||||
loginUser: store.authData.user
|
||||
};
|
||||
@@ -141,7 +141,7 @@ const ManageMembers: FC<Props> = ({ cid }) => {
|
||||
updateContact({ id: uid, is_admin: isAdmin });
|
||||
};
|
||||
const channel = channels.byId[cid] ?? null;
|
||||
const uids = channel ? (channel.is_public ? contacts.ids : channel.members) : contacts.ids;
|
||||
const uids = channel ? (channel.is_public ? users.ids : channel.members) : users.ids;
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
@@ -154,7 +154,7 @@ const ManageMembers: FC<Props> = ({ cid }) => {
|
||||
</div>
|
||||
<ul className="members">
|
||||
{uids.map((uid) => {
|
||||
const { name, email, is_admin } = contacts.byId[uid];
|
||||
const { name, email, is_admin } = users.byId[uid];
|
||||
const owner = channel && channel.owner == uid;
|
||||
const switchRoleVisible = loginUser.is_admin && loginUser.uid !== uid;
|
||||
const dotsVisible = email || loginUser?.is_admin;
|
||||
@@ -164,7 +164,7 @@ const ManageMembers: FC<Props> = ({ cid }) => {
|
||||
return (
|
||||
<li key={uid} className="member">
|
||||
<div className="left">
|
||||
<Contact compact uid={uid} interactive={false} />
|
||||
<User compact uid={uid} interactive={false} />
|
||||
<div className="info">
|
||||
<span className="name">
|
||||
{name} {owner && <IconOwner />}
|
||||
|
||||
@@ -20,8 +20,8 @@ interface Props {
|
||||
}
|
||||
|
||||
const Mention: FC<Props> = ({ uid, popover = true, cid, textOnly = false }) => {
|
||||
const contactsData = useAppSelector((store) => store.contacts.byId);
|
||||
const user = contactsData[uid];
|
||||
const usersData = useAppSelector((store) => store.users.byId);
|
||||
const user = usersData[uid];
|
||||
if (!user) return null;
|
||||
if (textOnly) return `@${user.name}`;
|
||||
return (
|
||||
|
||||
@@ -10,12 +10,12 @@ interface Props {
|
||||
}
|
||||
|
||||
const PreviewMessage: FC<Props> = ({ mid = 0 }) => {
|
||||
const { msg, contactsData } = useAppSelector((store) => {
|
||||
return { msg: store.message[mid], contactsData: store.contacts.byId };
|
||||
const { msg, usersData } = useAppSelector((store) => {
|
||||
return { msg: store.message[mid], usersData: store.users.byId };
|
||||
});
|
||||
if (!msg) return null;
|
||||
const { from_uid, created_at, content_type, content, thumbnail, properties } = msg;
|
||||
const { name, avatar } = contactsData[from_uid];
|
||||
const { name, avatar } = usersData[from_uid];
|
||||
return (
|
||||
<StyledWrapper className={`preview`}>
|
||||
<div className="avatar">
|
||||
|
||||
@@ -106,9 +106,9 @@ const StyledDetails = styled.div`
|
||||
}
|
||||
`;
|
||||
const ReactionDetails = ({ uids = [], emoji, index }) => {
|
||||
const contactsData = useSelector((store) => store.contacts.byId);
|
||||
const usersData = useSelector((store) => store.users.byId);
|
||||
const names = uids.map((id) => {
|
||||
return contactsData[id]?.name;
|
||||
return usersData[id]?.name;
|
||||
});
|
||||
const emojiData = getEmojiDataFromNative(emoji, "apple", AppleEmojiData);
|
||||
const prefixDesc =
|
||||
|
||||
@@ -156,7 +156,7 @@ interface ReplyProps {
|
||||
|
||||
const Reply: FC<ReplyProps> = ({ mid, interactive = true }) => {
|
||||
const { data, users } = useAppSelector((store) => {
|
||||
return { data: store.message[mid], users: store.contacts.byId };
|
||||
return { data: store.message[mid], users: store.users.byId };
|
||||
});
|
||||
const handleClick = (evt: MouseEvent<HTMLDivElement>) => {
|
||||
const { mid } = evt.currentTarget.dataset;
|
||||
|
||||
@@ -38,12 +38,12 @@ function Message({
|
||||
const {
|
||||
message = {},
|
||||
reactionMessageData,
|
||||
contactsData
|
||||
usersData
|
||||
} = useSelector((store) => {
|
||||
return {
|
||||
reactionMessageData: store.reactionMessage,
|
||||
message: store.message[mid] || {},
|
||||
contactsData: store.contacts.byId
|
||||
usersData: store.users.byId
|
||||
};
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ function Message({
|
||||
}, [mid, read]);
|
||||
|
||||
const reactions = reactionMessageData[mid];
|
||||
const currUser = contactsData[fromUid] || {};
|
||||
const currUser = usersData[fromUid] || {};
|
||||
// if (!message) return null;
|
||||
let timePrefix = null;
|
||||
const dayjsTime = dayjs(time);
|
||||
@@ -115,10 +115,7 @@ function Message({
|
||||
visible={contextMenuVisible}
|
||||
hide={hideContextMenu}
|
||||
>
|
||||
<div
|
||||
className="details"
|
||||
data-pin-tip={`pinned by ${contactsData[pinInfo?.created_by]?.name}`}
|
||||
>
|
||||
<div className="details" data-pin-tip={`pinned by ${usersData[pinInfo?.created_by]?.name}`}>
|
||||
<div className="up">
|
||||
<span className="name">{currUser.name}</span>
|
||||
<Tooltip
|
||||
|
||||
@@ -30,7 +30,7 @@ import { ReactEditor } from "slate-react";
|
||||
import useUploadFile from "../../hook/useUploadFile";
|
||||
import Styled from "./styled";
|
||||
import { CONFIG } from "./config";
|
||||
import Contact from "../Contact";
|
||||
import User from "../User";
|
||||
export const TEXT_EDITOR_PREFIX = "_text_editor";
|
||||
|
||||
let components = createPlateUI({
|
||||
@@ -50,7 +50,7 @@ const Plugins = ({
|
||||
const [context, to] = id.split("_");
|
||||
const { addStageFile } = useUploadFile({ context, id: to });
|
||||
const enableMentions = members.length > 0;
|
||||
const contactData = useSelector((store) => store.contacts.byId);
|
||||
const userData = useSelector((store) => store.users.byId);
|
||||
const [msgs, setMsgs] = useState([]);
|
||||
const [cmdKey, setCmdKey] = useState(false);
|
||||
const editableRef = useRef(null);
|
||||
@@ -220,12 +220,12 @@ const Plugins = ({
|
||||
onRenderItem={({ item }) => {
|
||||
console.log("wtf", item);
|
||||
if (!item || !item.data) return null;
|
||||
return <Contact key={item.data.uid} uid={item.data.uid} interactive={false} />;
|
||||
return <User key={item.data.uid} uid={item.data.uid} interactive={false} />;
|
||||
}}
|
||||
items={members.map((id) => {
|
||||
const data = contactData[id];
|
||||
const data = userData[id];
|
||||
if (!data) {
|
||||
// console.log("wtffe", id, contactData);
|
||||
// console.log("wtffe", id, userData);
|
||||
return { key: id };
|
||||
}
|
||||
const { uid, name, ...rest } = data;
|
||||
|
||||
@@ -30,7 +30,7 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
|
||||
|
||||
const { data } = useAppSelector((store) => {
|
||||
return {
|
||||
data: store.contacts.byId[uid]
|
||||
data: store.users.byId[uid]
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -122,15 +122,15 @@ const renderContent = (data) => {
|
||||
|
||||
export default function Replying({ context, id, mid }) {
|
||||
const { removeReplying } = useSendMessage({ to: id, context });
|
||||
const { msg, contactsData } = useAppSelector((store) => {
|
||||
return { contactsData: store.contacts.byId, msg: store.message[mid] };
|
||||
const { msg, usersData } = useAppSelector((store) => {
|
||||
return { usersData: store.users.byId, msg: store.message[mid] };
|
||||
});
|
||||
const removeReply = () => {
|
||||
removeReplying();
|
||||
};
|
||||
if (!msg) return null;
|
||||
const { from_uid } = msg;
|
||||
const user = contactsData[from_uid];
|
||||
const user = usersData[from_uid];
|
||||
return (
|
||||
<Styled className="reply">
|
||||
<div className="prefix">
|
||||
|
||||
@@ -39,13 +39,13 @@ function Send({
|
||||
mode,
|
||||
uploadFiles,
|
||||
channelsData,
|
||||
contactsData,
|
||||
usersData,
|
||||
uids
|
||||
} = useAppSelector((store) => {
|
||||
return {
|
||||
channelsData: store.channels.byId,
|
||||
uids: store.contacts.ids,
|
||||
contactsData: store.contacts.byId,
|
||||
uids: store.users.ids,
|
||||
usersData: store.users.byId,
|
||||
mode: store.ui.inputMode,
|
||||
from_uid: store.authData.user?.uid,
|
||||
replying_mid: store.message.replying[`${context}_${id}`],
|
||||
@@ -127,7 +127,7 @@ function Send({
|
||||
const toggleMarkdownFullscreen = () => {
|
||||
setMarkdownFullscreen((prev) => !prev);
|
||||
};
|
||||
const name = context == "channel" ? channelsData[id]?.name : contactsData[id]?.name;
|
||||
const name = context == "channel" ? channelsData[id]?.name : usersData[id]?.name;
|
||||
const placeholder = `Send to ${ChatPrefixs[context]}${name} `;
|
||||
const members =
|
||||
context == "channel" ? (channelsData[id]?.is_public ? uids : channelsData[id]?.members) : [];
|
||||
|
||||
@@ -56,7 +56,7 @@ export default function Server() {
|
||||
const { pathname } = useLocation();
|
||||
const { server, userCount } = useAppSelector((store) => {
|
||||
return {
|
||||
userCount: store.contacts.ids.length,
|
||||
userCount: store.users.ids.length,
|
||||
server: store.server
|
||||
};
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ interface Props {
|
||||
enableContextMenu?: boolean;
|
||||
}
|
||||
|
||||
const Contact: FC<Props> = ({
|
||||
const User: FC<Props> = ({
|
||||
cid,
|
||||
uid,
|
||||
owner = false,
|
||||
@@ -34,7 +34,7 @@ const Contact: FC<Props> = ({
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { visible: contextMenuVisible, handleContextMenuEvent, hideContextMenu } = useContextMenu();
|
||||
const curr = useAppSelector((store) => store.contacts.byId[uid]);
|
||||
const curr = useAppSelector((store) => store.users.byId[uid]);
|
||||
const handleDoubleClick = () => {
|
||||
navigate(`/chat/dm/${uid}`);
|
||||
};
|
||||
@@ -73,4 +73,4 @@ const Contact: FC<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default Contact;
|
||||
export default User;
|
||||
@@ -4,7 +4,7 @@ import { NavLink } from "react-router-dom";
|
||||
import { useOutsideClick } from "rooks";
|
||||
import useFilteredUsers from "../hook/useFilteredUsers";
|
||||
|
||||
import Contact from "./Contact";
|
||||
import User from "./User";
|
||||
import Modal from "./Modal";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
@@ -16,7 +16,6 @@ const StyledWrapper = styled.div`
|
||||
box-shadow: 0 25px 50px rgba(31, 41, 55, 0.25);
|
||||
border-radius: 8px;
|
||||
transition: all 0.5s ease;
|
||||
/* overflow-y: scroll; */
|
||||
.search {
|
||||
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
|
||||
padding: 8px;
|
||||
@@ -58,7 +57,7 @@ interface Props {
|
||||
|
||||
const ContactsModal: FC<Props> = ({ closeModal }) => {
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const { contacts, updateInput, input } = useFilteredUsers();
|
||||
const { users, updateInput, input } = useFilteredUsers();
|
||||
useOutsideClick(wrapperRef, closeModal);
|
||||
|
||||
const handleSearch = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
@@ -71,14 +70,14 @@ const ContactsModal: FC<Props> = ({ closeModal }) => {
|
||||
<div className="search">
|
||||
<input value={input} onChange={handleSearch} placeholder="Type Username to search" />
|
||||
</div>
|
||||
{contacts && (
|
||||
{users && (
|
||||
<ul className="users">
|
||||
{contacts.map((u) => {
|
||||
{users.map((u) => {
|
||||
const { uid } = u;
|
||||
return (
|
||||
<li key={uid} className="user">
|
||||
<NavLink onClick={closeModal} to={`/chat/dm/${uid}`}>
|
||||
<Contact uid={uid} interactive={false} />
|
||||
<User uid={uid} interactive={false} />
|
||||
</NavLink>
|
||||
</li>
|
||||
);
|
||||
@@ -4,7 +4,7 @@ import toast from "react-hot-toast";
|
||||
import { useNavigate, useMatch } from "react-router-dom";
|
||||
import { hideAll } from "tippy.js";
|
||||
import { useRemoveMembersMutation } from "../../app/services/channel";
|
||||
import { useLazyDeleteContactQuery } from "../../app/services/contact";
|
||||
import { useLazyDeleteContactQuery } from "../../app/services/user";
|
||||
import useConfig from "./useConfig";
|
||||
import useCopy from "./useCopy";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
@@ -15,14 +15,14 @@ interface Props {
|
||||
const useContactOperation: FC<Props> = ({ uid, cid }) => {
|
||||
const [passedUid, setPassedUid] = useState(undefined);
|
||||
const { values: agoraConfig } = useConfig("agora");
|
||||
const isUserDetailPath = useMatch(`/contacts/${uid}`);
|
||||
const isUserDetailPath = useMatch(`/users/${uid}`);
|
||||
const [removeUser, { isSuccess: removeUserSuccess }] = useLazyDeleteContactQuery();
|
||||
const [removeInChannel, { isSuccess: removeSuccess }] = useRemoveMembersMutation();
|
||||
const navigateTo = useNavigate();
|
||||
const { copy } = useCopy();
|
||||
const { user, channel, loginUser } = useAppSelector((store) => {
|
||||
return {
|
||||
user: store.contacts.byId[uid],
|
||||
user: store.users.byId[uid],
|
||||
channel: store.channels.byId[cid],
|
||||
loginUser: store.authData.user
|
||||
};
|
||||
@@ -36,7 +36,7 @@ const useContactOperation: FC<Props> = ({ uid, cid }) => {
|
||||
if (removeSuccess || removeUserSuccess) {
|
||||
toast.success("Remove Successfully");
|
||||
if (removeUserSuccess && isUserDetailPath) {
|
||||
navigateTo(`/contacts`);
|
||||
navigateTo(`/users`);
|
||||
}
|
||||
}
|
||||
}, [removeSuccess, removeUserSuccess, isUserDetailPath]);
|
||||
|
||||
@@ -3,16 +3,16 @@ import { useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useFilteredUsers() {
|
||||
const [input, setInput] = useState("");
|
||||
const contacts = useAppSelector((store) => Object.values(store.contacts.byId));
|
||||
const users = useAppSelector((store) => Object.values(store.users.byId));
|
||||
const [filteredUsers, setFilteredUsers] = useState([]);
|
||||
useEffect(() => {
|
||||
if (!input) {
|
||||
setFilteredUsers(contacts);
|
||||
setFilteredUsers(users);
|
||||
} else {
|
||||
let str = ["", input.toLowerCase(), ""].join(".*");
|
||||
let reg = new RegExp(str);
|
||||
setFilteredUsers(
|
||||
contacts.filter((c) => {
|
||||
users.filter((c) => {
|
||||
return reg.test(c.name.toLowerCase());
|
||||
})
|
||||
);
|
||||
@@ -25,7 +25,7 @@ export default function useFilteredUsers() {
|
||||
|
||||
return {
|
||||
input,
|
||||
contacts: filteredUsers,
|
||||
users: filteredUsers,
|
||||
updateInput
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { useSendChannelMsgMutation } from "../../app/services/channel";
|
||||
import { useSendMsgMutation } from "../../app/services/contact";
|
||||
import { useSendMsgMutation } from "../../app/services/user";
|
||||
import { useCreateArchiveMutation } from "../../app/services/message";
|
||||
|
||||
export default function useForwardMessage() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useDispatch, batch } from "react-redux";
|
||||
import { resetFootprint } from "../../app/slices/footprint";
|
||||
import { resetChannels } from "../../app/slices/channels";
|
||||
import { resetContacts } from "../../app/slices/contacts";
|
||||
import { resetContacts } from "../../app/slices/users";
|
||||
import { resetChannelMsg } from "../../app/slices/message.channel";
|
||||
import { resetUserMsg } from "../../app/slices/message.user";
|
||||
import { resetReactionMessage } from "../../app/slices/message.reaction";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import { useLazyGetHistoryMessagesQuery } from "../../app/services/channel";
|
||||
import { useLazyGetHistoryMessagesQuery as useLazyGetDMHistoryMsg } from "../../app/services/contact";
|
||||
import { useLazyGetHistoryMessagesQuery as useLazyGetDMHistoryMsg } from "../../app/services/user";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
export interface PageInfo {
|
||||
isFirst: boolean;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { usePinMessageMutation, useUnpinMessageMutation } from "../../app/services/message";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
import { PinnedMessage } from "../../types/channel";
|
||||
|
||||
export default function usePinMessage(cid: number) {
|
||||
const [pins, setPins] = useState([]);
|
||||
const [pins, setPins] = useState<PinnedMessage[]>([]);
|
||||
const { channel, loginUser } = useAppSelector((store) => {
|
||||
return {
|
||||
channel: store.channels.byId[cid],
|
||||
@@ -13,15 +14,15 @@ export default function usePinMessage(cid: number) {
|
||||
const [pin, { isError, isLoading, isSuccess }] = usePinMessageMutation();
|
||||
const [unpin, { isError: isUnpinError, isLoading: isUnpining, isSuccess: isUnpinSuccess }] =
|
||||
useUnpinMessageMutation();
|
||||
const pinMessage = (mid) => {
|
||||
const pinMessage = (mid: number) => {
|
||||
if (!mid || !cid) return;
|
||||
pin({ mid, gid: +cid });
|
||||
};
|
||||
const unpinMessage = (mid) => {
|
||||
const unpinMessage = (mid: number) => {
|
||||
if (!mid || !cid) return;
|
||||
unpin({ mid, gid: +cid });
|
||||
};
|
||||
const getPinInfo = (mid) => {
|
||||
const getPinInfo = (mid: number) => {
|
||||
if (!cid || !channel) return;
|
||||
const pins = channel.pinned_messages;
|
||||
if (!pins || pins.length == 0) return;
|
||||
@@ -38,7 +39,7 @@ export default function usePinMessage(cid: number) {
|
||||
getPinInfo,
|
||||
channel,
|
||||
pins,
|
||||
canPin: loginUser.is_admin || channel?.owner == loginUser.uid,
|
||||
canPin: loginUser?.is_admin || channel?.owner == loginUser?.uid,
|
||||
pinMessage,
|
||||
unpinMessage,
|
||||
isError,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import toast from "react-hot-toast";
|
||||
import { removeReplyingMessage, addReplyingMessage } from "../../app/slices/message";
|
||||
import { useSendChannelMsgMutation } from "../../app/services/channel";
|
||||
import { useSendMsgMutation } from "../../app/services/contact";
|
||||
import { useSendMsgMutation } from "../../app/services/user";
|
||||
import { useReplyMessageMutation } from "../../app/services/message";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/store";
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
updateReadUsers,
|
||||
updateMute
|
||||
} from "../../../app/slices/footprint";
|
||||
import { updateUsersByLogs, updateUsersStatus } from "../../../app/slices/contacts";
|
||||
import { updateUsersByLogs, updateUsersStatus } from "../../../app/slices/users";
|
||||
import { resetAuthData } from "../../../app/slices/auth.data";
|
||||
import chatMessageHandler from "./chat.handler";
|
||||
import store, { useAppDispatch, useAppSelector } from "../../../app/store";
|
||||
|
||||
@@ -20,12 +20,9 @@ export default function useUploadFile(props: { context: string; id: string } | o
|
||||
const canceledRef = useRef(false);
|
||||
const sliceUploadedCountRef = useRef(0);
|
||||
const totalSliceCountRef = useRef(1);
|
||||
const [prepareUploadFile, { isLoading: isPreparing, isSuccess: isPrepared }] =
|
||||
usePrepareUploadFileMutation();
|
||||
const [
|
||||
uploadFileFn,
|
||||
{ isLoading: isUploading, isSuccess: isUploaded, isError: uploadFileError }
|
||||
] = useUploadFileMutation();
|
||||
const [prepareUploadFile, { isLoading: isPreparing }] = usePrepareUploadFileMutation();
|
||||
const [uploadFileFn, { isLoading: isUploading, isError: uploadFileError }] =
|
||||
useUploadFileMutation();
|
||||
|
||||
const uploadChunk = (data: { file_id: string; chunk: File; is_last: boolean }) => {
|
||||
const { file_id, chunk, is_last } = data;
|
||||
|
||||
@@ -11,7 +11,7 @@ import useMessageFeed from "../../../common/hook/useMessageFeed";
|
||||
import useConfig from "../../../common/hook/useConfig";
|
||||
import ChannelIcon from "../../../common/component/ChannelIcon";
|
||||
import Tooltip from "../../../common/component/Tooltip";
|
||||
import Contact from "../../../common/component/Contact";
|
||||
import User from "../../../common/component/User";
|
||||
import Layout from "../Layout";
|
||||
import { renderMessageFragment } from "../utils";
|
||||
import EditIcon from "../../../assets/icons/edit.svg";
|
||||
@@ -66,7 +66,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
footprint: store.footprint,
|
||||
loginUser: store.authData.user,
|
||||
// msgIds: store.channelMessage[cid] || [],
|
||||
userIds: store.contacts.ids,
|
||||
userIds: store.users.ids,
|
||||
data: store.channels.byId[cid] || {},
|
||||
messageData: store.message || {}
|
||||
};
|
||||
@@ -183,7 +183,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
</div>
|
||||
</StyledHeader>
|
||||
}
|
||||
contacts={
|
||||
users={
|
||||
membersVisible ? (
|
||||
<>
|
||||
<StyledContacts>
|
||||
@@ -195,7 +195,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||
)}
|
||||
{memberIds.map((uid) => {
|
||||
return (
|
||||
<Contact
|
||||
<User
|
||||
enableContextMenu={true}
|
||||
cid={cid}
|
||||
owner={owner == uid}
|
||||
|
||||
@@ -11,7 +11,7 @@ import Tooltip from "../../../common/component/Tooltip";
|
||||
import IconSetting from "../../../assets/icons/setting.svg";
|
||||
import IconInvite from "../../../assets/icons/invite.from.channel.svg";
|
||||
import { useReadMessageMutation } from "../../../app/services/message";
|
||||
import { useUpdateMuteSettingMutation } from "../../../app/services/contact";
|
||||
import { useUpdateMuteSettingMutation } from "../../../app/services/user";
|
||||
import StyledLink from "./styled";
|
||||
import ChannelIcon from "../../../common/component/ChannelIcon";
|
||||
import { getUnreadCount } from "../utils";
|
||||
|
||||
@@ -8,7 +8,7 @@ import FavIcon from "../../../assets/icons/bookmark.svg";
|
||||
// import IconHeadphone from "../../../assets/icons/headphone.svg";
|
||||
// import useChatScroll from "../../../common/hook/useChatScroll";
|
||||
import { useReadMessageMutation } from "../../../app/services/message";
|
||||
import Contact from "../../../common/component/Contact";
|
||||
import User from "../../../common/component/User";
|
||||
import Layout from "../Layout";
|
||||
import { StyledHeader, StyledDMChat } from "./styled";
|
||||
import LoadMore from "../LoadMore";
|
||||
@@ -34,7 +34,7 @@ export default function DMChat({ uid = 0, dropFiles = [] }) {
|
||||
selects: store.ui.selectMessages[`user_${uid}`],
|
||||
loginUid: store.authData.user?.uid,
|
||||
footprint: store.footprint,
|
||||
currUser: store.contacts.byId[uid],
|
||||
currUser: store.users.byId[uid],
|
||||
messageData: store.message
|
||||
};
|
||||
});
|
||||
@@ -81,7 +81,7 @@ export default function DMChat({ uid = 0, dropFiles = [] }) {
|
||||
}
|
||||
header={
|
||||
<StyledHeader className="head">
|
||||
<Contact interactive={false} uid={currUser.uid} />
|
||||
<User interactive={false} uid={currUser.uid} />
|
||||
</StyledHeader>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -14,7 +14,7 @@ import useContextMenu from "../../../common/hook/useContextMenu";
|
||||
import ContextMenu from "../../../common/component/ContextMenu";
|
||||
dayjs.extend(relativeTime);
|
||||
import { renderPreviewMessage } from "../utils";
|
||||
import Contact from "../../../common/component/Contact";
|
||||
import User from "../../../common/component/User";
|
||||
import { ContentTypes } from "../../../app/config";
|
||||
const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
const [previewMsg, setPreviewMsg] = useState(null);
|
||||
@@ -24,7 +24,7 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
const [updateReadIndex] = useReadMessageMutation();
|
||||
const { currMsg, currUser } = useSelector((store) => {
|
||||
return {
|
||||
currUser: store.contacts.byId[uid],
|
||||
currUser: store.users.byId[uid],
|
||||
currMsg: store.message[mid]
|
||||
};
|
||||
});
|
||||
@@ -107,7 +107,7 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
to={`/chat/dm/${uid}`}
|
||||
onContextMenu={handleContextMenuEvent}
|
||||
>
|
||||
<Contact compact interactive={false} className="avatar" uid={uid} />
|
||||
<User compact interactive={false} className="avatar" uid={uid} />
|
||||
<div className="details">
|
||||
<div className="up">
|
||||
<span className="name">{currUser.name}</span>
|
||||
|
||||
@@ -13,7 +13,7 @@ const DMList: FC<Props> = ({ uids, setDropFiles }) => {
|
||||
return {
|
||||
loginUid: store.authData.user?.uid,
|
||||
readUsers: store.footprint.readUsers,
|
||||
contactData: store.contacts.byId,
|
||||
userData: store.users.byId,
|
||||
userMessage: store.userMessage.byId,
|
||||
messageData: store.message
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ interface Props {
|
||||
children: ReactElement;
|
||||
header: ReactElement;
|
||||
aside: ReactElement | null;
|
||||
contacts: ReactElement | null;
|
||||
users: ReactElement | null;
|
||||
dropFiles: [];
|
||||
context: string;
|
||||
to: number | null;
|
||||
@@ -23,7 +23,7 @@ const Layout: FC<Props> = ({
|
||||
children,
|
||||
header,
|
||||
aside = null,
|
||||
contacts = null,
|
||||
users = null,
|
||||
dropFiles = [],
|
||||
context = "channel",
|
||||
to = null
|
||||
@@ -31,11 +31,11 @@ const Layout: FC<Props> = ({
|
||||
const { addStageFile } = useUploadFile({ context, id: to });
|
||||
const messagesContainer = useRef<HTMLDivElement>(null);
|
||||
const [previewImage, setPreviewImage] = useState(null);
|
||||
const { selects, channelsData, contactsData } = useAppSelector((store) => {
|
||||
const { selects, channelsData, usersData } = useAppSelector((store) => {
|
||||
return {
|
||||
selects: store.ui.selectMessages[`${context}_${to}`],
|
||||
channelsData: store.channels.byId,
|
||||
contactsData: store.contacts.byId
|
||||
usersData: store.users.byId
|
||||
};
|
||||
});
|
||||
const [{ isActive }, drop] = useDrop(
|
||||
@@ -95,7 +95,7 @@ const Layout: FC<Props> = ({
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
const name = context == "channel" ? channelsData[to]?.name : contactsData[to]?.name;
|
||||
const name = context == "channel" ? channelsData[to]?.name : usersData[to]?.name;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -110,7 +110,7 @@ const Layout: FC<Props> = ({
|
||||
{selects && <Operations context={context} id={to} />}
|
||||
</div>
|
||||
</div>
|
||||
{contacts && <div className="members">{contacts}</div>}
|
||||
{users && <div className="members">{users}</div>}
|
||||
{aside && <div className="aside">{aside}</div>}
|
||||
</main>
|
||||
<div className={`drag_tip ${isActive ? "visible animate__animated animate__fadeIn" : ""}`}>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Tippy from "@tippyjs/react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate, useLocation, useMatch } from "react-router-dom";
|
||||
import { useUpdateMuteSettingMutation } from "../../../app/services/contact";
|
||||
import { useUpdateMuteSettingMutation } from "../../../app/services/user";
|
||||
import { useReadMessageMutation } from "../../../app/services/message";
|
||||
import { removeUserSession } from "../../../app/slices/message.user";
|
||||
import ContextMenu from "../../../common/component/ContextMenu";
|
||||
|
||||
@@ -6,7 +6,7 @@ import { NativeTypes } from "react-dnd-html5-backend";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import ContextMenu from "./ContextMenu";
|
||||
import getUnreadCount, { renderPreviewMessage } from "../utils";
|
||||
import Contact from "../../../common/component/Contact";
|
||||
import User from "../../../common/component/User";
|
||||
import Avatar from "../../../common/component/Avatar";
|
||||
import iconChannel from "../../../assets/icons/channel.svg?url";
|
||||
import IconLock from "../../../assets/icons/lock.svg";
|
||||
@@ -51,7 +51,7 @@ export default function Session({
|
||||
|
||||
const { visible: contextMenuVisible, handleContextMenuEvent, hideContextMenu } = useContextMenu();
|
||||
const [data, setData] = useState(null);
|
||||
const { messageData, contactData, channelData, readIndex, loginUid, mids, muted } = useSelector(
|
||||
const { messageData, userData, channelData, readIndex, loginUid, mids, muted } = useSelector(
|
||||
(store) => {
|
||||
return {
|
||||
mids: type == "user" ? store.userMessage.byId[id] : store.channelMessage[id],
|
||||
@@ -59,7 +59,7 @@ export default function Session({
|
||||
readIndex:
|
||||
type == "user" ? store.footprint.readUsers[id] : store.footprint.readChannels[id],
|
||||
messageData: store.message,
|
||||
contactData: store.contacts.byId,
|
||||
userData: store.users.byId,
|
||||
channelData: store.channels.byId,
|
||||
muted: type == "user" ? store.footprint.muteUsers[id] : store.footprint.muteChannels[id]
|
||||
};
|
||||
@@ -72,13 +72,13 @@ export default function Session({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const tmp = type == "user" ? contactData[id] : channelData[id];
|
||||
const tmp = type == "user" ? userData[id] : channelData[id];
|
||||
if (!tmp) return;
|
||||
const { name, icon, avatar, is_public = true } = tmp;
|
||||
const session =
|
||||
type == "user" ? { name, icon: avatar, mid, is_public } : { name, icon, mid, is_public };
|
||||
setData(session);
|
||||
}, [id, mid, type, contactData, channelData]);
|
||||
}, [id, mid, type, userData, channelData]);
|
||||
if (!data) return null;
|
||||
const previewMsg = messageData[mid] || {};
|
||||
const { name, icon, is_public } = data;
|
||||
@@ -108,7 +108,7 @@ export default function Session({
|
||||
>
|
||||
<div className="icon">
|
||||
{type == "user" ? (
|
||||
<Contact avatarSize={40} compact interactive={false} className="avatar" uid={id} />
|
||||
<User avatarSize={40} compact interactive={false} className="avatar" uid={id} />
|
||||
) : (
|
||||
<Avatar className="icon" type="channel" name={name} url={icon} />
|
||||
// <img
|
||||
|
||||
@@ -10,12 +10,12 @@ import AddIcon from "../../assets/icons/add.svg";
|
||||
import BlankPlaceholder from "../../common/component/BlankPlaceholder";
|
||||
import Server from "../../common/component/Server";
|
||||
import Tooltip from "../../common/component/Tooltip";
|
||||
// import Contact from "../../common/component/Contact";
|
||||
// import User from "../../common/component/User";
|
||||
// import CurrentUser from "../../common/component/CurrentUser";
|
||||
import ChannelChat from "./ChannelChat";
|
||||
import DMChat from "./DMChat";
|
||||
import ChannelList from "./ChannelList";
|
||||
import ContactsModal from "../../common/component/ContactsModal";
|
||||
import ContactsModal from "../../common/component/UsersModal";
|
||||
import ChannelModal from "../../common/component/ChannelModal";
|
||||
import DMList from "./DMList";
|
||||
|
||||
@@ -28,7 +28,7 @@ export default function ChatPage() {
|
||||
};
|
||||
});
|
||||
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
||||
const [contactsModalVisible, setContactsModalVisible] = useState(false);
|
||||
const [usersModalVisible, setContactsModalVisible] = useState(false);
|
||||
const { channel_id, user_id } = useParams();
|
||||
const toggleContactsModalVisible = () => {
|
||||
setContactsModalVisible((prev) => !prev);
|
||||
@@ -49,7 +49,7 @@ export default function ChatPage() {
|
||||
{channelModalVisible && (
|
||||
<ChannelModal closeModal={toggleChannelModalVisible} personal={true} />
|
||||
)}
|
||||
{contactsModalVisible && <ContactsModal closeModal={toggleContactsModalVisible} />}
|
||||
{usersModalVisible && <ContactsModal closeModal={toggleContactsModalVisible} />}
|
||||
<StyledWrapper>
|
||||
<div className="left">
|
||||
<Server />
|
||||
|
||||
@@ -9,12 +9,12 @@ import Server from "../../common/component/Server";
|
||||
import CurrentUser from "../../common/component/CurrentUser";
|
||||
import ChannelChat from "./ChannelChat";
|
||||
import DMChat from "./DMChat";
|
||||
import ContactsModal from "../../common/component/ContactsModal";
|
||||
import ContactsModal from "../../common/component/UsersModal";
|
||||
import ChannelModal from "../../common/component/ChannelModal";
|
||||
import SessionList from "./SessionList";
|
||||
export default function ChatPage() {
|
||||
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
||||
const [contactsModalVisible, setContactsModalVisible] = useState(false);
|
||||
const [usersModalVisible, setContactsModalVisible] = useState(false);
|
||||
const { channel_id, user_id } = useParams();
|
||||
const { sessionUids } = useSelector((store) => {
|
||||
return {
|
||||
@@ -38,7 +38,7 @@ export default function ChatPage() {
|
||||
{channelModalVisible && (
|
||||
<ChannelModal closeModal={toggleChannelModalVisible} personal={true} />
|
||||
)}
|
||||
{contactsModalVisible && <ContactsModal closeModal={toggleContactsModalVisible} />}
|
||||
{usersModalVisible && <ContactsModal closeModal={toggleContactsModalVisible} />}
|
||||
<StyledWrapper>
|
||||
<div className="left">
|
||||
<Server />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
// import { useUpdateChannelMutation } from "../../app/services/channel";
|
||||
import { useUpdateMuteSettingMutation } from "../../app/services/contact";
|
||||
import { useUpdateMuteSettingMutation } from "../../app/services/user";
|
||||
import { useReadMessageMutation } from "../../app/services/message";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
@@ -8,10 +8,10 @@ export default function useSession({ type, id }) {
|
||||
const [inviteModalVisible, setInviteModalVisible] = useState(false);
|
||||
const [muteChannel] = useUpdateMuteSettingMutation();
|
||||
const [updateReadIndex] = useReadMessageMutation();
|
||||
const { messageData, contactData, channelData } = useAppSelector((store) => {
|
||||
const { messageData, userData, channelData } = useAppSelector((store) => {
|
||||
return {
|
||||
messageData: store.message,
|
||||
contactData: store.contacts.byId,
|
||||
userData: store.users.byId,
|
||||
channelData: store.channels.byId
|
||||
};
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@ function FavsPage() {
|
||||
console.log("favs", store.favorites);
|
||||
return {
|
||||
favorites: store.favorites,
|
||||
userData: store.contacts.byId,
|
||||
userData: store.users.byId,
|
||||
channelData: store.channels.byId
|
||||
};
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ interface Props {
|
||||
|
||||
const User: FC<Props> = ({ uid }) => {
|
||||
const { pathname } = useLocation();
|
||||
const user = useAppSelector((store) => store.contacts.byId[uid]);
|
||||
const user = useAppSelector((store) => store.users.byId[uid]);
|
||||
if (!user) return null;
|
||||
|
||||
return (
|
||||
|
||||
@@ -13,7 +13,7 @@ import Notification from "../../common/component/Notification";
|
||||
import Manifest from "../../common/component/Manifest";
|
||||
|
||||
import ChatIcon from "../../assets/icons/chat.svg";
|
||||
import ContactIcon from "../../assets/icons/contact.svg";
|
||||
import ContactIcon from "../../assets/icons/user.svg";
|
||||
import FavIcon from "../../assets/icons/bookmark.svg";
|
||||
import FolderIcon from "../../assets/icons/folder.svg";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
@@ -27,7 +27,7 @@ export default function HomePage() {
|
||||
loginUid,
|
||||
ui: {
|
||||
ready,
|
||||
remeberedNavs: { chat: chatPath, contact: contactPath }
|
||||
remeberedNavs: { chat: chatPath, user: userPath }
|
||||
}
|
||||
} = useAppSelector((store) => {
|
||||
return {
|
||||
@@ -52,7 +52,7 @@ export default function HomePage() {
|
||||
}
|
||||
// 有点绕
|
||||
const chatNav = isChatHomePath ? "/chat" : chatPath || "/chat";
|
||||
const contactNav = contactPath || "/contacts";
|
||||
const userNav = userPath || "/users";
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -72,7 +72,7 @@ export default function HomePage() {
|
||||
<ChatIcon />
|
||||
</Tooltip>
|
||||
</NavLink>
|
||||
<NavLink className="link" to={contactNav}>
|
||||
<NavLink className="link" to={userNav}>
|
||||
<Tooltip tip="Members">
|
||||
<ContactIcon />
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect } from "react";
|
||||
import initCache, { useRehydrate } from "../../app/cache";
|
||||
import { useLazyGetFavoritesQuery } from "../../app/services/message";
|
||||
import { useLazyGetContactsQuery } from "../../app/services/contact";
|
||||
import { useLazyGetContactsQuery } from "../../app/services/user";
|
||||
import { useLazyGetServerQuery } from "../../app/services/server";
|
||||
import useStreaming from "../../common/hook/useStreaming";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
@@ -27,12 +27,7 @@ export default function usePreload() {
|
||||
] = useLazyGetFavoritesQuery();
|
||||
const [
|
||||
getContacts,
|
||||
{
|
||||
isLoading: contactsLoading,
|
||||
isSuccess: contactsSuccess,
|
||||
isError: contactsError,
|
||||
data: contacts
|
||||
}
|
||||
{ isLoading: usersLoading, isSuccess: usersSuccess, isError: usersError, data: users }
|
||||
] = useLazyGetContactsQuery();
|
||||
const [
|
||||
getServer,
|
||||
@@ -61,11 +56,11 @@ export default function usePreload() {
|
||||
}, [canStreaming]);
|
||||
|
||||
return {
|
||||
loading: contactsLoading || serverLoading || favoritesLoading || !rehydrated,
|
||||
error: contactsError && serverError && favoritesError,
|
||||
success: contactsSuccess && serverSuccess && favoritesSuccess,
|
||||
loading: usersLoading || serverLoading || favoritesLoading || !rehydrated,
|
||||
error: usersError && serverError && favoritesError,
|
||||
success: usersSuccess && serverSuccess && favoritesSuccess,
|
||||
data: {
|
||||
contacts,
|
||||
users,
|
||||
server,
|
||||
favorites
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const SendMagicLinkPage = lazy(() => import("./sendMagicLink"));
|
||||
const RegPage = lazy(() => import("./reg/Register"));
|
||||
const LoginPage = lazy(() => import("./login"));
|
||||
const OAuthPage = lazy(() => import("./oauth"));
|
||||
const ContactsPage = lazy(() => import("./contacts"));
|
||||
const ContactsPage = lazy(() => import("./users"));
|
||||
const FavoritesPage = lazy(() => import("./favs"));
|
||||
const OnboardingPage = lazy(() => import("./onboarding"));
|
||||
const InvitePage = lazy(() => import("./invite"));
|
||||
@@ -138,7 +138,7 @@ const PageRoutes = () => {
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="contacts">
|
||||
<Route path="users">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
|
||||
@@ -77,7 +77,7 @@ export default function LoginPage() {
|
||||
break;
|
||||
case 410:
|
||||
toast.error(
|
||||
"No associated account found, please contact admin for an invitation link to join."
|
||||
"No associated account found, please user admin for an invitation link to join."
|
||||
);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -58,11 +58,11 @@ export const Dates = {
|
||||
};
|
||||
|
||||
export default function Date({ select = "", updateFilter }) {
|
||||
// const { input, updateInput, contacts } = useFilteredUsers();
|
||||
// const contacts=useSelector(store=>store.contacts);
|
||||
// const { input, updateInput, users } = useFilteredUsers();
|
||||
// const users=useSelector(store=>store.users);
|
||||
|
||||
// const uid=contacts.ids;
|
||||
// const dataMap=contacts.byId;
|
||||
// const uid=users.ids;
|
||||
// const dataMap=users.byId;
|
||||
const handleClick = (dur) => {
|
||||
updateFilter({ date: dur });
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import styled from "styled-components";
|
||||
import Search from "../Search";
|
||||
import CheckSign from "../../../assets/icons/check.sign.svg";
|
||||
import Contact from "../../../common/component/Contact";
|
||||
import User from "../../../common/component/User";
|
||||
import useFilteredUsers from "../../../common/hook/useFilteredUsers";
|
||||
|
||||
const Styled = styled.div`
|
||||
@@ -28,7 +28,7 @@ const Styled = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.contact {
|
||||
.user {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
&.none {
|
||||
@@ -49,11 +49,11 @@ const Styled = styled.div`
|
||||
`;
|
||||
|
||||
export default function From({ select = "", updateFilter }) {
|
||||
const { input, updateInput, contacts } = useFilteredUsers();
|
||||
// const contacts=useSelector(store=>store.contacts);
|
||||
const { input, updateInput, users } = useFilteredUsers();
|
||||
// const users=useSelector(store=>store.users);
|
||||
|
||||
// const uid=contacts.ids;
|
||||
// const dataMap=contacts.byId;
|
||||
// const uid=users.ids;
|
||||
// const dataMap=users.byId;
|
||||
const handleClick = (uid) => {
|
||||
updateFilter({ from: uid });
|
||||
};
|
||||
@@ -64,14 +64,14 @@ export default function From({ select = "", updateFilter }) {
|
||||
<Search embed={true} value={input} updateSearchValue={updateInput} />
|
||||
</div>
|
||||
<ul className="list">
|
||||
<li className="contact none" onClick={handleClick.bind(null, undefined)}>
|
||||
<li className="user none" onClick={handleClick.bind(null, undefined)}>
|
||||
Anyone
|
||||
{!select && <CheckSign className="check" />}
|
||||
</li>
|
||||
{contacts.map(({ uid }) => {
|
||||
{users.map(({ uid }) => {
|
||||
return (
|
||||
<li key={uid} className="contact" onClick={handleClick.bind(null, uid)}>
|
||||
<Contact uid={uid} interactive={true} />
|
||||
<li key={uid} className="user" onClick={handleClick.bind(null, uid)}>
|
||||
<User uid={uid} interactive={true} />
|
||||
{select == uid && <CheckSign className="check" />}
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -78,11 +78,11 @@ export const FileTypes = {
|
||||
}
|
||||
};
|
||||
export default function Type({ select = "", updateFilter }) {
|
||||
// const { input, updateInput, contacts } = useFilteredUsers();
|
||||
// const contacts=useSelector(store=>store.contacts);
|
||||
// const { input, updateInput, users } = useFilteredUsers();
|
||||
// const users=useSelector(store=>store.users);
|
||||
|
||||
// const uid=contacts.ids;
|
||||
// const dataMap=contacts.byId;
|
||||
// const uid=users.ids;
|
||||
// const dataMap=users.byId;
|
||||
const handleClick = (type) => {
|
||||
updateFilter({ type });
|
||||
};
|
||||
|
||||
@@ -65,8 +65,8 @@ export default function Filter({ filter, updateFilter }) {
|
||||
};
|
||||
toggleFilterVisible(tmp);
|
||||
};
|
||||
const { contactMap, channelMap } = useAppSelector((store) => {
|
||||
return { contactMap: store.contacts.byId, channelMap: store.channels.byId };
|
||||
const { userMap, channelMap } = useAppSelector((store) => {
|
||||
return { userMap: store.users.byId, channelMap: store.channels.byId };
|
||||
});
|
||||
|
||||
const { from, channel, type, date } = filter;
|
||||
@@ -91,9 +91,9 @@ export default function Filter({ filter, updateFilter }) {
|
||||
onClick={toggleFilterVisible.bind(null, { from: true })}
|
||||
>
|
||||
{from && (
|
||||
<Avatar className="avatar" name={contactMap[from].name} url={contactMap[from].avatar} />
|
||||
<Avatar className="avatar" name={userMap[from].name} url={userMap[from].avatar} />
|
||||
)}
|
||||
<span className="txt">From {from && contactMap[from].name}</span>
|
||||
<span className="txt">From {from && userMap[from].name}</span>
|
||||
<ArrowDown className="arrow" />
|
||||
</div>
|
||||
</Tippy>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, MouseEvent } from "react";
|
||||
import styled from "styled-components";
|
||||
import toast from "react-hot-toast";
|
||||
import { useUpdateAvatarMutation } from "../../app/services/contact";
|
||||
import { useUpdateAvatarMutation } from "../../app/services/user";
|
||||
import AvatarUploader from "../../common/component/AvatarUploader";
|
||||
import ProfileBasicEditModal from "./ProfileBasicEditModal";
|
||||
import UpdatePasswordModal from "./UpdatePasswordModal";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ChangeEvent, FC, useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import toast from "react-hot-toast";
|
||||
import Input from "../../common/component/styled/Input";
|
||||
import { useUpdateInfoMutation } from "../../app/services/contact";
|
||||
import { useUpdateInfoMutation } from "../../app/services/user";
|
||||
import StyledModal from "../../common/component/styled/Modal";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
import Modal from "../../common/component/Modal";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { NavLink, useParams, useLocation } from "react-router-dom";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { updateRemeberedNavs } from "../../app/slices/ui";
|
||||
import Search from "../../common/component/Search";
|
||||
import Contact from "../../common/component/Contact";
|
||||
import User from "../../common/component/User";
|
||||
import Profile from "../../common/component/Profile";
|
||||
|
||||
import StyledWrapper from "./styled";
|
||||
@@ -14,26 +14,26 @@ export default function ContactsPage() {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const { user_id } = useParams();
|
||||
const contactIds = useSelector((store) => store.contacts.ids);
|
||||
const userIds = useSelector((store) => store.users.ids);
|
||||
useEffect(() => {
|
||||
dispatch(updateRemeberedNavs({ key: "contact" }));
|
||||
dispatch(updateRemeberedNavs({ key: "user" }));
|
||||
return () => {
|
||||
dispatch(updateRemeberedNavs({ key: "contact", path: pathname }));
|
||||
dispatch(updateRemeberedNavs({ key: "user", path: pathname }));
|
||||
};
|
||||
}, [pathname]);
|
||||
|
||||
console.log({ contactIds, user_id });
|
||||
if (!contactIds) return null;
|
||||
console.log({ userIds, user_id });
|
||||
if (!userIds) return null;
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="left">
|
||||
<Search />
|
||||
<div className="list">
|
||||
<nav className="nav">
|
||||
{contactIds.map((uid) => {
|
||||
{userIds.map((uid) => {
|
||||
return (
|
||||
<NavLink key={uid} className="session" to={`/contacts/${uid}`}>
|
||||
<Contact uid={uid} enableContextMenu={true} />
|
||||
<NavLink key={uid} className="session" to={`/users/${uid}`}>
|
||||
<User uid={uid} enableContextMenu={true} />
|
||||
</NavLink>
|
||||
);
|
||||
})}
|
||||
@@ -47,7 +47,7 @@ export default function ContactsPage() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="right placeholder">
|
||||
<BlankPlaceholder type="contact" />
|
||||
<BlankPlaceholder type="user" />
|
||||
</div>
|
||||
)}
|
||||
</StyledWrapper>
|
||||
@@ -1,9 +1,8 @@
|
||||
import { ContentType } from "./message";
|
||||
export interface ChannelMember {}
|
||||
|
||||
export interface Message {}
|
||||
|
||||
export type ContentType = "text/plain" | "text/markdown" | "vocechat/file" | "vocechat/archive";
|
||||
|
||||
export interface PinnedMessage {
|
||||
mid: number;
|
||||
content: string;
|
||||
@@ -17,10 +16,10 @@ export interface PinnedMessage {
|
||||
|
||||
export interface Channel {
|
||||
gid: number;
|
||||
// icon: string; // todo: check
|
||||
owner: number;
|
||||
name: string;
|
||||
description: string;
|
||||
icon?: string;
|
||||
members: number[];
|
||||
is_public: boolean;
|
||||
avatar_updated_at: number;
|
||||
@@ -37,8 +36,6 @@ export interface CreateChannelDTO {
|
||||
export interface UpdateChannelDTO {
|
||||
operation: "add_member" | "remove_member";
|
||||
members?: number[];
|
||||
|
||||
// type = 'group_changed'
|
||||
gid: number; // todo check
|
||||
name?: string;
|
||||
description?: string;
|
||||
|
||||
@@ -1,3 +1,39 @@
|
||||
export interface EntityId {
|
||||
id: number;
|
||||
}
|
||||
export interface OG {
|
||||
type: string;
|
||||
title: string;
|
||||
url: string;
|
||||
images: [
|
||||
{
|
||||
type?: string;
|
||||
url: string;
|
||||
secure_url?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
alt?: string;
|
||||
}
|
||||
];
|
||||
audios: [
|
||||
{
|
||||
type?: string;
|
||||
url: string;
|
||||
secure_url?: string;
|
||||
}
|
||||
];
|
||||
videos: [
|
||||
{
|
||||
type?: string;
|
||||
url: string;
|
||||
secure_url?: string;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
];
|
||||
favicon_url?: string;
|
||||
description?: string;
|
||||
locale?: string;
|
||||
locale_alternate?: [];
|
||||
site_name?: string;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export type ContentType = "text/plain" | "text/markdown" | "vocechat/file" | "vocechat/archive";
|
||||
+3
-1
@@ -1,5 +1,6 @@
|
||||
import { User } from "./auth";
|
||||
import { Channel, ContentType } from "./channel";
|
||||
import { Channel } from "./channel";
|
||||
import { ContentType } from "./message";
|
||||
|
||||
export interface ReadyEvent {
|
||||
type: "ready";
|
||||
@@ -75,6 +76,7 @@ export interface RelatedGroupsEvent {
|
||||
}
|
||||
|
||||
export interface NormalMessage {
|
||||
mid: number;
|
||||
type: "normal";
|
||||
properties: {};
|
||||
content_type: ContentType;
|
||||
|
||||
Reference in New Issue
Block a user