feat(settings): grey out server-synced settings while offline
Profile's name/avatar and every Preferences toggle (except Appearance, which is local-only) now disable + show a hint when isEffectivelyOnline is false, instead of letting a save silently fail. Matches how Share/ Permissions/Search already behave — these are a "needs a real connection" category, not queued through the offline write queue (infrequent writes, not worth a second offline-sync path for).
This commit is contained in:
@@ -127,6 +127,9 @@ struct SettingsView: View {
|
||||
private var profileDetail: some View {
|
||||
VStack(alignment: .leading, spacing: 24) {
|
||||
sectionHeader
|
||||
if !isEffectivelyOnline {
|
||||
offlineSettingsHint
|
||||
}
|
||||
avatarRow
|
||||
Divider().frame(maxWidth: 420)
|
||||
nameRow
|
||||
@@ -184,6 +187,7 @@ struct SettingsView: View {
|
||||
ProgressView().controlSize(.small)
|
||||
}
|
||||
}
|
||||
.disabled(!isEffectivelyOnline)
|
||||
if let avatarErrorMessage {
|
||||
Text(avatarErrorMessage)
|
||||
.font(.caption)
|
||||
@@ -212,6 +216,7 @@ struct SettingsView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled(!isEffectivelyOnline)
|
||||
if let nameErrorMessage {
|
||||
Text(nameErrorMessage)
|
||||
.font(.caption)
|
||||
@@ -248,8 +253,13 @@ struct SettingsView: View {
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
if !isEffectivelyOnline {
|
||||
offlineSettingsHint
|
||||
}
|
||||
|
||||
preferencesSubsection("Display") {
|
||||
languageRow
|
||||
.disabled(!isEffectivelyOnline)
|
||||
Divider()
|
||||
appearanceRow
|
||||
Divider()
|
||||
@@ -259,6 +269,7 @@ struct SettingsView: View {
|
||||
isOn: session.userPreferences?.useCursorPointer ?? false,
|
||||
onChange: { newValue in Task { await savePreference { $0.useCursorPointer = newValue } } }
|
||||
)
|
||||
.disabled(!isEffectivelyOnline)
|
||||
Divider()
|
||||
preferenceToggleRow(
|
||||
"Show line numbers",
|
||||
@@ -266,6 +277,7 @@ struct SettingsView: View {
|
||||
isOn: session.userPreferences?.codeBlockLineNumbers ?? false,
|
||||
onChange: { newValue in Task { await savePreference { $0.codeBlockLineNumbers = newValue } } }
|
||||
)
|
||||
.disabled(!isEffectivelyOnline)
|
||||
Divider()
|
||||
preferenceToggleRow(
|
||||
"Show comment marker",
|
||||
@@ -273,6 +285,7 @@ struct SettingsView: View {
|
||||
isOn: session.userPreferences?.showCommentMarker ?? false,
|
||||
onChange: { newValue in Task { await savePreference { $0.showCommentMarker = newValue } } }
|
||||
)
|
||||
.disabled(!isEffectivelyOnline)
|
||||
}
|
||||
|
||||
preferencesSubsection("Behavior") {
|
||||
@@ -299,6 +312,7 @@ struct SettingsView: View {
|
||||
Divider()
|
||||
notificationBadgeRow
|
||||
}
|
||||
.disabled(!isEffectivelyOnline)
|
||||
|
||||
if let preferencesErrorMessage {
|
||||
Text(preferencesErrorMessage)
|
||||
@@ -309,6 +323,7 @@ struct SettingsView: View {
|
||||
preferencesSubsection("Danger") {
|
||||
deleteAccountRow
|
||||
}
|
||||
.disabled(!isEffectivelyOnline)
|
||||
}
|
||||
.frame(maxWidth: 480, alignment: .leading)
|
||||
.task { await refreshProfile() }
|
||||
@@ -778,6 +793,20 @@ struct SettingsView: View {
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
/// Everything backed by a live `users.update`/`users.notifications*`
|
||||
/// call (Profile's name/avatar, all of Preferences, all of
|
||||
/// Notifications) shows this and disables its controls while offline —
|
||||
/// there's nothing to optimistically apply here the way document edits
|
||||
/// can be, and no offline queue for it (see `TODO.local.md`'s own
|
||||
/// "things that actually require an internet connection" framing,
|
||||
/// already applied to Share/Permissions/Search). Local-only settings
|
||||
/// (Appearance, Offline Mode itself) are deliberately left enabled.
|
||||
private var offlineSettingsHint: some View {
|
||||
Text("You're offline — these settings need a connection to change.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.orange)
|
||||
}
|
||||
|
||||
private func labeledRow(_ label: String, _ value: String) -> some View {
|
||||
HStack {
|
||||
Text(label)
|
||||
|
||||
Reference in New Issue
Block a user