Created
February 12, 2020 18:35
-
-
Save lukepighetti/1bda67aed0dfdd5446f485b616adbdaf to your computer and use it in GitHub Desktop.
Quick example of what an extensions file might look like in one of my projects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:email_validator/email_validator.dart'; | |
import 'package:firebase_dynamic_links/firebase_dynamic_links.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/material.dart' as material; | |
import 'package:intl/intl.dart'; | |
import 'package:rxdart/rxdart.dart'; | |
extension BuildContextExtensions on BuildContext { | |
dynamic get arguments => ModalRoute.of(this).settings.arguments; | |
bool dismissModalBottomSheet<T>([T result]) => navigator.pop<T>(result); | |
Future<T> search<T>({String query, SearchDelegate<T> delegate}) => | |
showSearch(context: this, delegate: delegate, query: query); | |
Future<T> showModalBottomSheet<T>(WidgetBuilder builder) => | |
material.showModalBottomSheet<T>(context: this, builder: builder); | |
TextTheme get textTheme => Theme.of(this).textTheme; | |
ThemeData get theme => Theme.of(this); | |
NavigatorState get navigator => Navigator.of(this); | |
} | |
extension ColorExtensions on Color { | |
Color get withSuperLightOpacity => this.withOpacity(0.15); | |
Color get withLightOpacity => this.withOpacity(0.25); | |
HSVColor get toHsv => HSVColor.fromColor(this); | |
Gradient get asGradient => LinearGradient( | |
colors: [ | |
this, | |
this | |
.toHsv | |
.withSaturation((this.toHsv.saturation + 0.2).clamp(0.0, 1.0)) | |
.toColor() | |
], | |
begin: Alignment.bottomCenter, | |
end: Alignment.topCenter, | |
); | |
} | |
/// Turns the firebase_dynamic_links read API into a ValueStream | |
extension FirebaseDynamicLinksExtensions on FirebaseDynamicLinks { | |
static final _linkSubject = BehaviorSubject<PendingDynamicLinkData>(); | |
/// This lets us access onLinkSubject naiively without having to worry about | |
/// our onSuccess/onError handlers getting replaced with new ones | |
static bool _didSetupLinkSubject = false; | |
/// Convert the onLink handler into a BehaviorSubject | |
ValueStream<PendingDynamicLinkData> get onLinkStream { | |
if (_didSetupLinkSubject == false) { | |
/// Add launching link | |
FirebaseDynamicLinks.instance.getInitialLink().then((v) { | |
if (v != null) _linkSubject.add(v); | |
}); | |
/// Add all subsequent links | |
FirebaseDynamicLinks.instance.onLink( | |
onSuccess: (v) async => _linkSubject.add(v), | |
onError: (e) async => _linkSubject.addError(e), | |
); | |
_didSetupLinkSubject = true; | |
} | |
return _linkSubject; | |
} | |
dispose() { | |
_linkSubject.close(); | |
} | |
} | |
extension IntExtensions on int { | |
bool isBetween(int max, int min) => this > max && this < min; | |
} | |
extension IterableExtensions<E> on Iterable<E> { | |
List<T> mapList<T>(T Function(E) f) => this.map<T>(f).toList(); | |
} | |
extension ListExtensions<E> on List<E> { | |
/// Converts list into a table with specified `width`. | |
/// `this.length` must be evenly divisible by `width`. | |
List<List<E>> asTable(int width) { | |
final table = List<List<E>>(); | |
for (int i = 0; i < this.length; i += width) { | |
final row = this.sublist(i, i + width); | |
table.add(row); | |
} | |
return table; | |
} | |
List<E> whereList(bool Function(E) test) => this.where(test).toList(); | |
} | |
extension NumExtensions on num { | |
String get withCommas => NumberFormat.decimalPattern().format(this); | |
} | |
extension ObjectExtensions on Object { | |
bool get isNull => this == null; | |
bool get isNotNull => this != null; | |
} | |
extension SizedBoxExtensions on SizedBox { | |
SizedBox square(double dimension) => | |
SizedBox.fromSize(size: Size.square(dimension)); | |
SizedBox get eight => square(8); | |
SizedBox get twentyFour => square(24); | |
SizedBox get forty => square(40); | |
} | |
extension StringExtensions on String { | |
/// Matches `^[a-zA-Z ]+$` | |
bool get isLetters => RegExp(r"^[a-zA-Z ]+$").hasMatch(this); | |
/// Matches `^[0-9]+$` | |
bool get isNumbers => RegExp(r"^[0-9]+$").hasMatch(this); | |
/// Matches emails using [EmailValidator] | |
bool get isEmail => EmailValidator.validate(this); | |
/// Is between `1899` and `2222` | |
bool get isSchoolYear => | |
this.isNumbers && int.parse(this).isBetween(1899, 2222); | |
/// Fuzzy search, usually used for mocking search services. | |
bool fuzzyContains(String query) => | |
this.toLowerCase().contains(query.toLowerCase()); | |
} | |
extension WidgetExtensions on Widget { | |
/// Convenience method to delay the display of a widget. Useful for | |
/// items that might display for a split second before it's replaced | |
/// with another widget, eg when loading data. | |
Widget delayed([Duration duration = const Duration(seconds: 1)]) { | |
return FutureBuilder<bool>( | |
future: Future.delayed(duration, () => true), | |
initialData: false, | |
builder: (context, snapshot) { | |
final isVisible = snapshot.data; | |
return Opacity( | |
opacity: isVisible ? 1 : 0, | |
child: this, | |
); | |
}, | |
); | |
} | |
Widget nudge({double x = 0, double y = 0}) => | |
Transform.translate(offset: Offset(x, y), child: this); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment