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: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; |
||||||
final TextStyle? style; |
|
||||||
|
|
||||||
static String format(final DateTime date) { |
/// The text style of the calculated time. |
||||||
final now = DateTime.now(); |
/// |
||||||
var diff = now.difference(date.toLocal()); |
/// If not specified the nearest [TextStyle] will be used. |
||||||
final text = StringBuffer(); |
final TextStyle? style; |
||||||
|
|
||||||
// Sometimes something can be messed up... |
@override |
||||||
if (diff.isNegative) { |
State<RelativeTime> createState() => _RelativeTimeState(); |
||||||
if (diff.inMinutes >= 1) { |
|
||||||
text.write('-'); |
|
||||||
} |
|
||||||
diff = Duration(microseconds: -diff.inMicroseconds); |
|
||||||
} |
} |
||||||
|
|
||||||
if (diff.inMinutes < 1) { |
class _RelativeTimeState extends State<RelativeTime> { |
||||||
text.write('now'); |
late final Timer timer; |
||||||
} else if (diff.inHours < 1) { |
|
||||||
text.write('${diff.inMinutes}m'); |
@override |
||||||
} else if (diff.inDays < 1) { |
void initState() { |
||||||
text.write('${diff.inHours}h'); |
timer = Timer.periodic( |
||||||
} else if (diff.inDays < 365) { |
const Duration(minutes: 1), |
||||||
text.write('${diff.inDays}d'); |
(final _) => setState(() {}), |
||||||
} else { |
); |
||||||
text.write('${diff.inDays ~/ 365}y'); |
|
||||||
|
super.initState(); |
||||||
} |
} |
||||||
|
|
||||||
return text.toString(); |
@override |
||||||
|
void dispose() { |
||||||
|
timer.cancel(); |
||||||
|
|
||||||
|
super.dispose(); |
||||||
} |
} |
||||||
|
|
||||||
@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…
Reference in new issue