Merge pull request #220 from ente-io/home+stories-redesign

Home+stories redesign
This commit is contained in:
Neeraj Gupta 2022-04-26 14:13:39 +05:30 committed by GitHub
commit b8551ebd9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 136 additions and 105 deletions

View file

@ -140,8 +140,8 @@ class _ApkDownloaderDialogState extends State<ApkDownloaderDialog> {
} catch (e) {
Logger("ApkDownloader").severe(e);
AlertDialog alert = AlertDialog(
title: Text("sorry"),
content: Text("the download could not be completed"),
title: Text("Sorry"),
content: Text("The download could not be completed"),
actions: [
TextButton(
child: Text(

View file

@ -1,24 +0,0 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:photos/models/file.dart';
import 'package:photos/ui/thumbnail_widget.dart';
class BlurredFileBackdrop extends StatelessWidget {
final File file;
BlurredFileBackdrop(this.file, {Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 64.0, sigmaY: 64.0),
child: ThumbnailWidget(
file,
fit: BoxFit.cover,
key: Key("memory_backdrop" + file.tag()),
),
);
}
}

View file

@ -1,5 +1,4 @@
import 'package:extended_image/extended_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';
@ -265,7 +264,7 @@ class _DetailPageState extends State<DetailPage> {
file.ownerID != Configuration.instance.getUserID()) {
_logger.severe("Attempt to edit unowned file", UnauthorizedEditError(),
StackTrace.current);
showErrorDialog(context, "sorry",
showErrorDialog(context, "Sorry",
"we don't support editing photos and albums that you don't own yet");
return;
}

View file

@ -11,13 +11,9 @@ import 'package:photos/models/billing_plan.dart';
import 'package:photos/services/billing_service.dart';
import 'package:photos/services/user_service.dart';
import 'package:photos/ui/common/dynamicFAB.dart';
//import 'package:photos/ui/common/report_bug_popup.dart';
//import 'package:photos/ui/common_elements.dart';
import 'package:photos/ui/loading_widget.dart';
import 'package:photos/ui/web_page.dart';
import 'package:photos/utils/data_util.dart';
//import 'package:photos/utils/dialog_util.dart';
//import 'package:photos/utils/email_util.dart';
import 'package:step_progress_indicator/step_progress_indicator.dart';
class EmailEntryPage extends StatefulWidget {

View file

@ -215,7 +215,7 @@ class FadingAppBarState extends State<FadingAppBar> {
} catch (e, s) {
_logger.severe(e, s);
hasError = true;
showToast("sorry, could not add this to favorites!");
showToast("Sorry, could not add this to favorites!");
} finally {
if (shouldBlockUser) {
await dialog.hide();
@ -227,7 +227,7 @@ class FadingAppBarState extends State<FadingAppBar> {
} catch (e, s) {
_logger.severe(e, s);
hasError = true;
showToast("sorry, could not remove this from favorites!");
showToast("Sorry, could not remove this from favorites!");
}
}
return hasError ? oldValue : isLiked;

View file

@ -1,8 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:photos/models/memory.dart';
import 'package:photos/services/memories_service.dart';
import 'package:photos/ui/blurred_file_backdrop.dart';
import 'package:photos/ui/extents_page_view.dart';
import 'package:photos/ui/file_widget.dart';
import 'package:photos/ui/thumbnail_widget.dart';
@ -10,6 +8,7 @@ import 'package:photos/utils/date_time_util.dart';
import 'package:photos/utils/file_util.dart';
import 'package:photos/utils/navigation_util.dart';
import 'package:photos/utils/share_util.dart';
import 'package:step_progress_indicator/step_progress_indicator.dart';
class MemoriesWidget extends StatelessWidget {
const MemoriesWidget({Key key}) : super(key: key);
@ -22,9 +21,14 @@ class MemoriesWidget extends StatelessWidget {
if (snapshot.hasError || !snapshot.hasData || snapshot.data.isEmpty) {
return Container();
} else {
return Padding(
padding: const EdgeInsets.all(8.0),
child: _buildMemories(snapshot.data),
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildMemories(snapshot.data),
Divider(
thickness: 1,
)
],
);
}
},
@ -96,7 +100,7 @@ class _MemoryWidgetState extends State<MemoryWidget> {
},
child: SizedBox(
width: 100,
height: 120,
height: 100,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
@ -109,10 +113,10 @@ class _MemoryWidgetState extends State<MemoryWidget> {
type: MaterialType.transparency,
child: Text(
title,
style: TextStyle(
fontSize: 12,
color: Colors.white60,
),
style: Theme.of(context)
.textTheme
.subtitle1
.copyWith(fontSize: 12),
textAlign: TextAlign.center,
),
),
@ -139,8 +143,8 @@ class _MemoryWidgetState extends State<MemoryWidget> {
),
child: ClipOval(
child: SizedBox(
width: isSeen ? 76 : 72,
height: isSeen ? 76 : 72,
width: isSeen ? 60 : 56,
height: isSeen ? 60 : 56,
child: Hero(
tag: "memories" + memory.file.tag(),
child: ThumbnailWidget(
@ -225,27 +229,69 @@ class _FullScreenMemoryState extends State<FullScreenMemory> {
final file = widget.memories[_index].file;
return Scaffold(
appBar: AppBar(
title: Text(getFormattedDate(
DateTime.fromMicrosecondsSinceEpoch(file.creationTime))),
toolbarHeight: 84,
automaticallyImplyLeading: false,
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StepProgressIndicator(
totalSteps: widget.memories.length,
currentStep: _index + 1,
size: 2,
selectedColor: Colors.white, //same for both themes
unselectedColor: Colors.white.withOpacity(0.4),
),
SizedBox(
height: 18,
),
Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 16),
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.close,
color: Colors.white, //same for both themes
),
),
),
Text(
getFormattedDate(
DateTime.fromMicrosecondsSinceEpoch(file.creationTime)),
style: Theme.of(context).textTheme.subtitle1.copyWith(
fontSize: 14, color: Colors.white), //same for both themes
),
],
),
],
),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.black.withOpacity(0.6),
Colors.black.withOpacity(0.5),
Colors.transparent,
],
stops: const [0, 0.6, 1],
)),
),
backgroundColor: Color(0x00000000),
elevation: 0,
actions: [
IconButton(
icon: Icon(Icons.share),
onPressed: () {
share(context, [file]);
},
),
],
),
extendBodyBehindAppBar: true,
body: Container(
color: Colors.black,
child: Stack(children: [
BlurredFileBackdrop(file),
child: Stack(alignment: Alignment.bottomCenter, children: [
_buildSwiper(),
bottomGradient(),
_buildTitleText(),
_buildIndexText(),
_buildBottomIcons(),
]),
),
);
@ -256,37 +302,50 @@ class _FullScreenMemoryState extends State<FullScreenMemory> {
tag: widget.title,
child: Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.fromLTRB(0, 0, 0, 160),
padding: EdgeInsets.fromLTRB(0, 0, 0, 28),
child: AnimatedOpacity(
opacity: _opacity,
duration: Duration(milliseconds: 500),
child: Material(
type: MaterialType.transparency,
child: Text(
widget.title,
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none),
),
),
child: Text(widget.title,
style: Theme.of(context)
.textTheme
.headline4
.copyWith(color: Colors.white)),
),
),
);
}
Widget _buildIndexText() {
Widget _buildBottomIcons() {
final file = widget.memories[_index].file;
return Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.fromLTRB(0, 0, 0, 20),
child: Text(
(_index + 1).toString() + " / " + widget.memories.length.toString(),
style: TextStyle(
fontSize: 24,
decoration: TextDecoration.none,
color: Colors.white60,
),
),
alignment: Alignment.bottomRight,
padding: EdgeInsets.fromLTRB(0, 0, 26, 20),
child: IconButton(
icon: Icon(
Icons.adaptive.share,
color: Colors.white,
), //same for both themes
onPressed: () {
share(context, [file]);
},
));
}
Widget bottomGradient() {
return Container(
height: 124,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black.withOpacity(0.5), //same for both themes
Colors.transparent,
],
stops: const [0, 0.8],
)),
);
}

View file

@ -701,7 +701,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
await dialog.hide();
if (e is UnsupportedError) {
showErrorDialog(context, "insecure device",
"sorry, we could not generate secure keys on this device.\n\nplease sign up from a different device.");
"Sorry, we could not generate secure keys on this device.\n\nplease sign up from a different device.");
} else {
showGenericErrorDialog(context);
}

View file

@ -304,7 +304,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
if (!_isStripeSubscriber &&
_hasActiveSubscription &&
_currentSubscription.productID != kFreeProductID) {
showErrorDialog(context, "sorry",
showErrorDialog(context, "Sorry",
"please cancel your existing subscription from ${_currentSubscription.paymentProvider} first");
return;
}
@ -314,7 +314,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
await _dialog.hide();
if (usage > plan.storage) {
showErrorDialog(
context, "sorry", "you cannot downgrade to this plan");
context, "Sorry", "you cannot downgrade to this plan");
return;
}
}

View file

@ -29,7 +29,7 @@ class SubscriptionPage extends StatefulWidget {
}) : super(key: key);
@override
State<SubscriptionPage> createState() => _SubscriptionPageState();
State<SubscriptionPage> createState() => _SubscriptionPageState();
}
class _SubscriptionPageState extends State<SubscriptionPage> {
@ -59,8 +59,8 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
final productID = _isActiveStripeSubscriber
? plan.stripeID
: Platform.isAndroid
? plan.androidID
: plan.iosID;
? plan.androidID
: plan.iosID;
return productID != null && productID.isNotEmpty;
}).toList();
_freePlan = billingPlans.freePlan;
@ -177,7 +177,7 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
widgets.add(ValidityWidget(currentSubscription: _currentSubscription));
}
if ( _currentSubscription.productID == kFreeProductID) {
if (_currentSubscription.productID == kFreeProductID) {
if (widget.isOnboarding) {
widgets.add(SkipSubscriptionWidget(freePlan: _freePlan));
}
@ -257,7 +257,7 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
if (isActive) {
return;
}
showErrorDialog(context, "sorry",
showErrorDialog(context, "Sorry",
"please visit web.ente.io to manage your subscription");
},
child: SubscriptionPlanWidget(
@ -311,13 +311,13 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
if (usage > plan.storage) {
await _dialog.hide();
showErrorDialog(
context, "sorry", "you cannot downgrade to this plan");
context, "Sorry", "you cannot downgrade to this plan");
return;
}
}
final ProductDetailsResponse response =
await InAppPurchaseConnection.instance
.queryProductDetails({productID});
await InAppPurchaseConnection.instance
.queryProductDetails({productID});
if (response.notFoundIDs.isNotEmpty) {
_logger.severe("Could not find products: " +
response.notFoundIDs.toString());
@ -331,8 +331,8 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
_currentSubscription.productID != plan.androidID;
if (isCrossGradingOnAndroid) {
final existingProductDetailsResponse =
await InAppPurchaseConnection.instance
.queryProductDetails({_currentSubscription.productID});
await InAppPurchaseConnection.instance
.queryProductDetails({_currentSubscription.productID});
if (existingProductDetailsResponse.notFoundIDs.isNotEmpty) {
_logger.severe("Could not find existing products: " +
response.notFoundIDs.toString());
@ -401,4 +401,3 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
);
}
}

View file

@ -113,8 +113,8 @@ class _RecoveryPageState extends State<RecoveryPage> {
onTap: () {
showErrorDialog(
context,
"sorry",
"due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key",
"Sorry",
"Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key",
);
},
child: Container(

View file

@ -397,9 +397,9 @@ class _SharingDialogState extends State<SharingDialog> {
void _showUnSupportedAlert() {
AlertDialog alert = AlertDialog(
title: Text("sorry"),
title: Text("Sorry"),
content:
Text("sharing is not permitted for free accounts, please subscribe"),
Text("Sharing is not permitted for free accounts, please subscribe"),
actions: [
TextButton(
child: Text(

View file

@ -72,6 +72,10 @@ String getFullMonth(DateTime dateTime) {
return _fullMonths[dateTime.month];
}
String getAbbreviationOfYear(DateTime dateTime) {
return (dateTime.year % 100).toString();
}
String getTime(DateTime dateTime) {
final hours = dateTime.hour > 9
? dateTime.hour.toString()
@ -95,13 +99,11 @@ String getFormattedTime(DateTime dateTime) {
}
String getFormattedDate(DateTime dateTime) {
return getDay(dateTime) +
", " +
getMonth(dateTime) +
return dateTime.day.toString() +
" " +
dateTime.day.toString() +
", " +
dateTime.year.toString();
getMonth(dateTime) +
"'" +
getAbbreviationOfYear(dateTime);
}
String daysLeft(int futureTime) {