diff --git a/assets/protected.png b/assets/protected.png new file mode 100644 index 000000000..551004a88 Binary files /dev/null and b/assets/protected.png differ diff --git a/lib/ui/sign_in_header_widget.dart b/lib/ui/sign_in_header_widget.dart index d21953fe1..af2f9e385 100644 --- a/lib/ui/sign_in_header_widget.dart +++ b/lib/ui/sign_in_header_widget.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:dots_indicator/dots_indicator.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:photos/core/configuration.dart'; @@ -7,7 +8,6 @@ import 'package:photos/core/event_bus.dart'; import 'package:photos/events/subscription_purchased_event.dart'; import 'package:photos/services/billing_service.dart'; import 'package:photos/ui/email_entry_page.dart'; -import 'package:photos/ui/expansion_card.dart'; import 'package:photos/ui/login_page.dart'; import 'package:photos/ui/password_entry_page.dart'; import 'package:photos/ui/password_reentry_page.dart'; @@ -22,6 +22,7 @@ class SignInHeader extends StatefulWidget { class _SignInHeaderState extends State { StreamSubscription _userAuthEventSubscription; + double _featureIndex = 0; @override void initState() { @@ -49,164 +50,327 @@ class _SignInHeaderState extends State { } } - SingleChildScrollView _getBody(BuildContext context) { - return SingleChildScrollView( - child: Container( - padding: EdgeInsets.fromLTRB(8, 24, 8, 8), - child: Column( - children: [ - Text.rich( - TextSpan( - children: [ - TextSpan( - text: "with ", - style: TextStyle( - fontSize: 16, - ), - ), - TextSpan( - text: "ente", - style: TextStyle( - fontWeight: FontWeight.bold, - fontFamily: 'Montserrat', - fontSize: 16, - ), - ), - ], - ), - textAlign: TextAlign.center, - ), - Padding( - padding: EdgeInsets.all(2), - ), - Text.rich( - TextSpan( - children: [ - TextSpan( - text: "your ", - style: TextStyle( - fontSize: 16, - ), - ), - TextSpan( - text: "memories", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - ), - ), - TextSpan( - text: " are", - style: TextStyle( - fontSize: 16, - ), - ), - ], - ), - textAlign: TextAlign.center, - ), - Padding( - padding: EdgeInsets.all(8), - ), - ExpansionCard( - title: Text('protected'), - color: Theme.of(context).accentColor, - margin: EdgeInsets.all(0), - children: [ - Align( - alignment: Alignment.bottomLeft, - child: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Text( - 'only visible to you as they are encrypted by your master key', - ), + Widget _getBody(BuildContext context) { + return Container( + padding: EdgeInsets.fromLTRB(8, 24, 8, 8), + child: Column( + children: [ + Text.rich( + TextSpan( + children: [ + TextSpan( + text: "with ", + style: TextStyle( + fontSize: 16, ), ), - ], - ), - ExpansionCard( - title: Text('preserved'), - color: Theme.of(context).accentColor, - margin: EdgeInsets.all(0), - children: [ - Align( - alignment: Alignment.bottomLeft, - child: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Text( - 'stored in multiple locations including an underground fallout shelter', - ), - ), - ), - ], - ), - ExpansionCard( - title: Text('accessible'), - color: Theme.of(context).accentColor, - margin: EdgeInsets.all(0), - children: [ - Align( - alignment: Alignment.bottomLeft, - child: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Text( - 'available on all your devices', - ), - ), - ), - ], - ), - Padding( - padding: EdgeInsets.all(10), - ), - Padding( - padding: const EdgeInsets.fromLTRB(60, 0, 60, 0), - ), - Container( - width: double.infinity, - height: 64, - padding: const EdgeInsets.fromLTRB(80, 0, 80, 0), - child: RaisedButton( - child: Text( - "sign up", + TextSpan( + text: "ente", style: TextStyle( fontWeight: FontWeight.bold, - fontSize: 18, - letterSpacing: 1.0, + fontFamily: 'Montserrat', + fontSize: 16, + ), + ), + ], + ), + textAlign: TextAlign.center, + ), + Padding( + padding: EdgeInsets.all(2), + ), + Text.rich( + TextSpan( + children: [ + TextSpan( + text: "your ", + style: TextStyle( + fontSize: 16, + ), + ), + TextSpan( + text: "memories", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + TextSpan( + text: " are", + style: TextStyle( + fontSize: 16, + ), + ), + ], + ), + textAlign: TextAlign.center, + ), + Padding( + padding: EdgeInsets.all(18), + ), + _getFeatureSlider(), + new DotsIndicator( + dotsCount: 3, + position: _featureIndex, + decorator: DotsDecorator( + color: Colors.white24, // Inactive color + activeColor: Theme.of(context).buttonColor, + ), + ), + Padding( + padding: EdgeInsets.all(20), + ), + _getSignUpButton(context), + GestureDetector( + behavior: HitTestBehavior.translucent, + child: Container( + width: double.infinity, + padding: EdgeInsets.all(28), + child: Center( + child: Text( + "sign in", + style: TextStyle( + fontSize: 16, + color: Theme.of(context).buttonColor, + fontWeight: FontWeight.bold, + letterSpacing: 0.6, + ), + ), + ), + ), + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) { + return LoginPage(); + }, + ), + ); + }, + ), + Divider( + height: 4, + color: Theme.of(context).buttonColor.withOpacity(0.5), + ), + ], + ), + ); + } + + Container _getSignUpButton(BuildContext context) { + return Container( + width: 340, + height: 54, + padding: const EdgeInsets.fromLTRB(80, 0, 80, 0), + child: RaisedButton( + child: Text( + "sign up", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + letterSpacing: 1.0, + ), + textAlign: TextAlign.center, + ), + onPressed: () { + var page; + if (Configuration.instance.getToken() == null) { + page = EmailEntryPage(); + } else { + // No key + if (Configuration.instance.getKeyAttributes() == null) { + // Never had a key + page = PasswordEntryPage(); + } else if (Configuration.instance.getKey() == null) { + // Yet to decrypt the key + page = PasswordReentryPage(); + } else { + // All is well, user just has not subscribed + page = SubscriptionPage(isOnboarding: true); + } + } + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) { + return page; + }, + ), + ); + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + ), + ); + } + + ConstrainedBox _getFeatureSlider() { + return ConstrainedBox( + constraints: BoxConstraints( + maxHeight: 290, + ), + child: PageView( + children: [ + _getProtectedFeature(), + _getPreservedFeature(), + _getAccessibleFeature(), + ], + onPageChanged: (index) { + setState(() { + _featureIndex = double.parse(index.toString()); + }); + }, + ), + ); + } + + Widget _getProtectedFeature() { + return Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Image.asset( + "assets/protected.png", + height: 170, + ), + Padding(padding: EdgeInsets.all(10)), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "protected", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + Padding(padding: EdgeInsets.all(6)), + Container( + child: Text( + "encrypted by your master key,", + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white70, + ), + ), + ), + Padding(padding: EdgeInsets.all(2)), + Container( + child: Text( + "only visible to you", + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white70, + ), + ), + ), + ], + ), + ), + ], + ), + ); + } + + Widget _getPreservedFeature() { + return Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Image.asset( + "assets/protected.png", + height: 170, + ), + Padding(padding: EdgeInsets.all(10)), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "preserved", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + Padding(padding: EdgeInsets.all(6)), + Container( + child: Text( + "reliably saved to multiple locations,", + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white70, + ), + ), + ), + Padding(padding: EdgeInsets.all(2)), + Container( + child: Text( + "including a fallout shelter", + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white70, + ), + ), + ), + ], + ), + ), + ], + ), + ); + } + + Widget _getAccessibleFeature() { + return Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Image.asset( + "assets/protected.png", + height: 170, + ), + Padding(padding: EdgeInsets.all(10)), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "accessible", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), - onPressed: _navigateToSignUpPage, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - ), - ), - GestureDetector( - behavior: HitTestBehavior.translucent, - child: Container( - width: double.infinity, - padding: EdgeInsets.all(28), - child: Center( + Padding(padding: EdgeInsets.all(6)), + Container( child: Text( - "sign in", + "available on all your devices,", + textAlign: TextAlign.center, style: TextStyle( - fontSize: 16, - color: Theme.of(context).buttonColor, - fontWeight: FontWeight.bold, - letterSpacing: 0.6, + color: Colors.white70, ), ), ), + ], + ), + ), + Padding(padding: EdgeInsets.all(2)), + Container( + child: Text( + "android, ios and desktop", + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white70, ), - onTap: _navigateToSignInPage, ), - Divider( - height: 4, - color: Theme.of(context).buttonColor.withOpacity(0.5), - ), - ], - ), + ), + ], ), ); } diff --git a/pubspec.lock b/pubspec.lock index f003aff1a..985ea4e08 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -169,6 +169,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0" + dots_indicator: + dependency: "direct main" + description: + name: dots_indicator + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" event_bus: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 56f823e92..c9d2d83b3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -77,6 +77,7 @@ dependencies: quiver: ^3.0.1 move_to_background: ^1.0.2 loading_animations: ^2.1.0 + dots_indicator: ^2.0.0 dev_dependencies: flutter_test: