mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-04-23 23:39:12 +00:00
Added realtime logs
This commit is contained in:
parent
be3e76eafc
commit
7991f29707
6 changed files with 190 additions and 8 deletions
|
@ -795,5 +795,7 @@
|
||||||
"clientIpCopied": "Client IP copied to the clipboard",
|
"clientIpCopied": "Client IP copied to the clipboard",
|
||||||
"clientNameCopied": "Client name copied to the clipboard",
|
"clientNameCopied": "Client name copied to the clipboard",
|
||||||
"dnsServerAddressCopied": "DNS server address copied to the clipboard",
|
"dnsServerAddressCopied": "DNS server address copied to the clipboard",
|
||||||
"select": "Select"
|
"select": "Select",
|
||||||
|
"liveLogs": "Live logs",
|
||||||
|
"hereWillAppearRealtimeLogs": "Here there will appear the logs on realtime."
|
||||||
}
|
}
|
|
@ -795,5 +795,7 @@
|
||||||
"clientIpCopied": "Dirección IP del cliente copiada al portapapeles",
|
"clientIpCopied": "Dirección IP del cliente copiada al portapapeles",
|
||||||
"clientNameCopied": "Nombre del cliente copiado al portapapeles",
|
"clientNameCopied": "Nombre del cliente copiado al portapapeles",
|
||||||
"dnsServerAddressCopied": "Dirección del servidor DNS copiada al portapapeles",
|
"dnsServerAddressCopied": "Dirección del servidor DNS copiada al portapapeles",
|
||||||
"select": "Seleccionar"
|
"select": "Seleccionar",
|
||||||
|
"liveLogs": "Registros en directo",
|
||||||
|
"hereWillAppearRealtimeLogs": "Aquí aparecerán los registros en tiempo real."
|
||||||
}
|
}
|
51
lib/providers/live_logs_provider.dart
Normal file
51
lib/providers/live_logs_provider.dart
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/models/logs.dart';
|
||||||
|
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||||
|
|
||||||
|
class LiveLogsProvider with ChangeNotifier {
|
||||||
|
ServersProvider? _serversProvider;
|
||||||
|
|
||||||
|
update(ServersProvider? provider) {
|
||||||
|
_serversProvider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _isDisposed = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_isDisposed = true;
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Log> _logs = [];
|
||||||
|
|
||||||
|
List<Log> get logs {
|
||||||
|
return _logs;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime? _lastTime;
|
||||||
|
|
||||||
|
void startFetchLogs() {
|
||||||
|
_lastTime = DateTime.now();
|
||||||
|
_fetchLogs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fetchLogs() async {
|
||||||
|
if (_lastTime == null) return;
|
||||||
|
final result = await _serversProvider!.apiClient2!.getLogs(
|
||||||
|
count: 100
|
||||||
|
);
|
||||||
|
if (result.successful == false || result.content == null) return;
|
||||||
|
final valid = (result.content as LogsData).data.where((e) => e.time.isAfter(_lastTime!));
|
||||||
|
_logs = [...valid, ..._logs];
|
||||||
|
_lastTime = DateTime.now();
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
|
if (_isDisposed == true) return;
|
||||||
|
_fetchLogs();
|
||||||
|
}
|
||||||
|
}
|
89
lib/screens/logs/live/live_logs_screen.dart
Normal file
89
lib/screens/logs/live/live_logs_screen.dart
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/screens/logs/details/log_details_screen.dart';
|
||||||
|
import 'package:adguard_home_manager/screens/logs/log_tile.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/providers/live_logs_provider.dart';
|
||||||
|
|
||||||
|
class LiveLogsScreen extends StatefulWidget {
|
||||||
|
const LiveLogsScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<LiveLogsScreen> createState() => _LiveLogsScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LiveLogsScreenState extends State<LiveLogsScreen> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
Provider.of<LiveLogsProvider>(context, listen: false).startFetchLogs();
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final liveLogsProvider = Provider.of<LiveLogsProvider>(context);
|
||||||
|
print(liveLogsProvider.logs.length);
|
||||||
|
return Scaffold(
|
||||||
|
body: NestedScrollView(
|
||||||
|
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||||
|
SliverOverlapAbsorber(
|
||||||
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
|
sliver: SliverAppBar.large(
|
||||||
|
title: Text(AppLocalizations.of(context)!.liveLogs),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
body: SafeArea(
|
||||||
|
top: false,
|
||||||
|
bottom: false,
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) => CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverOverlapInjector(
|
||||||
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
|
),
|
||||||
|
if (liveLogsProvider.logs.isEmpty) SliverFillRemaining(
|
||||||
|
child: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)!.hereWillAppearRealtimeLogs,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
fontSize: 24
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (liveLogsProvider.logs.isNotEmpty) SliverList.builder(
|
||||||
|
itemCount: liveLogsProvider.logs.length,
|
||||||
|
itemBuilder: (context, index) => LogTile(
|
||||||
|
log: liveLogsProvider.logs[index],
|
||||||
|
length: liveLogsProvider.logs.length,
|
||||||
|
index: index,
|
||||||
|
onLogTap: (log) {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => LogDetailsScreen(
|
||||||
|
log: log,
|
||||||
|
dialog: false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
twoColumns: false
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,14 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/screens/logs/live/live_logs_screen.dart';
|
||||||
import 'package:adguard_home_manager/screens/logs/filters/logs_filters_modal.dart';
|
import 'package:adguard_home_manager/screens/logs/filters/logs_filters_modal.dart';
|
||||||
|
|
||||||
import 'package:adguard_home_manager/config/globals.dart';
|
import 'package:adguard_home_manager/config/globals.dart';
|
||||||
import 'package:adguard_home_manager/constants/enums.dart';
|
import 'package:adguard_home_manager/constants/enums.dart';
|
||||||
import 'package:adguard_home_manager/functions/desktop_mode.dart';
|
import 'package:adguard_home_manager/functions/desktop_mode.dart';
|
||||||
|
import 'package:adguard_home_manager/providers/live_logs_provider.dart';
|
||||||
|
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||||
import 'package:adguard_home_manager/models/applied_filters.dart';
|
import 'package:adguard_home_manager/models/applied_filters.dart';
|
||||||
import 'package:adguard_home_manager/providers/logs_provider.dart';
|
import 'package:adguard_home_manager/providers/logs_provider.dart';
|
||||||
|
|
||||||
|
@ -74,6 +77,22 @@ class LogsListAppBar extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openLiveLogsScreen() {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => MultiProvider(
|
||||||
|
providers: [
|
||||||
|
ChangeNotifierProxyProvider<ServersProvider, LiveLogsProvider>(
|
||||||
|
create: (context) => LiveLogsProvider(),
|
||||||
|
update: (context, servers, logs) => logs!..update(servers),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: const LiveLogsScreen()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final Map<String, String> translatedString = {
|
final Map<String, String> translatedString = {
|
||||||
"all": AppLocalizations.of(context)!.all,
|
"all": AppLocalizations.of(context)!.all,
|
||||||
"filtered": AppLocalizations.of(context)!.filtered,
|
"filtered": AppLocalizations.of(context)!.filtered,
|
||||||
|
@ -104,10 +123,29 @@ class LogsListAppBar extends StatelessWidget {
|
||||||
icon: const Icon(Icons.search_rounded),
|
icon: const Icon(Icons.search_rounded),
|
||||||
tooltip: AppLocalizations.of(context)!.search,
|
tooltip: AppLocalizations.of(context)!.search,
|
||||||
),
|
),
|
||||||
if (logsProvider.loadStatus == LoadStatus.loaded) IconButton(
|
if (logsProvider.loadStatus == LoadStatus.loaded) PopupMenuButton(
|
||||||
onPressed: openFilersModal,
|
itemBuilder: (context) => [
|
||||||
icon: const Icon(Icons.filter_list_rounded),
|
PopupMenuItem(
|
||||||
tooltip: AppLocalizations.of(context)!.filters,
|
onTap: openFilersModal,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.filter_list_rounded),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(AppLocalizations.of(context)!.filters)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
onTap: openLiveLogsScreen,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.stream_rounded),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(AppLocalizations.of(context)!.liveLogs)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
],
|
],
|
||||||
|
|
|
@ -206,14 +206,14 @@ class ApiClientV2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ApiResponse> getLogs({
|
Future<ApiResponse> getLogs({
|
||||||
required int count,
|
int? count,
|
||||||
int? offset,
|
int? offset,
|
||||||
DateTime? olderThan,
|
DateTime? olderThan,
|
||||||
String? responseStatus,
|
String? responseStatus,
|
||||||
String? search
|
String? search
|
||||||
}) async {
|
}) async {
|
||||||
final result = await HttpRequestClient.get(
|
final result = await HttpRequestClient.get(
|
||||||
urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}',
|
urlPath: '/querylog?${count != null ? 'limit=$count' : ''}${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}',
|
||||||
server: server
|
server: server
|
||||||
);
|
);
|
||||||
if (result.successful == true) {
|
if (result.successful == true) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue