Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import 'package:flutter/material.dart';
- import '../core/services/map_firestore_service.dart';
- import '../core/utils/app_error_messages.dart';
- import '../models/bus_line_model.dart';
- import '../models/line_route_model.dart';
- import '../models/location_model.dart';
- class MapProvider extends ChangeNotifier {
- final MapFirestoreService _mapFirestoreService;
- MapProvider({MapFirestoreService? mapFirestoreService})
- : _mapFirestoreService = mapFirestoreService ?? MapFirestoreService();
- List<BusLineModel> _busLines = [];
- List<LineRouteModel> _lineRoutes = [];
- List<LocationModel> _locations = [];
- final Set<String> _selectedLineIds = {};
- String _selectedDirection = 'west_to_east';
- bool _isLoading = false;
- String? _errorMessage;
- AppErrorType _errorType = AppErrorType.server;
- List<BusLineModel> get busLines => _busLines;
- List<LineRouteModel> get lineRoutes => _lineRoutes;
- List<LocationModel> get locations => _locations;
- Set<String> get selectedLineIds => _selectedLineIds;
- String get selectedDirection => _selectedDirection;
- bool get isLoading => _isLoading;
- String? get errorMessage => _errorMessage;
- AppErrorType get errorType => _errorType;
- bool get hasData =>
- _busLines.isNotEmpty && _lineRoutes.isNotEmpty && _locations.isNotEmpty;
- List<LineRouteModel> get selectedRoutes {
- return _lineRoutes.where((route) {
- return _selectedLineIds.contains(route.lineId) &&
- route.direction == _selectedDirection &&
- route.isActive;
- }).toList();
- }
- List<LocationModel> get selectedRouteStops {
- final allStopIds = selectedRoutes.expand((route) => route.stopIdsOrdered).toSet();
- return _locations.where((location) {
- return allStopIds.contains(location.id);
- }).toList();
- }
- Future<void> loadMapData() async {
- _isLoading = true;
- _errorMessage = null;
- _errorType = AppErrorType.server;
- notifyListeners();
- try {
- final busLines = await _mapFirestoreService.getBusLines();
- final locations = await _mapFirestoreService.getLocations();
- final lineRoutes = await _mapFirestoreService.getLineRoutes();
- _busLines = busLines;
- _locations = locations;
- _lineRoutes = lineRoutes;
- _selectedLineIds
- ..clear()
- ..addAll(_busLines.map((line) => line.id));
- if (!hasData) {
- _errorMessage = "I couldn't load the app data right now. Please try again in a moment.";
- }
- } catch (e) {
- _busLines = [];
- _locations = [];
- _lineRoutes = [];
- _selectedLineIds.clear();
- final errorInfo = AppErrorMessages.fromError(
- e,
- context: 'transport map',
- );
- _errorMessage = errorInfo.message;
- _errorType = errorInfo.type;
- } finally {
- _isLoading = false;
- notifyListeners();
- }
- }
- List<int> getLineNumbersForStop(String stopId) {
- final lineIds = _lineRoutes
- .where(
- (route) => route.stopIdsOrdered.contains(stopId) && route.isActive,
- )
- .map((route) => route.lineId)
- .toSet();
- final numbers = _busLines
- .where((line) => lineIds.contains(line.id))
- .map((line) => line.number)
- .toList();
- numbers.sort();
- return numbers;
- }
- String getShortDescription(String? description, {int maxLength = 30}) {
- if (description == null || description.trim().isEmpty) {
- return '';
- }
- final trimmed = description.trim();
- if (trimmed.length <= maxLength) {
- return trimmed;
- }
- return '${trimmed.substring(0, maxLength)}...';
- }
- void toggleLineSelection(String lineId) {
- if (_selectedLineIds.contains(lineId)) {
- if (_selectedLineIds.length > 1) {
- _selectedLineIds.remove(lineId);
- }
- } else {
- _selectedLineIds.add(lineId);
- }
- notifyListeners();
- }
- void selectDirection(String direction) {
- _selectedDirection = direction;
- notifyListeners();
- }
- }
- import 'package:flutter/material.dart';
- import 'package:shared_preferences/shared_preferences.dart';
- import '../core/services/notifications_firestore_service.dart';
- import '../core/utils/app_error_messages.dart';
- import '../models/app_notification_model.dart';
- class NotificationsProvider extends ChangeNotifier {
- static const String _readIdsKey = 'read_notification_ids';
- final NotificationsFirestoreService _service;
- NotificationsProvider({NotificationsFirestoreService? service})
- : _service = service ?? NotificationsFirestoreService();
- List<AppNotificationModel> _notifications = [];
- Set<String> _readIds = {};
- bool _isLoading = false;
- String? _errorMessage;
- AppErrorType _errorType = AppErrorType.server;
- List<AppNotificationModel> get notifications => _notifications;
- bool get isLoading => _isLoading;
- String? get errorMessage => _errorMessage;
- AppErrorType get errorType => _errorType;
- bool isRead(String id) => _readIds.contains(id);
- bool get hasUnread {
- return _notifications.any((notification) => !_readIds.contains(notification.id));
- }
- Future<void> initialize() async {
- await _loadReadIds();
- await loadNotifications();
- }
- Future<void> _loadReadIds() async {
- final prefs = await SharedPreferences.getInstance();
- final stored = prefs.getStringList(_readIdsKey) ?? [];
- _readIds = stored.toSet();
- notifyListeners();
- }
- Future<void> _saveReadIds() async {
- final prefs = await SharedPreferences.getInstance();
- await prefs.setStringList(_readIdsKey, _readIds.toList());
- }
- Future<void> loadNotifications() async {
- _isLoading = true;
- _errorMessage = null;
- _errorType = AppErrorType.server;
- notifyListeners();
- try {
- final result = await _service.getNotifications(limit: 20);
- _notifications = result;
- } catch (e) {
- final errorInfo = AppErrorMessages.fromError(
- e,
- context: 'notifications',
- );
- _errorMessage = errorInfo.message;
- _errorType = errorInfo.type;
- _notifications = [];
- } finally {
- _isLoading = false;
- notifyListeners();
- }
- }
- Future<void> markAsRead(String id) async {
- if (_readIds.contains(id)) return;
- _readIds.add(id);
- await _saveReadIds();
- notifyListeners();
- }
- String getPreviewText(String text, {int maxLength = 70}) {
- final trimmed = text.trim();
- if (trimmed.length <= maxLength) return trimmed;
- return '${trimmed.substring(0, maxLength)}...';
- }
- String formatNotificationDate(DateTime? date) {
- if (date == null) return '';
- final now = DateTime.now();
- final today = DateTime(now.year, now.month, now.day);
- final target = DateTime(date.year, date.month, date.day);
- final difference = today.difference(target).inDays;
- if (difference == 0) return 'Today';
- if (difference == 1) return 'Yesterday';
- final day = date.day.toString().padLeft(2, '0');
- final month = date.month.toString().padLeft(2, '0');
- final year = date.year.toString();
- return '$day.$month.$year';
- }
- String formatNotificationTime(DateTime? date) {
- if (date == null) return '';
- final hour = date.hour.toString().padLeft(2, '0');
- final minute = date.minute.toString().padLeft(2, '0');
- return '$hour:$minute';
- }
- }
- import 'package:flutter/material.dart';
- import '../core/services/info_firestore_service.dart';
- import '../core/utils/app_error_messages.dart';
- import '../models/info_slide_model.dart';
- class InfoProvider extends ChangeNotifier {
- final InfoFirestoreService _service;
- InfoProvider({InfoFirestoreService? service})
- : _service = service ?? InfoFirestoreService();
- List<InfoSlideModel> _slides = [];
- bool _isLoading = false;
- String? _errorMessage;
- AppErrorType _errorType = AppErrorType.server;
- List<InfoSlideModel> get slides => _slides;
- bool get isLoading => _isLoading;
- String? get errorMessage => _errorMessage;
- AppErrorType get errorType => _errorType;
- Future<void> loadSlides() async {
- _isLoading = true;
- _errorMessage = null;
- _errorType = AppErrorType.server;
- notifyListeners();
- try {
- final fetchedSlides = await _service.getInfoSlides();
- _slides = fetchedSlides;
- } catch (e) {
- final errorInfo = AppErrorMessages.fromError(
- e,
- context: 'app info',
- );
- _errorMessage = errorInfo.message;
- _errorType = errorInfo.type;
- _slides = [];
- } finally {
- _isLoading = false;
- notifyListeners();
- }
- }
- }
- import 'dart:async';
- import 'package:flutter/material.dart';
- import '../core/services/arrivals_firestore_service.dart';
- import '../core/utils/app_error_messages.dart';
- import '../models/upcoming_arrival_model.dart';
- class ArrivalsProvider extends ChangeNotifier {
- final ArrivalsFirestoreService _service;
- ArrivalsProvider({ArrivalsFirestoreService? service})
- : _service = service ?? ArrivalsFirestoreService();
- List<UpcomingArrivalModel> _upcomingArrivals = [];
- bool _isLoading = false;
- String? _errorMessage;
- AppErrorType _errorType = AppErrorType.server;
- String? _currentStopId;
- String? _currentDirection;
- Timer? _alignmentTimer;
- Timer? _refreshTimer;
- List<UpcomingArrivalModel> get upcomingArrivals => _upcomingArrivals;
- bool get isLoading => _isLoading;
- String? get errorMessage => _errorMessage;
- AppErrorType get errorType => _errorType;
- Future<void> loadArrivals({
- required String stopId,
- required String direction,
- }) async {
- _currentStopId = stopId;
- _currentDirection = direction;
- _isLoading = true;
- _errorMessage = null;
- _errorType = AppErrorType.server;
- notifyListeners();
- try {
- final now = DateTime.now();
- final relevantTimetables = await _service.getArrivalsForStop(
- stopId: stopId,
- direction: direction,
- );
- final List<UpcomingArrivalModel> arrivals = [];
- for (final timetable in relevantTimetables) {
- for (final departureTime in timetable.departureTimes) {
- final parts = departureTime.split(':');
- if (parts.length != 2) continue;
- final hour = int.tryParse(parts[0]);
- final minute = int.tryParse(parts[1]);
- if (hour == null || minute == null) continue;
- final todayDeparture = DateTime(
- now.year,
- now.month,
- now.day,
- hour,
- minute,
- );
- final minutesUntil = todayDeparture.difference(now).inMinutes;
- if (minutesUntil >= 0) {
- arrivals.add(
- UpcomingArrivalModel(
- routeId: timetable.routeId,
- stopId: timetable.stopId,
- lineId: timetable.lineId,
- minutesUntilArrival: minutesUntil,
- ),
- );
- }
- }
- }
- arrivals.sort(
- (a, b) => a.minutesUntilArrival.compareTo(b.minutesUntilArrival),
- );
- _upcomingArrivals = arrivals.take(5).toList();
- } catch (e) {
- final errorInfo = AppErrorMessages.fromError(
- e,
- context: 'arrival times',
- );
- _errorMessage = errorInfo.message;
- _errorType = errorInfo.type;
- _upcomingArrivals = [];
- } finally {
- _isLoading = false;
- notifyListeners();
- }
- }
- void startAutoRefresh() {
- stopAutoRefresh();
- final now = DateTime.now();
- final nextMinute = DateTime(
- now.year,
- now.month,
- now.day,
- now.hour,
- now.minute + 1,
- );
- final delay = nextMinute.difference(now);
- _alignmentTimer = Timer(delay, () async {
- if (_currentStopId != null && _currentDirection != null) {
- await loadArrivals(
- stopId: _currentStopId!,
- direction: _currentDirection!,
- );
- }
- _refreshTimer = Timer.periodic(const Duration(minutes: 1), (_) {
- if (_currentStopId != null && _currentDirection != null) {
- loadArrivals(
- stopId: _currentStopId!,
- direction: _currentDirection!,
- );
- }
- });
- });
- }
- void stopAutoRefresh() {
- _alignmentTimer?.cancel();
- _alignmentTimer = null;
- _refreshTimer?.cancel();
- _refreshTimer = null;
- }
- String formatArrivalText(int minutes) {
- if (minutes <= 1) return 'Now';
- if (minutes >= 180) {
- final hours = minutes ~/ 60;
- return '${hours}h. +';
- }
- return '$minutes min.';
- }
- bool isArrivingSoon(int minutes) {
- return minutes <= 1 || minutes < 10;
- }
- @override
- void dispose() {
- stopAutoRefresh();
- super.dispose();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment