mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-07 11:19:58 +02:00
feat(apple): contacts screen and consent prompts
Device list, detail, and block list under Settings, plus the two sheets: an incoming offer and a device asking to be remembered. Both are answer-only, since swiping away would leave the sender waiting. Accepting an offer routes the released ticket into the ordinary receive path, so the platform still chooses the destination. The prompt does not ask a second time; it only falls back to the review sheet when the destination is unusable.
This commit is contained in:
@@ -8,6 +8,7 @@ enum SettingsSection: Hashable {
|
||||
case appearance
|
||||
case notifications
|
||||
case network
|
||||
case contacts
|
||||
case storage
|
||||
case about
|
||||
case bugReport
|
||||
@@ -19,6 +20,7 @@ enum SettingsSection: Hashable {
|
||||
case .appearance: return L10n.Appearance.title
|
||||
case .notifications: return L10n.Notifications.title
|
||||
case .network: return L10n.Settings.networkTitle
|
||||
case .contacts: return L10n.Contacts.title
|
||||
case .storage: return L10n.Storage.title
|
||||
case .about: return L10n.About.title
|
||||
case .bugReport: return L10n.About.bugReport
|
||||
|
||||
@@ -5,6 +5,7 @@ import SFSafeSymbols
|
||||
/// navigation. The model stays the source of truth via a derived path binding.
|
||||
struct SettingsScreen: View {
|
||||
@ObservedObject var model: SettingsModel
|
||||
@ObservedObject var contacts: ContactsModel
|
||||
let windowClass: WindowClass
|
||||
@State private var showBugReport = false
|
||||
|
||||
@@ -54,6 +55,15 @@ struct SettingsScreen: View {
|
||||
NavigationLink(value: SettingsSection.storage) {
|
||||
SettingsRow(icon: .internaldrive, title: String(localized: L10n.Storage.title), value: nil)
|
||||
}
|
||||
NavigationLink(value: SettingsSection.contacts) {
|
||||
SettingsRow(
|
||||
icon: .laptopcomputerAndIphone,
|
||||
title: String(localized: L10n.Contacts.title),
|
||||
value: contacts.state.contacts.isEmpty
|
||||
? nil
|
||||
: String(contacts.state.contacts.count)
|
||||
)
|
||||
}
|
||||
}
|
||||
Section(String(localized: L10n.Settings.advancedTitle)) {
|
||||
NavigationLink(value: SettingsSection.network) {
|
||||
@@ -80,6 +90,17 @@ struct SettingsScreen: View {
|
||||
|
||||
@ViewBuilder
|
||||
private func sectionForm(_ section: SettingsSection) -> some View {
|
||||
// Contacts brings its own Form and push destination, so it is not wrapped
|
||||
// in the shared section chrome.
|
||||
if section == .contacts {
|
||||
ContactsScreen(model: contacts)
|
||||
} else {
|
||||
settingsSectionForm(section)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func settingsSectionForm(_ section: SettingsSection) -> some View {
|
||||
let content = Form {
|
||||
SettingsSectionContent(model: model, section: section)
|
||||
}
|
||||
@@ -130,6 +151,9 @@ private struct SettingsSectionContent: View {
|
||||
NetworkSettings(model: model)
|
||||
case .storage:
|
||||
StorageSettings(model: model)
|
||||
case .contacts:
|
||||
// Rendered by SettingsScreen itself, which owns the contacts model.
|
||||
EmptyView()
|
||||
case .about:
|
||||
AboutSettings(model: model)
|
||||
case .bugReport:
|
||||
|
||||
Reference in New Issue
Block a user