Nikolas Rimikis
1 year ago
2 changed files with 72 additions and 33 deletions
@ -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(); |
||||
} |
||||
} |
@ -1,49 +1,52 @@
|
||||
import 'dart:async'; |
||||
|
||||
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({ |
||||
required this.date, |
||||
this.style, |
||||
super.key, |
||||
}); |
||||
|
||||
/// The timestamp to be displayed. |
||||
final DateTime date; |
||||
|
||||
/// The text style of the calculated time. |
||||
/// |
||||
/// If not specified the nearest [TextStyle] will be used. |
||||
final TextStyle? style; |
||||
|
||||
static String format(final DateTime date) { |
||||
final now = DateTime.now(); |
||||
var diff = now.difference(date.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(); |
||||
@override |
||||
State<RelativeTime> createState() => _RelativeTimeState(); |
||||
} |
||||
|
||||
class _RelativeTimeState extends State<RelativeTime> { |
||||
late final Timer timer; |
||||
|
||||
@override |
||||
void initState() { |
||||
timer = Timer.periodic( |
||||
const Duration(minutes: 1), |
||||
(final _) => setState(() {}), |
||||
); |
||||
|
||||
super.initState(); |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
timer.cancel(); |
||||
|
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) => StreamBuilder( |
||||
stream: Stream.periodic(const Duration(minutes: 1)), |
||||
builder: (final context, final _) => Text( |
||||
format(date), |
||||
style: style, |
||||
), |
||||
Widget build(final BuildContext context) => Text( |
||||
widget.date.formatRelative(), |
||||
style: widget.style, |
||||
); |
||||
} |
||||
|
Loading…
Reference in new issue