Skip to content

Commit ff70595

Browse files
committed
chore: display ai model desc and fix flashing when select model
1 parent f6f19a0 commit ff70595

6 files changed

Lines changed: 100 additions & 80 deletions

File tree

frontend/appflowy_flutter/lib/workspace/application/settings/ai/settings_ai_bloc.dart

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ import 'package:freezed_annotation/freezed_annotation.dart';
1111

1212
part 'settings_ai_bloc.freezed.dart';
1313

14+
const String aiModelsGlobalActiveModel = "ai_models_global_active_model";
15+
1416
class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
1517
SettingsAIBloc(
1618
this.userProfile,
1719
this.workspaceId,
1820
) : _userListener = UserListener(userProfile: userProfile),
1921
_aiModelSwitchListener =
20-
AIModelSwitchListener(objectId: "ai_models_global_active_model"),
22+
AIModelSwitchListener(objectId: aiModelsGlobalActiveModel),
2123
super(
2224
SettingsAIState(
2325
userProfile: userProfile,
@@ -58,6 +60,7 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
5860
},
5961
);
6062
_loadModelList();
63+
_loadUserWorkspaceSetting();
6164
},
6265
didReceiveUserProfile: (userProfile) {
6366
emit(state.copyWith(userProfile: userProfile));
@@ -75,6 +78,12 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
7578
if (!model.isLocal) {
7679
await _updateUserWorkspaceSetting(model: model.name);
7780
}
81+
await AIEventUpdateSelectedModel(
82+
UpdateSelectedModelPB(
83+
source: aiModelsGlobalActiveModel,
84+
selectedModel: model,
85+
),
86+
).send();
7887
},
7988
didLoadAISetting: (UseAISettingPB settings) {
8089
emit(
@@ -135,6 +144,19 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
135144
});
136145
});
137146
}
147+
148+
void _loadUserWorkspaceSetting() {
149+
final payload = UserWorkspaceIdPB(workspaceId: workspaceId);
150+
UserEventGetWorkspaceSetting(payload).send().then((result) {
151+
result.fold((settings) {
152+
if (!isClosed) {
153+
add(SettingsAIEvent.didLoadAISetting(settings));
154+
}
155+
}, (err) {
156+
Log.error(err);
157+
});
158+
});
159+
}
138160
}
139161

140162
@freezed

frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/setting_ai_view/model_selection.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,19 @@ import 'package:flutter_bloc/flutter_bloc.dart';
1212

1313
class AIModelSelection extends StatelessWidget {
1414
const AIModelSelection({super.key});
15+
static const double height = 49;
1516

1617
@override
1718
Widget build(BuildContext context) {
1819
return BlocBuilder<SettingsAIBloc, SettingsAIState>(
20+
buildWhen: (previous, current) =>
21+
previous.availableModels != current.availableModels,
1922
builder: (context, state) {
2023
if (state.availableModels == null) {
21-
return const SizedBox.shrink();
24+
return const SizedBox(
25+
// Using same height as SettingsDropdown to avoid layout shift
26+
height: height,
27+
);
2228
}
2329

2430
return Padding(
@@ -47,7 +53,7 @@ class AIModelSelection extends StatelessWidget {
4753
value: model,
4854
label: model.i18n,
4955
subLabel: model.desc,
50-
maximumHeight: 49,
56+
maximumHeight: height,
5157
),
5258
)
5359
.toList(),

frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/setting_ai_view/settings_ai_view.dart

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,14 @@ class SettingsAIView extends StatelessWidget {
4444
return BlocProvider<SettingsAIBloc>(
4545
create: (_) => SettingsAIBloc(userProfile, workspaceId)
4646
..add(const SettingsAIEvent.started()),
47-
child: BlocBuilder<SettingsAIBloc, SettingsAIState>(
48-
builder: (context, state) {
49-
final children = <Widget>[
50-
const AIModelSelection(),
51-
];
52-
53-
children.add(const _AISearchToggle(value: false));
54-
children.add(const LocalAISetting());
55-
56-
return SettingsBody(
57-
title: LocaleKeys.settings_aiPage_title.tr(),
58-
description:
59-
LocaleKeys.settings_aiPage_keys_aiSettingsDescription.tr(),
60-
children: children,
61-
);
62-
},
47+
child: SettingsBody(
48+
title: LocaleKeys.settings_aiPage_title.tr(),
49+
description: LocaleKeys.settings_aiPage_keys_aiSettingsDescription.tr(),
50+
children: [
51+
const AIModelSelection(),
52+
const _AISearchToggle(value: false),
53+
const LocalAISetting(),
54+
],
6355
),
6456
);
6557
}

frontend/appflowy_flutter/lib/workspace/presentation/settings/settings_dialog.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class SettingsDialog extends StatelessWidget {
141141
case SettingsPage.ai:
142142
if (user.authenticator == AuthenticatorPB.AppFlowyCloud) {
143143
return SettingsAIView(
144-
key: ValueKey(user.hashCode),
144+
key: ValueKey(workspaceId),
145145
userProfile: user,
146146
currentWorkspaceMemberRole: currentWorkspaceMemberRole,
147147
workspaceId: workspaceId,

frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/af_dropdown_menu_entry.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ DropdownMenuEntry<T> buildDropdownMenuEntry<T>(
99
BuildContext context, {
1010
required T value,
1111
required String label,
12-
String? subLabel,
12+
String subLabel = '',
1313
T? selectedValue,
1414
Widget? leadingWidget,
1515
Widget? trailingWidget,
@@ -20,7 +20,7 @@ DropdownMenuEntry<T> buildDropdownMenuEntry<T>(
2020
? getGoogleFontSafely(fontFamily).fontFamily ?? defaultFontFamily
2121
: defaultFontFamily;
2222
Widget? labelWidget;
23-
if (subLabel != null) {
23+
if (subLabel.isNotEmpty) {
2424
labelWidget = Column(
2525
crossAxisAlignment: CrossAxisAlignment.start,
2626
children: [

frontend/rust-lib/build-tool/flowy-codegen/src/protobuf_file/mod.rs

Lines changed: 58 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -76,64 +76,64 @@ pub fn dart_gen(crate_name: &str) {
7676
}
7777
}
7878

79-
#[allow(unused_variables)]
80-
fn ts_gen(crate_name: &str, dest_folder_name: &str, project: Project) {
81-
// 1. generate the proto files to proto_file_dir
82-
#[cfg(feature = "proto_gen")]
83-
let proto_crates = gen_proto_files(crate_name);
84-
85-
for proto_crate in proto_crates {
86-
let mut proto_file_paths = vec![];
87-
let mut file_names = vec![];
88-
let proto_file_output_path = proto_crate
89-
.proto_output_path()
90-
.to_str()
91-
.unwrap()
92-
.to_string();
93-
let protobuf_output_path = proto_crate
94-
.protobuf_crate_path()
95-
.to_str()
96-
.unwrap()
97-
.to_string();
98-
99-
for (path, file_name) in WalkDir::new(&proto_file_output_path)
100-
.into_iter()
101-
.filter_map(|e| e.ok())
102-
.map(|e| {
103-
let path = e.path().to_str().unwrap().to_string();
104-
let file_name = e.path().file_stem().unwrap().to_str().unwrap().to_string();
105-
(path, file_name)
106-
})
107-
{
108-
if path.ends_with(".proto") {
109-
// https://stackoverflow.com/questions/49077147/how-can-i-force-build-rs-to-run-again-without-cleaning-my-whole-project
110-
println!("cargo:rerun-if-changed={}", path);
111-
proto_file_paths.push(path);
112-
file_names.push(file_name);
113-
}
114-
}
115-
let protoc_bin_path = protoc_bin_vendored::protoc_bin_path().unwrap();
116-
117-
// 2. generate the protobuf files(Dart)
118-
#[cfg(feature = "ts")]
119-
generate_ts_protobuf_files(
120-
dest_folder_name,
121-
&proto_file_output_path,
122-
&proto_file_paths,
123-
&file_names,
124-
&protoc_bin_path,
125-
&project,
126-
);
127-
128-
// 3. generate the protobuf files(Rust)
129-
generate_rust_protobuf_files(
130-
&protoc_bin_path,
131-
&proto_file_paths,
132-
&proto_file_output_path,
133-
&protobuf_output_path,
134-
);
135-
}
136-
}
79+
// #[allow(unused_variables)]
80+
// fn ts_gen(crate_name: &str, dest_folder_name: &str, project: Project) {
81+
// // 1. generate the proto files to proto_file_dir
82+
// #[cfg(feature = "proto_gen")]
83+
// let proto_crates = gen_proto_files(crate_name);
84+
//
85+
// for proto_crate in proto_crates {
86+
// let mut proto_file_paths = vec![];
87+
// let mut file_names = vec![];
88+
// let proto_file_output_path = proto_crate
89+
// .proto_output_path()
90+
// .to_str()
91+
// .unwrap()
92+
// .to_string();
93+
// let protobuf_output_path = proto_crate
94+
// .protobuf_crate_path()
95+
// .to_str()
96+
// .unwrap()
97+
// .to_string();
98+
//
99+
// for (path, file_name) in WalkDir::new(&proto_file_output_path)
100+
// .into_iter()
101+
// .filter_map(|e| e.ok())
102+
// .map(|e| {
103+
// let path = e.path().to_str().unwrap().to_string();
104+
// let file_name = e.path().file_stem().unwrap().to_str().unwrap().to_string();
105+
// (path, file_name)
106+
// })
107+
// {
108+
// if path.ends_with(".proto") {
109+
// // https://stackoverflow.com/questions/49077147/how-can-i-force-build-rs-to-run-again-without-cleaning-my-whole-project
110+
// println!("cargo:rerun-if-changed={}", path);
111+
// proto_file_paths.push(path);
112+
// file_names.push(file_name);
113+
// }
114+
// }
115+
// let protoc_bin_path = protoc_bin_vendored::protoc_bin_path().unwrap();
116+
//
117+
// // 2. generate the protobuf files(Dart)
118+
// #[cfg(feature = "ts")]
119+
// generate_ts_protobuf_files(
120+
// dest_folder_name,
121+
// &proto_file_output_path,
122+
// &proto_file_paths,
123+
// &file_names,
124+
// &protoc_bin_path,
125+
// &project,
126+
// );
127+
//
128+
// // 3. generate the protobuf files(Rust)
129+
// generate_rust_protobuf_files(
130+
// &protoc_bin_path,
131+
// &proto_file_paths,
132+
// &proto_file_output_path,
133+
// &protobuf_output_path,
134+
// );
135+
// }
136+
// }
137137

138138
fn generate_rust_protobuf_files(
139139
protoc_bin_path: &Path,

0 commit comments

Comments
 (0)