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