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.
This commit is contained in:
padreug 2025-09-06 22:56:50 +02:00
parent 8a019db34a
commit 7cfeaee21e

View file

@ -38,8 +38,22 @@ export class ChatService extends BaseService {
* Service-specific initialization (called by BaseService) * Service-specific initialization (called by BaseService)
*/ */
protected async onInitialize(): Promise<void> { protected async onInitialize(): Promise<void> {
// Check if we have user pubkey // Import global auth to ensure we're checking the right instance
if (!this.authService?.user?.value?.pubkey) { 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') this.debug('User not authenticated yet, deferring full initialization')
// Listen for auth events to complete initialization when user logs in // Listen for auth events to complete initialization when user logs in
@ -52,9 +66,30 @@ export class ChatService extends BaseService {
await this.completeInitialization() 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 return
} }
this.debug('User is authenticated, proceeding with initialization')
await this.completeInitialization() await this.completeInitialization()
} }
@ -62,6 +97,14 @@ export class ChatService extends BaseService {
* Complete the initialization once all dependencies are available * Complete the initialization once all dependencies are available
*/ */
private async completeInitialization(): Promise<void> { private async completeInitialization(): Promise<void> {
// 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 // Load peers from storage first
this.loadPeersFromStorage() this.loadPeersFromStorage()
@ -76,13 +119,18 @@ export class ChatService extends BaseService {
// Register with visibility service // Register with visibility service
this.registerWithVisibilityService() 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) // Initialize message handling (subscription + history loading)
async initializeMessageHandling(): Promise<void> { async initializeMessageHandling(): Promise<void> {
// Set up real-time subscription // Set up real-time subscription
this.setupMessageSubscription() await this.setupMessageSubscription()
// Load message history for known peers // Load message history for known peers
await this.loadMessageHistory() await this.loadMessageHistory()
@ -198,37 +246,60 @@ export class ChatService extends BaseService {
// Refresh peers from API // Refresh peers from API
async refreshPeers(): Promise<void> { async refreshPeers(): Promise<void> {
// 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() return this.loadPeersFromAPI()
} }
// Check if services are available for messaging // 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 // 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 return null
} }
if (!this.relayHub.isConnected) { if (!this.relayHub.isConnected.value) {
return null return null
} }
return { relayHub: this.relayHub, authService: this.authService } return {
relayHub: this.relayHub,
authService: this.authService,
globalAuth: auth
}
} }
// Send a message // Send a message
async sendMessage(peerPubkey: string, content: string): Promise<void> { async sendMessage(peerPubkey: string, content: string): Promise<void> {
try { try {
const services = this.checkServicesAvailable() const services = await this.checkServicesAvailable()
if (!services) { if (!services) {
throw new Error('Chat services not ready. Please wait for connection to establish.') 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 // Use auth service if available, otherwise fall back to global auth
const userPubkey = authService.user.value.pubkey 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 // Encrypt the message using NIP-04
const encryptedContent = await nip04.encrypt(userPrivkey, peerPubkey, content) const encryptedContent = await nip04.encrypt(userPrivkey, peerPubkey, content)
@ -398,15 +469,20 @@ export class ChatService extends BaseService {
// Load message history for known peers // Load message history for known peers
private async loadMessageHistory(): Promise<void> { private async loadMessageHistory(): Promise<void> {
try { 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') console.warn('Cannot load message history: missing services')
return return
} }
const userPubkey = this.authService.user.value.pubkey const userPubkey = hasAuthService ? this.authService.user.value.pubkey : auth.currentUser.value.pubkey
const userPrivkey = this.authService.user.value.prvkey const userPrivkey = hasAuthService ? this.authService.user.value.prvkey : auth.currentUser.value.prvkey
const peerPubkeys = Array.from(this.peers.value.keys()) const peerPubkeys = Array.from(this.peers.value.keys())
if (peerPubkeys.length === 0) { if (peerPubkeys.length === 0) {
@ -479,11 +555,24 @@ export class ChatService extends BaseService {
} }
// Setup subscription for incoming messages // Setup subscription for incoming messages
private setupMessageSubscription(): void { private async setupMessageSubscription(): Promise<void> {
try { 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') console.warn('💬 Cannot setup message subscription: missing services')
// Retry after a short delay // Retry after a short delay
setTimeout(() => this.setupMessageSubscription(), 2000) setTimeout(() => this.setupMessageSubscription(), 2000)
@ -510,8 +599,6 @@ export class ChatService extends BaseService {
return return
} }
const userPubkey = this.authService.user.value.pubkey
// Subscribe to encrypted direct messages (kind 4) addressed to this user // Subscribe to encrypted direct messages (kind 4) addressed to this user
console.log('💬 Setting up chat message subscription for user:', userPubkey.slice(0, 8)) 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<void> { private async processIncomingMessage(event: any): Promise<void> {
try { try {
const userPubkey = this.authService?.user?.value?.pubkey // Import global auth to ensure we're checking the right instance
const userPrivkey = this.authService?.user?.value?.prvkey 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) { if (!userPubkey || !userPrivkey) {
console.warn('Cannot process message: user not authenticated') console.warn('Cannot process message: user not authenticated')
@ -679,7 +769,8 @@ export class ChatService extends BaseService {
* Load recent messages for a specific peer * Load recent messages for a specific peer
*/ */
private async loadRecentMessagesForPeer(peerPubkey: string): Promise<void> { private async loadRecentMessagesForPeer(peerPubkey: string): Promise<void> {
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 if (!userPubkey || !this.relayHub) return
try { try {