Skip to content

Commit

Permalink
Merge pull request #5 from Rexsunon/feat/no-ref/search-and-filter
Browse files Browse the repository at this point in the history
feat: create and implement network filter functionality
  • Loading branch information
JideGuru authored May 24, 2024
2 parents 681ac15 + dd1a4f7 commit 877f878
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 21 deletions.
30 changes: 29 additions & 1 deletion lib/src/models/network_logman_record.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ class NetworkLogmanRecord extends LogmanRecord {

@override
String toString() {
return '';
return 'NetworkRequestLogmanRecord(request: $request, response: $response)';
}

Map<String, dynamic> toJson() {
return {
'request': request.toJson(),
'response': response?.toJson(),
};
}
}

Expand Down Expand Up @@ -51,6 +58,17 @@ class NetworkRequestLogmanRecord {
.formatJson();
return 'NetworkRequestLogmanRecord $readableJson';
}

Map<String, dynamic> toJson() {
return {
'id': id,
'url': url,
'method': method,
'headers': headers,
'body': body,
'sentAt': sentAt?.toIso8601String(),
};
}
}

class NetworkResponseLogmanRecord {
Expand Down Expand Up @@ -78,4 +96,14 @@ class NetworkResponseLogmanRecord {
.formatJson();
return 'NetworkResponseLogmanRecord $readableJson';
}

Map<String, dynamic> toJson() {
return {
'id': id,
'statusCode': statusCode,
'headers': headers,
'body': body,
'receivedAt': receivedAt?.toIso8601String(),
};
}
}
10 changes: 9 additions & 1 deletion lib/src/models/simple_logman_record.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ class SimpleLogmanRecord extends LogmanRecord {

@override
String toString() {
return 'SimpleLogmanRecord (message: $message, source: $source, isError: $isError)';
return 'SimpleLogmanRecord(message: $message, source: $source, isError: $isError)';
}

Map<String, dynamic> toJson() {
return {
'message': message,
'source': source,
'isError': isError,
};
}
}
38 changes: 38 additions & 0 deletions lib/src/presentation/notifier/network_record_notifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'package:flutter/cupertino.dart';
import 'package:logman/src/models/models.dart';
import 'package:logman/src/presentation/pages/pages.dart';

class NetworkRecordNotifier extends ValueNotifier<List<NetworkLogmanRecord>> {
NetworkRecordNotifier(List<NetworkLogmanRecord> initialValue)
: super(initialValue) {
_originalNetworkRecords = List.from(initialValue);
}

late final List<NetworkLogmanRecord> _originalNetworkRecords;

void filterNetworkRecords(NetworkStatus status) {
value = _originalNetworkRecords.where((networkRecord) {
switch (status) {
case NetworkStatus.success:
return _isSuccessStatusCode(networkRecord);
case NetworkStatus.error:
return _isErrorStatusCode(networkRecord);
case NetworkStatus.all:
default:
return true;
}
}).toList();
notifyListeners();
}

bool _isSuccessStatusCode(NetworkLogmanRecord record) {
final statusCode = record.response?.statusCode;
return statusCode != null && statusCode >= 200 && statusCode < 300;
}

bool _isErrorStatusCode(NetworkLogmanRecord record) {
final statusCode = record.response?.statusCode;
return statusCode != null && (statusCode >= 400 && statusCode <= 500) ||
statusCode == 0;
}
}
1 change: 1 addition & 0 deletions lib/src/presentation/notifier/notifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'network_record_notifier.dart';
106 changes: 105 additions & 1 deletion lib/src/presentation/pages/logman_dashboard_page.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'package:flutter/material.dart';
import 'package:logman/logman.dart';
import 'package:logman/src/presentation/notifier/notifier.dart';
import 'package:logman/src/presentation/presentation.dart';

enum NetworkStatus { all, error, success }

class LogmanDashboardPage extends StatefulWidget {
final Widget? debugPage;
final Logman logman;
Expand Down Expand Up @@ -32,11 +35,25 @@ class LogmanDashboardPage extends StatefulWidget {

class _LogmanDashboardPageState extends State<LogmanDashboardPage>
with SingleTickerProviderStateMixin {
int currentIndex = 0; // To track tab page index

late final NetworkRecordNotifier _recordNotifier;
late final _tabController = TabController(
initialIndex: currentIndex,
length: widget.debugPage != null ? 5 : 4,
vsync: this,
);

@override
void initState() {
super.initState();
// Get all NetworkLogmanRecords from logman record list
final networkRecords =
widget.logman.records.value.whereType<NetworkLogmanRecord>().toList();

_recordNotifier = NetworkRecordNotifier(networkRecords);
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand All @@ -54,6 +71,8 @@ class _LogmanDashboardPageState extends State<LogmanDashboardPage>
controller: _tabController,
isScrollable: true,
tabAlignment: TabAlignment.center,
onTap: (value) =>
setState(() => currentIndex = value), // Update currentIndex value
tabs: [
const Tab(text: 'All'),
const Tab(text: 'Logs'),
Expand All @@ -63,6 +82,21 @@ class _LogmanDashboardPageState extends State<LogmanDashboardPage>
],
),
actions: [
// Only show these action widgets when network tab is active
Visibility(
visible: currentIndex == 2,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// todo implement search functionality
/*IconButton(
onPressed: () {},
icon: const Icon(Icons.search_rounded),
),*/
_NetworkFilterButton(recordsNotifier: _recordNotifier),
],
),
),
IconButton(
onPressed: () {
Navigator.of(context).pop();
Expand All @@ -82,7 +116,7 @@ class _LogmanDashboardPageState extends State<LogmanDashboardPage>
children: [
AllRecordsPage(records: records),
SimpleRecordsPage(records: records),
NetworkRecordsPage(records: records),
NetworkRecordsPage(networkRecordNotifier: _recordNotifier),
NavigationRecordsPage(records: records),
if (widget.debugPage != null) widget.debugPage!,
],
Expand All @@ -92,3 +126,73 @@ class _LogmanDashboardPageState extends State<LogmanDashboardPage>
);
}
}

class _NetworkFilterButton extends StatefulWidget {
const _NetworkFilterButton({required this.recordsNotifier});

final NetworkRecordNotifier recordsNotifier;

@override
State<_NetworkFilterButton> createState() => _NetworkFilterButtonState();
}

class _NetworkFilterButtonState extends State<_NetworkFilterButton> {
late final NetworkRecordNotifier _recordNotifier;

@override
void initState() {
super.initState();

_recordNotifier = widget.recordsNotifier;
}

@override
Widget build(BuildContext context) {
return PopupMenuButton<NetworkStatus>(
position: PopupMenuPosition.under,
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
onSelected: (value) => _recordNotifier.filterNetworkRecords(value),
itemBuilder: (BuildContext context) => [
PopupMenuItem(
value: NetworkStatus.all,
child: filterPopupButton(
icon: Icons.public,
title: 'All',
),
),
PopupMenuItem(
value: NetworkStatus.error,
child: filterPopupButton(
icon: Icons.public_off,
title: 'Error',
color: Colors.red,
),
),
PopupMenuItem(
value: NetworkStatus.success,
child: filterPopupButton(
icon: Icons.public,
title: 'Success',
color: Colors.green,
),
),
],
child: const Icon(Icons.filter_alt_rounded),
);
}

Row filterPopupButton({
required IconData icon,
required String title,
Color? color,
}) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, color: color, size: 16),
const SizedBox(width: 10),
Text(title),
],
);
}
}
37 changes: 19 additions & 18 deletions lib/src/presentation/pages/network_records_page.dart
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import 'package:flutter/material.dart';
import 'package:logman/logman.dart';
import 'package:logman/src/presentation/notifier/notifier.dart';
import 'package:logman/src/presentation/presentation.dart';

class NetworkRecordsPage extends StatelessWidget {
final List<LogmanRecord> records;
final NetworkRecordNotifier networkRecordNotifier;

const NetworkRecordsPage({super.key, required this.records});
const NetworkRecordsPage({super.key, required this.networkRecordNotifier});

@override
Widget build(BuildContext context) {
final simpleRecords = List<LogmanRecord>.from(records)
..retainWhere(
(element) => element is NetworkLogmanRecord,
);
return ValueListenableBuilder<List<NetworkLogmanRecord>>(
valueListenable: networkRecordNotifier,
builder: (context, networkRecords, child) {
if (networkRecords.isEmpty) {
return const Center(
child: Text('No Network calls recorded yet!'),
);
}

if (simpleRecords.isEmpty) {
return const Center(
child: Text('No Network calls recorded yet!'),
);
}

return ListView.separated(
itemCount: simpleRecords.length,
itemBuilder: (context, index) {
final record = simpleRecords[index] as NetworkLogmanRecord;
return NetworkRecordItem(record: record);
return ListView.separated(
itemCount: networkRecords.length,
itemBuilder: (context, index) {
final networkRecord = networkRecords[index];
return NetworkRecordItem(record: networkRecord);
},
separatorBuilder: (context, index) => const CustomDivider(),
);
},
separatorBuilder: (context, index) => const CustomDivider(),
);
}
}

0 comments on commit 877f878

Please sign in to comment.