feat(share): dup-aware interactive save card with AI tag suggestions
All checks were successful
CI / build-and-deploy (push) Successful in 20s
All checks were successful
CI / build-and-deploy (push) Successful in 20s
Replace the fire-and-forget share toast with an interactive SwiftUI card. On open it checks linkding's /api/bookmarks/check/ so an already-saved URL routes to an Update (no more silent duplicates) and a new URL shows a save form with title, tags, notes, and a read-later toggle. Tag suggestions are hybrid: fetch the user's existing tag vocabulary (/api/tags/) and AI tag ideas (/v1/marks/enrich via anonymous device auth), auto-fill known-vocabulary matches into the field and surface net-new ideas as tappable chips. Best-effort and non-blocking — failures never block save. Also: - Refresh bookmarks when the app returns to the foreground (scenePhase). - Render bookmark dates as a static relative label instead of the live ticking RelativeDateTime timer. - Share LinkdingAPI/Bookmark/ServerConfig/MarksAuth into the ShareExtension target via project.yml (durable across xcodegen regen) and regenerate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,7 @@ struct MainContainer: View {
|
||||
@State private var showDeepLinkPlayer = false
|
||||
@State private var selectedTab: AppTab = .bookmarks
|
||||
@State private var router = IntentRouter.shared
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
|
||||
init(config: ServerConfig, onDisconnect: @escaping () -> Void) {
|
||||
self.config = config
|
||||
@@ -64,6 +65,13 @@ struct MainContainer: View {
|
||||
.task { applyPendingIntent() }
|
||||
.onChange(of: router.openBookmarkURL) { _, _ in applyPendingIntent() }
|
||||
.onChange(of: router.searchRequest) { _, _ in applyPendingIntent() }
|
||||
.onChange(of: scenePhase) { old, new in
|
||||
// Refresh when returning to the foreground (cold launch is already
|
||||
// covered by BookmarksView's .task, so only react to a real re-entry).
|
||||
if new == .active && old != .active {
|
||||
Task { await viewModel.load() }
|
||||
}
|
||||
}
|
||||
.sheet(item: $deepLinkBrowser) { item in
|
||||
BrowserView(url: item.url, title: item.url.host ?? "", claude: viewModel.claude, podcastPlayer: viewModel.podcastPlayer)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user