Files
letro-ios/ElementX/Sources/Screens/EmojiPickerScreen/EmojiPickerScreenViewModel.swift
Stefan Ceriu 7eda122d20 Fix various flakey unit tests (#1783)
* Fix flakey emoji provider tests

* Fix flakey RoomScreenViewModel tests

* Fix flakey HomeScreenViewModel tests

* Fix flakey RoomMemberListScreen tests, problem with bindings getting overriden and deferFulfillment cancellable not getting stored

* Fix flakey RoomNotificationSettingsScreen tests and crashes

* Fix flakey RoomMemberDetailsScreen tests

* Deprecate old `deferFulfillment` and `nextViewState` methods

* Convert more files to the new `deferFulfillment`

* Converted the rest of the tests to the new deferFulfillment

* Removed now unused `nextViewState` and `deferFulfillment`

* Remove automatic retries from unit tests

* Reset analytics flag after running unit tests

* Address PR comments

* Introduce a new `deferFulfillment(publisher, keyPath, transitionValues)` method and use it where appropiate
2023-09-26 13:28:29 +03:00

75 lines
2.7 KiB
Swift

//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Combine
import SwiftUI
typealias EmojiPickerScreenViewModelType = StateStoreViewModel<EmojiPickerScreenViewState, EmojiPickerScreenViewAction>
class EmojiPickerScreenViewModel: EmojiPickerScreenViewModelType, EmojiPickerScreenViewModelProtocol {
private var actionsSubject: PassthroughSubject<EmojiPickerScreenViewModelAction, Never> = .init()
var actions: AnyPublisher<EmojiPickerScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
private let emojiProvider: EmojiProviderProtocol
init(emojiProvider: EmojiProviderProtocol) {
let initialViewState = EmojiPickerScreenViewState(categories: [])
self.emojiProvider = emojiProvider
super.init(initialViewState: initialViewState)
loadEmojis()
}
// MARK: - Public
override func process(viewAction: EmojiPickerScreenViewAction) {
switch viewAction {
case let .search(searchString: searchString):
Task {
let categories = await emojiProvider.categories(searchString: searchString)
state.categories = convert(emojiCategories: categories)
}
case let .emojiTapped(emoji: emoji):
actionsSubject.send(.emojiSelected(emoji: emoji.value))
case .dismiss:
actionsSubject.send(.dismiss)
}
}
// MARK: - Private
private func loadEmojis() {
Task(priority: .userInitiated) { [weak self] in
guard let self else { return }
let categories = await self.emojiProvider.categories(searchString: nil)
self.state.categories = convert(emojiCategories: categories)
}
}
private func convert(emojiCategories: [EmojiCategory]) -> [EmojiPickerEmojiCategoryViewData] {
emojiCategories.compactMap { emojiCategory in
let emojisViewData: [EmojiPickerEmojiViewData] = emojiCategory.emojis.compactMap { emojiItem in
EmojiPickerEmojiViewData(id: emojiItem.id, value: emojiItem.unicode)
}
return EmojiPickerEmojiCategoryViewData(id: emojiCategory.id, emojis: emojisViewData)
}
}
}