Files
simplex-chat/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift
Evgeny Poberezkin f5eea018d9 ios: chat themes and wallpapers (#4376)
* ios: wallpapers (#4304)

* ios: wallpapers

* theme selection

* applied theme colors and preset wallpaper

* more places with background

* one more

* accent color

* defaults

* rename

* background

* no change to cell color

* unneeded

* changes

* no global tint

* defaults

* removed unneeded class

* for merging

* ios: wallpapers types (#4325)

* types and api

* divided types per target

* creating directory for wallpapers

* creating wallpaper dir at launch

* ios: wallpapers appearance (#4335)

* appearance

* changes

* refactor

* scale

* lambda to function

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>

* ios: wallpapers user/chat overrides (#4345)

* ios: wallpapers user/chat overrides

* chat overrides

* color picker updates colors correctly

* fix state update

* labels

* background for light theme

* small optimization

* removed commented code

* ios: enhancements to wallpapers (#4361)

* ios: enhancements to wallpapers

* colors for background

* ios: wallpapers import/export (#4362)

* ios: wallpapers import/export

* comment

* ios: wallpapers theme updates (#4365)

* ios: wallpapers theme updates

* group member background

* colors

* profile picture colors

* unneeded

* optimizations, images, state fixes

* fixes

* no editing of title color

* rename Menus and alerts, refactor

* tint applying fix

* fixes

* migration of accent and themes

* fix updating system theme

* migration changes

* limiting color range

* ios: wallpapers rename enum (#4384)

* ios: wallpapers rename enum2 (#4385)

* ios: wallpapers rename enum2

* change

* colors were commented

* fix build and look

---------

Co-authored-by: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com>
2024-07-03 22:42:13 +01:00

149 lines
6.2 KiB
Swift

//
// ContactPreferencesView.swift
// SimpleX (iOS)
//
// Created by Evgeny on 13/11/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct ContactPreferencesView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@EnvironmentObject var chatModel: ChatModel
@EnvironmentObject var theme: AppTheme
@Binding var contact: Contact
@State var featuresAllowed: ContactFeaturesAllowed
@State var currentFeaturesAllowed: ContactFeaturesAllowed
@State private var showSaveDialogue = false
var body: some View {
let user: User = chatModel.currentUser!
VStack {
List {
timedMessagesFeatureSection()
featureSection(.fullDelete, user.fullPreferences.fullDelete.allow, contact.mergedPreferences.fullDelete, $featuresAllowed.fullDelete)
featureSection(.reactions, user.fullPreferences.reactions.allow, contact.mergedPreferences.reactions, $featuresAllowed.reactions)
featureSection(.voice, user.fullPreferences.voice.allow, contact.mergedPreferences.voice, $featuresAllowed.voice)
featureSection(.calls, user.fullPreferences.calls.allow, contact.mergedPreferences.calls, $featuresAllowed.calls)
Section {
Button("Reset") { featuresAllowed = currentFeaturesAllowed }
Button("Save and notify contact") { savePreferences() }
}
.disabled(currentFeaturesAllowed == featuresAllowed)
}
}
.modifier(BackButton(disabled: Binding.constant(false)) {
if currentFeaturesAllowed == featuresAllowed {
dismiss()
} else {
showSaveDialogue = true
}
})
.confirmationDialog("Save preferences?", isPresented: $showSaveDialogue) {
Button("Save and notify contact") {
savePreferences()
dismiss()
}
Button("Exit without saving") { dismiss() }
}
}
private func featureSection(_ feature: ChatFeature, _ userDefault: FeatureAllowed, _ pref: ContactUserPreference<SimplePreference>, _ allowFeature: Binding<ContactFeatureAllowed>) -> some View {
let enabled = FeatureEnabled.enabled(
asymmetric: feature.asymmetric,
user: SimplePreference(allow: allowFeature.wrappedValue.allowed),
contact: pref.contactPreference
)
return Section {
Picker("You allow", selection: allowFeature) {
ForEach(ContactFeatureAllowed.values(userDefault)) { allow in
Text(allow.text)
}
}
.frame(height: 36)
infoRow("Contact allows", pref.contactPreference.allow.text)
}
header: { featureHeader(feature, enabled).foregroundColor(theme.colors.secondary) }
footer: { featureFooter(feature, enabled).foregroundColor(theme.colors.secondary) }
}
private func timedMessagesFeatureSection() -> some View {
let pref = contact.mergedPreferences.timedMessages
let enabled = FeatureEnabled.enabled(
asymmetric: ChatFeature.timedMessages.asymmetric,
user: TimedMessagesPreference(allow: featuresAllowed.timedMessagesAllowed ? .yes : .no),
contact: pref.contactPreference
)
return Section {
Toggle("You allow", isOn: $featuresAllowed.timedMessagesAllowed)
.onChange(of: featuresAllowed.timedMessagesAllowed) { allow in
if allow {
if featuresAllowed.timedMessagesTTL == nil {
featuresAllowed.timedMessagesTTL = 86400
}
} else {
featuresAllowed.timedMessagesTTL = currentFeaturesAllowed.timedMessagesTTL
}
}
infoRow("Contact allows", pref.contactPreference.allow.text)
if featuresAllowed.timedMessagesAllowed {
DropdownCustomTimePicker(
selection: $featuresAllowed.timedMessagesTTL,
label: "Delete after",
dropdownValues: TimedMessagesPreference.ttlValues,
customPickerConfirmButtonText: "Select",
customPickerDescription: "Delete after"
)
.frame(height: 36)
} else if pref.contactPreference.allow == .yes || pref.contactPreference.allow == .always {
infoRow("Delete after", timeText(pref.contactPreference.ttl))
}
}
header: { featureHeader(.timedMessages, enabled).foregroundColor(theme.colors.secondary) }
footer: { featureFooter(.timedMessages, enabled).foregroundColor(theme.colors.secondary) }
}
private func featureHeader(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> some View {
HStack {
Image(systemName: feature.iconFilled)
.foregroundColor(enabled.forUser ? .green : enabled.forContact ? .yellow : .red)
Text(feature.text)
}
}
private func featureFooter(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> some View {
Text(feature.enabledDescription(enabled))
}
private func savePreferences() {
Task {
do {
let prefs = contactFeaturesAllowedToPrefs(featuresAllowed)
if let toContact = try await apiSetContactPrefs(contactId: contact.contactId, preferences: prefs) {
await MainActor.run {
contact = toContact
chatModel.updateContact(toContact)
currentFeaturesAllowed = featuresAllowed
}
}
} catch {
logger.error("ContactPreferencesView apiSetContactPrefs error: \(responseError(error))")
}
}
}
}
struct ContactPreferencesView_Previews: PreviewProvider {
static var previews: some View {
ContactPreferencesView(
contact: Binding.constant(Contact.sampleData),
featuresAllowed: ContactFeaturesAllowed.sampleData,
currentFeaturesAllowed: ContactFeaturesAllowed.sampleData
)
}
}