mirror of
https://github.com/DocNR/POWR.git
synced 2025-06-03 15:52:06 +00:00
basic relay managment system working
This commit is contained in:
parent
07fada6d07
commit
4cd62cf775
@ -1,6 +1,6 @@
|
||||
// app/(tabs)/library/programs.tsx
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { View, ScrollView, TextInput, ActivityIndicator, Platform, TouchableOpacity } from 'react-native';
|
||||
import { View, ScrollView, TextInput, ActivityIndicator, Platform, Alert, TouchableOpacity } from 'react-native';
|
||||
import { Text } from '@/components/ui/text';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
@ -17,6 +17,7 @@ import { FilterSheet, type FilterOptions, type SourceType } from '@/components/l
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { NostrEventKind } from '@/types/nostr';
|
||||
import { useNDKStore } from '@/lib/stores/ndk';
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
|
||||
// Define relay status
|
||||
enum RelayStatus {
|
||||
@ -150,34 +151,84 @@ export default function ProgramsScreen() {
|
||||
|
||||
const resetDatabase = async () => {
|
||||
try {
|
||||
await db.withTransactionAsync(async () => {
|
||||
// Drop all tables
|
||||
const tables = await db.getAllAsync<{ name: string }>(
|
||||
setTestResults(null);
|
||||
|
||||
// Clear stored keys first
|
||||
try {
|
||||
await SecureStore.deleteItemAsync('nostr_privkey');
|
||||
console.log('[Database Reset] Cleared stored Nostr keys');
|
||||
} catch (keyError) {
|
||||
console.warn('[Database Reset] Error clearing keys:', keyError);
|
||||
}
|
||||
|
||||
// Define explicit type for tables
|
||||
let tables: { name: string }[] = [];
|
||||
|
||||
// Try to get existing tables
|
||||
try {
|
||||
tables = await db.getAllAsync<{ name: string }>(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
|
||||
);
|
||||
|
||||
for (const { name } of tables) {
|
||||
await db.execAsync(`DROP TABLE IF EXISTS ${name}`);
|
||||
console.log(`[Database Reset] Found ${tables.length} tables to drop`);
|
||||
} catch (tableListError) {
|
||||
console.warn('[Database Reset] Error listing tables:', tableListError);
|
||||
// Initialize with empty array if query fails
|
||||
tables = [];
|
||||
}
|
||||
|
||||
// Drop tables one by one
|
||||
for (const table of tables) {
|
||||
try {
|
||||
await db.execAsync(`DROP TABLE IF EXISTS "${table.name}";`);
|
||||
console.log(`[Database Reset] Dropped table: ${table.name}`);
|
||||
} catch (dropError) {
|
||||
console.error(`[Database Reset] Error dropping table ${table.name}:`, dropError);
|
||||
}
|
||||
|
||||
// Recreate schema
|
||||
await schema.createTables(db);
|
||||
});
|
||||
}
|
||||
|
||||
// Use a delay to allow any pending operations to complete
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// Create a completely new database instance instead of using the existing one
|
||||
// This will bypass the "Access to closed resource" issue
|
||||
Alert.alert(
|
||||
'Database Tables Dropped',
|
||||
'All database tables have been dropped. The app needs to be restarted to complete the reset process.',
|
||||
[
|
||||
{
|
||||
text: 'Restart Now',
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
// In a production app, you would use something like RN's DevSettings.reload()
|
||||
// For Expo, we'll suggest manual restart
|
||||
Alert.alert(
|
||||
'Manual Restart Required',
|
||||
'Please completely close the app and reopen it to finish the database reset.',
|
||||
[{ text: 'OK', style: 'default' }]
|
||||
);
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
setTestResults({
|
||||
success: true,
|
||||
message: 'Database reset successfully'
|
||||
message: 'Database tables dropped. Please restart the app to complete the reset.'
|
||||
});
|
||||
|
||||
// Refresh database status
|
||||
checkDatabase();
|
||||
inspectDatabase();
|
||||
} catch (error) {
|
||||
console.error('Error resetting database:', error);
|
||||
console.error('[Database Reset] Error resetting database:', error);
|
||||
setTestResults({
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : 'Unknown error during reset'
|
||||
message: error instanceof Error ? error.message : 'Unknown error during database reset'
|
||||
});
|
||||
|
||||
// Still recommend a restart since the database might be in an inconsistent state
|
||||
Alert.alert(
|
||||
'Database Reset Error',
|
||||
'There was an error during database reset. Please restart the app and try again.',
|
||||
[{ text: 'OK', style: 'default' }]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,217 +1,92 @@
|
||||
// components/RelayManagement.tsx
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { View, Text, FlatList, TextInput, ActivityIndicator, Alert, TouchableOpacity, Modal, ScrollView } from 'react-native';
|
||||
import { Switch } from 'react-native-gesture-handler'; // Or your UI library's Switch component
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Text, FlatList, TouchableOpacity, Modal, ActivityIndicator } from 'react-native';
|
||||
import { useRelayStore } from '@/lib/stores/relayStore';
|
||||
import { useNDKStore } from '@/lib/stores/ndk';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { X } from 'lucide-react-native';
|
||||
import { RelayWithStatus } from '@/lib/db/services/RelayService';
|
||||
|
||||
interface Props {
|
||||
// Define proper interface for component props
|
||||
interface RelayManagementProps {
|
||||
isVisible: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function RelayManagement({ isVisible, onClose }: Props) {
|
||||
// Get relay state and actions from the store
|
||||
// Simple RelayManagement component
|
||||
export default function RelayManagement({ isVisible, onClose }: RelayManagementProps) {
|
||||
const relays = useRelayStore(state => state.relays);
|
||||
const isLoading = useRelayStore(state => state.isLoading);
|
||||
const isRefreshing = useRelayStore(state => state.isRefreshing);
|
||||
const isSaving = useRelayStore(state => state.isSaving);
|
||||
const loadRelays = useRelayStore(state => state.loadRelays);
|
||||
const addRelay = useRelayStore(state => state.addRelay);
|
||||
const removeRelay = useRelayStore(state => state.removeRelay);
|
||||
const updateRelay = useRelayStore(state => state.updateRelay);
|
||||
const applyChanges = useRelayStore(state => state.applyChanges);
|
||||
const resetToDefaults = useRelayStore(state => state.resetToDefaults);
|
||||
|
||||
// Get current user for import/export functions
|
||||
const { ndk, currentUser } = useNDKStore();
|
||||
|
||||
// Local state
|
||||
const [newRelayUrl, setNewRelayUrl] = useState('');
|
||||
const [isAddingRelay, setIsAddingRelay] = useState(false);
|
||||
|
||||
// Load relays when component mounts or becomes visible
|
||||
useEffect(() => {
|
||||
if (isVisible) {
|
||||
console.log('[RelayManagement] Component became visible, loading relays');
|
||||
loadRelays();
|
||||
}
|
||||
}, [isVisible, loadRelays]);
|
||||
|
||||
// Debug logging
|
||||
useEffect(() => {
|
||||
if (isVisible) {
|
||||
console.log('[RelayManagement] Component state:', {
|
||||
relaysCount: relays.length,
|
||||
isLoading,
|
||||
isRefreshing,
|
||||
isAddingRelay
|
||||
});
|
||||
|
||||
// Log the first relay for inspection
|
||||
if (relays.length > 0) {
|
||||
console.log('[RelayManagement] First relay:', relays[0]);
|
||||
} else {
|
||||
console.log('[RelayManagement] No relays loaded');
|
||||
}
|
||||
}
|
||||
}, [isVisible, relays, isLoading, isRefreshing, isAddingRelay]);
|
||||
}, [isVisible]);
|
||||
|
||||
// Function to add a new relay
|
||||
const handleAddRelay = async () => {
|
||||
if (!newRelayUrl || !newRelayUrl.startsWith('wss://')) {
|
||||
Alert.alert('Invalid Relay URL', 'Relay URL must start with wss://');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await addRelay(newRelayUrl);
|
||||
setNewRelayUrl('');
|
||||
setIsAddingRelay(false);
|
||||
} catch (error) {
|
||||
Alert.alert('Error', error instanceof Error ? error.message : 'Failed to add relay');
|
||||
}
|
||||
};
|
||||
|
||||
// Function to handle relay removal with confirmation
|
||||
const handleRemoveRelay = (url: string) => {
|
||||
Alert.alert(
|
||||
'Remove Relay',
|
||||
`Are you sure you want to remove ${url}?`,
|
||||
[
|
||||
{ text: 'Cancel', style: 'cancel' },
|
||||
{
|
||||
text: 'Remove',
|
||||
style: 'destructive',
|
||||
onPress: async () => {
|
||||
try {
|
||||
await removeRelay(url);
|
||||
} catch (error) {
|
||||
Alert.alert('Error', 'Failed to remove relay');
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
// Function to toggle read/write permission
|
||||
const handleTogglePermission = (url: string, permission: 'read' | 'write') => {
|
||||
const relay = relays.find(r => r.url === url);
|
||||
if (relay) {
|
||||
console.log(`[RelayManagement] Toggling ${permission} for relay ${url}`);
|
||||
updateRelay(url, { [permission]: !relay[permission] });
|
||||
}
|
||||
};
|
||||
|
||||
// Function to apply changes
|
||||
const handleApplyChanges = async () => {
|
||||
try {
|
||||
console.log('[RelayManagement] Applying changes...');
|
||||
const success = await applyChanges();
|
||||
if (success) {
|
||||
Alert.alert('Success', 'Relay configuration applied successfully!');
|
||||
}
|
||||
} catch (error) {
|
||||
Alert.alert('Error', 'Failed to apply relay configuration');
|
||||
}
|
||||
};
|
||||
|
||||
// Function to reset to defaults with confirmation
|
||||
const handleResetToDefaults = () => {
|
||||
Alert.alert(
|
||||
'Reset to Defaults',
|
||||
'Are you sure you want to reset all relays to the default configuration?',
|
||||
[
|
||||
{ text: 'Cancel', style: 'cancel' },
|
||||
{
|
||||
text: 'Reset',
|
||||
style: 'destructive',
|
||||
onPress: async () => {
|
||||
try {
|
||||
await resetToDefaults();
|
||||
Alert.alert('Success', 'Relays reset to defaults');
|
||||
} catch (error) {
|
||||
Alert.alert('Error', 'Failed to reset relays');
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
// Function to get color based on relay status
|
||||
const getStatusColor = (status: string) => {
|
||||
// Status indicator color with proper typing
|
||||
const getStatusColor = (status: string): string => {
|
||||
switch (status) {
|
||||
case 'connected': return '#10b981'; // Green
|
||||
case 'connecting': return '#f59e0b'; // Amber
|
||||
case 'error': return '#ef4444'; // Red
|
||||
case 'error':
|
||||
case 'disconnected': return '#ef4444'; // Red
|
||||
default: return '#6b7280'; // Gray
|
||||
}
|
||||
};
|
||||
|
||||
// Render a relay item
|
||||
const renderRelayItem = ({ item }: { item: RelayWithStatus }) => {
|
||||
console.log(`[RelayManagement] Rendering relay: ${item.url}, status: ${item.status}`);
|
||||
return (
|
||||
<View style={{ padding: 16, borderBottomWidth: 1, borderBottomColor: '#e5e7eb' }}>
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', flex: 1 }}>
|
||||
<View
|
||||
style={{
|
||||
width: 12,
|
||||
height: 12,
|
||||
borderRadius: 6,
|
||||
backgroundColor: getStatusColor(item.status),
|
||||
marginRight: 8
|
||||
}}
|
||||
/>
|
||||
<Text numberOfLines={1} style={{ flex: 1 }}>{item.url}</Text>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => handleRemoveRelay(item.url)}
|
||||
style={{ padding: 8 }}
|
||||
>
|
||||
<Text style={{ color: '#ef4444' }}>Remove</Text>
|
||||
</TouchableOpacity>
|
||||
// Render a relay item with proper typing
|
||||
const renderRelayItem = ({ item }: { item: RelayWithStatus }) => (
|
||||
<View style={{
|
||||
padding: 12,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: '#e5e7eb',
|
||||
backgroundColor: 'white',
|
||||
}}>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', flex: 1 }}>
|
||||
<View style={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
backgroundColor: getStatusColor(item.status),
|
||||
marginRight: 8
|
||||
}} />
|
||||
<Text style={{ flex: 1 }}>{item.url}</Text>
|
||||
</View>
|
||||
|
||||
<View style={{ flexDirection: 'row', marginTop: 12, justifyContent: 'space-around' }}>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Text style={{ marginRight: 8 }}>Read</Text>
|
||||
<Switch
|
||||
value={item.read}
|
||||
onValueChange={() => handleTogglePermission(item.url, 'read')}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Text style={{ marginRight: 8 }}>Write</Text>
|
||||
<Switch
|
||||
value={item.write}
|
||||
onValueChange={() => handleTogglePermission(item.url, 'write')}
|
||||
/>
|
||||
</View>
|
||||
<Text style={{ fontSize: 12, color: '#6b7280' }}>
|
||||
{item.status}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-around',
|
||||
marginTop: 8,
|
||||
paddingTop: 8,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: '#f3f4f6'
|
||||
}}>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Text style={{ marginRight: 8 }}>Read</Text>
|
||||
<Switch
|
||||
checked={item.read}
|
||||
onCheckedChange={() => updateRelay(item.url, { read: !item.read })}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Text style={{ marginRight: 8 }}>Write</Text>
|
||||
<Switch
|
||||
checked={item.write}
|
||||
onCheckedChange={() => updateRelay(item.url, { write: !item.write })}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
// Reset component state
|
||||
const resetComponent = () => {
|
||||
setIsAddingRelay(false);
|
||||
setNewRelayUrl('');
|
||||
loadRelays();
|
||||
};
|
||||
|
||||
// Error handler
|
||||
const handleError = (error: any) => {
|
||||
console.error('[RelayManagement] Error:', error);
|
||||
Alert.alert('Error', error instanceof Error ? error.message : 'An unknown error occurred');
|
||||
resetComponent();
|
||||
};
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@ -220,148 +95,60 @@ export default function RelayManagement({ isVisible, onClose }: Props) {
|
||||
transparent={true}
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
<View style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'center', alignItems: 'center' }}>
|
||||
<View style={{ width: '90%', maxHeight: '80%', backgroundColor: '#fff', borderRadius: 12 }}>
|
||||
{/* Header */}
|
||||
<View style={{ padding: 16, borderBottomWidth: 1, borderBottomColor: '#e5e7eb', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<View style={{
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
justifyContent: 'flex-end',
|
||||
}}>
|
||||
<View style={{
|
||||
backgroundColor: 'white',
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
paddingBottom: 20,
|
||||
maxHeight: '80%',
|
||||
}}>
|
||||
<View style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: 16,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: '#e5e7eb',
|
||||
}}>
|
||||
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>Manage Relays</Text>
|
||||
<TouchableOpacity onPress={onClose}>
|
||||
<Text>Close</Text>
|
||||
<X size={24} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Content */}
|
||||
<View style={{ flex: 1 }}>
|
||||
{isLoading ? (
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 }}>
|
||||
<ActivityIndicator size="large" />
|
||||
<Text style={{ marginTop: 16 }}>Loading relays...</Text>
|
||||
</View>
|
||||
) : (
|
||||
<>
|
||||
{/* Relay list */}
|
||||
{relays.length === 0 ? (
|
||||
<View style={{ padding: 20, alignItems: 'center' }}>
|
||||
<Text style={{ marginBottom: 16 }}>No relays configured</Text>
|
||||
<TouchableOpacity
|
||||
onPress={handleResetToDefaults}
|
||||
style={{ padding: 10, backgroundColor: '#e5e7eb', borderRadius: 8 }}
|
||||
>
|
||||
<Text>Reset to Defaults</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
) : (
|
||||
<FlatList
|
||||
data={relays}
|
||||
keyExtractor={(item) => item.url}
|
||||
renderItem={renderRelayItem}
|
||||
ListEmptyComponent={
|
||||
<View style={{ padding: 20, alignItems: 'center' }}>
|
||||
<Text>No relays found. Try resetting to defaults.</Text>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{isLoading ? (
|
||||
<View style={{ padding: 20, alignItems: 'center' }}>
|
||||
<ActivityIndicator size="large" />
|
||||
<Text style={{ marginTop: 10 }}>Loading relays...</Text>
|
||||
</View>
|
||||
) : (
|
||||
<>
|
||||
<FlatList
|
||||
data={relays}
|
||||
keyExtractor={(item) => item.url}
|
||||
renderItem={renderRelayItem}
|
||||
style={{ maxHeight: '70%' }}
|
||||
/>
|
||||
|
||||
<View style={{ padding: 16 }}>
|
||||
<Button onPress={loadRelays} style={{ marginBottom: 8 }}>
|
||||
<Text style={{ color: 'white' }}>Refresh Relays</Text>
|
||||
</Button>
|
||||
|
||||
{/* Add relay section */}
|
||||
{isAddingRelay ? (
|
||||
<View style={{ padding: 16, borderTopWidth: 1, borderTopColor: '#e5e7eb' }}>
|
||||
<Text style={{ marginBottom: 8 }}>Add New Relay</Text>
|
||||
<TextInput
|
||||
style={{
|
||||
borderWidth: 1,
|
||||
borderColor: '#e5e7eb',
|
||||
borderRadius: 8,
|
||||
padding: 10,
|
||||
marginBottom: 12
|
||||
}}
|
||||
placeholder="wss://relay.example.com"
|
||||
value={newRelayUrl}
|
||||
onChangeText={setNewRelayUrl}
|
||||
autoCapitalize="none"
|
||||
/>
|
||||
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
||||
<TouchableOpacity
|
||||
onPress={() => setIsAddingRelay(false)}
|
||||
style={{
|
||||
padding: 10,
|
||||
backgroundColor: '#e5e7eb',
|
||||
borderRadius: 8,
|
||||
flex: 1,
|
||||
marginRight: 8,
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Text>Cancel</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={handleAddRelay}
|
||||
style={{
|
||||
padding: 10,
|
||||
backgroundColor: '#3b82f6',
|
||||
borderRadius: 8,
|
||||
flex: 1,
|
||||
alignItems: 'center'
|
||||
}}
|
||||
disabled={!newRelayUrl.startsWith('wss://')}
|
||||
>
|
||||
<Text style={{ color: '#fff' }}>Add Relay</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View style={{ padding: 16, borderTopWidth: 1, borderTopColor: '#e5e7eb' }}>
|
||||
<TouchableOpacity
|
||||
onPress={() => setIsAddingRelay(true)}
|
||||
style={{
|
||||
padding: 10,
|
||||
backgroundColor: '#e5e7eb',
|
||||
borderRadius: 8,
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Text>Add New Relay</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Footer */}
|
||||
<View style={{ padding: 16, borderTopWidth: 1, borderTopColor: '#e5e7eb' }}>
|
||||
<TouchableOpacity
|
||||
onPress={handleApplyChanges}
|
||||
style={{
|
||||
padding: 14,
|
||||
backgroundColor: '#3b82f6',
|
||||
borderRadius: 8,
|
||||
alignItems: 'center'
|
||||
}}
|
||||
disabled={isSaving}
|
||||
>
|
||||
{isSaving ? (
|
||||
<ActivityIndicator size="small" color="#fff" />
|
||||
) : (
|
||||
<Text style={{ color: '#fff', fontWeight: '500' }}>Apply Changes</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={handleResetToDefaults}
|
||||
style={{
|
||||
padding: 14,
|
||||
backgroundColor: 'transparent',
|
||||
borderRadius: 8,
|
||||
alignItems: 'center',
|
||||
marginTop: 8
|
||||
}}
|
||||
>
|
||||
<Text>Reset to Defaults</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Button
|
||||
variant="outline"
|
||||
onPress={onClose}
|
||||
>
|
||||
<Text>Close</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
|
@ -40,11 +40,23 @@ export interface RelayWithStatus extends RelayConfig {
|
||||
export class RelayService {
|
||||
private db: SQLiteDatabase;
|
||||
private ndk: NDKCommon | null = null;
|
||||
private debug: boolean = false;
|
||||
|
||||
constructor(db: SQLiteDatabase) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
enableDebug() {
|
||||
this.debug = true;
|
||||
console.log('[RelayService] Debug mode enabled');
|
||||
}
|
||||
|
||||
private logDebug(message: string, ...args: any[]) {
|
||||
if (this.debug) {
|
||||
console.log(`[RelayService Debug] ${message}`, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set NDK instance for relay operations
|
||||
*/
|
||||
@ -84,24 +96,21 @@ export class RelayService {
|
||||
|
||||
if (!this.ndk) {
|
||||
console.warn('[RelayService] NDK not initialized, returning relays with disconnected status');
|
||||
// Return relays with disconnected status if NDK not initialized
|
||||
return relays.map(relay => ({
|
||||
...relay,
|
||||
status: 'disconnected'
|
||||
}));
|
||||
}
|
||||
|
||||
// Log the relays in the NDK pool for debugging
|
||||
console.log('[RelayService] Checking status for relays. Current NDK pool:');
|
||||
this.ndk.pool.relays.forEach((ndkRelay, url) => {
|
||||
console.log(` - ${url}: status=${ndkRelay.status}`);
|
||||
});
|
||||
|
||||
return relays.map(relay => {
|
||||
let status: 'connected' | 'connecting' | 'disconnected' | 'error' = 'disconnected';
|
||||
|
||||
try {
|
||||
const ndkRelay = this.ndk?.pool.getRelay(relay.url);
|
||||
if (ndkRelay) {
|
||||
status = this.getRelayStatus(ndkRelay);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[RelayService] Error getting status for relay ${relay.url}:`, error);
|
||||
}
|
||||
const status = this.getRelayStatus(relay);
|
||||
console.log(`[RelayService] Status for relay ${relay.url}: ${status}`);
|
||||
|
||||
return {
|
||||
...relay,
|
||||
@ -114,13 +123,18 @@ export class RelayService {
|
||||
}
|
||||
}
|
||||
|
||||
private normalizeRelayUrl(url: string): string {
|
||||
// Remove trailing slash if present
|
||||
return url.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new relay to the database
|
||||
*/
|
||||
async addRelay(url: string, read = true, write = true, priority?: number): Promise<boolean> {
|
||||
try {
|
||||
// Normalize the URL
|
||||
url = url.trim();
|
||||
url = this.normalizeRelayUrl(url.trim());
|
||||
|
||||
// Validate URL format
|
||||
if (!url.startsWith('wss://')) {
|
||||
@ -408,6 +422,24 @@ export class RelayService {
|
||||
|
||||
console.log(`[RelayService] Found relay list in event created at ${new Date(latestCreatedAt * 1000).toISOString()}`);
|
||||
|
||||
// Safely log event details without circular references
|
||||
try {
|
||||
console.log('[RelayService] Event ID:', latestEvent.id);
|
||||
console.log('[RelayService] Event Kind:', latestEvent.kind);
|
||||
console.log('[RelayService] Event Created At:', latestEvent.created_at);
|
||||
console.log('[RelayService] Event Tags Count:', latestEvent.tags ? latestEvent.tags.length : 0);
|
||||
|
||||
// Safely log the tags
|
||||
if (latestEvent.tags && Array.isArray(latestEvent.tags)) {
|
||||
console.log('[RelayService] Tags:');
|
||||
latestEvent.tags.forEach((tag: any[], index: number) => {
|
||||
console.log(` Tag ${index}:`, JSON.stringify(tag));
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('[RelayService] Error logging event details:', error);
|
||||
}
|
||||
|
||||
// Get highest current priority
|
||||
const highestPriority = await this.db.getFirstAsync<{ priority: number }>(
|
||||
'SELECT MAX(priority) as priority FROM relays'
|
||||
@ -417,52 +449,295 @@ export class RelayService {
|
||||
let importCount = 0;
|
||||
let updatedCount = 0;
|
||||
|
||||
// Check if any relay tags exist
|
||||
let relayTagsFound = false;
|
||||
|
||||
// Process each relay in the event
|
||||
for (const tag of latestEvent.tags) {
|
||||
if (tag[0] === 'r') {
|
||||
const url = tag[1];
|
||||
|
||||
// Check for read/write specification in the tag
|
||||
let read = true;
|
||||
let write = true;
|
||||
|
||||
if (tag.length > 2) {
|
||||
read = tag[2] !== 'write'; // If "write", then not read
|
||||
write = tag[2] !== 'read'; // If "read", then not write
|
||||
}
|
||||
|
||||
if (latestEvent.tags && Array.isArray(latestEvent.tags)) {
|
||||
for (const tag of latestEvent.tags) {
|
||||
try {
|
||||
// Check if the relay already exists
|
||||
const existingRelay = await this.db.getFirstAsync<{ url: string }>(
|
||||
'SELECT url FROM relays WHERE url = ?',
|
||||
[url]
|
||||
);
|
||||
console.log(`[RelayService] Processing tag: ${JSON.stringify(tag)}`);
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
if (existingRelay) {
|
||||
// Update existing relay
|
||||
await this.db.runAsync(
|
||||
'UPDATE relays SET read = ?, write = ?, updated_at = ? WHERE url = ?',
|
||||
[read ? 1 : 0, write ? 1 : 0, now, url]
|
||||
);
|
||||
updatedCount++;
|
||||
} else {
|
||||
// Add new relay with incremented priority
|
||||
maxPriority++;
|
||||
await this.db.runAsync(
|
||||
'INSERT INTO relays (url, read, write, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[url, read ? 1 : 0, write ? 1 : 0, maxPriority, now, now]
|
||||
);
|
||||
importCount++;
|
||||
// More flexible tag detection - handle 'r', 'R', or 'relay' tag types
|
||||
if ((tag[0] === 'r' || tag[0] === 'R' || tag[0] === 'relay') && tag.length > 1 && tag[1]) {
|
||||
relayTagsFound = true;
|
||||
console.log(`[RelayService] Found relay tag: ${tag[1]}`);
|
||||
|
||||
const url = tag[1];
|
||||
|
||||
// Ensure URL is properly formatted
|
||||
if (!url.startsWith('wss://') && !url.startsWith('ws://')) {
|
||||
console.log(`[RelayService] Skipping invalid relay URL: ${url}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for read/write specification in the tag
|
||||
let read = true;
|
||||
let write = true;
|
||||
|
||||
if (tag.length > 2) {
|
||||
// Handle various common formatting patterns
|
||||
const readWriteSpec = tag[2]?.toLowerCase();
|
||||
if (readWriteSpec === 'write') {
|
||||
read = false;
|
||||
write = true;
|
||||
console.log(`[RelayService] Relay ${url} configured as write-only`);
|
||||
} else if (readWriteSpec === 'read') {
|
||||
read = true;
|
||||
write = false;
|
||||
console.log(`[RelayService] Relay ${url} configured as read-only`);
|
||||
} else {
|
||||
console.log(`[RelayService] Unrecognized read/write spec: ${readWriteSpec}, using default (read+write)`);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if the relay already exists
|
||||
const existingRelay = await this.db.getFirstAsync<{ url: string }>(
|
||||
'SELECT url FROM relays WHERE url = ?',
|
||||
[url]
|
||||
);
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
if (existingRelay) {
|
||||
// Update existing relay
|
||||
await this.db.runAsync(
|
||||
'UPDATE relays SET read = ?, write = ?, updated_at = ? WHERE url = ?',
|
||||
[read ? 1 : 0, write ? 1 : 0, now, url]
|
||||
);
|
||||
updatedCount++;
|
||||
console.log(`[RelayService] Updated existing relay: ${url} (read=${read}, write=${write})`);
|
||||
} else {
|
||||
// Add new relay with incremented priority
|
||||
maxPriority++;
|
||||
await this.db.runAsync(
|
||||
'INSERT INTO relays (url, read, write, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[url, read ? 1 : 0, write ? 1 : 0, maxPriority, now, now]
|
||||
);
|
||||
importCount++;
|
||||
console.log(`[RelayService] Added new relay: ${url} (read=${read}, write=${write}, priority=${maxPriority})`);
|
||||
}
|
||||
} catch (innerError) {
|
||||
console.error(`[RelayService] Error importing relay ${url}:`, innerError);
|
||||
// Continue with other relays
|
||||
}
|
||||
}
|
||||
} catch (innerError) {
|
||||
console.error(`[RelayService] Error importing relay ${url}:`, innerError);
|
||||
// Continue with other relays
|
||||
} catch (tagError) {
|
||||
console.log('[RelayService] Error processing tag:', tagError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for relays in content (some clients store them there)
|
||||
if (!relayTagsFound) {
|
||||
console.log('[RelayService] No relay tags found in event tags, checking content...');
|
||||
|
||||
try {
|
||||
// Only try to parse the content if it's a string
|
||||
if (typeof latestEvent.content === 'string') {
|
||||
const contentObj = JSON.parse(latestEvent.content);
|
||||
|
||||
// Only log specific properties to avoid circular references
|
||||
console.log('[RelayService] Content has relays property:', contentObj.hasOwnProperty('relays'));
|
||||
|
||||
// Some clients store relays in content as an object
|
||||
if (contentObj.relays && typeof contentObj.relays === 'object') {
|
||||
console.log('[RelayService] Found relay URLs in content:', Object.keys(contentObj.relays));
|
||||
|
||||
// Process relays from content object
|
||||
for (const [url, permissions] of Object.entries(contentObj.relays)) {
|
||||
try {
|
||||
if (typeof url === 'string' && (url.startsWith('wss://') || url.startsWith('ws://'))) {
|
||||
relayTagsFound = true;
|
||||
|
||||
let read = true;
|
||||
let write = true;
|
||||
|
||||
// Handle different formats of permissions
|
||||
if (typeof permissions === 'object' && permissions !== null) {
|
||||
// Format: { "wss://relay.example.com": { "read": true, "write": false } }
|
||||
if ('read' in permissions) read = Boolean((permissions as any).read);
|
||||
if ('write' in permissions) write = Boolean((permissions as any).write);
|
||||
} else if (typeof permissions === 'string') {
|
||||
// Format: { "wss://relay.example.com": "read" }
|
||||
read = (permissions as string).includes('read');
|
||||
write = (permissions as string).includes('write');
|
||||
}
|
||||
|
||||
console.log(`[RelayService] Found relay in content: ${url} (read=${read}, write=${write})`);
|
||||
|
||||
// Then add or update the relay just like above...
|
||||
try {
|
||||
const existingRelay = await this.db.getFirstAsync<{ url: string }>(
|
||||
'SELECT url FROM relays WHERE url = ?',
|
||||
[url]
|
||||
);
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
if (existingRelay) {
|
||||
await this.db.runAsync(
|
||||
'UPDATE relays SET read = ?, write = ?, updated_at = ? WHERE url = ?',
|
||||
[read ? 1 : 0, write ? 1 : 0, now, url]
|
||||
);
|
||||
updatedCount++;
|
||||
console.log(`[RelayService] Updated existing relay from content: ${url} (read=${read}, write=${write})`);
|
||||
} else {
|
||||
maxPriority++;
|
||||
await this.db.runAsync(
|
||||
'INSERT INTO relays (url, read, write, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[url, read ? 1 : 0, write ? 1 : 0, maxPriority, now, now]
|
||||
);
|
||||
importCount++;
|
||||
console.log(`[RelayService] Added new relay from content: ${url} (read=${read}, write=${write}, priority=${maxPriority})`);
|
||||
}
|
||||
} catch (innerError) {
|
||||
console.error(`[RelayService] Error importing relay ${url} from content:`, innerError);
|
||||
}
|
||||
}
|
||||
} catch (relayError) {
|
||||
console.log('[RelayService] Error processing relay from content:', relayError);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('[RelayService] Content is not a string:', typeof latestEvent.content);
|
||||
}
|
||||
} catch (e) {
|
||||
// Convert the unknown error to a string safely
|
||||
const errorMessage = e instanceof Error ? e.message : String(e);
|
||||
console.log('[RelayService] Content is not JSON or does not contain relay information:', errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the raw event string that might be available
|
||||
if (!relayTagsFound && latestEvent.rawEvent && typeof latestEvent.rawEvent === 'string') {
|
||||
console.log('[RelayService] Checking raw event string for relay information');
|
||||
try {
|
||||
const rawEventObj = JSON.parse(latestEvent.rawEvent);
|
||||
if (rawEventObj.tags && Array.isArray(rawEventObj.tags)) {
|
||||
console.log(`[RelayService] Raw event has ${rawEventObj.tags.length} tags`);
|
||||
|
||||
for (const tag of rawEventObj.tags) {
|
||||
try {
|
||||
if ((tag[0] === 'r' || tag[0] === 'R') && tag.length > 1 && tag[1]) {
|
||||
relayTagsFound = true;
|
||||
const url = tag[1];
|
||||
|
||||
console.log(`[RelayService] Found relay in raw event: ${url}`);
|
||||
|
||||
// Process like above...
|
||||
if (url.startsWith('wss://') || url.startsWith('ws://')) {
|
||||
let read = true;
|
||||
let write = true;
|
||||
|
||||
if (tag.length > 2) {
|
||||
const readWriteSpec = tag[2]?.toLowerCase();
|
||||
if (readWriteSpec === 'write') {
|
||||
read = false;
|
||||
write = true;
|
||||
} else if (readWriteSpec === 'read') {
|
||||
read = true;
|
||||
write = false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const existingRelay = await this.db.getFirstAsync<{ url: string }>(
|
||||
'SELECT url FROM relays WHERE url = ?',
|
||||
[url]
|
||||
);
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
if (existingRelay) {
|
||||
await this.db.runAsync(
|
||||
'UPDATE relays SET read = ?, write = ?, updated_at = ? WHERE url = ?',
|
||||
[read ? 1 : 0, write ? 1 : 0, now, url]
|
||||
);
|
||||
updatedCount++;
|
||||
} else {
|
||||
maxPriority++;
|
||||
await this.db.runAsync(
|
||||
'INSERT INTO relays (url, read, write, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[url, read ? 1 : 0, write ? 1 : 0, maxPriority, now, now]
|
||||
);
|
||||
importCount++;
|
||||
}
|
||||
} catch (innerError) {
|
||||
console.error(`[RelayService] Error importing relay ${url} from raw event:`, innerError);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (tagError) {
|
||||
console.log('[RelayService] Error processing tag from raw event:', tagError);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (rawError) {
|
||||
// Convert the unknown error to a string safely
|
||||
const errorMessage = rawError instanceof Error ? rawError.message : String(rawError);
|
||||
console.log('[RelayService] Error parsing raw event:', errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to access user cached relays
|
||||
if (!relayTagsFound && ndk && ndk.pool && ndk.pool.relays) {
|
||||
console.log('[RelayService] Checking for relays in the user NDK pool');
|
||||
|
||||
try {
|
||||
// Try to access the user's connected relays
|
||||
const userRelays = Array.from(ndk.pool.relays.keys());
|
||||
if (userRelays.length > 0) {
|
||||
console.log(`[RelayService] Found ${userRelays.length} relays in user's NDK pool:`, userRelays);
|
||||
|
||||
// Import these relays
|
||||
for (const url of userRelays) {
|
||||
if (typeof url === 'string' && (url.startsWith('wss://') || url.startsWith('ws://'))) {
|
||||
try {
|
||||
const existingRelay = await this.db.getFirstAsync<{ url: string }>(
|
||||
'SELECT url FROM relays WHERE url = ?',
|
||||
[url]
|
||||
);
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
if (existingRelay) {
|
||||
// We'll only update the timestamp, not the permissions
|
||||
await this.db.runAsync(
|
||||
'UPDATE relays SET updated_at = ? WHERE url = ?',
|
||||
[now, url]
|
||||
);
|
||||
updatedCount++;
|
||||
console.log(`[RelayService] Updated existing relay from NDK pool: ${url}`);
|
||||
} else {
|
||||
maxPriority++;
|
||||
await this.db.runAsync(
|
||||
'INSERT INTO relays (url, read, write, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[url, 1, 1, maxPriority, now, now]
|
||||
);
|
||||
importCount++;
|
||||
console.log(`[RelayService] Added new relay from NDK pool: ${url}`);
|
||||
}
|
||||
} catch (innerError) {
|
||||
console.error(`[RelayService] Error importing relay ${url} from NDK pool:`, innerError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set flag to true because we found relays
|
||||
relayTagsFound = userRelays.length > 0;
|
||||
}
|
||||
} catch (poolError) {
|
||||
console.log('[RelayService] Error accessing NDK pool relays:', poolError);
|
||||
}
|
||||
}
|
||||
|
||||
if (!relayTagsFound) {
|
||||
console.log('[RelayService] No relay information found in any format');
|
||||
}
|
||||
|
||||
console.log(`[RelayService] Imported ${importCount} new relays, updated ${updatedCount} existing relays`);
|
||||
return importCount > 0 || updatedCount > 0;
|
||||
} catch (error) {
|
||||
@ -483,19 +758,25 @@ export class RelayService {
|
||||
|
||||
// Add default relays
|
||||
const now = Date.now();
|
||||
let addedCount = 0;
|
||||
|
||||
for (let i = 0; i < DEFAULT_RELAYS.length; i++) {
|
||||
const url = DEFAULT_RELAYS[i];
|
||||
const priority = DEFAULT_RELAYS.length - i; // Higher priority for first relays
|
||||
|
||||
await this.db.runAsync(
|
||||
'INSERT INTO relays (url, read, write, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[url, 1, 1, priority, now, now]
|
||||
);
|
||||
try {
|
||||
await this.db.runAsync(
|
||||
'INSERT INTO relays (url, read, write, priority, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[url, 1, 1, priority, now, now]
|
||||
);
|
||||
addedCount++;
|
||||
} catch (innerError) {
|
||||
console.error(`[RelayService] Error adding default relay ${url}:`, innerError);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[RelayService] Successfully reset to ${DEFAULT_RELAYS.length} default relays`);
|
||||
return true;
|
||||
console.log(`[RelayService] Successfully reset to ${addedCount} default relays`);
|
||||
return addedCount > 0;
|
||||
} catch (error) {
|
||||
console.error('[RelayService] Error resetting relays to defaults:', error);
|
||||
throw error;
|
||||
@ -603,22 +884,42 @@ export class RelayService {
|
||||
* Helper to convert NDK relay status to our status format
|
||||
*/
|
||||
private getRelayStatus(relay: any): 'connected' | 'connecting' | 'disconnected' | 'error' {
|
||||
try {
|
||||
if (relay.status === NDK_RELAY_STATUS.CONNECTED) {
|
||||
try {
|
||||
// Check if the relay has a trailing slash in the URL
|
||||
const urlWithoutSlash = relay.url ? relay.url.replace(/\/$/, '') : '';
|
||||
const urlWithSlash = urlWithoutSlash + '/';
|
||||
|
||||
// Try to get the relay from NDK pool - check both with and without trailing slash
|
||||
const ndkRelay = this.ndk?.pool.getRelay(urlWithoutSlash) ||
|
||||
this.ndk?.pool.getRelay(urlWithSlash);
|
||||
|
||||
if (ndkRelay) {
|
||||
console.log(`[RelayService] Detailed relay status for ${relay.url}: status=${ndkRelay.status}, connected=${!!ndkRelay.connected}`);
|
||||
|
||||
// The most reliable way to check connection status is to check the 'connected' property
|
||||
if (ndkRelay.connected) {
|
||||
return 'connected';
|
||||
} else if (
|
||||
relay.status === NDK_RELAY_STATUS.CONNECTING ||
|
||||
relay.status === NDK_RELAY_STATUS.RECONNECTING
|
||||
) {
|
||||
}
|
||||
|
||||
// NDK relay status: 0=connecting, 1=connected, 2=disconnecting, 3=disconnected, 4=reconnecting, 5=auth_required
|
||||
if (ndkRelay.status === 1) {
|
||||
return 'connected';
|
||||
} else if (ndkRelay.status === 0 || ndkRelay.status === 4) { // CONNECTING or RECONNECTING
|
||||
return 'connecting';
|
||||
} else if (ndkRelay.status === 5) { // AUTH_REQUIRED - This is actually a connected state!
|
||||
return 'connected'; // This is the key fix
|
||||
} else {
|
||||
return 'disconnected';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[RelayService] Error getting relay status:`, error);
|
||||
return 'disconnected';
|
||||
}
|
||||
|
||||
// If we can't find the relay in the NDK pool
|
||||
return 'disconnected';
|
||||
} catch (error) {
|
||||
console.error(`[RelayService] Error getting relay status:`, error);
|
||||
return 'disconnected';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and debug relays table and content
|
||||
@ -674,9 +975,10 @@ export class RelayService {
|
||||
);
|
||||
|
||||
// If we have relays and they're not just the defaults, skip import
|
||||
if (existingCount?.count > DEFAULT_RELAYS.length) {
|
||||
console.log(`[RelayService] Using existing relay configuration (${existingCount?.count} relays)`);
|
||||
return;
|
||||
if (existingCount && existingCount.count !== undefined && existingCount.count > 0) {
|
||||
console.log(`[RelayService] Found ${existingCount.count} existing relays, checking if we need to import more`);
|
||||
} else {
|
||||
console.log('[RelayService] No existing relays found, will attempt to import');
|
||||
}
|
||||
|
||||
console.log('[RelayService] Attempting to import user relay preferences');
|
||||
@ -689,10 +991,19 @@ export class RelayService {
|
||||
// Apply the imported configuration immediately
|
||||
await this.applyRelayConfig(ndk);
|
||||
} else {
|
||||
console.log('[RelayService] No relay preferences found, using defaults');
|
||||
console.log('[RelayService] No relay preferences found, resetting to defaults');
|
||||
await this.resetToDefaults();
|
||||
await this.applyRelayConfig(ndk);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[RelayService] Error importing user relays:', error);
|
||||
// On error, reset to defaults
|
||||
try {
|
||||
console.log('[RelayService] Error occurred, resetting to defaults');
|
||||
await this.resetToDefaults();
|
||||
await this.applyRelayConfig(ndk);
|
||||
} catch (resetError) {
|
||||
console.error('[RelayService] Error resetting to defaults:', resetError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
@ -19,6 +19,8 @@ export async function initializeNDK() {
|
||||
// Initialize database and relay service
|
||||
const db = openDatabaseSync('powr.db');
|
||||
const relayService = new RelayService(db);
|
||||
|
||||
relayService.enableDebug();
|
||||
|
||||
// Load relays from database or use defaults
|
||||
console.log('[NDK] Loading relay configuration...');
|
||||
@ -97,7 +99,6 @@ export async function initializeNDK() {
|
||||
});
|
||||
|
||||
try {
|
||||
// Connect to relays
|
||||
console.log('[NDK] Connecting to relays...');
|
||||
await ndk.connect();
|
||||
|
||||
@ -111,6 +112,17 @@ export async function initializeNDK() {
|
||||
|
||||
console.log(`[NDK] Connected to ${connectedRelays.length}/${relays.length} relays`);
|
||||
|
||||
// Add more detailed relay status logging
|
||||
console.log('[NDK] Detailed relay status:');
|
||||
relays.forEach(url => {
|
||||
const relay = ndk.pool.getRelay(url);
|
||||
console.log(` - ${url}: ${relay ?
|
||||
(relay.status === 1 ? 'connected' :
|
||||
relay.status === 0 ? 'connecting' :
|
||||
relay.status === 3 ? 'disconnected' :
|
||||
`status=${relay.status}`) : 'not found'}`);
|
||||
});
|
||||
|
||||
return {
|
||||
ndk,
|
||||
relayStatus,
|
||||
|
@ -10,6 +10,7 @@ import NDK, {
|
||||
import { generateSecretKey, getPublicKey, nip19 } from 'nostr-tools';
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
import { RelayService } from '@/lib/db/services/RelayService';
|
||||
import { openDatabaseSync } from 'expo-sqlite';
|
||||
|
||||
// Constants for SecureStore
|
||||
const PRIVATE_KEY_STORAGE_KEY = 'nostr_privkey';
|
||||
|
Loading…
x
Reference in New Issue
Block a user