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

Send custom data though Navigating back with a result #678

Closed
mohsen2986 opened this issue Sep 4, 2024 · 13 comments
Closed

Send custom data though Navigating back with a result #678

mohsen2986 opened this issue Sep 4, 2024 · 13 comments
Labels
feedback needed Extra attention is needed

Comments

@mohsen2986
Copy link

i got this issue
Argument type mismatch: actual type is 'com.mohsen.habito.Day', but 'java.nio.charset.Charset' was expected.
how i can solve it?
here is full error
Capture33

@raamcosta
Copy link
Owner

It's really difficult for me to understand the issue from this.
Let me know what you are trying to do and the code you're using to do it. Use formatted code instead of images surrounding code with the button <> you have here on Github.

Thanks

@raamcosta raamcosta added the feedback needed Extra attention is needed label Sep 5, 2024
@mohsen2986
Copy link
Author

Thanks for your attention
I'm trying rend result back though navigation
here is the screen that open dialogue

@Destination<RootGraph>
@Composable
fun AddTask(
    viewModel: MainViewModel ,
    navigator: DestinationsNavigator,
    resultRecipient: ResultRecipient<DialWithDialogExampleDestination, Day>,
){
    resultRecipient.onResult { resultValue ->
        println("got result $resultValue")
        Log.d("log" , "result $resultValue")
    }
    }

and here the dialogue implementation

@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>(style = DestinationStyle.Dialog.Default::class)
@Composable
fun DialWithDialogExample(
    resultNavigator: ResultBackNavigator<Day>
) {
    TimePickerDialog(
        onDismiss = {
            resultNavigator.navigateBack()
                    },
        onConfirm = {
            resultNavigator.navigateBack(result = Day("sd"))
        }
    ) {
        TimePicker(
            state = timePickerState,
        )
    }
}

and Day data class is here

@Serializable
data class Day(
    val dayName: String,
)

and my library versions is here

 implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1")
    implementation ("io.github.raamcosta.compose-destinations:core:2.0.0-beta11")
    ksp ("io.github.raamcosta.compose-destinations:ksp:2.0.0-beta11")

I'm confusing what I'm missed? Thanks in advance

@raamcosta
Copy link
Owner

Can you show me how the generated DayNavType looks like?

@mohsen2986
Copy link
Author

yes

import android.os.Bundle
import androidx.lifecycle.SavedStateHandle
import com.mohsen.habito.Task
import com.ramcosta.composedestinations.generated.navargs.ktxserializable.DefaultKtxSerializableNavTypeSerializer
import com.ramcosta.composedestinations.navargs.DestinationsNavType
import com.ramcosta.composedestinations.navargs.primitives.DECODED_NULL
import com.ramcosta.composedestinations.navargs.primitives.ENCODED_NULL
import com.ramcosta.composedestinations.navargs.utils.encodeForRoute
import kotlinx.serialization.ExperimentalSerializationApi

@OptIn(ExperimentalSerializationApi::class)
public val taskNavType: TaskNavType = TaskNavType(
    DefaultKtxSerializableNavTypeSerializer(Task.serializer())
)

@OptIn(ExperimentalSerializationApi::class)
public class TaskNavType(
    private val serializer: DefaultKtxSerializableNavTypeSerializer<Task>
) : DestinationsNavType<Task?>() {

    override fun get(bundle: Bundle, key: String): Task? =
        bundle.getByteArray(key)?.let { fromByteArray(it) }

    override fun put(bundle: Bundle, key: String, value: Task?) {
        bundle.putByteArray(key, value?.let { toByteArray(it) })
    }

    override fun parseValue(value: String): Task? {
        return if (value == DECODED_NULL) {
            null
        } else {
            serializer.fromRouteString(value)       
        }
    }

    override fun serializeValue(value: Task?): String {
        return if (value == null) {
            ENCODED_NULL
        } else {
            encodeForRoute(serializer.toRouteString(value))
        }
    }

    override fun get(savedStateHandle: SavedStateHandle, key: String): Task? {
        return savedStateHandle.get<ByteArray>(key)?.let { fromByteArray(it) }
    }
    
    override fun put(savedStateHandle: SavedStateHandle, key: String, value: Task?) {
        savedStateHandle[key] = value?.let { toByteArray(it) }
    }

    private fun fromByteArray(bytes: ByteArray): Task = serializer.fromByteArray(bytes)

    private fun toByteArray(value: Task): ByteArray = serializer.toByteArray(value)

}

@raamcosta
Copy link
Owner

This is TaskNavType, I wonder how DayNavType looks like :)

@raamcosta
Copy link
Owner

That's where the error is, looking at the first image with the errors you posted.

@mohsen2986
Copy link
Author

It doesn't matter which type it is !
It always shows the same error: DefaultKtxSerializableNavTypeSerializer not found.

Here is the generated code with Day class.

package com.ramcosta.composedestinations.generated.navtype

import android.os.Bundle
import androidx.lifecycle.SavedStateHandle
import com.mohsen.habito.model.Day
import com.ramcosta.composedestinations.generated.navargs.ktxserializable.DefaultKtxSerializableNavTypeSerializer
import com.ramcosta.composedestinations.navargs.DestinationsNavType
import com.ramcosta.composedestinations.navargs.primitives.DECODED_NULL
import com.ramcosta.composedestinations.navargs.primitives.ENCODED_NULL
import com.ramcosta.composedestinations.navargs.utils.encodeForRoute
import kotlinx.serialization.ExperimentalSerializationApi

@OptIn(ExperimentalSerializationApi::class)
public val dayNavType: DayNavType = DayNavType(
    DefaultKtxSerializableNavTypeSerializer(Day.serializer())
)

@OptIn(ExperimentalSerializationApi::class)
public class DayNavType(
    private val serializer: DefaultKtxSerializableNavTypeSerializer<Day>
) : DestinationsNavType<Day?>() {

    override fun get(bundle: Bundle, key: String): Day? =
        bundle.getByteArray(key)?.let { fromByteArray(it) }

    override fun put(bundle: Bundle, key: String, value: Day?) {
        bundle.putByteArray(key, value?.let { toByteArray(it) })
    }

    override fun parseValue(value: String): Day? {
        return if (value == DECODED_NULL) {
            null
        } else {
            serializer.fromRouteString(value)       
        }
    }

    override fun serializeValue(value: Day?): String {
        return if (value == null) {
            ENCODED_NULL
        } else {
            encodeForRoute(serializer.toRouteString(value))
        }
    }

    override fun get(savedStateHandle: SavedStateHandle, key: String): Day? {
        return savedStateHandle.get<ByteArray>(key)?.let { fromByteArray(it) }
    }
    
    override fun put(savedStateHandle: SavedStateHandle, key: String, value: Day?) {
        savedStateHandle[key] = value?.let { toByteArray(it) }
    }

    private fun fromByteArray(bytes: ByteArray): Day = serializer.fromByteArray(bytes)

    private fun toByteArray(value: Day): ByteArray = serializer.toByteArray(value)

}

and here is the IDE errors
image

@raamcosta
Copy link
Owner

What lib version are you using?

@raamcosta
Copy link
Owner

raamcosta commented Oct 17, 2024

Do you have any navigation arguments other than the ones you want to send back, that are Ktx Serializable?

I think I may know what’s the issue 🤔

@mohsen2986
Copy link
Author

What lib version are you using?

I'm using 2.1.0-beta12 version

@mohsen2986
Copy link
Author

Do you have any navigation arguments other than the ones you want to send back, that are Ktx Serializable?

I think I may know what’s the issue 🤔

Here is my implementation at the moment

@Serializable
data class Day(
    val dayName: String,
    val monthDayNumber: String,
    @Serializable(with = DateSerializer::class)
    val date: Date,
)

and my dialog is

@Destination<RootGraph>(style = DestinationStyle.Dialog.Default::class)
@Composable
fun DatePicker(
    viewModel: MainViewModel,
    resultBackNavigator: ResultBackNavigator<Day>,
    navigator: DestinationsNavigator,
) {
    DatePickerContent(
        viewModel::setTaskDateForAddTask,
        navigator,
    )
}

and here, I want to result back data

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AddTask(
    addTask: (Task) -> Unit,
    taskDate: String,
    taskTime: SelectedClockState,
    navigator: DestinationsNavigator,
    resultRecipient: ResultRecipient<DatePickerDestination, Day>,
) {
}

@raamcosta
Copy link
Owner

Should be fixed on latest version, please let me know!

and thanks for reporting! 🙏

@mohsen2986
Copy link
Author

I tested it, and it works!
Thank you for your attention.

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

No branches or pull requests

2 participants