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
11 changes: 11 additions & 0 deletions .pubignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Files to exclude from pub.dev publishing

SDUI_Flutter_Integration_Guide.txt
docs/
.github/
.hooks/
.idea/
\*.iml
build/
.dart_tool/
bin/
15 changes: 9 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

### 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
- Server-Driven UI framework for Flutter
- JSON and gRPC support for dynamic UI rendering
- Protocol Buffers integration for type-safe communication
- Core widget support: Text, Column, Row, Container, Scaffold, Image, Icon, SizedBox, Spacer
- SduiGrpcClient for server communication
- SduiGrpcRenderer widget for rendering server-driven UI
- Comprehensive documentation and examples
- Flutter-to-SDUI conversion utilities
- Error handling and loading states
391 changes: 140 additions & 251 deletions LICENSE

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,34 @@ This project is licensed under the [LICENSE](LICENSE) file in the repository.
</a>
</p>
</td>
<td>
Rujin Devkota
<p align="center">
<img src = "https://avatars.githubusercontent.com/u/71916379?v=4" width="150" height="150" alt="Rujin Devkota">
</p>
<p align="center">
<a href = "https://github.com/rujin2003">
<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/rujin-devkota/">
<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>
</td>
<td>
Adhavan K
<p align="center">
<img src = "https://avatars.githubusercontent.com/u/108629544?v=4" width="150" height="150" alt="Adhavan K">
</p>
<p align="center">
<a href = "https://github.com/TBA5854">
<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/adhavan-k-503b8a28a/">
<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>
</td>
</tr>
</table>

Expand Down
1 change: 0 additions & 1 deletion SDUI_Flutter_Integration_Guide.txt

This file was deleted.

File renamed without changes.
27 changes: 21 additions & 6 deletions example/grpc_example.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import 'package:flutter/material.dart';
import 'package:flutter_sdui/flutter_sdui.dart';

/// Example application demonstrating Flutter SDUI with gRPC.
///
/// This example shows how to:
/// * Connect to a gRPC server
/// * Fetch server-driven UI definitions
/// * Render dynamic UI content
/// * Handle different screen types
void main() {
runApp(const MyApp());
}

/// Root application widget that sets up the Material theme and routing.
class MyApp extends StatelessWidget {
const MyApp({super.key});

Expand All @@ -21,6 +29,13 @@ class MyApp extends StatelessWidget {
}
}

/// Demo widget that showcases the gRPC renderer functionality.
///
/// This widget demonstrates how to:
/// * Initialize a gRPC client connection
/// * Switch between different screen definitions
/// * Handle loading and error states
/// * Properly dispose of resources
class GrpcRendererDemo extends StatefulWidget {
const GrpcRendererDemo({super.key});

Expand All @@ -35,16 +50,16 @@ class _GrpcRendererDemoState extends State<GrpcRendererDemo> {
@override
void initState() {
super.initState();
// Connect to your gRPC server
// Initialize gRPC client with server connection details
_grpcClient = SduiGrpcClient(
host: 'localhost', // Replace with your server address
port: 50051, // Replace with your server port
host: 'localhost',
port: 50051,
);
}

@override
void dispose() {
// Close the gRPC connection when done
// Clean up gRPC connection
_grpcClient.dispose();
super.dispose();
}
Expand All @@ -57,7 +72,7 @@ class _GrpcRendererDemoState extends State<GrpcRendererDemo> {
),
body: Column(
children: [
// Screen selector
// Screen selection controls
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
Expand All @@ -84,7 +99,7 @@ class _GrpcRendererDemoState extends State<GrpcRendererDemo> {
),
),

// SDUI Renderer that fetches UI from gRPC server
// Server-driven UI renderer
Expanded(
child: SduiGrpcRenderer(
client: _grpcClient,
Expand Down
47 changes: 35 additions & 12 deletions example/grpc_server_example_dart.dart
Original file line number Diff line number Diff line change
@@ -1,29 +1,51 @@
// Server implementation example (Dart)
// Note: This is a standalone Dart server, not a Flutter application
// Run with: dart run example/grpc_server_example.dart
/// Example gRPC server implementation for Flutter SDUI.
///
/// This is a standalone Dart server that provides server-driven UI definitions
/// through gRPC. It demonstrates how to:
/// * Set up a gRPC server with SDUI service
/// * Handle different screen requests
/// * Create widget definitions using protobuf
/// * Return complex UI structures
///
/// To run this server:
/// ```bash
/// dart run example/grpc_server_example_dart.dart
/// ```
///
/// The server listens on port 50051 by default.
library;
import 'dart:developer';

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

/// Entry point for the gRPC server.
///
/// Initializes the server with the SDUI service implementation
/// and starts listening for client connections.
Future<void> main() async {
final server = Server.create(
services: [
SduiServiceImpl(),
],
);

final port = 50051;
const port = 50051;
await server.serve(port: port);
print('Server listening on port $port...');
print('Press Ctrl+C to stop');
log('Server listening on port $port...');
log('Press Ctrl+C to stop');
}

// Implementation of the SDUI service
/// Implementation of the SDUI gRPC service.
///
/// This class handles incoming requests for UI definitions and returns
/// appropriate widget data based on the requested screen ID.
class SduiServiceImpl extends SduiServiceBase {
@override
Future<SduiWidgetData> getSduiWidget(
ServiceCall call, SduiRequest request) async {
// Based on the requested screen, return different UI definitions
print('Received request for screen: ${request.screenId}');
log('Received request for screen: ${request.screenId}');

switch (request.screenId) {
case 'home':
return _createHomeScreen();
Expand All @@ -32,13 +54,14 @@ class SduiServiceImpl extends SduiServiceBase {
case 'settings':
return _createSettingsScreen();
default:
// Default or error screen
print('Warning: Unknown screen ID requested: ${request.screenId}');
log('Warning: Unknown screen ID requested: ${request.screenId}');
return _createErrorScreen();
}
}

// Sample screen definitions
/// Creates the home screen UI definition.
///
/// Returns a scaffold with an app bar and a column of welcome content.
SduiWidgetData _createHomeScreen() {
final homeScreen = SduiWidgetData()
..type = WidgetType.SCAFFOLD
Expand Down
35 changes: 28 additions & 7 deletions lib/flutter_sdui.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
/// Flutter SDUI Package
/// Flutter Server-Driven UI Package
///
/// A Flutter package to render server driven UI.
/// A Flutter package that enables server-driven UI development by parsing
/// protobuf-based widget definitions from a gRPC server and rendering them
/// as native Flutter widgets.
///
/// This package provides:
/// * Protobuf-based widget parsing and rendering
/// * gRPC client for server communication
/// * A comprehensive set of SDUI widgets that mirror Flutter's core widgets
/// * Type-safe widget definitions through generated protobuf models
///
/// ## Usage
///
/// ```dart
/// // Create a gRPC client
/// final client = SduiGrpcClient(host: 'localhost', port: 50051);
///
/// // Render server-driven UI
/// SduiGrpcRenderer(
/// client: client,
/// screenId: 'home',
/// )
/// ```
library;

// Export the core parser and widget base
export 'src/parser/sdui_proto_parser.dart'; // New proto parser
// Core parsing and widget foundation
export 'src/parser/sdui_proto_parser.dart';
export 'src/widgets/sdui_widget.dart';

// Export individual widget models
// SDUI widget implementations
export 'src/widgets/sdui_column.dart';
export 'src/widgets/sdui_row.dart';
export 'src/widgets/sdui_text.dart';
Expand All @@ -18,11 +39,11 @@ export 'src/widgets/sdui_scaffold.dart';
export 'src/widgets/sdui_spacer.dart';
export 'src/widgets/sdui_icon.dart';

// Export gRPC client and renderer
// Network communication
export 'src/service/sdui_grpc_client.dart';
export 'src/renderer/sdui_grpc_renderer.dart';

// Export generated Protobuf models for public use
// Generated protobuf models
export 'src/generated/sdui.pb.dart';
export 'src/generated/sdui.pbgrpc.dart';
export 'src/generated/sdui.pbenum.dart';
Expand Down
38 changes: 27 additions & 11 deletions lib/src/parser/flutter_to_sdui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ SduiWidget flutterToSdui(Widget widget) {
width: widget.width,
height: widget.height,
fit: widget.fit,
alignment: widget.alignment is Alignment ? widget.alignment as Alignment : null,
alignment: widget.alignment is Alignment
? widget.alignment as Alignment
: null,
repeat: widget.repeat,
color: widget.color,
colorBlendMode: widget.colorBlendMode,
Expand All @@ -75,27 +77,40 @@ SduiWidget flutterToSdui(Widget widget) {
} else if (widget is Container) {
return SduiContainer(
child: widget.child != null ? flutterToSdui(widget.child!) : null,
padding: widget.padding is EdgeInsets ? widget.padding as EdgeInsets : null,
padding:
widget.padding is EdgeInsets ? widget.padding as EdgeInsets : null,
margin: widget.margin is EdgeInsets ? widget.margin as EdgeInsets : null,
decoration: widget.decoration is BoxDecoration ? widget.decoration as BoxDecoration : null,
decoration: widget.decoration is BoxDecoration
? widget.decoration as BoxDecoration
: null,
width: null, // Container does not expose width directly
height: null, // Container does not expose height directly
color: widget.color,
alignment: widget.alignment is Alignment ? widget.alignment as Alignment : null,
alignment:
widget.alignment is Alignment ? widget.alignment as Alignment : null,
constraints: widget.constraints,
transform: widget.transform,
transformAlignment: widget.transformAlignment is AlignmentGeometry ? widget.transformAlignment as AlignmentGeometry : null,
transformAlignment: widget.transformAlignment is AlignmentGeometry
? widget.transformAlignment as AlignmentGeometry
: null,
clipBehavior: widget.clipBehavior,
);
} else if (widget is Scaffold) {
return SduiScaffold(
appBar: widget.appBar != null ? flutterToSdui(widget.appBar!) : null,
body: widget.body != null ? flutterToSdui(widget.body!) : null,
floatingActionButton: widget.floatingActionButton != null ? flutterToSdui(widget.floatingActionButton!) : null,
bottomNavigationBar: widget.bottomNavigationBar != null ? flutterToSdui(widget.bottomNavigationBar!) : null,
floatingActionButton: widget.floatingActionButton != null
? flutterToSdui(widget.floatingActionButton!)
: null,
bottomNavigationBar: widget.bottomNavigationBar != null
? flutterToSdui(widget.bottomNavigationBar!)
: null,
drawer: widget.drawer != null ? flutterToSdui(widget.drawer!) : null,
endDrawer: widget.endDrawer != null ? flutterToSdui(widget.endDrawer!) : null,
bottomSheet: widget.bottomSheet != null ? flutterToSdui(widget.bottomSheet!) : null,
endDrawer:
widget.endDrawer != null ? flutterToSdui(widget.endDrawer!) : null,
bottomSheet: widget.bottomSheet != null
? flutterToSdui(widget.bottomSheet!)
: null,
backgroundColor: widget.backgroundColor,
resizeToAvoidBottomInset: widget.resizeToAvoidBottomInset,
primary: widget.primary,
Expand All @@ -121,5 +136,6 @@ SduiWidget flutterToSdui(Widget widget) {
shadows: widget.shadows,
);
}
throw UnimplementedError('Conversion for ${widget.runtimeType} is not implemented');
}
throw UnimplementedError(
'Conversion for ${widget.runtimeType} is not implemented');
}
Loading
Loading