mirror of
https://github.com/lux-tel/session-ios.git
synced 2026-10-30 20:38:32 +00:00
209 lines
8.8 KiB
Swift
209 lines
8.8 KiB
Swift
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
import Foundation
|
|
import GRDB
|
|
import DifferenceKit
|
|
import SessionUIKit
|
|
import SessionMessagingKit
|
|
import SessionUtilitiesKit
|
|
|
|
class ConversationSettingsViewModel: SessionTableViewModel, NavigatableStateHolder, ObservableTableSource {
|
|
typealias TableItem = Section
|
|
|
|
public let dependencies: Dependencies
|
|
public let navigatableState: NavigatableState = NavigatableState()
|
|
public let state: TableDataState<Section, TableItem> = TableDataState()
|
|
public let observableState: ObservableTableSourceState<Section, TableItem> = ObservableTableSourceState()
|
|
|
|
/// This value is the current state of the view
|
|
@MainActor @Published private(set) var internalState: State
|
|
private var observationTask: Task<Void, Never>?
|
|
|
|
// MARK: - Initialization
|
|
|
|
@MainActor init(using dependencies: Dependencies) {
|
|
self.dependencies = dependencies
|
|
self.internalState = State.initialState()
|
|
|
|
bindState()
|
|
}
|
|
|
|
// MARK: - Section
|
|
|
|
public enum Section: SessionTableSection {
|
|
case messageTrimming
|
|
case audioMessages
|
|
case blockedContacts
|
|
|
|
var title: String? {
|
|
switch self {
|
|
case .messageTrimming: return "conversationsMessageTrimming".localized()
|
|
case .audioMessages: return "conversationsAudioMessages".localized()
|
|
case .blockedContacts: return "conversationsBlockedContacts".localized()
|
|
}
|
|
}
|
|
|
|
var style: SessionTableSectionStyle { .titleRoundedContent }
|
|
}
|
|
|
|
// MARK: - Content
|
|
|
|
public struct State: ObservableKeyProvider {
|
|
let trimOpenGroupMessagesOlderThanSixMonths: Bool
|
|
let shouldAutoPlayConsecutiveAudioMessages: Bool
|
|
|
|
@MainActor public func sections(viewModel: ConversationSettingsViewModel, previousState: State) -> [SectionModel] {
|
|
ConversationSettingsViewModel.sections(
|
|
state: self,
|
|
previousState: previousState,
|
|
viewModel: viewModel
|
|
)
|
|
}
|
|
|
|
public let observedKeys: Set<ObservableKey> = [
|
|
.setting(.trimOpenGroupMessagesOlderThanSixMonths),
|
|
.setting(.shouldAutoPlayConsecutiveAudioMessages)
|
|
]
|
|
|
|
static func initialState() -> State {
|
|
return State(
|
|
trimOpenGroupMessagesOlderThanSixMonths: false,
|
|
shouldAutoPlayConsecutiveAudioMessages: false
|
|
)
|
|
}
|
|
}
|
|
|
|
let title: String = "sessionConversations".localized()
|
|
|
|
@MainActor private func bindState() {
|
|
observationTask = ObservationBuilder
|
|
.initialValue(self.internalState)
|
|
.debounce(for: .never)
|
|
.using(dependencies: dependencies)
|
|
.query(ConversationSettingsViewModel.queryState)
|
|
.assign { [weak self] updatedState in
|
|
guard let self = self else { return }
|
|
|
|
// FIXME: To slightly reduce the size of the changes this new observation mechanism is currently wired into the old SessionTableViewController observation mechanism, we should refactor it so everything uses the new mechanism
|
|
let oldState: State = self.internalState
|
|
self.internalState = updatedState
|
|
self.pendingTableDataSubject.send(updatedState.sections(viewModel: self, previousState: oldState))
|
|
}
|
|
}
|
|
|
|
@Sendable private static func queryState(
|
|
previousState: State,
|
|
events: [ObservedEvent],
|
|
isInitialQuery: Bool,
|
|
using dependencies: Dependencies
|
|
) async -> State {
|
|
var trimOpenGroupMessagesOlderThanSixMonths: Bool = previousState.trimOpenGroupMessagesOlderThanSixMonths
|
|
var shouldAutoPlayConsecutiveAudioMessages: Bool = previousState.shouldAutoPlayConsecutiveAudioMessages
|
|
|
|
if isInitialQuery {
|
|
dependencies.mutate(cache: .libSession) { libSession in
|
|
trimOpenGroupMessagesOlderThanSixMonths = libSession.get(.trimOpenGroupMessagesOlderThanSixMonths)
|
|
shouldAutoPlayConsecutiveAudioMessages = libSession.get(.shouldAutoPlayConsecutiveAudioMessages)
|
|
}
|
|
}
|
|
|
|
/// Process any event changes
|
|
events.forEach { event in
|
|
guard let updatedValue: Bool = event.value as? Bool else { return }
|
|
|
|
switch event.key {
|
|
case .setting(.trimOpenGroupMessagesOlderThanSixMonths):
|
|
trimOpenGroupMessagesOlderThanSixMonths = updatedValue
|
|
|
|
case .setting(.shouldAutoPlayConsecutiveAudioMessages):
|
|
shouldAutoPlayConsecutiveAudioMessages = updatedValue
|
|
|
|
default: break
|
|
}
|
|
}
|
|
|
|
/// Generate the new state
|
|
return State(
|
|
trimOpenGroupMessagesOlderThanSixMonths: trimOpenGroupMessagesOlderThanSixMonths,
|
|
shouldAutoPlayConsecutiveAudioMessages: shouldAutoPlayConsecutiveAudioMessages
|
|
)
|
|
}
|
|
|
|
private static func sections(
|
|
state: State,
|
|
previousState: State,
|
|
viewModel: ConversationSettingsViewModel
|
|
) -> [SectionModel] {
|
|
return [
|
|
SectionModel(
|
|
model: .messageTrimming,
|
|
elements: [
|
|
SessionCell.Info(
|
|
id: .messageTrimming,
|
|
title: "conversationsMessageTrimmingTrimCommunities".localized(),
|
|
subtitle: "conversationsMessageTrimmingTrimCommunitiesDescription".localized(),
|
|
trailingAccessory: .toggle(
|
|
state.trimOpenGroupMessagesOlderThanSixMonths,
|
|
oldValue: previousState.trimOpenGroupMessagesOlderThanSixMonths,
|
|
accessibility: Accessibility(
|
|
identifier: "Trim Communities - Switch"
|
|
)
|
|
),
|
|
onTap: { [dependencies = viewModel.dependencies] in
|
|
dependencies.setAsync(
|
|
.trimOpenGroupMessagesOlderThanSixMonths,
|
|
!state.trimOpenGroupMessagesOlderThanSixMonths
|
|
)
|
|
}
|
|
)
|
|
]
|
|
),
|
|
SectionModel(
|
|
model: .audioMessages,
|
|
elements: [
|
|
SessionCell.Info(
|
|
id: .audioMessages,
|
|
title: "conversationsAutoplayAudioMessage".localized(),
|
|
subtitle: "conversationsAutoplayAudioMessageDescription".localized(),
|
|
trailingAccessory: .toggle(
|
|
state.shouldAutoPlayConsecutiveAudioMessages,
|
|
oldValue: previousState.shouldAutoPlayConsecutiveAudioMessages,
|
|
accessibility: Accessibility(
|
|
identifier: "Autoplay Audio Messages - Switch"
|
|
)
|
|
),
|
|
onTap: { [dependencies = viewModel.dependencies] in
|
|
dependencies.setAsync(
|
|
.shouldAutoPlayConsecutiveAudioMessages,
|
|
!state.shouldAutoPlayConsecutiveAudioMessages
|
|
)
|
|
}
|
|
)
|
|
]
|
|
),
|
|
SectionModel(
|
|
model: .blockedContacts,
|
|
elements: [
|
|
SessionCell.Info(
|
|
id: .blockedContacts,
|
|
title: "conversationsBlockedContacts".localized(),
|
|
subtitle: "blockedContactsManageDescription".localized(),
|
|
trailingAccessory: .icon(
|
|
.chevronRight,
|
|
pinEdges: [.right]
|
|
),
|
|
accessibility: Accessibility(
|
|
identifier: "Block contacts - Navigation"
|
|
),
|
|
onTap: { [weak viewModel, dependencies = viewModel.dependencies] in
|
|
viewModel?.transitionToScreen(
|
|
SessionTableViewController(viewModel: BlockedContactsViewModel(using: dependencies))
|
|
)
|
|
}
|
|
)
|
|
]
|
|
)
|
|
]
|
|
}
|
|
}
|