Compare commits
2 commits
main
...
flutter-ho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d3e406d24 | ||
|
|
699f8de041 |
6 changed files with 57 additions and 73 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
class AnimatedScrollBorder extends StatefulWidget {
|
||||
class AnimatedScrollBorder extends HookWidget {
|
||||
final ScrollController scrollController;
|
||||
|
||||
const AnimatedScrollBorder({
|
||||
|
|
@ -8,41 +9,30 @@ class AnimatedScrollBorder extends StatefulWidget {
|
|||
required this.scrollController,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AnimatedScrollBorder> createState() => _AnimatedScrollBorderState();
|
||||
}
|
||||
|
||||
class _AnimatedScrollBorderState extends State<AnimatedScrollBorder> {
|
||||
bool _isScrolled = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.scrollController.addListener(_updateScrollState);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.scrollController.removeListener(_updateScrollState);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _updateScrollState() {
|
||||
setState(() {
|
||||
_isScrolled = widget.scrollController.offset > 0;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isScrolled = useState(false);
|
||||
|
||||
void updateScrollState() {
|
||||
isScrolled.value = scrollController.offset > 0;
|
||||
}
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
scrollController.addListener(updateScrollState);
|
||||
return () => scrollController.removeListener(updateScrollState);
|
||||
},
|
||||
[scrollController],
|
||||
);
|
||||
|
||||
return AnimatedSwitcher(
|
||||
switchInCurve: Curves.easeOut,
|
||||
switchOutCurve: Curves.easeIn,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: _isScrolled
|
||||
child: isScrolled.value
|
||||
? const Divider()
|
||||
: Divider(
|
||||
key: ValueKey(_isScrolled),
|
||||
key: ValueKey(isScrolled.value),
|
||||
color: Colors.transparent,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class FrostyPageView extends StatefulWidget {
|
||||
class FrostyPageView extends StatelessWidget {
|
||||
final List<String> headers;
|
||||
final List<Widget> children;
|
||||
|
||||
|
|
@ -10,15 +10,10 @@ class FrostyPageView extends StatefulWidget {
|
|||
required this.children,
|
||||
}) : assert(headers.length == children.length);
|
||||
|
||||
@override
|
||||
State<FrostyPageView> createState() => _FrostyPageViewState();
|
||||
}
|
||||
|
||||
class _FrostyPageViewState extends State<FrostyPageView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultTabController(
|
||||
length: widget.headers.length,
|
||||
length: headers.length,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -31,7 +26,7 @@ class _FrostyPageViewState extends State<FrostyPageView> {
|
|||
labelPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
),
|
||||
tabs: widget.headers
|
||||
tabs: headers
|
||||
.map(
|
||||
(header) => Tab(
|
||||
text: header,
|
||||
|
|
@ -40,7 +35,7 @@ class _FrostyPageViewState extends State<FrostyPageView> {
|
|||
.toList(),
|
||||
),
|
||||
const Divider(),
|
||||
Expanded(child: TabBarView(children: widget.children)),
|
||||
Expanded(child: TabBarView(children: children)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:frosty/cache_manager.dart';
|
||||
import 'package:frosty/theme.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FrostyPhotoViewDialog extends StatefulWidget {
|
||||
class FrostyPhotoViewDialog extends HookWidget {
|
||||
final String imageUrl;
|
||||
final String? cacheKey;
|
||||
|
||||
|
|
@ -15,32 +16,27 @@ class FrostyPhotoViewDialog extends StatefulWidget {
|
|||
this.cacheKey,
|
||||
});
|
||||
|
||||
@override
|
||||
State<FrostyPhotoViewDialog> createState() => _FrostyPhotoViewDialogState();
|
||||
}
|
||||
|
||||
class _FrostyPhotoViewDialogState extends State<FrostyPhotoViewDialog> {
|
||||
PhotoViewScaleState photoViewScaleState = PhotoViewScaleState.initial;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final photoViewScaleState = useState(PhotoViewScaleState.initial);
|
||||
|
||||
return Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
Dismissible(
|
||||
key: const Key('photo_view_dismissible'),
|
||||
direction: photoViewScaleState == PhotoViewScaleState.initial
|
||||
direction: photoViewScaleState.value == PhotoViewScaleState.initial
|
||||
? DismissDirection.vertical
|
||||
: DismissDirection.none,
|
||||
onDismissed: Navigator.of(context).pop,
|
||||
child: PhotoView(
|
||||
imageProvider: CachedNetworkImageProvider(
|
||||
widget.imageUrl,
|
||||
cacheKey: widget.cacheKey,
|
||||
imageUrl,
|
||||
cacheKey: cacheKey,
|
||||
cacheManager: CustomCacheManager.instance,
|
||||
),
|
||||
scaleStateChangedCallback: (value) =>
|
||||
setState(() => photoViewScaleState = value),
|
||||
photoViewScaleState.value = value,
|
||||
backgroundDecoration:
|
||||
const BoxDecoration(color: Colors.transparent),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
/// A widget that displays a timer representing the time since the given start time.
|
||||
/// The timer is updated every second.
|
||||
class Uptime extends StatefulWidget {
|
||||
class Uptime extends HookWidget {
|
||||
final String startTime;
|
||||
final TextStyle? style;
|
||||
|
||||
|
|
@ -14,35 +15,28 @@ class Uptime extends StatefulWidget {
|
|||
this.style,
|
||||
});
|
||||
|
||||
@override
|
||||
State<Uptime> createState() => _UptimeState();
|
||||
}
|
||||
|
||||
class _UptimeState extends State<Uptime> {
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_timer =
|
||||
Timer.periodic(const Duration(seconds: 1), (timer) => setState(() {}));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final updateTrigger = useState(0);
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
final timer = Timer.periodic(
|
||||
const Duration(seconds: 1),
|
||||
(timer) => updateTrigger.value++,
|
||||
);
|
||||
return timer.cancel;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return Text(
|
||||
DateTime.now()
|
||||
.difference(DateTime.parse(widget.startTime))
|
||||
.difference(DateTime.parse(startTime))
|
||||
.toString()
|
||||
.split('.')[0],
|
||||
style: widget.style
|
||||
?.copyWith(fontFeatures: [const FontFeature.tabularFigures()]),
|
||||
style:
|
||||
style?.copyWith(fontFeatures: [const FontFeature.tabularFigures()]),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -419,6 +419,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
flutter_hooks:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_hooks
|
||||
sha256: b772e710d16d7a20c0740c4f855095026b31c7eb5ba3ab67d2bd52021cd9461d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.21.2"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ dependencies:
|
|||
flutter_markdown: ^0.7.3+1
|
||||
flutter_colorpicker: ^1.1.0
|
||||
path_provider: ^2.1.5
|
||||
flutter_hooks: ^0.21.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue