personal web client for Bluesky
typescript
solidjs
bluesky
atcute
1import { lazy } from 'solid-js';
2
3import type { RouteDefinition } from './lib/navigation/router';
4
5const DID_RE = /^did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]$/;
6const DID_OR_HANDLE_RE =
7 /^(?:did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]|[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))$/;
8
9const TID_RE = /^[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}$/;
10
11const isValidDid = (str: string | undefined): boolean => {
12 return str !== undefined && DID_RE.test(str);
13};
14const isValidDidOrHandle = (str: string | undefined): boolean => {
15 return str !== undefined && DID_OR_HANDLE_RE.test(str);
16};
17const isValidTid = (str: string | undefined): boolean => {
18 return str !== undefined && str.length === 13 && TID_RE.test(str);
19};
20const isValidBookmarkTagId = (str: string | undefined) => {
21 return str === 'all' || isValidTid(str);
22};
23
24const routes: RouteDefinition[] = [
25 {
26 path: '/oauth/callback',
27 component: lazy(() => import('./views/oauth-callback')),
28 meta: {
29 public: true,
30 },
31 },
32
33 {
34 path: '/',
35 component: lazy(() => import('./views/main/home')),
36 single: true,
37 meta: {
38 name: 'Home',
39 main: true,
40 // public: true,
41 },
42 },
43 {
44 path: '/explore',
45 component: lazy(() => import('./views/main/explore')),
46 single: true,
47 meta: {
48 name: 'Explore',
49 main: true,
50 // public: true,
51 },
52 },
53 {
54 path: '/notifications',
55 component: lazy(() => import('./views/main/notifications')),
56 single: true,
57 meta: {
58 name: 'Notifications',
59 main: true,
60 },
61 },
62 {
63 path: '/messages',
64 component: lazy(() => import('./views/main/messages')),
65 single: true,
66 meta: {
67 name: 'Messages',
68 main: true,
69 },
70 },
71
72 {
73 path: '/moderation',
74 component: lazy(() => import('./views/moderation')),
75 },
76 {
77 path: '/moderation/lists',
78 component: lazy(() => import('./views/moderation-lists')),
79 },
80
81 {
82 path: '/settings',
83 component: lazy(() => import('./views/settings')),
84 },
85 {
86 path: '/settings/about',
87 component: lazy(() => import('./views/settings-about')),
88 },
89 {
90 path: '/settings/account',
91 component: lazy(() => import('./views/settings-account')),
92 },
93 {
94 path: '/settings/app-passwords',
95 component: lazy(() => import('./views/settings-app-passwords')),
96 },
97 {
98 path: '/settings/appearance',
99 component: lazy(() => import('./views/settings-appearance')),
100 },
101 {
102 path: '/settings/content',
103 component: lazy(() => import('./views/settings-content')),
104 },
105 {
106 path: '/settings/content/translation',
107 component: lazy(() => import('./views/settings-content-translation')),
108 },
109 {
110 path: '/settings/content/translation/exclusion',
111 component: lazy(() => import('./views/settings-content-translation-exclusion')),
112 },
113 {
114 path: '/settings/explore/feeds',
115 component: lazy(() => import('./views/settings-explore-feeds')),
116 },
117
118 {
119 path: '/bookmarks',
120 component: lazy(() => import('./views/bookmarks')),
121 },
122 {
123 path: '/bookmarks/:tagId',
124 component: lazy(() => import('./views/bookmarks-listing')),
125 validate(params) {
126 return isValidBookmarkTagId(params.tagId);
127 },
128 },
129
130 {
131 path: '/search',
132 component: lazy(() => import('./views/search')),
133 },
134
135 {
136 path: '/likes',
137 component: lazy(() => import('./views/likes')),
138 },
139 {
140 path: '/lists',
141 component: lazy(() => import('./views/lists')),
142 },
143
144 {
145 path: '/bluemoji/emotes',
146 component: lazy(() => import('./views/bluemoji-emotes')),
147 },
148
149 {
150 path: '/:didOrHandle',
151 component: lazy(() => import('./views/profile')),
152 validate(params) {
153 return isValidDidOrHandle(params.didOrHandle);
154 },
155 },
156
157 {
158 path: '/:didOrHandle/search',
159 component: lazy(() => import('./views/profile-search')),
160 validate(params) {
161 return isValidDidOrHandle(params.didOrHandle);
162 },
163 },
164
165 {
166 path: '/:did/following',
167 component: lazy(() => import('./views/profile-following')),
168 validate(params) {
169 return isValidDid(params.did);
170 },
171 },
172 {
173 path: '/:did/followers',
174 component: lazy(() => import('./views/profile-followers')),
175 validate(params) {
176 return isValidDid(params.did);
177 },
178 },
179 {
180 path: '/:did/known-followers',
181 component: lazy(() => import('./views/profile-known-followers')),
182 validate(params) {
183 return isValidDid(params.did);
184 },
185 },
186
187 {
188 path: '/:did/labels',
189 component: lazy(() => import('./views/profile-labels')),
190 validate(params) {
191 return isValidDid(params.did);
192 },
193 },
194
195 {
196 path: '/:did/feeds',
197 component: lazy(() => import('./views/profile-feeds')),
198 validate(params) {
199 return isValidDid(params.did);
200 },
201 },
202 {
203 path: '/:didOrHandle/feeds/:rkey',
204 component: lazy(() => import('./views/profile-feed')),
205 validate(params) {
206 return isValidDidOrHandle(params.didOrHandle);
207 },
208 },
209
210 {
211 path: '/:did/lists',
212 component: lazy(() => import('./views/profile-lists')),
213 validate(params) {
214 return isValidDid(params.did);
215 },
216 },
217 {
218 path: '/:didOrHandle/lists/:rkey',
219 component: lazy(() => import('./views/profile-list')),
220 validate(params) {
221 return isValidDidOrHandle(params.didOrHandle);
222 },
223 },
224 {
225 path: '/:did/curation-lists/:rkey',
226 component: lazy(() => import('./views/profile-curation-list')),
227 validate(params) {
228 return isValidDid(params.did);
229 },
230 },
231 {
232 path: '/:did/moderation-lists/:rkey',
233 component: lazy(() => import('./views/profile-moderation-list')),
234 validate(params) {
235 return isValidDid(params.did);
236 },
237 },
238
239 {
240 path: '/:didOrHandle/:rkey',
241 component: lazy(() => import('./views/post-thread')),
242 validate(params) {
243 return isValidDidOrHandle(params.didOrHandle) && isValidTid(params.rkey);
244 },
245 },
246 {
247 path: '/:did/:rkey/likes',
248 component: lazy(() => import('./views/post-likes')),
249 validate(params) {
250 return isValidDid(params.did) && isValidTid(params.rkey);
251 },
252 },
253 {
254 path: '/:did/:rkey/reposts',
255 component: lazy(() => import('./views/post-reposts')),
256 validate(params) {
257 return isValidDid(params.did) && isValidTid(params.rkey);
258 },
259 },
260 {
261 path: '/:did/:rkey/quotes',
262 component: lazy(() => import('./views/post-quotes')),
263 validate(params) {
264 return isValidDid(params.did) && isValidTid(params.rkey);
265 },
266 },
267
268 {
269 path: '*',
270 component: lazy(() => import('./views/not-found')),
271 meta: {
272 public: true,
273 },
274 },
275];
276
277export default routes;