mirror of
https://github.com/BlowaterNostr/blowater.git
synced 2024-10-18 15:43:20 +00:00
209 lines
7.5 KiB
TypeScript
209 lines
7.5 KiB
TypeScript
/** @jsx h */
|
|
import { 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,
|
|
SecondaryBackgroundColor,
|
|
SecondaryTextColor,
|
|
} 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<NavigationUpdate>;
|
|
} & NavigationModel;
|
|
|
|
export type ActiveNav = ActiveTab | "Setting";
|
|
export type ActiveTab = "DM" | /* "Group" | */ "Profile" | "About" | "AppList";
|
|
|
|
export type NavigationModel = {
|
|
activeNav: ActiveNav;
|
|
};
|
|
|
|
export type NavigationUpdate = {
|
|
type: "ChangeNavigation";
|
|
index: ActiveNav;
|
|
};
|
|
|
|
const navTabLayoutOrder: ActiveTab[] = ["DM", /*"Group",*/ "Profile", "About", "AppList"];
|
|
const tabs = {
|
|
"DM": (active: boolean) => (
|
|
<ChatIcon
|
|
class={tw`w-[2rem] h-[2rem]`}
|
|
style={{
|
|
stroke: active ? PrimaryTextColor : SecondaryTextColor,
|
|
fill: "none",
|
|
}}
|
|
/>
|
|
),
|
|
"Profile": (active: boolean) => (
|
|
<UserIcon
|
|
class={tw`w-[2rem] h-[2rem]`}
|
|
style={{
|
|
stroke: active ? PrimaryTextColor : SecondaryTextColor,
|
|
fill: "none",
|
|
}}
|
|
/>
|
|
),
|
|
"About": (active: boolean) => (
|
|
<AboutIcon
|
|
class={tw`w-[2rem] h-[2rem]`}
|
|
style={{
|
|
fill: active ? PrimaryTextColor : SecondaryTextColor,
|
|
}}
|
|
/>
|
|
),
|
|
"AppList": (active: boolean) => (
|
|
<AppListIcon
|
|
class={tw`w-[2rem] h-[2rem]`}
|
|
style={{
|
|
stroke: active ? PrimaryTextColor : SecondaryTextColor,
|
|
fill: "none",
|
|
}}
|
|
/>
|
|
),
|
|
};
|
|
|
|
export function NavBar(props: Props) {
|
|
return (
|
|
<div
|
|
class={tw`bg-[${PrimaryBackgroundColor}] w-[5.75rem] h-full flex flex-col justify-between overflow-y-auto px-[1.12rem] py-[3rem]`}
|
|
>
|
|
<div>
|
|
<Avatar
|
|
picture={props.profilePicURL}
|
|
class={tw`w-[3.5rem] h-[3.5rem] m-auto mb-[2rem]`}
|
|
/>
|
|
<ul>
|
|
{navTabLayoutOrder.map((tab) => {
|
|
const tabComponent = tabs[tab];
|
|
return (
|
|
<li
|
|
class={tw`
|
|
w-[3.5rem] h-[3.5rem] cursor-pointer hover:bg-[${SecondaryBackgroundColor}] rounded-[1rem] mb-[0.5rem] ${CenterClass}
|
|
${
|
|
props.activeNav === tab
|
|
? `bg-[${SecondaryBackgroundColor}] hover:bg-[${SecondaryBackgroundColor}]`
|
|
: ""
|
|
}
|
|
`}
|
|
onClick={() => {
|
|
props.emit({
|
|
type: "ChangeNavigation",
|
|
index: tab,
|
|
});
|
|
}}
|
|
>
|
|
{tabComponent(props.activeNav === tab)}
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
<button
|
|
onClick={() => {
|
|
props.emit({
|
|
type: "ChangeNavigation",
|
|
index: "Setting",
|
|
});
|
|
}}
|
|
class={tw`
|
|
w-[3.5rem] h-[3.5rem] mx-auto hover:bg-[${SecondaryBackgroundColor}] rounded-[1rem] ${CenterClass} ${NoOutlineClass}
|
|
${props.activeNav === "Setting" ? `bg-[${SecondaryBackgroundColor}]` : ""}
|
|
`}
|
|
>
|
|
<SettingIcon
|
|
class={tw`w-[2rem] h-[2rem]`}
|
|
style={{
|
|
stroke: props.activeNav === "Setting" ? PrimaryTextColor : SecondaryTextColor,
|
|
fill: "none",
|
|
}}
|
|
/>
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function MobileNavBar(props: Props) {
|
|
return (
|
|
<div
|
|
class={tw`bg-[${PrimaryBackgroundColor}] h-[5.75rem] w-full flex justify-between overflow-x-auto py-[1.12rem] px-[3rem]`}
|
|
>
|
|
<div
|
|
class={tw`flex`}
|
|
style={{
|
|
minWidth: "fit-content",
|
|
}}
|
|
>
|
|
<ul class={tw`flex`}>
|
|
{navTabLayoutOrder.map((tab) => {
|
|
const tabComponent = tabs[tab];
|
|
return (
|
|
<li
|
|
class={tw`
|
|
w-[3.5rem] h-[3.5rem] cursor-pointer hover:bg-[${SecondaryBackgroundColor}] rounded-[1rem] mr-[0.5rem] ${CenterClass}
|
|
${
|
|
props.activeNav === tab
|
|
? `bg-[${SecondaryBackgroundColor}] hover:bg-[${SecondaryBackgroundColor}]`
|
|
: ""
|
|
}
|
|
`}
|
|
onClick={() => {
|
|
props.emit({
|
|
type: "ChangeNavigation",
|
|
index: tab,
|
|
});
|
|
}}
|
|
>
|
|
{tabComponent(props.activeNav === tab)}
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
<div
|
|
class={tw`w-20 h-full flex`}
|
|
style={{
|
|
minWidth: "5rem",
|
|
}}
|
|
>
|
|
<button
|
|
onClick={() => {
|
|
props.emit({
|
|
type: "ChangeNavigation",
|
|
index: "Setting",
|
|
});
|
|
}}
|
|
class={tw`
|
|
w-[3.5rem] h-[3.5rem] mx-auto hover:bg-[${SecondaryBackgroundColor}] rounded-[1rem] ${CenterClass} ${NoOutlineClass}
|
|
${props.activeNav === "Setting" ? `bg-[${SecondaryBackgroundColor}]` : ""}
|
|
`}
|
|
>
|
|
<SettingIcon
|
|
class={tw`w-[2rem] h-[2rem]`}
|
|
style={{
|
|
stroke: props.activeNav === "Setting" ? PrimaryTextColor : SecondaryTextColor,
|
|
fill: "none",
|
|
}}
|
|
/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|