Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
Tommy Chow
4d3e406d24 refactor: convert StatefulWidgets to HookWidgets for improved state management 2025-06-14 22:35:13 -04:00
Tommy Chow
699f8de041 add flutter_hooks dependency to pubspec.yaml 2025-06-14 22:15:49 -04:00
6 changed files with 57 additions and 73 deletions

View file

@ -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,
),
);

View file

@ -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)),
],
),
);

View file

@ -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),
),

View file

@ -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();
}
}

View file

@ -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:

View file

@ -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: