mirror of
https://github.com/BlowaterNostr/blowater.git
synced 2024-10-18 15:43:20 +00:00
fix ConversationList & simplify DirectMessageContainer (#359)
This commit is contained in:
parent
3f1bebb790
commit
e6a1819b72
42
UI/app.tsx
42
UI/app.tsx
@ -412,29 +412,23 @@ export function AppComponent(props: {
|
|||||||
) {
|
) {
|
||||||
if (model.navigationModel.activeNav == "DM") {
|
if (model.navigationModel.activeNav == "DM") {
|
||||||
dmVNode = (
|
dmVNode = (
|
||||||
<div
|
<DirectMessageContainer
|
||||||
class={tw`flex-1 overflow-hidden`}
|
{...model.dm}
|
||||||
>
|
rightPanelModel={model.rightPanelModel}
|
||||||
{DirectMessageContainer({
|
bus={app.eventBus}
|
||||||
...model.dm,
|
ctx={myAccountCtx}
|
||||||
rightPanelModel: model.rightPanelModel,
|
profileGetter={app.database}
|
||||||
bus: app.eventBus,
|
pool={props.pool}
|
||||||
ctx: myAccountCtx,
|
conversationLists={app.conversationLists}
|
||||||
profileGetter: app.database,
|
profilesSyncer={app.profileSyncer}
|
||||||
pool: props.pool,
|
eventSyncer={app.eventSyncer}
|
||||||
conversationLists: app.conversationLists,
|
pinListGetter={app.otherConfig}
|
||||||
profilesSyncer: app.profileSyncer,
|
groupChatController={app.groupChatController}
|
||||||
eventSyncer: app.eventSyncer,
|
newMessageChecker={app.conversationLists}
|
||||||
pinListGetter: app.otherConfig,
|
messageGetter={model.dm.isGroupMessage ? app.groupChatController : app.dmController}
|
||||||
groupChatController: app.groupChatController,
|
newMessageListener={model.dm.isGroupMessage ? app.groupChatController : app.dmController}
|
||||||
newMessageChecker: app.conversationLists,
|
relayRecordGetter={app.database}
|
||||||
messageGetter: model.dm.isGroupMessage ? app.groupChatController : app.dmController,
|
/>
|
||||||
newMessageListener: model.dm.isGroupMessage
|
|
||||||
? app.groupChatController
|
|
||||||
: app.dmController,
|
|
||||||
relayRecordGetter: app.database,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +440,7 @@ export function AppComponent(props: {
|
|||||||
console.debug("AppComponent:2", Date.now() - t);
|
console.debug("AppComponent:2", Date.now() - t);
|
||||||
|
|
||||||
const final = (
|
const final = (
|
||||||
<div class={tw`h-screen fixed w-full flex-1 flex overflow-hidden`}>
|
<div class={tw`h-screen w-full flex`}>
|
||||||
<nav.NavBar
|
<nav.NavBar
|
||||||
publicKey={app.ctx.publicKey}
|
publicKey={app.ctx.publicKey}
|
||||||
profileGetter={app.database}
|
profileGetter={app.database}
|
||||||
|
@ -6,7 +6,6 @@ import { Datebase_View } from "../database.ts";
|
|||||||
import { PrivateKey } from "../lib/nostr-ts/key.ts";
|
import { PrivateKey } from "../lib/nostr-ts/key.ts";
|
||||||
import { InMemoryAccountContext, NostrEvent, NostrKind } from "../lib/nostr-ts/nostr.ts";
|
import { InMemoryAccountContext, NostrEvent, NostrKind } from "../lib/nostr-ts/nostr.ts";
|
||||||
import { testEventBus } from "./_setup.test.ts";
|
import { testEventBus } from "./_setup.test.ts";
|
||||||
import { initialModel } from "./app_model.ts";
|
|
||||||
import { DM_List } from "./conversation-list.ts";
|
import { DM_List } from "./conversation-list.ts";
|
||||||
import { NewIndexedDB } from "./dexie-db.ts";
|
import { NewIndexedDB } from "./dexie-db.ts";
|
||||||
import { ProfileSyncer } from "../features/profile.ts";
|
import { ProfileSyncer } from "../features/profile.ts";
|
||||||
@ -16,7 +15,6 @@ import { GroupChatSyncer, GroupMessageController } from "../features/gm.ts";
|
|||||||
import { Channel } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
import { Channel } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
||||||
import { LamportTime } from "../time.ts";
|
import { LamportTime } from "../time.ts";
|
||||||
import { prepareEncryptedNostrEvent } from "../lib/nostr-ts/event.ts";
|
import { prepareEncryptedNostrEvent } from "../lib/nostr-ts/event.ts";
|
||||||
import { PublicKey } from "../lib/nostr-ts/nodejs/index.mjs";
|
|
||||||
|
|
||||||
const ctx = InMemoryAccountContext.Generate();
|
const ctx = InMemoryAccountContext.Generate();
|
||||||
const db = NewIndexedDB();
|
const db = NewIndexedDB();
|
||||||
|
@ -107,12 +107,15 @@ export class ConversationList extends Component<Props, State> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={tw`h-screen flex flex-col mobile:w-full desktop:w-64 bg-[${SecondaryBackgroundColor}]`}
|
// https://tailwindcss.com/docs/hover-focus-and-other-states#quick-reference
|
||||||
|
class={`
|
||||||
|
h-screen w-80 max-sm:w-full
|
||||||
|
flex flex-col bg-[${SecondaryBackgroundColor}]`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class={tw`flex items-center gap-2 px-4 h-20 border-b border-[#36393F]`}
|
class={`gap-2 py-2.5 px-4 border-b border-[#36393F]`}
|
||||||
>
|
>
|
||||||
<div class={`flex-1 ${LinearGradientsClass}} items-center`}>
|
<div class={`${LinearGradientsClass} flex items-center justify-center rounded-lg`}>
|
||||||
<button
|
<button
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
props.emit({
|
props.emit({
|
||||||
|
@ -69,7 +69,5 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body></body>
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -76,7 +76,5 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body></body>
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -69,8 +69,7 @@ pool.addRelayURL(relays[0]);
|
|||||||
const gmControl = new GroupMessageController(ctx, { add: (_) => {} }, { add: (_) => {} });
|
const gmControl = new GroupMessageController(ctx, { add: (_) => {} }, { add: (_) => {} });
|
||||||
const dmControl = new DirectedMessageController(ctx);
|
const dmControl = new DirectedMessageController(ctx);
|
||||||
|
|
||||||
const view = () => {
|
render(
|
||||||
return (
|
|
||||||
<DirectMessageContainer
|
<DirectMessageContainer
|
||||||
conversationLists={dm_list}
|
conversationLists={dm_list}
|
||||||
eventSyncer={new EventSyncer(pool, database)}
|
eventSyncer={new EventSyncer(pool, database)}
|
||||||
@ -91,11 +90,9 @@ const view = () => {
|
|||||||
newMessageChecker={dm_list}
|
newMessageChecker={dm_list}
|
||||||
newMessageListener={dmControl}
|
newMessageListener={dmControl}
|
||||||
relayRecordGetter={database}
|
relayRecordGetter={database}
|
||||||
/>
|
/>,
|
||||||
);
|
document.body,
|
||||||
};
|
);
|
||||||
|
|
||||||
render(view(), document.body);
|
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
for await (const event of database.subscribe()) {
|
for await (const event of database.subscribe()) {
|
||||||
@ -105,25 +102,3 @@ render(view(), document.body);
|
|||||||
dm_list.addEvents([event]);
|
dm_list.addEvents([event]);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
for await (const e of testEventBus.onChange()) {
|
|
||||||
console.log(e);
|
|
||||||
if (e.type == "SendMessage") {
|
|
||||||
const err = await handle_SendMessage(
|
|
||||||
e,
|
|
||||||
ctx,
|
|
||||||
lamport,
|
|
||||||
pool,
|
|
||||||
model.dmEditors,
|
|
||||||
model.gmEditors,
|
|
||||||
database,
|
|
||||||
gmControl,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (err instanceof Error) {
|
|
||||||
console.error("update:SendMessage", err);
|
|
||||||
continue; // todo: global error toast
|
|
||||||
}
|
|
||||||
}
|
|
||||||
render(view(), document.body);
|
|
||||||
}
|
|
||||||
|
143
UI/dm.tsx
143
UI/dm.tsx
@ -1,5 +1,5 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
import { h } from "https://esm.sh/preact@10.17.1";
|
import { Component, h, VNode } from "https://esm.sh/preact@10.17.1";
|
||||||
import * as cl from "./conversation-list.tsx";
|
import * as cl from "./conversation-list.tsx";
|
||||||
import { MessagePanel, NewMessageListener } from "./message-panel.tsx";
|
import { MessagePanel, NewMessageListener } from "./message-panel.tsx";
|
||||||
import { EventBus } from "../event-bus.ts";
|
import { EventBus } from "../event-bus.ts";
|
||||||
@ -22,6 +22,7 @@ import { UserIcon } from "./icons/user-icon.tsx";
|
|||||||
import { LeftArrowIcon } from "./icons/left-arrow-icon.tsx";
|
import { LeftArrowIcon } from "./icons/left-arrow-icon.tsx";
|
||||||
import { RelayRecordGetter } from "../database.ts";
|
import { RelayRecordGetter } from "../database.ts";
|
||||||
import { RightPanelModel } from "./right-panel.tsx";
|
import { RightPanelModel } from "./right-panel.tsx";
|
||||||
|
import { Channel, PopChannel } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
||||||
|
|
||||||
export type DM_Model = {
|
export type DM_Model = {
|
||||||
currentEditor: EditorModel | undefined;
|
currentEditor: EditorModel | undefined;
|
||||||
@ -52,7 +53,44 @@ export type StartInvite = {
|
|||||||
publicKey: PublicKey;
|
publicKey: PublicKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function DirectMessageContainer(props: DirectMessageContainerProps) {
|
type State = {
|
||||||
|
currentEditor: EditorModel | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class DirectMessageContainer extends Component<DirectMessageContainerProps, State> {
|
||||||
|
changes?: PopChannel<UI_Interaction_Event>;
|
||||||
|
|
||||||
|
state: State = {
|
||||||
|
currentEditor: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillUpdate(nextProps: Readonly<DirectMessageContainerProps>): void {
|
||||||
|
this.setState({
|
||||||
|
currentEditor: nextProps.currentEditor,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
this.setState({
|
||||||
|
currentEditor: this.props.currentEditor,
|
||||||
|
});
|
||||||
|
|
||||||
|
const changes = this.props.bus.onChange();
|
||||||
|
this.changes = changes;
|
||||||
|
for await (const change of changes) {
|
||||||
|
if (change.type == "SelectConversation") {
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
if (this.changes) {
|
||||||
|
this.changes.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(props: DirectMessageContainerProps) {
|
||||||
const t = Date.now();
|
const t = Date.now();
|
||||||
|
|
||||||
const currentEditor = props.currentEditor;
|
const currentEditor = props.currentEditor;
|
||||||
@ -112,7 +150,11 @@ export function DirectMessageContainer(props: DirectMessageContainerProps) {
|
|||||||
<div
|
<div
|
||||||
class={`h-full w-full flex bg-[#36393F] overflow-hidden`}
|
class={`h-full w-full flex bg-[#36393F] overflow-hidden`}
|
||||||
>
|
>
|
||||||
<div class={`${props.currentEditor ? "mobile:hidden" : "mobile:w-full"}`}>
|
<div
|
||||||
|
class={`w-fit
|
||||||
|
max-sm:w-full
|
||||||
|
${props.currentEditor ? "max-sm:hidden" : ""}`}
|
||||||
|
>
|
||||||
<cl.ConversationList
|
<cl.ConversationList
|
||||||
eventBus={props.bus}
|
eventBus={props.bus}
|
||||||
emit={props.bus.emit}
|
emit={props.bus.emit}
|
||||||
@ -122,13 +164,57 @@ export function DirectMessageContainer(props: DirectMessageContainerProps) {
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{props.currentEditor
|
|
||||||
|
{this.state.currentEditor
|
||||||
? (
|
? (
|
||||||
<div class={`h-screen flex-1 overflow-hidden flex-col flex`}>
|
<div class={`flex flex-col flex-1 overflow-hidden`}>
|
||||||
|
<TopBar
|
||||||
|
bus={this.props.bus}
|
||||||
|
buttons={buttons}
|
||||||
|
currentEditor={this.state.currentEditor}
|
||||||
|
profileGetter={this.props.profileGetter}
|
||||||
|
showRightPanel={this.props.rightPanelModel.show}
|
||||||
|
/>
|
||||||
|
<div class={`flex-1 overflow-auto`}>
|
||||||
|
<MessagePanel
|
||||||
|
myPublicKey={props.ctx.publicKey}
|
||||||
|
rightPanelModel={props.rightPanelModel}
|
||||||
|
emit={props.bus.emit}
|
||||||
|
newMessageListener={props.newMessageListener}
|
||||||
|
focusedContent={getFocusedContent(
|
||||||
|
props.focusedContent.get(this.state.currentEditor.pubkey.hex),
|
||||||
|
props.profileGetter,
|
||||||
|
)}
|
||||||
|
profilesSyncer={props.profilesSyncer}
|
||||||
|
eventSyncer={props.eventSyncer}
|
||||||
|
isGroupMessage={props.isGroupMessage}
|
||||||
|
profileGetter={props.profileGetter}
|
||||||
|
editorModel={this.state.currentEditor}
|
||||||
|
messageGetter={props.messageGetter}
|
||||||
|
relayRecordGetter={props.relayRecordGetter}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
: undefined}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
console.debug("DirectMessageContainer:end", Date.now() - t);
|
||||||
|
return vDom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function TopBar(props: {
|
||||||
|
bus: EventBus<UI_Interaction_Event>;
|
||||||
|
currentEditor: EditorModel;
|
||||||
|
profileGetter: ProfileGetter;
|
||||||
|
showRightPanel: boolean;
|
||||||
|
buttons: VNode[];
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
<div
|
<div
|
||||||
class={`h-14 mobile:h-12
|
class={`h-14 border-l border-b border-[#36393F] flex
|
||||||
border-l border-b border-[#36393F] flex
|
items-center justify-between bg-[#2F3136]`}
|
||||||
items-center justify-between px- mobile:px-2 bg-[#2F3136]`}
|
|
||||||
>
|
>
|
||||||
<div class={`flex items-center overflow-hidden`}>
|
<div class={`flex items-center overflow-hidden`}>
|
||||||
<button
|
<button
|
||||||
@ -162,24 +248,26 @@ export function DirectMessageContainer(props: DirectMessageContainerProps) {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.profileGetter.getProfilesByPublicKey(props.currentEditor.pubkey)
|
{props.profileGetter.getProfilesByPublicKey(
|
||||||
|
props.currentEditor.pubkey,
|
||||||
|
)
|
||||||
?.profile.name ||
|
?.profile.name ||
|
||||||
props.currentEditor.pubkey.bech32()}
|
props.currentEditor.pubkey.bech32()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{buttons}
|
{props.buttons}
|
||||||
|
|
||||||
{!props.rightPanelModel.show
|
{!props.showRightPanel
|
||||||
? (
|
? (
|
||||||
<button
|
<button
|
||||||
class={`absolute z-10 w-6 h-6 transition-transform duration-100 ease-in-out right-4 mobile:right-0 top-4${
|
class={`absolute z-10 w-6 h-6 transition-transform duration-100 ease-in-out right-4 mobile:right-0 top-4${
|
||||||
props.rightPanelModel.show ? " rotate-180" : ""
|
props.showRightPanel ? " rotate-180" : ""
|
||||||
} ${IconButtonClass}`}
|
} ${IconButtonClass}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.bus.emit({
|
props.bus.emit({
|
||||||
type: "ToggleRightPanel",
|
type: "ToggleRightPanel",
|
||||||
show: !props.rightPanelModel.show,
|
show: !props.showRightPanel,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -194,34 +282,5 @@ export function DirectMessageContainer(props: DirectMessageContainerProps) {
|
|||||||
: undefined}
|
: undefined}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class={`flex-1 overflow-x-auto`}>
|
|
||||||
{props.currentEditor
|
|
||||||
? (
|
|
||||||
<MessagePanel
|
|
||||||
myPublicKey={props.ctx.publicKey}
|
|
||||||
rightPanelModel={props.rightPanelModel}
|
|
||||||
emit={props.bus.emit}
|
|
||||||
newMessageListener={props.newMessageListener}
|
|
||||||
focusedContent={getFocusedContent(
|
|
||||||
props.focusedContent.get(props.currentEditor.pubkey.hex),
|
|
||||||
props.profileGetter,
|
|
||||||
)}
|
|
||||||
profilesSyncer={props.profilesSyncer}
|
|
||||||
eventSyncer={props.eventSyncer}
|
|
||||||
isGroupMessage={props.isGroupMessage}
|
|
||||||
profileGetter={props.profileGetter}
|
|
||||||
editorModel={props.currentEditor}
|
|
||||||
messageGetter={props.messageGetter}
|
|
||||||
relayRecordGetter={props.relayRecordGetter}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
: undefined}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
: undefined}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
console.debug("DirectMessageContainer:end", Date.now() - t);
|
|
||||||
return vDom;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user