From 40862eeb2c7344a045ed86d5f80cfdd351fdae39 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Tue, 31 Mar 2026 12:02:20 +0200 Subject: [PATCH] fix electron refresh fix about and readme pages --- build/icon.png | Bin 0 -> 6832 bytes electron/main.cjs | 29 +++++-- electron/preload.cjs | 5 +- package-lock.json | 17 ++++- package.json | 19 +++-- src/components/AboutInfoDialog/index.tsx | 72 ++++++++---------- .../NotificationsButton.tsx | 13 +++- .../KeyboardShortcutsHelp/index.tsx | 39 +++++----- src/components/Sidebar/NotificationButton.tsx | 14 +++- src/components/Username/index.tsx | 6 +- src/services/session-feed-snapshot.service.ts | 5 ++ src/vite-env.d.ts | 6 +- 12 files changed, 142 insertions(+), 83 deletions(-) create mode 100644 build/icon.png diff --git a/build/icon.png b/build/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a98b8819b26cf0ba47de8a08ccf3454cb7f156fe GIT binary patch literal 6832 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 literal 0 HcmV?d00001 diff --git a/electron/main.cjs b/electron/main.cjs index f779da79..b32ae8dc 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -1,11 +1,23 @@ 'use strict' -const { app, BrowserWindow, shell } = require('electron') +const { app, BrowserWindow, ipcMain, shell } = require('electron') const path = require('path') /** True when running from source (`electron .`); false when packaged. */ const isDev = !app.isPackaged +function loadRenderer(win) { + if (isDev) { + const devUrl = process.env.VITE_DEV_SERVER_URL || 'http://127.0.0.1:5173' + void win.loadURL(devUrl) + if (!win.webContents.isDevToolsOpened()) { + win.webContents.openDevTools({ mode: 'detach' }) + } + return + } + void win.loadFile(path.join(__dirname, '..', 'dist', 'index.html')) +} + function createWindow() { const win = new BrowserWindow({ width: 1280, @@ -23,13 +35,7 @@ function createWindow() { win.once('ready-to-show', () => win.show()) - if (isDev) { - const devUrl = process.env.VITE_DEV_SERVER_URL || 'http://127.0.0.1:5173' - win.loadURL(devUrl) - win.webContents.openDevTools({ mode: 'detach' }) - } else { - win.loadFile(path.join(__dirname, '..', 'dist', 'index.html')) - } + loadRenderer(win) win.webContents.setWindowOpenHandler(({ url }) => { if (url.startsWith('http:') || url.startsWith('https:')) { @@ -40,6 +46,13 @@ function createWindow() { } app.whenReady().then(() => { + ipcMain.handle('jumble:reload-app', async (event) => { + const win = BrowserWindow.fromWebContents(event.sender) + if (!win || win.isDestroyed()) return false + loadRenderer(win) + return true + }) + createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() diff --git a/electron/preload.cjs b/electron/preload.cjs index 8f9e83c7..6251fbe3 100644 --- a/electron/preload.cjs +++ b/electron/preload.cjs @@ -1,7 +1,8 @@ 'use strict' -const { contextBridge } = require('electron') +const { contextBridge, ipcRenderer } = require('electron') contextBridge.exposeInMainWorld('jumbleElectron', { - isElectron: true + isElectron: true, + reloadApp: () => ipcRenderer.invoke('jumble:reload-app') }) diff --git a/package-lock.json b/package-lock.json index 33cb4d32..7bbbd80b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jumble-imwald", - "version": "21.3.1", + "version": "21.3.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jumble-imwald", - "version": "21.3.1", + "version": "21.3.2", "license": "MIT", "dependencies": { "@asciidoctor/core": "^3.0.4", @@ -65,6 +65,7 @@ "katex": "^0.16.25", "lru-cache": "^11.0.2", "lucide-react": "^0.469.0", + "marked": "^17.0.5", "nostr-tools": "^2.17.0", "nstart-modal": "^2.0.0", "path-to-regexp": "^8.3.0", @@ -11183,6 +11184,18 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/marked": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.5.tgz", + "integrity": "sha512-6hLvc0/JEbRjRgzI6wnT2P1XuM1/RrrDEX0kPt0N7jGm1133g6X7DlxFasUIx+72aKAr904GTxhSLDrd5DIlZg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", diff --git a/package.json b/package.json index 2aa6a821..b7172e93 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jumble-imwald", - "version": "21.3.1", + "version": "21.3.2", "description": "A user-friendly Nostr client focused on relay feed browsing and relay discovery, forked from Jumble", "private": true, "type": "module", @@ -38,7 +38,6 @@ "@getalby/bitcoin-connect-react": "^3.10.0", "@getalby/lightning-tools": "^6.1.0", "@noble/hashes": "^1.6.1", - "@scure/base": "^2.0.0", "@radix-ui/react-alert-dialog": "^1.1.4", "@radix-ui/react-avatar": "^1.1.2", "@radix-ui/react-checkbox": "^1.3.3", @@ -56,6 +55,7 @@ "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.1.2", "@radix-ui/react-tabs": "^1.1.2", + "@scure/base": "^2.0.0", "@tailwindcss/typography": "^0.5.16", "@tiptap/core": "^2.12.0", "@tiptap/extension-document": "^2.12.0", @@ -69,7 +69,6 @@ "@tiptap/pm": "^2.12.0", "@tiptap/react": "^2.12.0", "@tiptap/suggestion": "^2.12.0", - "prosemirror-state": "^1.4.3", "@webbtc/webln-types": "^3.0.0", "blossom-client-sdk": "^4.1.0", "blurhash": "^2.0.5", @@ -87,9 +86,11 @@ "katex": "^0.16.25", "lru-cache": "^11.0.2", "lucide-react": "^0.469.0", + "marked": "^17.0.5", "nostr-tools": "^2.17.0", "nstart-modal": "^2.0.0", "path-to-regexp": "^8.3.0", + "prosemirror-state": "^1.4.3", "qr-code-styling": "^1.9.2", "qr-scanner": "^1.4.2", "react": "^18.3.1", @@ -113,6 +114,8 @@ "@types/react-dom": "^18.3.5", "@vitejs/plugin-react": "^4.3.4", "autoprefixer": "^10.4.20", + "concurrently": "^9.1.2", + "cross-env": "^7.0.3", "eslint": "^9.17.0", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.16", @@ -126,8 +129,6 @@ "vite": "^6.0.3", "vite-plugin-pwa": "^0.21.1", "vitest": "^4.0.8", - "concurrently": "^9.1.2", - "cross-env": "^7.0.3", "wait-on": "^8.0.1" }, "optionalDependencies": { @@ -147,9 +148,13 @@ "package.json" ], "linux": { - "target": ["AppImage", "deb"], + "target": [ + "AppImage", + "deb" + ], "category": "Network", - "maintainer": "Silberengel" + "maintainer": "Silberengel", + "icon": "build/icon.png" } }, "overrides": { diff --git a/src/components/AboutInfoDialog/index.tsx b/src/components/AboutInfoDialog/index.tsx index d786c8fc..8c84cff4 100644 --- a/src/components/AboutInfoDialog/index.tsx +++ b/src/components/AboutInfoDialog/index.tsx @@ -1,32 +1,27 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog' import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerTrigger } from '@/components/ui/drawer' -import { CODY_PUBKEY, SILBERENGEL_PUBKEY } from '@/constants' +import { Button } from '@/components/ui/button' +import { SILBERENGEL_PUBKEY } from '@/constants' import { useScreenSize } from '@/providers/ScreenSizeProvider' import { useState, useEffect } from 'react' -import Username from '../Username' import { replaceableEventService } from '@/services/client.service' import { getProfileFromEvent } from '@/lib/event-metadata' import { kinds } from 'nostr-tools' +import { toProfile } from '@/lib/link' export default function AboutInfoDialog({ children }: { children: React.ReactNode }) { const { isSmallScreen } = useScreenSize() const [open, setOpen] = useState(false) - const [codyLightning, setCodyLightning] = useState(null) const [silberengelLightning, setSilberengelLightning] = useState(null) useEffect(() => { const fetchProfiles = async () => { - const [codyProfileEvent, silberengelProfileEvent] = await Promise.all([ - replaceableEventService.fetchReplaceableEvent(CODY_PUBKEY, kinds.Metadata), - replaceableEventService.fetchReplaceableEvent(SILBERENGEL_PUBKEY, kinds.Metadata) - ]) - const codyProfile = codyProfileEvent ? getProfileFromEvent(codyProfileEvent) : undefined + const silberengelProfileEvent = await replaceableEventService.fetchReplaceableEvent( + SILBERENGEL_PUBKEY, + kinds.Metadata + ) const silberengelProfile = silberengelProfileEvent ? getProfileFromEvent(silberengelProfileEvent) : undefined - - if (codyProfile?.lightningAddress) { - setCodyLightning(codyProfile.lightningAddress) - } - + if (silberengelProfile?.lightningAddress) { setSilberengelLightning(silberengelProfile.lightningAddress) } @@ -34,26 +29,37 @@ export default function AboutInfoDialog({ children }: { children: React.ReactNod fetchProfiles() }, []) + const openSilberengelProfile = () => { + setOpen(false) + window.location.assign(toProfile(SILBERENGEL_PUBKEY)) + } + + const openGithubFork = () => { + setOpen(false) + window.open('https://github.com/Silberengel/jumble', '_blank', 'noopener,noreferrer') + } + const content = ( <>
Jumble 🌲
A user-friendly Nostr client focused on relay feed browsing and relay discovery
+
+ Version: v{import.meta.env.APP_VERSION} +
-
-
Main developer:
-
- - {codyLightning && ( -
⚡ {codyLightning}
- )} -
-
Imwald branch:
- + {silberengelLightning && (
⚡ {silberengelLightning}
)} @@ -61,24 +67,10 @@ export default function AboutInfoDialog({ children }: { children: React.ReactNod
- Source code:{' '} - - Main repo - - {' · '} - +
Source code:
+
If you like Jumble, please consider giving it a star ⭐
diff --git a/src/components/BottomNavigationBar/NotificationsButton.tsx b/src/components/BottomNavigationBar/NotificationsButton.tsx index f2023c0c..8d2c46f5 100644 --- a/src/components/BottomNavigationBar/NotificationsButton.tsx +++ b/src/components/BottomNavigationBar/NotificationsButton.tsx @@ -1,6 +1,6 @@ import { usePrimaryPage } from '@/contexts/primary-page-context' import { useNostr } from '@/providers/NostrProvider' -import { Bell } from 'lucide-react' +import { Bell, Settings } from 'lucide-react' import BottomNavigationBarItem from './BottomNavigationBarItem' export default function NotificationsButton() { @@ -8,7 +8,16 @@ export default function NotificationsButton() { const { pubkey } = useNostr() const spell = (currentPageProps as { spell?: string } | undefined)?.spell - if (!pubkey) return null + if (!pubkey) { + return ( + navigate('settings')} + > + + + ) + } return ( - createFakeEvent({ - id: '0'.repeat(64), - pubkey: '0'.repeat(64), - content: readmeMarkdown, - created_at: 0, - kind: 1, - tags: [], - sig: '0'.repeat(128) - }), - [] - ) + const readmeHtml = useMemo(() => { + // README is local project content; render it as regular markdown (not note-content parsing). + const html = marked.parse(readmeMarkdown, { + gfm: true, + breaks: true + }) + const resolved = typeof html === 'string' ? html : '' + return resolved.replace(/ - -
+
) } diff --git a/src/components/Sidebar/NotificationButton.tsx b/src/components/Sidebar/NotificationButton.tsx index 2ed17ab6..a985cc6f 100644 --- a/src/components/Sidebar/NotificationButton.tsx +++ b/src/components/Sidebar/NotificationButton.tsx @@ -1,7 +1,7 @@ import { usePrimaryPage } from '@/contexts/primary-page-context' import { usePrimaryNoteView } from '@/contexts/primary-note-view-context' import { useNostr } from '@/providers/NostrProvider' -import { Bell } from 'lucide-react' +import { Bell, Settings } from 'lucide-react' import SidebarItem from './SidebarItem' export default function NotificationButton() { @@ -10,7 +10,17 @@ export default function NotificationButton() { const { pubkey } = useNostr() const spell = (currentPageProps as { spell?: string } | undefined)?.spell - if (!pubkey) return null + if (!pubkey) { + return ( + navigate('settings')} + active={display && current === 'settings' && primaryViewType === null} + > + + + ) + } return ( void }) { const { profile, isFetching } = useFetchProfile(userId) const { navigateToProfile } = useSmartProfileNavigationOptional() @@ -50,6 +52,7 @@ export default function Username({ style={{ verticalAlign: 'baseline', ...style }} onClick={(e) => { e.stopPropagation() + onNavigate?.() navigateToProfile(toProfile(profilePubkey)) }} > @@ -72,6 +75,7 @@ export default function Username({ style={{ verticalAlign: 'baseline', ...style }} onClick={(e) => { e.stopPropagation() + onNavigate?.() navigateToProfile(toProfile(pubkey)) }} > diff --git a/src/services/session-feed-snapshot.service.ts b/src/services/session-feed-snapshot.service.ts index 4baafbfc..453b8336 100644 --- a/src/services/session-feed-snapshot.service.ts +++ b/src/services/session-feed-snapshot.service.ts @@ -1,5 +1,6 @@ import type { Event } from 'nostr-tools' import logger from '@/lib/logger' +import { isJumbleElectron } from '@/lib/client-platform' /** Max events stored per feed key (matches typical initial timeline cap). */ const MAX_EVENTS_PER_FEED = 120 @@ -46,6 +47,10 @@ export function setSessionFeedSnapshot(key: string, events: readonly Event[]): v */ export function hardReloadPreservingFeedSnapshots(): void { persistSessionFeedSnapshotsForHardRefresh() + if (isJumbleElectron() && typeof window.jumbleElectron?.reloadApp === 'function') { + void window.jumbleElectron.reloadApp() + return + } window.location.reload() } diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 8113f995..29936e35 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -10,6 +10,10 @@ declare global { interface Window { nostr?: TNip07 /** Set by {@link electron/preload.cjs} when running inside Electron. */ - jumbleElectron?: { isElectron: true } + jumbleElectron?: { + isElectron: true + /** Ask Electron main to reload index safely (avoids file:// history path reload issues). */ + reloadApp?: () => Promise + } } }