Fix ShareExtension "Open Marks first" + add widget + BookmarkListRow polish
All checks were successful
CI / build-and-deploy (push) Successful in 41s
All checks were successful
CI / build-and-deploy (push) Successful in 41s
- Save serverConfig to App Group on every app launch so ShareExtension can always find credentials without requiring a disconnect/reconnect flow - Add MarksWidget target with RandomBookmarkWidget (random saved bookmark, reloads hourly) using file-based App Group storage to avoid CFPreferences issues - Extract BookmarkListRow as shared component with editorial typography tweaks (17pt semibold title, 13pt domain, relative date, 32×32 favicon, italic AI summary, 20pt podcast icon, 16pt horizontal insets) - Add MarksWidget and ShareExtension Xcode schemes for direct run/debug Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,16 +18,24 @@ struct MarksApp: App {
|
||||
defaultConfig.save()
|
||||
serverConfig = defaultConfig
|
||||
}
|
||||
.task { serverConfig.save() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct IdentifiableURL: Identifiable {
|
||||
let id = UUID()
|
||||
let url: URL
|
||||
}
|
||||
|
||||
// Holds the API + ViewModel so they survive re-renders
|
||||
struct MainContainer: View {
|
||||
let config: ServerConfig
|
||||
let onDisconnect: () -> Void
|
||||
|
||||
@State private var viewModel: BookmarksViewModel
|
||||
@State private var deepLinkBrowser: IdentifiableURL?
|
||||
@State private var showDeepLinkPlayer = false
|
||||
|
||||
init(config: ServerConfig, onDisconnect: @escaping () -> Void) {
|
||||
self.config = config
|
||||
@@ -48,5 +56,45 @@ struct MainContainer: View {
|
||||
SearchView(viewModel: viewModel)
|
||||
}
|
||||
}
|
||||
.onOpenURL { url in
|
||||
handleDeepLink(url)
|
||||
}
|
||||
.sheet(item: $deepLinkBrowser) { item in
|
||||
BrowserView(url: item.url, title: item.url.host ?? "", claude: viewModel.claude, podcastPlayer: viewModel.podcastPlayer)
|
||||
}
|
||||
.sheet(isPresented: $showDeepLinkPlayer) {
|
||||
PodcastPlayerView(
|
||||
vm: viewModel.podcastPlayer,
|
||||
articleUrl: viewModel.podcastPlayer.currentArticleUrl,
|
||||
articleTitle: viewModel.podcastPlayer.currentArticleTitle,
|
||||
claude: viewModel.claude,
|
||||
stopOnDismiss: false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleDeepLink(_ url: URL) {
|
||||
guard url.scheme == "marks",
|
||||
let comps = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
||||
let articleUrl = comps.queryItems?.first(where: { $0.name == "url" })?.value
|
||||
else { return }
|
||||
|
||||
switch url.host {
|
||||
case "bookmark":
|
||||
if let browserURL = URL(string: articleUrl) {
|
||||
deepLinkBrowser = IdentifiableURL(url: browserURL)
|
||||
}
|
||||
case "podcast":
|
||||
let podcasts = WidgetDataStore.loadPodcasts()
|
||||
let found = podcasts.first { $0.articleUrl == articleUrl }
|
||||
viewModel.podcastPlayer.start(
|
||||
articleUrl: articleUrl,
|
||||
articleTitle: found?.title ?? "",
|
||||
claude: viewModel.claude
|
||||
)
|
||||
showDeepLinkPlayer = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user