fix: note creator mobile
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing

This commit is contained in:
Kieran 2023-10-21 22:26:04 +01:00
parent 63950f1e6b
commit c2991b8e26
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
6 changed files with 23 additions and 31 deletions

View File

@ -1,7 +1,6 @@
import Icon from "Icons/Icon"; import Icon from "Icons/Icon";
import useLoading from "Hooks/useLoading"; import useLoading from "Hooks/useLoading";
import Spinner from "Icons/Spinner"; import Spinner from "Icons/Spinner";
import classNames from "classnames";
export type AsyncIconProps = React.HTMLProps<HTMLDivElement> & { export type AsyncIconProps = React.HTMLProps<HTMLDivElement> & {
iconName: string; iconName: string;
@ -17,7 +16,7 @@ export function AsyncIcon(props: AsyncIconProps) {
delete mergedProps["iconSize"]; delete mergedProps["iconSize"];
delete mergedProps["loading"]; delete mergedProps["loading"];
return ( return (
<div {...mergedProps} onClick={handle} className={classNames("button-icon-sm", props.className)}> <div {...mergedProps} onClick={handle} className={props.className}>
{loading ? <Spinner /> : <Icon name={props.iconName} size={props.iconSize} />} {loading ? <Spinner /> : <Icon name={props.iconName} size={props.iconSize} />}
{props.children} {props.children}
</div> </div>

View File

@ -34,7 +34,7 @@ export default function DmWindow({ id }: { id: string }) {
<div> <div>
<div className="flex flex-col">{chat && <DmChatSelected chat={chat} />}</div> <div className="flex flex-col">{chat && <DmChatSelected chat={chat} />}</div>
</div> </div>
<div> <div className="flex g8">
<WriteMessage chat={chat} /> <WriteMessage chat={chat} />
</div> </div>
</div> </div>

View File

@ -1,17 +1,14 @@
import { useState } from "react";
import { NostrEvent, NostrLink, NostrPrefix } from "@snort/system"; import { NostrEvent, NostrLink, NostrPrefix } from "@snort/system";
import useEventPublisher from "Hooks/useEventPublisher"; import useEventPublisher from "Hooks/useEventPublisher";
import Icon from "Icons/Icon";
import Spinner from "Icons/Spinner";
import { useState } from "react";
import useFileUpload from "Upload"; import useFileUpload from "Upload";
import { openFile } from "SnortUtils"; import { openFile } from "SnortUtils";
import Textarea from "../Textarea"; import Textarea from "../Textarea";
import { Chat } from "chat"; import { Chat } from "chat";
import { AsyncIcon } from "Element/AsyncIcon";
export default function WriteMessage({ chat }: { chat: Chat }) { export default function WriteMessage({ chat }: { chat: Chat }) {
const [msg, setMsg] = useState(""); const [msg, setMsg] = useState("");
const [sending, setSending] = useState(false);
const [uploading, setUploading] = useState(false);
const [otherEvents, setOtherEvents] = useState<Array<NostrEvent>>([]); const [otherEvents, setOtherEvents] = useState<Array<NostrEvent>>([]);
const [error, setError] = useState(""); const [error, setError] = useState("");
const { publisher, system } = useEventPublisher(); const { publisher, system } = useEventPublisher();
@ -31,7 +28,6 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
} }
async function uploadFile(file: File | Blob) { async function uploadFile(file: File | Blob) {
setUploading(true);
try { try {
if (file) { if (file) {
const rx = await uploader.upload(file, file.name); const rx = await uploader.upload(file, file.name);
@ -51,26 +47,20 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
if (e instanceof Error) { if (e instanceof Error) {
setError(e.message); setError(e.message);
} }
} finally {
setUploading(false);
} }
} }
async function sendMessage() { async function sendMessage() {
if (msg && publisher && chat) { if (msg && publisher && chat) {
setSending(true);
const ev = await chat.createMessage(msg, publisher); const ev = await chat.createMessage(msg, publisher);
await chat.sendMessage(ev, system); await chat.sendMessage(ev, system);
setMsg(""); setMsg("");
setSending(false);
} }
} }
function onChange(e: React.ChangeEvent<HTMLTextAreaElement>) { function onChange(e: React.ChangeEvent<HTMLTextAreaElement>) {
if (!sending) {
setMsg(e.target.value); setMsg(e.target.value);
} }
}
async function onEnter(e: React.KeyboardEvent<HTMLTextAreaElement>) { async function onEnter(e: React.KeyboardEvent<HTMLTextAreaElement>) {
const isEnter = e.code === "Enter"; const isEnter = e.code === "Enter";
@ -82,10 +72,8 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
return ( return (
<> <>
<button className="circle flex items-center" onClick={() => attachFile()}> <AsyncIcon className="circle flex items-center button" iconName="attachment" onClick={() => attachFile()} />
{uploading ? <Spinner width={20} /> : <Icon name="attachment" size={20} />} <div className="grow">
</button>
<div className="w-max">
<Textarea <Textarea
autoFocus={true} autoFocus={true}
placeholder="" placeholder=""
@ -99,9 +87,7 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
/> />
{error && <b className="error">{error}</b>} {error && <b className="error">{error}</b>}
</div> </div>
<button className="circle flex items-center" onClick={() => sendMessage()}> <AsyncIcon className="circle flex items-center button" iconName="arrow-right" onClick={() => sendMessage()} />
{sending ? <Spinner width={20} /> : <Icon name="arrow-right" size={20} />}
</button>
</> </>
); );
} }

View File

@ -16,6 +16,7 @@
.note-creator-modal .note.card { .note-creator-modal .note.card {
padding: 0; padding: 0;
border: none; border: none;
min-height: unset;
} }
.note-creator-modal .note.card.note-quote { .note-creator-modal .note.card.note-quote {

View File

@ -465,7 +465,9 @@ export function NoteCreator() {
onClick={() => note.update(v => (v.advanced = !v.advanced))} onClick={() => note.update(v => (v.advanced = !v.advanced))}
className={classNames("note-creator-icon", { active: note.advanced })} className={classNames("note-creator-icon", { active: note.advanced })}
/> />
<span className="sm:inline hidden">
<FormattedMessage defaultMessage="Preview" /> <FormattedMessage defaultMessage="Preview" />
</span>
<ToggleSwitch <ToggleSwitch
onClick={() => loadPreview()} onClick={() => loadPreview()}
size={40} size={40}
@ -546,10 +548,10 @@ export function NoteCreator() {
)} )}
{note.preview && getPreviewNote()} {note.preview && getPreviewNote()}
{!note.preview && ( {!note.preview && (
<div onPaste={handlePaste} className={`note-creator${note.pollOptions ? " poll" : ""}`}> <div onPaste={handlePaste} className={classNames("note-creator", { poll: Boolean(note.pollOptions) })}>
<Textarea <Textarea
autoFocus autoFocus
className={`textarea ${note.active ? "textarea--focused" : ""}`} className={classNames("textarea", { "textarea--focused": note.active })}
onChange={c => onChange(c)} onChange={c => onChange(c)}
value={note.note} value={note.note}
onFocus={() => note.update(v => (v.active = true))} onFocus={() => note.update(v => (v.active = true))}

View File

@ -241,10 +241,7 @@ small {
line-height: 22px; /* 157.143% */ line-height: 22px; /* 157.143% */
} }
button, .button {
[type="button"],
[type="reset"],
[type="submit"] {
position: relative; position: relative;
cursor: pointer; cursor: pointer;
padding: 10px 16px; padding: 10px 16px;
@ -257,6 +254,13 @@ button,
outline: none; outline: none;
} }
button,
[type="button"],
[type="reset"],
[type="submit"] {
@apply button;
}
.btn, .btn,
input, input,
select { select {
@ -809,7 +813,7 @@ button.tall {
} }
} }
.rta__textarea { .note-creator-modal .rta__textarea {
/* Fix width calculation to account for 32px padding on input */ /* Fix width calculation to account for 32px padding on input */
width: calc(100% - 32px) !important; width: calc(100% - 32px) !important;
font-size: 15px !important; font-size: 15px !important;