Open
Description
I have the NewGameViewModel in commonMain Shared code of KMM.
interface NewGameIntents {
fun updateUserName(userName: String)
fun startNewGameButtonTapped()
fun newGameCreated(newGameID: String)
fun newGameCreationFailed()
}
sealed interface NewGameActions {
data class CreateNewGameAction(val userName: String): NewGameActions
data class GoToMainScreenAction(val gameID: String, val userName: String) : NewGameActions
}
class NewGameViewModel: BaseViewModel(), NewGameIntents {
private val _actions = Channel<NewGameActions>()
val actions: CFlow<NewGameActions> get() = _actions.receiveAsFlow().cFlow()
private val _userName: CMutableStateFlow<String> = MutableStateFlow("").cMutableStateFlow()
val userName: CStateFlow<String> = _userName.cStateFlow()
init {
val previousName = SettingsHelper().lastGameName ?: SettingsHelper().userName
previousName?.let {
updateUserName(it)
}
}
override fun updateUserName(userName: String) {
_userName.value = userName
}
override fun startNewGameButtonTapped() {
updateUserName(_userName.value.trim())
createNewGame()
}
override fun newGameCreated(newGameID: String) {
showLoading(false)
viewModelScope.launch {
_actions.send(NewGameActions.GoToMainScreenAction(newGameID, _userName.value))
}
}
override fun newGameCreationFailed() {
showLoading(false)
showErrorAlert()
}
private fun createNewGame() {
showLoading(true)
viewModelScope.launch {
_actions.send(NewGameActions.CreateNewGameAction(_userName.value))
}
}
}
I have also the NewGameScreen in iOS:
struct NewGameScreen: View {
@ObservedObject var newGameViewModel: NewGameViewModel = NewGameViewModel()
var body: some View {
ScrollView {
VStack(spacing: 0) {
CustomTextField(
value: newGameViewModel.state(\.userName),
label: getKmmString(stringResource: \.your_name),
onTextChange: { text in
newGameViewModel.updateUserName(userName: text)
}
)
Spacer().frame(height: 32)
CustomButton(
text: getKmmString(stringResource: \.start_game),
onClick: {
newGameViewModel.startNewGameButtonTapped()
}
)
}
.padding(16)
}
.navigationBarBackButtonHidden(true)
.onReceive(createPublisher(newGameViewModel.actions)) { action in
handleNewGameAction(action: action)
}
}
private func handleNewGameAction(action: NewGameActions) {
switch action {
case let action as NewGameActionsCreateNewGameAction: do {
let newGameMap = getMapFromFunction(name: action.userName) // Create map here
var documentReference: DocumentReference? = nil
documentReference = Firestore.firestore()
.collection(Game.companion.COLLECTION_GAMES)
.addDocument(data: newGameMap) { error in
if let error {
newGameViewModel.doNewGameCreationFailed()
} else if let documentId = documentReference?.documentID, !documentId.isEmpty {
newGameViewModel.doNewGameCreated(newGameID: documentId)
} else {
newGameViewModel.doNewGameCreationFailed()
}
}
}
case let action as NewGameActionsGoToMainScreenAction: do {
closeScreen()
PalermoHelper().goToMainGameScreen(gameID: action.gameID, name: action.userName)
}
default: return
}
}
}
When I tap the button, startNewGameButtonTapped() function of viewModel is called and then the action CreateNewGameAction should be handled by iOS.
Sometimes it works and sometimes not. Maybe it is a lifecycle issue, but I am not sure and I do not know how to solve it. Do you have any ideas?
Metadata
Metadata
Assignees
Labels
No labels