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)
*/
protected async onInitialize(): Promise<void> {
// 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<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
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<void> {
// 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<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()
}
// 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<void> {
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<void> {
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<void> {
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<void> {
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<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
try {