-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
225 additions
and
66 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
frontend/appflowy_flutter/lib/workspace/application/settings/ai/settings_ai_bloc.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import 'package:appflowy/user/application/user_listener.dart'; | ||
import 'package:appflowy/user/application/user_service.dart'; | ||
import 'package:appflowy_backend/log.dart'; | ||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; | ||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; | ||
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; | ||
import 'package:appflowy_result/appflowy_result.dart'; | ||
import 'package:bloc/bloc.dart'; | ||
import 'package:freezed_annotation/freezed_annotation.dart'; | ||
|
||
part 'settings_ai_bloc.freezed.dart'; | ||
|
||
class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> { | ||
SettingsAIBloc(this.userProfile) | ||
: _userListener = UserListener(userProfile: userProfile), | ||
_userService = UserBackendService(userId: userProfile.id), | ||
super(SettingsAIState(userProfile: userProfile)) { | ||
_dispatch(); | ||
} | ||
|
||
final UserBackendService _userService; | ||
final UserListener _userListener; | ||
final UserProfilePB userProfile; | ||
|
||
@override | ||
Future<void> close() async { | ||
await _userListener.stop(); | ||
return super.close(); | ||
} | ||
|
||
void _dispatch() { | ||
on<SettingsAIEvent>((event, emit) { | ||
event.when( | ||
started: () { | ||
_userListener.start(onProfileUpdated: _onProfileUpdated); | ||
}, | ||
didReceiveUserProfile: (userProfile) => | ||
emit(state.copyWith(userProfile: userProfile)), | ||
updateUserOpenAIKey: (openAIKey) { | ||
_userService.updateUserProfile(openAIKey: openAIKey).then((result) { | ||
result.fold( | ||
(l) => null, | ||
(err) => Log.error(err), | ||
); | ||
}); | ||
}, | ||
updateUserStabilityAIKey: (stabilityAIKey) { | ||
_userService | ||
.updateUserProfile(stabilityAiKey: stabilityAIKey) | ||
.then((result) { | ||
result.fold( | ||
(l) => null, | ||
(err) => Log.error(err), | ||
); | ||
}); | ||
}, | ||
); | ||
}); | ||
} | ||
|
||
void _onProfileUpdated( | ||
FlowyResult<UserProfilePB, FlowyError> userProfileOrFailed, | ||
) => | ||
userProfileOrFailed.fold( | ||
(newUserProfile) => | ||
add(SettingsAIEvent.didReceiveUserProfile(newUserProfile)), | ||
(err) => Log.error(err), | ||
); | ||
} | ||
|
||
@freezed | ||
class SettingsAIEvent with _$SettingsAIEvent { | ||
const factory SettingsAIEvent.started() = _Started; | ||
|
||
const factory SettingsAIEvent.updateUserOpenAIKey(String openAIKey) = | ||
_UpdateUserOpenaiKey; | ||
|
||
const factory SettingsAIEvent.updateUserStabilityAIKey( | ||
String stabilityAIKey, | ||
) = _UpdateUserStabilityAIKey; | ||
|
||
const factory SettingsAIEvent.didReceiveUserProfile( | ||
UserProfilePB newUserProfile, | ||
) = _DidReceiveUserProfile; | ||
} | ||
|
||
@freezed | ||
class SettingsAIState with _$SettingsAIState { | ||
const factory SettingsAIState({ | ||
required UserProfilePB userProfile, | ||
}) = _SettingsAIState; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_ai_view.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
import 'package:appflowy/generated/locale_keys.g.dart'; | ||
import 'package:appflowy/workspace/application/settings/ai/settings_ai_bloc.dart'; | ||
import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart'; | ||
import 'package:appflowy/workspace/presentation/settings/shared/settings_category.dart'; | ||
import 'package:appflowy/workspace/presentation/settings/shared/settings_dashed_divider.dart'; | ||
import 'package:appflowy/workspace/presentation/settings/shared/settings_input_field.dart'; | ||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart'; | ||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart'; | ||
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; | ||
import 'package:easy_localization/easy_localization.dart'; | ||
import 'package:flowy_infra_ui/style_widget/text.dart'; | ||
import 'package:flowy_infra_ui/widget/spacing.dart'; | ||
import 'package:flutter_bloc/flutter_bloc.dart'; | ||
|
||
class SettingsAIView extends StatelessWidget { | ||
const SettingsAIView({ | ||
super.key, | ||
required this.userProfile, | ||
}); | ||
|
||
final UserProfilePB userProfile; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return BlocProvider<SettingsAIBloc>( | ||
create: (context) => | ||
SettingsAIBloc(userProfile)..add(const SettingsAIEvent.started()), | ||
child: BlocBuilder<SettingsAIBloc, SettingsAIState>( | ||
builder: (context, state) { | ||
return SettingsBody( | ||
title: LocaleKeys.settings_aiPage_title.tr(), | ||
children: [ | ||
SettingsCategory( | ||
title: LocaleKeys.settings_aiPage_keys_title.tr(), | ||
children: [ | ||
SettingsInputField( | ||
label: LocaleKeys.settings_aiPage_keys_openAILabel.tr(), | ||
tooltip: LocaleKeys.settings_aiPage_keys_openAITooltip.tr(), | ||
placeholder: | ||
LocaleKeys.settings_aiPage_keys_openAIHint.tr(), | ||
value: state.userProfile.openaiKey, | ||
obscureText: true, | ||
onSave: (key) => context | ||
.read<SettingsAIBloc>() | ||
.add(SettingsAIEvent.updateUserOpenAIKey(key)), | ||
), | ||
SettingsInputField( | ||
label: | ||
LocaleKeys.settings_aiPage_keys_stabilityAILabel.tr(), | ||
tooltip: | ||
LocaleKeys.settings_aiPage_keys_stabilityAITooltip.tr(), | ||
placeholder: | ||
LocaleKeys.settings_aiPage_keys_stabilityAIHint.tr(), | ||
value: state.userProfile.stabilityAiKey, | ||
obscureText: true, | ||
onSave: (key) => context | ||
.read<SettingsAIBloc>() | ||
.add(SettingsAIEvent.updateUserStabilityAIKey(key)), | ||
), | ||
const SettingsDashedDivider(), | ||
// TODO(Nathan): Propagate this value from `state` | ||
const _AIChatToggle(value: false), | ||
], | ||
), | ||
], | ||
); | ||
}, | ||
), | ||
); | ||
} | ||
} | ||
|
||
class _AIChatToggle extends StatelessWidget { | ||
const _AIChatToggle({required this.value}); | ||
|
||
final bool value; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Row( | ||
children: [ | ||
const Expanded( | ||
child: FlowyText.regular( | ||
'Enable AI Chat', // TODO(Nathan): Change and localize in `aiPage` in en.json | ||
fontSize: 16, | ||
), | ||
), | ||
const HSpace(16), | ||
Toggle( | ||
style: ToggleStyle.big, | ||
value: value, | ||
onChanged: (_) { | ||
// TODO(Nathan): Add this event | ||
// context | ||
// .read<SettingsAIBloc>() | ||
// .add(SettingsAIEvent.toggleAIChat()); | ||
}, | ||
), | ||
], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters