tangled
alpha
login
or
join now
bad-example.com
/
spacedust-utils
6
fork
atom
demos for spacedust
6
fork
atom
overview
issues
pulls
pipelines
admin page
bad-example.com
8 months ago
93ce77d2
29260c32
+51
-21
9 changed files
expand all
collapse all
unified
split
atproto-notifications
src
App.tsx
components
setup
Chrome.tsx
WithServerHello.tsx
context.ts
index.css
main.tsx
pages
Admin.tsx
Feed.css
Feed.tsx
+2
-3
atproto-notifications/src/App.tsx
···
1
1
import { useCallback, useState, useEffect } from 'react';
2
2
+
import { Outlet } from 'react-router';
2
3
import { useLocalStorage } from "@uidotdev/usehooks";
3
4
import { GetJson } from './components/fetch';
4
5
import { WhoAmI } from './components/WhoAmI';
5
5
-
import { Feed } from './components/Feed';
6
6
import { WithFeatureChecks } from './components/setup/WithFeatureChecks';
7
7
import { WithServiceWorker } from './components/setup/WithServiceWorker';
8
8
import { WithServerHello } from './components/setup/WithServerHello';
9
9
-
import { UserContext } from './context';
10
9
import { WithNotificationPermission } from './components/setup/WithNotificationPermission';
11
10
import { WithPushSubscription } from './components/setup/WithPushSubscription';
12
11
import { urlBase64ToUint8Array } from './utils';
···
22
21
<WithServiceWorker>
23
22
<WithNotificationPermission>
24
23
<WithPushSubscription>
25
25
-
<Feed />
24
24
+
{children}
26
25
</WithPushSubscription>
27
26
</WithNotificationPermission>
28
27
</WithServiceWorker>
atproto-notifications/src/components/Feed.css
atproto-notifications/src/pages/Feed.css
+2
-2
atproto-notifications/src/components/Feed.tsx
atproto-notifications/src/pages/Feed.tsx
···
1
1
import { useEffect, useState } from 'react';
2
2
import { getNotifications, getSecondary } from '../db';
3
3
-
import { ButtonGroup } from './Buttons';
4
4
-
import { Notification } from './Notification';
3
3
+
import { ButtonGroup } from '../components/Buttons';
4
4
+
import { Notification } from '../components/Notification';
5
5
import psl from 'psl';
6
6
import lexicons from 'lexicons';
7
7
+11
-2
atproto-notifications/src/components/setup/Chrome.tsx
···
1
1
+
import { Link } from 'react-router';
1
2
import { Handle } from '../User';
2
3
import './Chrome.css';
3
4
···
7
8
return (
8
9
<>
9
10
<header id="app-header">
10
10
-
<h1>spacedust notifications <span className="demo">demo!</span></h1>
11
11
+
<h1>
12
12
+
<Link to="/" className="inherit-font">
13
13
+
spacedust notifications <span className="demo">demo!</span>
14
14
+
</Link>
15
15
+
</h1>
11
16
{user && (
12
17
<div className="current-user">
13
18
<p>
···
15
20
<Handle did={user.did} />
16
21
{user.role !== 'public' && (
17
22
<span className="chrome-role-tag">
18
18
-
{user.role}
23
23
+
{user.role === 'admin' ? (
24
24
+
<Link to="/admin" className="inherit-font">{user.role}</Link>
25
25
+
) : (
26
26
+
<>{user.role}</>
27
27
+
)}
19
28
</span>
20
29
)}
21
30
</span>
+7
-3
atproto-notifications/src/components/setup/WithServerHello.tsx
···
1
1
import { useCallback, useEffect, useState } from 'react';
2
2
-
import { UserContext, PushServerContext } from '../../context';
2
2
+
import { RoleContext, PushServerContext } from '../../context';
3
3
import { WhoAmI } from '../WhoAmI';
4
4
import { SecretPassword } from '../SecretPassword';
5
5
import { GetJson, PostJson } from '../Fetch';
···
71
71
ok={({ did, role, webPushPublicKey }) => (
72
72
<Chrome user={{ did, role }} onLogout={handleLogout}>
73
73
<PushServerContext.Provider value={webPushPublicKey}>
74
74
-
{childrenFor(did, role, children)}
74
74
+
<RoleContext.Provider value={role}>
75
75
+
{childrenFor(did, role, children)}
76
76
+
</RoleContext.Provider>
75
77
</PushServerContext.Provider>
76
78
</Chrome>
77
79
)}
···
81
83
return (
82
84
<Chrome user={{ did, role }} onLogout={handleLogout}>
83
85
<PushServerContext.Provider value={webPushPublicKey}>
84
84
-
{childrenFor(did, role, children)}
86
86
+
<RoleContext.Provider value={role}>
87
87
+
{childrenFor(did, role, children)}
88
88
+
</RoleContext.Provider>
85
89
</PushServerContext.Provider>
86
90
</Chrome>
87
91
);
+1
-1
atproto-notifications/src/context.ts
···
1
1
import { createContext } from 'react';
2
2
3
3
-
export const UserContext = createContext('light');
3
3
+
export const RoleContext = createContext('public');
4
4
export const PushServerContext = createContext(null);
+5
atproto-notifications/src/index.css
···
22
22
color: #535bf2;
23
23
}
24
24
25
25
+
a.inherit-font {
26
26
+
font: inherit;
27
27
+
color: inherit;
28
28
+
}
29
29
+
25
30
body {
26
31
margin: 0;
27
32
min-width: 320px;
+12
-10
atproto-notifications/src/main.tsx
···
1
1
-
import { StrictMode } from 'react'
2
2
-
import { createRoot } from 'react-dom/client'
1
1
+
import { StrictMode } from 'react';
2
2
+
import { createRoot } from 'react-dom/client';
3
3
import { BrowserRouter, Routes, Route } from "react-router";
4
4
-
import './index.css'
5
5
-
import { App } from './App.tsx'
4
4
+
import './index.css';
5
5
+
import { App } from './App';
6
6
+
import { Feed } from './pages/Feed';
7
7
+
import { Admin } from './pages/Admin';
6
8
7
9
createRoot(document.getElementById('root')!).render(
8
10
<StrictMode>
9
9
-
<App>
10
10
-
<BrowserRouter>
11
11
+
<BrowserRouter>
12
12
+
<App>
11
13
<Routes>
12
12
-
{/*<Route index element={<Home />} />*/}
13
13
-
{/*<Route path="/status" element={<Status />} />*/}
14
14
+
<Route index element={<Feed />} />
15
15
+
<Route path="/admin" element={<Admin />} />
14
16
</Routes>
15
15
-
</BrowserRouter>
16
16
-
</App>
17
17
+
</App>
18
18
+
</BrowserRouter>
17
19
</StrictMode>,
18
20
);
19
21
+11
atproto-notifications/src/pages/Admin.tsx
···
1
1
+
import { useContext } from 'react';
2
2
+
import { RoleContext } from '../context';
3
3
+
4
4
+
export function Admin({}) {
5
5
+
const role = useContext(RoleContext);
6
6
+
if (role !== 'admin') {
7
7
+
return <p>sorry, this page is admin-only</p>
8
8
+
}
9
9
+
10
10
+
return 'sup';
11
11
+
}