@ -1,9 +0,0 @@ |
|||||||
root = true |
|
||||||
|
|
||||||
[*] |
|
||||||
charset = utf-8 |
|
||||||
indent_style = space |
|
||||||
indent_size = 2 |
|
||||||
end_of_line = lf |
|
||||||
insert_final_newline = true |
|
||||||
trim_trailing_whitespace = true |
|
||||||
@ -1,14 +0,0 @@ |
|||||||
module.exports = { |
|
||||||
extends: [ |
|
||||||
'eslint:recommended', |
|
||||||
'plugin:react/recommended', |
|
||||||
'plugin:react/jsx-runtime', |
|
||||||
'@electron-toolkit/eslint-config-ts/recommended', |
|
||||||
'@electron-toolkit/eslint-config-prettier' |
|
||||||
], |
|
||||||
rules: { |
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off', |
|
||||||
'react/prop-types': 'off', |
|
||||||
'@typescript-eslint/no-explicit-any': 'off' |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,57 +0,0 @@ |
|||||||
name: Build/release |
|
||||||
|
|
||||||
on: |
|
||||||
push: |
|
||||||
tags: |
|
||||||
- v*.*.* |
|
||||||
|
|
||||||
permissions: |
|
||||||
contents: write |
|
||||||
|
|
||||||
jobs: |
|
||||||
release: |
|
||||||
runs-on: ${{ matrix.os }} |
|
||||||
|
|
||||||
strategy: |
|
||||||
matrix: |
|
||||||
os: [ubuntu-latest, macos-13, windows-latest] |
|
||||||
|
|
||||||
steps: |
|
||||||
- name: Check out Git repository |
|
||||||
uses: actions/checkout@v4 |
|
||||||
|
|
||||||
- name: Install Node.js |
|
||||||
uses: actions/setup-node@v4 |
|
||||||
with: |
|
||||||
node-version: 20 |
|
||||||
|
|
||||||
- name: Install Dependencies |
|
||||||
run: npm install |
|
||||||
|
|
||||||
- name: build-linux |
|
||||||
if: matrix.os == 'ubuntu-latest' |
|
||||||
run: npm run build:linux |
|
||||||
|
|
||||||
- name: build-mac |
|
||||||
if: matrix.os == 'macos-13' |
|
||||||
run: npm run build:mac |
|
||||||
|
|
||||||
- name: build-win |
|
||||||
if: matrix.os == 'windows-latest' |
|
||||||
run: npm run build:win |
|
||||||
|
|
||||||
- name: release |
|
||||||
uses: softprops/action-gh-release@v2 |
|
||||||
with: |
|
||||||
draft: true |
|
||||||
files: | |
|
||||||
dist/*.exe |
|
||||||
dist/*.zip |
|
||||||
dist/*.dmg |
|
||||||
dist/*.AppImage |
|
||||||
dist/*.snap |
|
||||||
dist/*.deb |
|
||||||
dist/*.rpm |
|
||||||
dist/*.tar.gz |
|
||||||
env: |
|
||||||
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} |
|
||||||
@ -1,5 +1,24 @@ |
|||||||
|
# Logs |
||||||
|
logs |
||||||
|
*.log |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
pnpm-debug.log* |
||||||
|
lerna-debug.log* |
||||||
|
|
||||||
node_modules |
node_modules |
||||||
dist |
dist |
||||||
out |
dist-ssr |
||||||
|
*.local |
||||||
|
|
||||||
|
# Editor directories and files |
||||||
|
.vscode/* |
||||||
|
!.vscode/extensions.json |
||||||
|
.idea |
||||||
.DS_Store |
.DS_Store |
||||||
*.log* |
*.suo |
||||||
|
*.ntvs* |
||||||
|
*.njsproj |
||||||
|
*.sln |
||||||
|
*.sw? |
||||||
|
|||||||
@ -1,3 +0,0 @@ |
|||||||
{ |
|
||||||
"recommendations": ["dbaeumer.vscode-eslint"] |
|
||||||
} |
|
||||||
@ -1,39 +0,0 @@ |
|||||||
{ |
|
||||||
"version": "0.2.0", |
|
||||||
"configurations": [ |
|
||||||
{ |
|
||||||
"name": "Debug Main Process", |
|
||||||
"type": "node", |
|
||||||
"request": "launch", |
|
||||||
"cwd": "${workspaceRoot}", |
|
||||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", |
|
||||||
"windows": { |
|
||||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" |
|
||||||
}, |
|
||||||
"runtimeArgs": ["--sourcemap"], |
|
||||||
"env": { |
|
||||||
"REMOTE_DEBUGGING_PORT": "9222" |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
"name": "Debug Renderer Process", |
|
||||||
"port": 9222, |
|
||||||
"request": "attach", |
|
||||||
"type": "chrome", |
|
||||||
"webRoot": "${workspaceFolder}/src/renderer", |
|
||||||
"timeout": 60000, |
|
||||||
"presentation": { |
|
||||||
"hidden": true |
|
||||||
} |
|
||||||
} |
|
||||||
], |
|
||||||
"compounds": [ |
|
||||||
{ |
|
||||||
"name": "Debug All", |
|
||||||
"configurations": ["Debug Main Process", "Debug Renderer Process"], |
|
||||||
"presentation": { |
|
||||||
"order": 1 |
|
||||||
} |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
{ |
|
||||||
"[typescript]": { |
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|
||||||
}, |
|
||||||
"[javascript]": { |
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|
||||||
}, |
|
||||||
"[json]": { |
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,21 +0,0 @@ |
|||||||
MIT License |
|
||||||
|
|
||||||
Copyright (c) 2024 Cody Tseng |
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||||
of this software and associated documentation files (the "Software"), to deal |
|
||||||
in the Software without restriction, including without limitation the rights |
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||||
copies of the Software, and to permit persons to whom the Software is |
|
||||||
furnished to do so, subject to the following conditions: |
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all |
|
||||||
copies or substantial portions of the Software. |
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
||||||
SOFTWARE. |
|
||||||
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 71 KiB |
@ -1,17 +1,21 @@ |
|||||||
{ |
{ |
||||||
"$schema": "https://ui.shadcn.com/schema.json", |
"$schema": "https://ui.shadcn.com/schema.json", |
||||||
"style": "default", |
"style": "new-york", |
||||||
"rsc": false, |
"rsc": false, |
||||||
"tsx": true, |
"tsx": true, |
||||||
"tailwind": { |
"tailwind": { |
||||||
"config": "tailwind.config.js", |
"config": "tailwind.config.js", |
||||||
"css": "src/renderer/src/assets/main.css", |
"css": "src/index.css", |
||||||
"baseColor": "slate", |
"baseColor": "zinc", |
||||||
"cssVariables": true, |
"cssVariables": true, |
||||||
"prefix": "" |
"prefix": "" |
||||||
}, |
}, |
||||||
"aliases": { |
"aliases": { |
||||||
"components": "@renderer/components", |
"components": "@/components", |
||||||
"utils": "@renderer/lib/utils" |
"utils": "@/lib/utils", |
||||||
} |
"ui": "@/components/ui", |
||||||
|
"lib": "@/lib", |
||||||
|
"hooks": "@/hooks" |
||||||
|
}, |
||||||
|
"iconLibrary": "lucide" |
||||||
} |
} |
||||||
|
|||||||
@ -1,34 +0,0 @@ |
|||||||
appId: com.jumble.app |
|
||||||
productName: jumble |
|
||||||
directories: |
|
||||||
buildResources: build |
|
||||||
files: |
|
||||||
- '!**/.vscode/*' |
|
||||||
- '!src/*' |
|
||||||
- '!electron.vite.config.{js,ts,mjs,cjs}' |
|
||||||
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' |
|
||||||
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}' |
|
||||||
- '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}' |
|
||||||
asarUnpack: |
|
||||||
- resources/** |
|
||||||
win: |
|
||||||
executableName: jumble |
|
||||||
nsis: |
|
||||||
artifactName: ${name}-${version}-setup.${ext} |
|
||||||
shortcutName: ${productName} |
|
||||||
uninstallDisplayName: ${productName} |
|
||||||
createDesktopShortcut: always |
|
||||||
mac: |
|
||||||
notarize: false |
|
||||||
dmg: |
|
||||||
artifactName: ${name}-${version}.${ext} |
|
||||||
linux: |
|
||||||
target: |
|
||||||
- AppImage |
|
||||||
- snap |
|
||||||
- deb |
|
||||||
maintainer: codytseng |
|
||||||
category: Utility |
|
||||||
appImage: |
|
||||||
artifactName: ${name}-${version}.${ext} |
|
||||||
npmRebuild: false |
|
||||||
@ -1,21 +0,0 @@ |
|||||||
import { resolve } from 'path' |
|
||||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite' |
|
||||||
import react from '@vitejs/plugin-react' |
|
||||||
|
|
||||||
export default defineConfig({ |
|
||||||
main: { |
|
||||||
plugins: [externalizeDepsPlugin()] |
|
||||||
}, |
|
||||||
preload: { |
|
||||||
plugins: [externalizeDepsPlugin()] |
|
||||||
}, |
|
||||||
renderer: { |
|
||||||
resolve: { |
|
||||||
alias: { |
|
||||||
'@renderer': resolve('src/renderer/src'), |
|
||||||
'@common': resolve('src/common') |
|
||||||
} |
|
||||||
}, |
|
||||||
plugins: [react()] |
|
||||||
} |
|
||||||
}) |
|
||||||
@ -0,0 +1,30 @@ |
|||||||
|
import js from '@eslint/js' |
||||||
|
import globals from 'globals' |
||||||
|
import reactHooks from 'eslint-plugin-react-hooks' |
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh' |
||||||
|
import tseslint from 'typescript-eslint' |
||||||
|
|
||||||
|
export default tseslint.config( |
||||||
|
{ ignores: ['dist'] }, |
||||||
|
{ |
||||||
|
extends: [js.configs.recommended, ...tseslint.configs.recommended], |
||||||
|
files: ['**/*.{ts,tsx}'], |
||||||
|
languageOptions: { |
||||||
|
ecmaVersion: 2020, |
||||||
|
globals: globals.browser |
||||||
|
}, |
||||||
|
plugins: { |
||||||
|
'react-hooks': reactHooks, |
||||||
|
'react-refresh': reactRefresh |
||||||
|
}, |
||||||
|
rules: { |
||||||
|
...reactHooks.configs.recommended.rules, |
||||||
|
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], |
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off', |
||||||
|
'react/prop-types': 'off', |
||||||
|
'@typescript-eslint/no-explicit-any': 'off', |
||||||
|
'react-refresh/only-export-components': 'off', |
||||||
|
'react-hooks/exhaustive-deps': 'off' |
||||||
|
} |
||||||
|
} |
||||||
|
) |
||||||
@ -1,23 +1,34 @@ |
|||||||
<!doctype html> |
<!doctype html> |
||||||
<html> |
<html lang="en"> |
||||||
<head> |
<head> |
||||||
<meta charset="UTF-8" /> |
<meta charset="UTF-8" /> |
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
<link |
||||||
<link rel="icon" href="/src/assets/favicon-light.svg" media="(prefers-color-scheme: light)" type="image/svg+xml" /> |
rel="icon" |
||||||
<link rel="icon" href="/src/assets/favicon-dark.svg" media="(prefers-color-scheme: dark)" type="image/svg+xml" /> |
href="/favicon-light.svg" |
||||||
|
media="(prefers-color-scheme: light)" |
||||||
|
type="image/svg+xml" |
||||||
|
/> |
||||||
|
<link |
||||||
|
rel="icon" |
||||||
|
href="/favicon-dark.svg" |
||||||
|
media="(prefers-color-scheme: dark)" |
||||||
|
type="image/svg+xml" |
||||||
|
/> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
|
||||||
<meta property="og:url" content="https://jumble.social" /> |
<meta property="og:url" content="https://jumble.social" /> |
||||||
<meta property="og:type" content="website" /> |
<meta property="og:type" content="website" /> |
||||||
<meta property="og:title" content="Jumble" /> |
<meta property="og:title" content="Jumble" /> |
||||||
<meta property="og:description" content="A beautiful nostr client focused on browsing relay feeds" /> |
<meta |
||||||
|
property="og:description" |
||||||
|
content="A beautiful nostr client focused on browsing relay feeds" |
||||||
|
/> |
||||||
<meta |
<meta |
||||||
property="og:image" |
property="og:image" |
||||||
content="https://github.com/CodyTseng/jumble/blob/master/resources/og-image.png?raw=true" |
content="https://github.com/CodyTseng/jumble/blob/master/resources/og-image.png?raw=true" |
||||||
/> |
/> |
||||||
|
<title>Jumble</title> |
||||||
</head> |
</head> |
||||||
|
|
||||||
<title>Jumble</title> |
|
||||||
|
|
||||||
<body> |
<body> |
||||||
<div id="root"></div> |
<div id="root"></div> |
||||||
<script type="module" src="/src/main.tsx"></script> |
<script type="module" src="/src/main.tsx"></script> |
||||||
@ -1,3 +1,6 @@ |
|||||||
module.exports = { |
export default { |
||||||
plugins: [require('tailwindcss'), require('autoprefixer')] |
plugins: { |
||||||
|
tailwindcss: {}, |
||||||
|
autoprefixer: {} |
||||||
|
} |
||||||
} |
} |
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 23 KiB |
@ -1,8 +1,8 @@ |
|||||||
import 'yet-another-react-lightbox/styles.css' |
import 'yet-another-react-lightbox/styles.css' |
||||||
import './assets/main.css' |
import './index.css' |
||||||
|
|
||||||
import { Toaster } from '@renderer/components/ui/toaster' |
import { Toaster } from '@/components/ui/toaster' |
||||||
import { ThemeProvider } from '@renderer/providers/ThemeProvider' |
import { ThemeProvider } from '@/providers/ThemeProvider' |
||||||
import { PageManager } from './PageManager' |
import { PageManager } from './PageManager' |
||||||
import NoteListPage from './pages/primary/NoteListPage' |
import NoteListPage from './pages/primary/NoteListPage' |
||||||
import { FollowListProvider } from './providers/FollowListProvider' |
import { FollowListProvider } from './providers/FollowListProvider' |
||||||
@ -1,59 +0,0 @@ |
|||||||
import { ElectronAPI } from '@electron-toolkit/preload' |
|
||||||
import { Event } from 'nostr-tools' |
|
||||||
|
|
||||||
export type TRelayGroup = { |
|
||||||
groupName: string |
|
||||||
relayUrls: string[] |
|
||||||
isActive: boolean |
|
||||||
} |
|
||||||
|
|
||||||
export type TConfig = { |
|
||||||
relayGroups: TRelayGroup[] |
|
||||||
theme: TThemeSetting |
|
||||||
} |
|
||||||
|
|
||||||
export type TThemeSetting = 'light' | 'dark' | 'system' |
|
||||||
export type TTheme = 'light' | 'dark' |
|
||||||
|
|
||||||
export type TDraftEvent = Pick<Event, 'content' | 'created_at' | 'kind' | 'tags'> |
|
||||||
|
|
||||||
export interface ISigner { |
|
||||||
getPublicKey: () => Promise<string | null> |
|
||||||
signEvent: (draftEvent: TDraftEvent) => Promise<Event | null> |
|
||||||
} |
|
||||||
|
|
||||||
export type TElectronWindow = { |
|
||||||
electron: ElectronAPI |
|
||||||
api: { |
|
||||||
system: { |
|
||||||
isEncryptionAvailable: () => Promise<boolean> |
|
||||||
getSelectedStorageBackend: () => Promise<string> |
|
||||||
} |
|
||||||
theme: { |
|
||||||
addChangeListener: (listener: (theme: TTheme) => void) => void |
|
||||||
removeChangeListener: () => void |
|
||||||
current: () => Promise<TTheme> |
|
||||||
} |
|
||||||
storage: { |
|
||||||
getItem: (key: string) => Promise<string> |
|
||||||
setItem: (key: string, value: string) => Promise<void> |
|
||||||
removeItem: (key: string) => Promise<void> |
|
||||||
} |
|
||||||
nostr: { |
|
||||||
login: (nsec: string) => Promise<{ |
|
||||||
pubkey?: string |
|
||||||
reason?: string |
|
||||||
}> |
|
||||||
logout: () => Promise<void> |
|
||||||
} |
|
||||||
} |
|
||||||
nostr: ISigner |
|
||||||
} |
|
||||||
|
|
||||||
export type TAccount = { |
|
||||||
pubkey: string |
|
||||||
signerType: 'nsec' | 'browser-nsec' | 'nip-07' | 'bunker' |
|
||||||
nsec?: string |
|
||||||
bunker?: string |
|
||||||
bunkerClientSecretKey?: string |
|
||||||
} |
|
||||||
@ -1,5 +1,5 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { useNostr } from '@renderer/providers/NostrProvider' |
import { useNostr } from '@/providers/NostrProvider' |
||||||
import { LogIn } from 'lucide-react' |
import { LogIn } from 'lucide-react' |
||||||
|
|
||||||
export default function LoginButton({ |
export default function LoginButton({ |
||||||
@ -1,4 +1,4 @@ |
|||||||
import { useNostr } from '@renderer/providers/NostrProvider' |
import { useNostr } from '@/providers/NostrProvider' |
||||||
import LoginButton from './LoginButton' |
import LoginButton from './LoginButton' |
||||||
import ProfileButton from './ProfileButton' |
import ProfileButton from './ProfileButton' |
||||||
|
|
||||||
@ -1,5 +1,5 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { useSecondaryPage } from '@renderer/PageManager' |
import { useSecondaryPage } from '@/PageManager' |
||||||
import { ChevronLeft } from 'lucide-react' |
import { ChevronLeft } from 'lucide-react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
|
|
||||||
@ -1,5 +1,5 @@ |
|||||||
import { isNsfwEvent } from '@renderer/lib/event' |
import { isNsfwEvent } from '@/lib/event' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { Event } from 'nostr-tools' |
import { Event } from 'nostr-tools' |
||||||
import { memo } from 'react' |
import { memo } from 'react' |
||||||
import { |
import { |
||||||
@ -1,5 +1,5 @@ |
|||||||
import { toNoteList } from '@renderer/lib/link' |
import { toNoteList } from '@/lib/link' |
||||||
import { SecondaryPageLink } from '@renderer/PageManager' |
import { SecondaryPageLink } from '@/PageManager' |
||||||
import { TEmbeddedRenderer } from './types' |
import { TEmbeddedRenderer } from './types' |
||||||
|
|
||||||
export function EmbeddedHashtag({ hashtag }: { hashtag: string }) { |
export function EmbeddedHashtag({ hashtag }: { hashtag: string }) { |
||||||
@ -1,6 +1,6 @@ |
|||||||
import { useFetchEvent } from '@renderer/hooks' |
import { useFetchEvent } from '@/hooks' |
||||||
import { toNoStrudelArticle, toNoStrudelNote, toNoStrudelStream } from '@renderer/lib/link' |
import { toNoStrudelArticle, toNoStrudelNote, toNoStrudelStream } from '@/lib/link' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { kinds } from 'nostr-tools' |
import { kinds } from 'nostr-tools' |
||||||
import ShortTextNoteCard from '../NoteCard/ShortTextNoteCard' |
import ShortTextNoteCard from '../NoteCard/ShortTextNoteCard' |
||||||
|
|
||||||
@ -1,5 +1,5 @@ |
|||||||
import { useSecondaryPage } from '@renderer/PageManager' |
import { useSecondaryPage } from '@/PageManager' |
||||||
import { toNoteList } from '@renderer/lib/link' |
import { toNoteList } from '@/lib/link' |
||||||
import { TEmbeddedRenderer } from './types' |
import { TEmbeddedRenderer } from './types' |
||||||
|
|
||||||
export function EmbeddedWebsocketUrl({ url }: { url: string }) { |
export function EmbeddedWebsocketUrl({ url }: { url: string }) { |
||||||
@ -1,7 +1,7 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { useToast } from '@renderer/hooks' |
import { useToast } from '@/hooks' |
||||||
import { useFollowList } from '@renderer/providers/FollowListProvider' |
import { useFollowList } from '@/providers/FollowListProvider' |
||||||
import { useNostr } from '@renderer/providers/NostrProvider' |
import { useNostr } from '@/providers/NostrProvider' |
||||||
import { Loader } from 'lucide-react' |
import { Loader } from 'lucide-react' |
||||||
import { useMemo, useState } from 'react' |
import { useMemo, useState } from 'react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
@ -1,6 +1,6 @@ |
|||||||
import { Image } from '@nextui-org/image' |
import { Image } from '@nextui-org/image' |
||||||
import { ScrollArea, ScrollBar } from '@renderer/components/ui/scroll-area' |
import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { useState } from 'react' |
import { useState } from 'react' |
||||||
import Lightbox from 'yet-another-react-lightbox' |
import Lightbox from 'yet-another-react-lightbox' |
||||||
import Zoom from 'yet-another-react-lightbox/plugins/zoom' |
import Zoom from 'yet-another-react-lightbox/plugins/zoom' |
||||||
@ -1,6 +1,6 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { Input } from '@renderer/components/ui/input' |
import { Input } from '@/components/ui/input' |
||||||
import { useNostr } from '@renderer/providers/NostrProvider' |
import { useNostr } from '@/providers/NostrProvider' |
||||||
import { Loader } from 'lucide-react' |
import { Loader } from 'lucide-react' |
||||||
import { useState } from 'react' |
import { useState } from 'react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
@ -1,4 +1,4 @@ |
|||||||
import { useFetchNip05 } from '@renderer/hooks/useFetchNip05' |
import { useFetchNip05 } from '@/hooks/useFetchNip05' |
||||||
import { BadgeAlert, BadgeCheck } from 'lucide-react' |
import { BadgeAlert, BadgeCheck } from 'lucide-react' |
||||||
|
|
||||||
export default function Nip05({ nip05, pubkey }: { nip05?: string; pubkey: string }) { |
export default function Nip05({ nip05, pubkey }: { nip05?: string; pubkey: string }) { |
||||||
@ -1,5 +1,5 @@ |
|||||||
import { useSecondaryPage } from '@renderer/PageManager' |
import { useSecondaryPage } from '@/PageManager' |
||||||
import { toNote } from '@renderer/lib/link' |
import { toNote } from '@/lib/link' |
||||||
import { Event } from 'nostr-tools' |
import { Event } from 'nostr-tools' |
||||||
import Content from '../Content' |
import Content from '../Content' |
||||||
import { FormattedTimestamp } from '../FormattedTimestamp' |
import { FormattedTimestamp } from '../FormattedTimestamp' |
||||||
@ -1,4 +1,4 @@ |
|||||||
import client from '@renderer/services/client.service' |
import client from '@/services/client.service' |
||||||
import { Event, kinds, verifyEvent } from 'nostr-tools' |
import { Event, kinds, verifyEvent } from 'nostr-tools' |
||||||
import { useMemo } from 'react' |
import { useMemo } from 'react' |
||||||
import ShortTextNoteCard from './ShortTextNoteCard' |
import ShortTextNoteCard from './ShortTextNoteCard' |
||||||
@ -1,8 +1,8 @@ |
|||||||
import { useFetchEvent } from '@renderer/hooks' |
import { useFetchEvent } from '@/hooks' |
||||||
import { getParentEventId, getRootEventId } from '@renderer/lib/event' |
import { getParentEventId, getRootEventId } from '@/lib/event' |
||||||
import { toNote } from '@renderer/lib/link' |
import { toNote } from '@/lib/link' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { useSecondaryPage } from '@renderer/PageManager' |
import { useSecondaryPage } from '@/PageManager' |
||||||
import { Repeat2 } from 'lucide-react' |
import { Repeat2 } from 'lucide-react' |
||||||
import { Event } from 'nostr-tools' |
import { Event } from 'nostr-tools' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
@ -1,5 +1,4 @@ |
|||||||
import { Event } from 'nostr-tools' |
import { Event, kinds } from 'nostr-tools' |
||||||
import { kinds } from 'nostr-tools' |
|
||||||
import RepostNoteCard from './RepostNoteCard' |
import RepostNoteCard from './RepostNoteCard' |
||||||
import ShortTextNoteCard from './ShortTextNoteCard' |
import ShortTextNoteCard from './ShortTextNoteCard' |
||||||
|
|
||||||
@ -1,5 +1,5 @@ |
|||||||
import { useNostr } from '@renderer/providers/NostrProvider' |
import { useNostr } from '@/providers/NostrProvider' |
||||||
import { useNoteStats } from '@renderer/providers/NoteStatsProvider' |
import { useNoteStats } from '@/providers/NoteStatsProvider' |
||||||
import { MessageCircle } from 'lucide-react' |
import { MessageCircle } from 'lucide-react' |
||||||
import { Event } from 'nostr-tools' |
import { Event } from 'nostr-tools' |
||||||
import { useMemo, useState } from 'react' |
import { useMemo, useState } from 'react' |
||||||
@ -1,4 +1,4 @@ |
|||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { Event } from 'nostr-tools' |
import { Event } from 'nostr-tools' |
||||||
import LikeButton from './LikeButton' |
import LikeButton from './LikeButton' |
||||||
import NoteOptions from './NoteOptions' |
import NoteOptions from './NoteOptions' |
||||||
@ -1,6 +1,6 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { toNotifications } from '@renderer/lib/link' |
import { toNotifications } from '@/lib/link' |
||||||
import { useSecondaryPage } from '@renderer/PageManager' |
import { useSecondaryPage } from '@/PageManager' |
||||||
import { Bell } from 'lucide-react' |
import { Bell } from 'lucide-react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
|
|
||||||
@ -1,4 +1,4 @@ |
|||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { useState } from 'react' |
import { useState } from 'react' |
||||||
|
|
||||||
export default function NsfwOverlay({ className }: { className?: string }) { |
export default function NsfwOverlay({ className }: { className?: string }) { |
||||||
@ -1,7 +1,7 @@ |
|||||||
|
import { cn } from '@/lib/utils' |
||||||
import { Event } from 'nostr-tools' |
import { Event } from 'nostr-tools' |
||||||
import UserAvatar from '../UserAvatar' |
|
||||||
import { cn } from '@renderer/lib/utils' |
|
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
|
import UserAvatar from '../UserAvatar' |
||||||
|
|
||||||
export default function ParentNotePreview({ |
export default function ParentNotePreview({ |
||||||
event, |
event, |
||||||
@ -1,5 +1,5 @@ |
|||||||
import PostDialog from '@renderer/components/PostDialog' |
import PostDialog from '@/components/PostDialog' |
||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { PencilLine } from 'lucide-react' |
import { PencilLine } from 'lucide-react' |
||||||
import { useState } from 'react' |
import { useState } from 'react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
@ -1,4 +1,4 @@ |
|||||||
import { Card } from '@renderer/components/ui/card' |
import { Card } from '@/components/ui/card' |
||||||
import dayjs from 'dayjs' |
import dayjs from 'dayjs' |
||||||
import Content from '../Content' |
import Content from '../Content' |
||||||
|
|
||||||
@ -1,17 +1,17 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { |
import { |
||||||
Dialog, |
Dialog, |
||||||
DialogContent, |
DialogContent, |
||||||
DialogDescription, |
DialogDescription, |
||||||
DialogHeader, |
DialogHeader, |
||||||
DialogTitle |
DialogTitle |
||||||
} from '@renderer/components/ui/dialog' |
} from '@/components/ui/dialog' |
||||||
import { ScrollArea } from '@renderer/components/ui/scroll-area' |
import { ScrollArea } from '@/components/ui/scroll-area' |
||||||
import { Textarea } from '@renderer/components/ui/textarea' |
import { Textarea } from '@/components/ui/textarea' |
||||||
import { useToast } from '@renderer/hooks/use-toast' |
import { useToast } from '@/hooks/use-toast' |
||||||
import { createShortTextNoteDraftEvent } from '@renderer/lib/draft-event' |
import { createShortTextNoteDraftEvent } from '@/lib/draft-event' |
||||||
import { useNostr } from '@renderer/providers/NostrProvider' |
import { useNostr } from '@/providers/NostrProvider' |
||||||
import client from '@renderer/services/client.service' |
import client from '@/services/client.service' |
||||||
import { LoaderCircle } from 'lucide-react' |
import { LoaderCircle } from 'lucide-react' |
||||||
import { Event } from 'nostr-tools' |
import { Event } from 'nostr-tools' |
||||||
import { Dispatch, useState } from 'react' |
import { Dispatch, useState } from 'react' |
||||||
@ -1,6 +1,6 @@ |
|||||||
import { Image } from '@nextui-org/image' |
import { Image } from '@nextui-org/image' |
||||||
import { generateImageByPubkey } from '@renderer/lib/pubkey' |
import { generateImageByPubkey } from '@/lib/pubkey' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { useEffect, useMemo, useState } from 'react' |
import { useEffect, useMemo, useState } from 'react' |
||||||
|
|
||||||
export default function ProfileBanner({ |
export default function ProfileBanner({ |
||||||
@ -1,6 +1,6 @@ |
|||||||
import { Avatar, AvatarFallback, AvatarImage } from '@renderer/components/ui/avatar' |
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' |
||||||
import { useFetchProfile } from '@renderer/hooks' |
import { useFetchProfile } from '@/hooks' |
||||||
import { generateImageByPubkey } from '@renderer/lib/pubkey' |
import { generateImageByPubkey } from '@/lib/pubkey' |
||||||
import { useMemo } from 'react' |
import { useMemo } from 'react' |
||||||
import FollowButton from '../FollowButton' |
import FollowButton from '../FollowButton' |
||||||
import Nip05 from '../Nip05' |
import Nip05 from '../Nip05' |
||||||
@ -1,5 +1,5 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { usePrimaryPage } from '@renderer/PageManager' |
import { usePrimaryPage } from '@/PageManager' |
||||||
import { RefreshCcw } from 'lucide-react' |
import { RefreshCcw } from 'lucide-react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
|
|
||||||
@ -1,12 +1,12 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { |
import { |
||||||
DropdownMenu, |
DropdownMenu, |
||||||
DropdownMenuContent, |
DropdownMenuContent, |
||||||
DropdownMenuItem, |
DropdownMenuItem, |
||||||
DropdownMenuTrigger |
DropdownMenuTrigger |
||||||
} from '@renderer/components/ui/dropdown-menu' |
} from '@/components/ui/dropdown-menu' |
||||||
import { Input } from '@renderer/components/ui/input' |
import { Input } from '@/components/ui/input' |
||||||
import { useRelaySettings } from '@renderer/providers/RelaySettingsProvider' |
import { useRelaySettings } from '@/providers/RelaySettingsProvider' |
||||||
import { Check, ChevronDown, Circle, CircleCheck, EllipsisVertical } from 'lucide-react' |
import { Check, ChevronDown, Circle, CircleCheck, EllipsisVertical } from 'lucide-react' |
||||||
import { useState } from 'react' |
import { useState } from 'react' |
||||||
import RelayUrls from './RelayUrl' |
import RelayUrls from './RelayUrl' |
||||||
@ -1,7 +1,7 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { useFetchRelayInfos } from '@renderer/hooks' |
import { useFetchRelayInfos } from '@/hooks' |
||||||
import { useRelaySettings } from '@renderer/providers/RelaySettingsProvider' |
import { useRelaySettings } from '@/providers/RelaySettingsProvider' |
||||||
import client from '@renderer/services/client.service' |
import client from '@/services/client.service' |
||||||
import { Save, SearchCheck } from 'lucide-react' |
import { Save, SearchCheck } from 'lucide-react' |
||||||
import { useEffect, useState } from 'react' |
import { useEffect, useState } from 'react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
@ -1,7 +1,7 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { Input } from '@renderer/components/ui/input' |
import { Input } from '@/components/ui/input' |
||||||
import { Separator } from '@renderer/components/ui/separator' |
import { Separator } from '@/components/ui/separator' |
||||||
import { useRelaySettings } from '@renderer/providers/RelaySettingsProvider' |
import { useRelaySettings } from '@/providers/RelaySettingsProvider' |
||||||
import { useEffect, useRef, useState } from 'react' |
import { useEffect, useRef, useState } from 'react' |
||||||
import { RelaySettingsComponentProvider } from './provider' |
import { RelaySettingsComponentProvider } from './provider' |
||||||
import RelayGroup from './RelayGroup' |
import RelayGroup from './RelayGroup' |
||||||
@ -1,10 +1,10 @@ |
|||||||
import RelaySettings from '@renderer/components/RelaySettings' |
import RelaySettings from '@/components/RelaySettings' |
||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { Popover, PopoverContent, PopoverTrigger } from '@renderer/components/ui/popover' |
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' |
||||||
import { ScrollArea } from '@renderer/components/ui/scroll-area' |
import { ScrollArea } from '@/components/ui/scroll-area' |
||||||
import { toRelaySettings } from '@renderer/lib/link' |
import { toRelaySettings } from '@/lib/link' |
||||||
import { SecondaryPageLink } from '@renderer/PageManager' |
import { SecondaryPageLink } from '@/PageManager' |
||||||
import { useScreenSize } from '@renderer/providers/ScreenSizeProvider' |
import { useScreenSize } from '@/providers/ScreenSizeProvider' |
||||||
import { Server } from 'lucide-react' |
import { Server } from 'lucide-react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
|
|
||||||
@ -1,5 +1,5 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { ChevronUp } from 'lucide-react' |
import { ChevronUp } from 'lucide-react' |
||||||
|
|
||||||
export default function ScrollToTopButton({ |
export default function ScrollToTopButton({ |
||||||
@ -1,4 +1,4 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { Search } from 'lucide-react' |
import { Search } from 'lucide-react' |
||||||
import { useState } from 'react' |
import { useState } from 'react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
@ -1,5 +1,5 @@ |
|||||||
import { Button } from '@renderer/components/ui/button' |
import { Button } from '@/components/ui/button' |
||||||
import { useTheme } from '@renderer/providers/ThemeProvider' |
import { useTheme } from '@/providers/ThemeProvider' |
||||||
import { Moon, Sun, SunMoon } from 'lucide-react' |
import { Moon, Sun, SunMoon } from 'lucide-react' |
||||||
import { useTranslation } from 'react-i18next' |
import { useTranslation } from 'react-i18next' |
||||||
|
|
||||||
@ -0,0 +1,23 @@ |
|||||||
|
import { cn } from '@/lib/utils' |
||||||
|
|
||||||
|
export function Titlebar({ |
||||||
|
children, |
||||||
|
className, |
||||||
|
visible = true |
||||||
|
}: { |
||||||
|
children?: React.ReactNode |
||||||
|
className?: string |
||||||
|
visible?: boolean |
||||||
|
}) { |
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={cn( |
||||||
|
'absolute top-0 w-full h-9 max-sm:h-11 z-50 bg-background/80 backdrop-blur-md flex items-center font-semibold gap-1 px-2 duration-700 transition-transform', |
||||||
|
visible ? '' : '-translate-y-full', |
||||||
|
className |
||||||
|
)} |
||||||
|
> |
||||||
|
{children} |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
@ -1,11 +1,11 @@ |
|||||||
import { Avatar, AvatarFallback, AvatarImage } from '@renderer/components/ui/avatar' |
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' |
||||||
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@renderer/components/ui/hover-card' |
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card' |
||||||
import { Skeleton } from '@renderer/components/ui/skeleton' |
import { Skeleton } from '@/components/ui/skeleton' |
||||||
import { useFetchProfile } from '@renderer/hooks' |
import { useFetchProfile } from '@/hooks' |
||||||
import { generateImageByPubkey } from '@renderer/lib/pubkey' |
import { generateImageByPubkey } from '@/lib/pubkey' |
||||||
import { toProfile } from '@renderer/lib/link' |
import { toProfile } from '@/lib/link' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { SecondaryPageLink } from '@renderer/PageManager' |
import { SecondaryPageLink } from '@/PageManager' |
||||||
import ProfileCard from '../ProfileCard' |
import ProfileCard from '../ProfileCard' |
||||||
import { useMemo } from 'react' |
import { useMemo } from 'react' |
||||||
|
|
||||||
@ -1,8 +1,8 @@ |
|||||||
import FollowButton from '@renderer/components/FollowButton' |
import FollowButton from '@/components/FollowButton' |
||||||
import Nip05 from '@renderer/components/Nip05' |
import Nip05 from '@/components/Nip05' |
||||||
import UserAvatar from '@renderer/components/UserAvatar' |
import UserAvatar from '@/components/UserAvatar' |
||||||
import Username from '@renderer/components/Username' |
import Username from '@/components/Username' |
||||||
import { useFetchProfile } from '@renderer/hooks' |
import { useFetchProfile } from '@/hooks' |
||||||
|
|
||||||
export default function UserItem({ pubkey }: { pubkey: string }) { |
export default function UserItem({ pubkey }: { pubkey: string }) { |
||||||
const { profile } = useFetchProfile(pubkey) |
const { profile } = useFetchProfile(pubkey) |
||||||
@ -1,9 +1,9 @@ |
|||||||
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@renderer/components/ui/hover-card' |
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card' |
||||||
import { Skeleton } from '@renderer/components/ui/skeleton' |
import { Skeleton } from '@/components/ui/skeleton' |
||||||
import { useFetchProfile } from '@renderer/hooks' |
import { useFetchProfile } from '@/hooks' |
||||||
import { toProfile } from '@renderer/lib/link' |
import { toProfile } from '@/lib/link' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { SecondaryPageLink } from '@renderer/PageManager' |
import { SecondaryPageLink } from '@/PageManager' |
||||||
import ProfileCard from '../ProfileCard' |
import ProfileCard from '../ProfileCard' |
||||||
|
|
||||||
export default function Username({ |
export default function Username({ |
||||||
@ -1,4 +1,4 @@ |
|||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import NsfwOverlay from '../NsfwOverlay' |
import NsfwOverlay from '../NsfwOverlay' |
||||||
|
|
||||||
export default function VideoPlayer({ |
export default function VideoPlayer({ |
||||||
@ -1,6 +1,6 @@ |
|||||||
import { Image } from '@nextui-org/image' |
import { Image } from '@nextui-org/image' |
||||||
import { useFetchWebMetadata } from '@renderer/hooks/useFetchWebMetadata' |
import { useFetchWebMetadata } from '@/hooks/useFetchWebMetadata' |
||||||
import { cn } from '@renderer/lib/utils' |
import { cn } from '@/lib/utils' |
||||||
import { useMemo } from 'react' |
import { useMemo } from 'react' |
||||||
|
|
||||||
export default function WebPreview({ |
export default function WebPreview({ |
||||||