mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-27 06:18:50 +01:00
186 lines
5.9 KiB
Dart
186 lines
5.9 KiB
Dart
import 'dart:convert';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
|
import 'package:cake_wallet/src/screens/dev/moneroc_cache_debug.dart';
|
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
|
import 'package:cake_wallet/view_model/dev/network_requests_view_model.dart';
|
|
import 'package:cw_core/utils/proxy_logger/abstract.dart';
|
|
import 'package:cw_core/utils/proxy_logger/memory_proxy_logger.dart';
|
|
import 'package:cw_core/utils/proxy_wrapper.dart';
|
|
import 'package:cw_core/utils/tor/abstract.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
|
import 'package:on_chain/solana/solana.dart';
|
|
|
|
class DevNetworkRequests extends BasePage {
|
|
final NetworkRequestsViewModel viewModel = NetworkRequestsViewModel();
|
|
|
|
DevNetworkRequests() {
|
|
viewModel.loadLogs();
|
|
}
|
|
|
|
@override
|
|
String? get title => "[dev] network requests";
|
|
|
|
@override
|
|
Widget? trailing(BuildContext context) {
|
|
return IconButton(
|
|
icon: Icon(Icons.refresh),
|
|
onPressed: () => viewModel.loadLogs(),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget body(BuildContext context) {
|
|
return Observer(
|
|
builder: (_) {
|
|
if (viewModel.logs.isEmpty) {
|
|
return Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Text("No logs loaded"),
|
|
SizedBox(height: 16),
|
|
ElevatedButton(
|
|
onPressed: () => viewModel.loadLogs(),
|
|
child: Text("Load Logs"),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
} else {
|
|
return ListView.builder(
|
|
itemCount: viewModel.logs.length,
|
|
itemBuilder: (BuildContext context, int i) {
|
|
final item = viewModel.logs[i];
|
|
return ListTile(
|
|
onTap: () {
|
|
Navigator.of(context).push(
|
|
MaterialPageRoute(
|
|
builder: (BuildContext context) {
|
|
return DevRequestDetails(item);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
leading: switch (item.network) {
|
|
RequestNetwork.clearnet => Text("C"),
|
|
RequestNetwork.tor => Text("T"),
|
|
},
|
|
trailing: switch (item.method) {
|
|
RequestMethod.get => Text("GET"),
|
|
RequestMethod.post => Text("POST"),
|
|
RequestMethod.put => Text("PUT"),
|
|
RequestMethod.delete => Text("DELETE"),
|
|
RequestMethod.newHttpClient ||
|
|
RequestMethod.newHttpIOClient ||
|
|
RequestMethod.newProxySocket =>
|
|
null,
|
|
},
|
|
title: Text(item.time.toIso8601String()),
|
|
subtitle: switch (item.method) {
|
|
RequestMethod.get ||
|
|
RequestMethod.post ||
|
|
RequestMethod.put ||
|
|
RequestMethod.delete =>
|
|
Text("${item.uri}"),
|
|
RequestMethod.newHttpClient => Text("newHttpClient"),
|
|
RequestMethod.newHttpIOClient => Text("newHttpIOClient"),
|
|
RequestMethod.newProxySocket => Text("newProxySocket"),
|
|
},
|
|
tileColor: item.error != null ? Colors.red : null,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class DevRequestDetails extends BasePage {
|
|
final MemoryProxyLoggerEntry req;
|
|
DevRequestDetails(this.req);
|
|
|
|
@override
|
|
Widget body(BuildContext context) {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: _body(context),
|
|
);
|
|
}
|
|
|
|
Widget _body(BuildContext context) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
_sectionTitle("Time"),
|
|
SelectableText(req.time.toString()),
|
|
_sectionTitle("Method"),
|
|
SelectableText(req.method.toString()),
|
|
_sectionTitle("URI"),
|
|
SelectableText(req.uri?.toString() ?? "null"),
|
|
_sectionTitle("Network"),
|
|
SelectableText(req.network.toString()),
|
|
if (req.network == RequestNetwork.tor) ...[
|
|
_sectionTitle("Tor socks server"),
|
|
SelectableText(CakeTor.instance.runtimeType.toString()),
|
|
_sectionTitle("Tor socks details"),
|
|
SelectableText(CakeTor.instance.toString()),
|
|
],
|
|
_sectionTitle("Body (as UTF-8)"),
|
|
SelectableText(_tryDecodeBody(req.body)),
|
|
_buildJsonExplorer(context, _tryDecodeBody(req.body)),
|
|
_sectionTitle("Response"),
|
|
SelectableText(req.response?.body ?? "null"),
|
|
_buildJsonExplorer(context, req.response?.body ?? "{}"),
|
|
_sectionTitle("Error"),
|
|
SelectableText(req.error ?? "No error"),
|
|
_sectionTitle("Stack Trace"),
|
|
SelectableText(req.trace.toString()),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildJsonExplorer(BuildContext context, String body) {
|
|
try {
|
|
final jsonData = json.decode(body);
|
|
return PrimaryButton(
|
|
text: "View JSON",
|
|
color: Colors.blue,
|
|
textColor: Colors.white,
|
|
onPressed: () {
|
|
Navigator.of(context).push(
|
|
MaterialPageRoute(
|
|
builder: (context) {
|
|
return JsonExplorerPage(data: jsonData, title: "body");
|
|
},
|
|
),
|
|
);
|
|
},
|
|
);
|
|
} catch (e) {
|
|
return SelectableText("Invalid JSON: $e");
|
|
}
|
|
}
|
|
|
|
Widget _sectionTitle(String title) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
child: Text(
|
|
title,
|
|
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
|
|
),
|
|
);
|
|
}
|
|
|
|
String _tryDecodeBody(Uint8List body) {
|
|
try {
|
|
return utf8.decode(body);
|
|
} catch (_) {
|
|
return 'Binary data (${body.length} bytes)';
|
|
}
|
|
}
|
|
}
|