blowater/UI/dm.tsx

204 lines
8.1 KiB
TypeScript
Raw Normal View History

2023-06-30 14:05:57 +00:00
/** @jsx h */
2023-10-19 03:44:43 +00:00
import { h, JSX, VNode } from "https://esm.sh/preact@10.17.1";
2023-06-30 14:05:57 +00:00
import { tw } from "https://esm.sh/twind@0.16.16";
2023-09-23 21:54:13 +00:00
import * as cl from "./conversation-list.tsx";
2023-06-30 14:05:57 +00:00
import { MessagePanel, RightPanelModel } from "./message-panel.tsx";
2023-10-04 21:34:43 +00:00
import { EventBus } from "../event-bus.ts";
2023-06-30 14:05:57 +00:00
import { LeftArrowIcon } from "./icons/left-arrow-icon.tsx";
2023-10-04 15:07:40 +00:00
import { CenterClass, IconButtonClass } from "./components/tw.ts";
2023-10-09 18:52:30 +00:00
import { DirectMessageGetter, GroupMessageGetter, UI_Interaction_Event } from "./app_update.tsx";
import { NostrAccountContext, NostrEvent } from "../lib/nostr-ts/nostr.ts";
2023-08-28 17:58:05 +00:00
import { ConnectionPool } from "../lib/nostr-ts/relay.ts";
import { ProfileSyncer } from "../features/profile.ts";
2023-06-30 14:05:57 +00:00
import { getFocusedContent } from "./app.tsx";
import { EventSyncer } from "./event_syncer.ts";
2023-10-04 15:07:40 +00:00
import { ButtonGroup } from "./components/button-group.tsx";
import { PrimaryTextColor } from "./style/colors.ts";
import { SettingIcon } from "./icons2/setting-icon.tsx";
import { GroupMessageController } from "../features/gm.ts";
import { ProfileGetter } from "./search.tsx";
2023-10-07 17:15:27 +00:00
import { InviteIcon } from "./icons2/invite-icon.tsx";
import { PublicKey } from "../lib/nostr-ts/key.ts";
2023-10-09 18:52:30 +00:00
import { ChatMessage } from "./message.ts";
import { EditorModel } from "./editor.tsx";
2023-10-19 03:44:43 +00:00
import { InviteButton } from "./invite-button.tsx";
import { IsGruopChatSupported } from "./conversation-list.tsx";
2023-10-09 18:52:30 +00:00
export type DM_Model = {
currentEditor: EditorModel | undefined;
2023-10-15 22:39:21 +00:00
focusedContent: Map<string, NostrEvent | PublicKey>;
2023-10-09 18:52:30 +00:00
isGroupMessage: boolean;
};
2023-06-30 14:05:57 +00:00
type DirectMessageContainerProps = {
rightPanelModel: RightPanelModel;
2023-10-04 21:34:43 +00:00
ctx: NostrAccountContext;
2023-06-30 14:05:57 +00:00
pool: ConnectionPool;
2023-10-04 21:34:43 +00:00
bus: EventBus<UI_Interaction_Event>;
2023-10-01 20:59:07 +00:00
profilesSyncer: ProfileSyncer;
eventSyncer: EventSyncer;
groupChatController: GroupMessageController;
// getters
profileGetter: ProfileGetter;
dmGetter: DirectMessageGetter;
gmGetter: GroupMessageGetter;
pinListGetter: cl.PinListGetter;
conversationLists: cl.ConversationListRetriever;
2023-10-07 20:40:18 +00:00
newMessageChecker: cl.NewMessageChecker;
} & DM_Model;
2023-06-30 14:05:57 +00:00
2023-10-07 17:15:27 +00:00
export type StartInvite = {
type: "StartInvite";
publicKey: PublicKey;
};
2023-06-30 14:05:57 +00:00
export function DirectMessageContainer(props: DirectMessageContainerProps) {
const t = Date.now();
let messagePanel: VNode | undefined;
2023-10-07 20:40:18 +00:00
if (props.currentEditor && props.currentEditor) {
2023-06-30 14:05:57 +00:00
const convoMsgs = getConversationMessages({
2023-10-07 20:40:18 +00:00
targetPubkey: props.currentEditor.pubkey.hex,
isGroupChat: props.isGroupMessage,
dmGetter: props.dmGetter,
gmGetter: props.gmGetter,
2023-06-30 14:05:57 +00:00
});
const focusedContent = getFocusedContent(
2023-10-07 20:40:18 +00:00
props.focusedContent.get(props.currentEditor.pubkey.hex),
props.profileGetter,
);
messagePanel = new MessagePanel({
2023-10-04 21:34:43 +00:00
myPublicKey: props.ctx.publicKey,
2023-06-30 14:05:57 +00:00
messages: convoMsgs,
rightPanelModel: props.rightPanelModel,
2023-10-04 21:34:43 +00:00
emit: props.bus.emit,
2023-06-30 14:05:57 +00:00
focusedContent: focusedContent,
profilesSyncer: props.profilesSyncer,
eventSyncer: props.eventSyncer,
isGroupChat: props.isGroupMessage,
profileGetter: props.profileGetter,
2023-10-07 20:40:18 +00:00
editorModel: props.currentEditor,
}).render();
2023-06-30 14:05:57 +00:00
}
2023-10-07 17:15:27 +00:00
const currentEditor = props.currentEditor;
2023-10-19 03:44:43 +00:00
let actions: JSX.Element | undefined;
if (currentEditor && IsGruopChatSupported) {
const canEditGroupProfile = props.isGroupMessage &&
props.groupChatController.getGroupAdminCtx(currentEditor.pubkey);
actions = canEditGroupProfile
? (
<ButtonGroup>
<button
class={tw`w-8 h-8 ${CenterClass}`}
onClick={() => {
props.bus.emit({
type: "StartInvite",
publicKey: currentEditor.pubkey,
});
}}
>
<InviteIcon
class={tw`w-6 h-6 text-[${PrimaryTextColor}] fill-current`}
/>
</button>
<button
class={tw`w-8 h-8 ${CenterClass}`}
onClick={() => {
props.bus.emit({
type: "StartEditGroupChatProfile",
publicKey: currentEditor.pubkey,
});
}}
>
<SettingIcon
class={tw`w-6 h-6 text-[${PrimaryTextColor}] stroke-current`}
style={{ fill: "none" }}
/>
</button>
</ButtonGroup>
)
: (
<ButtonGroup>
<InviteButton
groupChatController={props.groupChatController}
profileGetter={props.profileGetter}
userPublicKey={currentEditor.pubkey}
emit={props.bus.emit}
2023-10-07 17:15:27 +00:00
/>
2023-10-19 03:44:43 +00:00
</ButtonGroup>
);
}
2023-06-30 14:05:57 +00:00
const vDom = (
<div
class={tw`h-full w-full flex bg-[#36393F] overflow-hidden`}
>
2023-10-07 20:40:18 +00:00
<div class={tw`${props.currentEditor ? "mobile:hidden" : "mobile:w-full"}`}>
<cl.ConversationList
2023-10-04 21:34:43 +00:00
eventBus={props.bus}
emit={props.bus.emit}
2023-10-04 15:07:40 +00:00
convoListRetriever={props.conversationLists}
groupChatListGetter={props.groupChatController}
2023-10-07 20:40:18 +00:00
hasNewMessages={props.newMessageChecker}
{...props}
/>
2023-06-30 14:05:57 +00:00
</div>
2023-10-07 20:40:18 +00:00
{props.currentEditor
2023-06-30 14:05:57 +00:00
? (
<div class={tw`flex-1 overflow-hidden flex-col flex`}>
<div
2023-10-04 15:07:40 +00:00
class={tw`h-14 border-l border-b border-[#36393F] flex items-center justify-between px-5 bg-[#2F3136]`}
2023-06-30 14:05:57 +00:00
>
2023-10-04 15:07:40 +00:00
<div class={tw`flex items-center`}>
<button
onClick={() => {
2023-10-04 21:34:43 +00:00
props.bus.emit({
2023-10-04 15:07:40 +00:00
type: "BackToContactList",
});
2023-06-30 14:05:57 +00:00
}}
2023-10-04 15:07:40 +00:00
class={tw`w-6 h-6 mr-4 desktop:hidden ${IconButtonClass}`}
>
<LeftArrowIcon
class={tw`w-4 h-4`}
style={{
fill: "rgb(185, 187, 190)",
}}
/>
</button>
<span class={tw`text-[#F3F4EA] text-[1.2rem] whitespace-nowrap truncate`}>
2023-10-07 20:40:18 +00:00
{props.profileGetter.getProfilesByPublicKey(props.currentEditor.pubkey)
?.profile.name ||
2023-10-07 20:40:18 +00:00
props.currentEditor.pubkey.bech32()}
2023-10-04 15:07:40 +00:00
</span>
</div>
2023-10-19 03:44:43 +00:00
{actions}
2023-06-30 14:05:57 +00:00
</div>
<div class={tw`flex-1 overflow-x-auto`}>
{messagePanel}
</div>
</div>
)
: undefined}
</div>
);
console.debug("DirectMessageContainer:end", Date.now() - t);
return vDom;
}
2023-10-09 18:52:30 +00:00
export function getConversationMessages(args: {
targetPubkey: string;
isGroupChat: boolean;
dmGetter: DirectMessageGetter;
gmGetter: GroupMessageGetter;
}): ChatMessage[] {
const { targetPubkey } = args;
if (args.isGroupChat) {
return args.gmGetter.getGroupMessages(args.targetPubkey);
}
let messages = args.dmGetter.getDirectMessages(targetPubkey);
return messages;
}