This commit introduces a comprehensive refactoring of the tag management system, replacing the previous API-based approach with a Core Data-first strategy for improved performance and offline support. Major Changes: Tag Management Architecture: - Add CoreDataTagManagementView using @FetchRequest for reactive updates - Implement cache-first sync strategy in LabelsRepository - Create SyncTagsUseCase following Clean Architecture principles - Add TagSortOrder enum for configurable tag sorting (by count/alphabetically) - Mark LegacyTagManagementView as deprecated Share Extension Improvements: - Replace API-based tag loading with Core Data queries - Display top 150 tags sorted by usage count - Remove unnecessary label fetching logic - Add "Most used tags" localized title - Improve offline bookmark tag management Main App Enhancements: - Add tag sync triggers in AddBookmarkView and BookmarkLabelsView - Implement user-configurable tag sorting in settings - Add sort order indicator labels with localization - Automatic UI updates via SwiftUI @FetchRequest reactivity Settings & Configuration: - Add TagSortOrder setting with persistence - Refactor Settings model structure - Add FontFamily and FontSize domain models - Improve settings repository with tag sort order support Use Case Layer: - Add SyncTagsUseCase for background tag synchronization - Update UseCaseFactory with tag sync support - Add mock implementations for testing Localization: - Add German and English translations for: - "Most used tags" - "Sorted by usage count" - "Sorted alphabetically" Technical Improvements: - Batch tag updates with conflict detection - Background sync with silent failure handling - Reduced server load through local caching - Better separation of concerns following Clean Architecture
141 lines
5.7 KiB
Swift
141 lines
5.7 KiB
Swift
import Foundation
|
|
|
|
protocol UseCaseFactory {
|
|
func makeLoginUseCase() -> PLoginUseCase
|
|
func makeGetBookmarksUseCase() -> PGetBookmarksUseCase
|
|
func makeGetBookmarkUseCase() -> PGetBookmarkUseCase
|
|
func makeGetBookmarkArticleUseCase() -> PGetBookmarkArticleUseCase
|
|
func makeSaveSettingsUseCase() -> PSaveSettingsUseCase
|
|
func makeLoadSettingsUseCase() -> PLoadSettingsUseCase
|
|
func makeUpdateBookmarkUseCase() -> PUpdateBookmarkUseCase
|
|
func makeDeleteBookmarkUseCase() -> PDeleteBookmarkUseCase
|
|
func makeCreateBookmarkUseCase() -> PCreateBookmarkUseCase
|
|
func makeLogoutUseCase() -> PLogoutUseCase
|
|
func makeSearchBookmarksUseCase() -> PSearchBookmarksUseCase
|
|
func makeSaveServerSettingsUseCase() -> PSaveServerSettingsUseCase
|
|
func makeAddLabelsToBookmarkUseCase() -> PAddLabelsToBookmarkUseCase
|
|
func makeRemoveLabelsFromBookmarkUseCase() -> PRemoveLabelsFromBookmarkUseCase
|
|
func makeGetLabelsUseCase() -> PGetLabelsUseCase
|
|
func makeSyncTagsUseCase() -> PSyncTagsUseCase
|
|
func makeAddTextToSpeechQueueUseCase() -> PAddTextToSpeechQueueUseCase
|
|
func makeOfflineBookmarkSyncUseCase() -> POfflineBookmarkSyncUseCase
|
|
func makeLoadCardLayoutUseCase() -> PLoadCardLayoutUseCase
|
|
func makeSaveCardLayoutUseCase() -> PSaveCardLayoutUseCase
|
|
func makeCheckServerReachabilityUseCase() -> PCheckServerReachabilityUseCase
|
|
func makeGetBookmarkAnnotationsUseCase() -> PGetBookmarkAnnotationsUseCase
|
|
func makeDeleteAnnotationUseCase() -> PDeleteAnnotationUseCase
|
|
}
|
|
|
|
|
|
|
|
class DefaultUseCaseFactory: UseCaseFactory {
|
|
private let tokenProvider = KeychainTokenProvider()
|
|
private lazy var api: PAPI = API(tokenProvider: tokenProvider)
|
|
private lazy var authRepository: PAuthRepository = AuthRepository(api: api, settingsRepository: settingsRepository)
|
|
private lazy var bookmarksRepository: PBookmarksRepository = BookmarksRepository(api: api)
|
|
private let settingsRepository: PSettingsRepository = SettingsRepository()
|
|
private lazy var infoApiClient: PInfoApiClient = InfoApiClient(tokenProvider: tokenProvider)
|
|
private lazy var serverInfoRepository: PServerInfoRepository = ServerInfoRepository(apiClient: infoApiClient)
|
|
private lazy var annotationsRepository: PAnnotationsRepository = AnnotationsRepository(api: api)
|
|
|
|
static let shared = DefaultUseCaseFactory()
|
|
|
|
private init() {}
|
|
|
|
func makeLoginUseCase() -> PLoginUseCase {
|
|
LoginUseCase(repository: authRepository)
|
|
}
|
|
|
|
func makeGetBookmarksUseCase() -> PGetBookmarksUseCase {
|
|
GetBookmarksUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeGetBookmarkUseCase() -> PGetBookmarkUseCase {
|
|
GetBookmarkUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeGetBookmarkArticleUseCase() -> PGetBookmarkArticleUseCase {
|
|
GetBookmarkArticleUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeSaveSettingsUseCase() -> PSaveSettingsUseCase {
|
|
SaveSettingsUseCase(settingsRepository: settingsRepository)
|
|
}
|
|
|
|
func makeLoadSettingsUseCase() -> PLoadSettingsUseCase {
|
|
LoadSettingsUseCase(authRepository: authRepository)
|
|
}
|
|
|
|
func makeUpdateBookmarkUseCase() -> PUpdateBookmarkUseCase {
|
|
return UpdateBookmarkUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeLogoutUseCase() -> PLogoutUseCase {
|
|
return LogoutUseCase()
|
|
}
|
|
|
|
func makeDeleteBookmarkUseCase() -> PDeleteBookmarkUseCase {
|
|
return DeleteBookmarkUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeCreateBookmarkUseCase() -> PCreateBookmarkUseCase {
|
|
return CreateBookmarkUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeSearchBookmarksUseCase() -> PSearchBookmarksUseCase {
|
|
return SearchBookmarksUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeSaveServerSettingsUseCase() -> PSaveServerSettingsUseCase {
|
|
return SaveServerSettingsUseCase(repository: SettingsRepository())
|
|
}
|
|
|
|
func makeAddLabelsToBookmarkUseCase() -> PAddLabelsToBookmarkUseCase {
|
|
return AddLabelsToBookmarkUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeRemoveLabelsFromBookmarkUseCase() -> PRemoveLabelsFromBookmarkUseCase {
|
|
return RemoveLabelsFromBookmarkUseCase(repository: bookmarksRepository)
|
|
}
|
|
|
|
func makeGetLabelsUseCase() -> PGetLabelsUseCase {
|
|
let api = API(tokenProvider: KeychainTokenProvider())
|
|
let labelsRepository = LabelsRepository(api: api)
|
|
return GetLabelsUseCase(labelsRepository: labelsRepository)
|
|
}
|
|
|
|
func makeSyncTagsUseCase() -> PSyncTagsUseCase {
|
|
let api = API(tokenProvider: KeychainTokenProvider())
|
|
let labelsRepository = LabelsRepository(api: api)
|
|
return SyncTagsUseCase(labelsRepository: labelsRepository)
|
|
}
|
|
|
|
func makeAddTextToSpeechQueueUseCase() -> PAddTextToSpeechQueueUseCase {
|
|
return AddTextToSpeechQueueUseCase()
|
|
}
|
|
|
|
func makeOfflineBookmarkSyncUseCase() -> POfflineBookmarkSyncUseCase {
|
|
return OfflineBookmarkSyncUseCase()
|
|
}
|
|
|
|
func makeLoadCardLayoutUseCase() -> PLoadCardLayoutUseCase {
|
|
return LoadCardLayoutUseCase(settingsRepository: settingsRepository)
|
|
}
|
|
|
|
func makeSaveCardLayoutUseCase() -> PSaveCardLayoutUseCase {
|
|
return SaveCardLayoutUseCase(settingsRepository: settingsRepository)
|
|
}
|
|
|
|
func makeCheckServerReachabilityUseCase() -> PCheckServerReachabilityUseCase {
|
|
return CheckServerReachabilityUseCase(repository: serverInfoRepository)
|
|
}
|
|
|
|
func makeGetBookmarkAnnotationsUseCase() -> PGetBookmarkAnnotationsUseCase {
|
|
return GetBookmarkAnnotationsUseCase(repository: annotationsRepository)
|
|
}
|
|
|
|
func makeDeleteAnnotationUseCase() -> PDeleteAnnotationUseCase {
|
|
return DeleteAnnotationUseCase(repository: annotationsRepository)
|
|
}
|
|
}
|