bring back browser notifications

This commit is contained in:
Patrick O'Sullivan 2023-03-03 09:48:54 -06:00
parent a3819c2416
commit 0030cfeec6
3 changed files with 48 additions and 10 deletions

View File

@ -16,11 +16,18 @@ import useKilnState from './state/kiln';
import useContactState from './state/contact';
import api from './state/api';
import { useMedia } from './logic/useMedia';
import { useSettingsState, useTheme } from './state/settings';
import {
useBrowserNotifications,
useSettingsState,
useTheme,
} from './state/settings';
import { useBrowserId, useLocalState } from './state/local';
import { ErrorAlert } from './components/ErrorAlert';
import { useErrorHandler } from './logic/useErrorHandler';
import useHarkState from './state/hark';
import { useNotifications } from './nav/notifications/useNotifications';
import { getNotificationType } from './nav/notifications/Notification';
import { isYarnShip } from './state/hark-types';
const getNoteRedirect = (path: string) => {
if (path.startsWith('/desk/')) {
@ -51,6 +58,23 @@ const AppRoutes = () => {
const { search } = useLocation();
const handleError = useErrorHandler();
const browserId = useBrowserId();
const { count, unreadNotifications } = useNotifications();
const browserNotifications = useBrowserNotifications(browserId);
useEffect(() => {
if (count > 0 && browserNotifications && 'Notification' in window) {
unreadNotifications.forEach((bin) => {
const rope = bin.topYarn?.rope;
// need to capitalize desk name
const app = rope?.desk.slice(0, 1).toUpperCase() + rope?.desk.slice(1);
const type = getNotificationType(rope);
const ship = bin.topYarn?.con.find(isYarnShip)?.ship;
new Notification(`Landscape: ${app}`, {
body: `${ship}${bin.topYarn.con[1]}${bin.topYarn.con[2]}`,
});
});
}
}, [count, browserNotifications, unreadNotifications]);
useEffect(() => {
getId().then((value) => {

View File

@ -47,7 +47,7 @@ function makePrettyTime(date: Date) {
return format(date, 'HH:mm');
}
function getNotificationType(rope: Rope): NotificationType {
export function getNotificationType(rope: Rope): NotificationType {
if (
['/channel/edit', '/channel/add', '/channel/del', '/joins', '/leaves'].some(
(thread) => rope.thread.endsWith(thread)

View File

@ -18,20 +18,25 @@ export interface DayGrouping {
}
function getYarns(thread: Thread, yarns: Yarns) {
return _.values(_.pickBy(yarns, (v, k) => thread.includes(k))).sort((a, b) => b.time - a.time);
return _.values(_.pickBy(yarns, (v, k) => thread.includes(k))).sort(
(a, b) => b.time - a.time
);
}
function getBin(thread: Thread, yarns: Yarns, unread: boolean): Bin {
const ys = getYarns(thread, yarns);
const topYarn = _.head(ys) as Yarn;
const shipCount = _.uniqBy<Yarn>(ys, (y) => y.con.find(isYarnShip)?.ship).length;
const shipCount = _.uniqBy<Yarn>(
ys,
(y) => y.con.find(isYarnShip)?.ship
).length;
return {
time: topYarn?.time || 0,
count: thread.length,
shipCount,
unread,
topYarn
topYarn,
};
}
@ -54,20 +59,29 @@ function groupBinsByDate(bins: Bin[]): DayGrouping[] {
.map(([k, v]) => ({
date: k,
latest: _.head(v)?.time || 0,
bins: v.sort((a, b) => b.time - a.time)
bins: v.sort((a, b) => b.time - a.time),
}))
.sort((a, b) => b.latest - a.latest);
}
const selNotifications = (state: HarkState) => ({ carpet: state.carpet, blanket: state.blanket });
const selNotifications = (state: HarkState) => ({
carpet: state.carpet,
blanket: state.blanket,
});
export const useNotifications = () => {
const { carpet, blanket } = useHarkState(selNotifications);
const bins: Bin[] = carpet.cable.map((c) => getBin(c.thread, carpet.yarns, true));
const oldBins: Bin[] = Object.values(blanket.quilt).map((t) => getBin(t, blanket.yarns, false));
const bins: Bin[] = carpet.cable.map((c) =>
getBin(c.thread, carpet.yarns, true)
);
const oldBins: Bin[] = Object.values(blanket.quilt).map((t) =>
getBin(t, blanket.yarns, false)
);
const notifications: DayGrouping[] = groupBinsByDate(bins.concat(oldBins));
const unreadNotifications = bins.filter((b) => b.unread);
return {
count: carpet.cable.length,
notifications
notifications,
unreadNotifications,
};
};