constants.ts raw
1 import { kinds } from 'nostr-tools'
2
3 export const DEPLOYMENT = {
4 loginMethods: (import.meta.env.VITE_LOGIN_METHODS || 'nsec,nip07,bunker')
5 .split(',')
6 .map((s: string) => s.trim()),
7 defaultRelay: import.meta.env.VITE_DEFAULT_RELAY || ''
8 } as const
9
10 export const SMESH_API_BASE_URL = 'https://api.smesh.social'
11
12 export const RECOMMENDED_BLOSSOM_SERVERS = [
13 'https://blossom.band/',
14 'https://blossom.primal.net/',
15 'https://nostr.media/'
16 ]
17
18 export const StorageKey = {
19 VERSION: 'version',
20 THEME_SETTING: 'themeSetting',
21 RELAY_SETS: 'relaySets',
22 ACCOUNTS: 'accounts',
23 CURRENT_ACCOUNT: 'currentAccount',
24 ADD_CLIENT_TAG: 'addClientTag',
25 NOTE_LIST_MODE: 'noteListMode',
26 NOTIFICATION_TYPE: 'notificationType',
27 DEFAULT_ZAP_SATS: 'defaultZapSats',
28 DEFAULT_ZAP_COMMENT: 'defaultZapComment',
29 QUICK_ZAP: 'quickZap',
30 LAST_READ_NOTIFICATION_TIME_MAP: 'lastReadNotificationTimeMap',
31 ACCOUNT_FEED_INFO_MAP: 'accountFeedInfoMap',
32 AUTOPLAY: 'autoplay',
33 HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions',
34 HIDE_UNTRUSTED_NOTIFICATIONS: 'hideUntrustedNotifications',
35 TRANSLATION_SERVICE_CONFIG_MAP: 'translationServiceConfigMap',
36 MEDIA_UPLOAD_SERVICE_CONFIG_MAP: 'mediaUploadServiceConfigMap',
37 HIDE_UNTRUSTED_NOTES: 'hideUntrustedNotes',
38 DISMISSED_TOO_MANY_RELAYS_ALERT: 'dismissedTooManyRelaysAlert',
39 SHOW_KINDS: 'showKinds',
40 SHOW_KINDS_VERSION: 'showKindsVersion',
41 HIDE_CONTENT_MENTIONING_MUTED_USERS: 'hideContentMentioningMutedUsers',
42 NOTIFICATION_LIST_STYLE: 'notificationListStyle',
43 MEDIA_AUTO_LOAD_POLICY: 'mediaAutoLoadPolicy',
44 SHOWN_CREATE_WALLET_GUIDE_TOAST_PUBKEYS: 'shownCreateWalletGuideToastPubkeys',
45 SIDEBAR_COLLAPSE: 'sidebarCollapse',
46 PRIMARY_COLOR: 'primaryColor',
47 ENABLE_SINGLE_COLUMN_LAYOUT: 'enableSingleColumnLayout',
48 FALLBACK_RELAY_COUNT: 'fallbackRelayCount',
49 FAVICON_URL_TEMPLATE: 'faviconUrlTemplate',
50 FILTER_OUT_ONION_RELAYS: 'filterOutOnionRelays',
51 QUICK_REACTION: 'quickReaction',
52 QUICK_REACTION_EMOJI: 'quickReactionEmoji',
53 NSFW_DISPLAY_POLICY: 'nsfwDisplayPolicy',
54 PREFER_NIP44: 'preferNip44',
55 DM_CONVERSATION_FILTER: 'dmConversationFilter',
56 DM_ENCRYPTION_PREFERENCES: 'dmEncryptionPreferences',
57 DM_LAST_SEEN_TIMESTAMP: 'dmLastSeenTimestamp',
58 GRAPH_QUERIES_ENABLED: 'graphQueriesEnabled',
59 SOCIAL_GRAPH_PROXIMITY: 'socialGraphProximity',
60 SOCIAL_GRAPH_INCLUDE_MODE: 'socialGraphIncludeMode',
61 NRC_ONLY_CONFIG_SYNC: 'nrcOnlyConfigSync',
62 AUTO_INSERT_NEW_NOTES: 'autoInsertNewNotes',
63 VERBOSE_LOGGING: 'verboseLogging',
64 ENABLE_MARKDOWN: 'enableMarkdown',
65 SEARCH_RELAYS: 'searchRelays',
66 LLM_CONFIG_MAP: 'llmConfigMap',
67 OUTBOX_MODE: 'outboxMode',
68 DEFAULT_SHOW_NSFW: 'defaultShowNsfw', // deprecated
69 PINNED_PUBKEYS: 'pinnedPubkeys', // deprecated
70 MEDIA_UPLOAD_SERVICE: 'mediaUploadService', // deprecated
71 HIDE_UNTRUSTED_EVENTS: 'hideUntrustedEvents', // deprecated
72 ACCOUNT_RELAY_LIST_EVENT_MAP: 'accountRelayListEventMap', // deprecated
73 ACCOUNT_FOLLOW_LIST_EVENT_MAP: 'accountFollowListEventMap', // deprecated
74 ACCOUNT_MUTE_LIST_EVENT_MAP: 'accountMuteListEventMap', // deprecated
75 ACCOUNT_MUTE_DECRYPTED_TAGS_MAP: 'accountMuteDecryptedTagsMap', // deprecated
76 ACCOUNT_PROFILE_EVENT_MAP: 'accountProfileEventMap', // deprecated
77 ACTIVE_RELAY_SET_ID: 'activeRelaySetId', // deprecated
78 FEED_TYPE: 'feedType' // deprecated
79 }
80
81 export const ApplicationDataKey = {
82 NOTIFICATIONS_SEEN_AT: 'seen_notifications_at',
83 SETTINGS: 'smesh_settings',
84 DM_DELETED_MESSAGES: 'dm_deleted_messages',
85 // Relay hint for DMs - contains bech32-encoded relays (nrelay1...) that smesh clients should check first
86 DM_RELAY_HINT: 'smesh_dm_relays'
87 }
88
89 /**
90 * Recommended search relays that users can opt into.
91 * These are NOT used by default - search is opt-in to protect privacy.
92 * Users must explicitly configure search relays or accept these recommendations.
93 */
94 export const RECOMMENDED_SEARCH_RELAYS = [
95 'wss://search.nos.today/',
96 'wss://relay.ditto.pub/',
97 'wss://relay.nostrcheck.me/',
98 'wss://relay.nostr.band/'
99 ]
100
101 export const GROUP_METADATA_EVENT_KIND = 39000
102
103 export const ExtendedKind = {
104 SEAL: 13,
105 PRIVATE_DM: 14,
106 EXTERNAL_CONTENT_REACTION: 17,
107 PICTURE: 20,
108 VIDEO: 21,
109 SHORT_VIDEO: 22,
110 POLL: 1068,
111 POLL_RESPONSE: 1018,
112 COMMENT: 1111,
113 VOICE: 1222,
114 GIFT_WRAP: 1059,
115 VOICE_COMMENT: 1244,
116 PINNED_USERS: 10010,
117 FAVORITE_RELAYS: 10012,
118 BLOSSOM_SERVER_LIST: 10063,
119 FOLLOW_PACK: 39089,
120 RELAY_REVIEW: 31987,
121 GROUP_METADATA: 39000,
122 ADDRESSABLE_NORMAL_VIDEO: 34235,
123 ADDRESSABLE_SHORT_VIDEO: 34236
124 }
125
126 export const ALLOWED_FILTER_KINDS = [
127 kinds.ShortTextNote,
128 kinds.Repost,
129 kinds.GenericRepost,
130 ExtendedKind.PICTURE,
131 ExtendedKind.VIDEO,
132 ExtendedKind.SHORT_VIDEO,
133 ExtendedKind.POLL,
134 ExtendedKind.COMMENT,
135 ExtendedKind.VOICE,
136 ExtendedKind.VOICE_COMMENT,
137 kinds.Highlights,
138 kinds.LongFormArticle,
139 ExtendedKind.ADDRESSABLE_NORMAL_VIDEO,
140 ExtendedKind.ADDRESSABLE_SHORT_VIDEO
141 ]
142
143 export const SUPPORTED_KINDS = [
144 ...ALLOWED_FILTER_KINDS,
145 ExtendedKind.RELAY_REVIEW,
146 kinds.Emojisets,
147 ExtendedKind.FOLLOW_PACK
148 ]
149
150 export const URL_REGEX =
151 /https?:\/\/[\w\p{L}\p{N}\p{M}&.\-/?=#@%+_:!~*]+[^\s.,;:'")\]}!?,。;:"'!?】)]/giu
152 export const WS_URL_REGEX =
153 /wss?:\/\/[\w\p{L}\p{N}\p{M}&.\-/?=#@%+_:!~*]+[^\s.,;:'")\]}!?,。;:"'!?】)]/giu
154 export const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
155 export const EMOJI_SHORT_CODE_REGEX = /:[a-zA-Z0-9_-]+:/g
156 export const EMBEDDED_EVENT_REGEX = /nostr:(note1[a-z0-9]{58}|nevent1[a-z0-9]+|naddr1[a-z0-9]+)/g
157 export const EMBEDDED_MENTION_REGEX = /nostr:(npub1[a-z0-9]{58}|nprofile1[a-z0-9]+)/g
158 export const HASHTAG_REGEX = /#[\p{L}\p{N}\p{M}_]+/gu
159 export const LN_INVOICE_REGEX = /(ln(?:bc|tb|bcrt))([0-9]+[munp]?)?1([02-9ac-hj-np-z]+)/g
160 export const EMOJI_REGEX =
161 /[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F900}-\u{1F9FF}]|[\u{1FA70}-\u{1FAFF}]|[\u{1F004}]|[\u{1F0CF}]|[\u{1F18E}]|[\u{3030}]|[\u{2B50}]|[\u{2B55}]|[\u{2934}-\u{2935}]|[\u{2B05}-\u{2B07}]|[\u{2B1B}-\u{2B1C}]|[\u{3297}]|[\u{3299}]|[\u{303D}]|[\u{00A9}]|[\u{00AE}]|[\u{2122}]|[\u{23E9}-\u{23EF}]|[\u{23F0}]|[\u{23F3}]|[\u{FE00}-\u{FE0F}]|[\u{200D}]/gu
162 export const YOUTUBE_URL_REGEX =
163 /https?:\/\/(?:(?:www|m)\.)?(?:youtube\.com\/(?:watch\?[^#\s]*|embed\/[\w-]+|shorts\/[\w-]+|live\/[\w-]+)|youtu\.be\/[\w-]+)(?:\?[^#\s]*)?(?:#[^\s]*)?/gi
164 export const X_URL_REGEX =
165 /https?:\/\/(?:www\.)?(twitter\.com|x\.com)\/(?:#!\/)?(\w+)\/status(?:es)?\/(\d+)(?:[?#].*)?/gi
166
167 export const SMESH_PUBKEY = '4c800257a588a82849d049817c2bdaad984b25a45ad9f6dad66e47d3b47e3b2f'
168
169 export const NIP_96_SERVICE = [
170 'https://mockingyou.com',
171 'https://nostpic.com',
172 'https://nostr.build', // default
173 'https://nostrcheck.me',
174 'https://nostrmedia.com',
175 'https://files.sovbit.host'
176 ]
177 export const DEFAULT_NIP_96_SERVICE = 'https://nostr.build'
178
179 export const DEFAULT_FAVICON_URL_TEMPLATE = 'https://{hostname}/favicon.ico'
180
181 export const POLL_TYPE = {
182 MULTIPLE_CHOICE: 'multiplechoice',
183 SINGLE_CHOICE: 'singlechoice'
184 } as const
185
186 export const NOTIFICATION_LIST_STYLE = {
187 COMPACT: 'compact',
188 DETAILED: 'detailed'
189 } as const
190
191 export const MEDIA_AUTO_LOAD_POLICY = {
192 ALWAYS: 'always',
193 WIFI_ONLY: 'wifi-only',
194 NEVER: 'never'
195 } as const
196
197 export const NSFW_DISPLAY_POLICY = {
198 HIDE: 'hide',
199 HIDE_CONTENT: 'hide_content',
200 SHOW: 'show'
201 } as const
202
203 export const MAX_PINNED_NOTES = 10
204
205 export const PRIMARY_COLORS = {
206 DEFAULT: {
207 name: 'Default',
208 light: {
209 primary: '38 92% 50%',
210 'primary-hover': '38 92% 60%',
211 'primary-foreground': '0 0% 10%',
212 ring: '38 92% 50%'
213 },
214 dark: {
215 primary: '38 92% 50%',
216 'primary-hover': '38 92% 60%',
217 'primary-foreground': '240 5.9% 10%',
218 ring: '38 92% 50%'
219 }
220 },
221 RED: {
222 name: 'Red',
223 light: {
224 primary: '0 65% 55%',
225 'primary-hover': '0 65% 65%',
226 'primary-foreground': '0 0% 98%',
227 ring: '0 65% 55%'
228 },
229 dark: {
230 primary: '0 65% 55%',
231 'primary-hover': '0 65% 65%',
232 'primary-foreground': '240 5.9% 10%',
233 ring: '0 65% 55%'
234 }
235 },
236 ORANGE: {
237 name: 'Orange',
238 light: {
239 primary: '30 100% 50%',
240 'primary-hover': '30 100% 60%',
241 'primary-foreground': '0 0% 98%',
242 ring: '30 100% 50%'
243 },
244 dark: {
245 primary: '30 100% 50%',
246 'primary-hover': '30 100% 60%',
247 'primary-foreground': '240 5.9% 10%',
248 ring: '30 100% 50%'
249 }
250 },
251 AMBER: {
252 name: 'Amber',
253 light: {
254 primary: '42 100% 50%',
255 'primary-hover': '42 100% 60%',
256 'primary-foreground': '0 0% 98%',
257 ring: '42 100% 50%'
258 },
259 dark: {
260 primary: '42 100% 50%',
261 'primary-hover': '42 100% 60%',
262 'primary-foreground': '240 5.9% 10%',
263 ring: '42 100% 50%'
264 }
265 },
266 YELLOW: {
267 name: 'Yellow',
268 light: {
269 primary: '54 100% 50%',
270 'primary-hover': '54 100% 60%',
271 'primary-foreground': '0 0% 10%',
272 ring: '54 100% 50%'
273 },
274 dark: {
275 primary: '54 100% 50%',
276 'primary-hover': '54 100% 60%',
277 'primary-foreground': '240 5.9% 10%',
278 ring: '54 100% 50%'
279 }
280 },
281 LIME: {
282 name: 'Lime',
283 light: {
284 primary: '90 60% 50%',
285 'primary-hover': '90 60% 60%',
286 'primary-foreground': '0 0% 98%',
287 ring: '90 60% 50%'
288 },
289 dark: {
290 primary: '90 60% 50%',
291 'primary-hover': '90 60% 60%',
292 'primary-foreground': '240 5.9% 10%',
293 ring: '90 60% 50%'
294 }
295 },
296 GREEN: {
297 name: 'Green',
298 light: {
299 primary: '140 60% 40%',
300 'primary-hover': '140 60% 50%',
301 'primary-foreground': '0 0% 98%',
302 ring: '140 60% 40%'
303 },
304 dark: {
305 primary: '140 60% 40%',
306 'primary-hover': '140 60% 50%',
307 'primary-foreground': '240 5.9% 10%',
308 ring: '140 60% 40%'
309 }
310 },
311 EMERALD: {
312 name: 'Emerald',
313 light: {
314 primary: '160 70% 40%',
315 'primary-hover': '160 70% 50%',
316 'primary-foreground': '0 0% 98%',
317 ring: '160 70% 40%'
318 },
319 dark: {
320 primary: '160 70% 40%',
321 'primary-hover': '160 70% 50%',
322 'primary-foreground': '240 5.9% 10%',
323 ring: '160 70% 40%'
324 }
325 },
326 TEAL: {
327 name: 'Teal',
328 light: {
329 primary: '180 70% 40%',
330 'primary-hover': '180 70% 50%',
331 'primary-foreground': '0 0% 98%',
332 ring: '180 70% 40%'
333 },
334 dark: {
335 primary: '180 70% 40%',
336 'primary-hover': '180 70% 50%',
337 'primary-foreground': '240 5.9% 10%',
338 ring: '180 70% 40%'
339 }
340 },
341 CYAN: {
342 name: 'Cyan',
343 light: {
344 primary: '200 70% 40%',
345 'primary-hover': '200 70% 50%',
346 'primary-foreground': '0 0% 98%',
347 ring: '200 70% 40%'
348 },
349 dark: {
350 primary: '200 70% 40%',
351 'primary-hover': '200 70% 50%',
352 'primary-foreground': '240 5.9% 10%',
353 ring: '200 70% 40%'
354 }
355 },
356 SKY: {
357 name: 'Sky',
358 light: {
359 primary: '210 70% 50%',
360 'primary-hover': '210 70% 60%',
361 'primary-foreground': '0 0% 98%',
362 ring: '210 70% 50%'
363 },
364 dark: {
365 primary: '210 70% 50%',
366 'primary-hover': '210 70% 60%',
367 'primary-foreground': '240 5.9% 10%',
368 ring: '210 70% 50%'
369 }
370 },
371 BLUE: {
372 name: 'Blue',
373 light: {
374 primary: '220 80% 50%',
375 'primary-hover': '220 80% 60%',
376 'primary-foreground': '0 0% 98%',
377 ring: '220 80% 50%'
378 },
379 dark: {
380 primary: '220 80% 50%',
381 'primary-hover': '220 80% 60%',
382 'primary-foreground': '240 5.9% 10%',
383 ring: '220 80% 50%'
384 }
385 },
386 INDIGO: {
387 name: 'Indigo',
388 light: {
389 primary: '230 80% 50%',
390 'primary-hover': '230 80% 60%',
391 'primary-foreground': '0 0% 98%',
392 ring: '230 80% 50%'
393 },
394 dark: {
395 primary: '230 80% 50%',
396 'primary-hover': '230 80% 60%',
397 'primary-foreground': '240 5.9% 10%',
398 ring: '230 80% 50%'
399 }
400 },
401 VIOLET: {
402 name: 'Violet',
403 light: {
404 primary: '250 80% 50%',
405 'primary-hover': '250 80% 60%',
406 'primary-foreground': '0 0% 98%',
407 ring: '250 80% 50%'
408 },
409 dark: {
410 primary: '250 80% 50%',
411 'primary-hover': '250 80% 60%',
412 'primary-foreground': '240 5.9% 10%',
413 ring: '250 80% 50%'
414 }
415 },
416 PURPLE: {
417 name: 'Purple',
418 light: {
419 primary: '280 80% 50%',
420 'primary-hover': '280 80% 60%',
421 'primary-foreground': '0 0% 98%',
422 ring: '280 80% 50%'
423 },
424 dark: {
425 primary: '280 80% 50%',
426 'primary-hover': '280 80% 60%',
427 'primary-foreground': '240 5.9% 10%',
428 ring: '280 80% 50%'
429 }
430 },
431 FUCHSIA: {
432 name: 'Fuchsia',
433 light: {
434 primary: '310 80% 50%',
435 'primary-hover': '310 80% 60%',
436 'primary-foreground': '0 0% 98%',
437 ring: '310 80% 50%'
438 },
439 dark: {
440 primary: '310 80% 50%',
441 'primary-hover': '310 80% 60%',
442 'primary-foreground': '240 5.9% 10%',
443 ring: '310 80% 50%'
444 }
445 },
446 PINK: {
447 name: 'Pink',
448 light: {
449 primary: '330 80% 60%',
450 'primary-hover': '330 80% 70%',
451 'primary-foreground': '0 0% 10%',
452 ring: '330 80% 60%'
453 },
454 dark: {
455 primary: '330 80% 60%',
456 'primary-hover': '330 80% 70%',
457 'primary-foreground': '240 5.9% 10%',
458 ring: '330 80% 60%'
459 }
460 },
461 ROSE: {
462 name: 'Rose',
463 light: {
464 primary: '350 80% 60%',
465 'primary-hover': '350 80% 70%',
466 'primary-foreground': '0 0% 10%',
467 ring: '350 80% 60%'
468 },
469 dark: {
470 primary: '350 80% 60%',
471 'primary-hover': '350 80% 70%',
472 'primary-foreground': '240 5.9% 10%',
473 ring: '350 80% 60%'
474 }
475 }
476 } as const
477 export type TPrimaryColor = keyof typeof PRIMARY_COLORS
478
479 export const LONG_PRESS_THRESHOLD = 400
480