Browse Source

perf(neon): make RelativeTime stateful

Signed-off-by: Nikolas Rimikis <leptopoda@users.noreply.github.com>
pull/776/head
Nikolas Rimikis 1 year ago
parent
commit
a43762d7e4
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 36
      packages/neon/neon/lib/src/utils/relative_time.dart
  2. 69
      packages/neon/neon/lib/src/widgets/relative_time.dart

36
packages/neon/neon/lib/src/utils/relative_time.dart

@ -0,0 +1,36 @@
import 'package:meta/meta.dart';
/// Extension for formating the differnce between two [DateTime]s.
@internal
extension RelativeTimeFormat on DateTime {
/// Format the relative time between this and [to].
///
/// If unspecified [DateTime.now] will be used.
String formatRelative([final DateTime? to]) {
final now = to ?? DateTime.now();
var diff = now.difference(toLocal());
final text = StringBuffer();
// Sometimes something can be messed up...
if (diff.isNegative) {
if (diff.inMinutes >= 1) {
text.write('-');
}
diff = Duration(microseconds: -diff.inMicroseconds);
}
if (diff.inMinutes < 1) {
text.write('now');
} else if (diff.inHours < 1) {
text.write('${diff.inMinutes}m');
} else if (diff.inDays < 1) {
text.write('${diff.inHours}h');
} else if (diff.inDays < 365) {
text.write('${diff.inDays}d');
} else {
text.write('${diff.inDays ~/ 365}y');
}
return text.toString();
}
}

69
packages/neon/neon/lib/src/widgets/relative_time.dart

@ -1,49 +1,52 @@
import 'dart:async';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:neon/src/utils/relative_time.dart';
class RelativeTime extends StatelessWidget { /// Shows the time elapsed since a [DateTime] and periodically updates itself.
class RelativeTime extends StatefulWidget {
/// Creates a new relative DateTime widget.
const RelativeTime({ const RelativeTime({
required this.date, required this.date,
this.style, this.style,
super.key, super.key,
}); });
/// The timestamp to be displayed.
final DateTime date; final DateTime date;
/// The text style of the calculated time.
///
/// If not specified the nearest [TextStyle] will be used.
final TextStyle? style; final TextStyle? style;
static String format(final DateTime date) { @override
final now = DateTime.now(); State<RelativeTime> createState() => _RelativeTimeState();
var diff = now.difference(date.toLocal()); }
final text = StringBuffer();
class _RelativeTimeState extends State<RelativeTime> {
// Sometimes something can be messed up... late final Timer timer;
if (diff.isNegative) {
if (diff.inMinutes >= 1) { @override
text.write('-'); void initState() {
} timer = Timer.periodic(
diff = Duration(microseconds: -diff.inMicroseconds); const Duration(minutes: 1),
} (final _) => setState(() {}),
);
if (diff.inMinutes < 1) {
text.write('now'); super.initState();
} else if (diff.inHours < 1) { }
text.write('${diff.inMinutes}m');
} else if (diff.inDays < 1) { @override
text.write('${diff.inHours}h'); void dispose() {
} else if (diff.inDays < 365) { timer.cancel();
text.write('${diff.inDays}d');
} else { super.dispose();
text.write('${diff.inDays ~/ 365}y');
}
return text.toString();
} }
@override @override
Widget build(final BuildContext context) => StreamBuilder( Widget build(final BuildContext context) => Text(
stream: Stream.periodic(const Duration(minutes: 1)), widget.date.formatRelative(),
builder: (final context, final _) => Text( style: widget.style,
format(date),
style: style,
),
); );
} }

Loading…
Cancel
Save