Browse Source

chore: enable edit user email (#3286)

Nathan.fooo 1 year ago
parent
commit
1205f0ebf7

+ 9 - 0
frontend/appflowy_flutter/lib/workspace/application/user/settings_user_bloc.dart

@@ -57,6 +57,14 @@ class SettingsUserViewBloc extends Bloc<SettingsUserEvent, SettingsUserState> {
         openHistoricalUser: (HistoricalUserPB historicalUser) async {
           await UserBackendService.openHistoricalUser(historicalUser);
         },
+        updateUserEmail: (String email) {
+          _userService.updateUserProfile(email: email).then((result) {
+            result.fold(
+              (l) => null,
+              (err) => Log.error(err),
+            );
+          });
+        },
       );
     });
   }
@@ -96,6 +104,7 @@ class SettingsUserViewBloc extends Bloc<SettingsUserEvent, SettingsUserState> {
 class SettingsUserEvent with _$SettingsUserEvent {
   const factory SettingsUserEvent.initial() = _Initial;
   const factory SettingsUserEvent.updateUserName(String name) = _UpdateUserName;
+  const factory SettingsUserEvent.updateUserEmail(String email) = _UpdateEmail;
   const factory SettingsUserEvent.updateUserIcon(String iconUrl) =
       _UpdateUserIcon;
   const factory SettingsUserEvent.updateUserOpenAIKey(String openAIKey) =

+ 70 - 0
frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_user_view.dart

@@ -50,6 +50,12 @@ class SettingsUserView extends StatelessWidget {
             mainAxisSize: MainAxisSize.min,
             children: [
               _renderUserNameInput(context),
+
+              if (user.email.isNotEmpty) ...[
+                const VSpace(20),
+                UserEmailInput(user.email)
+              ],
+
               const VSpace(20),
               _renderCurrentIcon(context),
               const VSpace(20),
@@ -174,6 +180,70 @@ class UserNameInputState extends State<UserNameInput> {
   }
 }
 
+@visibleForTesting
+class UserEmailInput extends StatefulWidget {
+  final String email;
+
+  const UserEmailInput(
+    this.email, {
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  UserEmailInputState createState() => UserEmailInputState();
+}
+
+class UserEmailInputState extends State<UserEmailInput> {
+  late TextEditingController _controller;
+
+  Timer? _debounce;
+  final Duration _debounceDuration = const Duration(milliseconds: 500);
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = TextEditingController(text: widget.email);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return TextField(
+      controller: _controller,
+      decoration: InputDecoration(
+        labelText: LocaleKeys.settings_user_email.tr(),
+        labelStyle: Theme.of(context)
+            .textTheme
+            .titleMedium!
+            .copyWith(fontWeight: FontWeight.w500),
+        enabledBorder: UnderlineInputBorder(
+          borderSide:
+              BorderSide(color: Theme.of(context).colorScheme.onBackground),
+        ),
+        focusedBorder: UnderlineInputBorder(
+          borderSide: BorderSide(color: Theme.of(context).colorScheme.primary),
+        ),
+      ),
+      onChanged: (val) {
+        if (_debounce?.isActive ?? false) {
+          _debounce!.cancel();
+        }
+
+        _debounce = Timer(_debounceDuration, () {
+          context
+              .read<SettingsUserViewBloc>()
+              .add(SettingsUserEvent.updateUserEmail(val));
+        });
+      },
+    );
+  }
+
+  @override
+  void dispose() {
+    _controller.dispose();
+    super.dispose();
+  }
+}
+
 class _OpenaiKeyInput extends StatefulWidget {
   final String openAIKey;
   const _OpenaiKeyInput(

+ 1 - 0
frontend/resources/translations/en.json

@@ -305,6 +305,7 @@
     },
     "user": {
       "name": "Name",
+      "email": "Email",
       "icon": "Icon",
       "selectAnIcon": "Select an icon",
       "pleaseInputYourOpenAIKey": "please input your OpenAI key",