some issues fixed
This commit is contained in:
@@ -94,6 +94,8 @@ class HomeFilterWidget {
|
||||
this.showAmountIn = true,
|
||||
this.showAmountOut = true,
|
||||
this.showCount = true,
|
||||
this.updatedAt = 0,
|
||||
this.deleted = false,
|
||||
});
|
||||
|
||||
final String id;
|
||||
@@ -129,6 +131,12 @@ class HomeFilterWidget {
|
||||
final bool showAmountOut;
|
||||
final bool showCount;
|
||||
|
||||
/// Epoch ms; used for last-write-wins sync across devices.
|
||||
final int updatedAt;
|
||||
|
||||
/// Soft-delete so removals propagate via sync instead of being recreated.
|
||||
final bool deleted;
|
||||
|
||||
IconData get icon => HomeWidgetIcons.iconFor(iconId);
|
||||
|
||||
TransactionFilterSelection get filter => TransactionFilterSelection(
|
||||
@@ -161,6 +169,9 @@ class HomeFilterWidget {
|
||||
bool? showAmountIn,
|
||||
bool? showAmountOut,
|
||||
bool? showCount,
|
||||
int? updatedAt,
|
||||
bool? deleted,
|
||||
bool touchUpdatedAt = false,
|
||||
}) {
|
||||
return HomeFilterWidget(
|
||||
id: id ?? this.id,
|
||||
@@ -183,6 +194,10 @@ class HomeFilterWidget {
|
||||
showAmountIn: showAmountIn ?? this.showAmountIn,
|
||||
showAmountOut: showAmountOut ?? this.showAmountOut,
|
||||
showCount: showCount ?? this.showCount,
|
||||
updatedAt: touchUpdatedAt
|
||||
? DateTime.now().millisecondsSinceEpoch
|
||||
: (updatedAt ?? this.updatedAt),
|
||||
deleted: deleted ?? this.deleted,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -208,6 +223,7 @@ class HomeFilterWidget {
|
||||
showAmountIn: showIn,
|
||||
showAmountOut: showOut,
|
||||
showCount: true,
|
||||
updatedAt: DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -236,6 +252,8 @@ class HomeFilterWidget {
|
||||
'showAmountIn': showAmountIn,
|
||||
'showAmountOut': showAmountOut,
|
||||
'showCount': showCount,
|
||||
'updatedAt': updatedAt,
|
||||
'deleted': deleted,
|
||||
};
|
||||
|
||||
factory HomeFilterWidget.fromJson(Map<String, dynamic> json) {
|
||||
@@ -302,20 +320,30 @@ class HomeFilterWidget {
|
||||
showAmountIn: json['showAmountIn'] as bool? ?? true,
|
||||
showAmountOut: json['showAmountOut'] as bool? ?? true,
|
||||
showCount: json['showCount'] as bool? ?? true,
|
||||
updatedAt: asInt(json['updatedAt'] ?? json['updated_at'], 0),
|
||||
deleted: json['deleted'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Union home widgets by id (local wins on conflict).
|
||||
/// Union home widgets by id with last-write-wins on [HomeFilterWidget.updatedAt].
|
||||
List<HomeFilterWidget> mergeHomeFilterWidgets(
|
||||
List<HomeFilterWidget> local,
|
||||
List<HomeFilterWidget> remote,
|
||||
) {
|
||||
final byId = <String, HomeFilterWidget>{
|
||||
for (final w in remote) w.id: w,
|
||||
};
|
||||
final byId = <String, HomeFilterWidget>{};
|
||||
void put(HomeFilterWidget w) {
|
||||
final existing = byId[w.id];
|
||||
if (existing == null || w.updatedAt >= existing.updatedAt) {
|
||||
byId[w.id] = w;
|
||||
}
|
||||
}
|
||||
|
||||
for (final w in remote) {
|
||||
put(w);
|
||||
}
|
||||
for (final w in local) {
|
||||
byId[w.id] = w;
|
||||
put(w);
|
||||
}
|
||||
final merged = byId.values.toList()
|
||||
..sort((a, b) => a.sortOrder.compareTo(b.sortOrder));
|
||||
|
||||
@@ -16,6 +16,8 @@ class OverviewFavourite {
|
||||
this.flow = TxFlowFilter.expense,
|
||||
this.barStyle = LabelChartBarStyle.parallel,
|
||||
this.invertExpensePerspective = false,
|
||||
this.updatedAt = 0,
|
||||
this.deleted = false,
|
||||
});
|
||||
|
||||
final String id;
|
||||
@@ -34,6 +36,12 @@ class OverviewFavourite {
|
||||
final LabelChartBarStyle barStyle;
|
||||
final bool invertExpensePerspective;
|
||||
|
||||
/// Epoch ms; used for last-write-wins sync across devices.
|
||||
final int updatedAt;
|
||||
|
||||
/// Soft-delete so removals propagate via sync instead of being recreated.
|
||||
final bool deleted;
|
||||
|
||||
OverviewFavourite copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
@@ -44,6 +52,9 @@ class OverviewFavourite {
|
||||
TxFlowFilter? flow,
|
||||
LabelChartBarStyle? barStyle,
|
||||
bool? invertExpensePerspective,
|
||||
int? updatedAt,
|
||||
bool? deleted,
|
||||
bool touchUpdatedAt = false,
|
||||
}) {
|
||||
return OverviewFavourite(
|
||||
id: id ?? this.id,
|
||||
@@ -56,6 +67,10 @@ class OverviewFavourite {
|
||||
barStyle: barStyle ?? this.barStyle,
|
||||
invertExpensePerspective:
|
||||
invertExpensePerspective ?? this.invertExpensePerspective,
|
||||
updatedAt: touchUpdatedAt
|
||||
? DateTime.now().millisecondsSinceEpoch
|
||||
: (updatedAt ?? this.updatedAt),
|
||||
deleted: deleted ?? this.deleted,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,9 +84,18 @@ class OverviewFavourite {
|
||||
'flow': flow.name,
|
||||
'barStyle': barStyle.name,
|
||||
'invertExpensePerspective': invertExpensePerspective,
|
||||
'updatedAt': updatedAt,
|
||||
'deleted': deleted,
|
||||
};
|
||||
|
||||
factory OverviewFavourite.fromJson(Map<String, dynamic> json) {
|
||||
final rawUpdated = json['updatedAt'] ?? json['updated_at'];
|
||||
final updatedAt = switch (rawUpdated) {
|
||||
int n => n,
|
||||
num n => n.round(),
|
||||
String s => int.tryParse(s) ?? 0,
|
||||
_ => 0,
|
||||
};
|
||||
return OverviewFavourite(
|
||||
id: json['id'] as String? ?? 'fav_${DateTime.now().millisecondsSinceEpoch}',
|
||||
name: (json['name'] as String?)?.trim().isNotEmpty == true
|
||||
@@ -100,6 +124,8 @@ class OverviewFavourite {
|
||||
),
|
||||
invertExpensePerspective:
|
||||
json['invertExpensePerspective'] as bool? ?? false,
|
||||
updatedAt: updatedAt,
|
||||
deleted: json['deleted'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -107,3 +133,25 @@ class OverviewFavourite {
|
||||
enum OverviewMetricMode { flow, labels }
|
||||
|
||||
enum OverviewPeriodMode { monthly, yearly }
|
||||
|
||||
/// Union favourites by id with last-write-wins on [OverviewFavourite.updatedAt].
|
||||
List<OverviewFavourite> mergeOverviewFavourites(
|
||||
List<OverviewFavourite> local,
|
||||
List<OverviewFavourite> remote,
|
||||
) {
|
||||
final byId = <String, OverviewFavourite>{};
|
||||
void put(OverviewFavourite fav) {
|
||||
final existing = byId[fav.id];
|
||||
if (existing == null || fav.updatedAt >= existing.updatedAt) {
|
||||
byId[fav.id] = fav;
|
||||
}
|
||||
}
|
||||
|
||||
for (final fav in remote) {
|
||||
put(fav);
|
||||
}
|
||||
for (final fav in local) {
|
||||
put(fav);
|
||||
}
|
||||
return byId.values.toList(growable: false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user