peer ab/group tab refresh, animated refresh icon
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
ec9062f505
commit
0bda66dd7f
30
flutter/lib/common/widgets/animated_rotation_widget.dart
Normal file
30
flutter/lib/common/widgets/animated_rotation_widget.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AnimatedRotationWidget extends StatefulWidget {
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
final ValueChanged<bool>? onHover;
|
||||||
|
final Widget child;
|
||||||
|
const AnimatedRotationWidget(
|
||||||
|
{super.key, required this.onPressed, required this.child, this.onHover});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AnimatedRotationWidget> createState() => AnimatedRotationWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnimatedRotationWidgetState extends State<AnimatedRotationWidget> {
|
||||||
|
double turns = 0.0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnimatedRotation(
|
||||||
|
turns: turns,
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
setState(() => turns += 1.0);
|
||||||
|
widget.onPressed();
|
||||||
|
},
|
||||||
|
onHover: widget.onHover,
|
||||||
|
child: widget.child));
|
||||||
|
}
|
||||||
|
}
|
@ -37,7 +37,7 @@ class _MyGroupState extends State<MyGroup> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Future<Widget> buildBody(BuildContext context) async {
|
Future<Widget> buildBody(BuildContext context) async {
|
||||||
gFFI.groupModel.pullUserPeers();
|
gFFI.groupModel.pull();
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
if (gFFI.groupModel.groupLoading.value ||
|
if (gFFI.groupModel.groupLoading.value ||
|
||||||
gFFI.groupModel.peerLoading.value) {
|
gFFI.groupModel.peerLoading.value) {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'dart:math';
|
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
import 'package:bot_toast/bot_toast.dart';
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
@ -8,6 +7,7 @@ import 'package:flutter_hbb/common/widgets/address_book.dart';
|
|||||||
import 'package:flutter_hbb/common/widgets/my_group.dart';
|
import 'package:flutter_hbb/common/widgets/my_group.dart';
|
||||||
import 'package:flutter_hbb/common/widgets/peers_view.dart';
|
import 'package:flutter_hbb/common/widgets/peers_view.dart';
|
||||||
import 'package:flutter_hbb/common/widgets/peer_card.dart';
|
import 'package:flutter_hbb/common/widgets/peer_card.dart';
|
||||||
|
import 'package:flutter_hbb/common/widgets/animated_rotation_widget.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
import 'package:flutter_hbb/desktop/widgets/popup_menu.dart';
|
import 'package:flutter_hbb/desktop/widgets/popup_menu.dart';
|
||||||
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
||||||
@ -18,7 +18,6 @@ import 'package:get/get.dart';
|
|||||||
import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart';
|
import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:visibility_detector/visibility_detector.dart';
|
import 'package:visibility_detector/visibility_detector.dart';
|
||||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
|
||||||
|
|
||||||
import '../../common.dart';
|
import '../../common.dart';
|
||||||
import '../../models/platform_model.dart';
|
import '../../models/platform_model.dart';
|
||||||
@ -63,12 +62,13 @@ class _PeerTabPageState extends State<PeerTabPage>
|
|||||||
AddressBook(
|
AddressBook(
|
||||||
menuPadding: _menuPadding(),
|
menuPadding: _menuPadding(),
|
||||||
),
|
),
|
||||||
() => {}),
|
() => gFFI.abModel.pullAb()),
|
||||||
_TabEntry(
|
_TabEntry(
|
||||||
MyGroup(
|
MyGroup(
|
||||||
menuPadding: _menuPadding(),
|
menuPadding: _menuPadding(),
|
||||||
),
|
),
|
||||||
() => {}),
|
() => gFFI.groupModel.pull(),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
final _scrollDebounce = Debouncer(delay: Duration(milliseconds: 50));
|
final _scrollDebounce = Debouncer(delay: Duration(milliseconds: 50));
|
||||||
|
|
||||||
@ -109,11 +109,11 @@ class _PeerTabPageState extends State<PeerTabPage>
|
|||||||
child:
|
child:
|
||||||
visibleContextMenuListener(_createSwitchBar(context))),
|
visibleContextMenuListener(_createSwitchBar(context))),
|
||||||
buildScrollJumper(),
|
buildScrollJumper(),
|
||||||
const PeerSearchBar(),
|
const PeerSearchBar().marginOnly(right: 13),
|
||||||
|
_createRefresh(),
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: !isDesktop,
|
offstage: !isDesktop,
|
||||||
child: _createPeerViewTypeSwitch(context)
|
child: _createPeerViewTypeSwitch(context)),
|
||||||
.marginOnly(left: 13)),
|
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: _hideSort,
|
offstage: _hideSort,
|
||||||
child: PeerSortDropdown().marginOnly(left: 8),
|
child: PeerSortDropdown().marginOnly(left: 8),
|
||||||
@ -241,6 +241,29 @@ class _PeerTabPageState extends State<PeerTabPage>
|
|||||||
child: child.marginSymmetric(vertical: isDesktop ? 12.0 : 6.0));
|
child: child.marginSymmetric(vertical: isDesktop ? 12.0 : 6.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _createRefresh() {
|
||||||
|
final textColor = Theme.of(context).textTheme.titleLarge?.color;
|
||||||
|
return Offstage(
|
||||||
|
offstage: gFFI.peerTabModel.currentTab < 3, // local tab can't see effect
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(4.0),
|
||||||
|
child: AnimatedRotationWidget(
|
||||||
|
onPressed: () {
|
||||||
|
if (gFFI.peerTabModel.currentTab < entries.length) {
|
||||||
|
entries[gFFI.peerTabModel.currentTab].load();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: RotatedBox(
|
||||||
|
quarterTurns: 2,
|
||||||
|
child: Icon(
|
||||||
|
Icons.refresh,
|
||||||
|
size: 18,
|
||||||
|
color: textColor,
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _createPeerViewTypeSwitch(BuildContext context) {
|
Widget _createPeerViewTypeSwitch(BuildContext context) {
|
||||||
final textColor = Theme.of(context).textTheme.titleLarge?.color;
|
final textColor = Theme.of(context).textTheme.titleLarge?.color;
|
||||||
final deco = BoxDecoration(
|
final deco = BoxDecoration(
|
||||||
|
@ -6,6 +6,7 @@ import 'package:auto_size_text/auto_size_text.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
|
import 'package:flutter_hbb/common/widgets/animated_rotation_widget.dart';
|
||||||
import 'package:flutter_hbb/common/widgets/custom_password.dart';
|
import 'package:flutter_hbb/common/widgets/custom_password.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
import 'package:flutter_hbb/desktop/pages/connection_page.dart';
|
import 'package:flutter_hbb/desktop/pages/connection_page.dart';
|
||||||
@ -247,19 +248,19 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
InkWell(
|
AnimatedRotationWidget(
|
||||||
child: Obx(
|
onPressed: () => bind.mainUpdateTemporaryPassword(),
|
||||||
() => Icon(
|
child: Obx(() => RotatedBox(
|
||||||
Icons.refresh,
|
quarterTurns: 2,
|
||||||
color: refreshHover.value
|
child: Icon(
|
||||||
? textColor
|
Icons.refresh,
|
||||||
: Color(0xFFDDDDDD),
|
color: refreshHover.value
|
||||||
size: 22,
|
? textColor
|
||||||
).marginOnly(right: 8, top: 4),
|
: Color(0xFFDDDDDD),
|
||||||
),
|
size: 22,
|
||||||
onTap: () => bind.mainUpdateTemporaryPassword(),
|
))),
|
||||||
onHover: (value) => refreshHover.value = value,
|
onHover: (value) => refreshHover.value = value,
|
||||||
),
|
).marginOnly(right: 8, top: 4),
|
||||||
InkWell(
|
InkWell(
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => Icon(
|
() => Icon(
|
||||||
@ -574,7 +575,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
_updateTimer?.cancel();
|
_updateTimer?.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPluginEntry() {
|
Widget buildPluginEntry() {
|
||||||
final entries = PluginUiManager.instance.entries.entries;
|
final entries = PluginUiManager.instance.entries.entries;
|
||||||
return Offstage(
|
return Offstage(
|
||||||
@ -582,8 +583,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
...
|
...entries.map((entry) {
|
||||||
entries.map((entry) {
|
|
||||||
return entry.value;
|
return entry.value;
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
@ -103,6 +103,7 @@ class GroupModel {
|
|||||||
} finally {
|
} finally {
|
||||||
groupLoading.value = false;
|
groupLoading.value = false;
|
||||||
gFFI.peerTabModel.check_dynamic_tabs();
|
gFFI.peerTabModel.check_dynamic_tabs();
|
||||||
|
_pullUserPeers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +135,7 @@ class GroupModel {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> pullUserPeers() async {
|
Future<void> _pullUserPeers() async {
|
||||||
peersShow.clear();
|
peersShow.clear();
|
||||||
peerLoading.value = true;
|
peerLoading.value = true;
|
||||||
peerLoadError.value = "";
|
peerLoadError.value = "";
|
||||||
|
Loading…
Reference in New Issue
Block a user