don't use Offstage as widget of animated loading, reuse refresh as
loading Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
d56356e595
commit
24e6b54650
@ -10,7 +10,6 @@ import 'package:get/get.dart';
|
||||
|
||||
import '../../common.dart';
|
||||
import 'dialog.dart';
|
||||
import 'loading_dot_widget.dart';
|
||||
import 'login.dart';
|
||||
|
||||
final hideAbTagsPanel = false.obs;
|
||||
@ -47,8 +46,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
_buildNotEmptyLoading(),
|
||||
_buildRetryProgress(),
|
||||
if (gFFI.abModel.retrying.value) LinearProgressIndicator(),
|
||||
_buildErrorBanner(
|
||||
err: gFFI.abModel.pullError,
|
||||
retry: null,
|
||||
@ -121,29 +119,6 @@ class _AddressBookState extends State<AddressBook> {
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildNotEmptyLoading() {
|
||||
double size = 15;
|
||||
return Obx(() => Offstage(
|
||||
offstage: !(gFFI.abModel.abLoading.value && !gFFI.abModel.emtpy),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: size,
|
||||
child: Center(child: LoadingDotWidget(size: size)))
|
||||
.marginSymmetric(vertical: 10)
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildRetryProgress() {
|
||||
return Obx(() => Offstage(
|
||||
offstage: !gFFI.abModel.retrying.value,
|
||||
child: LinearProgressIndicator(),
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildAddressBookDesktop() {
|
||||
return Row(
|
||||
children: [
|
||||
|
@ -1,11 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class AnimatedRotationWidget extends StatefulWidget {
|
||||
final VoidCallback onPressed;
|
||||
final ValueChanged<bool>? onHover;
|
||||
final Widget child;
|
||||
final RxBool? spinning;
|
||||
const AnimatedRotationWidget(
|
||||
{super.key, required this.onPressed, required this.child, this.onHover});
|
||||
{super.key,
|
||||
required this.onPressed,
|
||||
required this.child,
|
||||
this.spinning,
|
||||
this.onHover});
|
||||
|
||||
@override
|
||||
State<AnimatedRotationWidget> createState() => AnimatedRotationWidgetState();
|
||||
@ -14,14 +20,31 @@ class AnimatedRotationWidget extends StatefulWidget {
|
||||
class AnimatedRotationWidgetState extends State<AnimatedRotationWidget> {
|
||||
double turns = 0.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.spinning?.listen((v) {
|
||||
if (v && mounted) {
|
||||
setState(() {
|
||||
turns += 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedRotation(
|
||||
turns: turns,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
onEnd: () {
|
||||
if (widget.spinning?.value == true && mounted) {
|
||||
setState(() => turns += 1.0);
|
||||
}
|
||||
},
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
setState(() => turns += 1.0);
|
||||
if (mounted) setState(() => turns += 1.0);
|
||||
widget.onPressed();
|
||||
},
|
||||
onHover: widget.onHover,
|
||||
|
@ -1,65 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class LoadingDotWidget extends StatefulWidget {
|
||||
final int count;
|
||||
final double size;
|
||||
final int duration;
|
||||
LoadingDotWidget(
|
||||
{Key? key, required this.size, this.count = 3, this.duration = 200})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<LoadingDotWidget> createState() => _LoadingDotWidgetState();
|
||||
}
|
||||
|
||||
class _LoadingDotWidgetState extends State<LoadingDotWidget> {
|
||||
int counter = 0;
|
||||
Timer? timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
startAnimation();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void startAnimation() {
|
||||
timer = Timer.periodic(Duration(milliseconds: widget.duration), (timer) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
counter = (counter + 1) % widget.count;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
getChild(int index) {
|
||||
return AnimatedContainer(
|
||||
duration: Duration(milliseconds: widget.duration),
|
||||
width: counter == index ? widget.size : widget.size / 2,
|
||||
height: counter == index ? widget.size : widget.size / 2,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.grey,
|
||||
),
|
||||
).marginSymmetric(horizontal: widget.size);
|
||||
}
|
||||
|
||||
return Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(widget.count, (e) => e)
|
||||
.map((e) => getChild(e))
|
||||
.toList()),
|
||||
);
|
||||
}
|
||||
}
|
@ -219,6 +219,7 @@ class _PeerTabPageState extends State<PeerTabPage>
|
||||
entries[gFFI.peerTabModel.currentTab].load();
|
||||
}
|
||||
},
|
||||
spinning: gFFI.abModel.abLoading,
|
||||
child: RotatedBox(
|
||||
quarterTurns: 2,
|
||||
child: Tooltip(
|
||||
|
@ -59,7 +59,6 @@ class AbModel {
|
||||
if (!gFFI.userModel.isLogin) return;
|
||||
if (abLoading.value) return;
|
||||
if (!force && initialized) return;
|
||||
DateTime startTime = DateTime.now();
|
||||
if (pushError.isNotEmpty) {
|
||||
try {
|
||||
// push to retry
|
||||
@ -120,14 +119,7 @@ class AbModel {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
var ms =
|
||||
(Duration(milliseconds: 300) - DateTime.now().difference(startTime))
|
||||
.inMilliseconds;
|
||||
ms = ms > 0 ? ms : 0;
|
||||
Future.delayed(Duration(milliseconds: ms), () {
|
||||
abLoading.value = false;
|
||||
});
|
||||
|
||||
abLoading.value = false;
|
||||
initialized = true;
|
||||
_syncAllFromRecent = true;
|
||||
_timerCounter = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user