Code Monkey home page Code Monkey logo

Comments (29)

AaronErhardt avatar AaronErhardt commented on May 13, 2024 2

Sounds great! I'm reading this while I'm in the train so I will follow up with a more complete answer later.

One thing that comes to my mind when it comes to syncing up UI stuff is property bindings. For example, if you bind the active property of an toggle button to a revealer, GLib will handle the rest. But that's just part of the solution I think.

Also, I've been thinking about adding a concept I call "micro components". This would be about small components that live in their parents model, can be modified from their parents model but at the same time have their own widgets and update function. This would reduce the hierarchy issues I think and also makes components more flexible.

I really hope we can come up with a good solution for this problem :)

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 2

@AaronErhardt cargo run --package=relm4-store-examples --example todo_2_single_scroll is an example where using store and view you can scroll across 10 000 000 records without any gobject. It was even easier then I thought.

MicroComponent looks promising. Only thing I can say now is let's try it

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 2

I'm alive again. So here is a bunch of news for data store.

Sorting got merged into the main branch of the data store repo.

  1. Lot's of tests. Like twice as much as in previous message 🎉
  2. todo_3 example showcasing the different versions of the WindowBehavior is complete and working
  3. todo_4 example showcasing how to implement sorting on backend side has been added

For near future:

  1. Housekeeping
    • Make id allocators a dependent types of Record/DataStore
    • Update book side of data store
  2. Reordering records in the store view
  3. Remove records from the data store

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024 1

@mskorkowski I'm glad to hear of your latest progress.

Regarding MicroComponents, I don't have any real code yet but in my previous comment I tried to write down the API and some of the internals of how I think a MicroComponent could work. The only thing left to do is to copy the normal component code and adapt it for MicroComponents. One of the differences will be that only Rc<RefCell<Model>> is moved into the message handler closure so that the model can still be modified from outside. Also the initialisation and traits will be simpler.

Currently, I don't have a lot of time I can spend for Relm4 so any help will be appreciated. You can always ask if something's unclear and if I find some time this weekend I can help with the implementation.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 1

Plans for near future (next week or two) in data-store repo:

  1. Remove unnecessarily restrictive limitations
    1. Get rid of single store-view for component limitation
    2. Figure a way to use standard Widgets or figure out a way to use widget macro. Now you must implement the Widget like trait by hand to make it work.
  2. Houskeeping
    1. Cleanup names of traits and structures. Some of them are not longer what they are named after.
    2. Ease of use. Make use more straightforward. Currently there are traits you must implement only cos of history of development.
  3. Sorting (and filtering)

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 1

Update on the current status of the data-store repo

I consider housekeeping phase done

  • Using data-store is much simpler now
  • Widgets and widgets macro now can be used again.
  • Cleanup went further then I expected. In terms of internals it's almost a rewrite instead of update.
  • #![warn(
        missing_debug_implementations,
        missing_docs,
        rust_2018_idioms,
        unreachable_pub
    )]
    
    Is not reporting any issues. Tons of rustdoc added inside of the code.
  • Pagination component now handles total page count properly

Summary of differences between relm4 and relm4-store component code

relm4-store relm4
StoreViewComponent: custom component type which knows how to work around all the state updates in presence of the store-view Component
FactoryConfiguration: To make a store view/store view component behave. It's like a merge of FactoryPrototype and ComponentUpdate. FactoryPrototype + ComponentUpdate
StoreViewInnerComponent: Extra trait extending relm4::Components required by the StoreViewComponent. It allows to send messages to the components in case store was updated. N/A
StoreViewContainerWidget: Extra trait extending relm4::Widgets required by the StoreViewComponent. It returns the reference to the widget to which factory will add the widgets. relm4 doesn't need it. Factory implementation can work it out in all cases

Next steps

Currently I'm redesigning sorting and filtering. Main issue is how std::cmp::Ord is defined which makes it hard to implement multiple sorting methods for single type. I have some ideas how to abuse Ord to make it work, but it still requires a solid amount of work to make it user friendly.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 1

Changes last week on the sorting branch

  • There is sorted in memory backend ready for small amounts of data relm4_store_backend_inmemory::SortedInMemoryBackend. (I wouldn't use it above 10k records)
  • Some fixes to the store view to make is usable with sorted data store (under construction still, if you run example todo_3 it might panic in some corner cases)

This week an maybe next I won't have much time to continue working on the data store so no plans for near future

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 1

I've manage to find a bit of time this weekend and I've started writing unit tests

  • I've added DummyBackend. It's another data store implementation. It's just extra dumb and any state changes must be provided manually. Makes a great tool for testing
  • StoreViewImplementation got moved to separate package so it can use a DummyBackend in tests.
  • I've added notes about the testing code using gtk/glib in book/appending/testing/README.md.

All of it is part of the sorting branch

@AaronErhardt I've seen that you released new beta versions for 0.4. I've started updating the code to use new components. Can you explain the parent! macro and what should happen in the connect_parent method? I would like to update the StoreViewComponent and code around it to follow the relm4 as close as possible (or ditch it if possible)

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024 1

The way components are initialized changed with Relm4 0.4. This was done to better suit some GTK and libadwaita APIs where widgets are returned by widget assignment functions (see gtk::Stack for example). In Relm4 0.2, the model and the widgets were initialized from the main app to the outermost components (therefore the component! macro and the connect_components function to connect the components because they were initialized after their parent).

Now, this is exactly the opposite for the widgets. They are now initialized from the outermost components to the main app. This means that now the components are already initialized when their parent initializes its widgets but the components have to wait to access the parent widgets. Therefore there's now the parent! macro and the connect_parent method.

It's basically the same as before, only that components now don't need any special macro to work, but instead accessing the parent widgets need some special code. And in case you don't use the parent widgets you can just leave the connect_parent method empty.

I really hope this doesn't break anything for you. One reason I've published this beta early was for you to test it against your implementation so we can quickly find any regression and fix them if possible.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 1

I'm still working on housekeeping

  • Big ease of use improvements. Almost all if not all Rc<RefCell<>> got removed from user side code
  • book folder become real mdbook

There are still bugs all around of the place related to the improvements so don't stare at the housekeeping branch code too much

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 1

This weekend the lib got into useful state with records removal example working

🍾 relm4-store 0.1.0-beta.1 has been released on crates.io
🍾 relm4-store book can be found at https://mskorkowski.github.io/relm4-store/beta/book/index.html

Any comments on the code/book/whatever else are highly welcomed

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 1

Version 0.1-beta.2 just got released

Now I'm going to focus on rewriting documentation to make it easier to understand. Any pointers about which parts are missing, or hard to understand, or completely wrong, or anything else documentation related is highly welcome

Documentation issue

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024 1

It's long time since I've posted last update. For a last three weeks I'm working on the reordering of the records in the store/store view. This feature is much bigger then I originally expected.

Initial work on the reordering was done alongside of sorting. Current implementation will take it from being a small consequence of the update of the record to be a feature by itself. In the future it will be the base for drag/drop operations on the list.

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024

First of all, I'm open for any change in Relm4 that makes sense in general and helps you with your project. However, I'm not very familiar with what you're trying to archive so you need to tell me whether my ideas are actually solving your problems. You can of course tell me your ideas, too, and I can tell you if they fit into Relm4.

Regarding Issue 1 I have a few ideas:

  1. Implementing the Widgets trait for the same model twice would be an option. Then you could have the same data with two views. That'd probably require some changes to Relm4 and wouldn't be very flexible if you're data isn't always available in the same struct.
  2. I already mentioned "micro components". In this case two micro components would have to share state (using Rc<RefCell<Data>> which usually works fine). If micro components then had an update_view() method, you wouldn't even need to send a message but could just call that method.
    For this a tracker that supports multiple views would also be interesting for efficient UI updates.
  3. GLib is an option as well. But wrapping your Rust data structures in a GObject is not very nice IMO. However you will need GObjects if you're trying to create efficient large lists because Relm4 can't be integrated that deeply into GTK without using GObjects itself.

Let me know what you think about my suggestions :)

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

Goals

My short term goal is to make state management easier for sufficiently big application

From my experience with Relm4 it boils down to

  1. Efficiently manage business model in the application as far from widgets/components as sanely possible
  2. Make business model state changes propagation as painless as possible

Bonus point's for making it work for super fast for big datasets if data source (point 1) is implemented properly [1].

List of long term goals

Where I am

relm4-store repo is what I have stripped out from my app and made generic enough. I'm pushing the boundaries of what can be done with relm4 and it's more of research how to do it then having a precise target. Any solution that removes painful points works for me.

Amount of code which I have created in my app which is fairly similar and can be generalized upon is the driver for relm4-store effort but definitely my app is not the owner for the relm4-store code base. If we discover that some changes are required to make relm4-store work better which goes against my app. Sucks to be me, I need to update my app to follow.
I'm sure I will rewrite my app a few times while making it maintainable.

Because I have my app I know where it's painful when I develop. I'm willing to invest my time to solve them. If you have any task in the relm4 you would like to see done for it link an issue here and I'll try to implement it.

Proposals for solution

  1. I don't think it's solution.

  2. I'm willing to bet that with slight updates to current store view (prepending is not implemented) I can make efficient list with tons of records with pure rust/relm4 without binding to GObject.

About point 2

Is your idea along the lines

store-view becomes merge of factory and micro-component so whenever it receives the data it can trigger self.update_view()? I think it's worth to try. Is there any work you need a help with in relm4 to make it happen?

My plan for a next few days

Have POC for point 3 with goal of copy of example todo_2 work with single scroll to access all of the data like in the simple todo example from gtk book.

Annotations

[1] just yesterday I've pushed updates to the relm4-store repo which makes example todo_2 work fast with huge datasets. I've tested it up to 10000000 records.

Postscript

@AaronErhardt if you wish to play with a code I can give you write access to the relm4-store repo.

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024

Sounds awesome. If you manage to implement a store that's efficient and doesn't require GObjects that'd be a huge win for Relm4 :)

Still I'm wondering how to help you because I'm not sure how exactly you want the store to work internally. Currently, I don't have the time to analyze the code you've wrote so far so I think communication is key here. You tell me what you want (which you already did with the ToDo example etc.) and I can make suggestions that you need to analyze for your problems.

That said, most parts of Relm4 are actually quite simple and you can always implement or change stuff.

Anyway, to make my idea more tangible, I've written down some Rust-like code that represents the concept of "micro-components". Micro-components are "loose" so they need the parent to attach the root widget to its widgets. They don't need to store a clone of their parents sender but have a "data" field that holds (currently immutable) data that can be used to store senders and other stuff according to the needs of the user (to make them more flexible). They can easily be modified by their parent component and also handle messages. The view function can be called manually by using update_view(). Of course there are some possible panics but they should be easy to debug and the only other option to RefCell would be unsafe code.

What do you think? Would that make things easier for you? Is there a use-case that isn't properly covered?

struct MicroComponent<Model: MicroModel> {
    model: Rc<RefCell<Model>>,
    widgets: Rc<RefCell<Model::Widgets>>,
    data: Mode::Data, // for additional data such as senders to other components
    sender: Sender<Model::Msg>,
}

impl<Model: MicroModel> MicroComponent<Model> {
    fn new(model: Model, data: Model::Data) -> Self { ... }
    fn update_view(&self) { ... }
    fn model(&self) -> &Model { ... }
    fn model_mut(&self) -> &mut Model { ... }
    fn widgets(&self) -> &Model::Widgets { ... }
    fn send(&self, msg: Model::Msg) { ... }
    fn sender(&self) -> Sender<Model::Msg> { ... }
}

trait MicroModel {
    type Msg;
    type Widgets: MicroWidgets<Self>;
    type Data;
    
    fn update(&mut self, msg: Self::Msg, data: &Data, sender: Sender<Self::Msg>);
}

trait MicroWidgets<Model: MicroModel> {
    type Root;
    
    fn init_view(&mut self, model: &Model, sender: Sender<Mode::Msg>) -> Self;
    fn view(&mut self, model: &Model, sender: Sender<Mode::Msg>);
    fn root_widget(&self) -> Self::Root;
}

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

I've more or less finalized the way you can define a behavior of the store view in presence of the new data. I also wrote a bunch of docs which can be found in book directory. It should talk a lot about the how stuff works.

My next target would be sorting but to make it I would love to solve the issue with events. If there would be requirement to do a rework of internals related to this ticket after sorting it would become a huge task.

Sorting is about internal data representation both in the data store (less) and in the view a lot. The way data are kept in the view affects the speed a lot.

So @AaronErhardt is there anything I can do to help with MicroComponents? I don't even know where to start with it. If you have even a half baked implementation lying somewhere on your disk it would be great. I need something I need to hook on.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

Micro components still had an issue of chicken and the egg. So I've ended up writing my own component based on that. Now I'm polishing the new approach and rewriting the existing examples

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

Store behaves more like a component and store view works like a factory. So I don't see any reason to make it broken with new architecture. I can run all examples fine since I've never used parent widgets in my code.

Only work I see is to update the StoreViewComponent to follow the new rules, which should be trivial.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

First thing first: Happy New Year 🎉

I've managed to remove all bugs I was aware of. What happens next depends on #63

API is rather stable and nice now so either #63 will move us towards release or I'll complete the book side of the store and add proper handling for removing the records and moving the records.

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024

Happy new year!

That's great news! I wouldn't make this dependent on #63 but rather release this as soon as you're ready. I think releasing a beta would be great to make it easier for others to test the code and to give feedback.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

It's not going to be more ready any time soon. I'm currently closing simple lists. After that is filtering and single view sorting which itself will probably take another 2-3 months at least and that's just beginning really. Since it's always bad time to release it's always equally good time to do it.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

Here is the tracking issue until 0.1.0-beta.2

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024

Today I finally had some time to read through the book (at least the simple to-do example). Overall you did an excellent job. After all, relm4-store is much more that a factory and factories are already quite complex internally.

I only felt like the book is a bit hard to understand.
Maybe the concept would be easier to understand if you take a database (that needs an unique ID for entries) as metaphor 🤔

In any case, great work! I will try to discover the other examples in the book over the next few days.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

Thanks for reading. I've created a ticket to discuss documentation issues mskorkowski/relm4-store#22

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024

Do you want to announce the release in the Relm4 matrix room? I think this might be interesting for some people in the room.

from relm4.

mskorkowski avatar mskorkowski commented on May 13, 2024

That's a great idea

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024

Sounds good! Reordering, sorting and darg/drop without glib would be huge, actually!

from relm4.

AaronErhardt avatar AaronErhardt commented on May 13, 2024

Closing this as duplicate of #102

from relm4.

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.