snort/src/Pages/Layout.tsx

124 lines
4.6 KiB
TypeScript
Raw Normal View History

2022-12-29 15:36:40 +00:00
import "./Layout.css";
2022-12-30 23:35:02 +00:00
import { useEffect } from "react"
2022-12-27 23:46:13 +00:00
import { useDispatch, useSelector } from "react-redux";
2023-01-12 12:00:44 +00:00
import { Outlet, useNavigate } from "react-router-dom";
2023-01-12 09:48:39 +00:00
import { faBell, faMessage } from "@fortawesome/free-solid-svg-icons";
2023-01-03 10:54:18 +00:00
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2022-12-29 15:36:40 +00:00
2023-01-20 11:11:50 +00:00
import { RootState } from "State/Store";
2023-01-20 18:59:08 +00:00
import { init, setPreferences, UserPreferences } from "State/Login";
2023-01-20 11:11:50 +00:00
import { HexKey, RawEvent, TaggedRawEvent } from "Nostr";
import { RelaySettings } from "Nostr/Connection";
import { System } from "Nostr/System"
import ProfileImage from "Element/ProfileImage";
import useLoginFeed from "Feed/LoginFeed";
import { totalUnread } from "Pages/MessagesPage";
2022-12-18 14:51:47 +00:00
2023-01-16 18:14:08 +00:00
export default function Layout() {
2022-12-27 23:46:13 +00:00
const dispatch = useDispatch();
2022-12-18 14:51:47 +00:00
const navigate = useNavigate();
2023-01-16 18:14:08 +00:00
const isInit = useSelector<RootState, boolean | undefined>(s => s.login.loggedOut);
const key = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
const relays = useSelector<RootState, Record<string, RelaySettings>>(s => s.login.relays);
const notifications = useSelector<RootState, TaggedRawEvent[]>(s => s.login.notifications);
const readNotifications = useSelector<RootState, number>(s => s.login.readNotifications);
2023-01-17 10:47:00 +00:00
const dms = useSelector<RootState, RawEvent[]>(s => s.login.dms);
2023-01-20 17:07:14 +00:00
const prefs = useSelector<RootState, UserPreferences>(s => s.login.preferences);
2022-12-28 23:28:28 +00:00
useLoginFeed();
2022-12-18 14:51:47 +00:00
useEffect(() => {
2022-12-30 23:35:02 +00:00
if (relays) {
2022-12-28 23:28:28 +00:00
for (let [k, v] of Object.entries(relays)) {
2022-12-30 23:35:02 +00:00
System.ConnectToRelay(k, v);
2022-12-18 14:51:47 +00:00
}
2023-01-16 11:53:15 +00:00
for (let [k, v] of System.Sockets) {
2023-01-09 12:40:10 +00:00
if (!relays[k]) {
System.DisconnectRelay(k);
}
}
2022-12-18 14:51:47 +00:00
}
2022-12-30 23:35:02 +00:00
}, [relays]);
2022-12-18 14:51:47 +00:00
2023-01-20 18:59:08 +00:00
function setTheme(theme: "light" | "dark") {
2023-01-20 17:07:14 +00:00
const elm = document.documentElement;
2023-01-20 18:59:08 +00:00
if (theme === "light" && !elm.classList.contains("light")) {
2023-01-20 17:07:14 +00:00
elm.classList.add("light");
2023-01-20 18:59:08 +00:00
} else if (theme === "dark" && elm.classList.contains("light")) {
2023-01-20 17:07:14 +00:00
elm.classList.remove("light");
}
2023-01-20 18:59:08 +00:00
}
useEffect(() => {
let osTheme = window.matchMedia("(prefers-color-scheme: light)");
setTheme(prefs.theme === "system" && osTheme.matches ? "light" : prefs.theme === "light" ? "light" : "dark");
osTheme.onchange = (e) => {
if (prefs.theme === "system") {
setTheme(e.matches ? "light" : "dark");
}
}
return () => { osTheme.onchange = null; }
}, [prefs.theme]);
2023-01-20 17:07:14 +00:00
2022-12-27 23:46:13 +00:00
useEffect(() => {
dispatch(init());
}, []);
2023-01-16 18:14:08 +00:00
async function goToNotifications(e: any) {
2023-01-03 13:17:09 +00:00
e.stopPropagation();
// request permissions to send notifications
2023-01-19 11:03:51 +00:00
if ("Notification" in window) {
2023-01-03 13:17:09 +00:00
try {
2023-01-19 11:03:51 +00:00
if (Notification.permission !== "granted") {
let res = await Notification.requestPermission();
console.debug(res);
}
2023-01-03 13:17:09 +00:00
} catch (e) {
console.error(e);
}
}
navigate("/notifications");
}
2022-12-29 15:36:40 +00:00
function accountHeader() {
2023-01-10 07:09:09 +00:00
const unreadNotifications = notifications?.filter(a => (a.created_at * 1000) > readNotifications).length;
2023-01-17 10:47:00 +00:00
const unreadDms = key ? totalUnread(dms, key) : 0;
2022-12-29 15:36:40 +00:00
return (
<>
2023-01-17 10:47:00 +00:00
<div className={`btn btn-rnd${unreadDms === 0 ? " mr10" : ""}`} onClick={(e) => navigate("/messages")}>
2023-01-12 09:48:39 +00:00
<FontAwesomeIcon icon={faMessage} size="xl" />
</div>
2023-01-17 10:47:00 +00:00
{unreadDms > 0 && (<span className="unread-count">
{unreadDms > 100 ? ">99" : unreadDms}
</span>)}
2023-01-12 09:48:39 +00:00
<div className={`btn btn-rnd${unreadNotifications === 0 ? " mr10" : ""}`} onClick={(e) => goToNotifications(e)}>
2022-12-29 15:36:40 +00:00
<FontAwesomeIcon icon={faBell} size="xl" />
</div>
2023-01-12 09:48:39 +00:00
{unreadNotifications > 0 && (<span className="unread-count">
{unreadNotifications > 100 ? ">99" : unreadNotifications}
</span>)}
2023-01-16 18:14:08 +00:00
<ProfileImage pubkey={key || ""} showUsername={false} />
2022-12-29 15:36:40 +00:00
</>
)
}
2023-01-02 11:59:03 +00:00
if (typeof isInit !== "boolean") {
return null;
}
2022-12-18 14:51:47 +00:00
return (
<div className="page">
<div className="header">
2023-01-19 23:19:09 +00:00
<div className="logo" onClick={() => navigate("/")}>snort</div>
2022-12-18 14:51:47 +00:00
<div>
2022-12-29 15:36:40 +00:00
{key ? accountHeader() :
2022-12-27 23:46:13 +00:00
<div className="btn" onClick={() => navigate("/login")}>Login</div>
}
2022-12-18 14:51:47 +00:00
</div>
</div>
2023-01-16 18:14:08 +00:00
<Outlet />
2022-12-18 14:51:47 +00:00
</div>
)
2023-01-19 23:19:09 +00:00
}