diff --git a/assets/around_the_world.svg b/assets/around_the_world.svg
new file mode 100644
index 000000000..a17b5950d
--- /dev/null
+++ b/assets/around_the_world.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/core/configuration.dart b/lib/core/configuration.dart
index 8cd30c876..86ed4340d 100644
--- a/lib/core/configuration.dart
+++ b/lib/core/configuration.dart
@@ -12,10 +12,9 @@ class Configuration {
static final Configuration instance = Configuration._privateConstructor();
static const endpointKey = "endpoint";
- static const tokenKey = "token";
- static const usernameKey = "username";
static const userIDKey = "user_id";
- static const passwordKey = "password";
+ static const emailKey = "email";
+ static const tokenKey = "token";
static const hasOptedForE2EKey = "has_opted_for_e2e_encryption";
static const keyKey = "key";
static const keyEncryptedKey = "encrypted_key";
@@ -50,7 +49,7 @@ class Configuration {
}
String getEndpoint() {
- return _preferences.getString(endpointKey);
+ return "192.168.0.106";
}
String getHttpEndpoint() {
@@ -72,12 +71,12 @@ class Configuration {
await _preferences.setString(tokenKey, token);
}
- String getUsername() {
- return _preferences.getString(usernameKey);
+ String getEmail() {
+ return _preferences.getString(emailKey);
}
- void setUsername(String username) async {
- await _preferences.setString(usernameKey, username);
+ void setEmail(String email) async {
+ await _preferences.setString(emailKey, email);
}
int getUserID() {
@@ -88,14 +87,6 @@ class Configuration {
await _preferences.setInt(userIDKey, userID);
}
- String getPassword() {
- return _preferences.getString(passwordKey);
- }
-
- void setPassword(String password) async {
- await _preferences.setString(passwordKey, password);
- }
-
void setOptInForE2E(bool hasOptedForE2E) async {
await _preferences.setBool(hasOptedForE2EKey, hasOptedForE2E);
}
diff --git a/lib/folder_service.dart b/lib/folder_service.dart
index 29775e92a..907afbf28 100644
--- a/lib/folder_service.dart
+++ b/lib/folder_service.dart
@@ -136,7 +136,7 @@ class FolderSharingService {
try {
return Folder(
null,
- Configuration.instance.getUsername() + "s " + deviceFolder,
+ Configuration.instance.getEmail() + "s " + deviceFolder,
Configuration.instance.getUserID(),
deviceFolder,
Set(),
diff --git a/lib/main.dart b/lib/main.dart
index 250fcbf88..c392738d5 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -109,8 +109,11 @@ class MyApp extends StatelessWidget with WidgetsBindingObserver {
return MaterialApp(
title: _title,
- theme: ThemeData.dark()
- .copyWith(hintColor: Colors.grey, accentColor: Colors.pink[400]),
+ theme: ThemeData.dark().copyWith(
+ hintColor: Colors.grey,
+ accentColor: Colors.pink[400],
+ buttonColor: Colors.pink,
+ ),
home: HomeWidget(_title),
);
}
diff --git a/lib/ui/email_entry_page.dart b/lib/ui/email_entry_page.dart
index 1b1dc9547..5b5f30c4f 100644
--- a/lib/ui/email_entry_page.dart
+++ b/lib/ui/email_entry_page.dart
@@ -1,11 +1,8 @@
-import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
-import 'package:logging/logging.dart';
-import 'package:photos/core/configuration.dart';
-import 'package:photos/ui/ott_verification_page.dart';
-import 'package:photos/utils/dialog_util.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:photos/user_authenticator.dart';
class EmailEntryPage extends StatefulWidget {
EmailEntryPage({Key key}) : super(key: key);
@@ -28,96 +25,44 @@ class _EmailEntryPageState extends State {
}
Widget _getBody() {
- return Container(
- padding: EdgeInsets.all(8),
- child: Column(
- children: [
- TextFormField(
- decoration: InputDecoration(
- hintText: 'email@domain.com',
- contentPadding: EdgeInsets.all(20),
+ return SingleChildScrollView(
+ child: Container(
+ padding: EdgeInsets.all(8),
+ child: Column(
+ children: [
+ SvgPicture.asset(
+ "assets/around_the_world.svg",
+ width: 256,
+ height: 256,
),
- controller: _emailController,
- autofocus: true,
- autocorrect: false,
- keyboardType: TextInputType.emailAddress,
- ),
- Padding(padding: EdgeInsets.all(8)),
- SizedBox(
- width: double.infinity,
- child: RaisedButton(
- onPressed: () {
- _getOtt(_emailController.text);
- },
- padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
- child: Text("Sign In"),
- color: Colors.pink[400],
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(18.0),
- ),
- )),
- ],
- ),
- );
- }
-
- Future _getOtt(String email) async {
- final dialog = createProgressDialog(context, "Please wait...");
- await dialog.show();
- await Dio()
- .get(Configuration.instance.getHttpEndpoint() + "/users/ott",
- queryParameters: {
- "email": email,
- },
- options: Options(
- headers: {
- "X-Auth-Token": Configuration.instance.getToken(),
- },
- ))
- .catchError((e) async {
- Logger("EmailEntryPage").severe(e);
- await dialog.hide();
- _showErrorDialog();
- }).then((response) async {
- await dialog.hide();
- if (response.statusCode == 200) {
- _navigateToVerificationInstructionPage(email);
- } else {
- _showErrorDialog();
- }
- });
- }
-
- void _navigateToVerificationInstructionPage(String email) {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (BuildContext context) {
- return OTTVerificationPage(email);
- },
- ),
- );
- }
-
- _showErrorDialog() {
- AlertDialog alert = AlertDialog(
- title: Text("Oops."),
- content: Text("Sorry, something went wrong. Please try again."),
- actions: [
- FlatButton(
- child: Text("OK"),
- onPressed: () {
- Navigator.of(context).pop();
- },
+ TextFormField(
+ decoration: InputDecoration(
+ hintText: 'email@domain.com',
+ contentPadding: EdgeInsets.all(20),
+ ),
+ controller: _emailController,
+ autofocus: true,
+ autocorrect: false,
+ keyboardType: TextInputType.emailAddress,
+ ),
+ Padding(padding: EdgeInsets.all(8)),
+ SizedBox(
+ width: double.infinity,
+ child: RaisedButton(
+ onPressed: () {
+ UserAuthenticator.instance
+ .getOtt(context, _emailController.text);
+ },
+ padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
+ child: Text("Sign In"),
+ color: Theme.of(context).buttonColor,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(18.0),
+ ),
+ )),
+ ],
),
- ],
- );
-
- // show the dialog
- showDialog(
- context: context,
- builder: (BuildContext context) {
- return alert;
- },
+ ),
);
}
}
diff --git a/lib/ui/gallery_app_bar_widget.dart b/lib/ui/gallery_app_bar_widget.dart
index 846724f6e..14f96b159 100644
--- a/lib/ui/gallery_app_bar_widget.dart
+++ b/lib/ui/gallery_app_bar_widget.dart
@@ -2,11 +2,10 @@ import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:photos/core/configuration.dart';
-import 'package:photos/core/event_bus.dart';
-import 'package:photos/events/remote_sync_event.dart';
import 'package:photos/file_repository.dart';
import 'package:photos/models/selected_files.dart';
-import 'package:photos/ui/setup_page.dart';
+import 'package:photos/ui/email_entry_page.dart';
+import 'package:photos/ui/ott_verification_page.dart';
import 'package:photos/ui/share_folder_widget.dart';
import 'package:photos/utils/dialog_util.dart';
import 'package:photos/utils/file_util.dart';
@@ -41,16 +40,8 @@ class GalleryAppBarWidget extends StatefulWidget
}
class _GalleryAppBarWidgetState extends State {
- bool _hasSyncErrors = false;
- StreamSubscription _subscription;
-
@override
void initState() {
- _subscription = Bus.instance.on().listen((event) {
- setState(() {
- _hasSyncErrors = !event.success;
- });
- });
widget.selectedFiles.addListener(() {
setState(() {});
});
@@ -80,13 +71,13 @@ class _GalleryAppBarWidgetState extends State {
List _getDefaultActions(BuildContext context) {
List actions = List();
- if (_hasSyncErrors || !Configuration.instance.hasConfiguredAccount()) {
+ if (!Configuration.instance.hasConfiguredAccount()) {
actions.add(IconButton(
icon: Icon(Configuration.instance.hasConfiguredAccount()
? Icons.sync_problem
: Icons.sync_disabled),
onPressed: () {
- _openSyncConfiguration(context);
+ _navigateToSignInPage(context);
},
));
} else if (widget.type == GalleryAppBarType.local_folder &&
@@ -179,20 +170,14 @@ class _GalleryAppBarWidgetState extends State {
widget.selectedFiles.clearAll();
}
- void _openSyncConfiguration(BuildContext context) {
- final page = SetupPage();
+ void _navigateToSignInPage(BuildContext context) {
Navigator.of(context).push(
MaterialPageRoute(
- settings: RouteSettings(name: "/setup"),
builder: (BuildContext context) {
- return page;
+ // return OTTVerificationPage("hello@ente.io");
+ return EmailEntryPage();
},
),
);
}
-
- void dispose() {
- _subscription.cancel();
- super.dispose();
- }
}
diff --git a/lib/ui/ott_verification_page.dart b/lib/ui/ott_verification_page.dart
index 3c4399d61..5f65babeb 100644
--- a/lib/ui/ott_verification_page.dart
+++ b/lib/ui/ott_verification_page.dart
@@ -1,6 +1,9 @@
+import 'dart:ui';
+
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart';
+import 'package:photos/user_authenticator.dart';
class OTTVerificationPage extends StatefulWidget {
final String email;
@@ -29,6 +32,8 @@ class _OTTVerificationPageState extends State {
padding: EdgeInsets.fromLTRB(8, 64, 8, 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.end,
children: [
SvgPicture.asset(
"assets/email_sent.svg",
@@ -38,22 +43,22 @@ class _OTTVerificationPageState extends State {
Padding(padding: EdgeInsets.all(12)),
Text.rich(
TextSpan(
- text: "We've sent a mail to ",
style: TextStyle(fontSize: 18),
children: [
+ TextSpan(text: "We've sent a mail to "),
TextSpan(
text: widget.email,
style: TextStyle(
- decoration: TextDecoration.underline,
+ color: Theme.of(context).accentColor,
)),
- // can add more TextSpans here...
+ TextSpan(text: "."),
],
),
textAlign: TextAlign.center,
),
Padding(padding: EdgeInsets.all(12)),
Text(
- "Please check your inbox (and spam folders) to complete the verification.",
+ "Please check your inbox (and spam) to complete verification.",
textAlign: TextAlign.center,
),
Padding(padding: EdgeInsets.all(12)),
@@ -63,11 +68,45 @@ class _OTTVerificationPageState extends State {
contentPadding: EdgeInsets.all(20),
),
controller: _verificationCodeController,
- autofocus: true,
+ autofocus: false,
autocorrect: false,
keyboardType: TextInputType.visiblePassword,
textAlign: TextAlign.center,
+ onChanged: (_) {
+ setState(() {});
+ },
),
+ Padding(padding: EdgeInsets.all(8)),
+ SizedBox(
+ width: double.infinity,
+ child: RaisedButton(
+ onPressed: _verificationCodeController.text == null ||
+ _verificationCodeController.text.isEmpty
+ ? null
+ : () {
+ UserAuthenticator.instance.getCredentials(context,
+ widget.email, _verificationCodeController.text);
+ },
+ padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
+ child: Text(
+ "Sign In",
+ ),
+ color: Colors.pink,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(18.0),
+ ),
+ )),
+ TextButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ child: Text(
+ "Did not get email?",
+ style: TextStyle(
+ decoration: TextDecoration.underline,
+ fontSize: 12,
+ ),
+ ))
],
),
),
diff --git a/lib/user_authenticator.dart b/lib/user_authenticator.dart
index a9795a6a7..138be3e4d 100644
--- a/lib/user_authenticator.dart
+++ b/lib/user_authenticator.dart
@@ -1,9 +1,13 @@
import 'package:dio/dio.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/configuration.dart';
import 'package:photos/core/event_bus.dart';
import 'package:photos/events/user_authenticated_event.dart';
+import 'package:photos/ui/ott_verification_page.dart';
+import 'package:photos/utils/dialog_util.dart';
class UserAuthenticator {
final _dio = Dio();
@@ -14,6 +18,60 @@ class UserAuthenticator {
static final UserAuthenticator instance =
UserAuthenticator._privateConstructor();
+ Future getOtt(BuildContext context, String email) async {
+ final dialog = createProgressDialog(context, "Please wait...");
+ await dialog.show();
+ await Dio().get(
+ Configuration.instance.getHttpEndpoint() + "/users/ott",
+ queryParameters: {
+ "email": email,
+ },
+ ).catchError((e) async {
+ _logger.severe(e);
+ await dialog.hide();
+ showGenericErrorDialog(context);
+ }).then((response) async {
+ await dialog.hide();
+ if (response.statusCode == 200) {
+ Navigator.of(context).push(
+ MaterialPageRoute(
+ builder: (BuildContext context) {
+ return OTTVerificationPage(email);
+ },
+ ),
+ );
+ } else {
+ showGenericErrorDialog(context);
+ }
+ });
+ }
+
+ Future getCredentials(
+ BuildContext context, String email, String ott) async {
+ final dialog = createProgressDialog(context, "Please wait...");
+ await dialog.show();
+ await Dio().get(
+ Configuration.instance.getHttpEndpoint() + "/users/credentials",
+ queryParameters: {
+ "email": email,
+ "ott": ott,
+ },
+ ).catchError((e) async {
+ _logger.severe(e);
+ await dialog.hide();
+ showGenericErrorDialog(context);
+ }).then((response) async {
+ await dialog.hide();
+ if (response.statusCode == 200) {
+ _saveConfiguration(email, response);
+ Navigator.of(context).pop();
+ } else {
+ showErrorDialog(
+ context, "Oops.", "Verification failed, please try again.");
+ }
+ });
+ }
+
Future login(String username, String password) {
return _dio.post(
Configuration.instance.getHttpEndpoint() + "/users/authenticate",
@@ -22,7 +80,7 @@ class UserAuthenticator {
"password": password,
}).then((response) {
if (response.statusCode == 200 && response.data != null) {
- _saveConfiguration(username, password, response);
+ _saveConfiguration(username, response);
Bus.instance.fire(UserAuthenticatedEvent());
return true;
} else {
@@ -41,7 +99,7 @@ class UserAuthenticator {
"password": password,
}).then((response) {
if (response.statusCode == 200 && response.data != null) {
- _saveConfiguration(username, password, response);
+ _saveConfiguration(username, response);
return true;
} else {
if (response.data != null && response.data["message"] != null) {
@@ -68,9 +126,9 @@ class UserAuthenticator {
);
}
- void _saveConfiguration(String username, String password, Response response) {
- Configuration.instance.setUsername(username);
- Configuration.instance.setPassword(password);
+ void _saveConfiguration(String email, Response response) {
+ _logger.info("Saving configuration " + response.data.toString());
+ Configuration.instance.setEmail(email);
Configuration.instance.setUserID(response.data["id"]);
Configuration.instance.setToken(response.data["token"]);
final String encryptedKey = response.data["encryptedKey"];
diff --git a/lib/utils/dialog_util.dart b/lib/utils/dialog_util.dart
index 17285d9ae..2333018ee 100644
--- a/lib/utils/dialog_util.dart
+++ b/lib/utils/dialog_util.dart
@@ -20,3 +20,30 @@ ProgressDialog createProgressDialog(BuildContext context, String message) {
);
return dialog;
}
+
+void showErrorDialog(BuildContext context, String title, String content) {
+ AlertDialog alert = AlertDialog(
+ title: Text(title),
+ content: Text(content),
+ actions: [
+ FlatButton(
+ child: Text("OK"),
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ ),
+ ],
+ );
+
+ showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ return alert;
+ },
+ );
+}
+
+void showGenericErrorDialog(BuildContext context) {
+ showErrorDialog(
+ context, "Oops.", "Sorry, something went wrong. Please try again.");
+}
diff --git a/pubspec.lock b/pubspec.lock
index 8f76665da..087f18737 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -272,6 +272,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.3.3"
+ flutter_svg:
+ dependency: "direct main"
+ description:
+ name: flutter_svg
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.18.1"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -408,6 +415,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
+ path_drawing:
+ dependency: transitive
+ description:
+ name: path_drawing
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.4.1+1"
+ path_parsing:
+ dependency: transitive
+ description:
+ name: path_parsing
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.1.4"
path_provider:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index d86e6ba75..fee38d86d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -62,6 +62,7 @@ dependencies:
computer: ^1.0.2
flutter_secure_storage: ^3.3.3
uni_links: ^0.4.0
+ flutter_svg: ^0.18.1
dev_dependencies:
flutter_test:
@@ -78,6 +79,8 @@ flutter_icons:
# The following section is specific to Flutter.
flutter:
+ assets:
+ - assets/
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in