1.3.4 User-Scoped Storage Pattern: Add StorageService integration across modules for improved data management
- Introduced STORAGE_SERVICE token in the DI container for consistent service registration. - Updated BaseService to include storageService as a dependency, ensuring proper initialization and error handling. - Refactored ChatService to utilize storageService for managing unread messages and peers, replacing localStorage usage. - Enhanced MarketStore to save and load orders using storageService, improving data persistence and user experience. - Registered storageService in the base module, ensuring it is initialized and disposed of correctly. This integration streamlines data handling across the application, promoting better maintainability and consistency.
This commit is contained in:
parent
3abdd2d7d9
commit
3cf10b1db4
6 changed files with 285 additions and 103 deletions
|
|
@ -12,6 +12,7 @@ import { pwaService } from './pwa/pwa-service'
|
|||
// Import core services
|
||||
import { paymentService } from '@/core/services/PaymentService'
|
||||
import { visibilityService } from '@/core/services/VisibilityService'
|
||||
import { storageService } from '@/core/services/StorageService'
|
||||
|
||||
/**
|
||||
* Base Module Plugin
|
||||
|
|
@ -36,6 +37,9 @@ export const baseModule: ModulePlugin = {
|
|||
// Register visibility service
|
||||
container.provide(SERVICE_TOKENS.VISIBILITY_SERVICE, visibilityService)
|
||||
|
||||
// Register storage service
|
||||
container.provide(SERVICE_TOKENS.STORAGE_SERVICE, storageService)
|
||||
|
||||
// Register PWA service
|
||||
container.provide('pwaService', pwaService)
|
||||
|
||||
|
|
@ -54,6 +58,10 @@ export const baseModule: ModulePlugin = {
|
|||
waitForDependencies: false, // VisibilityService has no dependencies
|
||||
maxRetries: 1
|
||||
})
|
||||
await storageService.initialize({
|
||||
waitForDependencies: true, // StorageService depends on AuthService
|
||||
maxRetries: 3
|
||||
})
|
||||
|
||||
console.log('✅ Base module installed successfully')
|
||||
},
|
||||
|
|
@ -66,6 +74,7 @@ export const baseModule: ModulePlugin = {
|
|||
await auth.dispose()
|
||||
await paymentService.dispose()
|
||||
await visibilityService.dispose()
|
||||
await storageService.dispose()
|
||||
|
||||
console.log('✅ Base module uninstalled')
|
||||
},
|
||||
|
|
@ -74,6 +83,8 @@ export const baseModule: ModulePlugin = {
|
|||
relayHub,
|
||||
auth,
|
||||
paymentService,
|
||||
visibilityService,
|
||||
storageService,
|
||||
pwaService
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -6,15 +6,13 @@ import type { ChatMessage, ChatPeer, UnreadMessageData, ChatConfig } from '../ty
|
|||
import { getAuthToken } from '@/lib/config/lnbits'
|
||||
import { config } from '@/lib/config'
|
||||
|
||||
const UNREAD_MESSAGES_KEY = 'nostr-chat-unread-messages'
|
||||
const PEERS_KEY = 'nostr-chat-peers'
|
||||
|
||||
export class ChatService extends BaseService {
|
||||
// Service metadata
|
||||
protected readonly metadata = {
|
||||
name: 'ChatService',
|
||||
version: '1.0.0',
|
||||
dependencies: ['RelayHub', 'AuthService', 'VisibilityService']
|
||||
dependencies: ['RelayHub', 'AuthService', 'VisibilityService', 'StorageService']
|
||||
}
|
||||
|
||||
// Service-specific state
|
||||
|
|
@ -64,6 +62,9 @@ export class ChatService extends BaseService {
|
|||
* Complete the initialization once all dependencies are available
|
||||
*/
|
||||
private async completeInitialization(): Promise<void> {
|
||||
// Load peers from storage first
|
||||
this.loadPeersFromStorage()
|
||||
|
||||
// Load peers from API
|
||||
await this.loadPeersFromAPI().catch(error => {
|
||||
console.warn('Failed to load peers from API:', error)
|
||||
|
|
@ -290,36 +291,24 @@ export class ChatService extends BaseService {
|
|||
}
|
||||
|
||||
private getUnreadData(peerPubkey: string): UnreadMessageData {
|
||||
try {
|
||||
const stored = localStorage.getItem(`${UNREAD_MESSAGES_KEY}-${peerPubkey}`)
|
||||
if (stored) {
|
||||
const data = JSON.parse(stored)
|
||||
return {
|
||||
...data,
|
||||
processedMessageIds: new Set(data.processedMessageIds || [])
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load unread data for peer:', peerPubkey, error)
|
||||
}
|
||||
const data = this.storageService.getUserData(`chat-unread-messages-${peerPubkey}`, {
|
||||
lastReadTimestamp: 0,
|
||||
unreadCount: 0,
|
||||
processedMessageIds: []
|
||||
})
|
||||
|
||||
return {
|
||||
lastReadTimestamp: 0,
|
||||
unreadCount: 0,
|
||||
processedMessageIds: new Set()
|
||||
return {
|
||||
...data,
|
||||
processedMessageIds: new Set(data.processedMessageIds || [])
|
||||
}
|
||||
}
|
||||
|
||||
private saveUnreadData(peerPubkey: string, data: UnreadMessageData): void {
|
||||
try {
|
||||
const serializable = {
|
||||
...data,
|
||||
processedMessageIds: Array.from(data.processedMessageIds)
|
||||
}
|
||||
localStorage.setItem(`${UNREAD_MESSAGES_KEY}-${peerPubkey}`, JSON.stringify(serializable))
|
||||
} catch (error) {
|
||||
console.warn('Failed to save unread data for peer:', peerPubkey, error)
|
||||
const serializable = {
|
||||
...data,
|
||||
processedMessageIds: Array.from(data.processedMessageIds)
|
||||
}
|
||||
this.storageService.setUserData(`chat-unread-messages-${peerPubkey}`, serializable)
|
||||
}
|
||||
|
||||
// Load peers from API
|
||||
|
|
@ -369,26 +358,21 @@ export class ChatService extends BaseService {
|
|||
}
|
||||
|
||||
private loadPeersFromStorage(): void {
|
||||
try {
|
||||
const stored = localStorage.getItem(PEERS_KEY)
|
||||
if (stored) {
|
||||
const peersArray = JSON.parse(stored) as ChatPeer[]
|
||||
peersArray.forEach(peer => {
|
||||
this.peers.value.set(peer.pubkey, peer)
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load peers from storage:', error)
|
||||
// Skip loading peers in constructor as StorageService may not be available yet
|
||||
// This will be called later during initialization when dependencies are ready
|
||||
if (!this.isInitialized.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const peersArray = this.storageService.getUserData('chat-peers', []) as ChatPeer[]
|
||||
peersArray.forEach(peer => {
|
||||
this.peers.value.set(peer.pubkey, peer)
|
||||
})
|
||||
}
|
||||
|
||||
private savePeersToStorage(): void {
|
||||
try {
|
||||
const peersArray = Array.from(this.peers.value.values())
|
||||
localStorage.setItem(PEERS_KEY, JSON.stringify(peersArray))
|
||||
} catch (error) {
|
||||
console.warn('Failed to save peers to storage:', error)
|
||||
}
|
||||
const peersArray = Array.from(this.peers.value.values())
|
||||
this.storageService.setUserData('chat-peers', peersArray)
|
||||
}
|
||||
|
||||
// Load message history for known peers
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { invoiceService } from '@/lib/services/invoiceService'
|
|||
import { paymentMonitor } from '@/lib/services/paymentMonitor'
|
||||
import { nostrmarketService } from '../services/nostrmarketService'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
|
||||
import type { LightningInvoice } from '@/lib/services/invoiceService'
|
||||
|
||||
|
||||
|
|
@ -16,12 +17,7 @@ import type {
|
|||
|
||||
export const useMarketStore = defineStore('market', () => {
|
||||
const auth = useAuth()
|
||||
|
||||
// Helper function to get user-specific storage key
|
||||
const getUserStorageKey = (baseKey: string) => {
|
||||
const userPubkey = auth.currentUser?.value?.pubkey
|
||||
return userPubkey ? `${baseKey}_${userPubkey}` : baseKey
|
||||
}
|
||||
const storageService = injectService(SERVICE_TOKENS.STORAGE_SERVICE) as any
|
||||
// Core market state
|
||||
const markets = ref<Market[]>([])
|
||||
const stalls = ref<Stall[]>([])
|
||||
|
|
@ -681,63 +677,42 @@ export const useMarketStore = defineStore('market', () => {
|
|||
|
||||
// Persistence methods
|
||||
const saveOrdersToStorage = () => {
|
||||
try {
|
||||
const storageKey = getUserStorageKey('market_orders')
|
||||
localStorage.setItem(storageKey, JSON.stringify(orders.value))
|
||||
|
||||
// Debug: Check what's being saved
|
||||
const orderCount = Object.keys(orders.value).length
|
||||
const paidOrders = Object.values(orders.value).filter(o => o.paymentStatus === 'paid' || o.status === 'paid')
|
||||
|
||||
console.log('💾 Saved orders to localStorage:', {
|
||||
storageKey,
|
||||
totalOrders: orderCount,
|
||||
paidOrders: paidOrders.length,
|
||||
orderStatuses: Object.values(orders.value).map(o => ({
|
||||
id: o.id?.slice(-8),
|
||||
status: o.status,
|
||||
paymentStatus: o.paymentStatus,
|
||||
hasPaymentRequest: !!o.paymentRequest
|
||||
}))
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn('Failed to save orders to localStorage:', error)
|
||||
}
|
||||
storageService.setUserData('market_orders', orders.value)
|
||||
|
||||
// Debug: Check what's being saved
|
||||
const orderCount = Object.keys(orders.value).length
|
||||
const paidOrders = Object.values(orders.value).filter(o => o.paymentStatus === 'paid' || o.status === 'paid')
|
||||
|
||||
console.log('💾 Saved orders to storage:', {
|
||||
totalOrders: orderCount,
|
||||
paidOrders: paidOrders.length,
|
||||
orderStatuses: Object.values(orders.value).map(o => ({
|
||||
id: o.id?.slice(-8),
|
||||
status: o.status,
|
||||
paymentStatus: o.paymentStatus,
|
||||
hasPaymentRequest: !!o.paymentRequest
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
const loadOrdersFromStorage = () => {
|
||||
try {
|
||||
const storageKey = getUserStorageKey('market_orders')
|
||||
const stored = localStorage.getItem(storageKey)
|
||||
if (stored) {
|
||||
const parsedOrders = JSON.parse(stored)
|
||||
orders.value = parsedOrders
|
||||
|
||||
// Debug: Check payment status of loaded orders
|
||||
const orderCount = Object.keys(parsedOrders).length
|
||||
const paidOrders = Object.values(parsedOrders).filter((o: any) => o.paymentStatus === 'paid' || o.status === 'paid')
|
||||
|
||||
console.log('📦 Loaded orders from localStorage:', {
|
||||
storageKey,
|
||||
totalOrders: orderCount,
|
||||
paidOrders: paidOrders.length,
|
||||
orderStatuses: Object.values(parsedOrders).map((o: any) => ({
|
||||
id: o.id?.slice(-8),
|
||||
status: o.status,
|
||||
paymentStatus: o.paymentStatus,
|
||||
hasPaymentRequest: !!o.paymentRequest
|
||||
}))
|
||||
})
|
||||
} else {
|
||||
console.log('No orders found in localStorage for key:', storageKey)
|
||||
// Clear any existing orders when switching users
|
||||
orders.value = {}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load orders from localStorage:', error)
|
||||
// Clear orders on error
|
||||
orders.value = {}
|
||||
}
|
||||
const parsedOrders = storageService.getUserData('market_orders', {})
|
||||
orders.value = parsedOrders
|
||||
|
||||
// Debug: Check payment status of loaded orders
|
||||
const orderCount = Object.keys(parsedOrders).length
|
||||
const paidOrders = Object.values(parsedOrders).filter((o: any) => o.paymentStatus === 'paid' || o.status === 'paid')
|
||||
|
||||
console.log('📦 Loaded orders from storage:', {
|
||||
totalOrders: orderCount,
|
||||
paidOrders: paidOrders.length,
|
||||
orderStatuses: Object.values(parsedOrders).map((o: any) => ({
|
||||
id: o.id?.slice(-8),
|
||||
status: o.status,
|
||||
paymentStatus: o.paymentStatus,
|
||||
hasPaymentRequest: !!o.paymentRequest
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
// Clear orders when user changes
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue