/** @jsx h */ import { createRef, h } from "https://esm.sh/preact@10.17.1"; import { CenterClass, LinearGradientsClass, NoOutlineClass } from "./components/tw.ts"; import { emitFunc } from "../event-bus.ts"; import { NostrKind } from "../../libs/nostr.ts/nostr.ts"; import { PublicKey } from "../../libs/nostr.ts/key.ts"; import { ImageIcon } from "./icons/image-icon.tsx"; import { DividerBackgroundColor, PrimaryBackgroundColor, PrimaryTextColor } from "./style/colors.ts"; import { SendIcon } from "./icons/send-icon.tsx"; import { Component } from "https://esm.sh/preact@10.17.1"; import { RemoveIcon } from "./icons/remove-icon.tsx"; import { isMobile, setState } from "./_helper.ts"; import { XCircleIcon } from "./icons/x-circle-icon.tsx"; import { func_GetEventByID } from "./message-list.tsx"; import { ProfileGetter } from "./search.tsx"; import { NoteID } from "../../libs/nostr.ts/nip19.ts"; export type EditorEvent = SendMessage | UpdateEditorText | UpdateMessageFiles; export type SendMessage = { readonly type: "SendMessage"; readonly text: string; readonly files: Blob[]; readonly reply_to_event_id?: string | NoteID; }; export type UpdateEditorText = { readonly type: "UpdateEditorText"; readonly pubkey: PublicKey; readonly isGroupChat: boolean; readonly text: string; }; export type UpdateMessageFiles = { readonly type: "UpdateMessageFiles"; readonly pubkey: PublicKey; readonly isGroupChat: boolean; readonly files: Blob[]; }; type EditorProps = { readonly replyTo?: { eventID?: string | NoteID; onEventIDChange: (eventID?: string | NoteID) => void; }; readonly placeholder: string; readonly maxHeight: string; readonly emit: emitFunc; readonly getters: { getEventByID: func_GetEventByID; profileGetter: ProfileGetter; }; }; export type EditorState = { text: string; files: Blob[]; }; export class Editor extends Component { state: Readonly = { text: "", files: [], }; textareaElement = createRef(); sendMessage = async () => { const props = this.props; props.emit({ type: "SendMessage", files: this.state.files, text: this.state.text, reply_to_event_id: this.props.replyTo?.eventID, }); this.textareaElement.current?.setAttribute( "rows", "1", ); this.props.replyTo?.onEventIDChange(undefined); await setState(this, { text: "", files: [] }); }; removeFile = (index: number) => { const files = this.state.files; const newFiles = files.slice(0, index).concat(files.slice(index + 1)); this.setState({ files: newFiles, }); }; render(props: EditorProps, state: EditorState) { const uploadFileInput = createRef(); return (
{ReplyIndicator({ getters: props.getters, replyTo: props.replyTo, })}
{ let propsfiles = this.state.files; const files = e.currentTarget.files; if (!files) { return; } for (let i = 0; i < files.length; i++) { const file = files.item(i); if (!file) { continue; } propsfiles = propsfiles.concat([file]); } await setState(this, { files: propsfiles, }); }} class={`hidden`} />
{this.state.files.length > 0 ? (
    {this.state.files.map((file, index) => { return (
  • ); })}
) : undefined}
); } } function ReplyIndicator(props: { readonly replyTo?: { eventID?: string | NoteID; onEventIDChange: (eventID?: string | NoteID) => void; }; getters: { getEventByID: func_GetEventByID; profileGetter: ProfileGetter; }; }) { if (!props.replyTo || !props.replyTo.eventID) { return undefined; } const ctx = props.getters.getEventByID(props.replyTo.eventID)?.publicKey; if (!ctx) { return undefined; } const profile = props.getters.profileGetter.getProfilesByPublicKey(ctx)?.profile; let replyToAuthor = profile?.name || profile?.display_name; if (!replyToAuthor) { replyToAuthor = ctx.bech32(); } else { replyToAuthor = `@${replyToAuthor}`; } return (
); }