Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ migrate_working_dir/
.flutter-plugins
.flutter-plugins-dependencies
build/
bin
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Changelog

## 0.0.1

* TODO: Describe initial release.
### Added

- Basic framework for Server-Driven UI implementation
- Support for rendering UI from server-provided definitions
- gRPC integration with Protocol Buffers
- Core widget support (Text, Column, Row, Container, etc.)
- Example application demonstrating gRPC usage
- Setup scripts for Protocol Buffer compilation
313 changes: 291 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,328 @@
<a href="https://dscvit.com">
<img width="400" src="https://user-images.githubusercontent.com/56252312/159312411-58410727-3933-4224-b43e-4e9b627838a3.png#gh-light-mode-only" alt="GDSC VIT"/>
</a>
<h2 align="center"> < Insert Project Title Here > </h2>
<h4 align="center"> < Insert Project Description Here > <h4>
<h2 align="center">Flutter SDUI Package</h2>
<h4 align="center">A Flutter package for implementing Server-Driven UI with both JSON and gRPC support<h4>
</p>

---
[![Join Us](https://img.shields.io/badge/Join%20Us-Developer%20Student%20Clubs-red)](https://dsc.community.dev/vellore-institute-of-technology/)
[![Discord Chat](https://img.shields.io/discord/760928671698649098.svg)](https://discord.gg/498KVdSKWR)
[![DOCS](https://img.shields.io/badge/Documentation-see%20docs-green?style=flat-square&logo=appveyor)](docs/grpc_support.md)
[![UI ](https://img.shields.io/badge/Flutter-SDK-blue?style=flat-square&logo=flutter)](https://flutter.dev)

[![DOCS](https://img.shields.io/badge/Documentation-see%20docs-green?style=flat-square&logo=appveyor)](INSERT_LINK_FOR_DOCS_HERE)
[![UI ](https://img.shields.io/badge/User%20Interface-Link%20to%20UI-orange?style=flat-square&logo=appveyor)](INSERT_UI_LINK_HERE)
A powerful Flutter package for implementing Server-Driven UI (SDUI) with both JSON and gRPC support.

## What is SDUI?

Server-Driven UI is an architectural pattern where the UI layout and content definitions come from a backend server rather than being hardcoded in the client application. This approach enables:

- Dynamic UI updates without app store releases
- A/B testing and feature flagging at the UI level
- Consistent UI across platforms
- Faster iteration cycles for UI changes

## Features
- [ ] < feature >
- [ ] < feature >
- [ ] < feature >
- [ ] < feature >

<br>
- [x] Render UI dynamically from server-provided definitions
- [x] Support for essential Flutter widgets (Text, Column, Row, Container, etc.)
- [x] JSON parsing for server responses
- [x] gRPC support for efficient, type-safe communication
- [x] Protocol Buffers for structured data exchange
- [x] Easy-to-use client API
- [x] Customizable error handling and loading states

## Dependencies
- < dependency >
- < dependency >
## Installation

Add the package to your `pubspec.yaml`:

```yaml
dependencies:
flutter_sdui: ^0.0.1
```

## Running
```yaml
# For devs
dependencies:
flutter_sdui:
path: path/to/flutter_sdui
```

Or use the Flutter CLI:

< directions to install >
```bash
< insert code >
flutter pub add flutter_sdui
```

Import the package in your Dart code:

```dart
import 'package:flutter_sdui/flutter_sdui.dart';
```

## Basic Usage

This package provides two approaches for implementing server-driven UI:

### 1. Using gRPC (Recommended)

For efficient, type-safe server communication:

```dart
// Create a gRPC client
final client = SduiGrpcClient(
host: 'your-server.com',
port: 50051,
);

// Use the SduiGrpcRenderer widget
SduiGrpcRenderer(
client: client,
screenId: 'home_screen',
loadingWidget: CircularProgressIndicator(),
errorBuilder: (context, error) => Text('Error: $error'),
)
```

### 2. Using JSON

For simpler implementation with standard HTTP requests (coming soon).

## Example

Here's a complete example of using the gRPC renderer:

```dart
import 'package:flutter/material.dart';
import 'package:flutter_sdui/flutter_sdui.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SDUI Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const SDUIDemo(),
);
}
}

class SDUIDemo extends StatefulWidget {
const SDUIDemo({super.key});

@override
State<SDUIDemo> createState() => _SDUIDemoState();
}

class _SDUIDemoState extends State<SDUIDemo> {
late SduiGrpcClient _grpcClient;
String _screenId = 'home';

@override
void initState() {
super.initState();
_grpcClient = SduiGrpcClient(
host: 'localhost', // Replace with your server address
port: 50051, // Replace with your server port
);
}

@override
void dispose() {
_grpcClient.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Server-Driven UI Demo'),
),
body: SduiGrpcRenderer(
client: _grpcClient,
screenId: _screenId,
loadingWidget: const Center(
child: CircularProgressIndicator(),
),
errorBuilder: (context, error) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.error, color: Colors.red, size: 48),
SizedBox(height: 16),
Text('Error: $error'),
SizedBox(height: 16),
ElevatedButton(
onPressed: () => setState(() {}),
child: Text('Retry'),
),
],
),
);
},
),
);
}
}
```

< directions to execute >
## Server Implementation

### Setting Up a gRPC Server

Here's a basic example of a Dart server that provides UI definitions via gRPC:

```dart
import 'package:grpc/grpc.dart';
import 'package:flutter_sdui/src/generated/sdui.pb.dart';
import 'package:flutter_sdui/src/generated/sdui.pbgrpc.dart';

Future<void> main() async {
final server = Server.create(
services: [
SduiServiceImpl(),
],
);

await server.serve(port: 50051);
print('Server listening on port 50051...');
}

class SduiServiceImpl extends SduiServiceBase {
@override
Future<SduiWidgetData> getSduiWidget(
ServiceCall call, SduiRequest request) async {
// Return different UI based on the screenId
switch (request.screenId) {
case 'home':
return _createHomeScreen();
default:
return _createErrorScreen();
}
}

SduiWidgetData _createHomeScreen() {
return SduiWidgetData()
..type = WidgetType.SCAFFOLD
..body = (SduiWidgetData()
..type = WidgetType.COLUMN
..children.addAll([
SduiWidgetData()
..type = WidgetType.CONTAINER
..padding = (EdgeInsetsData()..all = 16)
..child = (SduiWidgetData()
..type = WidgetType.TEXT
..stringAttributes['text'] = 'Welcome to Server-Driven UI!'
..textStyle = (TextStyleData()
..fontSize = 22
..fontWeight = 'bold')),
SduiWidgetData()
..type = WidgetType.TEXT
..stringAttributes['text'] = 'This UI is rendered from gRPC data'
]));
}
}
```

## Supported Widgets

The package currently supports these Flutter widgets:

- `Scaffold`
- `Container`
- `Column`
- `Row`
- `Text`
- `Image`
- `SizedBox`
- `Spacer`
- `Icon`

## Advanced Usage

### Protobuf Definitions

The package uses Protocol Buffers to define the data structures for gRPC communication. Here's a simplified version of the main message types:

```protobuf
message SduiWidgetData {
WidgetType type = 1;
map<string, string> string_attributes = 2;
map<string, double> double_attributes = 3;
map<string, bool> bool_attributes = 4;

// Complex nested attributes
TextStyleData text_style = 6;
EdgeInsetsData padding = 7;

// Children widgets
repeated SduiWidgetData children = 12;
SduiWidgetData child = 13;

// Scaffold specific parts
SduiWidgetData app_bar = 14;
SduiWidgetData body = 15;
}

service SduiService {
rpc GetSduiWidget (SduiRequest) returns (SduiWidgetData);
}
```

### Working with Protocol Buffers

If you need to regenerate the Dart files from the proto definitions:

1. Install the Protocol Buffer compiler using the provided scripts:

```bash
< insert code >
# Windows
pwsh ./tool/setup_protoc.ps1

# Generate the Protobuf files
pwsh ./tool/generate_protos.ps1
```

## Roadmap

- [x] Basic widget support
- [x] gRPC implementation
- [ ] JSON implementation
- [ ] Interactive widgets (buttons, forms)
- [ ] More advanced widget support

## Contributing

We welcome contributions! Please see our [contributing guidelines](contributing.md) for details.

## License

This project is licensed under the [LICENSE](LICENSE) file in the repository.

## Contributors

<table>
<tr align="center">
<td>
John Doe
Jothish Kamal
<p align="center">
<img src = "https://dscvit.com/images/dsc-logo-square.svg" width="150" height="150" alt="Your Name Here (Insert Your Image Link In Src">
<img src = "https://avatars.githubusercontent.com/u/74227363?v=4" width="150" height="150" alt="Jothish Kamal">
</p>
<p align="center">
<a href = "https://github.com/person1">
<a href = "https://github.com/JothishKamal">
<img src = "http://www.iconninja.com/files/241/825/211/round-collaboration-social-github-code-circle-network-icon.svg" width="36" height = "36" alt="GitHub"/>
</a>
<a href = "https://www.linkedin.com/in/person1">
<a href = "https://www.linkedin.com/in/jothishkamal">
<img src = "http://www.iconninja.com/files/863/607/751/network-linkedin-social-connection-circular-circle-media-icon.svg" width="36" height="36" alt="LinkedIn"/>
</a>
</p>
Expand Down
10 changes: 10 additions & 0 deletions build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
targets:
$default:
builders:
protoc_plugin: # Using the package name as the builder key
enabled: true
options:
grpc: true # Enable gRPC stub generation
output_directory: lib/src/generated # Specify output directory
generate_mixins: true # Generate mixins for classes
generate_kythe_info: false
Loading
Loading