constants.ts raw

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