We need some abstraction layer, to easily implement business logic without any interaction with generated files.
I have already a few ideas and I can contribute but firstly I would like to show what I am thinking about. And also I want to verify my ideas with other people opinion.
How to implement your own features
So let me begin with how will UI operate with custom code. Basically we would have Features abstract class in adobe_xd plugin. Its responsibility is to invoke custom code, provide UI data and return processed data to the view.
ViewDataGetter lambda which normally is reference to a method returning UI data.
OnData also reference to method from UI - it is invoked when processed data is changed.
Each UI generates its own Features for example Login Page would have features like this:
abstract class LoginFeatures extends Features<LoginData> {
void login();
LoginFeatures(ViewDataGetter getter): super(getter);
}
class LoginData {
final LoginState state;
LoginData(this.state);
}
The method login() was generated based on Tap Callback of a button from Adobe XD.
LoginData is also generated - I do not have clear view how it will look yet, but probably it will be based on parameters or some additional settings of a page.
And yours implementation would look like this:
As you can see we invoke setData() to provide UI some updates based on our features. Also as you can see, you can easily take data from view through viewData["email"]. Through viewData you can also provide BuildContext if needed for some context-based operations - also we might consider adding BuildContext to every method so it will be always context from specific place in widget tree. Something like this void login(BuildContext context).
How to Provide your own Features class
For providing and injecting implementation of Features class you can use FeaturesProvider - for now it is very simple, but we may think of something more complex like BlocProvider.
FeaturesProvider would be a part of adobe_xd plugin. It contains all implementations of Features and injects them to UI.
Usage of it would look like this (in main.dart file):
Argument features is just a Map<Type, Features>. Based on Type, Features implementation is injected in UI. Additional code that will be generated in UI (in this case XDLoginScreen) looks like this:
LoginFeatures features;
//here will be all fields from Data class
LoginState state;
@override
void initState() {
super.initState();
features = FeaturesProvider
.of(context)
.getFeatures(_getViewData);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
features.init(onData);
});
}
@override
void dispose() {
features.dispose();
super.dispose();
}
void onData(LoginData data) {
setState(() {
state = data.state;
});
}
Map<String, dynamic> _getViewData() {
return {
"login": _loginController.text,
"password": _passwordController.text
};
}
As you probably noticed - the generated view was changed to StatefulWidget. That allows us to properly initialize and operate on Features and update UI when onData is invoked.
The thing to be thought through is UI data providing. For now I used TextEdittingController but it is too case-specific. We may think about creating some DataHolder<TYPE> or something like this, so it will be more generic. Such DataHolder would be placed in components which can modify its data.
Summary
There might be some holes in this whole idea. But I am placing it here so we could polish the idea together and come up with some great solution. Maybe someone has more simple solution?
We need some abstraction layer, to easily implement business logic without any interaction with generated files.
I have already a few ideas and I can contribute but firstly I would like to show what I am thinking about. And also I want to verify my ideas with other people opinion.
How to implement your own features
So let me begin with how will UI operate with custom code. Basically we would have
Features
abstract class inadobe_xd
plugin. Its responsibility is to invoke custom code, provide UI data and return processed data to the view.So what we have here is:
ViewDataGetter
lambda which normally is reference to a method returning UI data.OnData
also reference to method from UI - it is invoked when processed data is changed.Each UI generates its own
Features
for example Login Page would have features like this:The method
login()
was generated based on Tap Callback of a button from Adobe XD.LoginData
is also generated - I do not have clear view how it will look yet, but probably it will be based on parameters or some additional settings of a page. And yours implementation would look like this:As you can see we invoke
setData()
to provide UI some updates based on our features. Also as you can see, you can easily take data from view throughviewData["email"]
. Through viewData you can also provide BuildContext if needed for some context-based operations - also we might consider adding BuildContext to every method so it will be always context from specific place in widget tree. Something like thisvoid login(BuildContext context)
.How to Provide your own Features class
For providing and injecting implementation of
Features
class you can useFeaturesProvider
- for now it is very simple, but we may think of something more complex like BlocProvider.FeaturesProvider
would be a part ofadobe_xd
plugin. It contains all implementations ofFeatures
and injects them to UI. Usage of it would look like this (in main.dart file):Argument
features
is just aMap<Type, Features>
. Based onType
,Features
implementation is injected in UI. Additional code that will be generated in UI (in this case XDLoginScreen) looks like this:As you probably noticed - the generated view was changed to StatefulWidget. That allows us to properly initialize and operate on
Features
and update UI whenonData
is invoked. The thing to be thought through is UI data providing. For now I used TextEdittingController but it is too case-specific. We may think about creating someDataHolder<TYPE>
or something like this, so it will be more generic. Such DataHolder would be placed in components which can modify its data.Summary
There might be some holes in this whole idea. But I am placing it here so we could polish the idea together and come up with some great solution. Maybe someone has more simple solution?