Git Product home page Git Product logo

Comments (8)

chrisbanes avatar chrisbanes commented on April 20, 2024

I was initially thinking that we could change the internal loading logic to add a debounce on the Loading state, but the more I think about this, the more than feels like a UI thing.

The way I'm thinking about this is that we wrap the 'loading' content with something like this:

@Composable
fun WithDelay(
    delayMs: Long,
    content: @Composable () -> Unit
) {
    var visible by remember { mutableStateOf(false) }

    LaunchedEffect(Unit) {
        delay(delayMs)
        visible = true
    }

    if (visible) content()
}

You can then do:

CoilImage(
    // ...
    loading = {
        // choose whatever delay works, 500ms is a good initial value
        WithDelay(500) {
            Text("Loading...")
        }
    }
)

This matches the behavior of ContentLoadingProgressBar and feels right to me.

I haven't decided whether to bake this into the 'simple' CoilImage etc yet. I don't really want to add yet-another-parameter to control the delay, and the integration is pretty simple to do in clients.

from accompanist.

Bradleycorn avatar Bradleycorn commented on April 20, 2024

I wired that up, and it certainly works. Though for the scenario I described, you'd want to to use withDelay in the Empty state instead of the Loading state. it's a flash of the Empty state that I'm trying to eliminate. But, it could be useful in the Loading state as well. In cases where the image gets loaded fast, you could prevent a "flash" of the Loading state composable.

That also lends to the idea of NOT adding the delay as a parameter on the simple CoilImage composable. Different use cases might require delays on different states. As you mentioned, it's simple to wire up. It took me 2 minutes, and I even had to roll my own withDelay composable. If a client wants/needs a delay on a certain state, it's easy to setup.

from accompanist.

chrisbanes avatar chrisbanes commented on April 20, 2024

Ahhh, I misread the scenario 🤔

This makes me think that the Empty state is actually useless, since we always transition to Loading after the first composition + layout. The thrashing has no benefit.

One thought is to merge those into a single Pending state.

from accompanist.

Bradleycorn avatar Bradleycorn commented on April 20, 2024

yeah, when I looked at it originally, I kind of wondered if you could just initialize it in the Loading state. Merging the two might do the trick. One thing the Empty state IS useful for is supplying a drawable resource to use for @Preview composables in Android Studio. That's what led me down this rabbit hole in the first place. It might be useful to keep the Empty state around, but only use it in a case where the data parameter is null or otherwise empty.

from accompanist.

chrisbanes avatar chrisbanes commented on April 20, 2024

Thanks for the info! I think starting from Loading is the simplest solution, and we'll treat Empty as a 'result'/end state instead.

Can you attach an example of what you're doing for @Previews? I think we can fix that separately rather than relying on Empty.

from accompanist.

Bradleycorn avatar Bradleycorn commented on April 20, 2024

As a learning effort, I'm building a pretty basic app to consume a feed from a blog that I read and show posts, very similar to the JetNews sample app. The top post in the list on the home screen is "featured" and shows an image. My Composable for the top post looks like this:

@Composable
fun FeaturedPost(post: Post) {
    Column {
        PostImage(post.imageUrl)
        PostItem(post)
    }
}

@Composable
fun PostImage(url: String, modifier: Modifier = Modifier.fillMaxWidth().aspectRatio(1.78F)) {
    CoilImage(
        data = url,
        modifier = modifier) { imageState ->
        when (imageState) {
            is ImageLoadState.Success -> {
                MaterialLoadingImage(
                    result = imageState,
                    fadeInEnabled = true,
                    fadeInDurationMs = 600,
                    contentScale = ContentScale.Crop
                )
            }
            is sImageLoadState.Empty -> {
                //  Use this image in the Preview in Android Studio
                Image(asset = vectorResource(id = R.drawable.ic_uk_logo),
                    modifier = Modifier.fillMaxSize().padding(16.dp),
                    contentScale = ContentScale.Fit)
            }
        }
    }
}

The Post model (instances of which are created from the response of an API call) contains several fields, one of them being an image url:

data class Post(url: String, imageUrl: String, title: String, content: String) // etc, etc

To Preview a featured post, I create a mock Post, and call the FeaturedPost composable:

@Preview("Featured Post")
@Composable
fun PreviewPost() {
    val post = Post(
        url = "postUrl",
        image = "https://kentuckysportsradio.com/wp-content/uploads/2018/09/MSU-8843.jpg",
        title = "Featured Post Title",
        description = "The post preview is a a short description of the content that is in the main post",
        author = "Brad Ball",
        postDate = Date().time,
        content = "Main post content")

    ThemedPreview() {
        FeaturedPost(post)
    }
}

from accompanist.

chrisbanes avatar chrisbanes commented on April 20, 2024

Thanks! Yeah, I think we can do better here when in preview.

from accompanist.

chrisbanes avatar chrisbanes commented on April 20, 2024

Opened #150 for this.

from accompanist.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.