Add hook to change email
This commit is contained in:
parent
d8677970c1
commit
5260279beb
3
lib/events/email_changed_event.dart
Normal file
3
lib/events/email_changed_event.dart
Normal file
|
@ -0,0 +1,3 @@
|
|||
import 'package:photos/events/event.dart';
|
||||
|
||||
class EmailChangedEvent extends Event {}
|
|
@ -9,6 +9,7 @@ import 'package:photos/core/configuration.dart';
|
|||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/core/network.dart';
|
||||
import 'package:photos/db/public_keys_db.dart';
|
||||
import 'package:photos/events/email_changed_event.dart';
|
||||
import 'package:photos/events/two_factor_status_change_event.dart';
|
||||
import 'package:photos/models/key_attributes.dart';
|
||||
import 'package:photos/models/key_gen_result.dart';
|
||||
|
@ -37,34 +38,34 @@ class UserService {
|
|||
|
||||
static final UserService instance = UserService._privateConstructor();
|
||||
|
||||
Future<void> getOtt(BuildContext context, String email) async {
|
||||
Future<void> getOtt(
|
||||
BuildContext context,
|
||||
String email, {
|
||||
bool isChangeEmail = false,
|
||||
}) async {
|
||||
final dialog = createProgressDialog(context, "please wait...");
|
||||
await dialog.show();
|
||||
await _dio.get(
|
||||
_config.getHttpEndpoint() + "/users/ott",
|
||||
queryParameters: {
|
||||
"email": email,
|
||||
"purpose": isChangeEmail ? "change" : ""
|
||||
},
|
||||
).catchError((e) async {
|
||||
_logger.severe(e);
|
||||
}).then((response) async {
|
||||
await dialog.hide();
|
||||
if (response != null) {
|
||||
if (response.statusCode == 200) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return OTTVerificationPage();
|
||||
},
|
||||
),
|
||||
);
|
||||
} else if (response.statusCode == 403) {
|
||||
showErrorDialog(
|
||||
context,
|
||||
"please wait...",
|
||||
"we are currently not accepting new registrations. you have been added to the waitlist and we will let you know once we are ready for you.",
|
||||
);
|
||||
}
|
||||
if (response != null && response.statusCode == 200) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return OTTVerificationPage(
|
||||
email,
|
||||
isChangeEmail: isChangeEmail,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
showGenericErrorDialog(context);
|
||||
}
|
||||
|
@ -178,6 +179,50 @@ class UserService {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> changeEmail(
|
||||
BuildContext context,
|
||||
String email,
|
||||
String ott,
|
||||
) async {
|
||||
final dialog = createProgressDialog(context, "please wait...");
|
||||
await dialog.show();
|
||||
try {
|
||||
final response = await _dio.post(
|
||||
_config.getHttpEndpoint() + "/users/change-email",
|
||||
data: {
|
||||
"email": email,
|
||||
"ott": ott,
|
||||
},
|
||||
options: Options(
|
||||
headers: {
|
||||
"X-Auth-Token": _config.getToken(),
|
||||
},
|
||||
),
|
||||
);
|
||||
await dialog.hide();
|
||||
if (response != null && response.statusCode == 200) {
|
||||
showToast("email changed to " + email);
|
||||
_config.setEmail(email);
|
||||
Navigator.of(context).popUntil((route) => route.isFirst);
|
||||
Bus.instance.fire(EmailChangedEvent());
|
||||
return;
|
||||
}
|
||||
showErrorDialog(context, "oops", "verification failed, please try again");
|
||||
} on DioError catch (e) {
|
||||
await dialog.hide();
|
||||
if (e.response != null && e.response.statusCode == 403) {
|
||||
showErrorDialog(context, "oops", "this email is already in use");
|
||||
} else {
|
||||
showErrorDialog(context, "incorrect code",
|
||||
"authentication failed, please try again");
|
||||
}
|
||||
} catch (e) {
|
||||
await dialog.hide();
|
||||
_logger.severe(e);
|
||||
showErrorDialog(context, "oops", "verification failed, please try again");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setAttributes(KeyGenResult result) async {
|
||||
try {
|
||||
final name = _config.getName();
|
||||
|
|
78
lib/ui/change_email_dialog.dart
Normal file
78
lib/ui/change_email_dialog.dart
Normal file
|
@ -0,0 +1,78 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/utils/dialog_util.dart';
|
||||
import 'package:photos/utils/email_util.dart';
|
||||
|
||||
class ChangeEmailDialog extends StatefulWidget {
|
||||
const ChangeEmailDialog({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ChangeEmailDialogState createState() => _ChangeEmailDialogState();
|
||||
}
|
||||
|
||||
class _ChangeEmailDialogState extends State<ChangeEmailDialog> {
|
||||
String _email;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text("enter your email address"),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextFormField(
|
||||
decoration: InputDecoration(
|
||||
hintText: 'email',
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white30,
|
||||
),
|
||||
contentPadding: EdgeInsets.all(12),
|
||||
),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_email = value;
|
||||
});
|
||||
},
|
||||
autocorrect: false,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
initialValue: _email,
|
||||
autofocus: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
"cancel",
|
||||
style: TextStyle(
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
"verify email",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
if (!isValidEmail(_email)) {
|
||||
showErrorDialog(context, "invalid email address",
|
||||
"please enter a valid email address.");
|
||||
return;
|
||||
}
|
||||
UserService.instance.getOtt(context, _email, isChangeEmail: true);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,12 +2,18 @@ import 'dart:ui';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/ui/common_elements.dart';
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/common_elements.dart';
|
||||
|
||||
class OTTVerificationPage extends StatefulWidget {
|
||||
OTTVerificationPage({Key key}) : super(key: key);
|
||||
final String email;
|
||||
final bool isChangeEmail;
|
||||
|
||||
OTTVerificationPage(
|
||||
this.email, {
|
||||
this.isChangeEmail = false,
|
||||
Key key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_OTTVerificationPageState createState() => _OTTVerificationPageState();
|
||||
|
@ -42,7 +48,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
),
|
||||
Padding(padding: EdgeInsets.all(2)),
|
||||
Text(
|
||||
Configuration.instance.getEmail(),
|
||||
widget.email,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).buttonColor,
|
||||
fontSize: 18,
|
||||
|
@ -86,14 +92,19 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
_verificationCodeController.text.isEmpty
|
||||
? null
|
||||
: () {
|
||||
UserService.instance.verifyEmail(
|
||||
context, _verificationCodeController.text);
|
||||
if (widget.isChangeEmail) {
|
||||
UserService.instance.changeEmail(context,
|
||||
widget.email, _verificationCodeController.text);
|
||||
} else {
|
||||
UserService.instance.verifyEmail(
|
||||
context, _verificationCodeController.text);
|
||||
}
|
||||
},
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
FlatButton(
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -102,6 +113,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 12,
|
||||
color: Colors.white.withOpacity(0.7),
|
||||
),
|
||||
)),
|
||||
],
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/change_email_dialog.dart';
|
||||
import 'package:photos/ui/password_entry_page.dart';
|
||||
import 'package:photos/ui/recovery_key_dialog.dart';
|
||||
import 'package:photos/ui/settings/settings_section_title.dart';
|
||||
|
@ -84,24 +85,31 @@ class AccountSectionWidgetState extends State<AccountSectionWidget> {
|
|||
Platform.isIOS
|
||||
? Padding(padding: EdgeInsets.all(2))
|
||||
: Padding(padding: EdgeInsets.all(2)),
|
||||
// GestureDetector(
|
||||
// behavior: HitTestBehavior.translucent,
|
||||
// onTap: () async {
|
||||
// final result = await requestAuthentication();
|
||||
// if (!result) {
|
||||
// showToast("please authenticate to change your email");
|
||||
// return;
|
||||
// }
|
||||
// // showDialog
|
||||
// },
|
||||
// child:
|
||||
// SettingsTextItem(text: "change email", icon: Icons.navigate_next),
|
||||
// ),
|
||||
// Padding(padding: EdgeInsets.all(2)),
|
||||
// Divider(height: 4),
|
||||
// Platform.isIOS
|
||||
// ? Padding(padding: EdgeInsets.all(2))
|
||||
// : Padding(padding: EdgeInsets.all(4)),
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () async {
|
||||
// final result = await requestAuthentication();
|
||||
// if (!result) {
|
||||
// showToast("please authenticate to change your email");
|
||||
// return;
|
||||
// }
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ChangeEmailDialog();
|
||||
},
|
||||
barrierColor: Colors.black.withOpacity(0.85),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
},
|
||||
child:
|
||||
SettingsTextItem(text: "change email", icon: Icons.navigate_next),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(2)),
|
||||
Divider(height: 4),
|
||||
Platform.isIOS
|
||||
? Padding(padding: EdgeInsets.all(2))
|
||||
: Padding(padding: EdgeInsets.all(4)),
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () async {
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/email_changed_event.dart';
|
||||
import 'package:photos/models/user_details.dart';
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/loading_widget.dart';
|
||||
|
@ -18,10 +21,18 @@ class DetailsSectionWidget extends StatefulWidget {
|
|||
|
||||
class _DetailsSectionWidgetState extends State<DetailsSectionWidget> {
|
||||
UserDetails _userDetails;
|
||||
StreamSubscription<EmailChangedEvent> _emailChangedEvent;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchUserDetails();
|
||||
_emailChangedEvent = Bus.instance.on<EmailChangedEvent>().listen((event) {
|
||||
_fetchUserDetails();
|
||||
});
|
||||
}
|
||||
|
||||
void _fetchUserDetails() {
|
||||
UserService.instance.getUserDetails().then((details) {
|
||||
setState(() {
|
||||
_userDetails = details;
|
||||
|
@ -29,6 +40,12 @@ class _DetailsSectionWidgetState extends State<DetailsSectionWidget> {
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_emailChangedEvent.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
|
|
Loading…
Reference in a new issue