slint-ui / slint

Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
https://slint.dev
Other
16.93k stars 568 forks source link

Re-used components in the repeater with stale state #2598

Closed ogoffart closed 11 months ago

ogoffart commented 1 year ago

Step to reproduce with the todo example:

  1. open the todo example, ie https://slint-ui.com/demos/todo/
  2. Check "Test the application"
  3. check "Hide Done Items" (not remove)
  4. Observe that "profit" is checked.

What happens is that the "hide done items" will replace the model with another model (the FilterModel) This should normally reset all items.

But since https://github.com/slint-ui/slint/pull/1954 we re-use the items, and the checkbox was manually checked, breaking existing bindings. So we re-use a component that has a broken binding.

Discussion in https://chat.slint-ui.com/public/pl/m6mwp1f3q3d3by6rp81zw3utqy

We need to either re-create each component (revert #1954). Or perhaps we can get away by calling init again, this would probably fix that particular issue since it would re-create bindings and reset non-defaulted property. But there are still some state that wouldn't be reset.

ogoffart commented 11 months ago

This was repoorted in #3711 again. This is IMHO quite a bad bug and should be fixed. @tronical any objection reveting #1954 ?

tronical commented 11 months ago

I agree that's a bad bug. I guess we have to revert it. The primary motivation for the re-use was to avoid that init() is called a number of times that doesn't make sense:

export Demo := Window {
    height: 300px;
    width: 300px;
    property <int> creation-count: 0;
    property <bool> open: false;

    VerticalLayout {
        Text {
            text: creation-count;
        }
        if open: Rectangle {
            background: green;
            init => { creation-count += 1; }
        }
    }

    TouchArea {
        clicked => {
            open = !open;
        }
    }
}

If you click once, init is called twice. I find it hard to explain that behavior, but perhaps the fix for that is something else?

qarmin commented 11 months ago

Not sure if this is the same bug, because happens without replacing model, but this cause that it is almost impossible to use listview since it breaks in random moments and I don't know how to prevent this situations - slintpad example

Simple selection logic(looks that logic works fine):

https://github.com/slint-ui/slint/assets/41945903/0ec3e706-bde7-4962-a27a-159492ac8ac9

This works fine at start, but begin to select invalid rows, when I scroll even a little list. After deselecting all elements and going to top, everything starts to work again