diff --git a/README.md b/README.md
index b66daf3..a3b6cd2 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,48 @@
# Conduit - Open-WebUI Mobile Client
+
+
+
+
+
Conduit is an open-source, cross-platform mobile application for Open-WebUI, providing a native mobile experience for interacting with your self-hosted AI infrastructure.
## Features
### Core Features
-- ✅ **Real-time Chat**: Stream responses from AI models in real-time
-- ✅ **Model Selection**: Choose from available models on your server
-- ✅ **Conversation Management**: Create, search, and manage chat histories
-- ✅ **Markdown Rendering**: Full markdown support with syntax highlighting
-- ✅ **Theme Support**: Light, Dark, and System themes
+- **Real-time Chat**: Stream responses from AI models in real-time
+- **Model Selection**: Choose from available models on your server
+- **Conversation Management**: Create, search, and manage chat histories
+- **Markdown Rendering**: Full markdown support with syntax highlighting
+- **Theme Support**: Light, Dark, and System themes
### Advanced Features
-- ✅ **Voice Input**: Use speech-to-text for hands-free interaction
-- ✅ **File Uploads**: Support for images and documents (RAG)
-- ✅ **Multi-modal Support**: Work with vision models
-- ✅ **Secure Storage**: Credentials stored securely using platform keychains
+- **Voice Input**: Use speech-to-text for hands-free interaction
+- **File Uploads**: Support for images and documents (RAG)
+- **Multi-modal Support**: Work with vision models
+- **Secure Storage**: Credentials stored securely using platform keychains
+
+## Screenshots
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
## Requirements
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
new file mode 100644
index 0000000..1f7e857
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
new file mode 100644
index 0000000..5331fe3
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
new file mode 100644
index 0000000..b2b11fd
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
new file mode 100644
index 0000000..5d43ada
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
new file mode 100644
index 0000000..7f5390d
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png
new file mode 100644
index 0000000..fa4b509
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_01.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_01.png
deleted file mode 100644
index b3ed8b3..0000000
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_01.png and /dev/null differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_02.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_02.png
deleted file mode 100644
index 0a99fc1..0000000
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_02.png and /dev/null differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_03.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_03.png
deleted file mode 100644
index 4e9593d..0000000
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_03.png and /dev/null differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_04.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_04.png
deleted file mode 100644
index a03cdd8..0000000
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_04.png and /dev/null differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_05.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_05.png
deleted file mode 100644
index 1a3cd42..0000000
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_05.png and /dev/null differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_06.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_06.png
deleted file mode 100644
index 3e6a21c..0000000
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_06.png and /dev/null differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_07.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_07.png
deleted file mode 100644
index e39477e..0000000
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/flutter_07.png and /dev/null differ
diff --git a/lib/core/services/api_service.dart b/lib/core/services/api_service.dart
index d7d375f..2787044 100644
--- a/lib/core/services/api_service.dart
+++ b/lib/core/services/api_service.dart
@@ -464,8 +464,14 @@ class ApiService {
// Parse full OpenWebUI chat with messages
Conversation _parseFullOpenWebUIChat(Map chatData) {
+ debugPrint('DEBUG: Parsing full OpenWebUI chat data');
+ debugPrint('DEBUG: Chat data keys: ${chatData.keys.toList()}');
+
final id = chatData['id'] as String;
final title = chatData['title'] as String;
+
+ debugPrint('DEBUG: Parsed chat ID: $id');
+ debugPrint('DEBUG: Parsed chat title: $title');
// Safely parse timestamps with validation
final updatedAt = _parseTimestamp(chatData['updated_at']);
@@ -481,26 +487,33 @@ class ApiService {
final chatObject = chatData['chat'] as Map?;
final messages = [];
- // Try multiple locations for messages
+ // Try multiple locations for messages - prefer list format to avoid duplication
List? messagesList;
- Map? messagesMap;
if (chatObject != null) {
- // Check for messages in chat.history.messages (map format)
- final history = chatObject['history'] as Map?;
- if (history != null && history['messages'] != null) {
- messagesMap = history['messages'] as Map;
- debugPrint(
- 'DEBUG: Found ${messagesMap.length} messages in chat.history.messages',
- );
- }
-
- // Check for messages in chat.messages (list format)
+ // Check for messages in chat.messages (list format) - PREFERRED
if (chatObject['messages'] != null) {
messagesList = chatObject['messages'] as List;
debugPrint(
'DEBUG: Found ${messagesList.length} messages in chat.messages',
);
+ } else {
+ // Fallback: Check for messages in chat.history.messages (map format)
+ final history = chatObject['history'] as Map?;
+ if (history != null && history['messages'] != null) {
+ final messagesMap = history['messages'] as Map;
+ debugPrint(
+ 'DEBUG: Found ${messagesMap.length} messages in chat.history.messages (converting to list)',
+ );
+
+ // Convert map to list format to use common parsing logic
+ messagesList = [];
+ for (final entry in messagesMap.entries) {
+ final msgData = Map.from(entry.value as Map);
+ msgData['id'] = entry.key; // Use the key as the message ID
+ messagesList.add(msgData);
+ }
+ }
}
} else if (chatData['messages'] != null) {
messagesList = chatData['messages'] as List;
@@ -509,42 +522,21 @@ class ApiService {
);
}
- // Parse messages from map format (chat.history.messages)
- if (messagesMap != null) {
- for (final entry in messagesMap.entries) {
- try {
- final msgData = entry.value as Map;
- msgData['id'] = entry.key; // Use the key as the message ID
- debugPrint(
- 'DEBUG: Parsing message from map: ${entry.key} - role: ${msgData['role']} - content length: ${msgData['content']?.toString().length ?? 0}',
- );
- // Convert OpenWebUI message format to our ChatMessage format
- final message = _parseOpenWebUIMessage(msgData);
- messages.add(message);
- debugPrint(
- 'DEBUG: Successfully parsed message from map: ${message.id} - ${message.role}',
- );
- } catch (e) {
- debugPrint('DEBUG: Error parsing message from map: $e');
- }
- }
- }
-
- // Parse messages from list format (chat.messages or top-level)
+ // Parse messages from list format only (avoiding duplication)
if (messagesList != null) {
for (final msgData in messagesList) {
try {
debugPrint(
- 'DEBUG: Parsing message from list: ${msgData['id']} - role: ${msgData['role']} - content length: ${msgData['content']?.toString().length ?? 0}',
+ 'DEBUG: Parsing message: ${msgData['id']} - role: ${msgData['role']} - content length: ${msgData['content']?.toString().length ?? 0}',
);
// Convert OpenWebUI message format to our ChatMessage format
final message = _parseOpenWebUIMessage(msgData);
messages.add(message);
debugPrint(
- 'DEBUG: Successfully parsed message from list: ${message.id} - ${message.role}',
+ 'DEBUG: Successfully parsed message: ${message.id} - ${message.role}',
);
} catch (e) {
- debugPrint('DEBUG: Error parsing message from list: $e');
+ debugPrint('DEBUG: Error parsing message: $e');
}
}
}
@@ -607,7 +599,6 @@ class ApiService {
);
}
- // Create new conversation using OpenWebUI API
// Create new conversation using OpenWebUI API
Future createConversation({
required String title,
@@ -618,39 +609,47 @@ class ApiService {
debugPrint('DEBUG: Creating new conversation on OpenWebUI server');
debugPrint('DEBUG: Title: $title, Messages: ${messages.length}');
- // Convert messages to the new format with proper structure
+ // Build messages with parent-child relationships
final Map messagesMap = {};
+ final List