diff --git a/UI/app.tsx b/UI/app.tsx index 0076c49..fe9e0cd 100644 --- a/UI/app.tsx +++ b/UI/app.tsx @@ -467,14 +467,11 @@ export function AppComponent(props: {
- {nav.NavBar({ - profilePicURL: model.myProfile?.picture, - publicKey: myAccountCtx.publicKey, - database: app.database, - pool: props.pool, - emit: app.eventBus.emit, - ...model.navigationModel, - })} +
{ - }
diff --git a/UI/app_update.tsx b/UI/app_update.tsx index 0f8c1f5..08d1ca0 100644 --- a/UI/app_update.tsx +++ b/UI/app_update.tsx @@ -255,7 +255,7 @@ export async function* UI_Interaction_Update(args: { // Navigation // else if (event.type == "ChangeNavigation") { - model.navigationModel.activeNav = event.index; + model.navigationModel.activeNav = event.id; model.rightPanelModel = { show: false, }; diff --git a/UI/icons2/about-icon.tsx b/UI/icons2/about-icon.tsx new file mode 100644 index 0000000..1ef292d --- /dev/null +++ b/UI/icons2/about-icon.tsx @@ -0,0 +1,40 @@ +/** @jsx h */ +import { h } from "https://esm.sh/preact@10.17.1"; + +export function AboutIcon(props: { + class?: string | h.JSX.SignalLike | undefined; + style?: + | string + | h.JSX.CSSProperties + | h.JSX.SignalLike + | undefined; +}) { + return ( + + + + + + + + + + + + + ); +} diff --git a/UI/icons2/app-list-icon.tsx b/UI/icons2/app-list-icon.tsx new file mode 100644 index 0000000..af2a408 --- /dev/null +++ b/UI/icons2/app-list-icon.tsx @@ -0,0 +1,27 @@ +/** @jsx h */ +import { h } from "https://esm.sh/preact@10.17.1"; + +export function AppListIcon(props: { + class?: string | h.JSX.SignalLike | undefined; + style?: + | string + | h.JSX.CSSProperties + | h.JSX.SignalLike + | undefined; +}) { + return ( + + + + + + + + + ); +} diff --git a/UI/nav.test.tsx b/UI/nav.test.tsx index c54af59..20bde8f 100644 --- a/UI/nav.test.tsx +++ b/UI/nav.test.tsx @@ -1,41 +1,24 @@ /** @jsx h */ import { h, render } from "https://esm.sh/preact@10.17.1"; - -import { NewIndexedDB } from "./dexie-db.ts"; - -import * as nav from "./nav.tsx"; +import { NavBar } from "./nav.tsx"; +import { InMemoryAccountContext } from "../lib/nostr-ts/nostr.ts"; +import { Database_Contextual_View } from "../database.ts"; +import { fail } from "https://deno.land/std@0.176.0/testing/asserts.ts"; +import { testEventBus, testEventsAdapter } from "./_setup.test.ts"; import { tw } from "https://esm.sh/twind@0.16.16"; -import { EventBus } from "../event-bus.ts"; -import { UI_Interaction_Event } from "./app_update.ts"; -import { PublicKey } from "../lib/nostr-ts/key.ts"; -import { ConnectionPool } from "../lib/nostr-ts/relay.ts"; +const db = await Database_Contextual_View.New(testEventsAdapter); +if (db instanceof Error) fail(db.message); +const ctx = InMemoryAccountContext.Generate(); -const db = await NewIndexedDB(); -if (db instanceof Error) { - throw db; +render( +
+ + +
, + document.body, +); + +for await (const event of testEventBus.onChange()) { + console.log(event); } -const NavProps: nav.Props = { - publicKey: PublicKey.FromHex( - "0add27aa36e2e5e2591370f485af1344447705cfc37b1a1e6b0224be878c9687", - ) as PublicKey, - database: db, - pool: new ConnectionPool(), - eventEmitter: new EventBus(), - AddRelayButtonClickedError: "", - AddRelayInput: "", - activeNav: "DM", - picture: undefined, -}; - -export default function NavTest() { - return ( -
- -
- ); -} - -render(, document.body); diff --git a/UI/nav.tsx b/UI/nav.tsx index 9940101..b3f6047 100644 --- a/UI/nav.tsx +++ b/UI/nav.tsx @@ -1,14 +1,8 @@ /** @jsx h */ -import { h } from "https://esm.sh/preact@10.17.1"; +import { ComponentChild, h } from "https://esm.sh/preact@10.17.1"; import { tw } from "https://esm.sh/twind@0.16.16"; -import { AboutIcon, AppListIcon } from "./icons/mod.tsx"; -import * as db from "../database.ts"; - import { Avatar } from "./components/avatar.tsx"; -import { CenterClass, NoOutlineClass } from "./components/tw.ts"; -import { emitFunc, EventEmitter } from "../event-bus.ts"; import { PublicKey } from "../lib/nostr-ts/key.ts"; -import { ConnectionPool } from "../lib/nostr-ts/relay.ts"; import { PrimaryBackgroundColor, PrimaryTextColor, @@ -17,192 +11,135 @@ import { } from "./style/colors.ts"; import { ChatIcon } from "./icons2/chat-icon.tsx"; import { UserIcon } from "./icons2/user-icon.tsx"; -import { SocialIcon } from "./icons2/social-icon.tsx"; import { SettingIcon } from "./icons2/setting-icon.tsx"; - -export type Props = { - profilePicURL: string | undefined; - publicKey: PublicKey; - database: db.Database_Contextual_View; - pool: ConnectionPool; - emit: emitFunc; -} & NavigationModel; - -export type ActiveNav = ActiveTab | "Setting"; -export type ActiveTab = "DM" | /* "Group" | */ "Profile" | "About" | "AppList"; - -export type NavigationModel = { - activeNav: ActiveNav; -}; +import { Component } from "https://esm.sh/preact@10.17.1"; +import { ProfileGetter } from "./search.tsx"; +import { ProfileData } from "../features/profile.ts"; +import { AboutIcon } from "./icons2/about-icon.tsx"; +import { AppListIcon } from "./icons2/app-list-icon.tsx"; +import { CenterClass, NoOutlineClass } from "./components/tw.ts"; +import { emitFunc } from "../event-bus.ts"; export type NavigationUpdate = { type: "ChangeNavigation"; - index: ActiveNav; + id: NavTabID; }; -const navTabLayoutOrder: ActiveTab[] = ["DM", /*"Group",*/ "Profile", "About", "AppList"]; -const tabs = { - "DM": (active: boolean) => ( - - ), - "Profile": (active: boolean) => ( - - ), - "About": (active: boolean) => ( - - ), - "AppList": (active: boolean) => ( - - ), +export type NavigationModel = { + activeNav: NavTabID; }; -export function NavBar(props: Props) { - return ( -
-
- -
    - {navTabLayoutOrder.map((tab) => { - const tabComponent = tabs[tab]; - return ( -
  • { - props.emit({ - type: "ChangeNavigation", - index: tab, - }); - }} - > - {tabComponent(props.activeNav === tab)} -
  • - ); - })} -
-
- -
- ); -} +type Props = { + publicKey: PublicKey; + profileGetter: ProfileGetter; + emit: emitFunc; + isMobile?: boolean; +}; -export function MobileNavBar(props: Props) { - return ( -
-
-
    - {navTabLayoutOrder.map((tab) => { - const tabComponent = tabs[tab]; - return ( -
  • { - props.emit({ - type: "ChangeNavigation", - index: tab, - }); - }} +type State = { + activeIndex: number; +}; + +type NavTabID = "DM" | "Profile" | "About" | "AppList" | "Setting"; +type NavTab = { + icon: (active: boolean) => ComponentChild; + id: NavTabID; +}; + +export class NavBar extends Component { + styles = { + container: + tw`h-full w-16 flex flex-col gap-y-4 overflow-y-auto bg-[${PrimaryBackgroundColor}] py-8 items-center`, + icons: (active: boolean, fill?: boolean) => ( + tw`w-6 h-6 ${fill ? "fill-current" : "stroke-current"} text-[${ + active ? PrimaryTextColor : SecondaryTextColor + }]` + ), + avatar: tw`w-12 h-12`, + tabsContainer: tw`last:flex-1 last:flex last:items-end`, + tabs: (active: boolean) => + tw`rounded-lg w-10 h-10 ${ + active ? `bg-[${SecondaryBackgroundColor}]` : "" + } hover:bg-[${SecondaryBackgroundColor}] ${CenterClass} ${NoOutlineClass}`, + mobileContainer: tw`h-16 flex justify-evenly bg-[${PrimaryBackgroundColor}] items-center`, + }; + + myProfile: ProfileData | undefined; + tabs: NavTab[] = [ + { + icon: (active: boolean) => , + id: "DM", + }, + { + icon: (active: boolean) => , + id: "Profile", + }, + { + icon: (active: boolean) => , + id: "About", + }, + { + icon: (active: boolean) => , + id: "AppList", + }, + { + icon: (active: boolean) => , + id: "Setting", + }, + ]; + + componentWillMount() { + this.setState({ + activeIndex: 0, + }); + this.myProfile = this.props.profileGetter.getProfilesByPublicKey(this.props.publicKey)?.profile; + } + + changeTab = (activeIndex: number) => { + if (activeIndex == this.state.activeIndex) { + return; + } + + this.props.emit({ + type: "ChangeNavigation", + id: this.tabs[activeIndex].id, + }); + + this.setState({ + activeIndex: activeIndex, + }); + }; + + render() { + return ( + this.props.isMobile + ? ( +
    + {this.tabs.map((tab, index) => ( +
  • - ); - })} -
-
-
- -
-
- ); + {tab.icon(this.state.activeIndex == index)} + + ))} +
+ ) + : ( +
+ + {this.tabs.map((tab, index) => ( +
+ +
+ ))} +
+ ) + ); + } }