Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/src/features/chats/ChatBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ const ScrollContainer = styled.div`

z-index: 1;



display: flex;
flex-direction: column;
padding: 10px;
Expand Down
4 changes: 3 additions & 1 deletion app/src/features/chats/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ function ChatInput() {
const [input, setInput] = useState("");
const [isEmojiSelectorOpen, setIsEmojiSelectorOpen] = useState(false);
const { handleSendMessage } = useMessageSender();
const activeMessage = useSelector((state: RootState) => state.activeMessage);

const dispatch = useDispatch();

const toggleShowEmojies = () => {
Expand Down Expand Up @@ -109,7 +111,7 @@ function ChatInput() {
<Input>
{isEmojiSelectorOpen && <EmojiPickerItem setInputText={setInput} />}
<InputContainer>
<ReplyWrapper state="Edit" message="message" />
{activeMessage.id && <ReplyWrapper />}
<InputWrapper>
<InvisibleButton onClick={toggleShowEmojies}>
<Icon>{getIcon("Emojie")}</Icon>
Expand Down
12 changes: 11 additions & 1 deletion app/src/features/chats/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import renderWithHighlight from "@utils/renderWithHighlight";

import { useAppDispatch, useAppSelector } from "@hooks/useGlobalState";
import useScrollToLastMsg from "./hooks/useScrollToLastMsg";
import { setActiveMessage } from "@state/messages/activeMessage";
import { useSocket } from "@hooks/useSocket";

const StyledMessage = styled.div<{ $isMine: boolean }>`
Expand Down Expand Up @@ -156,6 +157,14 @@ function Message({
dispatch(setIsOptionListOpen({ value: !isOptionListOpen, id: id }));
}

function handleEditMessage() {
dispatch(setActiveMessage({ id, content, state: "edit" }));
}

function handleReply() {
dispatch(setActiveMessage({ id, content, state: "reply" }));
}

return (
<MessageRow $isChecked={isChecked}>
{showCheckbox && (
Expand All @@ -182,7 +191,8 @@ function Message({
forwardOnClick={forwardOnClick}
isPinned={isPinned}
pinOnClick={pinOnClick}
replyOnClick={() => {}} //TODO: Implement replyOnClick
replyOnClick={handleReply} //TODO: Implement replyOnClick
editOnClick={handleEditMessage}
/>
)}
</Bubble>
Expand Down
6 changes: 5 additions & 1 deletion app/src/features/chats/MessageOptionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@ interface Props {
$isMine: boolean;
forwardOnClick: () => void;
replyOnClick: () => void;
editOnClick: () => void;
pinOnClick: () => void;
isPinned: boolean;
}

function MessageOptionList(props: Props) {
const { $isMine, forwardOnClick, replyOnClick, pinOnClick, isPinned } = props;
const { $isMine, forwardOnClick, replyOnClick, editOnClick, pinOnClick, isPinned } = props;

return (
<StyledList $isMine={$isMine}>
Expand All @@ -63,6 +64,9 @@ function MessageOptionList(props: Props) {
<HoverMask onClick={replyOnClick}>
<StyledP>Reply</StyledP>
</HoverMask>
<HoverMask onClick={editOnClick}>
<StyledP>Edit</StyledP>
</HoverMask>
<HoverMask onClick={pinOnClick}>
<StyledP>{isPinned ? "Unpin" : "Pin"}</StyledP>
</HoverMask>
Expand Down
27 changes: 17 additions & 10 deletions app/src/features/chats/ReplyWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { useDispatch, useSelector } from "react-redux";
import styled from "styled-components";

import Icon from "@components/Icon";
import { getIcon } from "@data/icons";
import styled from "styled-components";

import { clearActiveMessage } from "@state/messages/activeMessage";
import { RootState } from "@state/store";

const Container = styled.div`
display: flex;
Expand Down Expand Up @@ -56,20 +61,22 @@ const Message = styled.div`
opacity: 0.9;
`;

type Props = {
state: "Edit" | "Reply";
message: string;
};
export default function ReplyWrapper() {
const dispatch = useDispatch();
const activeMessage = useSelector((state: RootState) => state.activeMessage);

function handleHideWrapper() {
dispatch(clearActiveMessage());
}

export default function ReplyWrapper({ state = "Edit", message }: Props) {
return (
<Container>
<Icon>{getIcon(state)}</Icon>
<Icon>{getIcon(activeMessage.state === "edit" ? "Edit" : "Reply")}</Icon>
<MessageBox>
<State>{`${state}ing`}</State>
<Message>{message}</Message>
<State>{`${activeMessage.state}ing`}</State>
<Message>{activeMessage.content}</Message>
</MessageBox>
<Icon>{getIcon("Close")}</Icon>
<Icon onClick={handleHideWrapper}>{getIcon("Close")}</Icon>
</Container>
);
}
36 changes: 36 additions & 0 deletions app/src/state/messages/activeMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

type ActiveMessageState = {
id: string | null;
content: string | null;
state: "edit" | "reply" | null;
};

const initialState: ActiveMessageState = {
id: null,
content: null,
state: null,
};

const activeMessageSlice = createSlice({
name: "editMessage",
initialState,
reducers: {
setActiveMessage: (state, action: PayloadAction<ActiveMessageState>) => {
state.id = action.payload.id;
state.content = action.payload.content;
state.state = action.payload.state;
},

clearActiveMessage: (state) => {
state.id = null;
state.content = null;
state.state = null;
},
},
});

export const { setActiveMessage, clearActiveMessage } =
activeMessageSlice.actions;

export default activeMessageSlice.reducer;
3 changes: 3 additions & 0 deletions app/src/state/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import sideBarReducer from "./side-bar/sideBar";
import userReducer from "./user/user";
import messagesReducer from "./messages/messages";
import searchReducer from "./messages/search";
import activeMessageReducer from "./messages/activeMessage";

export const store = configureStore({
reducer: {
theme: themeReducer,
sideBarData: sideBarReducer,
user: userReducer,
messages: messagesReducer,
search: searchReducer,
activeMessage: activeMessageReducer,
},
});

Expand Down