diff --git a/analysis_options.yaml b/analysis_options.yaml index 0d29021..6bbdacf 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -9,6 +9,12 @@ # packages, and plugins designed to encourage good coding practices. include: package:flutter_lints/flutter.yaml +analyzer: + errors: + # Freezed uses @JsonKey on constructor parameters which triggers this warning + # but is the correct pattern for freezed classes + invalid_annotation_target: ignore + linter: # The lint rules applied to this project can be customized in the # section below to disable rules from the `package:flutter_lints/flutter.yaml` diff --git a/lib/app.dart b/lib/app.dart index 078b9f7..b7e5c93 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -12,7 +12,7 @@ class TatlockApp extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final router = ref.watch(appRouterProvider); - final themeAsync = ref.watch(themeNotifierProvider); + final themeAsync = ref.watch(themeProvider); // Get theme mode, defaulting to system while loading final themeMode = switch (themeAsync) { diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index aeda315..43a2168 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -7,7 +7,7 @@ part 'api_client.g.dart'; /// Provides the Dio instance for Core API. @riverpod -Dio coreApiClient(CoreApiClientRef ref) { +Dio coreApiClient(Ref ref) { final dio = Dio( BaseOptions( baseUrl: AppConfig.coreApiUrl, @@ -31,7 +31,7 @@ Dio coreApiClient(CoreApiClientRef ref) { /// Provides the Dio instance for Tatlock API. @riverpod -Dio tatlockApiClient(TatlockApiClientRef ref) { +Dio tatlockApiClient(Ref ref) { final dio = Dio( BaseOptions( baseUrl: AppConfig.tatlockApiUrl, diff --git a/lib/core/api/api_interceptors.dart b/lib/core/api/api_interceptors.dart index 808f0cb..e7805b9 100644 --- a/lib/core/api/api_interceptors.dart +++ b/lib/core/api/api_interceptors.dart @@ -22,7 +22,7 @@ class AuthInterceptor extends Interceptor { return; } - final authState = _ref.read(authNotifierProvider); + final authState = _ref.read(authProvider); authState.whenData((auth) { if (auth.isAuthenticated && auth.accessToken != null) { @@ -43,7 +43,7 @@ class AuthInterceptor extends Interceptor { if (err.response?.statusCode == 401) { // Token expired - trigger re-authentication - _ref.read(authNotifierProvider.notifier).signOut(); + _ref.read(authProvider.notifier).signOut(); } handler.next(err); } diff --git a/lib/core/auth/auth_state.dart b/lib/core/auth/auth_state.dart index 900ad51..26f8086 100644 --- a/lib/core/auth/auth_state.dart +++ b/lib/core/auth/auth_state.dart @@ -4,7 +4,7 @@ part 'auth_state.freezed.dart'; /// Authentication state. @freezed -class AuthState with _$AuthState { +sealed class AuthState with _$AuthState { const factory AuthState({ @Default(false) bool isAuthenticated, String? accessToken, diff --git a/lib/features/control_room/containers/data/datasources/containers_datasource.dart b/lib/features/control_room/containers/data/datasources/containers_datasource.dart index 7b82f91..c894e75 100644 --- a/lib/features/control_room/containers/data/datasources/containers_datasource.dart +++ b/lib/features/control_room/containers/data/datasources/containers_datasource.dart @@ -1,5 +1,4 @@ import 'package:dio/dio.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:tatlock_ui/core/api/api_client.dart'; import 'package:tatlock_ui/features/control_room/containers/data/models/container_model.dart'; diff --git a/lib/features/control_room/containers/data/models/container_model.dart b/lib/features/control_room/containers/data/models/container_model.dart index 26ebc03..3eec3f5 100644 --- a/lib/features/control_room/containers/data/models/container_model.dart +++ b/lib/features/control_room/containers/data/models/container_model.dart @@ -6,7 +6,7 @@ part 'container_model.g.dart'; /// Container data model for API serialization. @freezed -class ContainerModel with _$ContainerModel { +sealed class ContainerModel with _$ContainerModel { const factory ContainerModel({ @JsonKey(name: 'Id') required String id, @JsonKey(name: 'Names') required List names, @@ -68,7 +68,7 @@ class ContainerModel with _$ContainerModel { /// Port mapping model. @freezed -class PortModel with _$PortModel { +sealed class PortModel with _$PortModel { const factory PortModel({ @JsonKey(name: 'IP') String? ip, @JsonKey(name: 'PrivatePort') required int privatePort, @@ -93,7 +93,7 @@ class PortModel with _$PortModel { /// Mount model. @freezed -class MountModel with _$MountModel { +sealed class MountModel with _$MountModel { const factory MountModel({ @JsonKey(name: 'Type') required String type, @JsonKey(name: 'Source') required String source, @@ -119,7 +119,7 @@ class MountModel with _$MountModel { /// Network settings model. @freezed -class NetworkSettingsModel with _$NetworkSettingsModel { +sealed class NetworkSettingsModel with _$NetworkSettingsModel { const factory NetworkSettingsModel({ @JsonKey(name: 'Networks') @Default({}) Map networks, }) = _NetworkSettingsModel; diff --git a/lib/features/control_room/containers/data/repositories/container_repository_impl.dart b/lib/features/control_room/containers/data/repositories/container_repository_impl.dart index da6ef36..451553c 100644 --- a/lib/features/control_room/containers/data/repositories/container_repository_impl.dart +++ b/lib/features/control_room/containers/data/repositories/container_repository_impl.dart @@ -77,7 +77,7 @@ class ContainerRepositoryImpl implements ContainerRepository { /// Provides the container repository. @riverpod -ContainerRepository containerRepository(ContainerRepositoryRef ref) { +ContainerRepository containerRepository(Ref ref) { final datasource = ref.watch(containersDatasourceProvider); return ContainerRepositoryImpl(datasource); } diff --git a/lib/features/control_room/containers/domain/entities/container.dart b/lib/features/control_room/containers/domain/entities/container.dart index fb9b9aa..aa7c936 100644 --- a/lib/features/control_room/containers/domain/entities/container.dart +++ b/lib/features/control_room/containers/domain/entities/container.dart @@ -4,7 +4,7 @@ part 'container.freezed.dart'; /// Docker container entity. @freezed -class Container with _$Container { +sealed class Container with _$Container { const factory Container({ /// Container ID (short form). required String id, @@ -122,7 +122,7 @@ enum ContainerState { /// Port mapping configuration. @freezed -class PortMapping with _$PortMapping { +sealed class PortMapping with _$PortMapping { const factory PortMapping({ /// Host IP (usually 0.0.0.0). String? hostIp, @@ -149,7 +149,7 @@ class PortMapping with _$PortMapping { /// Volume mount configuration. @freezed -class VolumeMount with _$VolumeMount { +sealed class VolumeMount with _$VolumeMount { const factory VolumeMount({ /// Mount type (bind, volume, tmpfs). required String type, diff --git a/lib/features/control_room/containers/presentation/providers/containers_provider.dart b/lib/features/control_room/containers/presentation/providers/containers_provider.dart index 9163f95..cf78fe3 100644 --- a/lib/features/control_room/containers/presentation/providers/containers_provider.dart +++ b/lib/features/control_room/containers/presentation/providers/containers_provider.dart @@ -7,14 +7,14 @@ part 'containers_provider.g.dart'; /// Provides all containers. @riverpod -Future> allContainers(AllContainersRef ref) async { +Future> allContainers(Ref ref) async { final repository = ref.watch(containerRepositoryProvider); return repository.getContainers(); } /// Provides containers filtered by the selected stack. @riverpod -Future> containers(ContainersRef ref) async { +Future> containers(Ref ref) async { final repository = ref.watch(containerRepositoryProvider); final selectedStack = ref.watch(selectedStackProvider); @@ -27,7 +27,7 @@ Future> containers(ContainersRef ref) async { /// Provides a single container by ID. @riverpod -Future container(ContainerRef ref, String id) async { +Future container(Ref ref, String id) async { final repository = ref.watch(containerRepositoryProvider); return repository.getContainer(id); } @@ -82,7 +82,7 @@ class ContainerActions extends _$ContainerActions { /// Container logs provider. @riverpod Future containerLogs( - ContainerLogsRef ref, + Ref ref, String id, { int? tail = 100, }) async { diff --git a/lib/features/control_room/containers/presentation/widgets/container_logs_viewer.dart b/lib/features/control_room/containers/presentation/widgets/container_logs_viewer.dart index 80ce75d..678c15b 100644 --- a/lib/features/control_room/containers/presentation/widgets/container_logs_viewer.dart +++ b/lib/features/control_room/containers/presentation/widgets/container_logs_viewer.dart @@ -22,7 +22,6 @@ class ContainerLogsViewer extends ConsumerStatefulWidget { class _ContainerLogsViewerState extends ConsumerState { final _scrollController = ScrollController(); int _tailLines = 100; - bool _autoScroll = true; @override void dispose() { diff --git a/lib/features/control_room/npm/data/datasources/proxy_hosts_datasource.dart b/lib/features/control_room/npm/data/datasources/proxy_hosts_datasource.dart index 314053d..dec0e7c 100644 --- a/lib/features/control_room/npm/data/datasources/proxy_hosts_datasource.dart +++ b/lib/features/control_room/npm/data/datasources/proxy_hosts_datasource.dart @@ -1,5 +1,4 @@ import 'package:dio/dio.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:tatlock_ui/core/api/api_client.dart'; import 'package:tatlock_ui/features/control_room/npm/data/models/proxy_host_model.dart'; diff --git a/lib/features/control_room/npm/data/models/proxy_host_model.dart b/lib/features/control_room/npm/data/models/proxy_host_model.dart index 0abf1ea..a2c8f86 100644 --- a/lib/features/control_room/npm/data/models/proxy_host_model.dart +++ b/lib/features/control_room/npm/data/models/proxy_host_model.dart @@ -43,7 +43,7 @@ class IntOrBoolConverter implements JsonConverter { /// /// Maps to the NPM API response format via Core API. @freezed -class ProxyHostModel with _$ProxyHostModel { +sealed class ProxyHostModel with _$ProxyHostModel { const factory ProxyHostModel({ required int id, @JsonKey(name: 'domain_names') required List domainNames, @@ -96,7 +96,7 @@ class ProxyHostModel with _$ProxyHostModel { /// Proxy location model. @freezed -class ProxyLocationModel with _$ProxyLocationModel { +sealed class ProxyLocationModel with _$ProxyLocationModel { const factory ProxyLocationModel({ required String path, @JsonKey(name: 'forward_scheme') required String forwardScheme, @@ -123,7 +123,7 @@ class ProxyLocationModel with _$ProxyLocationModel { /// /// This is a simpler model used for listing domains. @freezed -class DomainInfoModel with _$DomainInfoModel { +sealed class DomainInfoModel with _$DomainInfoModel { const factory DomainInfoModel({ required String domain, required String service, diff --git a/lib/features/control_room/npm/domain/entities/proxy_host.dart b/lib/features/control_room/npm/domain/entities/proxy_host.dart index 8147f38..23851c0 100644 --- a/lib/features/control_room/npm/domain/entities/proxy_host.dart +++ b/lib/features/control_room/npm/domain/entities/proxy_host.dart @@ -4,7 +4,7 @@ part 'proxy_host.freezed.dart'; /// NPM proxy host entity representing a domain configuration. @freezed -class ProxyHost with _$ProxyHost { +sealed class ProxyHost with _$ProxyHost { const factory ProxyHost({ /// Proxy host ID. required int id, @@ -76,7 +76,7 @@ class ProxyHost with _$ProxyHost { /// Proxy location for advanced routing. @freezed -class ProxyLocation with _$ProxyLocation { +sealed class ProxyLocation with _$ProxyLocation { const factory ProxyLocation({ /// Location path. required String path, diff --git a/lib/features/control_room/npm/presentation/pages/proxy_host_page.dart b/lib/features/control_room/npm/presentation/pages/proxy_host_page.dart index fa19457..94329ec 100644 --- a/lib/features/control_room/npm/presentation/pages/proxy_host_page.dart +++ b/lib/features/control_room/npm/presentation/pages/proxy_host_page.dart @@ -101,7 +101,7 @@ class _ProxyHostPageState extends ConsumerState child: EntityAsyncContent( isLoading: proxyHostAsync.isLoading, error: proxyHostAsync.error, - data: proxyHostAsync.valueOrNull, + data: proxyHostAsync.value, onRetry: () => ref.invalidate(proxyHostProvider(widget.proxyHostId!)), builder: (proxyHost) { if (isEditing) { @@ -275,7 +275,7 @@ class _ProxyHostView extends StatelessWidget { shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: proxyHost.locations.length, - separatorBuilder: (_, __) => const Divider(height: 1), + separatorBuilder: (_, index) => const Divider(height: 1), itemBuilder: (context, index) { final loc = proxyHost.locations[index]; return ListTile( diff --git a/lib/features/control_room/npm/presentation/providers/proxy_hosts_provider.dart b/lib/features/control_room/npm/presentation/providers/proxy_hosts_provider.dart index 6db875a..2c234f0 100644 --- a/lib/features/control_room/npm/presentation/providers/proxy_hosts_provider.dart +++ b/lib/features/control_room/npm/presentation/providers/proxy_hosts_provider.dart @@ -1,4 +1,3 @@ -import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:tatlock_ui/features/control_room/npm/data/datasources/proxy_hosts_datasource.dart'; import 'package:tatlock_ui/features/control_room/npm/data/models/proxy_host_model.dart'; diff --git a/lib/features/control_room/stacks/data/datasources/stacks_datasource.dart b/lib/features/control_room/stacks/data/datasources/stacks_datasource.dart index 6cdeb69..a099a0b 100644 --- a/lib/features/control_room/stacks/data/datasources/stacks_datasource.dart +++ b/lib/features/control_room/stacks/data/datasources/stacks_datasource.dart @@ -125,7 +125,7 @@ class StacksDatasource { /// Provides the stacks datasource. @riverpod -StacksDatasource stacksDatasource(StacksDatasourceRef ref) { +StacksDatasource stacksDatasource(Ref ref) { final dio = ref.watch(coreApiClientProvider); final containersDatasource = ref.watch(containersDatasourceProvider); return StacksDatasource(dio, containersDatasource); diff --git a/lib/features/control_room/stacks/data/models/stack_model.dart b/lib/features/control_room/stacks/data/models/stack_model.dart index 90b543d..e9ad33b 100644 --- a/lib/features/control_room/stacks/data/models/stack_model.dart +++ b/lib/features/control_room/stacks/data/models/stack_model.dart @@ -6,7 +6,7 @@ part 'stack_model.g.dart'; /// Stack data model for API serialization. @freezed -class StackModel with _$StackModel { +sealed class StackModel with _$StackModel { const factory StackModel({ required String id, required String name, diff --git a/lib/features/control_room/stacks/data/repositories/stack_repository_impl.dart b/lib/features/control_room/stacks/data/repositories/stack_repository_impl.dart index d232c9a..632247d 100644 --- a/lib/features/control_room/stacks/data/repositories/stack_repository_impl.dart +++ b/lib/features/control_room/stacks/data/repositories/stack_repository_impl.dart @@ -75,7 +75,7 @@ class StackRepositoryImpl implements StackRepository { /// Provides the stack repository. @riverpod -StackRepository stackRepository(StackRepositoryRef ref) { +StackRepository stackRepository(Ref ref) { final datasource = ref.watch(stacksDatasourceProvider); return StackRepositoryImpl(datasource); } diff --git a/lib/features/control_room/stacks/domain/entities/stack.dart b/lib/features/control_room/stacks/domain/entities/stack.dart index 7f7d4e4..55fe4c1 100644 --- a/lib/features/control_room/stacks/domain/entities/stack.dart +++ b/lib/features/control_room/stacks/domain/entities/stack.dart @@ -4,7 +4,7 @@ part 'stack.freezed.dart'; /// Container orchestration stack (Docker Compose stack). @freezed -class Stack with _$Stack { +sealed class Stack with _$Stack { const factory Stack({ /// Unique stack identifier. required String id, diff --git a/lib/features/control_room/stacks/presentation/providers/stacks_provider.dart b/lib/features/control_room/stacks/presentation/providers/stacks_provider.dart index 00d255f..83d4310 100644 --- a/lib/features/control_room/stacks/presentation/providers/stacks_provider.dart +++ b/lib/features/control_room/stacks/presentation/providers/stacks_provider.dart @@ -6,14 +6,14 @@ part 'stacks_provider.g.dart'; /// Provides the list of all stacks. @riverpod -Future> stacks(StacksRef ref) async { +Future> stacks(Ref ref) async { final repository = ref.watch(stackRepositoryProvider); return repository.getStacks(); } /// Provides a single stack by ID. @riverpod -Future stack(StackRef ref, String id) async { +Future stack(Ref ref, String id) async { final repository = ref.watch(stackRepositoryProvider); return repository.getStack(id); } @@ -35,14 +35,14 @@ class SelectedStack extends _$SelectedStack { /// Provides the YAML content for a stack. @riverpod -Future stackYaml(StackYamlRef ref, String stackId) async { +Future stackYaml(Ref ref, String stackId) async { final repository = ref.watch(stackRepositoryProvider); return repository.getStackYaml(stackId); } /// Provides the environment variables for a stack. @riverpod -Future> stackEnvVars(StackEnvVarsRef ref, String stackId) async { +Future> stackEnvVars(Ref ref, String stackId) async { final repository = ref.watch(stackRepositoryProvider); return repository.getStackEnvVars(stackId); } diff --git a/lib/features/security/groups/groups_list_page.dart b/lib/features/security/groups/groups_list_page.dart index af0a9cd..94bc574 100644 --- a/lib/features/security/groups/groups_list_page.dart +++ b/lib/features/security/groups/groups_list_page.dart @@ -40,6 +40,7 @@ class GroupsListPage extends ConsumerStatefulWidget { class _GroupsListPageState extends ConsumerState { late final StateNotifierProvider, DataGridState> _gridProvider; + bool _isSyncing = false; @override void initState() { @@ -59,6 +60,38 @@ class _GroupsListPageState extends ConsumerState { ); } + Future _syncFromAuthentik() async { + if (_isSyncing) return; + setState(() => _isSyncing = true); + + try { + final dio = ref.read(coreApiClientProvider); + await dio.post('/auth/groups/sync-from-authentik'); + + if (!mounted) return; + ref.read(_gridProvider.notifier).refresh(); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('Groups synced from Authentik'), + behavior: SnackBarBehavior.floating, + duration: const Duration(seconds: 2), + ), + ); + } catch (e) { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Sync failed: $e'), + behavior: SnackBarBehavior.floating, + duration: const Duration(seconds: 4), + ), + ); + } finally { + if (mounted) setState(() => _isSyncing = false); + } + } + DataGridConfig _buildConfig() { return DataGridConfig( columns: [ @@ -106,6 +139,18 @@ class _GroupsListPageState extends ConsumerState { tooltip: 'Refresh', onPressed: () => ref.read(_gridProvider.notifier).refresh(), ), + const SizedBox(width: 8), + FilledButton.icon( + onPressed: _isSyncing ? null : _syncFromAuthentik, + icon: _isSyncing + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : const Icon(Icons.sync), + label: const Text('Sync from Authentik'), + ), ], ); } diff --git a/lib/features/security/users/users_list_page.dart b/lib/features/security/users/users_list_page.dart index 5e531cc..6d54078 100644 --- a/lib/features/security/users/users_list_page.dart +++ b/lib/features/security/users/users_list_page.dart @@ -70,6 +70,7 @@ class UsersListPage extends ConsumerStatefulWidget { class _UsersListPageState extends ConsumerState { late final StateNotifierProvider, DataGridState> _gridProvider; + bool _isSyncing = false; @override void initState() { @@ -88,6 +89,38 @@ class _UsersListPageState extends ConsumerState { ); } + Future _syncFromAuthentik() async { + if (_isSyncing) return; + setState(() => _isSyncing = true); + + try { + final dio = ref.read(coreApiClientProvider); + await dio.post('/auth/users/sync-from-authentik'); + + if (!mounted) return; + ref.read(_gridProvider.notifier).refresh(); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('Users synced from Authentik'), + behavior: SnackBarBehavior.floating, + duration: const Duration(seconds: 2), + ), + ); + } catch (e) { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Sync failed: $e'), + behavior: SnackBarBehavior.floating, + duration: const Duration(seconds: 4), + ), + ); + } finally { + if (mounted) setState(() => _isSyncing = false); + } + } + DataGridConfig _buildConfig() { return DataGridConfig( columns: [ @@ -131,6 +164,18 @@ class _UsersListPageState extends ConsumerState { tooltip: 'Refresh', onPressed: () => ref.read(_gridProvider.notifier).refresh(), ), + const SizedBox(width: 8), + FilledButton.icon( + onPressed: _isSyncing ? null : _syncFromAuthentik, + icon: _isSyncing + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : const Icon(Icons.sync), + label: const Text('Sync from Authentik'), + ), ], ); } diff --git a/lib/routing/app_router.dart b/lib/routing/app_router.dart index 19f0119..154562f 100644 --- a/lib/routing/app_router.dart +++ b/lib/routing/app_router.dart @@ -17,7 +17,7 @@ abstract class AppRoutes { /// Provides the GoRouter instance. @riverpod -GoRouter appRouter(AppRouterRef ref) { +GoRouter appRouter(Ref ref) { return GoRouter( initialLocation: AppRoutes.frontHall, debugLogDiagnostics: true, diff --git a/lib/shared/components/data_grid/data_grid.dart b/lib/shared/components/data_grid/data_grid.dart index 5b6795c..568beca 100644 --- a/lib/shared/components/data_grid/data_grid.dart +++ b/lib/shared/components/data_grid/data_grid.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_riverpod/legacy.dart'; import 'data_grid_config.dart'; import 'data_grid_provider.dart'; -import 'data_grid_source.dart'; import 'data_grid_state.dart'; import 'widgets/data_grid_bulk_actions.dart'; import 'widgets/data_grid_empty_state.dart'; diff --git a/lib/shared/components/data_grid/data_grid_exports.dart b/lib/shared/components/data_grid/data_grid_exports.dart index 93c9455..fbcd5bc 100644 --- a/lib/shared/components/data_grid/data_grid_exports.dart +++ b/lib/shared/components/data_grid/data_grid_exports.dart @@ -75,6 +75,9 @@ /// ``` library; +export 'package:flutter_riverpod/legacy.dart' + show StateNotifierProvider, StateNotifier; + export 'data_grid.dart'; export 'data_grid_action.dart'; export 'data_grid_column.dart'; diff --git a/lib/shared/components/data_grid/data_grid_provider.dart b/lib/shared/components/data_grid/data_grid_provider.dart index 3a60db8..76b6caa 100644 --- a/lib/shared/components/data_grid/data_grid_provider.dart +++ b/lib/shared/components/data_grid/data_grid_provider.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_riverpod/legacy.dart'; import 'data_grid_config.dart'; import 'data_grid_source.dart'; diff --git a/lib/shared/components/data_grid/data_grid_state.dart b/lib/shared/components/data_grid/data_grid_state.dart index e05c1f7..38688e5 100644 --- a/lib/shared/components/data_grid/data_grid_state.dart +++ b/lib/shared/components/data_grid/data_grid_state.dart @@ -4,7 +4,7 @@ part 'data_grid_state.freezed.dart'; /// State for a DataGrid instance. @freezed -class DataGridState with _$DataGridState { +sealed class DataGridState with _$DataGridState { const factory DataGridState({ /// Current items being displayed. @Default([]) List items, diff --git a/lib/shared/layouts/widgets/profile_dropdown.dart b/lib/shared/layouts/widgets/profile_dropdown.dart index e92bec6..dd734c2 100644 --- a/lib/shared/layouts/widgets/profile_dropdown.dart +++ b/lib/shared/layouts/widgets/profile_dropdown.dart @@ -12,7 +12,7 @@ class ProfileDropdown extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final authState = ref.watch(authNotifierProvider); + final authState = ref.watch(authProvider); final colorScheme = Theme.of(context).colorScheme; return authState.when( @@ -94,7 +94,7 @@ class ProfileDropdown extends ConsumerWidget { case 'settings': context.go(AppRoutes.settings); case 'logout': - ref.read(authNotifierProvider.notifier).signOut(); + ref.read(authProvider.notifier).signOut(); } }, ), @@ -106,7 +106,7 @@ class ProfileDropdown extends ConsumerWidget { child: CircularProgressIndicator(strokeWidth: 2), ), ), - error: (_, __) => CircleAvatar( + error: (err, stack) => CircleAvatar( radius: 18, backgroundColor: colorScheme.errorContainer, child: Icon( diff --git a/lib/shared/layouts/widgets/top_header_bar.dart b/lib/shared/layouts/widgets/top_header_bar.dart index e5f6530..ab8ca0b 100644 --- a/lib/shared/layouts/widgets/top_header_bar.dart +++ b/lib/shared/layouts/widgets/top_header_bar.dart @@ -81,7 +81,7 @@ class TopHeaderBar extends StatelessWidget { 'assets/icons/logo.png', height: _logoSize, width: _logoSize, - errorBuilder: (_, __, ___) => Icon( + errorBuilder: (context, error, stack) => Icon( Icons.layers, size: 32, color: colorScheme.primary, diff --git a/pubspec.yaml b/pubspec.yaml index adfed5f..c2e95b0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,20 +32,20 @@ dependencies: sdk: flutter # State Management - flutter_riverpod: ^2.6.1 - riverpod_annotation: ^2.6.1 - hooks_riverpod: ^2.6.1 - flutter_hooks: ^0.20.5 + flutter_riverpod: ^3.0.0 + riverpod_annotation: ^4.0.0 + hooks_riverpod: ^3.0.0 + flutter_hooks: ^0.21.0 # Code Generation Support - freezed_annotation: ^2.4.4 + freezed_annotation: ^3.1.0 json_annotation: ^4.9.0 # Networking dio: ^5.7.0 # Routing - go_router: ^14.6.2 + go_router: ^17.0.1 # Storage shared_preferences: ^2.3.3 @@ -54,7 +54,7 @@ dependencies: flex_color_scheme: ^8.1.0 flutter_adaptive_scaffold: ^0.3.1 flutter_markdown: ^0.7.4 - fl_chart: ^0.69.2 + fl_chart: ^1.1.1 # Icons cupertino_icons: ^1.0.8 @@ -70,19 +70,19 @@ dev_dependencies: sdk: flutter # Linting - flutter_lints: ^5.0.0 + flutter_lints: ^6.0.0 # Code Generation build_runner: ^2.4.13 - freezed: ^2.5.7 + freezed: ^3.2.3 json_serializable: ^6.8.0 - riverpod_generator: ^2.6.3 + riverpod_generator: ^4.0.0 # Testing mocktail: ^1.0.4 # Build tools - build: ^2.4.0 + build: ^4.0.3 yaml: ^3.1.0 # For information on the generic Dart part of this file, see the