Browse Source

more refactoring

imwald
Silberengel 1 month ago
parent
commit
3cf2a6046b
  1. 345
      package-lock.json
  2. 13
      package.json
  3. 2
      src/components/Note/AsciidocArticle/AsciidocArticle.tsx
  4. 2
      src/components/Note/MarkdownArticle/MarkdownArticle.tsx
  5. 2
      src/components/ui/sonner.tsx
  6. 16
      src/i18n/locales/ar.ts
  7. 16
      src/i18n/locales/de.ts
  8. 16
      src/i18n/locales/en.ts
  9. 16
      src/i18n/locales/es.ts
  10. 16
      src/i18n/locales/fa.ts
  11. 16
      src/i18n/locales/fr.ts
  12. 16
      src/i18n/locales/hi.ts
  13. 16
      src/i18n/locales/it.ts
  14. 16
      src/i18n/locales/ja.ts
  15. 16
      src/i18n/locales/ko.ts
  16. 16
      src/i18n/locales/pl.ts
  17. 16
      src/i18n/locales/pt-BR.ts
  18. 16
      src/i18n/locales/pt-PT.ts
  19. 16
      src/i18n/locales/ru.ts
  20. 16
      src/i18n/locales/th.ts
  21. 16
      src/i18n/locales/zh.ts
  22. 81
      src/lib/utils.ts
  23. 95
      src/pages/secondary/HomePage/index.tsx
  24. 203
      src/pages/secondary/RizfulPage/index.tsx
  25. 1215
      src/services/client.service.refactored.ts
  26. 3
      src/styles/katex-bundle.css
  27. 1
      src/styles/katex-core.min.css
  28. 73
      src/styles/katex-fonts-subset.css
  29. 41
      src/styles/katex-overrides.css
  30. 116
      vite.config.ts

345
package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "jumble-imwald", "name": "jumble-imwald",
"version": "18.0.3", "version": "19.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "jumble-imwald", "name": "jumble-imwald",
"version": "18.0.3", "version": "19.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@asciidoctor/core": "^3.0.4", "@asciidoctor/core": "^3.0.4",
@ -33,15 +33,18 @@
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.1.2", "@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-tabs": "^1.1.2", "@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-toast": "^1.2.4",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@tiptap/core": "^2.12.0",
"@tiptap/extension-document": "^2.12.0",
"@tiptap/extension-emoji": "^2.26.1", "@tiptap/extension-emoji": "^2.26.1",
"@tiptap/extension-hard-break": "^2.12.0",
"@tiptap/extension-history": "^2.12.0", "@tiptap/extension-history": "^2.12.0",
"@tiptap/extension-mention": "^2.12.0", "@tiptap/extension-mention": "^2.12.0",
"@tiptap/extension-paragraph": "^2.12.0",
"@tiptap/extension-placeholder": "^2.12.0", "@tiptap/extension-placeholder": "^2.12.0",
"@tiptap/extension-text": "^2.12.0",
"@tiptap/pm": "^2.12.0", "@tiptap/pm": "^2.12.0",
"@tiptap/react": "^2.12.0", "@tiptap/react": "^2.12.0",
"@tiptap/starter-kit": "^2.12.0",
"@tiptap/suggestion": "^2.12.0", "@tiptap/suggestion": "^2.12.0",
"@webbtc/webln-types": "^3.0.0", "@webbtc/webln-types": "^3.0.0",
"blossom-client-sdk": "^4.1.0", "blossom-client-sdk": "^4.1.0",
@ -55,17 +58,16 @@
"embla-carousel-wheel-gestures": "^8.1.0", "embla-carousel-wheel-gestures": "^8.1.0",
"emoji-picker-react": "^4.12.2", "emoji-picker-react": "^4.12.2",
"flexsearch": "^0.7.43", "flexsearch": "^0.7.43",
"franc-min": "^6.2.0",
"highlight.js": "^11.9.0", "highlight.js": "^11.9.0",
"i18next": "^24.2.0", "i18next": "^24.2.0",
"i18next-browser-languagedetector": "^8.0.4", "i18next-browser-languagedetector": "^8.0.4",
"katex": "^0.16.25", "katex": "^0.16.25",
"lru-cache": "^11.0.2", "lru-cache": "^11.0.2",
"lucide-react": "^0.469.0", "lucide-react": "^0.469.0",
"next-themes": "^0.4.6",
"nostr-tools": "^2.17.0", "nostr-tools": "^2.17.0",
"nstart-modal": "^2.0.0", "nstart-modal": "^2.0.0",
"path-to-regexp": "^8.2.0", "path-to-regexp": "^8.2.0",
"prosemirror-state": "^1.4.3",
"qr-code-styling": "^1.9.2", "qr-code-styling": "^1.9.2",
"qr-scanner": "^1.4.2", "qr-scanner": "^1.4.2",
"react": "^18.3.1", "react": "^18.3.1",
@ -84,7 +86,6 @@
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
"@testing-library/jest-dom": "^6.9.1", "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0", "@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^22.10.2", "@types/node": "^22.10.2",
"@types/react": "^18.3.17", "@types/react": "^18.3.17",
"@types/react-dom": "^18.3.5", "@types/react-dom": "^18.3.5",
@ -4175,40 +4176,6 @@
} }
} }
}, },
"node_modules/@radix-ui/react-toast": {
"version": "1.2.15",
"resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz",
"integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-collection": "1.1.7",
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.2",
"@radix-ui/react-dismissable-layer": "1.1.11",
"@radix-ui/react-portal": "1.1.9",
"@radix-ui/react-presence": "1.1.5",
"@radix-ui/react-primitive": "2.1.3",
"@radix-ui/react-use-callback-ref": "1.1.1",
"@radix-ui/react-use-controllable-state": "1.2.2",
"@radix-ui/react-use-layout-effect": "1.1.1",
"@radix-ui/react-visually-hidden": "1.2.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-callback-ref": { "node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
@ -5036,20 +5003,6 @@
} }
} }
}, },
"node_modules/@testing-library/user-event": {
"version": "14.6.1",
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz",
"integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12",
"npm": ">=6"
},
"peerDependencies": {
"@testing-library/dom": ">=7.21.4"
}
},
"node_modules/@tiptap/core": { "node_modules/@tiptap/core": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.27.2.tgz",
@ -5063,32 +5016,6 @@
"@tiptap/pm": "^2.7.0" "@tiptap/pm": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-blockquote": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.27.2.tgz",
"integrity": "sha512-oIGZgiAeA4tG3YxbTDfrmENL4/CIwGuP3THtHsNhwRqwsl9SfMk58Ucopi2GXTQSdYXpRJ0ahE6nPqB5D6j/Zw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-bold": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.27.2.tgz",
"integrity": "sha512-bR7J5IwjCGQ0s3CIxyMvOCnMFMzIvsc5OVZKscTN5UkXzFsaY6muUAIqtKxayBUucjtUskm5qZowJITCeCb1/A==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-bubble-menu": { "node_modules/@tiptap/extension-bubble-menu": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.27.2.tgz",
@ -5106,46 +5033,6 @@
"@tiptap/pm": "^2.7.0" "@tiptap/pm": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-bullet-list": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.27.2.tgz",
"integrity": "sha512-gmFuKi97u5f8uFc/GQs+zmezjiulZmFiDYTh3trVoLRoc2SAHOjGEB7qxdx7dsqmMN7gwiAWAEVurLKIi1lnnw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-code": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.27.2.tgz",
"integrity": "sha512-7X9AgwqiIGXoZX7uvdHQsGsjILnN/JaEVtqfXZnPECzKGaWHeK/Ao4sYvIIIffsyZJA8k5DC7ny2/0sAgr2TuA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-code-block": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.27.2.tgz",
"integrity": "sha512-KgvdQHS4jXr79aU3wZOGBIZYYl9vCB7uDEuRFV4so2rYrfmiYMw3T8bTnlNEEGe4RUeAms1i4fdwwvQp9nR1Dw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0",
"@tiptap/pm": "^2.7.0"
}
},
"node_modules/@tiptap/extension-document": { "node_modules/@tiptap/extension-document": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.27.2.tgz",
@ -5159,20 +5046,6 @@
"@tiptap/core": "^2.7.0" "@tiptap/core": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-dropcursor": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.27.2.tgz",
"integrity": "sha512-oEu/OrktNoQXq1x29NnH/GOIzQZm8ieTQl3FK27nxfBPA89cNoH4mFEUmBL5/OFIENIjiYG3qWpg6voIqzswNw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0",
"@tiptap/pm": "^2.7.0"
}
},
"node_modules/@tiptap/extension-emoji": { "node_modules/@tiptap/extension-emoji": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-emoji/-/extension-emoji-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-emoji/-/extension-emoji-2.27.2.tgz",
@ -5210,20 +5083,6 @@
"@tiptap/pm": "^2.7.0" "@tiptap/pm": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-gapcursor": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.27.2.tgz",
"integrity": "sha512-/c9VF1HBxj+AP54XGVgCmD9bEGYc5w5OofYCFQgM7l7PB1J00A4vOke0oPkHJnqnOOyPlFaxO/7N6l3XwFcnKA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0",
"@tiptap/pm": "^2.7.0"
}
},
"node_modules/@tiptap/extension-hard-break": { "node_modules/@tiptap/extension-hard-break": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.27.2.tgz",
@ -5237,19 +5096,6 @@
"@tiptap/core": "^2.7.0" "@tiptap/core": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-heading": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.27.2.tgz",
"integrity": "sha512-iM3yeRWuuQR/IRQ1djwNooJGfn9Jts9zF43qZIUf+U2NY8IlvdNsk2wTOdBgh6E0CamrStPxYGuln3ZS4fuglw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-history": { "node_modules/@tiptap/extension-history": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.27.2.tgz",
@ -5264,46 +5110,6 @@
"@tiptap/pm": "^2.7.0" "@tiptap/pm": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-horizontal-rule": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.27.2.tgz",
"integrity": "sha512-WGWUSgX+jCsbtf9Y9OCUUgRZYuwjVoieW5n6mAUohJ9/6gc6sGIOrUpBShf+HHo6WD+gtQjRd+PssmX3NPWMpg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0",
"@tiptap/pm": "^2.7.0"
}
},
"node_modules/@tiptap/extension-italic": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.27.2.tgz",
"integrity": "sha512-1OFsw2SZqfaqx5Fa5v90iNlPRcqyt+lVSjBwTDzuPxTPFY4Q0mL89mKgkq2gVHYNCiaRkXvFLDxaSvBWbmthgg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-list-item": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.27.2.tgz",
"integrity": "sha512-eJNee7IEGXMnmygM5SdMGDC8m/lMWmwNGf9fPCK6xk0NxuQRgmZHL6uApKcdH6gyNcRPHCqvTTkhEP7pbny/fg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-mention": { "node_modules/@tiptap/extension-mention": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-mention/-/extension-mention-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-mention/-/extension-mention-2.27.2.tgz",
@ -5319,19 +5125,6 @@
"@tiptap/suggestion": "^2.7.0" "@tiptap/suggestion": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-ordered-list": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.27.2.tgz",
"integrity": "sha512-M7A4tLGJcLPYdLC4CI2Gwl8LOrENQW59u3cMVa+KkwG1hzSJyPsbDpa1DI6oXPC2WtYiTf22zrbq3gVvH+KA2w==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-paragraph": { "node_modules/@tiptap/extension-paragraph": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.27.2.tgz",
@ -5359,19 +5152,6 @@
"@tiptap/pm": "^2.7.0" "@tiptap/pm": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-strike": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.27.2.tgz",
"integrity": "sha512-HHIjhafLhS2lHgfAsCwC1okqMsQzR4/mkGDm4M583Yftyjri1TNA7lzhzXWRFWiiMfJxKtdjHjUAQaHuteRTZw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/extension-text": { "node_modules/@tiptap/extension-text": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.27.2.tgz",
@ -5385,19 +5165,6 @@
"@tiptap/core": "^2.7.0" "@tiptap/core": "^2.7.0"
} }
}, },
"node_modules/@tiptap/extension-text-style": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.27.2.tgz",
"integrity": "sha512-Omk+uxjJLyEY69KStpCw5fA9asvV+MGcAX2HOxyISDFoLaL49TMrNjhGAuz09P1L1b0KGXo4ml7Q3v/Lfy4WPA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.7.0"
}
},
"node_modules/@tiptap/pm": { "node_modules/@tiptap/pm": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.27.2.tgz",
@ -5451,39 +5218,6 @@
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
} }
}, },
"node_modules/@tiptap/starter-kit": {
"version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.27.2.tgz",
"integrity": "sha512-bb0gJvPoDuyRUQ/iuN52j1//EtWWttw+RXAv1uJxfR0uKf8X7uAqzaOOgwjknoCIDC97+1YHwpGdnRjpDkOBxw==",
"license": "MIT",
"dependencies": {
"@tiptap/core": "^2.27.2",
"@tiptap/extension-blockquote": "^2.27.2",
"@tiptap/extension-bold": "^2.27.2",
"@tiptap/extension-bullet-list": "^2.27.2",
"@tiptap/extension-code": "^2.27.2",
"@tiptap/extension-code-block": "^2.27.2",
"@tiptap/extension-document": "^2.27.2",
"@tiptap/extension-dropcursor": "^2.27.2",
"@tiptap/extension-gapcursor": "^2.27.2",
"@tiptap/extension-hard-break": "^2.27.2",
"@tiptap/extension-heading": "^2.27.2",
"@tiptap/extension-history": "^2.27.2",
"@tiptap/extension-horizontal-rule": "^2.27.2",
"@tiptap/extension-italic": "^2.27.2",
"@tiptap/extension-list-item": "^2.27.2",
"@tiptap/extension-ordered-list": "^2.27.2",
"@tiptap/extension-paragraph": "^2.27.2",
"@tiptap/extension-strike": "^2.27.2",
"@tiptap/extension-text": "^2.27.2",
"@tiptap/extension-text-style": "^2.27.2",
"@tiptap/pm": "^2.27.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
}
},
"node_modules/@tiptap/suggestion": { "node_modules/@tiptap/suggestion": {
"version": "2.27.2", "version": "2.27.2",
"resolved": "https://registry.npmjs.org/@tiptap/suggestion/-/suggestion-2.27.2.tgz", "resolved": "https://registry.npmjs.org/@tiptap/suggestion/-/suggestion-2.27.2.tgz",
@ -6688,16 +6422,6 @@
"react-dom": "^18 || ^19 || ^19.0.0-rc" "react-dom": "^18 || ^19 || ^19.0.0-rc"
} }
}, },
"node_modules/collapse-white-space": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
"integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/color-convert": { "node_modules/color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -7748,9 +7472,9 @@
} }
}, },
"node_modules/flatted": { "node_modules/flatted": {
"version": "3.4.1", "version": "3.4.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
"integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@ -7807,19 +7531,6 @@
"url": "https://github.com/sponsors/rawify" "url": "https://github.com/sponsors/rawify"
} }
}, },
"node_modules/franc-min": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/franc-min/-/franc-min-6.2.0.tgz",
"integrity": "sha512-1uDIEUSlUZgvJa2AKYR/dmJC66v/PvGQ9mWfI9nOr/kPpMFyvswK0gPXOwpYJYiYD008PpHLkGfG58SPjQJFxw==",
"license": "MIT",
"dependencies": {
"trigram-utils": "^2.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/fs-extra": { "node_modules/fs-extra": {
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@ -9294,16 +9005,6 @@
"thenify-all": "^1.0.0" "thenify-all": "^1.0.0"
} }
}, },
"node_modules/n-gram": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/n-gram/-/n-gram-2.0.2.tgz",
"integrity": "sha512-S24aGsn+HLBxUGVAUFOwGpKs7LBcG4RudKU//eWzt/mQ97/NMKQxDWHyHx63UNWk/OOdihgmzoETn1tf5nQDzQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.11", "version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
@ -9329,16 +9030,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/next-themes": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz",
"integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
}
},
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.36", "version": "2.0.36",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
@ -11506,20 +11197,6 @@
"node": ">=20" "node": ">=20"
} }
}, },
"node_modules/trigram-utils": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/trigram-utils/-/trigram-utils-2.0.1.tgz",
"integrity": "sha512-nfWIXHEaB+HdyslAfMxSqWKDdmqY9I32jS7GnqpdWQnLH89r6A5sdk3fDVYqGAZ0CrT8ovAFSAo6HRiWcWNIGQ==",
"license": "MIT",
"dependencies": {
"collapse-white-space": "^2.0.0",
"n-gram": "^2.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",

13
package.json

@ -1,6 +1,6 @@
{ {
"name": "jumble-imwald", "name": "jumble-imwald",
"version": "18.0.3", "version": "19.0.0",
"description": "A user-friendly Nostr client focused on relay feed browsing and relay discovery, forked from Jumble", "description": "A user-friendly Nostr client focused on relay feed browsing and relay discovery, forked from Jumble",
"private": true, "private": true,
"type": "module", "type": "module",
@ -45,16 +45,20 @@
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.1.2", "@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-tabs": "^1.1.2", "@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-toast": "^1.2.4",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@tiptap/core": "^2.12.0",
"@tiptap/extension-document": "^2.12.0",
"@tiptap/extension-emoji": "^2.26.1", "@tiptap/extension-emoji": "^2.26.1",
"@tiptap/extension-hard-break": "^2.12.0",
"@tiptap/extension-history": "^2.12.0", "@tiptap/extension-history": "^2.12.0",
"@tiptap/extension-mention": "^2.12.0", "@tiptap/extension-mention": "^2.12.0",
"@tiptap/extension-paragraph": "^2.12.0",
"@tiptap/extension-placeholder": "^2.12.0", "@tiptap/extension-placeholder": "^2.12.0",
"@tiptap/extension-text": "^2.12.0",
"@tiptap/pm": "^2.12.0", "@tiptap/pm": "^2.12.0",
"@tiptap/react": "^2.12.0", "@tiptap/react": "^2.12.0",
"@tiptap/starter-kit": "^2.12.0",
"@tiptap/suggestion": "^2.12.0", "@tiptap/suggestion": "^2.12.0",
"prosemirror-state": "^1.4.3",
"@webbtc/webln-types": "^3.0.0", "@webbtc/webln-types": "^3.0.0",
"blossom-client-sdk": "^4.1.0", "blossom-client-sdk": "^4.1.0",
"blurhash": "^2.0.5", "blurhash": "^2.0.5",
@ -67,14 +71,12 @@
"embla-carousel-wheel-gestures": "^8.1.0", "embla-carousel-wheel-gestures": "^8.1.0",
"emoji-picker-react": "^4.12.2", "emoji-picker-react": "^4.12.2",
"flexsearch": "^0.7.43", "flexsearch": "^0.7.43",
"franc-min": "^6.2.0",
"highlight.js": "^11.9.0", "highlight.js": "^11.9.0",
"i18next": "^24.2.0", "i18next": "^24.2.0",
"i18next-browser-languagedetector": "^8.0.4", "i18next-browser-languagedetector": "^8.0.4",
"katex": "^0.16.25", "katex": "^0.16.25",
"lru-cache": "^11.0.2", "lru-cache": "^11.0.2",
"lucide-react": "^0.469.0", "lucide-react": "^0.469.0",
"next-themes": "^0.4.6",
"nostr-tools": "^2.17.0", "nostr-tools": "^2.17.0",
"nstart-modal": "^2.0.0", "nstart-modal": "^2.0.0",
"path-to-regexp": "^8.2.0", "path-to-regexp": "^8.2.0",
@ -96,7 +98,6 @@
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
"@testing-library/jest-dom": "^6.9.1", "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0", "@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^22.10.2", "@types/node": "^22.10.2",
"@types/react": "^18.3.17", "@types/react": "^18.3.17",
"@types/react-dom": "^18.3.5", "@types/react-dom": "^18.3.5",

2
src/components/Note/AsciidocArticle/AsciidocArticle.tsx

@ -31,7 +31,7 @@ import logger from '@/lib/logger'
import { extractBookMetadata } from '@/lib/bookstr-parser' import { extractBookMetadata } from '@/lib/bookstr-parser'
import { ExtendedKind } from '@/constants' import { ExtendedKind } from '@/constants'
import katex from 'katex' import katex from 'katex'
import 'katex/dist/katex.min.css' import '@/styles/katex-bundle.css'
import { WS_URL_REGEX, YOUTUBE_URL_REGEX } from '@/constants' import { WS_URL_REGEX, YOUTUBE_URL_REGEX } from '@/constants'
/** /**

2
src/components/Note/MarkdownArticle/MarkdownArticle.tsx

@ -29,7 +29,7 @@ import { preprocessMarkdownMediaLinks } from './preprocessMarkup'
import { PAYTO_URI_REGEX, parsePaytoUri } from '@/lib/payto' import { PAYTO_URI_REGEX, parsePaytoUri } from '@/lib/payto'
import PaytoLink from '@/components/PaytoLink' import PaytoLink from '@/components/PaytoLink'
import katex from 'katex' import katex from 'katex'
import 'katex/dist/katex.min.css' import '@/styles/katex-bundle.css'
import { isContentSpacingDebug, reprString } from '@/lib/content-spacing-debug' import { isContentSpacingDebug, reprString } from '@/lib/content-spacing-debug'
import logger from '@/lib/logger' import logger from '@/lib/logger'

2
src/components/ui/sonner.tsx

@ -1,11 +1,9 @@
// import { useTheme } from "next-themes"
import { useTheme } from '@/providers/ThemeProvider' import { useTheme } from '@/providers/ThemeProvider'
import { Toaster as Sonner } from 'sonner' import { Toaster as Sonner } from 'sonner'
type ToasterProps = React.ComponentProps<typeof Sonner> type ToasterProps = React.ComponentProps<typeof Sonner>
const Toaster = ({ ...props }: ToasterProps) => { const Toaster = ({ ...props }: ToasterProps) => {
// const { theme = "system" } = useTheme()
const { themeSetting } = useTheme() const { themeSetting } = useTheme()
return ( return (

16
src/i18n/locales/ar.ts

@ -430,22 +430,6 @@ export default {
'Are you absolutely sure?': 'هل أنت متأكد تماماً؟', 'Are you absolutely sure?': 'هل أنت متأكد تماماً؟',
'You will not be able to send zaps to others.': 'لن تتمكن من إرسال zaps للآخرين.', 'You will not be able to send zaps to others.': 'لن تتمكن من إرسال zaps للآخرين.',
Disconnect: 'قطع الاتصال', Disconnect: 'قطع الاتصال',
'Start with a Rizful Vault': 'ابدأ بمحفظة Rizful',
'or other wallets': 'أو محافظ أخرى',
'Rizful Vault': 'محفظة Rizful',
'Rizful Vault connected!': 'تم توصيل محفظة Rizful!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'يمكنك الآن استخدام محفظة Rizful الخاصة بك لإرسال zap إلى ملاحظاتك والمبدعين المفضلين لديك.',
'Your Lightning Address': 'عنوان Lightning الخاص بك',
'New to Rizful?': 'جديد في Rizful؟',
'Sign up for Rizful': 'سجل في Rizful',
'If you already have a Rizful account, you can skip this step.':
'إذا كان لديك حساب Rizful بالفعل، يمكنك تخطي هذه الخطوة.',
'Get your one-time code': 'احصل على رمز الاستخدام مرة واحدة',
'Get code': 'احصل على الرمز',
'Connect to your Rizful Vault': 'الاتصال بمحفظة Rizful الخاصة بك',
'Paste your one-time code here': 'الصق رمز الاستخدام مرة واحدة هنا',
Connect: 'اتصال',
'Set up your wallet to send and receive sats!': 'قم بإعداد محفظتك لإرسال واستقبال الساتس!', 'Set up your wallet to send and receive sats!': 'قم بإعداد محفظتك لإرسال واستقبال الساتس!',
'Set up': 'إعداد' 'Set up': 'إعداد'
} }

16
src/i18n/locales/de.ts

@ -637,22 +637,6 @@ export default {
'You will not be able to send zaps to others.': 'You will not be able to send zaps to others.':
'Du wirst keine Zaps mehr an andere senden können.', 'Du wirst keine Zaps mehr an andere senden können.',
Disconnect: 'Trennen', Disconnect: 'Trennen',
'Start with a Rizful Vault': 'Starte mit einem Rizful Vault',
'or other wallets': 'oder andere Wallets',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vault verbunden!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'Du kannst jetzt dein Rizful Vault verwenden, um deine Lieblingsnotizen und -ersteller zu zapen.',
'Your Lightning Address': 'Deine Lightning-Adresse',
'New to Rizful?': 'Neu bei Rizful?',
'Sign up for Rizful': 'Registriere dich bei Rizful',
'If you already have a Rizful account, you can skip this step.':
'Wenn du bereits ein Rizful-Konto hast, kannst du diesen Schritt überspringen.',
'Get your one-time code': 'Hole dir deinen Einmal-Code',
'Get code': 'Code holen',
'Connect to your Rizful Vault': 'Verbinde dich mit deinem Rizful Vault',
'Paste your one-time code here': 'Füge hier deinen Einmal-Code ein',
Connect: 'Verbinden',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'Richte deine Wallet ein, um Sats zu senden und zu empfangen!', 'Richte deine Wallet ein, um Sats zu senden und zu empfangen!',
'Set up': 'Einrichten', 'Set up': 'Einrichten',

16
src/i18n/locales/en.ts

@ -704,22 +704,6 @@ export default {
'Are you absolutely sure?': 'Are you absolutely sure?', 'Are you absolutely sure?': 'Are you absolutely sure?',
'You will not be able to send zaps to others.': 'You will not be able to send zaps to others.', 'You will not be able to send zaps to others.': 'You will not be able to send zaps to others.',
Disconnect: 'Disconnect', Disconnect: 'Disconnect',
'Start with a Rizful Vault': 'Start with a Rizful Vault',
'or other wallets': 'or other wallets',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vault connected!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'You can now use your Rizful Vault to zap your favorite notes and creators.',
'Your Lightning Address': 'Your Lightning Address',
'New to Rizful?': 'New to Rizful?',
'Sign up for Rizful': 'Sign up for Rizful',
'If you already have a Rizful account, you can skip this step.':
'If you already have a Rizful account, you can skip this step.',
'Get your one-time code': 'Get your one-time code',
'Get code': 'Get code',
'Connect to your Rizful Vault': 'Connect to your Rizful Vault',
'Paste your one-time code here': 'Paste your one-time code here',
Connect: 'Connect',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!', 'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!',
'Set up': 'Set up', 'Set up': 'Set up',
'nested events': 'nested events', 'nested events': 'nested events',

16
src/i18n/locales/es.ts

@ -437,22 +437,6 @@ export default {
'Are you absolutely sure?': '¿Estás absolutamente seguro?', 'Are you absolutely sure?': '¿Estás absolutamente seguro?',
'You will not be able to send zaps to others.': 'No podrás enviar zaps a otros.', 'You will not be able to send zaps to others.': 'No podrás enviar zaps a otros.',
Disconnect: 'Desconectar', Disconnect: 'Desconectar',
'Start with a Rizful Vault': 'Comienza con una Bóveda Rizful',
'or other wallets': 'o otras billeteras',
'Rizful Vault': 'Bóveda Rizful',
'Rizful Vault connected!': '¡Bóveda Rizful conectada!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'Ahora puedes usar tu Bóveda Rizful para zapear tus notas y creadores favoritos.',
'Your Lightning Address': 'Tu Dirección Lightning',
'New to Rizful?': '¿Nuevo en Rizful?',
'Sign up for Rizful': 'Regístrate en Rizful',
'If you already have a Rizful account, you can skip this step.':
'Si ya tienes una cuenta de Rizful, puedes omitir este paso.',
'Get your one-time code': 'Obtén tu código de un solo uso',
'Get code': 'Obtener código',
'Connect to your Rizful Vault': 'Conéctate a tu Bóveda Rizful',
'Paste your one-time code here': 'Pega tu código de un solo uso aquí',
Connect: 'Conectar',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'¡Configura tu billetera para enviar y recibir sats!', '¡Configura tu billetera para enviar y recibir sats!',
'Set up': 'Configurar' 'Set up': 'Configurar'

16
src/i18n/locales/fa.ts

@ -432,22 +432,6 @@ export default {
'Are you absolutely sure?': 'آیا کاملاً مطمئن هستید؟', 'Are you absolutely sure?': 'آیا کاملاً مطمئن هستید؟',
'You will not be able to send zaps to others.': 'شما قادر نخواهید بود به دیگران زپ ارسال کنید.', 'You will not be able to send zaps to others.': 'شما قادر نخواهید بود به دیگران زپ ارسال کنید.',
Disconnect: 'قطع اتصال', Disconnect: 'قطع اتصال',
'Start with a Rizful Vault': 'شروع با Rizful Vault',
'or other wallets': 'یا کیف پولهای دیگر',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vault متصل شد!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'اکنون میتوانید از Rizful Vault خود برای زپ کردن یادداشتها و سازندگان مورد علاقه خود استفاده کنید.',
'Your Lightning Address': 'آدرس لایتنینگ شما',
'New to Rizful?': 'جدید در Rizful؟',
'Sign up for Rizful': 'برای Rizful ثبت نام کنید',
'If you already have a Rizful account, you can skip this step.':
'اگر قبلاً حساب Rizful دارید، میتوانید این مرحله را رد کنید.',
'Get your one-time code': 'کد یکبار مصرف خود را دریافت کنید',
'Get code': 'دریافت کد',
'Connect to your Rizful Vault': 'اتصال به Rizful Vault خود',
'Paste your one-time code here': 'کد یکبار مصرف خود را اینجا بچسبانید',
Connect: 'اتصال',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'کیف پولت را تنظیم کن تا ساتس ارسال و دریافت کنی!', 'کیف پولت را تنظیم کن تا ساتس ارسال و دریافت کنی!',
'Set up': 'تنظیم' 'Set up': 'تنظیم'

16
src/i18n/locales/fr.ts

@ -442,22 +442,6 @@ export default {
'You will not be able to send zaps to others.': 'You will not be able to send zaps to others.':
'Vous ne pourrez plus envoyer de zaps aux autres.', 'Vous ne pourrez plus envoyer de zaps aux autres.',
Disconnect: 'Déconnecter', Disconnect: 'Déconnecter',
'Start with a Rizful Vault': 'Démarrer avec un coffre Rizful',
'or other wallets': 'ou d’autres portefeuilles',
'Rizful Vault': 'Coffre Rizful',
'Rizful Vault connected!': 'Coffre Rizful connecté !',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'Vous pouvez maintenant utiliser votre coffre Rizful pour zapper vos notes et créateurs préférés.',
'Your Lightning Address': 'Votre adresse Lightning',
'New to Rizful?': 'Nouveau sur Rizful ?',
'Sign up for Rizful': 'Inscrivez-vous sur Rizful',
'If you already have a Rizful account, you can skip this step.':
'Si vous avez déjà un compte Rizful, vous pouvez passer cette étape.',
'Get your one-time code': 'Obtenez votre code à usage unique',
'Get code': 'Obtenir le code',
'Connect to your Rizful Vault': 'Connectez-vous à votre coffre Rizful',
'Paste your one-time code here': 'Collez votre code à usage unique ici',
Connect: 'Connecter',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'Configurez votre portefeuille pour envoyer et recevoir des sats !', 'Configurez votre portefeuille pour envoyer et recevoir des sats !',
'Set up': 'Configurer' 'Set up': 'Configurer'

16
src/i18n/locales/hi.ts

@ -434,22 +434,6 @@ export default {
'Are you absolutely sure?': 'क आप प तरह सिित ह?', 'Are you absolutely sure?': 'क आप प तरह सिित ह?',
'You will not be able to send zaps to others.': 'आप दसरप नहज प।', 'You will not be able to send zaps to others.': 'आप दसरप नहज प।',
Disconnect: 'डिकनट कर', Disconnect: 'डिकनट कर',
'Start with a Rizful Vault': 'Rizful वट कथ श कर',
'or other wallets': 'य अनय वट',
'Rizful Vault': 'Rizful वट',
'Rizful Vault connected!': 'Rizful वट कनड!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'अब आप अपन Rizful वट क उपयग अपन पसस और किएटरस कप करनिए कर सकत।',
'Your Lightning Address': 'आपकइटनिग पत',
'New to Rizful?': 'Rizful म नय?',
'Sign up for Rizful': 'Rizful किए सइन अप कर',
'If you already have a Rizful account, you can skip this step.':
'यदि आपकस पहल एक Rizful अकट ह, त आप इस चरण क सकत।',
'Get your one-time code': 'अपन वन-टइम कड पत कर',
'Get code': 'कड पत कर',
'Connect to your Rizful Vault': 'अपन Rizful वट स कनट कर',
'Paste your one-time code here': 'अपन वन-टइम कड यहट कर',
Connect: 'कनट कर',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'सस भजन और पत करनिए अपनट सट कर!', 'सस भजन और पत करनिए अपनट सट कर!',
'Set up': 'सट कर' 'Set up': 'सट कर'

16
src/i18n/locales/it.ts

@ -437,22 +437,6 @@ export default {
'Are you absolutely sure?': 'Sei assolutamente sicuro?', 'Are you absolutely sure?': 'Sei assolutamente sicuro?',
'You will not be able to send zaps to others.': 'Non sarai in grado di inviare zaps ad altri.', 'You will not be able to send zaps to others.': 'Non sarai in grado di inviare zaps ad altri.',
Disconnect: 'Disconnetti', Disconnect: 'Disconnetti',
'Start with a Rizful Vault': 'Inizia con un Rizful Vault',
'or other wallets': 'o altri wallet',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vault connesso!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'Puoi ora usare il tuo Rizful Vault per zappare le tue note e creatori preferiti.',
'Your Lightning Address': 'Il tuo Indirizzo Lightning',
'New to Rizful?': 'Nuovo a Rizful?',
'Sign up for Rizful': 'Iscriviti a Rizful',
'If you already have a Rizful account, you can skip this step.':
'Se hai già un account Rizful, puoi saltare questo passaggio.',
'Get your one-time code': 'Ottieni il tuo codice monouso',
'Get code': 'Ottieni codice',
'Connect to your Rizful Vault': 'Connettiti al tuo Rizful Vault',
'Paste your one-time code here': 'Incolla qui il tuo codice monouso',
Connect: 'Connetti',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'Configura il tuo wallet per inviare e ricevere sats!', 'Configura il tuo wallet per inviare e ricevere sats!',
'Set up': 'Configura' 'Set up': 'Configura'

16
src/i18n/locales/ja.ts

@ -433,22 +433,6 @@ export default {
'Are you absolutely sure?': '本当に確かですか?', 'Are you absolutely sure?': '本当に確かですか?',
'You will not be able to send zaps to others.': '他の人にZapを送信できなくなります。', 'You will not be able to send zaps to others.': '他の人にZapを送信できなくなります。',
Disconnect: '接続解除', Disconnect: '接続解除',
'Start with a Rizful Vault': 'Rizful Vaultで始める',
'or other wallets': 'または他のウォレット',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vaultが接続されました!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'これで、Rizful Vaultを使用してお気に入りのノートやクリエイターにZapを送信できます。',
'Your Lightning Address': 'あなたのライトニングアドレス',
'New to Rizful?': 'Rizfulを初めて利用しますか?',
'Sign up for Rizful': 'Rizfulにサインアップ',
'If you already have a Rizful account, you can skip this step.':
'すでにRizfulアカウントをお持ちの場合は、このステップをスキップできます。',
'Get your one-time code': 'ワンタイムコードを取得',
'Get code': 'コードを取得',
'Connect to your Rizful Vault': 'Rizful Vaultに接続',
'Paste your one-time code here': 'ここにワンタイムコードを貼り付けてください',
Connect: '接続',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'ウォレットを設定してサッツを送受信しましょう!', 'ウォレットを設定してサッツを送受信しましょう!',
'Set up': '設定する' 'Set up': '設定する'

16
src/i18n/locales/ko.ts

@ -433,22 +433,6 @@ export default {
'Are you absolutely sure?': '정말 확실합니까?', 'Are you absolutely sure?': '정말 확실합니까?',
'You will not be able to send zaps to others.': '다른 사람에게 잽을 보낼 수 없습니다.', 'You will not be able to send zaps to others.': '다른 사람에게 잽을 보낼 수 없습니다.',
Disconnect: '연결 해제', Disconnect: '연결 해제',
'Start with a Rizful Vault': 'Rizful Vault로 시작하기',
'or other wallets': '또는 다른 지갑',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vault 연결됨!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'이제 Rizful Vault를 사용하여 좋아하는 노트와 크리에이터에게 잽을 보낼 수 있습니다.',
'Your Lightning Address': '귀하의 라이트닝 주소',
'New to Rizful?': 'Rizful이 처음이신가요?',
'Sign up for Rizful': 'Rizful에 가입하기',
'If you already have a Rizful account, you can skip this step.':
'이미 Rizful 계정이 있다면 이 단계를 건너뛸 수 있습니다.',
'Get your one-time code': '일회용 코드 받기',
'Get code': '코드 받기',
'Connect to your Rizful Vault': 'Rizful Vault에 연결',
'Paste your one-time code here': '여기에 일회용 코드를 붙여넣기',
Connect: '연결',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'사츠를 보내고 받을 수 있도록 지갑을 설정하세요!', '사츠를 보내고 받을 수 있도록 지갑을 설정하세요!',
'Set up': '설정하기' 'Set up': '설정하기'

16
src/i18n/locales/pl.ts

@ -437,22 +437,6 @@ export default {
'Are you absolutely sure?': 'Czy jesteś całkowicie pewien?', 'Are you absolutely sure?': 'Czy jesteś całkowicie pewien?',
'You will not be able to send zaps to others.': 'Nie będziesz mógł wysyłać zapów innym.', 'You will not be able to send zaps to others.': 'Nie będziesz mógł wysyłać zapów innym.',
Disconnect: 'Odłącz', Disconnect: 'Odłącz',
'Start with a Rizful Vault': 'Zacznij od Rizful Vault',
'or other wallets': 'Lub inne portfele',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vault połączony!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'Możesz teraz używać swojego Rizful Vault, aby zapować swoje ulubione notatki i twórców.',
'Your Lightning Address': 'Twój Lightning Adres',
'New to Rizful?': 'Nowy w Rizful?',
'Sign up for Rizful': 'Zarejestruj się w Rizful',
'If you already have a Rizful account, you can skip this step.':
'Jeśli masz już konto Rizful, możesz pominąć ten krok.',
'Get your one-time code': 'Uzyskaj swój jednorazowy kod',
'Get code': 'Uzyskaj kod',
'Connect to your Rizful Vault': 'Połącz się ze swoim Rizful Vault',
'Paste your one-time code here': 'Wklej tutaj swój jednorazowy kod',
Connect: 'Połącz',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'Skonfiguruj swój portfel, aby wysyłać i odbierać satsy!', 'Skonfiguruj swój portfel, aby wysyłać i odbierać satsy!',
'Set up': 'Skonfiguruj' 'Set up': 'Skonfiguruj'

16
src/i18n/locales/pt-BR.ts

@ -434,22 +434,6 @@ export default {
'Are you absolutely sure?': 'Você tem certeza absoluta?', 'Are you absolutely sure?': 'Você tem certeza absoluta?',
'You will not be able to send zaps to others.': 'Você não poderá enviar zaps para outros.', 'You will not be able to send zaps to others.': 'Você não poderá enviar zaps para outros.',
Disconnect: 'Desconectar', Disconnect: 'Desconectar',
'Start with a Rizful Vault': 'Comece com um Cofre Rizful',
'or other wallets': 'ou outras carteiras',
'Rizful Vault': 'Cofre Rizful',
'Rizful Vault connected!': 'Cofre Rizful conectado!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'Você pode agora usar seu Cofre Rizful para zapear suas notas e criadores favoritos.',
'Your Lightning Address': 'Seu Endereço Lightning',
'New to Rizful?': 'Novo no Rizful?',
'Sign up for Rizful': 'Inscreva-se no Rizful',
'If you already have a Rizful account, you can skip this step.':
'Se você já tem uma conta Rizful, pode pular esta etapa.',
'Get your one-time code': 'Obtenha seu código único',
'Get code': 'Obter código',
'Connect to your Rizful Vault': 'Conecte-se ao seu Cofre Rizful',
'Paste your one-time code here': 'Cole seu código único aqui',
Connect: 'Conectar',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'Configure sua carteira para enviar e receber sats!', 'Configure sua carteira para enviar e receber sats!',
'Set up': 'Configurar' 'Set up': 'Configurar'

16
src/i18n/locales/pt-PT.ts

@ -437,22 +437,6 @@ export default {
'Are you absolutely sure?': 'Tem certeza absoluta?', 'Are you absolutely sure?': 'Tem certeza absoluta?',
'You will not be able to send zaps to others.': 'Você não poderá enviar zaps para outros.', 'You will not be able to send zaps to others.': 'Você não poderá enviar zaps para outros.',
Disconnect: 'Desconectar', Disconnect: 'Desconectar',
'Start with a Rizful Vault': 'Comece com um Cofre Rizful',
'or other wallets': 'outras carteiras',
'Rizful Vault': 'Cofre Rizful',
'Rizful Vault connected!': 'Cofre Rizful conectado!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'Agora você pode usar seu Cofre Rizful para zapear suas notas e criadores favoritos.',
'Your Lightning Address': 'Seu Endereço Lightning',
'New to Rizful?': 'Novo no Rizful?',
'Sign up for Rizful': 'Inscreva-se no Rizful',
'If you already have a Rizful account, you can skip this step.':
'Se você já tem uma conta Rizful, pode pular esta etapa.',
'Get your one-time code': 'Obtenha seu código único',
'Get code': 'Obter código',
'Connect to your Rizful Vault': 'Conecte-se ao seu Cofre Rizful',
'Paste your one-time code here': 'Cole seu código único aqui',
Connect: 'Conectar',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'Configure a sua carteira para enviar e receber sats!', 'Configure a sua carteira para enviar e receber sats!',
'Set up': 'Configurar' 'Set up': 'Configurar'

16
src/i18n/locales/ru.ts

@ -439,22 +439,6 @@ export default {
'Are you absolutely sure?': 'Вы абсолютно уверены?', 'Are you absolutely sure?': 'Вы абсолютно уверены?',
'You will not be able to send zaps to others.': 'Вы не сможете отправлять запы другим.', 'You will not be able to send zaps to others.': 'Вы не сможете отправлять запы другим.',
Disconnect: 'Отключить', Disconnect: 'Отключить',
'Start with a Rizful Vault': 'Начать с Rizful Vault',
'or other wallets': 'или другие кошельки',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vault подключён!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'Теперь вы можете использовать свой Rizful Vault, чтобы заппить ваши любимые заметки и создателей.',
'Your Lightning Address': 'Ваш Lightning-адрес',
'New to Rizful?': 'Новичок в Rizful?',
'Sign up for Rizful': 'Зарегистрируйтесь на Rizful',
'If you already have a Rizful account, you can skip this step.':
'Если у вас уже есть аккаунт Rizful, вы можете пропустить этот шаг.',
'Get your one-time code': 'Получите ваш одноразовый код',
'Get code': 'Получить код',
'Connect to your Rizful Vault': 'Подключитесь к вашему Rizful Vault',
'Paste your one-time code here': 'Вставьте ваш одноразовый код здесь',
Connect: 'Подключить',
'Set up your wallet to send and receive sats!': 'Set up your wallet to send and receive sats!':
'Настройте свой кошелёк, чтобы отправлять и получать саты!', 'Настройте свой кошелёк, чтобы отправлять и получать саты!',
'Set up': 'Настроить' 'Set up': 'Настроить'

16
src/i18n/locales/th.ts

@ -428,22 +428,6 @@ export default {
'Are you absolutely sure?': 'คณแนใจอยางยงหรอไม?', 'Are you absolutely sure?': 'คณแนใจอยางยงหรอไม?',
'You will not be able to send zaps to others.': 'คณจะไมสามารถสงซาตสไปยงผนได', 'You will not be able to send zaps to others.': 'คณจะไมสามารถสงซาตสไปยงผนได',
Disconnect: 'ตดการเชอมตอ', Disconnect: 'ตดการเชอมตอ',
'Start with a Rizful Vault': 'เรมตนดวย Rizful Vault',
'or other wallets': 'หรอกระเปาสตางคนๆ',
'Rizful Vault': 'Rizful Vault',
'Rizful Vault connected!': 'Rizful Vault เชอมตอแลว!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'คณสามารถใช Rizful Vault ของคณเพอสงซาตสไปยงโนตและผสรางทณชนชอบไดแลว',
'Your Lightning Address': 'ทอย Lightning ของคณ',
'New to Rizful?': 'ใหมบ Rizful?',
'Sign up for Rizful': 'สมครสมาชก Rizful',
'If you already have a Rizful account, you can skip this step.':
'หากคณมญช Rizful อยแลว คณสามารถขามขนตอนนได',
'Get your one-time code': 'รบรหสใชครงเดยวของคณ',
'Get code': 'รบรหส',
'Connect to your Rizful Vault': 'เชอมตอกบ Rizful Vault ของคณ',
'Paste your one-time code here': 'วางรหสใชครงเดยวของคณท',
Connect: 'เชอมตอ',
'Set up your wallet to send and receive sats!': 'ตงคากระเปาของคณเพอสงและรบ sats!', 'Set up your wallet to send and receive sats!': 'ตงคากระเปาของคณเพอสงและรบ sats!',
'Set up': 'ตงคา' 'Set up': 'ตงคา'
} }

16
src/i18n/locales/zh.ts

@ -426,22 +426,6 @@ export default {
'Are you absolutely sure?': '您确定吗?', 'Are you absolutely sure?': '您确定吗?',
'You will not be able to send zaps to others.': '您将无法向他人发送打闪。', 'You will not be able to send zaps to others.': '您将无法向他人发送打闪。',
Disconnect: '断开连接', Disconnect: '断开连接',
'Start with a Rizful Vault': '从 Rizful 钱包开始',
'or other wallets': '或其他钱包',
'Rizful Vault': 'Rizful 钱包',
'Rizful Vault connected!': 'Rizful 钱包已连接!',
'You can now use your Rizful Vault to zap your favorite notes and creators.':
'您现在可以使用您的 Rizful 钱包为您喜欢的笔记和创作者打闪。',
'Your Lightning Address': '您的闪电地址',
'New to Rizful?': '第一次使用 Rizful?',
'Sign up for Rizful': '注册 Rizful',
'If you already have a Rizful account, you can skip this step.':
'如果您已经有一个 Rizful 账户,可以跳过此步骤。',
'Get your one-time code': '获取一次性代码',
'Get code': '获取代码',
'Connect to your Rizful Vault': '连接到您的 Rizful 钱包',
'Paste your one-time code here': '将您的一次性代码粘贴到此处',
Connect: '连接',
'Set up your wallet to send and receive sats!': '设置你的钱包以发送和接收 sats!', 'Set up your wallet to send and receive sats!': '设置你的钱包以发送和接收 sats!',
'Set up': '去设置' 'Set up': '去设置'
} }

81
src/lib/utils.ts

@ -1,16 +1,6 @@
import {
EMAIL_REGEX,
EMBEDDED_EVENT_REGEX,
EMBEDDED_MENTION_REGEX,
EMOJI_REGEX,
HASHTAG_REGEX,
URL_REGEX,
WS_URL_REGEX
} from '@/constants'
import { TEmoji } from '@/types' import { TEmoji } from '@/types'
import { clsx, type ClassValue } from 'clsx' import { clsx, type ClassValue } from 'clsx'
import { parseNativeEmoji } from 'emoji-picker-react/src/dataUtils/parseNativeEmoji' import { parseNativeEmoji } from 'emoji-picker-react/src/dataUtils/parseNativeEmoji'
import { franc } from 'franc-min'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
@ -102,77 +92,6 @@ export function isDevEnv() {
return process.env.NODE_ENV === 'development' return process.env.NODE_ENV === 'development'
} }
export function detectLanguage(text?: string): string | null {
if (!text) {
return null
}
const cleanText = text
.replace(URL_REGEX, '')
.replace(WS_URL_REGEX, '')
.replace(EMAIL_REGEX, '')
.replace(EMBEDDED_MENTION_REGEX, '')
.replace(EMBEDDED_EVENT_REGEX, '')
.replace(HASHTAG_REGEX, '')
.replace(EMOJI_REGEX, '')
.trim()
if (!cleanText) {
return null
}
if (/[\u3040-\u309f\u30a0-\u30ff]/.test(cleanText)) {
return 'ja'
}
if (/[\u0e00-\u0e7f]/.test(cleanText)) {
return 'th'
}
if (/[\u4e00-\u9fff]/.test(cleanText)) {
return 'zh'
}
if (/[\u0600-\u06ff]/.test(cleanText)) {
return 'ar'
}
if (/[\u0590-\u05FF]/.test(cleanText)) {
return 'fa'
}
if (/[\u0400-\u04ff]/.test(cleanText)) {
return 'ru'
}
if (/[\u0900-\u097f]/.test(cleanText)) {
return 'hi'
}
try {
const detectedLang = franc(cleanText)
const langMap: { [key: string]: string } = {
ara: 'ar', // Arabic
deu: 'de', // German
eng: 'en', // English
spa: 'es', // Spanish
fas: 'fa', // Persian (Farsi)
pes: 'fa', // Persian (alternative code)
fra: 'fr', // French
hin: 'hi', // Hindi
ita: 'it', // Italian
jpn: 'ja', // Japanese
pol: 'pl', // Polish
por: 'pt', // Portuguese
rus: 'ru', // Russian
cmn: 'zh', // Chinese (Mandarin)
zho: 'zh' // Chinese (alternative code)
}
const normalizedLang = langMap[detectedLang]
if (!normalizedLang) {
return 'und'
}
return normalizedLang
} catch {
return 'und'
}
}
export function parseEmojiPickerUnified(unified: string): string | TEmoji | undefined { export function parseEmojiPickerUnified(unified: string): string | TEmoji | undefined {
if (unified.startsWith(':')) { if (unified.startsWith(':')) {
const secondColonIndex = unified.indexOf(':', 1) const secondColonIndex = unified.indexOf(':', 1)

95
src/pages/secondary/HomePage/index.tsx

@ -1,95 +0,0 @@
import { useSecondaryPage, useSmartRelayNavigation } from '@/PageManager'
import RelaySimpleInfo from '@/components/RelaySimpleInfo'
import { Button } from '@/components/ui/button'
import { RECOMMENDED_RELAYS } from '@/constants'
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
import { toRelay } from '@/lib/link'
import relayInfoService from '@/services/relay-info.service'
import { TRelayInfo } from '@/types'
import { ArrowRight, Server } from 'lucide-react'
import { forwardRef, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import logger from '@/lib/logger'
const HomePage = forwardRef(({ index }: { index?: number }, ref) => {
const { t } = useTranslation()
const { navigateToPrimaryPage } = useSecondaryPage()
const { navigateToRelay } = useSmartRelayNavigation()
// DEPRECATED: updateShowRecommendedRelaysPanel removed - double-panel functionality disabled
const [recommendedRelayInfos, setRecommendedRelayInfos] = useState<TRelayInfo[]>([])
useEffect(() => {
const init = async () => {
try {
const relays = await relayInfoService.getRelayInfos(RECOMMENDED_RELAYS)
setRecommendedRelayInfos(relays.filter(Boolean) as TRelayInfo[])
} catch (error) {
logger.error('Failed to fetch recommended relays', { error })
}
}
init()
}, [])
if (!recommendedRelayInfos.length) {
return (
<SecondaryPageLayout ref={ref} index={index} hideBackButton hideTitlebarBottomBorder>
<div className="text-muted-foreground w-full h-screen flex items-center justify-center">
{t('Welcome! 🥳')}
</div>
</SecondaryPageLayout>
)
}
return (
<SecondaryPageLayout
ref={ref}
index={index}
title={
<div className="flex items-center gap-2">
<Server />
<div>{t('Recommended relays')}</div>
</div>
}
controls={
// DEPRECATED: Close button removed - double-panel functionality disabled
null
}
hideBackButton
hideTitlebarBottomBorder
>
<div className="px-4 pt-2">
<div className="grid grid-cols-2 gap-3">
{recommendedRelayInfos.map((relayInfo) => (
<RelaySimpleInfo
key={relayInfo.url}
className="clickable h-auto px-4 py-3 rounded-lg border"
relayInfo={relayInfo}
onClick={(e) => {
e.stopPropagation()
navigateToRelay(toRelay(relayInfo.url))
}}
/>
))}
</div>
<div className="flex mt-2 justify-center">
<Button
variant="ghost"
onClick={() => {
navigateToPrimaryPage('home')
requestAnimationFrame(() => {
window.dispatchEvent(
new CustomEvent('restorePageTab', { detail: { page: 'home', tab: 'explore' } })
)
})
}}
>
<div>{t('Explore more')}</div>
<ArrowRight />
</Button>
</div>
</div>
</SecondaryPageLayout>
)
})
HomePage.displayName = 'HomePage'
export default HomePage

203
src/pages/secondary/RizfulPage/index.tsx

@ -1,203 +0,0 @@
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
import { createProfileDraftEvent } from '@/lib/draft-event'
import { isEmail } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider'
import { useZap } from '@/providers/ZapProvider'
import { connectNWC, WebLNProviders } from '@getalby/bitcoin-connect'
import { Check, CheckCircle2, Copy, ExternalLink, Loader2 } from 'lucide-react'
import { forwardRef, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
const RIZFUL_URL = 'https://rizful.com'
const RIZFUL_SIGNUP_URL = `${RIZFUL_URL}/create-account`
const RIZFUL_GET_TOKEN_URL = `${RIZFUL_URL}/nostr_onboarding_auth_token/get_token`
const RIZFUL_TOKEN_EXCHANGE_URL = `${RIZFUL_URL}/nostr_onboarding_auth_token/post_for_secrets`
const RizfulPage = forwardRef(({ index }: { index?: number }, ref) => {
const { t } = useTranslation()
const { pubkey, profile, profileEvent, publish, updateProfileEvent } = useNostr()
const { provider } = useZap()
const [token, setToken] = useState('')
const [connecting, setConnecting] = useState(false)
const [connected, setConnected] = useState(false)
const [copiedLightningAddress, setCopiedLightningAddress] = useState(false)
const [lightningAddress, setLightningAddress] = useState('')
useEffect(() => {
if (provider instanceof WebLNProviders.NostrWebLNProvider) {
const lud16 = provider.client.lud16
const domain = lud16?.split('@')[1]
if (domain !== 'rizful.com') return
if (lud16) {
setConnected(true)
setLightningAddress(lud16)
}
}
}, [provider])
const updateUserProfile = async (address: string) => {
try {
if (address === profile?.lightningAddress) {
return
}
const profileContent = profileEvent ? JSON.parse(profileEvent.content) : {}
if (isEmail(address)) {
profileContent.lud16 = address
} else if (address.startsWith('lnurl')) {
profileContent.lud06 = address
} else {
throw new Error(t('Invalid Lightning Address'))
}
if (!profileContent.nip05) {
profileContent.nip05 = address
}
const profileDraftEvent = createProfileDraftEvent(
JSON.stringify(profileContent),
profileEvent?.tags
)
const newProfileEvent = await publish(profileDraftEvent)
await updateProfileEvent(newProfileEvent)
} catch (e: unknown) {
toast.error(e instanceof Error ? e.message : String(e))
}
}
const connectRizful = async () => {
setConnecting(true)
try {
const r = await fetch(RIZFUL_TOKEN_EXCHANGE_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'omit',
body: JSON.stringify({
secret_code: token.trim(),
nostr_public_key: pubkey
})
})
if (!r.ok) {
const errorText = await r.text()
throw new Error(errorText || 'Exchange failed')
}
const j = (await r.json()) as {
nwc_uri?: string
lightning_address?: string
}
if (j.nwc_uri) {
connectNWC(j.nwc_uri)
}
if (j.lightning_address) {
updateUserProfile(j.lightning_address)
}
} catch (e: unknown) {
toast.error(e instanceof Error ? e.message : String(e))
} finally {
setConnecting(false)
}
}
if (connected) {
return (
<SecondaryPageLayout ref={ref} index={index} title={t('Rizful Vault')}>
<div className="px-4 pt-3 space-y-6 flex flex-col items-center">
<CheckCircle2 className="size-40 fill-green-400 text-background" />
<div className="font-semibold text-2xl">{t('Rizful Vault connected!')}</div>
<div className="text-center text-sm text-muted-foreground">
{t('You can now use your Rizful Vault to zap your favorite notes and creators.')}
</div>
{lightningAddress && (
<div className="flex flex-col items-center gap-2">
<div>{t('Your Lightning Address')}:</div>
<div
className="font-semibold text-lg rounded-lg px-4 py-1 flex justify-center items-center gap-2 cursor-pointer hover:bg-accent/80"
onClick={() => {
navigator.clipboard.writeText(lightningAddress)
setCopiedLightningAddress(true)
setTimeout(() => setCopiedLightningAddress(false), 2000)
}}
>
{lightningAddress}{' '}
{copiedLightningAddress ? (
<Check className="size-4" />
) : (
<Copy className="size-4" />
)}
</div>
</div>
)}
</div>
</SecondaryPageLayout>
)
}
return (
<SecondaryPageLayout ref={ref} index={index} title={t('Rizful Vault')}>
<div className="px-4 pt-3 space-y-6">
<div className="space-y-2">
<div className="font-semibold">1. {t('New to Rizful?')}</div>
<Button
className="bg-lime-500 hover:bg-lime-500/90 w-64"
onClick={() => window.open(RIZFUL_SIGNUP_URL, '_blank')}
>
{t('Sign up for Rizful')} <ExternalLink />
</Button>
<div className="text-sm text-muted-foreground">
{t('If you already have a Rizful account, you can skip this step.')}
</div>
</div>
<div className="space-y-2">
<div className="font-semibold">2. {t('Get your one-time code')}</div>
<Button
className="bg-orange-500 hover:bg-orange-500/90 w-64"
onClick={() => openPopup(RIZFUL_GET_TOKEN_URL, 'rizful_codes')}
>
{t('Get code')}
<ExternalLink />
</Button>
</div>
<div className="space-y-2">
<div className="font-semibold">3. {t('Connect to your Rizful Vault')}</div>
<Input
placeholder={t('Paste your one-time code here')}
value={token}
onChange={(e) => {
setToken(e.target.value.trim())
}}
/>
<Button
className="bg-sky-500 hover:bg-sky-500/90 w-64"
disabled={!token || connecting}
onClick={() => connectRizful()}
>
{connecting && <Loader2 className="animate-spin" />}
{t('Connect')}
</Button>
</div>
</div>
</SecondaryPageLayout>
)
})
RizfulPage.displayName = 'RizfulPage'
export default RizfulPage
function openPopup(url: string, name: string, width = 520, height = 700) {
const left = Math.max((window.screenX || 0) + (window.innerWidth - width) / 2, 0)
const top = Math.max((window.screenY || 0) + (window.innerHeight - height) / 2, 0)
return window.open(
url,
name,
`width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no,status=no`
)
}

1215
src/services/client.service.refactored.ts

File diff suppressed because it is too large Load Diff

3
src/styles/katex-bundle.css

@ -0,0 +1,3 @@
@import './katex-fonts-subset.css';
@import './katex-core.min.css';
@import './katex-overrides.css';

1
src/styles/katex-core.min.css vendored

File diff suppressed because one or more lines are too long

73
src/styles/katex-fonts-subset.css

@ -0,0 +1,73 @@
/* Subset of KaTeX fonts: Main + Math + Size14 (woff2 only). Drops AMS, Caligraphic,
Fraktur, SansSerif, Script, Typewriter to shrink the build / PWA precache. */
@font-face {
font-family: KaTeX_Main;
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Main-Bold.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Main;
font-style: italic;
font-weight: 700;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Main-BoldItalic.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Main;
font-style: italic;
font-weight: 400;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Main-Italic.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Main;
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Main-Regular.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Math;
font-style: italic;
font-weight: 700;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Math-BoldItalic.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Math;
font-style: italic;
font-weight: 400;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Math-Italic.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Size1;
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Size1-Regular.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Size2;
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Size2-Regular.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Size3;
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Size3-Regular.woff2') format('woff2');
}
@font-face {
font-family: KaTeX_Size4;
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('../../node_modules/katex/dist/fonts/KaTeX_Size4-Regular.woff2') format('woff2');
}

41
src/styles/katex-overrides.css

@ -0,0 +1,41 @@
/* Map styles that referenced bundled-out fonts onto KaTeX_Main so layout still works;
\mathbb, \mathcal, \mathfrak, etc. will not match canonical TeX glyphs. */
.katex .texttt,
.katex .mathtt {
font-family: KaTeX_Main, ui-monospace, monospace;
}
.katex .textsf,
.katex .mathsf,
.katex .mathboldsf,
.katex .textboldsf,
.katex .mathitsf,
.katex .mathsfit,
.katex .textitsf {
font-family: KaTeX_Main, sans-serif;
}
.katex .mathboldsf,
.katex .textboldsf {
font-weight: 700;
}
.katex .mathitsf,
.katex .mathsfit,
.katex .textitsf {
font-style: italic;
}
.katex .amsrm,
.katex .mathbb,
.katex .textbb,
.katex .mathcal,
.katex .mathfrak,
.katex .textfrak,
.katex .mathboldfrak,
.katex .textboldfrak,
.katex .mathscr,
.katex .textscr {
font-family: KaTeX_Main, Times New Roman, serif;
}
.katex .mathboldfrak,
.katex .textboldfrak {
font-weight: 700;
}

116
vite.config.ts

@ -38,6 +38,122 @@ export default defineConfig({
}, },
build: { build: {
rollupOptions: { rollupOptions: {
output: {
manualChunks(id) {
if (!id.includes('node_modules')) return undefined
// Lazy-loaded only — must not share a chunk with sync vendors or it gets preloaded
if (id.includes('@asciidoctor')) {
return 'vendor-asciidoctor'
}
if (id.includes('/katex/') || id.includes('node_modules/katex/')) {
return 'vendor-katex'
}
// React core (load first; keep together)
if (/node_modules\/(react-dom|react\/|scheduler\/|use-sync-external-store\/)/.test(id)) {
return 'vendor-react'
}
// TipTap + ProseMirror
if (id.includes('@tiptap') || id.includes('prosemirror-')) {
return 'vendor-editor'
}
// Radix UI primitives
if (id.includes('@radix-ui')) {
return 'vendor-radix'
}
// Nostr + crypto used by the stack
if (
id.includes('nostr-tools') ||
id.includes('@noble') ||
id.includes('@scure')
) {
return 'vendor-nostr'
}
if (id.includes('lucide-react')) {
return 'vendor-lucide'
}
if (id.includes('i18next') || id.includes('react-i18next')) {
return 'vendor-i18n'
}
if (id.includes('@dnd-kit')) {
return 'vendor-dnd'
}
if (id.includes('highlight.js')) {
return 'vendor-highlight'
}
if (id.includes('flexsearch')) {
return 'vendor-flexsearch'
}
if (id.includes('emoji-picker-react')) {
return 'vendor-emoji'
}
if (id.includes('yet-another-react-lightbox')) {
return 'vendor-lightbox'
}
if (
id.includes('@getalby') ||
id.includes('bitcoin-connect') ||
id.includes('nstart-modal')
) {
return 'vendor-lightning'
}
if (id.includes('embla-carousel')) {
return 'vendor-embla'
}
if (id.includes('qr-code-styling') || id.includes('/qr-scanner/')) {
return 'vendor-qr'
}
if (id.includes('/cmdk/')) {
return 'vendor-cmdk'
}
if (id.includes('/vaul/')) {
return 'vendor-vaul'
}
if (id.includes('tippy.js')) {
return 'vendor-tippy'
}
if (id.includes('/zod/') || id.includes('node_modules/zod')) {
return 'vendor-zod'
}
if (id.includes('/dayjs/')) {
return 'vendor-dayjs'
}
if (id.includes('/sonner/')) {
return 'vendor-sonner'
}
if (id.includes('blossom-client-sdk')) {
return 'vendor-blossom'
}
if (id.includes('@popperjs')) {
return 'vendor-popper'
}
return 'vendor-misc'
}
},
onwarn(warning, warn) { onwarn(warning, warn) {
// Suppress vite:reporter warnings about mixed static/dynamic imports // Suppress vite:reporter warnings about mixed static/dynamic imports
// These are informational warnings about code splitting, not errors // These are informational warnings about code splitting, not errors

Loading…
Cancel
Save