refactor(apps): 主题系统迁移至 ColorScheme + 扩展架构并支持 Dark Mode
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
enum ChatItemType { message, toolCall, toolResult }
|
||||
|
||||
enum MessageSender { user, ai }
|
||||
|
||||
enum ToolCallStatus { pending, executing, completed, error }
|
||||
|
||||
abstract class ChatListItem {
|
||||
String get id;
|
||||
DateTime get timestamp;
|
||||
ChatItemType get type;
|
||||
MessageSender get sender;
|
||||
}
|
||||
|
||||
class TextMessageItem extends ChatListItem {
|
||||
@override
|
||||
final String id;
|
||||
final String content;
|
||||
@override
|
||||
final DateTime timestamp;
|
||||
@override
|
||||
final MessageSender sender;
|
||||
final bool isStreaming;
|
||||
final List<Map<String, dynamic>> attachments;
|
||||
|
||||
TextMessageItem({
|
||||
required this.id,
|
||||
required this.content,
|
||||
required this.timestamp,
|
||||
required this.sender,
|
||||
this.isStreaming = false,
|
||||
this.attachments = const [],
|
||||
});
|
||||
|
||||
@override
|
||||
ChatItemType get type => ChatItemType.message;
|
||||
|
||||
TextMessageItem copyWith({
|
||||
String? id,
|
||||
String? content,
|
||||
DateTime? timestamp,
|
||||
MessageSender? sender,
|
||||
bool? isStreaming,
|
||||
List<Map<String, dynamic>>? attachments,
|
||||
}) => TextMessageItem(
|
||||
id: id ?? this.id,
|
||||
content: content ?? this.content,
|
||||
timestamp: timestamp ?? this.timestamp,
|
||||
sender: sender ?? this.sender,
|
||||
isStreaming: isStreaming ?? this.isStreaming,
|
||||
attachments: attachments ?? this.attachments,
|
||||
);
|
||||
}
|
||||
|
||||
class ToolCallItem extends ChatListItem {
|
||||
@override
|
||||
final String id;
|
||||
final String callId;
|
||||
final String toolName;
|
||||
final Map<String, dynamic> args;
|
||||
final ToolCallStatus status;
|
||||
final String? errorMessage;
|
||||
@override
|
||||
final DateTime timestamp;
|
||||
@override
|
||||
final MessageSender sender;
|
||||
|
||||
ToolCallItem({
|
||||
required this.id,
|
||||
required this.callId,
|
||||
required this.toolName,
|
||||
required this.args,
|
||||
required this.status,
|
||||
this.errorMessage,
|
||||
required this.timestamp,
|
||||
required this.sender,
|
||||
});
|
||||
|
||||
@override
|
||||
ChatItemType get type => ChatItemType.toolCall;
|
||||
|
||||
ToolCallItem copyWith({
|
||||
String? id,
|
||||
String? callId,
|
||||
String? toolName,
|
||||
Map<String, dynamic>? args,
|
||||
ToolCallStatus? status,
|
||||
String? errorMessage,
|
||||
DateTime? timestamp,
|
||||
MessageSender? sender,
|
||||
}) => ToolCallItem(
|
||||
id: id ?? this.id,
|
||||
callId: callId ?? this.callId,
|
||||
toolName: toolName ?? this.toolName,
|
||||
args: args ?? this.args,
|
||||
status: status ?? this.status,
|
||||
errorMessage: errorMessage ?? this.errorMessage,
|
||||
timestamp: timestamp ?? this.timestamp,
|
||||
sender: sender ?? this.sender,
|
||||
);
|
||||
}
|
||||
|
||||
class ToolResultItem extends ChatListItem {
|
||||
@override
|
||||
final String id;
|
||||
final String callId;
|
||||
final Map<String, dynamic> uiSchema;
|
||||
@override
|
||||
final DateTime timestamp;
|
||||
@override
|
||||
final MessageSender sender;
|
||||
|
||||
ToolResultItem({
|
||||
required this.id,
|
||||
required this.callId,
|
||||
required this.uiSchema,
|
||||
required this.timestamp,
|
||||
required this.sender,
|
||||
});
|
||||
|
||||
@override
|
||||
ChatItemType get type => ChatItemType.toolResult;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import '../../../../core/l10n/l10n.dart';
|
||||
|
||||
enum AgentStage { routing, execution, memory }
|
||||
|
||||
AgentStage? stageFromStepName(String value) {
|
||||
switch (value) {
|
||||
case 'router':
|
||||
return AgentStage.routing;
|
||||
case 'worker':
|
||||
return AgentStage.execution;
|
||||
case 'memory':
|
||||
return AgentStage.memory;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String stageLabel(AgentStage? stage) {
|
||||
return switch (stage) {
|
||||
AgentStage.routing => L10n.current.agentStageRouting,
|
||||
AgentStage.execution => L10n.current.agentStageExecution,
|
||||
AgentStage.memory => L10n.current.agentStageMemory,
|
||||
null => L10n.current.agentStageProcessing,
|
||||
};
|
||||
}
|
||||
@@ -2,25 +2,37 @@ import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:social_app/core/chat/agent_stage.dart';
|
||||
import 'package:social_app/core/chat/chat_list_item.dart';
|
||||
import 'package:social_app/core/chat/chat_orchestrator.dart';
|
||||
import 'package:social_app/core/network/i_api_client.dart';
|
||||
import 'package:social_app/core/l10n/l10n.dart';
|
||||
|
||||
import '../../data/models/ag_ui_event.dart';
|
||||
import '../../data/models/chat_list_item.dart';
|
||||
import '../../data/services/ag_ui_service.dart';
|
||||
import 'agent_stage.dart';
|
||||
|
||||
class ChatState {
|
||||
class ChatState implements ChatOrchestratorState {
|
||||
@override
|
||||
final List<ChatListItem> items;
|
||||
@override
|
||||
final bool isSending;
|
||||
@override
|
||||
final bool isWaitingFirstToken;
|
||||
@override
|
||||
final bool isStreaming;
|
||||
@override
|
||||
final bool isCancelling;
|
||||
@override
|
||||
final bool isLoadingHistory;
|
||||
@override
|
||||
final String? currentMessageId;
|
||||
@override
|
||||
final String? error;
|
||||
@override
|
||||
final DateTime? oldestLoadedDate;
|
||||
@override
|
||||
final bool hasEarlierHistory;
|
||||
@override
|
||||
final AgentStage? currentStage;
|
||||
|
||||
const ChatState({
|
||||
@@ -37,6 +49,7 @@ class ChatState {
|
||||
this.currentStage,
|
||||
});
|
||||
|
||||
@override
|
||||
bool get isLoading =>
|
||||
isSending ||
|
||||
isWaitingFirstToken ||
|
||||
@@ -81,7 +94,7 @@ class ChatState {
|
||||
}
|
||||
}
|
||||
|
||||
class ChatBloc extends Cubit<ChatState> {
|
||||
class ChatBloc extends Cubit<ChatState> implements ChatOrchestrator {
|
||||
ChatBloc({AgUiService? service, required IApiClient apiClient})
|
||||
: _service = service ?? AgUiService(apiClient: apiClient),
|
||||
super(const ChatState()) {
|
||||
@@ -382,6 +395,7 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
.reduce((a, b) => a.isBefore(b) ? a : b);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendMessage(String content, {List<XFile>? images}) async {
|
||||
final messageId = 'user-${DateTime.now().millisecondsSinceEpoch}';
|
||||
final attachments = (images ?? const <XFile>[])
|
||||
@@ -527,6 +541,7 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
emit(state.copyWith(items: items));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> loadHistory() async {
|
||||
if (state.isLoadingHistory) return;
|
||||
emit(state.copyWith(isLoadingHistory: true));
|
||||
@@ -554,6 +569,7 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> loadMoreHistory() async {
|
||||
if (state.isLoadingHistory || !state.hasEarlierHistory) return;
|
||||
if (state.oldestLoadedDate == null) return;
|
||||
@@ -584,10 +600,12 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> transcribeAudioFile(String filePath) {
|
||||
return _service.transcribeAudio(filePath);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> cancelCurrentRun() async {
|
||||
if (!(state.isWaitingFirstToken ||
|
||||
state.isStreaming ||
|
||||
@@ -637,6 +655,7 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
return future;
|
||||
}
|
||||
|
||||
@override
|
||||
void clearError() {
|
||||
emit(state.copyWith(error: null));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user