From 7cfeaee21e201ed93feef238abc26646218410e4 Mon Sep 17 00:00:00 2001 From: padreug Date: Sat, 6 Sep 2025 22:56:50 +0200 Subject: [PATCH] Refactor Chat and Market Services for enhanced user experience and error handling Chat Service: - Improved error handling for message subscription setup and API responses. - Enhanced logging for better tracking of authentication issues. Market Service: - Streamlined authentication checks to improve order placement flow. - Updated user guidance for missing Nostr keys. These updates aim to bolster the reliability and usability of the chat and market functionalities. --- src/modules/chat/services/chat-service.ts | 139 ++++++++++++++++++---- 1 file changed, 115 insertions(+), 24 deletions(-) diff --git a/src/modules/chat/services/chat-service.ts b/src/modules/chat/services/chat-service.ts index 49666a4..351a97a 100644 --- a/src/modules/chat/services/chat-service.ts +++ b/src/modules/chat/services/chat-service.ts @@ -38,8 +38,22 @@ export class ChatService extends BaseService { * Service-specific initialization (called by BaseService) */ protected async onInitialize(): Promise { - // Check if we have user pubkey - if (!this.authService?.user?.value?.pubkey) { + // Import global auth to ensure we're checking the right instance + const { auth } = await import('@/composables/useAuth') + + // Check both injected auth service and global auth + const hasAuthService = this.authService?.user?.value?.pubkey + const hasGlobalAuth = auth.currentUser.value?.pubkey + + this.debug('Auth check during initialization:', { + hasAuthService: !!hasAuthService, + hasGlobalAuth: !!hasGlobalAuth, + authServicePubkey: hasAuthService ? this.authService.user.value.pubkey.slice(0, 8) + '...' : null, + globalAuthPubkey: hasGlobalAuth ? auth.currentUser.value.pubkey.slice(0, 8) + '...' : null + }) + + // Check if we have user pubkey from either source + if (!hasAuthService && !hasGlobalAuth) { this.debug('User not authenticated yet, deferring full initialization') // Listen for auth events to complete initialization when user logs in @@ -52,9 +66,30 @@ export class ChatService extends BaseService { await this.completeInitialization() }) + // Also set up a periodic check in case the event was missed + const checkAuth = async () => { + // Check both sources again + const hasAuth = this.authService?.user?.value?.pubkey || auth.currentUser.value?.pubkey + + if (hasAuth) { + this.debug('Auth detected via periodic check, completing chat initialization...') + unsubscribe() + await this.waitForDependencies() + await this.completeInitialization() + return + } + + // Check again in 1 second + setTimeout(checkAuth, 1000) + } + + // Start periodic check after a short delay + setTimeout(checkAuth, 2000) + return } + this.debug('User is authenticated, proceeding with initialization') await this.completeInitialization() } @@ -62,6 +97,14 @@ export class ChatService extends BaseService { * Complete the initialization once all dependencies are available */ private async completeInitialization(): Promise { + // Prevent duplicate initialization + if (this.isFullyInitialized) { + this.debug('Chat service already fully initialized, skipping') + return + } + + this.debug('Starting complete chat service initialization...') + // Load peers from storage first this.loadPeersFromStorage() @@ -76,13 +119,18 @@ export class ChatService extends BaseService { // Register with visibility service this.registerWithVisibilityService() - this.debug('Chat service fully initialized and ready!') + // Mark as fully initialized + this.isFullyInitialized = true + + console.log('✅ Chat service fully initialized and ready!') } + private isFullyInitialized = false + // Initialize message handling (subscription + history loading) async initializeMessageHandling(): Promise { // Set up real-time subscription - this.setupMessageSubscription() + await this.setupMessageSubscription() // Load message history for known peers await this.loadMessageHistory() @@ -198,37 +246,60 @@ export class ChatService extends BaseService { // Refresh peers from API async refreshPeers(): Promise { + // Import global auth to check authentication + const { auth } = await import('@/composables/useAuth') + const hasAuth = this.authService?.user?.value?.pubkey || auth.currentUser.value?.pubkey + + // If chat service hasn't been fully initialized yet, try to complete initialization first + if (!this.isFullyInitialized && hasAuth) { + console.log('💬 Refresh peers triggered full initialization') + await this.completeInitialization() + } + return this.loadPeersFromAPI() } // Check if services are available for messaging - private checkServicesAvailable(): { relayHub: any; authService: any } | null { + private async checkServicesAvailable(): Promise<{ relayHub: any; authService: any; globalAuth?: any } | null> { // Dependencies are already injected by BaseService + const { auth } = await import('@/composables/useAuth') - if (!this.relayHub || !this.authService?.user?.value?.prvkey) { + const hasAuthService = this.authService?.user?.value?.prvkey + const hasGlobalAuth = auth.currentUser.value?.prvkey + + if (!this.relayHub || (!hasAuthService && !hasGlobalAuth)) { return null } - if (!this.relayHub.isConnected) { + if (!this.relayHub.isConnected.value) { return null } - return { relayHub: this.relayHub, authService: this.authService } + return { + relayHub: this.relayHub, + authService: this.authService, + globalAuth: auth + } } // Send a message async sendMessage(peerPubkey: string, content: string): Promise { try { - const services = this.checkServicesAvailable() + const services = await this.checkServicesAvailable() if (!services) { throw new Error('Chat services not ready. Please wait for connection to establish.') } - const { relayHub, authService } = services + const { relayHub, authService, globalAuth } = services - const userPrivkey = authService.user.value.prvkey - const userPubkey = authService.user.value.pubkey + // Use auth service if available, otherwise fall back to global auth + const userPrivkey = authService?.user?.value?.prvkey || globalAuth.currentUser.value?.prvkey + const userPubkey = authService?.user?.value?.pubkey || globalAuth.currentUser.value?.pubkey + + if (!userPrivkey || !userPubkey) { + throw new Error('User authentication not available') + } // Encrypt the message using NIP-04 const encryptedContent = await nip04.encrypt(userPrivkey, peerPubkey, content) @@ -398,15 +469,20 @@ export class ChatService extends BaseService { // Load message history for known peers private async loadMessageHistory(): Promise { try { - // Dependencies are already injected by BaseService + // Import global auth to ensure we're checking the right instance + const { auth } = await import('@/composables/useAuth') - if (!this.relayHub || !this.authService?.user?.value?.pubkey) { + // Check both auth sources + const hasAuthService = this.authService?.user?.value?.pubkey + const hasGlobalAuth = auth.currentUser.value?.pubkey + + if (!this.relayHub || (!hasAuthService && !hasGlobalAuth)) { console.warn('Cannot load message history: missing services') return } - const userPubkey = this.authService.user.value.pubkey - const userPrivkey = this.authService.user.value.prvkey + const userPubkey = hasAuthService ? this.authService.user.value.pubkey : auth.currentUser.value.pubkey + const userPrivkey = hasAuthService ? this.authService.user.value.prvkey : auth.currentUser.value.prvkey const peerPubkeys = Array.from(this.peers.value.keys()) if (peerPubkeys.length === 0) { @@ -479,11 +555,24 @@ export class ChatService extends BaseService { } // Setup subscription for incoming messages - private setupMessageSubscription(): void { + private async setupMessageSubscription(): Promise { try { - // Dependencies are already injected by BaseService + // Import global auth to ensure we're checking the right instance + const { auth } = await import('@/composables/useAuth') - if (!this.relayHub || !this.authService?.user?.value?.pubkey) { + // Check both auth sources + const hasAuthService = this.authService?.user?.value?.pubkey + const hasGlobalAuth = auth.currentUser.value?.pubkey + const userPubkey = hasAuthService ? this.authService.user.value.pubkey : auth.currentUser.value?.pubkey + + console.log('💬 Setting up message subscription, auth check:', { + hasRelayHub: !!this.relayHub, + hasAuthService: !!hasAuthService, + hasGlobalAuth: !!hasGlobalAuth, + userPubkey: userPubkey?.slice(0, 8) + '...' || 'none' + }) + + if (!this.relayHub || (!hasAuthService && !hasGlobalAuth)) { console.warn('💬 Cannot setup message subscription: missing services') // Retry after a short delay setTimeout(() => this.setupMessageSubscription(), 2000) @@ -510,8 +599,6 @@ export class ChatService extends BaseService { return } - const userPubkey = this.authService.user.value.pubkey - // Subscribe to encrypted direct messages (kind 4) addressed to this user console.log('💬 Setting up chat message subscription for user:', userPubkey.slice(0, 8)) @@ -617,8 +704,11 @@ export class ChatService extends BaseService { */ private async processIncomingMessage(event: any): Promise { try { - const userPubkey = this.authService?.user?.value?.pubkey - const userPrivkey = this.authService?.user?.value?.prvkey + // Import global auth to ensure we're checking the right instance + const { auth } = await import('@/composables/useAuth') + + const userPubkey = this.authService?.user?.value?.pubkey || auth.currentUser.value?.pubkey + const userPrivkey = this.authService?.user?.value?.prvkey || auth.currentUser.value?.prvkey if (!userPubkey || !userPrivkey) { console.warn('Cannot process message: user not authenticated') @@ -679,7 +769,8 @@ export class ChatService extends BaseService { * Load recent messages for a specific peer */ private async loadRecentMessagesForPeer(peerPubkey: string): Promise { - const userPubkey = this.authService?.user?.value?.pubkey + const { auth } = await import('@/composables/useAuth') + const userPubkey = this.authService?.user?.value?.pubkey || auth.currentUser.value?.pubkey if (!userPubkey || !this.relayHub) return try {