Dify Flutter
A comprehensive Flutter package for integrating Dify AI platform with beautiful chat UI components. This package provides a complete solution for building AI-powered chat applications using Dify's API.
Features
- π Easy Integration: Simple setup with just a few lines of code
- π¬ Beautiful Chat UI: Modern, customizable chat interface
- π Real-time Messaging: Support for streaming responses
- π± Cross-platform: Works on iOS, Android, Web, and Desktop
- π¨ Customizable: Highly customizable UI components
- π Provider Pattern: Built with Flutter Provider for state management
- πΎ Local Storage: Automatic user session management
- π WebSocket Support: Real-time communication capabilities
- π Error Handling: Comprehensive error handling and retry mechanisms
Installation
Add this to your package's pubspec.yaml file:
dependencies:
dify_flutter: ^1.0.0
Then run:
flutter pub get
Quick Start
1. Initialize Dify Client
import 'package:dify_flutter/dify_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChangeNotifierProvider(
create: (context) => DifyProvider(),
child: ChatScreen(),
),
);
}
}
2. Setup Configuration
class ChatScreen extends StatefulWidget {
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
@override
void initState() {
super.initState();
_initializeDify();
}
Future<void> _initializeDify() async {
final provider = context.read<DifyProvider>();
// Initialize with your Dify configuration
await provider.initialize(DifyConfig(
apiKey: 'your-dify-api-key',
baseUrl: 'https://api.dify.ai/v1', // Optional, defaults to this
));
// Set up user
await provider.setCurrentUser(
userId: 'user-123',
name: 'John Doe',
email: 'john@example.com',
);
}
@override
Widget build(BuildContext context) {
return DifyChatWidget(
title: 'AI Assistant',
placeholder: 'Ask me anything...',
);
}
}
Advanced Usage
Custom Chat Widget
DifyChatWidget(
title: 'Custom Chat',
placeholder: 'Type your message...',
showAppBar: true,
enableWebSocket: false,
onError: () {
// Handle errors
print('Chat error occurred');
},
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
actions: [
IconButton(
icon: Icon(Icons.settings),
onPressed: () {
// Open settings
},
),
],
)
Manual Message Handling
class CustomChatScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<DifyProvider>(
builder: (context, provider, child) {
return Scaffold(
appBar: AppBar(title: Text('Custom Chat')),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: provider.messages.length,
itemBuilder: (context, index) {
final message = provider.messages[index];
return DifyMessageBubble(
message: message,
onRetry: message.status == MessageStatus.error
? () => provider.sendMessage(message.content)
: null,
);
},
),
),
DifyInputField(
onSendMessage: provider.sendMessage,
isLoading: provider.isLoading,
placeholder: 'Type a message...',
),
],
),
);
},
);
}
}
Conversation Management
class ConversationScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<DifyProvider>(
builder: (context, provider, child) {
return Scaffold(
appBar: AppBar(
title: Text('Conversations'),
actions: [
IconButton(
icon: Icon(Icons.add),
onPressed: () => provider.createConversation(),
),
],
),
body: ListView.builder(
itemCount: provider.conversations.length,
itemBuilder: (context, index) {
final conversation = provider.conversations[index];
return ListTile(
title: Text(conversation.name),
subtitle: Text(conversation.updatedAt.toString()),
onTap: () => provider.loadConversation(conversation.id),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => provider.deleteConversation(conversation.id),
),
);
},
),
);
},
);
}
}
WebSocket Connection
// Enable WebSocket for real-time messaging
provider.connectWebSocket();
// Listen to incoming messages
provider.messageStream.listen((message) {
print('Received message: ${message.content}');
});
// Listen to errors
provider.errorStream.listen((error) {
print('WebSocket error: $error');
});
// Disconnect when done
provider.disconnectWebSocket();
API Reference
DifyConfig
Configuration for the Dify client.
DifyConfig({
required String apiKey,
String baseUrl = 'https://api.dify.ai/v1',
String? appId,
Duration timeout = const Duration(seconds: 30),
Map<String, String>? headers,
})
DifyProvider
Main provider class for managing Dify state.
Methods
initialize(DifyConfig config)- Initialize the Dify clientsetCurrentUser({required String userId, String? name, String? email, Map<String, dynamic>? metadata})- Set current usercreateConversation({String? name, Map<String, dynamic>? metadata})- Create new conversationloadConversation(String conversationId)- Load conversation by IDloadConversations()- Load all conversationssendMessage(String content)- Send a messagedeleteConversation(String conversationId)- Delete conversationconnectWebSocket()- Connect to WebSocketdisconnectWebSocket()- Disconnect WebSocket
Properties
messages- List of messages in current conversationconversations- List of all conversationscurrentUser- Current usercurrentConversation- Current conversationisLoading- Loading stateisConnected- WebSocket connection stateerror- Current error message
DifyMessage
Message model with the following properties:
id- Unique message IDcontent- Message contentrole- Message role (user, assistant, system)status- Message status (sending, sent, error, received)timestamp- Message timestampmetadata- Additional metadataconversationId- Associated conversation IDuserId- Associated user ID
DifyConversation
Conversation model with the following properties:
id- Unique conversation IDname- Conversation namecreatedAt- Creation timestampupdatedAt- Last update timestampmessageIds- List of message IDsmetadata- Additional metadatauserId- Associated user ID
Customization
Theme Customization
The package uses Flutter's theme system. You can customize colors, text styles, and other properties through your app's theme:
MaterialApp(
theme: ThemeData(
primaryColor: Colors.blue,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
// Customize other theme properties
),
home: MyApp(),
)
Custom Widgets
You can create custom message bubbles by extending or replacing the DifyMessageBubble widget:
class CustomMessageBubble extends StatelessWidget {
final DifyMessage message;
const CustomMessageBubble({required this.message});
@override
Widget build(BuildContext context) {
// Your custom implementation
return Container(
// Custom styling
);
}
}
Error Handling
The package provides comprehensive error handling:
Consumer<DifyProvider>(
builder: (context, provider, child) {
if (provider.error != null) {
return Center(
child: Column(
children: [
Text('Error: ${provider.error}'),
ElevatedButton(
onPressed: () => provider.clearError(),
child: Text('Retry'),
),
],
),
);
}
return YourWidget();
},
)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
If you encounter any issues or have questions, please:
- Check the documentation
- Search existing issues
- Create a new issue with detailed information
Author
Sezer OΔraΕ
- GitHub: @sezerogras
- Email: ograssezer474@gmail.com
Changelog
1.0.0
- Initial release
- Basic chat functionality
- WebSocket support
- Conversation management
- Beautiful UI components
- Provider pattern integration
- Error handling
- Local storage support