commit
956a3cbfb5
7 changed files with 472 additions and 288 deletions
|
@ -151,7 +151,7 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
|
|||
children: [
|
||||
const SizedBox(height: 12),
|
||||
SectionTitle("On device"),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: 12),
|
||||
items.folders.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.all(22),
|
||||
|
@ -191,11 +191,11 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
SectionTitle("On ente"),
|
||||
EnteSectionTitle(),
|
||||
_sortMenu(),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: 12),
|
||||
Configuration.instance.hasConfiguredAccount()
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
|
@ -746,3 +746,48 @@ class SectionTitle extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EnteSectionTitle extends StatelessWidget {
|
||||
final double opacity;
|
||||
|
||||
const EnteSectionTitle({
|
||||
this.opacity = 0.8,
|
||||
Key key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: EdgeInsets.fromLTRB(16, 12, 0, 0),
|
||||
child: Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "On ",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headline6
|
||||
.copyWith(fontSize: 22),
|
||||
),
|
||||
TextSpan(
|
||||
text: "ente",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Montserrat',
|
||||
fontSize: 22,
|
||||
color: Theme.of(context).colorScheme.defaultTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
163
lib/ui/header_error_widget.dart
Normal file
163
lib/ui/header_error_widget.dart
Normal file
|
@ -0,0 +1,163 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/errors.dart';
|
||||
import 'package:photos/ente_theme_data.dart';
|
||||
import 'package:photos/ui/payment/subscription.dart';
|
||||
import 'package:photos/utils/email_util.dart';
|
||||
|
||||
class HeaderErrorWidget extends StatelessWidget {
|
||||
final Error _error;
|
||||
|
||||
const HeaderErrorWidget({Key key, @required Error error})
|
||||
: _error = error,
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_error is NoActiveSubscriptionError) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(top: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
color: Colors.orange,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Text("Your subscription has expired"),
|
||||
],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
Container(
|
||||
width: 400,
|
||||
height: 52,
|
||||
padding: const EdgeInsets.fromLTRB(80, 0, 80, 0),
|
||||
child: OutlinedButton(
|
||||
child: Text("Subscribe"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return getSubscriptionPage();
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(12)),
|
||||
Divider(
|
||||
thickness: 2,
|
||||
height: 0,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(12)),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else if (_error is StorageLimitExceededError) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(top: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
color: Colors.orange,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Text("Storage limit exceeded"),
|
||||
],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
Container(
|
||||
width: 400,
|
||||
height: 52,
|
||||
padding: const EdgeInsets.fromLTRB(80, 0, 80, 0),
|
||||
child: OutlinedButton(
|
||||
child: Text("Upgrade"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return getSubscriptionPage();
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(12)),
|
||||
Divider(
|
||||
thickness: 2,
|
||||
height: 0,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(12)),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
color: Colors.red[400],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Text(
|
||||
"We could not backup your data.\nWe will retry later.",
|
||||
style: TextStyle(height: 1.4),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
InkWell(
|
||||
child: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.inverseTextColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
padding: EdgeInsets.fromLTRB(50, 16, 50, 16),
|
||||
side: BorderSide(
|
||||
width: 2,
|
||||
color: Colors.orange[600],
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
"Raise ticket",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
color: Colors.orange[600],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
onPressed: () {
|
||||
sendLogs(
|
||||
context,
|
||||
"Raise ticket",
|
||||
"support@ente.io",
|
||||
subject: "Backup failed",
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(16)),
|
||||
Divider(
|
||||
thickness: 2,
|
||||
height: 0,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(12)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,7 +48,7 @@ import 'package:photos/ui/memories_widget.dart';
|
|||
import 'package:photos/ui/nav_bar.dart';
|
||||
import 'package:photos/ui/settings_page.dart';
|
||||
import 'package:photos/ui/shared_collections_gallery.dart';
|
||||
import 'package:photos/ui/sync_indicator.dart';
|
||||
import 'package:photos/ui/status_bar_widget.dart';
|
||||
import 'package:photos/utils/dialog_util.dart';
|
||||
import 'package:photos/utils/navigation_util.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
|
@ -719,7 +719,7 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
|
|||
|
||||
class HeaderWidget extends StatelessWidget {
|
||||
static const _memoriesWidget = MemoriesWidget();
|
||||
static const _syncIndicator = SyncIndicator();
|
||||
static const _statusBarWidget = StatusBarWidget();
|
||||
|
||||
const HeaderWidget({
|
||||
Key key,
|
||||
|
@ -729,7 +729,7 @@ class HeaderWidget extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
Logger("Header").info("Building header widget");
|
||||
const list = [
|
||||
_syncIndicator,
|
||||
_statusBarWidget,
|
||||
_memoriesWidget,
|
||||
];
|
||||
return Column(
|
||||
|
|
|
@ -125,7 +125,7 @@ class _SharedCollectionGalleryState extends State<SharedCollectionGallery>
|
|||
children: [
|
||||
const SizedBox(height: 12),
|
||||
SectionTitle("Incoming"),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: 12),
|
||||
collections.incoming.isNotEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
|
@ -150,7 +150,6 @@ class _SharedCollectionGalleryState extends State<SharedCollectionGallery>
|
|||
: _getIncomingCollectionEmptyState(),
|
||||
const SizedBox(height: 32),
|
||||
SectionTitle("Outgoing"),
|
||||
const SizedBox(height: 12),
|
||||
collections.outgoing.isNotEmpty
|
||||
? ListView.builder(
|
||||
shrinkWrap: true,
|
||||
|
|
256
lib/ui/status_bar_widget.dart
Normal file
256
lib/ui/status_bar_widget.dart
Normal file
|
@ -0,0 +1,256 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/sync_status_update_event.dart';
|
||||
import 'package:photos/services/sync_service.dart';
|
||||
import 'package:photos/ui/header_error_widget.dart';
|
||||
|
||||
const double kContainerHeight = 48;
|
||||
|
||||
class StatusBarWidget extends StatefulWidget {
|
||||
const StatusBarWidget({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatusBarWidget> createState() => _StatusBarWidgetState();
|
||||
}
|
||||
|
||||
class _StatusBarWidgetState extends State<StatusBarWidget> {
|
||||
StreamSubscription<SyncStatusUpdate> _subscription;
|
||||
bool _showStatus = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_subscription = Bus.instance.on<SyncStatusUpdate>().listen((event) {
|
||||
if (event.status == SyncStatus.completed_first_gallery_import ||
|
||||
event.status == SyncStatus.completed_backup) {
|
||||
Future.delayed(Duration(milliseconds: 2000), () {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_showStatus = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_showStatus = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_subscription.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
AnimatedOpacity(
|
||||
opacity: _showStatus ? 0 : 1,
|
||||
duration: Duration(milliseconds: 1000),
|
||||
child: StatusBarBrandingWidget(),
|
||||
),
|
||||
AnimatedOpacity(
|
||||
opacity: _showStatus ? 1 : 0,
|
||||
duration: Duration(milliseconds: 1000),
|
||||
child: SyncStatusWidget(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SyncStatusWidget extends StatefulWidget {
|
||||
const SyncStatusWidget({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SyncStatusWidgetState createState() => _SyncStatusWidgetState();
|
||||
}
|
||||
|
||||
class _SyncStatusWidgetState extends State<SyncStatusWidget> {
|
||||
static const Duration kSleepDuration = Duration(milliseconds: 3000);
|
||||
|
||||
SyncStatusUpdate _event;
|
||||
StreamSubscription<SyncStatusUpdate> _subscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_subscription = Bus.instance.on<SyncStatusUpdate>().listen((event) {
|
||||
setState(() {
|
||||
_event = event;
|
||||
});
|
||||
});
|
||||
_event = SyncService.instance.getLastSyncStatusEvent();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_subscription.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isNotOutdatedEvent = _event != null &&
|
||||
(_event.status == SyncStatus.completed_backup ||
|
||||
_event.status == SyncStatus.completed_first_gallery_import) &&
|
||||
(DateTime.now().microsecondsSinceEpoch - _event.timestamp >
|
||||
kSleepDuration.inMicroseconds);
|
||||
if (_event == null || isNotOutdatedEvent) {
|
||||
return Container();
|
||||
}
|
||||
if (_event.status == SyncStatus.error) {
|
||||
return HeaderErrorWidget(error: _event.error);
|
||||
}
|
||||
if (_event.status == SyncStatus.completed_backup) {
|
||||
return SyncStatusCompletedWidget();
|
||||
}
|
||||
return RefreshIndicatorWidget(_event);
|
||||
}
|
||||
}
|
||||
|
||||
class RefreshIndicatorWidget extends StatelessWidget {
|
||||
static const _inProgressIcon = CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Color.fromRGBO(45, 194, 98, 1.0)),
|
||||
);
|
||||
|
||||
final SyncStatusUpdate event;
|
||||
|
||||
const RefreshIndicatorWidget(this.event, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: kContainerHeight,
|
||||
width: double.infinity,
|
||||
alignment: Alignment.center,
|
||||
child: SingleChildScrollView(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(2),
|
||||
width: 22,
|
||||
height: 22,
|
||||
child: _inProgressIcon,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 4, 0, 0),
|
||||
child: Text(_getRefreshingText()),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getRefreshingText() {
|
||||
if (event.status == SyncStatus.started_first_gallery_import ||
|
||||
event.status == SyncStatus.completed_first_gallery_import) {
|
||||
return "Loading gallery...";
|
||||
}
|
||||
if (event.status == SyncStatus.applying_remote_diff) {
|
||||
return "Syncing...";
|
||||
}
|
||||
if (event.status == SyncStatus.preparing_for_upload) {
|
||||
return "Encrypting backup...";
|
||||
}
|
||||
if (event.status == SyncStatus.in_progress) {
|
||||
return event.completed.toString() +
|
||||
"/" +
|
||||
event.total.toString() +
|
||||
" Memories preserved";
|
||||
}
|
||||
if (event.status == SyncStatus.paused) {
|
||||
return event.reason;
|
||||
}
|
||||
if (event.status == SyncStatus.error) {
|
||||
return event.reason ?? "Upload failed";
|
||||
}
|
||||
if (event.status == SyncStatus.completed_backup) {
|
||||
if (event.wasStopped) {
|
||||
return "Sync stopped";
|
||||
}
|
||||
}
|
||||
return "All memories preserved";
|
||||
}
|
||||
}
|
||||
|
||||
class StatusBarBrandingWidget extends StatelessWidget {
|
||||
const StatusBarBrandingWidget({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: kContainerHeight,
|
||||
padding: EdgeInsets.only(left: 12),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text(
|
||||
"ente",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Montserrat',
|
||||
fontSize: 28,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SyncStatusCompletedWidget extends StatelessWidget {
|
||||
const SyncStatusCompletedWidget({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: kContainerHeight,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(2),
|
||||
width: 22,
|
||||
height: 22,
|
||||
child: Icon(
|
||||
Icons.cloud_done_outlined,
|
||||
color: Theme.of(context).buttonColor,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 4, 0, 0),
|
||||
child: Text("All memories preserved"),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Divider(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,279 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/errors.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/sync_status_update_event.dart';
|
||||
import 'package:photos/services/sync_service.dart';
|
||||
import 'package:photos/ui/payment/subscription.dart';
|
||||
import 'package:photos/utils/email_util.dart';
|
||||
|
||||
class SyncIndicator extends StatefulWidget {
|
||||
const SyncIndicator({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SyncIndicatorState createState() => _SyncIndicatorState();
|
||||
}
|
||||
|
||||
class _SyncIndicatorState extends State<SyncIndicator> {
|
||||
static const kSleepDuration = Duration(milliseconds: 3000);
|
||||
SyncStatusUpdate _event;
|
||||
double _containerHeight = 48;
|
||||
StreamSubscription<SyncStatusUpdate> _subscription;
|
||||
static const _inProgressIcon = CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Color.fromRGBO(45, 194, 98, 1.0)),
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_subscription = Bus.instance.on<SyncStatusUpdate>().listen((event) {
|
||||
setState(() {
|
||||
_event = event;
|
||||
});
|
||||
});
|
||||
_event = SyncService.instance.getLastSyncStatusEvent();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_subscription.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isNotOutdatedEvent = _event != null &&
|
||||
(_event.status == SyncStatus.completed_backup ||
|
||||
_event.status == SyncStatus.completed_first_gallery_import) &&
|
||||
(DateTime.now().microsecondsSinceEpoch - _event.timestamp >
|
||||
kSleepDuration.inMicroseconds);
|
||||
if (_event == null || isNotOutdatedEvent) {
|
||||
return Container();
|
||||
}
|
||||
if (_event.status == SyncStatus.error) {
|
||||
return _getErrorWidget();
|
||||
}
|
||||
if (_event.status == SyncStatus.completed_first_gallery_import ||
|
||||
_event.status == SyncStatus.completed_backup) {
|
||||
Future.delayed(kSleepDuration, () {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_containerHeight = 0;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_containerHeight = 48;
|
||||
}
|
||||
final icon = _event.status == SyncStatus.completed_backup
|
||||
? Icon(
|
||||
Icons.cloud_done_outlined,
|
||||
color: Theme.of(context).buttonColor,
|
||||
)
|
||||
: _inProgressIcon;
|
||||
return AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
height: _containerHeight,
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(8),
|
||||
alignment: Alignment.center,
|
||||
child: SingleChildScrollView(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(2),
|
||||
width: 22,
|
||||
height: 22,
|
||||
child: icon,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 4, 0, 0),
|
||||
child: Text(_getRefreshingText()),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getErrorWidget() {
|
||||
if (_event.error is NoActiveSubscriptionError) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(top: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
color: Theme.of(context).buttonColor,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Text("Your subscription has expired"),
|
||||
],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(6)),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 64,
|
||||
padding: const EdgeInsets.fromLTRB(80, 0, 80, 0),
|
||||
child: OutlinedButton(
|
||||
child: Text("Subscribe"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return getSubscriptionPage();
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else if (_event.error is StorageLimitExceededError) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(top: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
color: Theme.of(context).buttonColor,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Text("Storage limit exceeded"),
|
||||
],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(6)),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 64,
|
||||
padding: const EdgeInsets.fromLTRB(80, 0, 80, 0),
|
||||
child: OutlinedButton(
|
||||
child: Text("Upgrade"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return getSubscriptionPage();
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
color: Colors.red[400],
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Text(
|
||||
"We could not backup your data\nwe will retry later",
|
||||
style: TextStyle(height: 1.4),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(8)),
|
||||
InkWell(
|
||||
child: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
padding: EdgeInsets.fromLTRB(50, 16, 50, 16),
|
||||
side: BorderSide(
|
||||
width: 1,
|
||||
color: Colors.orange[300],
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
"Raise ticket",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
color: Colors.orange[300],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
onPressed: () {
|
||||
sendLogs(
|
||||
context,
|
||||
"Raise ticket",
|
||||
"support@ente.io",
|
||||
subject: "Backup failed",
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(16)),
|
||||
Divider(
|
||||
thickness: 2,
|
||||
height: 0,
|
||||
),
|
||||
Padding(padding: EdgeInsets.all(12)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _getRefreshingText() {
|
||||
if (_event.status == SyncStatus.started_first_gallery_import ||
|
||||
_event.status == SyncStatus.completed_first_gallery_import) {
|
||||
return "Loading gallery...";
|
||||
}
|
||||
if (_event.status == SyncStatus.applying_remote_diff) {
|
||||
return "Syncing...";
|
||||
}
|
||||
if (_event.status == SyncStatus.preparing_for_upload) {
|
||||
return "Encrypting backup...";
|
||||
}
|
||||
if (_event.status == SyncStatus.in_progress) {
|
||||
return _event.completed.toString() +
|
||||
"/" +
|
||||
_event.total.toString() +
|
||||
" Memories preserved";
|
||||
}
|
||||
if (_event.status == SyncStatus.paused) {
|
||||
return _event.reason;
|
||||
}
|
||||
if (_event.status == SyncStatus.completed_backup) {
|
||||
if (_event.wasStopped) {
|
||||
return "Sync stopped";
|
||||
} else {
|
||||
return "All memories preserved";
|
||||
}
|
||||
}
|
||||
// _event.status == SyncStatus.error
|
||||
return _event.reason ?? "Upload failed";
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ description: ente photos application
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 0.5.37+317
|
||||
version: 0.5.38+318
|
||||
|
||||
environment:
|
||||
sdk: ">=2.10.0 <3.0.0"
|
||||
|
|
Loading…
Add table
Reference in a new issue