fix: resolve all linting and type errors

- Remove unused React import from nostrUriResolver
- Add block scoping to switch case statements
- Add react-hooks plugin to eslint config
- Fix exhaustive-deps warnings in components
- Fix DecodeResult type to use ReturnType<typeof decode>
- Update dependency arrays to include all used values
- Add eslint-disable comment for intentional dependency omission

All linting warnings resolved. TypeScript type checking passes.
This commit is contained in:
Gigi
2025-10-11 03:23:38 +01:00
parent 3a8203d26e
commit a0e30aa197
6 changed files with 23 additions and 17 deletions

View File

@@ -59,7 +59,8 @@
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"react-refresh"
"react-refresh",
"react-hooks"
],
"rules": {
"react-refresh/only-export-components": [
@@ -68,6 +69,7 @@
"allowConstantExport": true
}
],
"react-hooks/exhaustive-deps": "warn",
"@typescript-eslint/no-unused-vars": [
"error",
{

View File

@@ -139,7 +139,8 @@ const AddBookmarkModal: React.FC<AddBookmarkModalProps> = ({ onClose, onSave })
clearTimeout(fetchTimeoutRef.current)
}
}
}, [url]) // Only depend on url
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url]) // Only depend on url - title, description, tagsInput are intentionally checked but not dependencies
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()

View File

@@ -52,7 +52,7 @@ export const RelayStatusIndicator: React.FC<RelayStatusIndicatorProps> = ({ rela
hasRemoteRelay,
isConnecting
})
}, [offlineMode, localOnlyMode, connectedUrls.length, relayStatuses.length, hasLocalRelay, hasRemoteRelay, isConnecting])
}, [offlineMode, localOnlyMode, connectedUrls, relayStatuses.length, hasLocalRelay, hasRemoteRelay, isConnecting])
// Don't show indicator when fully connected (but show when connecting)
if (!localOnlyMode && !offlineMode && !isConnecting) return null

View File

@@ -113,22 +113,24 @@ const ThreePaneLayout: React.FC<ThreePaneLayoutProps> = (props) => {
// Handle ESC key to close sidebar or highlights
useEffect(() => {
const { isSidebarOpen, isHighlightsCollapsed, onToggleSidebar, onToggleHighlightsPanel } = props
if (!isMobile) return
if (!props.isSidebarOpen && props.isHighlightsCollapsed) return
if (!isSidebarOpen && isHighlightsCollapsed) return
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
if (props.isSidebarOpen) {
props.onToggleSidebar()
} else if (!props.isHighlightsCollapsed) {
props.onToggleHighlightsPanel()
if (isSidebarOpen) {
onToggleSidebar()
} else if (!isHighlightsCollapsed) {
onToggleHighlightsPanel()
}
}
}
document.addEventListener('keydown', handleEscape)
return () => document.removeEventListener('keydown', handleEscape)
}, [isMobile, props.isSidebarOpen, props.isHighlightsCollapsed, props.onToggleSidebar, props.onToggleHighlightsPanel])
}, [isMobile, props])
// Trap focus in sidebar when open on mobile
useEffect(() => {

View File

@@ -110,7 +110,7 @@ export const useBookmarksData = ({
handleFetchHighlights()
}
handleFetchContacts()
}, [relayPool, activeAccount?.pubkey, naddr, handleFetchBookmarks, handleFetchHighlights, handleFetchContacts])
}, [relayPool, activeAccount, naddr, handleFetchBookmarks, handleFetchHighlights, handleFetchContacts])
return {
bookmarks,

View File

@@ -1,6 +1,4 @@
import React from 'react'
import { decode, npubEncode, noteEncode } from 'nostr-tools/nip19'
import { DecodeResult } from 'nostr-tools/nip19'
/**
* Regular expression to match nostr: URIs and bare NIP-19 identifiers
@@ -75,15 +73,17 @@ export function getNostrUriLabel(encoded: string): string {
switch (decoded.type) {
case 'npub':
return `@${encoded.slice(0, 12)}...`
case 'nprofile':
case 'nprofile': {
const npub = npubEncode(decoded.data.pubkey)
return `@${npub.slice(0, 12)}...`
}
case 'note':
return `note:${encoded.slice(5, 12)}...`
case 'nevent':
case 'nevent': {
const note = noteEncode(decoded.data.id)
return `note:${note.slice(5, 12)}...`
case 'naddr':
}
case 'naddr': {
// For articles, show the identifier if available
const identifier = decoded.data.identifier
if (identifier && identifier.length > 0) {
@@ -91,6 +91,7 @@ export function getNostrUriLabel(encoded: string): string {
return identifier.length > 40 ? `${identifier.slice(0, 37)}...` : identifier
}
return 'nostr article'
}
default:
return encoded.slice(0, 16) + '...'
}
@@ -166,11 +167,11 @@ export function replaceNostrUrisInHTML(html: string): string {
*/
export function getNostrUriInfo(encoded: string): {
type: string
decoded: DecodeResult | null
decoded: ReturnType<typeof decode> | null
link: string
label: string
} {
let decoded: DecodeResult | null = null
let decoded: ReturnType<typeof decode> | null = null
try {
decoded = decode(encoded)
} catch (error) {