2025-03-23 21:53:05 +08:00
|
|
|
import 'dart:async';
|
|
|
|
|
2025-03-24 14:15:20 +08:00
|
|
|
import 'package:appflowy/ai/service/ai_model_state_notifier.dart';
|
2025-03-23 21:53:05 +08:00
|
|
|
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
|
|
|
import 'package:appflowy_backend/protobuf/flowy-ai/entities.pbserver.dart';
|
2025-03-24 14:15:20 +08:00
|
|
|
import 'package:equatable/equatable.dart';
|
2025-03-23 21:53:05 +08:00
|
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
|
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
|
|
|
|
|
|
part 'select_model_bloc.freezed.dart';
|
|
|
|
|
2025-03-24 14:15:20 +08:00
|
|
|
class AiModel extends Equatable {
|
|
|
|
const AiModel({
|
|
|
|
required this.name,
|
|
|
|
required this.isLocal,
|
|
|
|
});
|
|
|
|
|
|
|
|
factory AiModel.fromPB(AIModelPB pb) {
|
|
|
|
return AiModel(name: pb.name, isLocal: pb.isLocal);
|
|
|
|
}
|
|
|
|
|
|
|
|
AIModelPB toPB() {
|
|
|
|
return AIModelPB()
|
|
|
|
..name = name
|
|
|
|
..isLocal = isLocal;
|
|
|
|
}
|
|
|
|
|
|
|
|
final String name;
|
|
|
|
final bool isLocal;
|
|
|
|
|
|
|
|
@override
|
|
|
|
List<Object?> get props => [name, isLocal];
|
|
|
|
}
|
|
|
|
|
2025-03-23 21:53:05 +08:00
|
|
|
class SelectModelBloc extends Bloc<SelectModelEvent, SelectModelState> {
|
|
|
|
SelectModelBloc({
|
2025-03-24 14:15:20 +08:00
|
|
|
required AIModelStateNotifier aiModelStateNotifier,
|
|
|
|
}) : _aiModelStateNotifier = aiModelStateNotifier,
|
|
|
|
super(SelectModelState.initial()) {
|
2025-03-23 21:53:05 +08:00
|
|
|
on<SelectModelEvent>(
|
2025-03-24 14:15:20 +08:00
|
|
|
(event, emit) {
|
|
|
|
event.when(
|
|
|
|
selectModel: (model) {
|
|
|
|
AIEventUpdateSelectedModel(
|
2025-03-23 21:53:05 +08:00
|
|
|
UpdateSelectedModelPB(
|
2025-03-24 14:15:20 +08:00
|
|
|
source: _aiModelStateNotifier.objectId,
|
|
|
|
selectedModel: model.toPB(),
|
2025-03-23 21:53:05 +08:00
|
|
|
),
|
|
|
|
).send();
|
|
|
|
|
2025-03-24 14:15:20 +08:00
|
|
|
emit(state.copyWith(selectedModel: model));
|
|
|
|
},
|
|
|
|
didLoadModels: (models, selectedModel) {
|
2025-03-23 21:53:05 +08:00
|
|
|
emit(
|
2025-03-24 14:15:20 +08:00
|
|
|
SelectModelState(
|
|
|
|
models: models,
|
|
|
|
selectedModel: selectedModel,
|
2025-03-23 21:53:05 +08:00
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
2025-03-24 14:15:20 +08:00
|
|
|
|
|
|
|
_aiModelStateNotifier.addListener(
|
|
|
|
onAvailableModelsChanged: _onAvailableModelsChanged,
|
|
|
|
);
|
2025-03-23 21:53:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
final AIModelStateNotifier _aiModelStateNotifier;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<void> close() async {
|
2025-03-24 14:15:20 +08:00
|
|
|
_aiModelStateNotifier.removeListener(
|
|
|
|
onAvailableModelsChanged: _onAvailableModelsChanged,
|
|
|
|
);
|
2025-03-23 21:53:05 +08:00
|
|
|
await super.close();
|
|
|
|
}
|
2025-03-24 14:15:20 +08:00
|
|
|
|
|
|
|
void _onAvailableModelsChanged(List<AiModel> models, AiModel? selectedModel) {
|
|
|
|
if (!isClosed) {
|
|
|
|
add(SelectModelEvent.didLoadModels(models, selectedModel));
|
|
|
|
}
|
|
|
|
}
|
2025-03-23 21:53:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
@freezed
|
|
|
|
class SelectModelEvent with _$SelectModelEvent {
|
|
|
|
const factory SelectModelEvent.selectModel(
|
2025-03-24 14:15:20 +08:00
|
|
|
AiModel model,
|
2025-03-23 21:53:05 +08:00
|
|
|
) = _SelectModel;
|
|
|
|
|
|
|
|
const factory SelectModelEvent.didLoadModels(
|
2025-03-24 14:15:20 +08:00
|
|
|
List<AiModel> models,
|
|
|
|
AiModel? selectedModel,
|
2025-03-23 21:53:05 +08:00
|
|
|
) = _DidLoadModels;
|
|
|
|
}
|
|
|
|
|
|
|
|
@freezed
|
|
|
|
class SelectModelState with _$SelectModelState {
|
|
|
|
const factory SelectModelState({
|
2025-03-24 14:15:20 +08:00
|
|
|
required List<AiModel> models,
|
|
|
|
required AiModel? selectedModel,
|
2025-03-23 21:53:05 +08:00
|
|
|
}) = _SelectModelState;
|
2025-03-24 14:15:20 +08:00
|
|
|
|
|
|
|
factory SelectModelState.initial() => SelectModelState(
|
|
|
|
models: [],
|
|
|
|
selectedModel: null,
|
|
|
|
);
|
2025-03-23 21:53:05 +08:00
|
|
|
}
|