Skip to content

Commit

Permalink
major: package v3, duit_kernel v3 migration (#145)
Browse files Browse the repository at this point in the history
* Migrate to kernel v3 API

* Added re-export of kernel api, upd examples, export animation implementation parts, remove deprecations

* Prepare package to publish, edit readme and changelog, upd example app

* Upd example
  • Loading branch information
lesleysin authored Dec 3, 2024
1 parent b1f8ff2 commit ffec7a3
Show file tree
Hide file tree
Showing 45 changed files with 339 additions and 774 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## 3.0.0

- Migration to duit_kernel v3
- Removed deprecated features
- Removed DevMetrics feature (rework needed)
- Removed deprecated LayoutUpdate event handling
- Removed isolates support
- Improve library exports
- Update example app
- Action and events handling refactoring
- Re-exporting duit_kernel API as part of flutter_duit public API
- The Transform widget attribute type has been clarified

## 2.3.0

- Added RotatedBox widget
Expand Down
50 changes: 29 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,39 @@
# Duit - drived UI tooklit.

***Duit*** is a backend side UI framework for Flutter. It is used for creating widgets and server-side state management.
***Duit*** is a backend side UI framework for Flutter. It is used for creating widgets and
server-side state management.

The framework consists of several parts:

- Flutter package (this repository)
- [Go backend adapter](https://github.com/lesleysin/duit_go)
- [Node JS backend adapter](https://github.com/lesleysin/duit_js)

The framework ensures that the layout model is received from the server, interacts with the backend via the Action API, and embeds custom components into the widget hierarchy processing pipeline. Duit is flexible and extensible, which allows it to create rich UI dynamically.
The framework ensures that the layout model is received from the server, interacts with the backend
via the Action API, and embeds custom components into the widget hierarchy processing pipeline. Duit
is flexible and extensible, which allows it to create rich UI dynamically.

## Core features

- Initial connection to the server and receiving a layout
- Support for different [network protocols](https://github.com/lesleysin/flutter_duit/wiki/Networking) (http, websocket)
- Pointed widget state update (updating only those widgets for which the server returned an "update")
- Actions API. A special protocol that allows the server to specify dependencies for an action associated with a widget.
- Ability to add your own [custom widgets](https://github.com/lesleysin/flutter_duit/wiki/Adding-custom-widgets) on the Flutter and backend side.
- Support for
different [network protocols](https://github.com/lesleysin/flutter_duit/wiki/Networking) (http,
websocket)
- Pointed widget state update (updating only those widgets for which the server returned an "
update")
- Actions API. A special protocol that allows the server to specify dependencies for an action
associated with a widget.
- Ability to add your
own [custom widgets](https://github.com/lesleysin/flutter_duit/wiki/Adding-custom-widgets) on the
Flutter and backend side.

## Matching library and kernel versions

The flutter_duit library depends on the [duit_kernel](https://github.com/lesleysin/duit_kernel) package, which contains basic model definitions for implementing framework entities and developing third-party packages and extensions. Carefully study the version compatibility table if you are going to directly add duit_kernel to your project (needed to implement custom widgets and extensions).

The flutter_duit library depends on the [duit_kernel](https://github.com/lesleysin/duit_kernel)
package, which contains basic model definitions for implementing framework entities and developing
third-party packages and extensions. Carefully study the version compatibility table if you are
going to directly add duit_kernel to your project (needed to implement custom widgets and
extensions).

| Lib versions | Kernel versions |
|--------------|-----------------|
Expand All @@ -34,21 +46,14 @@ The flutter_duit library depends on the [duit_kernel](https://github.com/lesleys
| >= v2.0.0 | v2.0.1 |
| >= v2.2.0 | v2.1.1 |
| >= v2.3.0 | v2.1.3 |

| >= v3.0.0 | v3.0.0 |

## Usage example
0. If you want to use the advanced features of the framework, you should install a dependency on the duit_kernel package, which provides definitions of the basic abstractions on the basis of which custom widgets and third-party extensions are implemented.

```
flutter pub add duit_kernel
```

1. Create DuitDriver instance.

1. Create DuitDriver instance.


It is responsible for displaying the UI, updating the state of widgets, and calling widget-related actions.

It is responsible for displaying the UI, updating the state of widgets, and calling widget-related
actions.

```dart
Expand All @@ -67,17 +72,20 @@ final driver = DuitDriver(
DuitViewHost(
driver: driver,
placeholder: const CircularProgressIndicator(),
),
)
,
```

## Future plans

- Expanding the types of events generated by the server
- Expanding the widget collection
- Implementation of new network protocols (gRPC, socket.io)
- Adding new adapters for the backend (Dart, C#, etc.)
- Troubleshooting, updating documentation

## License
## License

MIT


Expand Down
2 changes: 1 addition & 1 deletion example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
Expand Down
14 changes: 10 additions & 4 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:duit_kernel/duit_kernel.dart';
import 'package:dio/dio.dart';
import 'package:example/src/custom/index.dart';
import 'package:flutter/material.dart';
import 'package:flutter_duit/flutter_duit.dart';

import 'src/custom/index.dart';

class CustomDecoder extends Converter<Uint8List, Map<String, dynamic>> {
@override
Map<String, dynamic> convert(Uint8List input) {
Expand Down Expand Up @@ -59,6 +58,13 @@ void main() async {
attributesFactory: exAttributeFactory,
);

final dio = Dio();

final res = await dio.get<List>("http://localhost:8999/components");

final comps = res.data!.cast<Map<String, dynamic>>();
await DuitRegistry.registerComponents(comps);

runApp(const MyApp());
}

Expand Down Expand Up @@ -90,7 +96,7 @@ class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
driver1 = DuitDriver(
"/some_endpoint",
"/example_screen",
transportOptions: HttpTransportOptions(
defaultHeaders: {
"Content-Type": "application/json",
Expand Down
31 changes: 24 additions & 7 deletions example/lib/src/custom/example/attributes.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
import 'package:duit_kernel/duit_kernel.dart';
import 'package:flutter_duit/flutter_duit.dart';

class ExampleCustomWidgetAttributes
final class ExampleCustomWidgetAttributes extends AnimatedPropertyOwner
implements DuitAttributes<ExampleCustomWidgetAttributes> {
String? random;
final String? random;

ExampleCustomWidgetAttributes({
required this.random,
required super.parentBuilderId,
required super.affectedProperties,
});

factory ExampleCustomWidgetAttributes.fromJson(Map<String, dynamic> json) {
final view = AnimatedPropHelper(json);

return ExampleCustomWidgetAttributes(
random: view["random"],
parentBuilderId: view.parentBuilderId,
affectedProperties: view.affectedProperties,
);
}

@override
ExampleCustomWidgetAttributes copyWith(other) {
return ExampleCustomWidgetAttributes(
random: other.random ?? random,
);
random: other.random ?? random,
parentBuilderId: other.parentBuilderId ?? parentBuilderId,
affectedProperties: other.affectedProperties ?? affectedProperties);
}

@override
Expand All @@ -21,7 +34,11 @@ class ExampleCustomWidgetAttributes
Iterable? positionalParams,
Map<String, dynamic>? namedParams,
}) {
// TODO: implement dispatchInternalCall
throw UnimplementedError();
return switch (methodName) {
"fromJson" =>
ExampleCustomWidgetAttributes.fromJson(positionalParams!.first)
as ReturnT,
String() => throw UnimplementedError("$methodName is not implemented"),
};
}
}
11 changes: 5 additions & 6 deletions example/lib/src/custom/example/factories.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import 'package:duit_kernel/duit_kernel.dart';
import 'package:example/src/custom/example/attributes.dart';
import 'package:example/src/custom/example/model.dart';
import 'package:example/src/custom/example/widget.dart';
import "package:flutter/material.dart";
import 'package:flutter_duit/flutter_duit.dart';

DuitAttributes exAttributeFactory(
String type,
Map<String, dynamic>? json,
) {
return ExampleCustomWidgetAttributes(random: json?["random"] ?? "no random")
as DuitAttributes;
return ExampleCustomWidgetAttributes.fromJson(json ?? {});
}

Widget exBuildFactory(
TreeElement model, [
ElementTreeEntry model, [
Iterable<Widget> subviews = const {},
]) {
final m = model as ExampleCustomWidget;
Expand All @@ -29,12 +28,12 @@ Widget exBuildFactory(
);
}

TreeElement exModelFactory(
ElementTreeEntry exModelFactory(
String id,
bool controlled,
ViewAttribute attributes,
UIElementController? controller, [
Iterable<TreeElement> subviews = const {},
Iterable<ElementTreeEntry> subviews = const {},
]) {
return ExampleCustomWidget(
id: id,
Expand Down
3 changes: 1 addition & 2 deletions example/lib/src/custom/example/widget.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import "package:duit_kernel/duit_kernel.dart";
import "package:flutter/material.dart";
import "package:flutter_duit/flutter_duit.dart";

Expand Down Expand Up @@ -44,4 +43,4 @@ class _ExampleWidgetState extends State<ExampleWidget>
),
);
}
}
}
22 changes: 19 additions & 3 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.8"
duit_kernel:
dio:
dependency: "direct main"
description:
name: dio
sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260"
url: "https://pub.dev"
source: hosted
version: "5.7.0"
dio_web_adapter:
dependency: transitive
description:
name: dio_web_adapter
sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
duit_kernel:
dependency: transitive
description:
name: duit_kernel
sha256: "80c2affe5fa0271c2fe17addbf5cd2f8d54f08596a370f6520bdf011744314af"
sha256: f813ecb708ceb114aa2757c121e7ba10275c73ea8d5233879d3b2f35c011a9bf
url: "https://pub.dev"
source: hosted
version: "2.1.3"
version: "3.0.0"
fake_async:
dependency: transitive
description:
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
duit_kernel: ^2.1.3
dio: ^5.7.0

dev_dependencies:
flutter_test:
Expand Down
17 changes: 9 additions & 8 deletions lib/flutter_duit.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
library flutter_duit;

export "./src/duit_impl/index.dart";
export "./src/ui/index.dart";
export "./src/transport/transport_type.dart";
export "./src/transport/options.dart";
export "./src/utils/index.dart"
export "package:flutter_duit/src/duit_impl/index.dart";
export "package:flutter_duit/src/ui/index.dart";
export "package:flutter_duit/src/transport/transport_type.dart";
export "package:flutter_duit/src/transport/options.dart";
export "package:flutter_duit/src/kernel_api/index.dart";
export "package:flutter_duit/src/animations/index.dart"
show AnimatedPropHelper, AnimatedAttributes;
export "package:flutter_duit/src/utils/index.dart"
hide
GestureInterceptionLogic,
AttributeParser,
Expand All @@ -25,6 +28,4 @@ export "./src/utils/index.dart"
ParseModelStartMessage,
ParseModelEndMessage,
RenderStartMessage,
RenderEndMessage,
DetachableController;
export './src/concurrency/index.dart' hide Worker;
RenderEndMessage;
11 changes: 0 additions & 11 deletions lib/src/animations/animated_props.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,6 @@ import 'package:flutter/material.dart';
import 'animation_context.dart';

mixin AnimatedAttributes on Widget {
@Deprecated("Will be removed in next major version")
T mergeWithController<T>(
BuildContext context,
UIElementController<T> controller,
) {
return mergeWithAttributes<T>(
context,
controller.attributes!.payload,
);
}

/// Merges the [attributes] with the animated properties in the [DuitAnimationContext].
T mergeWithAttributes<T>(
BuildContext context,
Expand Down
5 changes: 3 additions & 2 deletions lib/src/animations/animation_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class _DuitAnimationBuilderState extends State<DuitAnimationBuilder>
@override
void initState() {
widget.controller.listenCommand(_handleCommand);
final attrs = widget.controller.attributes!.payload;
final attrs = widget.controller.attributes.payload;
for (var animation in attrs.tweenDescriptions) {
final controller = AnimationController(
vsync: this,
Expand Down Expand Up @@ -200,7 +200,8 @@ class _DuitAnimationBuilderState extends State<DuitAnimationBuilder>

return DuitAnimationContext(
data: dataObj,
parentId: wC.attributes?.payload.persistentId ?? wC.id, //Priority use of persistentId
parentId: wC.attributes.payload.persistentId ?? wC.id,
//Priority use of persistentId
child: child ?? const SizedBox.shrink(),
);
},
Expand Down
6 changes: 5 additions & 1 deletion lib/src/animations/animation_command.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import 'index.dart';


/// A command that is sent to control an animation by interacting with an
/// animation controller identified by [controllerId]. The command specifies
/// the [method] to be executed, such as forward, reverse, repeat, or toggle,
/// on the animation controller. It also identifies the animated property key
/// using [animatedPropKey], which is affected by the animation.
final class AnimationCommand {
final String controllerId;
final AnimationMethod method;
Expand Down
1 change: 0 additions & 1 deletion lib/src/animations/animation_context.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import "package:flutter/material.dart";


class DuitAnimationContext extends InheritedWidget {
final Map<String, dynamic> data;
final String parentId;
Expand Down
Loading

0 comments on commit ffec7a3

Please sign in to comment.