Files
GitJournal/lib/widgets/sync_button.dart
Vishesh Handa 29fd576109 Avoid using git_bindings except for clone/pull/push/ls-remote
Lets use dart-git instead. It seems stable enough, and I'm soon going to
be moving away from libgit2 to go-git anyway. This is the first step towards
that.
2023-12-12 19:59:54 +01:00

195 lines
4.5 KiB
Dart

/*
* SPDX-FileCopyrightText: 2019-2021 Vishesh Handa <me@vhanda.in>
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import 'dart:async';
import 'package:badges/badges.dart' as badges;
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:gitjournal/repository.dart';
import 'package:gitjournal/sync_attempt.dart';
import 'package:gitjournal/utils/utils.dart';
import 'package:provider/provider.dart';
class SyncButton extends StatefulWidget {
@override
_SyncButtonState createState() => _SyncButtonState();
}
class _SyncButtonState extends State<SyncButton> {
late 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 repo = context.watch<GitJournalRepo>();
if (_connectivity == ConnectivityResult.none) {
return GitPendingChangesBadge(
child: IconButton(
icon: const Icon(Icons.signal_wifi_off),
onPressed: () async {
unawaited(_syncRepo());
},
),
);
}
if (repo.syncStatus == SyncStatus.Pulling) {
return BlinkingIcon(
child: GitPendingChangesBadge(
child: IconButton(
icon: const Icon(Icons.cloud_download),
onPressed: () {},
),
),
);
}
if (repo.syncStatus == SyncStatus.Pushing) {
return BlinkingIcon(
child: GitPendingChangesBadge(
child: IconButton(
icon: const Icon(Icons.cloud_upload),
onPressed: () {},
),
),
);
}
if (repo.syncStatus == SyncStatus.Error) {
return GitPendingChangesBadge(
child: IconButton(
icon: const Icon(Icons.cloud_off),
onPressed: () async {
unawaited(_syncRepo());
},
),
);
}
return GitPendingChangesBadge(
child: IconButton(
icon: Icon(_syncStatusIcon()),
onPressed: () async {
unawaited(_syncRepo());
},
),
);
}
Future<void> _syncRepo() async {
try {
final repo = context.read<GitJournalRepo>();
await repo.syncNotes();
} catch (e) {
showErrorSnackbar(context, e);
}
}
IconData _syncStatusIcon() {
final repo = context.watch<GitJournalRepo>();
switch (repo.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;
const BlinkingIcon({required this.child, this.interval = 500, Key? key});
@override
_BlinkingIconState createState() => _BlinkingIconState();
}
class _BlinkingIconState extends State<BlinkingIcon>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late 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;
const GitPendingChangesBadge({required this.child});
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var darkMode = theme.brightness == Brightness.dark;
var style = theme.textTheme.bodySmall!.copyWith(
fontSize: 6.0,
color: darkMode ? Colors.black : Colors.white,
);
final repo = context.watch<GitJournalRepo>();
return badges.Badge(
badgeContent: Text(repo.numChanges.toString(), style: style),
showBadge: repo.numChanges != 0,
badgeColor: theme.iconTheme.color!,
position: badges.BadgePosition.topEnd(top: 10.0, end: 4.0),
child: child,
);
}
}