Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 51 additions & 49 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,33 @@ void main() async {
} catch (e) {
debugPrint('Error initializing services: $e');
}

final themeController = await ThemeController.create();

runApp(
WidgetsBindingObserverWidget(
child: ChangeNotifierProvider<ThemeController>.value(
value: themeController,
child: const MyApp(),
runApp(
WidgetsBindingObserverWidget(
child: ChangeNotifierProvider<ThemeController>.value(
value: themeController,
child: const MyApp(),
),
),
),
);

);
} // ✅ THIS WAS MISSING

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
final themeController = context.watch<ThemeController>();

return MaterialApp(
title: 'Ell-ena',
debugShowCheckedModeBanner: false,
navigatorKey: NavigationService().navigatorKey,
navigatorObservers: <NavigatorObserver>[AppRouteObserver.instance],
navigatorObservers: <NavigatorObserver>[
AppRouteObserver.instance
],
theme: lightTheme,
darkTheme: darkTheme,
themeMode: themeController.flutterThemeMode,
Expand All @@ -53,19 +56,19 @@ class MyApp extends StatelessWidget {
settings: settings,
);
} else if (settings.name == '/home') {
final args = (settings.arguments is Map<String, dynamic>)
? settings.arguments as Map<String, dynamic>
final args = (settings.arguments is Map<String, dynamic>)
? settings.arguments as Map<String, dynamic>
: null;

return MaterialPageRoute(
builder: (context) => HomeScreen(arguments: args),
settings: settings,
);
} else if (settings.name == '/chat') {
final args = (settings.arguments is Map<String, dynamic>)
? settings.arguments as Map<String, dynamic>
final args = (settings.arguments is Map<String, dynamic>)
? settings.arguments as Map<String, dynamic>
: null;

return MaterialPageRoute(
builder: (context) => ChatScreen(arguments: args),
settings: settings,
Expand All @@ -78,49 +81,48 @@ class MyApp extends StatelessWidget {
}

class WidgetsBindingObserverWidget extends StatefulWidget {
final Widget child;
final Widget child;

const WidgetsBindingObserverWidget({
super.key,
required this.child,
});
const WidgetsBindingObserverWidget({
super.key,
required this.child,
});

@override
State<WidgetsBindingObserverWidget> createState() =>
_WidgetsBindingObserverWidgetState();
}
@override
State<WidgetsBindingObserverWidget> createState() =>
_WidgetsBindingObserverWidgetState();
}

class _WidgetsBindingObserverWidgetState
extends State<WidgetsBindingObserverWidget>
with WidgetsBindingObserver {
class _WidgetsBindingObserverWidgetState
extends State<WidgetsBindingObserverWidget>
with WidgetsBindingObserver {

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
SupabaseService().dispose(); // ✅ ONLY IMPORTANT LINE
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
SupabaseService().dispose();
}
}
Comment on lines +107 to +111
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if SupabaseService uses singleton pattern
ast-grep --pattern 'class SupabaseService {
  $$$
}'

# Also check for factory constructor or static instance
rg -n "static.*SupabaseService|factory SupabaseService|_instance" lib/services/supabase_service.dart -A2

Repository: AOSSIE-Org/Ell-ena

Length of output: 282


SupabaseService is a singleton; however, consider handling additional lifecycle states for platform compatibility.

The AppLifecycleState.detached state is not reliably fired on all platforms (especially iOS). For critical resource cleanup like database connections, consider also handling paused or inactive states to ensure proper cleanup across different platforms, or implement a more robust cleanup strategy.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/main.dart` around lines 107 - 111, didChangeAppLifecycleState currently
only disposes SupabaseService() on AppLifecycleState.detached, which can miss
events on some platforms; update didChangeAppLifecycleState in the widget
implementing WidgetsBindingObserver to also call SupabaseService().dispose() for
AppLifecycleState.paused and AppLifecycleState.inactive (or move cleanup to the
widget's dispose() to ensure deterministic teardown), and ensure
SupabaseService.dispose() is idempotent/safe to call multiple times so repeated
lifecycle triggers won't cause errors.


@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}

@override
Widget build(BuildContext context) {
return widget.child;
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}

// Simple singleton RouteObserver to allow screens to refresh on focus
class AppRouteObserver extends RouteObserver<ModalRoute<void>> {
AppRouteObserver._();
static final AppRouteObserver instance = AppRouteObserver._();
}
}
2 changes: 1 addition & 1 deletion lib/screens/auth/team_selection_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ class _OptionCard extends StatelessWidget {
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: isSelected
? Colors.green.withOpacity(0.2)
? Colors.green.withValues(alpha:0.2)
: Theme.of(context).colorScheme.surfaceContainerLow,
border: Border.all(
color: isSelected
Expand Down
22 changes: 7 additions & 15 deletions lib/screens/calendar/calendar_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class _CalendarScreenState extends State<CalendarScreen> {
Future<void> _loadEventsFromNetwork() async {
try {
// Load tasks, tickets, and meetings in parallel
final results = await Future.wait([
await Future.wait([
_loadTasks(),
_loadTickets(),
_loadMeetings(),
Expand Down Expand Up @@ -398,7 +398,7 @@ class _CalendarScreenState extends State<CalendarScreen> {
height: 16,
width: events.length > 3 ? 35 : (events.length * 8 + 10),
decoration: BoxDecoration(
color: Colors.green.withOpacity(markerOpacity),
color: Colors.green.withValues(alpha:markerOpacity),
borderRadius: BorderRadius.circular(10),
),
child: Center(
Expand All @@ -421,13 +421,13 @@ class _CalendarScreenState extends State<CalendarScreen> {
selectedTextStyle: TextStyle(color: colorScheme.onPrimary),
todayTextStyle: TextStyle(color: colorScheme.onSurface),
outsideTextStyle:
TextStyle(color: colorScheme.onSurface.withOpacity(0.38)),
TextStyle(color: colorScheme.onSurface.withValues(alpha:0.38)),
selectedDecoration: const BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
),
todayDecoration: BoxDecoration(
color: Colors.green.withOpacity(0.8),
color: Colors.green.withValues(alpha:0.8),
shape: BoxShape.circle,
),
markersMaxCount: 0,
Expand Down Expand Up @@ -484,7 +484,7 @@ class _CalendarScreenState extends State<CalendarScreen> {
SizedBox(
width: 50,
child: Text(
'${time.format(context).toLowerCase()}',
time.format(context).toLowerCase(),
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
fontSize: 12),
Expand Down Expand Up @@ -533,7 +533,7 @@ class _CalendarScreenState extends State<CalendarScreen> {
margin: const EdgeInsets.only(top: 4),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: event.type.color.withOpacity(0.2),
color: event.type.color.withValues(alpha:0.2),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: event.type.color, width: 1),
),
Expand Down Expand Up @@ -670,7 +670,7 @@ class _CalendarScreenState extends State<CalendarScreen> {
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
color: color.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: Row(
Expand All @@ -696,14 +696,6 @@ class _CalendarScreenState extends State<CalendarScreen> {

if (_selectedDay == null) return;

final selectedDateTime = DateTime(
_selectedDay!.year,
_selectedDay!.month,
_selectedDay!.day,
selectedTime.hour,
selectedTime.minute,
);

dynamic result;

switch (type) {
Expand Down
Loading