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