tes
This commit is contained in:
parent
f713294638
commit
4b9ea8598c
|
|
@ -18,7 +18,6 @@ class EvaporasiSettingsBloc extends Bloc<EvaporasiSettingsEvent, EvaporasiSettin
|
|||
on<EvaporasiSettingsStarted>(_onStarted);
|
||||
on<EvaporasiThresholdRendahChanged>(_onThresholdRendahChanged);
|
||||
on<EvaporasiThresholdTinggiChanged>(_onThresholdTinggiChanged);
|
||||
// rumusKalibrasi removed: calculation is handled on ESP32 hardware
|
||||
on<EvaporasiKoreksiOffsetChanged>(_onOffsetChanged);
|
||||
on<EvaporasiPumpStartChanged>(_onPumpStartChanged);
|
||||
on<EvaporasiPumpEndChanged>(_onPumpEndChanged);
|
||||
|
|
@ -133,8 +132,6 @@ class EvaporasiSettingsBloc extends Bloc<EvaporasiSettingsEvent, EvaporasiSettin
|
|||
Emitter<EvaporasiSettingsState> emit,
|
||||
) => emit(state.copyWith(thresholdTinggi: event.value));
|
||||
|
||||
// rumusKalibrasi handling removed — device firmware defines the formula
|
||||
|
||||
void _onOffsetChanged(
|
||||
EvaporasiKoreksiOffsetChanged event,
|
||||
Emitter<EvaporasiSettingsState> emit,
|
||||
|
|
|
|||
|
|
@ -336,14 +336,6 @@ class _SensorSettingsTab extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// ── Rumus preview ─────────────────────────────────────
|
||||
_FormulaPreview(
|
||||
kFaktor: state.kFaktor,
|
||||
radiusM: state.radiusM,
|
||||
magnetCount: state.magnetCount,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// ── Tombol Simpan ─────────────────────────────────────
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
|
|
@ -1037,75 +1029,6 @@ class _SettingsCard extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class _FormulaPreview extends StatelessWidget {
|
||||
final double kFaktor;
|
||||
final double radiusM;
|
||||
final int magnetCount;
|
||||
|
||||
const _FormulaPreview({
|
||||
required this.kFaktor,
|
||||
required this.radiusM,
|
||||
required this.magnetCount,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Contoh: 1 pulsa per detik
|
||||
final exampleRps = 1.0 / magnetCount;
|
||||
final exampleSpeed = 2 * 3.14159 * radiusM * exampleRps * kFaktor;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade900,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(children: [
|
||||
Icon(Icons.functions_rounded,
|
||||
size: 16, color: Colors.amber.shade300),
|
||||
const SizedBox(width: 8),
|
||||
Text('Preview Rumus',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.amber.shade300,
|
||||
fontWeight: FontWeight.bold)),
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'speed = 2π × radius × (pulsa / (dt × magnet)) × k',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey.shade400,
|
||||
fontFamily: 'monospace'),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
' = 2π × ${radiusM.toStringAsFixed(3)}m × (p / (dt × $magnetCount)) × ${kFaktor.toStringAsFixed(1)}',
|
||||
style: const TextStyle(
|
||||
fontSize: 12, color: Colors.white70, fontFamily: 'monospace'),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'@ 1 pulsa/detik → ${exampleSpeed.toStringAsFixed(3)} m/s',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.green.shade300,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'monospace'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ── WIDGET BARU: _MagnetCountSelector ─────────────────────────
|
||||
// Tambahkan class baru ini di bagian bawah file,
|
||||
// setelah class _FormulaPreview
|
||||
|
||||
class _MagnetCountSelector extends StatelessWidget {
|
||||
final int selected;
|
||||
final ValueChanged<int> onSelected;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'dart:async';
|
|||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:firebase_database/firebase_database.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:monitoring_repository/monitoring_repository.dart';
|
||||
|
||||
import '../../../../blocs/notification_bloc/notification_bloc.dart';
|
||||
|
|
@ -56,6 +57,8 @@ class EvaporasiBloc extends Bloc<EvaporasiEvent, EvaporasiState> {
|
|||
|
||||
final MonitoringRepository _repository;
|
||||
final NotificationBloc _notificationBloc;
|
||||
final FlutterLocalNotificationsPlugin _localNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
StreamSubscription<Evaporasi>? _subscription;
|
||||
double _thresholdRendah = 2.0;
|
||||
double _thresholdTinggi = 10.0;
|
||||
|
|
@ -66,6 +69,7 @@ class EvaporasiBloc extends Bloc<EvaporasiEvent, EvaporasiState> {
|
|||
}) : _repository = repository,
|
||||
_notificationBloc = notificationBloc,
|
||||
super(EvaporasiState()) {
|
||||
_initLocalNotifications();
|
||||
on<WatchEvaporasiStarted>(_onStarted);
|
||||
on<_EvaporasiRealtimeUpdated>(_onRealtimeUpdated);
|
||||
on<EvaporasiDateRangeChanged>(_onDateRangeChanged);
|
||||
|
|
@ -158,6 +162,17 @@ class EvaporasiBloc extends Bloc<EvaporasiEvent, EvaporasiState> {
|
|||
thresholdRendah: _thresholdRendah,
|
||||
thresholdTinggi: _thresholdTinggi,
|
||||
);
|
||||
|
||||
final bool hasFallenBelowCritical =
|
||||
event.data.tinggiAir < state.batasKritisCm &&
|
||||
state.waterLevel >= state.batasKritisCm;
|
||||
final bool statusBecameHigh =
|
||||
state.weatherStatus != 'Tinggi' && status == 'Tinggi';
|
||||
|
||||
if (hasFallenBelowCritical || statusBecameHigh) {
|
||||
await _showCriticalNotification();
|
||||
}
|
||||
|
||||
_emitAlert(status, willRain, event.data.evaporasi);
|
||||
|
||||
emit(state.copyWith(
|
||||
|
|
@ -180,79 +195,29 @@ class EvaporasiBloc extends Bloc<EvaporasiEvent, EvaporasiState> {
|
|||
emit(state.copyWith(isLoading: true));
|
||||
|
||||
final history = state.history;
|
||||
final start = event.startDate;
|
||||
final end = event.endDate;
|
||||
|
||||
final isSingle = _isSameDay(start, end);
|
||||
|
||||
List<double> values;
|
||||
List<double> temps;
|
||||
List<String> labels;
|
||||
|
||||
|
||||
if (isSingle) {
|
||||
// 1 hari → per jam
|
||||
values = TimeSeriesMapper.toSpecificDate(
|
||||
data: history,
|
||||
getTime: (e) => e.timestamp,
|
||||
getValue: (e) => e.evaporasi,
|
||||
targetDate: start,
|
||||
);
|
||||
temps = TimeSeriesMapper.toSpecificDate(
|
||||
data: history,
|
||||
getTime: (e) => e.timestamp,
|
||||
getValue: (e) => e.suhu,
|
||||
targetDate: start,
|
||||
);
|
||||
labels = List.generate(24, (i) => '${i.toString().padLeft(2, '0')}:00');
|
||||
} else {
|
||||
// Range → per hari (tapi evaporasi dikalibrasi dengan rumus:
|
||||
// E(hari ke-2) = max(evap hari ke-1) - max(evap hari ke-2))
|
||||
final days = _buildDayList(start, end);
|
||||
|
||||
|
||||
final dailyMaxEvap = List<double>.filled(days.length, 0.0);
|
||||
final dailyMaxTemp = List<double>.filled(days.length, 0.0);
|
||||
final dailyHasValue = List<bool>.filled(days.length, false);
|
||||
|
||||
|
||||
for (final item in history) {
|
||||
final d = DateTime(item.timestamp.year, item.timestamp.month, item.timestamp.day);
|
||||
final idx = days.indexWhere((x) => x == d);
|
||||
if (idx < 0) continue;
|
||||
|
||||
final evap = item.evaporasi;
|
||||
final temp = item.suhu;
|
||||
|
||||
if (!dailyHasValue[idx]) {
|
||||
dailyHasValue[idx] = true;
|
||||
dailyMaxEvap[idx] = evap;
|
||||
dailyMaxTemp[idx] = temp;
|
||||
} else {
|
||||
if (evap > dailyMaxEvap[idx]) dailyMaxEvap[idx] = evap;
|
||||
if (temp > dailyMaxTemp[idx]) dailyMaxTemp[idx] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// Hitung E berbasis pasangan H1 (maks hari sebelumnya) - H2 (maks hari ini).
|
||||
// Definisi sesuai permintaan: E untuk hari i = maxEvap(hari i-1) - maxEvap(hari i)
|
||||
// Mulai tanggal 21 Mei s/d sekarang: untuk hari pertama di rentang, nilainya 0
|
||||
final calibrated = List<double>.filled(days.length, 0.0);
|
||||
for (int i = 1; i < days.length; i++) {
|
||||
final e = dailyMaxEvap[i - 1] - dailyMaxEvap[i];
|
||||
calibrated[i] = e < 0 ? 0.0 : e;
|
||||
}
|
||||
|
||||
values = calibrated;
|
||||
temps = dailyMaxTemp;
|
||||
labels = _buildLabels(days);
|
||||
|
||||
}
|
||||
final selectedDate = DateTime(
|
||||
event.startDate.year,
|
||||
event.startDate.month,
|
||||
event.startDate.day,
|
||||
);
|
||||
|
||||
final values = TimeSeriesMapper.toSpecificDate(
|
||||
data: history,
|
||||
getTime: (e) => e.timestamp,
|
||||
getValue: (e) => e.evaporasi,
|
||||
targetDate: selectedDate,
|
||||
);
|
||||
final temps = TimeSeriesMapper.toSpecificDate(
|
||||
data: history,
|
||||
getTime: (e) => e.timestamp,
|
||||
getValue: (e) => e.suhu,
|
||||
targetDate: selectedDate,
|
||||
);
|
||||
final labels = List.generate(24, (i) => '${i.toString().padLeft(2, '0')}:00');
|
||||
|
||||
emit(state.copyWith(
|
||||
startDate: start,
|
||||
endDate: end,
|
||||
startDate: selectedDate,
|
||||
endDate: selectedDate,
|
||||
chartValues: values,
|
||||
chartTemperatures: temps,
|
||||
chartLabels: labels,
|
||||
|
|
@ -317,6 +282,56 @@ class EvaporasiBloc extends Bloc<EvaporasiEvent, EvaporasiState> {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _initLocalNotifications() async {
|
||||
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
|
||||
const iosSettings = DarwinInitializationSettings();
|
||||
const initSettings = InitializationSettings(
|
||||
android: androidSettings,
|
||||
iOS: iosSettings,
|
||||
macOS: iosSettings,
|
||||
);
|
||||
|
||||
try {
|
||||
await _localNotificationsPlugin.initialize(settings: initSettings);
|
||||
} catch (_) {
|
||||
// Jika gagal, lanjutkan tanpa notifikasi lokal.
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showCriticalNotification() async {
|
||||
const androidDetails = AndroidNotificationDetails(
|
||||
'evaporasi_alerts',
|
||||
'Evaporasi Alerts',
|
||||
channelDescription: 'Peringatan Evaporasi dan level air kritis',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
ticker: 'Peringatan Darurat',
|
||||
playSound: true,
|
||||
enableVibration: true,
|
||||
);
|
||||
const iosDetails = DarwinNotificationDetails(
|
||||
presentAlert: true,
|
||||
presentSound: true,
|
||||
presentBadge: true,
|
||||
);
|
||||
const notificationDetails = NotificationDetails(
|
||||
android: androidDetails,
|
||||
iOS: iosDetails,
|
||||
macOS: iosDetails,
|
||||
);
|
||||
|
||||
try {
|
||||
await _localNotificationsPlugin.show(
|
||||
id: 0,
|
||||
title: 'Peringatan Darurat',
|
||||
body: 'Peringatan Darurat: Batas Air Kritis tercapai, periksa pompa segera!',
|
||||
notificationDetails: notificationDetails,
|
||||
);
|
||||
} catch (_) {
|
||||
// Ignore local notification failure.
|
||||
}
|
||||
}
|
||||
|
||||
static double _toDouble(dynamic value, double fallback) {
|
||||
if (value == null) return fallback;
|
||||
if (value is num) return value.toDouble();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ class EvaporasiState extends Equatable {
|
|||
final double currentValue;
|
||||
final double temperature;
|
||||
final double waterLevel;
|
||||
final double batasKritisCm;
|
||||
|
||||
// Rentang tanggal aktif untuk grafik
|
||||
final DateTime startDate;
|
||||
|
|
@ -31,6 +32,7 @@ class EvaporasiState extends Equatable {
|
|||
this.currentValue = 0.0,
|
||||
this.temperature = 0.0,
|
||||
this.waterLevel = 0.0,
|
||||
this.batasKritisCm = 15.0,
|
||||
DateTime? startDate,
|
||||
DateTime? endDate,
|
||||
this.chartValues = const [],
|
||||
|
|
@ -50,6 +52,7 @@ class EvaporasiState extends Equatable {
|
|||
double? currentValue,
|
||||
double? temperature,
|
||||
double? waterLevel,
|
||||
double? batasKritisCm,
|
||||
DateTime? startDate,
|
||||
DateTime? endDate,
|
||||
List<double>? chartValues,
|
||||
|
|
@ -68,6 +71,7 @@ class EvaporasiState extends Equatable {
|
|||
currentValue: currentValue ?? this.currentValue,
|
||||
temperature: temperature ?? this.temperature,
|
||||
waterLevel: waterLevel ?? this.waterLevel,
|
||||
batasKritisCm: batasKritisCm ?? this.batasKritisCm,
|
||||
startDate: startDate ?? this.startDate,
|
||||
endDate: endDate ?? this.endDate,
|
||||
chartValues: chartValues ?? this.chartValues,
|
||||
|
|
@ -94,7 +98,7 @@ class EvaporasiState extends Equatable {
|
|||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
currentValue, temperature, waterLevel,
|
||||
currentValue, temperature, waterLevel, batasKritisCm,
|
||||
startDate, endDate,
|
||||
chartValues, chartTemperatures, chartLabels,
|
||||
history, filteredHistory, selectedDateFilter,
|
||||
|
|
|
|||
|
|
@ -372,71 +372,6 @@ class _EvaporasiScreenState extends State<EvaporasiScreen> {
|
|||
const EvaporasiRangeSelector(),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// ── Block nilai E (kalibrasi H1 - H2) ──────────────────
|
||||
BlocBuilder<EvaporasiBloc, EvaporasiState>(
|
||||
builder: (context, s) {
|
||||
if (s.chartValues.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
// Untuk range > 1 hari, chartValues berisi E per hari
|
||||
final isRange = !s.isSingleDay;
|
||||
if (!isRange) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
// Tampilkan E pada hari terakhir rentang (hari ke-N)
|
||||
final eLast = s.chartValues.last;
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(color: Colors.blue.shade100),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: const [
|
||||
Icon(Icons.calculate_rounded,
|
||||
color: Colors.blue, size: 20),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
'Nilai Evaporasi Terkalibrasi (E)',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'E terakhir (hari terakhir rentang): ${eLast.toStringAsFixed(2)} mm',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue.shade700,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'Rumus: E = max(H1) − max(H2)',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.blueGrey.shade700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// ── Chart ───────────────────────────────────
|
||||
BlocBuilder<EvaporasiBloc, EvaporasiState>(
|
||||
builder: (context, s) => EvaporasiChartWidget(
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class EvaporasiRangeSelector extends StatelessWidget {
|
|||
: '${_fmt(start)} → ${_fmt(end)}';
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => _pickRange(context, start, end),
|
||||
onTap: () => _pickDate(context, start),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
|
|
@ -79,9 +79,9 @@ class EvaporasiRangeSelector extends StatelessWidget {
|
|||
},
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
// Tombol pilih range bebas
|
||||
// Tombol pilih tanggal harian
|
||||
GestureDetector(
|
||||
onTap: () => _pickRange(context, start, end),
|
||||
onTap: () => _pickDate(context, start),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 6),
|
||||
|
|
@ -115,13 +115,13 @@ class EvaporasiRangeSelector extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> _pickRange(
|
||||
BuildContext context, DateTime start, DateTime end) async {
|
||||
final picked = await showDateRangePicker(
|
||||
Future<void> _pickDate(
|
||||
BuildContext context, DateTime date) async {
|
||||
final picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: date,
|
||||
firstDate: DateTime(2024),
|
||||
lastDate: DateTime.now(),
|
||||
initialDateRange: DateTimeRange(start: start, end: end),
|
||||
locale: const Locale('id', 'ID'),
|
||||
builder: (context, child) {
|
||||
return Theme(
|
||||
|
|
@ -138,10 +138,11 @@ class EvaporasiRangeSelector extends StatelessWidget {
|
|||
);
|
||||
|
||||
if (picked != null && context.mounted) {
|
||||
final selected = DateTime(picked.year, picked.month, picked.day);
|
||||
context.read<EvaporasiBloc>().add(
|
||||
EvaporasiDateRangeChanged(
|
||||
startDate: picked.start,
|
||||
endDate: picked.end,
|
||||
startDate: selected,
|
||||
endDate: selected,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import cloud_firestore
|
|||
import firebase_auth
|
||||
import firebase_core
|
||||
import firebase_database
|
||||
import flutter_local_notifications
|
||||
import flutter_localization
|
||||
import google_sign_in_ios
|
||||
import printing
|
||||
|
|
@ -22,6 +23,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
|
||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||
FLTFirebaseDatabasePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseDatabasePlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
FlutterLocalizationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalizationPlugin"))
|
||||
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
|
||||
PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin"))
|
||||
|
|
|
|||
60
pubspec.lock
60
pubspec.lock
|
|
@ -193,6 +193,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.8"
|
||||
dbus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dbus
|
||||
sha256: "0ce9b0a839e6dee59a37a623d2fc26a35bbbe6404213e419b0d6411023d62645"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.14"
|
||||
dio:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -374,6 +382,46 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
flutter_local_notifications:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: a0d7141f14cabcee42967470a858dfc99dd6cfb70d3cab404bacfcafa9e84e70
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "22.0.1"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_linux
|
||||
sha256: "9ca97e63776f29ab1b955725c09999fc2c150523269db150c39274f2a43c5a8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.1"
|
||||
flutter_local_notifications_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
sha256: ff0013eae795e8dc8fad4a8992a209e64d3ba2fbd8bf5e43c36bf448f95bd814
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.0.0"
|
||||
flutter_local_notifications_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_web
|
||||
sha256: "516afaf97a2d1e67a036c6617321b00d205d72f7a67b6eccf936cd565f985878"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
flutter_local_notifications_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_windows
|
||||
sha256: "6f43bdd03b171b7a90f22647506fea33e2bb12294b7c7c7a3d690e960a382945"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
flutter_localization:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -945,6 +993,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.7"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timezone
|
||||
sha256: "784a5e34d2eb62e1326f24d6f600aaaee452eb8ca8ef2f384a59244e292d158b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1036,10 +1092,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: a1fc9eb9248baa05dfc12ed5b66e377b3e23f095eec078e0371622b9033810d9
|
||||
sha256: ba6f4bba816c8d7e3c1580e170f3786d216951cc6b94babc3b814c08d2cb2738
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
version: "6.3.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ dependencies:
|
|||
path: packages/monitoring_repository
|
||||
path_provider: ^2.1.5
|
||||
pdf: ^3.11.1
|
||||
flutter_local_notifications: ^22.0.1
|
||||
printing: ^5.13.1
|
||||
rxdart: ^0.27.7
|
||||
share_plus: ^13.1.0
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
flutter_local_notifications_windows
|
||||
jni
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue