From db42cf30501c58f8ce1de370e0f3a24217f88c82 Mon Sep 17 00:00:00 2001 From: ssbg04 Date: Tue, 18 Aug 2026 10:30:34 +0800 Subject: [PATCH] fix: resolve Sheetifye Excel viewer integration, Riverpod autoDispose type bounds, and Dashboard initState error --- frontend/AGENTS.md | 7 +- .../lib/ui/providers/activity_provider.dart | 3 +- frontend/lib/ui/providers/auth_provider.dart | 7 +- .../lib/ui/providers/dashboard_provider.dart | 2 +- .../screens/dashboard/dashboard_screen.dart | 3 +- .../screens/documents/documents_screen.dart | 29 +- .../widgets/document_preview_modal.dart | 21 +- .../widgets/excel_viewer_widget.dart | 437 +----------------- .../ui/screens/students/students_screen.dart | 11 +- frontend/pubspec.lock | 184 +------- frontend/pubspec.yaml | 9 +- 11 files changed, 78 insertions(+), 635 deletions(-) diff --git a/frontend/AGENTS.md b/frontend/AGENTS.md index 41a443a..bb3b112 100644 --- a/frontend/AGENTS.md +++ b/frontend/AGENTS.md @@ -158,9 +158,12 @@ Files backup/restore - mirror mode or zip --> - Document preveiew modal -> make it fullscreen modal -> add "add to print list" icon button -> move the zoom in/out inside of the pdf or image viewer -> add "open with" icon button for excel files to open external excel viewer - hold feature to see more menu in android add "view student profile" --> -# ARCHVES SCREEN + + +# DOCUMENTS SCREEN +- document preview modal -> use sheetifye package for excel viewer --- diff --git a/frontend/lib/ui/providers/activity_provider.dart b/frontend/lib/ui/providers/activity_provider.dart index ecc4dad..708b8f6 100644 --- a/frontend/lib/ui/providers/activity_provider.dart +++ b/frontend/lib/ui/providers/activity_provider.dart @@ -49,7 +49,8 @@ final userHistoryQueryProvider = UserHistoryQueryParams >(UserHistoryQueryNotifier.new); -class UserHistoryQueryNotifier extends Notifier { +class UserHistoryQueryNotifier + extends AutoDisposeNotifier { @override UserHistoryQueryParams build() => const UserHistoryQueryParams(); diff --git a/frontend/lib/ui/providers/auth_provider.dart b/frontend/lib/ui/providers/auth_provider.dart index 72a90d6..f08ac48 100644 --- a/frontend/lib/ui/providers/auth_provider.dart +++ b/frontend/lib/ui/providers/auth_provider.dart @@ -5,13 +5,8 @@ import '../../domain/entities/user_model.dart'; import 'document_provider.dart'; import 'archives_provider.dart'; import 'student_provider.dart' hide academicYearsProvider; -import 'users_provider.dart'; -import 'notification_provider.dart'; import 'navigation_provider.dart'; -import 'dashboard_provider.dart'; -import 'setup_provider.dart'; import 'reports_provider.dart'; -import 'ocr_provider.dart'; import 'connected_users_provider.dart'; final authRepositoryProvider = Provider( @@ -102,7 +97,7 @@ class AuthNotifier extends AsyncNotifier { final repository = ref.read(authRepositoryProvider); final updatedUser = await repository.getProfile(); state = AsyncData(updatedUser); - } catch (e, stack) { + } catch (e) { // Don't emit error state to prevent UI disruptions on background refresh failures print('Background refresh failed: $e'); } diff --git a/frontend/lib/ui/providers/dashboard_provider.dart b/frontend/lib/ui/providers/dashboard_provider.dart index 8ebc6ad..27575bd 100644 --- a/frontend/lib/ui/providers/dashboard_provider.dart +++ b/frontend/lib/ui/providers/dashboard_provider.dart @@ -94,7 +94,7 @@ final activityQueryProvider = ActivityQueryNotifier.new, ); -class ActivityQueryNotifier extends Notifier { +class ActivityQueryNotifier extends AutoDisposeNotifier { @override ActivityQueryParams build() => const ActivityQueryParams(); diff --git a/frontend/lib/ui/screens/dashboard/dashboard_screen.dart b/frontend/lib/ui/screens/dashboard/dashboard_screen.dart index 75335a4..f8b995c 100644 --- a/frontend/lib/ui/screens/dashboard/dashboard_screen.dart +++ b/frontend/lib/ui/screens/dashboard/dashboard_screen.dart @@ -62,10 +62,9 @@ class _DashboardScreenState extends ConsumerState { if (mounted) setState(() {}); }); - ref.invalidate(dashboardDataProvider); - WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; + ref.invalidate(dashboardDataProvider); ref.read(notificationsProvider.notifier).refreshNotifications(); if (ref.read(activeTabProvider) == 'Dashboard') { diff --git a/frontend/lib/ui/screens/documents/documents_screen.dart b/frontend/lib/ui/screens/documents/documents_screen.dart index bac1c45..6cf94e1 100644 --- a/frontend/lib/ui/screens/documents/documents_screen.dart +++ b/frontend/lib/ui/screens/documents/documents_screen.dart @@ -107,23 +107,26 @@ class _DocumentsScreenState extends ConsumerState } }); - // If a specific student was passed, jump to Folders tab and open that folder - final initialFolder = ref.read(openedFolderProvider); - if (initialFolder != null) { - _openedFolderStudentId = initialFolder.id; - _openedFolderName = initialFolder.name; - WidgetsBinding.instance.addPostFrameCallback((_) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted) return; + // If a specific student was passed, jump to Folders tab and open that folder + final initialFolder = ref.read(openedFolderProvider); + if (initialFolder != null) { + setState(() { + _openedFolderStudentId = initialFolder.id; + _openedFolderName = initialFolder.name; + }); ref.read(documentQueryProvider.notifier).setStudentId(initialFolder.id); - }); - } else if (widget.initialStudentId != null) { - _openedFolderStudentId = widget.initialStudentId; - _openedFolderName = 'Student Documents'; - WidgetsBinding.instance.addPostFrameCallback((_) { + } else if (widget.initialStudentId != null) { + setState(() { + _openedFolderStudentId = widget.initialStudentId; + _openedFolderName = 'Student Documents'; + }); ref .read(documentQueryProvider.notifier) .setStudentId(widget.initialStudentId); - }); - } + } + }); _tabController.addListener(() { setState(() {}); // Ensure header title updates immediately on tab change diff --git a/frontend/lib/ui/screens/documents/widgets/document_preview_modal.dart b/frontend/lib/ui/screens/documents/widgets/document_preview_modal.dart index a4eb38e..2e46105 100644 --- a/frontend/lib/ui/screens/documents/widgets/document_preview_modal.dart +++ b/frontend/lib/ui/screens/documents/widgets/document_preview_modal.dart @@ -61,7 +61,6 @@ class _DocumentPreviewDialog extends ConsumerStatefulWidget { class _DocumentPreviewDialogState extends ConsumerState<_DocumentPreviewDialog> { bool _imageError = false; - bool _imageLoaded = false; String? _token; bool _isOpeningExternal = false; @@ -71,13 +70,13 @@ class _DocumentPreviewDialogState void _zoomImageIn() { final matrix = _imageTransformationController.value.clone(); - matrix.scale(1.25, 1.25, 1.0); + matrix.scaleByDouble(1.25, 1.25, 1.0, 1.0); _imageTransformationController.value = matrix; } void _zoomImageOut() { final matrix = _imageTransformationController.value.clone(); - matrix.scale(1 / 1.25, 1 / 1.25, 1.0); + matrix.scaleByDouble(1 / 1.25, 1 / 1.25, 1.0, 1.0); _imageTransformationController.value = matrix; } @@ -93,9 +92,6 @@ class _DocumentPreviewDialogState @override void initState() { super.initState(); - if (widget.localFile != null) { - _imageLoaded = true; - } _loadToken(); } @@ -447,16 +443,7 @@ class _DocumentPreviewDialogState _fileUrl, fit: BoxFit.contain, loadingBuilder: (ctx, child, progress) { - if (progress == null) { - WidgetsBinding.instance.addPostFrameCallback(( - _, - ) { - if (mounted) { - setState(() => _imageLoaded = true); - } - }); - return child; - } + if (progress == null) return child; return Center( child: Column( mainAxisSize: MainAxisSize.min, @@ -480,7 +467,7 @@ class _DocumentPreviewDialogState ), ); }, - errorBuilder: (_, __, ___) { + errorBuilder: (context, error, stackTrace) { WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) setState(() => _imageError = true); }); diff --git a/frontend/lib/ui/screens/documents/widgets/excel_viewer_widget.dart b/frontend/lib/ui/screens/documents/widgets/excel_viewer_widget.dart index 51b84ba..d95bc9b 100644 --- a/frontend/lib/ui/screens/documents/widgets/excel_viewer_widget.dart +++ b/frontend/lib/ui/screens/documents/widgets/excel_viewer_widget.dart @@ -1,100 +1,11 @@ -import 'dart:convert'; import 'dart:io'; -import 'dart:math' as math; +import 'dart:typed_data'; import 'package:dio/dio.dart'; -import 'package:excel/excel.dart' hide Border; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:sheetifye/sheetifye.dart'; import '../../../../core/constants/app_colors.dart'; -/// Background isolate function to decode CSV bytes without blocking UI thread. -Map>> _decodeCsvInBackground(List bytes) { - final content = utf8.decode(bytes); - final lines = content.split('\n'); - final List> rows = []; - for (var line in lines) { - if (line.trim().isEmpty) continue; - if (rows.length >= 500) break; // Cap at 500 rows for mobile/desktop instant preview - final cols = line.split(',').map((e) => e.trim()).toList(); - if (cols.length > 30) { - rows.add(cols.sublist(0, 30)); - } else { - rows.add(cols); - } - } - return {'Sheet 1': rows}; -} - -/// Background isolate function to decode Excel bytes without blocking UI thread. -Map>> _decodeExcelInBackground(List bytes) { - final excel = Excel.decodeBytes(bytes); - final Map>> parsedSheets = {}; - - for (final table in excel.tables.keys) { - final sheet = excel.tables[table]; - if (sheet == null || sheet.rows.isEmpty) continue; - - // 1st pass: find the actual last non-empty row and column in the sheet - int maxNonEmptyRow = -1; - int maxNonEmptyCol = -1; - final int rowLimit = math.min(sheet.rows.length, 500); // Cap at 500 rows - - for (int r = 0; r < rowLimit; r++) { - final row = sheet.rows[r]; - final int colLimit = math.min(row.length, 30); // Cap at 30 columns - for (int c = 0; c < colLimit; c++) { - final cell = row[c]; - if (cell != null && - cell.value != null && - cell.value.toString().trim().isNotEmpty) { - if (r > maxNonEmptyRow) maxNonEmptyRow = r; - if (c > maxNonEmptyCol) maxNonEmptyCol = c; - } - } - } - - if (maxNonEmptyRow == -1 || maxNonEmptyCol == -1) { - continue; // Skip completely empty sheets - } - - // 2nd pass: extract ONLY up to maxNonEmptyRow and maxNonEmptyCol - final List> sheetRows = []; - for (int r = 0; r <= maxNonEmptyRow; r++) { - final row = sheet.rows[r]; - final List rowCells = []; - for (int c = 0; c <= maxNonEmptyCol; c++) { - String valStr = ''; - if (c < row.length) { - final cell = row[c]; - if (cell != null && cell.value != null) { - final val = cell.value; - try { - if (val is TextCellValue) { - valStr = val.value.toString(); - } else if (val is IntCellValue) { - valStr = val.value.toString(); - } else if (val is DoubleCellValue) { - valStr = val.value.toString(); - } else if (val is BoolCellValue) { - valStr = val.value ? 'TRUE' : 'FALSE'; - } else { - valStr = val.toString(); - } - } catch (_) { - valStr = val.toString(); - } - } - } - rowCells.add(valStr); - } - sheetRows.add(rowCells); - } - parsedSheets[table] = sheetRows; - } - return parsedSheets; -} - class ExcelViewerWidget extends StatefulWidget { final File? localFile; final String? networkUrl; @@ -116,17 +27,7 @@ class ExcelViewerWidget extends StatefulWidget { class _ExcelViewerWidgetState extends State { bool _isLoading = true; String? _errorMessage; - - // Workbook data - Map>> _sheetData = {}; - List _sheetNames = []; - String? _activeSheetName; - - // Search query - String _searchQuery = ''; - - // Scroll controllers for synchronized scrolling - final ScrollController _horizontalController = ScrollController(); + Uint8List? _fileBytes; @override void initState() { @@ -134,12 +35,6 @@ class _ExcelViewerWidgetState extends State { _loadSpreadsheet(); } - @override - void dispose() { - _horizontalController.dispose(); - super.dispose(); - } - Future _loadSpreadsheet() async { setState(() { _isLoading = true; @@ -147,7 +42,7 @@ class _ExcelViewerWidgetState extends State { }); try { - List bytes; + Uint8List bytes; if (widget.localFile != null) { bytes = await widget.localFile!.readAsBytes(); } else if (widget.networkUrl != null && widget.networkUrl!.isNotEmpty) { @@ -163,49 +58,27 @@ class _ExcelViewerWidgetState extends State { if (response.data == null) { throw Exception('Failed to download spreadsheet file.'); } - bytes = response.data!; + bytes = Uint8List.fromList(response.data!); } else { throw Exception('No file source provided.'); } - final lowerName = widget.fileName.toLowerCase(); - Map>> parsedSheets; - if (lowerName.endsWith('.csv')) { - // Run CSV parsing in background isolate - parsedSheets = await compute(_decodeCsvInBackground, bytes); - } else { - // Run Excel parsing in background isolate to avoid Windows UI freeze - parsedSheets = await compute(_decodeExcelInBackground, bytes); - } - if (mounted) { setState(() { - _sheetData = parsedSheets; - _sheetNames = parsedSheets.keys.toList(); - _activeSheetName = _sheetNames.isNotEmpty ? _sheetNames.first : null; + _fileBytes = bytes; _isLoading = false; }); } } catch (e) { if (mounted) { setState(() { - _errorMessage = 'Could not read spreadsheet: $e'; + _errorMessage = 'Could not load spreadsheet: $e'; _isLoading = false; }); } } } - String _columnLetter(int index) { - String name = ''; - int idx = index; - while (idx >= 0) { - name = String.fromCharCode((idx % 26) + 65) + name; - idx = (idx ~/ 26) - 1; - } - return name; - } - @override Widget build(BuildContext context) { if (_isLoading) { @@ -224,7 +97,7 @@ class _ExcelViewerWidgetState extends State { ); } - if (_errorMessage != null) { + if (_errorMessage != null || _fileBytes == null) { return Center( child: Padding( padding: const EdgeInsets.all(24.0), @@ -243,7 +116,7 @@ class _ExcelViewerWidgetState extends State { ), const SizedBox(height: 8), Text( - _errorMessage!, + _errorMessage ?? 'Unable to display spreadsheet', textAlign: TextAlign.center, style: const TextStyle( color: AppColors.textSecondary, @@ -256,295 +129,9 @@ class _ExcelViewerWidgetState extends State { ); } - final List> activeRows = - _activeSheetName != null - ? (_sheetData[_activeSheetName] ?? >[]) - : >[]; - final List> filteredRows = - _searchQuery.isEmpty - ? activeRows - : activeRows.where((row) { - return row.any( - (cell) => - cell.toLowerCase().contains(_searchQuery.toLowerCase()), - ); - }).toList(); - - // Determine max columns in this sheet (capped at 50 to prevent horizontal bloat) - int maxCols = 0; - for (final r in filteredRows) { - if (r.length > maxCols) maxCols = r.length; - } - if (maxCols == 0) maxCols = 1; - maxCols = math.min(maxCols, 50); - - const double rowNumberWidth = 50.0; - const double cellWidth = 120.0; - final double totalTableWidth = rowNumberWidth + (maxCols * cellWidth); - - return Column( - children: [ - // Top search and statistics toolbar - Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - decoration: BoxDecoration( - color: Colors.white, - border: Border( - bottom: BorderSide(color: Colors.grey.shade300, width: 1), - ), - ), - child: Row( - children: [ - Icon( - Icons.table_chart_rounded, - size: 18, - color: Colors.green.shade700, - ), - const SizedBox(width: 8), - Text( - '${filteredRows.length} Rows × $maxCols Columns', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.textSecondary, - ), - ), - const Spacer(), - // Search field - SizedBox( - width: widget.isMobile ? 140 : 220, - height: 34, - child: TextField( - decoration: InputDecoration( - hintText: 'Search table...', - hintStyle: const TextStyle(fontSize: 12), - prefixIcon: const Icon(Icons.search, size: 16), - contentPadding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 0, - ), - isDense: true, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: BorderSide(color: Colors.grey.shade300), - ), - ), - style: const TextStyle(fontSize: 12), - onChanged: (val) { - setState(() => _searchQuery = val); - }, - ), - ), - ], - ), - ), - - // Main table grid - using Scrollbar and virtualized ListView.builder for instant rendering - Expanded( - child: Container( - color: Colors.white, - child: Scrollbar( - controller: _horizontalController, - thumbVisibility: true, - child: SingleChildScrollView( - controller: _horizontalController, - scrollDirection: Axis.horizontal, - child: SizedBox( - width: totalTableWidth, - child: Column( - children: [ - // Fixed Column Header Row (A, B, C...) - Container( - height: 34, - decoration: BoxDecoration( - color: Colors.grey.shade200, - border: Border( - bottom: BorderSide( - color: Colors.grey.shade400, - width: 1, - ), - ), - ), - child: Row( - children: [ - // Row number corner cell - Container( - width: rowNumberWidth, - alignment: Alignment.center, - color: Colors.grey.shade300, - child: const Text( - '#', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 11, - color: AppColors.textSecondary, - ), - ), - ), - for (int c = 0; c < maxCols; c++) - Container( - width: cellWidth, - alignment: Alignment.center, - decoration: BoxDecoration( - border: Border( - right: BorderSide( - color: Colors.grey.shade300, - width: 1, - ), - ), - ), - child: Text( - _columnLetter(c), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 12, - color: AppColors.textPrimary, - ), - ), - ), - ], - ), - ), - - // Virtualized Data Rows - builds ONLY visible rows instantly - Expanded( - child: ListView.builder( - itemCount: filteredRows.length, - itemBuilder: (context, r) { - final rowCells = filteredRows[r]; - return Container( - height: 32, - decoration: BoxDecoration( - color: - r % 2 == 0 - ? Colors.white - : Colors.grey.shade50, - border: Border( - bottom: BorderSide( - color: Colors.grey.shade200, - width: 1, - ), - ), - ), - child: Row( - children: [ - // Left Row Number (1, 2, 3...) - Container( - width: rowNumberWidth, - alignment: Alignment.center, - color: Colors.grey.shade200, - child: Text( - '${r + 1}', - style: const TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: AppColors.textSecondary, - ), - ), - ), - // Cell Values - for (int c = 0; c < maxCols; c++) - Container( - width: cellWidth, - alignment: Alignment.centerLeft, - padding: const EdgeInsets.symmetric( - horizontal: 8, - ), - decoration: BoxDecoration( - border: Border( - right: BorderSide( - color: Colors.grey.shade200, - width: 1, - ), - ), - ), - child: Text( - c < rowCells.length ? rowCells[c] : '', - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 12, - color: AppColors.textPrimary, - ), - ), - ), - ], - ), - ); - }, - ), - ), - ], - ), - ), - ), - ), - ), - ), - - // Bottom sheets TabBar (if multiple tabs exist) - if (_sheetNames.isNotEmpty) - Container( - height: 44, - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - color: Colors.grey.shade100, - border: Border( - top: BorderSide(color: Colors.grey.shade300, width: 1), - ), - ), - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: _sheetNames.length, - separatorBuilder: (_, __) => const SizedBox(width: 8), - itemBuilder: (context, index) { - final name = _sheetNames[index]; - final isSelected = name == _activeSheetName; - return Center( - child: InkWell( - onTap: () { - setState(() => _activeSheetName = name); - }, - borderRadius: BorderRadius.circular(6), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 14, - vertical: 6, - ), - decoration: BoxDecoration( - color: - isSelected - ? Colors.green.shade700 - : Colors.transparent, - borderRadius: BorderRadius.circular(6), - border: Border.all( - color: - isSelected - ? Colors.green.shade700 - : Colors.grey.shade300, - ), - ), - child: Text( - name, - style: TextStyle( - fontSize: 12, - fontWeight: - isSelected - ? FontWeight.bold - : FontWeight.normal, - color: - isSelected - ? Colors.white - : AppColors.textPrimary, - ), - ), - ), - ), - ); - }, - ), - ), - ], + return Sheetifye.memory( + _fileBytes!, + readOnly: true, ); } } diff --git a/frontend/lib/ui/screens/students/students_screen.dart b/frontend/lib/ui/screens/students/students_screen.dart index 76e9b6f..84b194b 100644 --- a/frontend/lib/ui/screens/students/students_screen.dart +++ b/frontend/lib/ui/screens/students/students_screen.dart @@ -51,16 +51,15 @@ class _StudentsScreenState extends ConsumerState { void initState() { super.initState(); - // Sync initial search text if it was set externally (e.g. from Dashboard) - final initialQuery = ref.read(studentQueryProvider).search; - if (initialQuery.isNotEmpty) { - _searchController.text = initialQuery; - } - _searchController.addListener(_onSearchChanged); _searchFocusNode.addListener(_onSearchFocusChanged); WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; + // Sync initial search text if it was set externally (e.g. from Dashboard) + final initialQuery = ref.read(studentQueryProvider).search; + if (initialQuery.isNotEmpty) { + _searchController.text = initialQuery; + } if (ref.read(activeTabProvider) == 'Students') { _shortcutFocusNode.requestFocus(); } diff --git a/frontend/pubspec.lock b/frontend/pubspec.lock index c1d53fc..228807c 100644 --- a/frontend/pubspec.lock +++ b/frontend/pubspec.lock @@ -1,22 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: a49d6cf99e8d8e7a8e93668d09ced0bbdb954d0b4fccc2f5f9241c6b87fad95c - url: "https://pub.dev" - source: hosted - version: "99.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: "663efa951fb8a45e06f491223a604c93820598f20e6a99c25617a1576065e8b7" - url: "https://pub.dev" - source: hosted - version: "12.1.0" ansicolor: dependency: transitive description: @@ -129,14 +113,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.10" - cli_config: - dependency: transitive - description: - name: cli_config - sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec - url: "https://pub.dev" - source: hosted - version: "0.2.0" cli_util: dependency: transitive description: @@ -185,14 +161,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" - coverage: - dependency: transitive - description: - name: coverage - sha256: "956a3de0725ca232ad353565a8290d3357592bf4250f6f298a185e2d949c5d3d" - url: "https://pub.dev" - source: hosted - version: "1.15.1" cross_file: dependency: transitive description: @@ -450,10 +418,10 @@ packages: dependency: "direct main" description: name: flutter_riverpod - sha256: "9255e1e3ad6e38906a1b4f8287678f95f378744c5b46b1985588543f3f19046e" + sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" url: "https://pub.dev" source: hosted - version: "3.3.2" + version: "2.6.1" flutter_secure_storage: dependency: "direct main" description: @@ -520,14 +488,14 @@ packages: description: flutter source: sdk version: "0.0.0" - frontend_server_client: + freezed_annotation: dependency: transitive description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + name: freezed_annotation + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "2.4.4" get_it: dependency: transitive description: @@ -536,14 +504,6 @@ packages: url: "https://pub.dev" source: hosted version: "9.2.1" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" google_fonts: dependency: "direct main" description: @@ -584,14 +544,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.6.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" http_parser: dependency: transitive description: @@ -680,14 +632,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.20.3" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" jni: dependency: transitive description: @@ -816,14 +760,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.17.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" objective_c: dependency: transitive description: @@ -992,14 +928,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - pool: - dependency: transitive - description: - name: pool - sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.dev" - source: hosted - version: "1.5.2" printing: dependency: "direct main" description: @@ -1052,10 +980,18 @@ packages: dependency: transitive description: name: riverpod - sha256: "17100416c51db7810c71a7bb2c34d1f881faa0074fd452afb0c4db6f8f126c76" + sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" url: "https://pub.dev" source: hosted - version: "3.3.2" + version: "2.6.1" + riverpod_annotation: + dependency: transitive + description: + name: riverpod_annotation + sha256: e14b0bf45b71326654e2705d462f21b958f987087be850afd60578fcd502d1b8 + url: "https://pub.dev" + source: hosted + version: "2.6.1" screen_retriever: dependency: transitive description: @@ -1152,35 +1088,19 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.1" - shelf: - dependency: transitive + sheetifye: + dependency: "direct main" description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + name: sheetifye + sha256: "096537cc78c896b51c1427ab31296ebe59539b50b5f0fcd2db2a65be1d9e00d9" url: "https://pub.dev" source: hosted - version: "1.4.2" - shelf_packages_handler: + version: "1.1.0" + shimmer: dependency: transitive description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 - url: "https://pub.dev" - source: hosted - version: "1.1.3" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + name: shimmer + sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" url: "https://pub.dev" source: hosted version: "3.0.0" @@ -1205,22 +1125,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.1" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b - url: "https://pub.dev" - source: hosted - version: "2.1.2" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" - url: "https://pub.dev" - source: hosted - version: "0.10.13" source_span: dependency: transitive description: @@ -1341,14 +1245,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.2" - test: - dependency: transitive - description: - name: test - sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20" - url: "https://pub.dev" - source: hosted - version: "1.31.0" test_api: dependency: transitive description: @@ -1357,14 +1253,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.11" - test_core: - dependency: transitive - description: - name: test_core - sha256: "1991d4cfe85d5043241acac92962c3977c8d2f2add1ee73130c7b286417d1d34" - url: "https://pub.dev" - source: hosted - version: "0.6.17" timezone: dependency: transitive description: @@ -1493,14 +1381,6 @@ packages: url: "https://pub.dev" source: hosted version: "15.2.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" - url: "https://pub.dev" - source: hosted - version: "1.2.1" web: dependency: transitive description: @@ -1517,22 +1397,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" - url: "https://pub.dev" - source: hosted - version: "1.2.1" win32: dependency: transitive description: diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml index 5f35231..50a1edc 100644 --- a/frontend/pubspec.yaml +++ b/frontend/pubspec.yaml @@ -34,7 +34,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 - flutter_riverpod: ^3.3.1 + flutter_riverpod: ^2.6.1 dio: ^5.9.2 flutter_secure_storage: ^10.1.0 google_fonts: ^8.1.0 @@ -58,7 +58,8 @@ dependencies: wolt_modal_sheet: ^0.11.0 printing: ^5.14.3 pdf: ^3.12.0 - intl: ^0.20.3 + intl: ^0.19.0 + sheetifye: ^1.1.0 flutter_local_notifications: ^17.2.2 workmanager: ^0.9.0+3 desktop_drop: ^0.7.1 @@ -79,6 +80,10 @@ dev_dependencies: flutter_native_splash: ^2.4.4 cider: ^0.2.10 +dependency_overrides: + google_fonts: ^8.1.0 + intl: ^0.20.3 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec