mirror of
https://github.com/BlowaterNostr/blowater.git
synced 2024-10-18 07:33:22 +00:00
Modal Component (#465)
This commit is contained in:
parent
d457cf089e
commit
5dcf8267bd
@ -33,6 +33,7 @@ import { getTags, Parsed_Event } from "../nostr.ts";
|
||||
import { Toast } from "./components/toast.tsx";
|
||||
import { ToastChannel } from "./components/toast.tsx";
|
||||
import { RightPanelChannel } from "./components/right-panel.tsx";
|
||||
import { Modal, ModalInputChannel } from "./components/modal.tsx";
|
||||
import { func_IsAdmin } from "./message-list.tsx";
|
||||
import { getRelayInformation } from "../../libs/nostr.ts/nip11.ts";
|
||||
|
||||
@ -52,6 +53,7 @@ export async function Start(database: DexieDatabase) {
|
||||
const eventBus = new EventBus<UI_Interaction_Event>();
|
||||
const popOverInputChan: PopOverInputChannel = new Channel();
|
||||
const rightPanelInputChan: RightPanelChannel = new Channel();
|
||||
const modalInputChan: ModalInputChannel = new Channel();
|
||||
const toastInputChan: ToastChannel = new Channel();
|
||||
const dbView = await Database_View.New(database, database, database);
|
||||
|
||||
@ -74,6 +76,7 @@ export async function Start(database: DexieDatabase) {
|
||||
pool: new ConnectionPool({ signer: ctx }),
|
||||
popOverInputChan,
|
||||
rightPanelInputChan,
|
||||
modalInputChan,
|
||||
otherConfig,
|
||||
lamport,
|
||||
installPrompt,
|
||||
@ -91,6 +94,7 @@ export async function Start(database: DexieDatabase) {
|
||||
model={model}
|
||||
popOverInputChan={popOverInputChan}
|
||||
rightPanelInputChan={rightPanelInputChan}
|
||||
modalInputChan={modalInputChan}
|
||||
installPrompt={installPrompt}
|
||||
toastInputChan={toastInputChan}
|
||||
/>,
|
||||
@ -104,6 +108,7 @@ export async function Start(database: DexieDatabase) {
|
||||
dbView: dbView,
|
||||
popOver: popOverInputChan,
|
||||
rightPanel: rightPanelInputChan,
|
||||
modal: modalInputChan,
|
||||
lamport,
|
||||
installPrompt,
|
||||
toastInputChan: toastInputChan,
|
||||
@ -117,6 +122,7 @@ export async function Start(database: DexieDatabase) {
|
||||
model={model}
|
||||
popOverInputChan={popOverInputChan}
|
||||
rightPanelInputChan={rightPanelInputChan}
|
||||
modalInputChan={modalInputChan}
|
||||
installPrompt={installPrompt}
|
||||
toastInputChan={toastInputChan}
|
||||
/>,
|
||||
@ -136,6 +142,7 @@ export class App {
|
||||
public readonly pool: ConnectionPool,
|
||||
public readonly popOverInputChan: PopOverInputChannel,
|
||||
public readonly rightPanelInputChan: RightPanelChannel,
|
||||
public readonly modalInputChan: ModalInputChannel,
|
||||
public readonly otherConfig: OtherConfig,
|
||||
public readonly conversationLists: DM_List,
|
||||
public readonly relayConfig: RelayConfig,
|
||||
@ -152,6 +159,7 @@ export class App {
|
||||
pool: ConnectionPool;
|
||||
popOverInputChan: PopOverInputChannel;
|
||||
rightPanelInputChan: RightPanelChannel;
|
||||
modalInputChan: ModalInputChannel;
|
||||
otherConfig: OtherConfig;
|
||||
lamport: LamportTime;
|
||||
installPrompt: InstallPrompt;
|
||||
@ -247,6 +255,7 @@ export class App {
|
||||
args.pool,
|
||||
args.popOverInputChan,
|
||||
args.rightPanelInputChan,
|
||||
args.modalInputChan,
|
||||
args.otherConfig,
|
||||
conversationLists,
|
||||
relayConfig,
|
||||
@ -274,6 +283,7 @@ export class App {
|
||||
model={this.model}
|
||||
popOverInputChan={this.popOverInputChan}
|
||||
rightPanelInputChan={this.rightPanelInputChan}
|
||||
modalInputChan={this.modalInputChan}
|
||||
installPrompt={installPrompt}
|
||||
toastInputChan={this.toastInputChan}
|
||||
/>,
|
||||
@ -305,6 +315,7 @@ export class App {
|
||||
model={this.model}
|
||||
popOverInputChan={this.popOverInputChan}
|
||||
rightPanelInputChan={this.rightPanelInputChan}
|
||||
modalInputChan={this.modalInputChan}
|
||||
installPrompt={installPrompt}
|
||||
toastInputChan={this.toastInputChan}
|
||||
/>,
|
||||
@ -326,6 +337,7 @@ type AppProps = {
|
||||
eventBus: AppEventBus;
|
||||
popOverInputChan: PopOverInputChannel;
|
||||
rightPanelInputChan: RightPanelChannel;
|
||||
modalInputChan: ModalInputChannel;
|
||||
toastInputChan: ToastChannel;
|
||||
installPrompt: InstallPrompt;
|
||||
};
|
||||
@ -495,6 +507,7 @@ export class AppComponent extends Component<AppProps, {
|
||||
inputChan={props.rightPanelInputChan}
|
||||
/>
|
||||
<Toast inputChan={props.toastInputChan} />
|
||||
<Modal inputChan={props.modalInputChan} />
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -62,7 +62,7 @@ import { SyncEvent } from "./message-panel.tsx";
|
||||
import { SendingEventRejection, ToastChannel } from "./components/toast.tsx";
|
||||
import { SingleRelayConnection } from "../../libs/nostr.ts/relay-single.ts";
|
||||
import { default_blowater_relay } from "./relay-config.ts";
|
||||
import { forever, setState } from "./_helper.ts";
|
||||
import { forever } from "./_helper.ts";
|
||||
import { DeleteEvent, func_GetEventByID } from "./message-list.tsx";
|
||||
import { FilterContent } from "./filter.tsx";
|
||||
import { CloseRightPanel } from "./components/right-panel.tsx";
|
||||
@ -70,7 +70,7 @@ import { RightPanelChannel } from "./components/right-panel.tsx";
|
||||
import { ReplyToMessage } from "./message-list.tsx";
|
||||
import { EditorSelectProfile } from "./editor.tsx";
|
||||
import { uploadFile } from "../../libs/nostr.ts/nip96.ts";
|
||||
import * as csp from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
||||
import { HideModal, ModalInputChannel } from "./components/modal.tsx";
|
||||
|
||||
export type UI_Interaction_Event =
|
||||
| SearchUpdate
|
||||
@ -92,6 +92,7 @@ export type UI_Interaction_Event =
|
||||
| UnblockUser
|
||||
| SelectSpace
|
||||
| HidePopOver
|
||||
| HideModal
|
||||
| SyncEvent
|
||||
| FilterContent
|
||||
| CloseRightPanel
|
||||
@ -121,6 +122,7 @@ export function UI_Interaction_Update(args: {
|
||||
dbView: Database_View;
|
||||
popOver: PopOverInputChannel;
|
||||
rightPanel: RightPanelChannel;
|
||||
modal: ModalInputChannel;
|
||||
lamport: LamportTime;
|
||||
installPrompt: InstallPrompt;
|
||||
toastInputChan: ToastChannel;
|
||||
@ -136,6 +138,7 @@ const handle_update_event = async (chan: PutChannel<true>, args: {
|
||||
dbView: Database_View;
|
||||
popOver: PopOverInputChannel;
|
||||
rightPanel: RightPanelChannel;
|
||||
modal: ModalInputChannel;
|
||||
lamport: LamportTime;
|
||||
installPrompt: InstallPrompt;
|
||||
toastInputChan: ToastChannel;
|
||||
@ -161,6 +164,7 @@ const handle_update_event = async (chan: PutChannel<true>, args: {
|
||||
pool,
|
||||
popOverInputChan: args.popOver,
|
||||
rightPanelInputChan: args.rightPanel,
|
||||
modalInputChan: args.modal,
|
||||
otherConfig,
|
||||
lamport: args.lamport,
|
||||
installPrompt,
|
||||
@ -210,6 +214,11 @@ const handle_update_event = async (chan: PutChannel<true>, args: {
|
||||
/>
|
||||
);
|
||||
args.popOver.put({ children: search });
|
||||
} else if (event.type == "HideModal") {
|
||||
await app.modalInputChan.put({
|
||||
children: undefined,
|
||||
onClose: event.onClose,
|
||||
});
|
||||
} //
|
||||
//
|
||||
// Setting
|
||||
|
59
app/UI/components/modal.test.tsx
Normal file
59
app/UI/components/modal.test.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
/** @jsx h */
|
||||
import { h, render } from "https://esm.sh/preact@10.17.1";
|
||||
import { HideModal, Modal, ModalInputChannel } from "./modal.tsx";
|
||||
import { Channel } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
||||
import { CenterClass } from "./tw.ts";
|
||||
import { testEventBus } from "../_setup.test.ts";
|
||||
import { emitFunc } from "../../event-bus.ts";
|
||||
|
||||
const modalChan: ModalInputChannel = new Channel();
|
||||
|
||||
function ModalTest(props: {
|
||||
emit: emitFunc<HideModal>;
|
||||
}) {
|
||||
return (
|
||||
<div class={`${CenterClass} w-screen h-screen text-white`}>
|
||||
<button
|
||||
class={`rounded bg-black px-4 py2`}
|
||||
onClick={async () => {
|
||||
await modalChan.put({
|
||||
children: (
|
||||
<div class="h-20 w-40 bg-white text-black rounded flex flex-col justify-center items-center">
|
||||
<div>
|
||||
Modal Test
|
||||
</div>
|
||||
<button
|
||||
class="rounded bg-[#007FFF] px-4 py2"
|
||||
onClick={async () => {
|
||||
await props.emit({
|
||||
type: "HideModal",
|
||||
onClose() {
|
||||
console.log("close the modal by HideModal");
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
close
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
onClose() {
|
||||
console.log("close the modal by click");
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
Show
|
||||
</button>
|
||||
<Modal inputChan={modalChan} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render(<ModalTest emit={testEventBus.emit} />, document.body);
|
||||
|
||||
for await (const event of testEventBus.onChange()) {
|
||||
if (event.type === "HideModal") {
|
||||
await modalChan.put({ children: undefined, onClose: event.onClose });
|
||||
}
|
||||
}
|
59
app/UI/components/modal.tsx
Normal file
59
app/UI/components/modal.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
/** @jsx h */
|
||||
import { Component, ComponentChildren, h } from "https://esm.sh/preact@10.17.1";
|
||||
import { Channel } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
||||
import { setState } from "../_helper.ts";
|
||||
|
||||
export type HideModal = {
|
||||
type: "HideModal";
|
||||
onClose?: () => void;
|
||||
};
|
||||
|
||||
type State = {
|
||||
show: boolean;
|
||||
};
|
||||
|
||||
export type ModalInputChannel = Channel<{ children: ComponentChildren; onClose?: () => void }>;
|
||||
export class Modal extends Component<{
|
||||
inputChan: ModalInputChannel;
|
||||
}, State> {
|
||||
state: State = { show: false };
|
||||
children: ComponentChildren = undefined;
|
||||
onClose?: () => void;
|
||||
|
||||
async componentDidMount() {
|
||||
for await (const { children, onClose } of this.props.inputChan) {
|
||||
this.onClose = onClose;
|
||||
if (children) {
|
||||
await this.show(children);
|
||||
} else {
|
||||
await this.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
show = async (children: ComponentChildren) => {
|
||||
this.children = children;
|
||||
await setState(this, { show: true });
|
||||
};
|
||||
|
||||
hide = async () => {
|
||||
await setState(this, { show: false });
|
||||
if (this.onClose) this.onClose();
|
||||
};
|
||||
|
||||
render() {
|
||||
if (!this.state.show) return;
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center z-30">
|
||||
<div
|
||||
className="fixed inset-0 z-[-1] bg-[#0A0A0A] bg-opacity-50 cursor-pointer"
|
||||
onClick={this.hide}
|
||||
>
|
||||
</div>
|
||||
<div className={`absolute`}>
|
||||
{this.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user