Comments (29)
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.
@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.
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.
- Lot's of tests. Like twice as much as in previous message 🎉
todo_3
example showcasing the different versions of theWindowBehavior
is complete and workingtodo_4
example showcasing how to implement sorting on backend side has been added
For near future:
- Housekeeping
- Make id allocators a dependent types of Record/DataStore
- Update
book
side of data store
- Reordering records in the store view
- Remove records from the data store
from relm4.
@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.
Plans for near future (next week or two) in data-store repo:
- Remove unnecessarily restrictive limitations
- Get rid of single store-view for component limitation
- Figure a way to use standard Widgets or figure out a way to use
widget
macro. Now you must implement theWidget
like trait by hand to make it work.
- Houskeeping
- Cleanup names of traits and structures. Some of them are not longer what they are named after.
- Ease of use. Make use more straightforward. Currently there are traits you must implement only cos of history of development.
- Sorting (and filtering)
from relm4.
Update on the current status of the data-store repo
I consider housekeeping phase done
- Using data-store is much simpler now
Widgets
andwidgets
macro now can be used again.- Cleanup went further then I expected. In terms of internals it's almost a rewrite instead of update.
-
Is not reporting any issues. Tons of rustdoc added inside of the code.
#![warn( missing_debug_implementations, missing_docs, rust_2018_idioms, unreachable_pub )]
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.
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.
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 aDummyBackend
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.
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.
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.
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.
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
from relm4.
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.
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:
- 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.
- 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 anupdate_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. - 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.
Goals
My short term goal is to make state management easier for sufficiently big application
From my experience with Relm4
it boils down to
- Efficiently manage business model in the application as far from widgets/components as sanely possible
- 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].
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
-
I don't think it's solution.
-
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.
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.
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.
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.
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.
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.
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.
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.
Here is the tracking issue until 0.1.0-beta.2
from relm4.
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.
Thanks for reading. I've created a ticket to discuss documentation issues mskorkowski/relm4-store#22
from relm4.
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.
That's a great idea
from relm4.
Sounds good! Reordering, sorting and darg/drop without glib would be huge, actually!
from relm4.
Closing this as duplicate of #102
from relm4.
Related Issues (20)
- Why does `SimpleComponent` take in `&Self::Root`, but `SimpleAsyncComponent` takes in `Self::Root`?
- Add async traits into `relm4::prelude` HOT 1
- macOS typical functionality HOT 1
- `menu_actions_and_settings` example crashes on macOS 14.1 ARM HOT 2
- Sync position of adw::TabPages in adw::TabView and FactoryVecDeque HOT 1
- Increase flexibility of `Alert` component HOT 2
- Unable to clone model fields in `view!` macro HOT 6
- Add option to not capture panics HOT 6
- Spinner doesn't spin in async app HOT 1
- Consider making `set_global_css` a method
- `if let` support in `view!` macro
- Documentation: Keyboard Events HOT 2
- `transient_for` errors in child component HOT 2
- Missing Trait Implementations for `FlowBox` and Potential Conflicts HOT 2
- Resizeable and expandable columns with TypedColumnView HOT 2
- Replace `this` with `model` in factory
- Support `match` at the top root of the widget
- Make #[local_ref] support expressions
- Just tested, weird behavior HOT 1
- OpenDialog : how to select file in root of disk HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from relm4.