global conditions hack

This commit is contained in:
spaced4ndy
2024-10-30 14:53:15 +04:00
parent 764d231332
commit 5b21db31e6
4 changed files with 133 additions and 56 deletions
+26
View File
@@ -193,6 +193,8 @@ final class ChatModel: ObservableObject {
@Published var draft: ComposeState?
@Published var draftChatId: String?
@Published var networkInfo = UserNetworkInfo(networkType: .other, online: true)
// server operators
@Published var serverOperators: [ServerOperator] = [ServerOperator.sampleData1, ServerOperator.sampleData2, ServerOperator.sampleData3]
var messageDelivery: Dictionary<Int64, () -> Void> = [:]
@@ -239,6 +241,30 @@ final class ChatModel: ObservableObject {
}
}
var operatorsWithConditionsAccepted: [ServerOperator] {
serverOperators.filter { $0.conditionsAcceptance.conditionsAccepted }
}
var enabledOperatorsWithConditionsNotAccepted: [ServerOperator] {
serverOperators.filter { $0.enabled && !$0.conditionsAcceptance.conditionsAccepted }
}
func acceptConditionsForEnabledOperators(_ date: Date) {
for (i, serverOperator) in serverOperators.enumerated() {
if serverOperator.enabled && !serverOperator.conditionsAcceptance.conditionsAccepted {
var updatedOperator = serverOperator
updatedOperator.conditionsAcceptance = .accepted(date: date)
serverOperators[i] = updatedOperator
}
}
}
func updateServerOperator(_ updatedOperator: ServerOperator) {
if let i = serverOperators.firstIndex(where: { $0.operatorId == updatedOperator.operatorId }) {
serverOperators[i] = updatedOperator
}
}
func hasChat(_ id: String) -> Bool {
chats.first(where: { $0.id == id }) != nil
}
@@ -33,14 +33,14 @@ struct OperatorView: View {
Section {
infoViewLink()
useOperatorToggle()
if serverOperatorToEdit.enabled || serverOperatorToEdit.latestConditionsAcceptance.conditionsAccepted {
if serverOperatorToEdit.enabled || serverOperatorToEdit.conditionsAcceptance.conditionsAccepted {
viewConditionsButton()
}
} header: {
Text("Operator")
.foregroundColor(theme.colors.secondary)
} footer: {
switch (serverOperatorToEdit.latestConditionsAcceptance) {
switch (serverOperatorToEdit.conditionsAcceptance) {
case let .accepted(date):
Text("Conditions accepted on: \(conditionsTimestamp(date)).")
case let .reviewAvailable(deadline):
@@ -70,6 +70,7 @@ struct OperatorView: View {
}
.modifier(BackButton(disabled: Binding.constant(false)) {
serverOperator = serverOperatorToEdit
ChatModel.shared.updateServerOperator(serverOperatorToEdit)
dismiss()
})
.onAppear {
@@ -108,24 +109,35 @@ struct OperatorView: View {
if useOperatorToggleReset {
useOperatorToggleReset = false
} else if useOperatorToggle {
if serverOperatorToEdit.latestConditionsAcceptance.usageAllowed {
switch serverOperatorToEdit.conditionsAcceptance {
case .accepted:
serverOperatorToEdit.enabled = true
} else {
ChatModel.shared.updateServerOperator(serverOperatorToEdit)
case .reviewAvailable:
if !ChatModel.shared.operatorsWithConditionsAccepted.isEmpty {
showConditionsSheet = true
} else {
serverOperatorToEdit.enabled = true
ChatModel.shared.updateServerOperator(serverOperatorToEdit)
}
case .reviewRequired:
showConditionsSheet = true
}
} else {
serverOperatorToEdit.enabled = false
ChatModel.shared.updateServerOperator(serverOperatorToEdit)
}
}
}
private func onUseToggleSheetDismissed() {
if useOperator {
if case .reviewRequired = serverOperatorToEdit.latestConditionsAcceptance {
if useOperator && !serverOperatorToEdit.enabled {
if case .reviewRequired = serverOperatorToEdit.conditionsAcceptance {
useOperatorToggleReset = true
useOperator = false
} else if serverOperatorToEdit.latestConditionsAcceptance.conditionsAccepted {
} else if serverOperatorToEdit.conditionsAcceptance.conditionsAccepted {
serverOperatorToEdit.enabled = true
ChatModel.shared.updateServerOperator(serverOperatorToEdit)
}
}
}
@@ -134,7 +146,7 @@ struct OperatorView: View {
Button {
showConditionsSheet = true
} label: {
if case .accepted = serverOperatorToEdit.latestConditionsAcceptance {
if case .accepted = serverOperatorToEdit.conditionsAcceptance {
Text("Conditions accepted")
} else {
Text("Review conditions")
@@ -250,6 +262,7 @@ struct UsageConditionsView: View {
@EnvironmentObject var theme: AppTheme
@Binding var serverOperator: ServerOperator
@State var serverOperatorToEdit: ServerOperator
@State private var conditionsExpanded: Bool = false
let conditionsText = """
Lorem ipsum odor amet, consectetuer adipiscing elit. Blandit mauris massa tempor ac; maximus accumsan magnis. Sollicitudin maximus tempor luctus sociosqu turpis dictum per imperdiet porttitor. Efficitur mattis fusce curae id efficitur. Non bibendum elementum faucibus vehicula morbi pulvinar. Accumsan habitant tincidunt sollicitudin taciti ad urna potenti velit. Primis laoreet pharetra magnis est dolor proin viverra.
@@ -265,54 +278,100 @@ struct UsageConditionsView: View {
var body: some View {
VStack(alignment: .leading, spacing: 20) {
Text("Use operator \(serverOperator.name)")
.font(.largeTitle)
.bold()
.padding(.horizontal)
.padding(.top)
.padding(.top)
if !serverOperator.latestConditionsAcceptance.conditionsAccepted {
Text("In order to use operator \(serverOperator.name), accept conditions of use.")
.foregroundColor(theme.colors.secondary)
.padding(.horizontal)
}
ScrollView {
Text(conditionsText)
.padding()
}
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(Color(uiColor: .secondarySystemGroupedBackground))
)
.padding(.horizontal)
Group {
if case let .accepted(date) = serverOperator.latestConditionsAcceptance {
Text("Use operator \(serverOperator.name)")
.font(.largeTitle)
.bold()
.padding(.top)
.padding(.top)
let operatorsWithConditionsAccepted = ChatModel.shared.operatorsWithConditionsAccepted
if case let .accepted(date) = serverOperator.conditionsAcceptance {
conditionsTextView()
Text("Conditions accepted on: \(conditionsTimestamp(date)).")
.foregroundColor(theme.colors.secondary)
} else {
HStack {
Spacer()
.padding(.bottom)
} else if !operatorsWithConditionsAccepted.isEmpty {
Text("You already accepted conditions of use for following operator(s): \(operatorsWithConditionsAccepted.map { $0.name }.joined(separator: ", ")).")
Text("Same conditions will apply to operator \(serverOperator.name).")
conditionsAppliedToOtherOperatorsText()
if !conditionsExpanded {
Button {
// Should call api to save state here, not when saving all servers
// (It's counterintuitive to lose to closed sheet or Reset)
serverOperatorToEdit.latestConditionsAcceptance = .accepted(date: Date.now)
serverOperator = serverOperatorToEdit
dismiss()
conditionsExpanded = true
} label: {
Text("Accept conditions")
Text("View conditions")
}
.buttonStyle(.borderedProminent)
Spacer()
} else {
conditionsTextView()
}
acceptConditionsButton()
.padding(.bottom)
} else {
Text("In order to use operator \(serverOperator.name), accept conditions of use.")
conditionsAppliedToOtherOperatorsText()
conditionsTextView()
acceptConditionsButton()
.padding(.bottom)
}
}
.padding(.horizontal)
.padding(.bottom)
}
.frame(maxHeight: .infinity)
}
private func conditionsTextView() -> some View {
ScrollView {
Text(conditionsText)
.padding()
}
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(Color(uiColor: .secondarySystemGroupedBackground))
)
}
@ViewBuilder private func conditionsAppliedToOtherOperatorsText() -> some View {
let otherEnabledOperators = ChatModel.shared.enabledOperatorsWithConditionsNotAccepted.filter { $0.operatorId != serverOperator.operatorId }
if !otherEnabledOperators.isEmpty {
Text("Conditions will also apply for following operator(s) you use: \(otherEnabledOperators.map { $0.name }.joined(separator: ", ")).")
}
}
private func acceptConditionsButton() -> some View {
HStack {
Spacer()
Button {
// Should call api to save state here, not when saving all servers
// (It's counterintuitive to lose to closed sheet or Reset)
let date = Date.now
ChatModel.shared.acceptConditionsForEnabledOperators(date)
serverOperatorToEdit.conditionsAcceptance = .accepted(date: date)
serverOperator = serverOperatorToEdit
dismiss()
} label: {
Text("Accept conditions")
}
.buttonStyle(.borderedProminent)
Spacer()
}
}
}
@@ -158,10 +158,10 @@ struct ProtocolServersView: View {
}
}
.onAppear {
serverOperators = ChatModel.shared.serverOperators
// this condition is needed to prevent re-setting the servers when exiting single server view
if justOpened {
do {
serverOperators = [ServerOperator.sampleData1, ServerOperator.sampleData2, ServerOperator.sampleData3]
let r = try getUserProtoServers(serverProtocol)
currServers = r.protoServers
presetServers = r.presetServers
+4 -12
View File
@@ -1236,21 +1236,13 @@ public enum UsageConditionsAcceptance: Decodable, Hashable {
case .reviewRequired: false
}
}
public var usageAllowed: Bool {
switch self {
case .accepted: true
case .reviewAvailable: true
case .reviewRequired: false
}
}
}
public struct ServerOperator: Identifiable, Decodable {
public var operatorId: Int64
public var name: String
public var tag: OperatorTag
public var latestConditionsAcceptance: UsageConditionsAcceptance
public var conditionsAcceptance: UsageConditionsAcceptance
public var enabled: Bool
public var roles: ServerRoles
@@ -1264,7 +1256,7 @@ public struct ServerOperator: Identifiable, Decodable {
operatorId: 1,
name: "SimpleX Chat",
tag: .simplex,
latestConditionsAcceptance: .reviewAvailable(deadline: Date.distantFuture),
conditionsAcceptance: .reviewAvailable(deadline: Date.distantFuture),
enabled: true,
roles: ServerRoles(storage: true, proxy: true)
)
@@ -1273,7 +1265,7 @@ public struct ServerOperator: Identifiable, Decodable {
operatorId: 2,
name: "XYZ",
tag: .xyz,
latestConditionsAcceptance: .reviewRequired,
conditionsAcceptance: .reviewRequired,
enabled: false,
roles: ServerRoles(storage: true, proxy: true)
)
@@ -1282,7 +1274,7 @@ public struct ServerOperator: Identifiable, Decodable {
operatorId: 3,
name: "Demo",
tag: .demo,
latestConditionsAcceptance: .reviewRequired,
conditionsAcceptance: .reviewRequired,
enabled: false,
roles: ServerRoles(storage: true, proxy: true)
)