refactor(legacy): split legacy_shared into cohesive packages
legacy_shared was the junk drawer of the legacy app mode — 37 files mixing device entities, command infrastructure, UI primitives, generic formatters, and a duplicate of sf_infrastructure's dio_error_mapper. Any module needing one piece pulled the whole bag into its graph. Split it by responsibility, following Mandamiento 4 of Real-World Flutter: - legacy_ui (new): 6 widget/layout primitives (PageLayout, MenuButton, SectionButton, PulsingLocationMarker, RefreshableErrorState, WeekDayChips) plus mapStyleProvider — shared UI state that was the only reason two modules needed a common package. - legacy_device_state (expanded 9 → 30): absorbed device entities, commands infrastructure (datasource + repo + provider + guard), device settings update flow, and the CSV exporter. Now one package owns the device domain end-to-end. - packages/utils: absorbed battery_utils and date_format_utils as pure formatters that never belonged in a legacy-scoped package. - legacy_shared: deleted entirely. The duplicate dio_error_mapper in legacy_shared is gone; callers now use the sf_infrastructure version (which was always the superset — it adds ApiException and the dart:io socket handling). DeviceEntity note: legacy_device_state keeps its own DeviceEntity (with int timestamps and typed paymentOptions) separate from sf_shared's DeviceEntity (String timestamps, untyped paymentOptions). The legacy one is intentionally not exported from the barrel to avoid the ambiguous_import collision that legacy_shared quietly hid by never exporting it in the first place. Unifying the two is a domain-model refactor out of scope here. 0 cross-module imports remain among legacy feature modules.
This commit is contained in:
@@ -15,9 +15,21 @@ late final SfTrackingRepository sfTracking;
|
||||
void initSfTracking() {
|
||||
sfTracking = SfTrackingRepository(
|
||||
clients: <TrackingClient>[
|
||||
// TODO: read consent from a persisted preference once the GDPR
|
||||
// consent screen exists, and call `sfTracking.setConsentStatus(...)`
|
||||
// when the user toggles it.
|
||||
// TODO(gdpr): consentAnalytics is hardcoded to `true`. This ships
|
||||
// Firebase Analytics events for every EU user WITHOUT explicit opt-in,
|
||||
// which violates GDPR Art. 6/7. Sensitive context: this app tracks
|
||||
// minors' location, so regulatory scrutiny is higher than baseline.
|
||||
//
|
||||
// To close this out:
|
||||
// 1. Build an onboarding consent screen with separate toggles for
|
||||
// analytics and crashlytics (granularity is required).
|
||||
// 2. Persist the decision in SharedPreferences (key per client).
|
||||
// 3. Read the stored preference here before constructing the client
|
||||
// — default to `false` until the user has explicitly accepted.
|
||||
// 4. Expose a "Privacy" entry in Settings that lets the user change
|
||||
// their mind; on toggle, call
|
||||
// `sfTracking.setConsentStatus(client: ..., granted: ...)`.
|
||||
// 5. Add the privacy notice + data-processing summary in-app.
|
||||
FirebaseTrackingClient(consentAnalytics: true),
|
||||
if (kDebugMode) const DebugTrackingClient(),
|
||||
],
|
||||
|
||||
11
packages/utils/lib/src/battery_utils.dart
Normal file
11
packages/utils/lib/src/battery_utils.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
IconData toBatteryIcon(int battery) {
|
||||
if (battery < 15) return Icons.battery_0_bar;
|
||||
if (battery < 30) return Icons.battery_1_bar;
|
||||
if (battery < 45) return Icons.battery_2_bar;
|
||||
if (battery < 60) return Icons.battery_3_bar;
|
||||
if (battery < 75) return Icons.battery_4_bar;
|
||||
if (battery < 90) return Icons.battery_5_bar;
|
||||
return Icons.battery_6_bar;
|
||||
}
|
||||
9
packages/utils/lib/src/date_format_utils.dart
Normal file
9
packages/utils/lib/src/date_format_utils.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
String formatPositionDate(int millisSinceEpoch) {
|
||||
final d = DateTime.fromMillisecondsSinceEpoch(millisSinceEpoch);
|
||||
final mm = d.month.toString().padLeft(2, '0');
|
||||
final dd = d.day.toString().padLeft(2, '0');
|
||||
final hh = d.hour.toString().padLeft(2, '0');
|
||||
final min = d.minute.toString().padLeft(2, '0');
|
||||
final ss = d.second.toString().padLeft(2, '0');
|
||||
return '$mm-$dd $hh:$min:$ss';
|
||||
}
|
||||
@@ -3,3 +3,5 @@ export 'src/duration_format.dart';
|
||||
export 'src/query_params_builder.dart';
|
||||
export 'src/size_utils.dart';
|
||||
export 'src/test.dart';
|
||||
export 'src/battery_utils.dart';
|
||||
export 'src/date_format_utils.dart';
|
||||
|
||||
Reference in New Issue
Block a user