Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ResultDestination with sealed interface as result acting unpredictably #133

Closed
burntcookie90 opened this issue Apr 3, 2024 · 5 comments
Closed

Comments

@burntcookie90
Copy link

burntcookie90 commented Apr 3, 2024

I have the following destination/result setup:

  @Serializable
  data class AddItem(
    val listUrlLocator: ListUrlLocator,
  ) : ListDestinations, ResultDestination<AddItem.Created> {
    @Serializable
    data object Created
  }

  @Serializable
  data class EditItem(
    val listUrlLocator: ListUrlLocator,
    val itemUrlLocator: ItemUrlLocator,
  ) : ListDestinations, ResultDestination<EditItem.Result> {

    sealed interface Result {

      @Serializable
      data class Updated(
        val itemUrlLocator: ItemUrlLocator,
      ) : Result

      @Serializable
      data object Deleted : Result

      @Serializable
      data class Archived(val itemUrlLocator: ItemUrlLocator) : Result
    }
  }

and the effect side:

      ComposableResultEffect<ListDestinations.AddItem.Created>(
        navController = navController,
        block = {
          dispatch(ListDetailEvents.ItemAdded)
        },
      )

      ComposableResultEffect<ListDestinations.EditItem.Result>(
        navController = navController,
        block = {
          Timber.d("$it")
          when (it) {
            is ListDestinations.EditItem.Result.Updated -> {
              dispatch(ListDetailEvents.ItemUpdated(it.itemUrlLocator))
            }
            is ListDestinations.EditItem.Result.Deleted -> {
              dispatch(ListDetailEvents.ItemDeleted)
            }
            is ListDestinations.EditItem.Result.Archived -> {
              dispatch(ListDetailEvents.ItemArchived(it.itemUrlLocator))
            }
          }
        },
      )

Graph setup:

  addItem(
    onItemCreated = { listUrlLocator ->
      navController.setResult(ListDestinations.AddItem.Created)
      navController.popBackStack()
    },
  )

  editItem(
    onItemEdited = {
      navController.setResult(ListDestinations.EditItem.Result.Updated(it))
      navController.popBackStack()
    },
    onItemDeleted = {
      navController.setResult(ListDestinations.EditItem.Result.Deleted)
      navController.popBackStack()
    },
    onItemArchived = { listUrlLocator: ListUrlLocator, itemUrlLocator: ItemUrlLocator ->
      navController.setResult(ListDestinations.EditItem.Result.Archived(itemUrlLocator))
      navController.popBackStack()
    },
  )

The effect for ListDestinations.AddItem.Created fires without issue every time. The effect for ListDestinations.EditItem.Result sometimes fires, often times not. Unfortunately, attaching the debugger seems to make the effect consistently fire 😅. Not sure whats happening here.

@burntcookie90
Copy link
Author

Also just to confirm: I switched to using a non-sealed interface and just testing with the Updated result and its working as intended.

@burntcookie90
Copy link
Author

burntcookie90 commented Apr 3, 2024

Workaround for now seems to be:

  @Serializable
  data class EditItem(
    val listUrlLocator: ListUrlLocator,
    val itemUrlLocator: ItemUrlLocator,
  ) : ListDestinations, ResultDestination<EditItem.Result> {

    @Serializable
    data class Result(val operation: Operation) {
      @Serializable
      sealed class Operation {
      
        @Serializable
        data class Updated(val itemUrlLocator: ItemUrlLocator) : Operation()

        @Serializable
        data object Deleted : Operation()

        @Serializable
        data class Archived(val itemUrlLocator: ItemUrlLocator) : Operation()
      }
    }

    
  }

@hrach
Copy link
Collaborator

hrach commented Apr 3, 2024

That's the problem of KotlinX.Serialization and its limitation on polymorphism. There are two options:

A:

navController.setResult<ListDestinations.AddItem.Result>(ListDestinations.AddItem.Created)

or B:
you found it - #133 (comment) - which is probably the better way as it is less error-prone.

AFAIK: there are no solutions, I spent hours finding something.

@burntcookie90
Copy link
Author

maybe it would be worthwhile to add an example to the result sharing part of the readme? either way this can be closed :)

@hrach
Copy link
Collaborator

hrach commented Apr 3, 2024

#134

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants