1+ import 'package:get/get.dart' ;
2+ import 'package:flutter/material.dart' ;
3+ import 'dart:async' ;
4+ import '../../../data/providers/isar_provider.dart' ;
5+ import '../../../modules/settings/controllers/theme_controller.dart' ;
6+ import '../../../utils/utils.dart' ;
7+ import '../../../utils/constants.dart' ;
8+ import '../../../data/models/debug_model.dart' ;
9+
10+ class DebugController extends GetxController {
11+ final ThemeController themeController = Get .find <ThemeController >();
12+ final TextEditingController searchController = TextEditingController ();
13+
14+ var logs = < Map <String , dynamic >> [].obs;
15+ var filteredLogs = < Map <String , dynamic >> [].obs;
16+ var selectedLogLevel = Rxn <LogLevel >();
17+ var startDate = Rxn <DateTime >();
18+ var endDate = Rxn <DateTime >();
19+
20+ Timer ? _timer;
21+
22+ @override
23+ void onInit () {
24+ super .onInit ();
25+ fetchLogs ();
26+ _timer = Timer .periodic (const Duration (seconds: 5 ), (timer) {
27+ fetchLogs ();
28+ });
29+ }
30+
31+ @override
32+ void onClose () {
33+ _timer? .cancel ();
34+ searchController.dispose ();
35+ super .onClose ();
36+ }
37+
38+ Future <void > fetchLogs () async {
39+ try {
40+ final fetchedLogs = await IsarDb ().getLogs ();
41+ logs.value = fetchedLogs.reversed.toList ();
42+ applyFilters ();
43+ debugPrint ('Debug screen: Successfully loaded ${fetchedLogs .length } logs' );
44+ } catch (e) {
45+ debugPrint ('Debug screen: Error loading logs: $e ' );
46+ Get .snackbar (
47+ 'Error' ,
48+ 'Error loading logs: $e ' ,
49+ backgroundColor: Colors .red,
50+ colorText: Colors .white,
51+ );
52+ }
53+ }
54+
55+ void applyFilters () {
56+ filteredLogs.value = logs.where ((log) {
57+ bool matchesSearch = searchController.text.isEmpty ||
58+ log['Status' ].toString ().toLowerCase ().contains (searchController.text.toLowerCase ()) ||
59+ log['LogID' ].toString ().contains (searchController.text) ||
60+ Utils .getFormattedDate (DateTime .fromMillisecondsSinceEpoch (log['LogTime' ]))
61+ .toLowerCase ()
62+ .contains (searchController.text.toLowerCase ());
63+
64+ bool matchesLevel = selectedLogLevel.value == null ;
65+ if (selectedLogLevel.value != null ) {
66+ final status = log['Status' ].toString ().toLowerCase ();
67+ debugPrint ('Checking log: "$status " for level: ${selectedLogLevel .value }' );
68+
69+ switch (selectedLogLevel.value! ) {
70+ case LogLevel .error:
71+ matchesLevel = status.contains ('error' );
72+ break ;
73+ case LogLevel .warning:
74+ matchesLevel = status.contains ('warning' );
75+ break ;
76+ case LogLevel .info:
77+ matchesLevel = ! status.contains ('error' ) && ! status.contains ('warning' );
78+ break ;
79+ }
80+ debugPrint ('Matches level: $matchesLevel ' );
81+ }
82+
83+ bool matchesDateRange = true ;
84+ if (startDate.value != null && endDate.value != null ) {
85+ final logTime = DateTime .fromMillisecondsSinceEpoch (log['LogTime' ]);
86+ final startOfDay = DateTime (startDate.value! .year, startDate.value! .month, startDate.value! .day);
87+ final endOfDay = DateTime (endDate.value! .year, endDate.value! .month, endDate.value! .day, 23 , 59 , 59 );
88+ matchesDateRange = logTime.isAfter (startOfDay) && logTime.isBefore (endOfDay);
89+ }
90+
91+ return matchesSearch && matchesLevel && matchesDateRange;
92+ }).toList ();
93+
94+ debugPrint ('Total logs: ${logs .length }' );
95+ debugPrint ('Filtered logs: ${filteredLogs .length }' );
96+ if (filteredLogs.isEmpty) {
97+ debugPrint ('First few log statuses:' );
98+ for (var i = 0 ; i < logs.length && i < 5 ; i++ ) {
99+ debugPrint ('Log ${i + 1 }: "${logs [i ]['Status' ]}"' );
100+ }
101+ }
102+ }
103+
104+ Future <void > clearLogs () async {
105+ try {
106+ await IsarDb ().clearLogs ();
107+ logs.value = [];
108+ filteredLogs.value = [];
109+ Get .snackbar (
110+ 'Success' ,
111+ 'Logs cleared successfully' ,
112+ backgroundColor: Colors .green,
113+ colorText: Colors .white,
114+ );
115+ } catch (e) {
116+ Get .snackbar (
117+ 'Error' ,
118+ 'Error clearing logs: $e ' ,
119+ backgroundColor: Colors .red,
120+ colorText: Colors .white,
121+ );
122+ }
123+ }
124+
125+ Future <void > selectDateRange () async {
126+ final DateTimeRange ? picked = await showDateRangePicker (
127+ context: Get .context! ,
128+ firstDate: DateTime (2020 ),
129+ lastDate: DateTime .now (),
130+ initialDateRange: DateTimeRange (
131+ start: startDate.value ?? DateTime .now ().subtract (const Duration (days: 7 )),
132+ end: endDate.value ?? DateTime .now (),
133+ ),
134+ builder: (context, child) {
135+ return Theme (
136+ data: Theme .of (context).copyWith (
137+ colorScheme: ColorScheme .light (
138+ primary: kprimaryColor,
139+ onPrimary: Colors .white,
140+ surface: themeController.secondaryBackgroundColor.value,
141+ onSurface: themeController.primaryTextColor.value,
142+ background: themeController.primaryBackgroundColor.value,
143+ onBackground: themeController.primaryTextColor.value,
144+ ),
145+ textButtonTheme: TextButtonThemeData (
146+ style: TextButton .styleFrom (
147+ foregroundColor: kprimaryColor,
148+ ),
149+ ),
150+ dialogBackgroundColor: themeController.secondaryBackgroundColor.value,
151+ ),
152+ child: child! ,
153+ );
154+ },
155+ );
156+ if (picked != null ) {
157+ startDate.value = picked.start;
158+ endDate.value = picked.end;
159+ applyFilters ();
160+ }
161+ }
162+
163+ Color getLogLevelColor (String status) {
164+ status = status.toLowerCase ();
165+ if (status.contains ('error' )) return Colors .red;
166+ if (status.contains ('warning' )) return Colors .orange;
167+ return Colors .green;
168+ }
169+ }
0 commit comments