refactor(mobile): build context extensions (#4923)
* refactor: move all extensions to separate package * refactor(mobile): add BuildContext extension * refactor(mobile): use theme getters from context * refactor(mobile): use media query size from context * refactor(mobile): use auto router methods from context * refactor(mobile): use navigator methods from context --------- Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
extension DurationExtension on String {
|
||||
Duration? toDuration() {
|
||||
try {
|
||||
final parts = split(':')
|
||||
.map((e) => double.parse(e).toInt())
|
||||
.toList(growable: false);
|
||||
return Duration(hours: parts[0], minutes: parts[1], seconds: parts[2]);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
double toDouble() {
|
||||
return double.parse(this);
|
||||
}
|
||||
|
||||
int toInt() {
|
||||
return int.parse(this);
|
||||
}
|
||||
}
|
||||
|
||||
extension ListExtension<E> on List<E> {
|
||||
List<E> uniqueConsecutive({
|
||||
int Function(E a, E b)? compare,
|
||||
void Function(E a, E b)? onDuplicate,
|
||||
}) {
|
||||
compare ??= (E a, E b) => a == b ? 0 : 1;
|
||||
int i = 1, j = 1;
|
||||
for (; i < length; i++) {
|
||||
if (compare(this[i - 1], this[i]) != 0) {
|
||||
if (i != j) {
|
||||
this[j] = this[i];
|
||||
}
|
||||
j++;
|
||||
} else if (onDuplicate != null) {
|
||||
onDuplicate(this[i - 1], this[i]);
|
||||
}
|
||||
}
|
||||
length = length == 0 ? 0 : j;
|
||||
return this;
|
||||
}
|
||||
|
||||
ListSlice<E> nestedSlice(int start, int end) {
|
||||
if (this is ListSlice) {
|
||||
final ListSlice<E> self = this as ListSlice<E>;
|
||||
return ListSlice<E>(self.source, self.start + start, self.start + end);
|
||||
}
|
||||
return ListSlice<E>(this, start, end);
|
||||
}
|
||||
}
|
||||
|
||||
extension IntListExtension on Iterable<int> {
|
||||
Int64List toInt64List() {
|
||||
final list = Int64List(length);
|
||||
list.setAll(0, this);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
extension StringExtension on String {
|
||||
String capitalize() {
|
||||
return split(" ")
|
||||
.map(
|
||||
(str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1),
|
||||
)
|
||||
.join(" ");
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
extension TimeAgoExtension on DateTime {
|
||||
String timeAgo({bool numericDates = true}) {
|
||||
DateTime date = toLocal();
|
||||
final date2 = DateTime.now().toLocal();
|
||||
final difference = date2.difference(date);
|
||||
|
||||
if (difference.inSeconds < 5) {
|
||||
return 'Just now';
|
||||
} else if (difference.inSeconds < 60) {
|
||||
return '${difference.inSeconds} seconds ago';
|
||||
} else if (difference.inMinutes <= 1) {
|
||||
return (numericDates) ? '1 minute ago' : 'A minute ago';
|
||||
} else if (difference.inMinutes < 60) {
|
||||
return '${difference.inMinutes} minutes ago';
|
||||
} else if (difference.inHours <= 1) {
|
||||
return (numericDates) ? '1 hour ago' : 'An hour ago';
|
||||
} else if (difference.inHours < 60) {
|
||||
return '${difference.inHours} hours ago';
|
||||
} else if (difference.inDays <= 1) {
|
||||
return (numericDates) ? '1 day ago' : 'Yesterday';
|
||||
} else if (difference.inDays < 6) {
|
||||
return '${difference.inDays} days ago';
|
||||
} else if ((difference.inDays / 7).ceil() <= 1) {
|
||||
return (numericDates) ? '1 week ago' : 'Last week';
|
||||
} else if ((difference.inDays / 7).ceil() < 4) {
|
||||
return '${(difference.inDays / 7).ceil()} weeks ago';
|
||||
} else if ((difference.inDays / 30).ceil() <= 1) {
|
||||
return (numericDates) ? '1 month ago' : 'Last month';
|
||||
} else if ((difference.inDays / 30).ceil() < 30) {
|
||||
return '${(difference.inDays / 30).ceil()} months ago';
|
||||
} else if ((difference.inDays / 365).ceil() <= 1) {
|
||||
return (numericDates) ? '1 year ago' : 'Last year';
|
||||
}
|
||||
return '${(difference.inDays / 365).floor()} years ago';
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'dart:math' as math;
|
||||
|
||||
extension MoveByBounds on MapController {
|
||||
// TODO: Remove this in favor of built-in method when upgrading flutter_map to 5.0.0
|
||||
LatLng? centerBoundsWithPadding(
|
||||
LatLng coordinates,
|
||||
Offset offset, {
|
||||
double? zoomLevel,
|
||||
}) {
|
||||
const crs = Epsg3857();
|
||||
final oldCenterPt = crs.latLngToPoint(coordinates, zoomLevel ?? zoom);
|
||||
final mapCenterPoint = _rotatePoint(
|
||||
oldCenterPt,
|
||||
oldCenterPt - CustomPoint(offset.dx, offset.dy),
|
||||
);
|
||||
return crs.pointToLatLng(mapCenterPoint, zoomLevel ?? zoom);
|
||||
}
|
||||
|
||||
CustomPoint<double> _rotatePoint(
|
||||
CustomPoint<double> mapCenter,
|
||||
CustomPoint<double> point, {
|
||||
bool counterRotation = true,
|
||||
}) {
|
||||
final counterRotationFactor = counterRotation ? -1 : 1;
|
||||
|
||||
final m = Matrix4.identity()
|
||||
..translate(mapCenter.x, mapCenter.y)
|
||||
..rotateZ(degToRadian(rotation) * counterRotationFactor)
|
||||
..translate(-mapCenter.x, -mapCenter.y);
|
||||
|
||||
final tp = MatrixUtils.transformPoint(m, Offset(point.x, point.y));
|
||||
|
||||
return CustomPoint(tp.dx, tp.dy);
|
||||
}
|
||||
|
||||
double getTapThresholdForZoomLevel() {
|
||||
const scale = [
|
||||
25000000,
|
||||
15000000,
|
||||
8000000,
|
||||
4000000,
|
||||
2000000,
|
||||
1000000,
|
||||
500000,
|
||||
250000,
|
||||
100000,
|
||||
50000,
|
||||
25000,
|
||||
15000,
|
||||
8000,
|
||||
4000,
|
||||
2000,
|
||||
1000,
|
||||
500,
|
||||
250,
|
||||
100,
|
||||
50,
|
||||
25,
|
||||
10,
|
||||
5,
|
||||
];
|
||||
return scale[math.max(0, math.min(20, zoom.round() + 2))].toDouble() / 6;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/shared/services/share.service.dart';
|
||||
@@ -26,7 +27,7 @@ void handleShareAssets(
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
}
|
||||
Navigator.of(buildContext).pop();
|
||||
context.pop();
|
||||
},
|
||||
);
|
||||
return const ShareDialog();
|
||||
|
||||
Reference in New Issue
Block a user