Files
GitJournal/lib/widgets/sync_button.dart
2020-10-23 01:38:47 +02:00

186 lines
4.4 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:badges/badges.dart';
import 'package:connectivity/connectivity.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:git_bindings/git_bindings.dart';
import 'package:provider/provider.dart';
import 'package:gitjournal/appstate.dart';
import 'package:gitjournal/repository.dart';
import 'package:gitjournal/utils.dart';
class SyncButton extends StatefulWidget {
@override
_SyncButtonState createState() => _SyncButtonState();
}
class _SyncButtonState extends State<SyncButton> {
StreamSubscription<ConnectivityResult> subscription;
ConnectivityResult _connectivity;
@override
void initState() {
super.initState();
subscription = Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult result) {
setState(() {
_connectivity = result;
});
});
}
@override
void dispose() {
subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final appState = Provider.of<Repository>(context).appState;
if (_connectivity == ConnectivityResult.none) {
return GitPendingChangesBadge(
child: IconButton(
icon: const Icon(Icons.signal_wifi_off),
onPressed: () async {
_syncRepo();
},
),
);
}
if (appState.syncStatus == SyncStatus.Pulling) {
return BlinkingIcon(
child: GitPendingChangesBadge(
child: IconButton(
icon: const Icon(Icons.cloud_download),
onPressed: () {},
),
),
);
}
if (appState.syncStatus == SyncStatus.Pushing) {
return BlinkingIcon(
child: GitPendingChangesBadge(
child: IconButton(
icon: const Icon(Icons.cloud_upload),
onPressed: () {},
),
),
);
}
return GitPendingChangesBadge(
child: IconButton(
icon: Icon(_syncStatusIcon()),
onPressed: () async {
_syncRepo();
},
),
);
}
void _syncRepo() async {
try {
final container = Provider.of<Repository>(context, listen: false);
await container.syncNotes();
} on GitException catch (e) {
showSnackbar(context, tr('widgets.SyncButton.error', args: [e.cause]));
} catch (e) {
showSnackbar(context, e.toString());
}
}
IconData _syncStatusIcon() {
final container = Provider.of<Repository>(context);
final appState = container.appState;
switch (appState.syncStatus) {
case SyncStatus.Error:
return Icons.cloud_off;
case SyncStatus.Unknown:
case SyncStatus.Done:
default:
return Icons.cloud_done;
}
}
}
class BlinkingIcon extends StatefulWidget {
final Widget child;
final int interval;
BlinkingIcon({@required this.child, this.interval = 500, Key key})
: super(key: key);
@override
_BlinkingIconState createState() => _BlinkingIconState();
}
class _BlinkingIconState extends State<BlinkingIcon>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(milliseconds: widget.interval),
vsync: this,
);
_animation = CurvedAnimation(
parent: _controller,
curve: Curves.linear,
);
_controller.repeat(reverse: true);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: _animation,
child: widget.child,
);
}
}
class GitPendingChangesBadge extends StatelessWidget {
final Widget child;
GitPendingChangesBadge({@required this.child});
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var darkMode = theme.brightness == Brightness.dark;
var style = theme.textTheme.caption.copyWith(
fontSize: 6.0,
color: darkMode ? Colors.black : Colors.white,
);
final appState = Provider.of<Repository>(context).appState;
return Badge(
badgeContent: Text(appState.numChanges.toString(), style: style),
showBadge: appState.numChanges != 0,
badgeColor: theme.iconTheme.color,
position: BadgePosition.topRight(top: 10.0, right: 4.0),
child: child,
);
}
}