feat: text input for mobile
This commit is contained in:
@@ -17,13 +17,11 @@ import {
|
|||||||
MentionCombobox
|
MentionCombobox
|
||||||
} from "@udecode/plate";
|
} from "@udecode/plate";
|
||||||
import { createComboboxPlugin } from "@udecode/plate-combobox";
|
import { createComboboxPlugin } from "@udecode/plate-combobox";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { ReactEditor } from "slate-react";
|
import { ReactEditor } from "slate-react";
|
||||||
import useUploadFile from "../../hook/useUploadFile";
|
import useUploadFile from "../../hook/useUploadFile";
|
||||||
import { CONFIG } from "./config";
|
import { CONFIG } from "./config";
|
||||||
import User from "../User";
|
import User from "../User";
|
||||||
import { useAppSelector } from "../../../app/store";
|
import { useAppSelector } from "../../../app/store";
|
||||||
import Button from "../styled/Button";
|
|
||||||
import { isMobile } from "../../utils";
|
import { isMobile } from "../../utils";
|
||||||
export const TEXT_EDITOR_PREFIX = "_text_editor";
|
export const TEXT_EDITOR_PREFIX = "_text_editor";
|
||||||
|
|
||||||
@@ -49,7 +47,7 @@ const Plugins: FC<Props> = ({
|
|||||||
sendMessages,
|
sendMessages,
|
||||||
members = []
|
members = []
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
|
||||||
// const { getMenuProps, getItemProps } = useComboboxControls();
|
// const { getMenuProps, getItemProps } = useComboboxControls();
|
||||||
const [context, to] = id.split("_") as [ctx, number];
|
const [context, to] = id.split("_") as [ctx, number];
|
||||||
const { addStageFile } = useUploadFile({ context, id: to });
|
const { addStageFile } = useUploadFile({ context, id: to });
|
||||||
@@ -229,7 +227,6 @@ const Plugins: FC<Props> = ({
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</Plate>
|
</Plate>
|
||||||
<Button onClick={handleSend} className="mini md:hidden absolute right-1.5 bottom-1.5">{t("action.send")}</Button>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import MixedInput, { useMixedEditor } from "../MixedInput";
|
|||||||
import useDraft from "../../hook/useDraft";
|
import useDraft from "../../hook/useDraft";
|
||||||
import useUploadFile from "../../hook/useUploadFile";
|
import useUploadFile from "../../hook/useUploadFile";
|
||||||
import { useAppDispatch, useAppSelector } from "../../../app/store";
|
import { useAppDispatch, useAppSelector } from "../../../app/store";
|
||||||
|
import TextInput from "../TextInput";
|
||||||
|
|
||||||
const Modes = {
|
const Modes = {
|
||||||
text: "text",
|
text: "text",
|
||||||
@@ -138,45 +139,50 @@ const Send: FC<IProps> = ({
|
|||||||
context == "channel" ? (channelsData[id]?.is_public ? uids : channelsData[id]?.members) : [];
|
context == "channel" ? (channelsData[id]?.is_public ? uids : channelsData[id]?.members) : [];
|
||||||
const isMarkdownMode = mode == Modes.markdown;
|
const isMarkdownMode = mode == Modes.markdown;
|
||||||
return (
|
return (
|
||||||
<div
|
<>
|
||||||
className={clsx(`send relative bg-gray-200 rounded-lg w-full dark:bg-gray-600 ${mode} ${markdownFullscreen ? "fullscreen" : ""} ${replying_mid ? "reply" : ""
|
{/* mobile input */}
|
||||||
} ${context}`, isMarkdownMode && markdownFullscreen && '-mt-9')}
|
<TextInput sendMessage={handleSendMessage} placeholder={placeholder} />
|
||||||
>
|
{/* PC input */}
|
||||||
{replying_mid && <Replying context={context} mid={replying_mid} id={id} />}
|
<div
|
||||||
{mode == Modes.text && <UploadFileList context={context} id={id} />}
|
className={clsx(`send hidden md:block relative bg-gray-200 rounded-lg w-full dark:bg-gray-600 ${mode} ${markdownFullscreen ? "fullscreen" : ""} ${replying_mid ? "reply" : ""
|
||||||
|
} ${context}`, isMarkdownMode && markdownFullscreen && '-mt-9')}
|
||||||
|
>
|
||||||
|
{replying_mid && <Replying context={context} mid={replying_mid} id={id} />}
|
||||||
|
{mode == Modes.text && <UploadFileList context={context} id={id} />}
|
||||||
|
|
||||||
<div className={clsx(`flex justify-between items-center gap-4 px-2 md:px-4 py-1 md:py-3.5`, isMarkdownMode && `grid grid-cols-[1fr_1fr] grid-rows-[auto_auto] gap-0`)}>
|
<div className={clsx(`flex justify-between items-center gap-4 px-4 py-3.5`, isMarkdownMode && `grid grid-cols-[1fr_1fr] grid-rows-[auto_auto] gap-0`)}>
|
||||||
<EmojiPicker selectEmoji={insertEmoji} />
|
<EmojiPicker selectEmoji={insertEmoji} />
|
||||||
{mode == Modes.text && (
|
{mode == Modes.text && (
|
||||||
<MixedInput
|
<MixedInput
|
||||||
updateDraft={getUpdateDraft()}
|
updateDraft={getUpdateDraft()}
|
||||||
initialValue={getDraft()}
|
initialValue={getDraft()}
|
||||||
members={members}
|
members={members}
|
||||||
id={`${context}_${id}`}
|
id={`${context}_${id}`}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
sendMessages={handleSendMessage}
|
sendMessages={handleSendMessage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Toolbar
|
||||||
|
context={context}
|
||||||
|
to={id}
|
||||||
|
mode={mode}
|
||||||
|
toggleMode={toggleMode}
|
||||||
|
fullscreen={markdownFullscreen}
|
||||||
|
toggleMarkdownFullscreen={toggleMarkdownFullscreen}
|
||||||
/>
|
/>
|
||||||
)}
|
{mode == Modes.markdown && (
|
||||||
<Toolbar
|
<MarkdownEditor
|
||||||
context={context}
|
updateDraft={getUpdateDraft("markdown")}
|
||||||
to={id}
|
initialValue={getDraft("markdown")}
|
||||||
mode={mode}
|
height={markdownFullscreen ? `calc(100vh - 168px)` : `30vh`}
|
||||||
toggleMode={toggleMode}
|
placeholder={placeholder}
|
||||||
fullscreen={markdownFullscreen}
|
setEditorInstance={setMarkdownEditor}
|
||||||
toggleMarkdownFullscreen={toggleMarkdownFullscreen}
|
sendMarkdown={sendMarkdown}
|
||||||
/>
|
/>
|
||||||
{mode == Modes.markdown && (
|
)}
|
||||||
<MarkdownEditor
|
</div>
|
||||||
updateDraft={getUpdateDraft("markdown")}
|
|
||||||
initialValue={getDraft("markdown")}
|
|
||||||
height={markdownFullscreen ? `calc(100vh - 168px)` : `30vh`}
|
|
||||||
placeholder={placeholder}
|
|
||||||
setEditorInstance={setMarkdownEditor}
|
|
||||||
sendMarkdown={sendMarkdown}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { ChangeEvent, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import TextareaAutoSize from "react-textarea-autosize";
|
||||||
|
|
||||||
|
import Button from "../styled/Button";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
placeholder: string,
|
||||||
|
sendMessage: any
|
||||||
|
}
|
||||||
|
const TextInput = ({ sendMessage, placeholder }: Props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [currMsg, setCurrMsg] = useState("");
|
||||||
|
const handleMsgChange = (evt: ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
setCurrMsg(evt.target.value);
|
||||||
|
};
|
||||||
|
const handleSend = () => {
|
||||||
|
if (!currMsg) return;
|
||||||
|
// todo
|
||||||
|
const msg = [{ type: "text", content: currMsg }];
|
||||||
|
sendMessage(msg);
|
||||||
|
setCurrMsg("");
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className='md:hidden relative mb-1 p-1 flex items-center w-full text-gray-600 dark:text-white bg-gray-200 dark:bg-gray-600 rounded-lg'>
|
||||||
|
<TextareaAutoSize
|
||||||
|
autoFocus
|
||||||
|
onFocus={(e) =>
|
||||||
|
e.currentTarget.setSelectionRange(
|
||||||
|
e.currentTarget.value.length,
|
||||||
|
e.currentTarget.value.length
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// ref={inputRef}
|
||||||
|
className="p-1 w-full min-h-[28px] resize-none bg-transparent text-gray-800 dark:text-white text-sm break-all"
|
||||||
|
maxRows={8}
|
||||||
|
minRows={1}
|
||||||
|
// onKeyDown={handleInputKeydown}
|
||||||
|
onChange={handleMsgChange}
|
||||||
|
value={currMsg}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<Button onClick={handleSend} className="mini absolute right-1.5 bottom-1.5">{t("action.send")}</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TextInput;
|
||||||
@@ -2,7 +2,8 @@ import { forwardRef, TextareaHTMLAttributes } from "react";
|
|||||||
|
|
||||||
type Props = TextareaHTMLAttributes<HTMLTextAreaElement>
|
type Props = TextareaHTMLAttributes<HTMLTextAreaElement>
|
||||||
const StyledTextarea = forwardRef(({ className, ...rest }: Props, ref) => {
|
const StyledTextarea = forwardRef(({ className, ...rest }: Props, ref) => {
|
||||||
return <textarea ref={ref} className={`rounded text-sm p-2 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 resize-none w-full shadow-sm border border-gray-200 dark:border-gray-400
|
return <textarea ref={ref} className={`rounded text-sm p-2 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 resize-none w-full shadow-sm
|
||||||
|
border border-solid border-gray-200 dark:border-gray-400
|
||||||
disabled:bg-gray-100 dark:disabled:bg-gray-800/50
|
disabled:bg-gray-100 dark:disabled:bg-gray-800/50
|
||||||
disabled:text-gray-400 dark:disabled:text-gray-500
|
disabled:text-gray-400 dark:disabled:text-gray-500
|
||||||
disabled:pointer-events-none
|
disabled:pointer-events-none
|
||||||
|
|||||||
Reference in New Issue
Block a user