Tor Status Pane Initial Cut
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
1d98f57cad
commit
a56a1e1f89
Binary file not shown.
After Width: | Height: | Size: 575 B |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 6.5 KiB |
|
@ -9,6 +9,9 @@ abstract class Cwtch {
|
||||||
// ignore: non_constant_identifier_names
|
// ignore: non_constant_identifier_names
|
||||||
void LoadProfiles(String pass);
|
void LoadProfiles(String pass);
|
||||||
|
|
||||||
|
// ignore: non_constant_identifier_names
|
||||||
|
void ResetTor();
|
||||||
|
|
||||||
// todo: remove these
|
// todo: remove these
|
||||||
// ignore: non_constant_identifier_names
|
// ignore: non_constant_identifier_names
|
||||||
void SendProfileEvent(String onion, String jsonEvent);
|
void SendProfileEvent(String onion, String jsonEvent);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter_app/torstatus.dart';
|
||||||
|
|
||||||
import '../errorHandler.dart';
|
import '../errorHandler.dart';
|
||||||
import '../model.dart';
|
import '../model.dart';
|
||||||
import '../settings.dart';
|
import '../settings.dart';
|
||||||
|
@ -11,11 +13,13 @@ class CwtchNotifier {
|
||||||
ProfileListState profileCN;
|
ProfileListState profileCN;
|
||||||
Settings settings;
|
Settings settings;
|
||||||
ErrorHandler error;
|
ErrorHandler error;
|
||||||
|
TorStatus torStatus;
|
||||||
|
|
||||||
CwtchNotifier(ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN) {
|
CwtchNotifier(ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN) {
|
||||||
profileCN = pcn;
|
profileCN = pcn;
|
||||||
settings = settingsCN;
|
settings = settingsCN;
|
||||||
error = errorCN;
|
error = errorCN;
|
||||||
|
torStatus = torStatusCN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMessage(String type, dynamic data) {
|
void handleMessage(String type, dynamic data) {
|
||||||
|
@ -75,6 +79,7 @@ class CwtchNotifier {
|
||||||
break;
|
break;
|
||||||
case "ACNStatus":
|
case "ACNStatus":
|
||||||
print("acn status: $data");
|
print("acn status: $data");
|
||||||
|
torStatus.handleUpdate(int.parse(data["Progress"]), data["Status"]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
print("unhandled event: $type");
|
print("unhandled event: $type");
|
||||||
|
|
|
@ -297,4 +297,11 @@ class CwtchFfi implements Cwtch {
|
||||||
final u3 = message.toNativeUtf8();
|
final u3 = message.toNativeUtf8();
|
||||||
SendMessage(u1, u1.length, u2, u2.length, u3, u3.length);
|
SendMessage(u1, u1.length, u2, u2.length, u3, u3.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void ResetTor() {
|
||||||
|
var resetTor = library.lookup<NativeFunction<Void Function()>>("c_ResetTor");
|
||||||
|
final ResetTor = resetTor.asFunction<void Function()>();
|
||||||
|
ResetTor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,4 +142,10 @@ class CwtchGomobile implements Cwtch {
|
||||||
void SendMessage(String profileOnion, String contactHandle, String message) {
|
void SendMessage(String profileOnion, String contactHandle, String message) {
|
||||||
cwtchPlatform.invokeMethod("SendMessage", {"ProfileOnion": profileOnion, "handle": contactHandle, "message": message});
|
cwtchPlatform.invokeMethod("SendMessage", {"ProfileOnion": profileOnion, "handle": contactHandle, "message": message});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: non_constant_identifier_names
|
||||||
|
void ResetTor() {
|
||||||
|
cwtchPlatform.invokeMethod("ResetTor", {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:flutter_app/cwtch/gomobile.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_app/errorHandler.dart';
|
import 'package:flutter_app/errorHandler.dart';
|
||||||
import 'package:flutter_app/settings.dart';
|
import 'package:flutter_app/settings.dart';
|
||||||
|
import 'package:flutter_app/torstatus.dart';
|
||||||
import 'package:flutter_app/views/triplecolview.dart';
|
import 'package:flutter_app/views/triplecolview.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'cwtch/cwtch.dart';
|
import 'cwtch/cwtch.dart';
|
||||||
|
@ -18,6 +19,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
var globalSettings = Settings(Locale("en", ''), Opaque.dark);
|
var globalSettings = Settings(Locale("en", ''), Opaque.dark);
|
||||||
var globalErrorHandler = ErrorHandler();
|
var globalErrorHandler = ErrorHandler();
|
||||||
|
var globalTorStatus = TorStatus();
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
LicenseRegistry.addLicense(() => licenses());
|
LicenseRegistry.addLicense(() => licenses());
|
||||||
|
@ -48,7 +50,7 @@ class FlwtchState extends State<Flwtch> {
|
||||||
cwtchInit = false;
|
cwtchInit = false;
|
||||||
|
|
||||||
profs = ProfileListState();
|
profs = ProfileListState();
|
||||||
var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler);
|
var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus);
|
||||||
|
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
cwtch = CwtchGomobile(cwtchNotifier);
|
cwtch = CwtchGomobile(cwtchNotifier);
|
||||||
|
@ -65,6 +67,7 @@ class FlwtchState extends State<Flwtch> {
|
||||||
appStatus = AppModel(cwtch: cwtch);
|
appStatus = AppModel(cwtch: cwtch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChangeNotifierProvider<TorStatus> getTorStatusProvider() => ChangeNotifierProvider.value(value: globalTorStatus);
|
||||||
ChangeNotifierProvider<ErrorHandler> getErrorHandlerProvider() => ChangeNotifierProvider.value(value: globalErrorHandler);
|
ChangeNotifierProvider<ErrorHandler> getErrorHandlerProvider() => ChangeNotifierProvider.value(value: globalErrorHandler);
|
||||||
ChangeNotifierProvider<Settings> getSettingsProvider() => ChangeNotifierProvider.value(value: globalSettings);
|
ChangeNotifierProvider<Settings> getSettingsProvider() => ChangeNotifierProvider.value(value: globalSettings);
|
||||||
Provider<FlwtchState> getFlwtchStateProvider() => Provider<FlwtchState>(create: (_) => this);
|
Provider<FlwtchState> getFlwtchStateProvider() => Provider<FlwtchState>(create: (_) => this);
|
||||||
|
@ -75,7 +78,7 @@ class FlwtchState extends State<Flwtch> {
|
||||||
//appStatus = AppModel(cwtch: cwtch);
|
//appStatus = AppModel(cwtch: cwtch);
|
||||||
|
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [getFlwtchStateProvider(), getProfileListProvider(), getSettingsProvider(), getErrorHandlerProvider()],
|
providers: [getFlwtchStateProvider(), getProfileListProvider(), getSettingsProvider(), getErrorHandlerProvider(), getTorStatusProvider()],
|
||||||
builder: (context, widget) {
|
builder: (context, widget) {
|
||||||
Provider.of<Settings>(context).initPackageInfo();
|
Provider.of<Settings>(context).initPackageInfo();
|
||||||
return Consumer<Settings>(
|
return Consumer<Settings>(
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class TorStatus extends ChangeNotifier {
|
||||||
|
int progress;
|
||||||
|
String status;
|
||||||
|
bool connected;
|
||||||
|
|
||||||
|
/// Called by the event bus.
|
||||||
|
handleUpdate(int new_progress, String new_status) {
|
||||||
|
if (progress == 100) {
|
||||||
|
connected = true;
|
||||||
|
} else {
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress = new_progress;
|
||||||
|
status = new_status;
|
||||||
|
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_app/settings.dart';
|
import 'package:flutter_app/settings.dart';
|
||||||
|
import 'package:flutter_app/views/torstatusview.dart';
|
||||||
import 'package:flutter_app/widgets/passwordfield.dart';
|
import 'package:flutter_app/widgets/passwordfield.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:flutter_app/widgets/profilerow.dart';
|
import 'package:flutter_app/widgets/profilerow.dart';
|
||||||
|
@ -34,6 +35,13 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(AppLocalizations.of(context).titleManageProfiles),
|
title: Text(AppLocalizations.of(context).titleManageProfiles),
|
||||||
actions: [
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: Image(
|
||||||
|
image: AssetImage("assets/core/Tor_icon.png"),
|
||||||
|
filterQuality: FilterQuality.low,
|
||||||
|
isAntiAlias: false,
|
||||||
|
),
|
||||||
|
onPressed: _pushTorStatus),
|
||||||
IconButton(icon: Icon(Icons.bug_report_outlined), onPressed: _setLoggingLevelDebug),
|
IconButton(icon: Icon(Icons.bug_report_outlined), onPressed: _setLoggingLevelDebug),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.lock_open),
|
icon: Icon(Icons.lock_open),
|
||||||
|
@ -75,6 +83,17 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _pushTorStatus() {
|
||||||
|
Navigator.of(context).push(MaterialPageRoute<void>(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Provider(
|
||||||
|
create: (_) => Provider.of<FlwtchState>(context, listen: false),
|
||||||
|
child: TorStatusView(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
void _pushAddEditProfile({onion: ""}) {
|
void _pushAddEditProfile({onion: ""}) {
|
||||||
Navigator.of(context).push(MaterialPageRoute<void>(
|
Navigator.of(context).push(MaterialPageRoute<void>(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_app/settings.dart';
|
||||||
|
import 'package:flutter_app/torstatus.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
import '../main.dart';
|
||||||
|
|
||||||
|
/// Tor Status View provides all info on Tor network state and the (future) ability to configure the network in a variety
|
||||||
|
/// of ways (restart, enable bridges, enable pluggable transports etc)
|
||||||
|
class TorStatusView extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_TorStatusView createState() => _TorStatusView();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TorStatusView extends State<TorStatusView> {
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("Tor Network Status"),
|
||||||
|
),
|
||||||
|
body: _buildSettingsList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSettingsList() {
|
||||||
|
return Consumer<TorStatus>(builder: (context, torStatus, child) {
|
||||||
|
return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
||||||
|
return Scrollbar(
|
||||||
|
isAlwaysShown: true,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minHeight: viewportConstraints.maxHeight,
|
||||||
|
),
|
||||||
|
child: Column(children: [
|
||||||
|
ListTile(
|
||||||
|
leading: Image(
|
||||||
|
image: AssetImage("assets/core/Tor_icon.png"),
|
||||||
|
),
|
||||||
|
title: Text("Tor Status"),
|
||||||
|
subtitle: Text(torStatus.progress == 100 ? AppLocalizations.of(context).networkStatusOnline : torStatus.status),
|
||||||
|
trailing: ElevatedButton(
|
||||||
|
child: Text("Reset"),
|
||||||
|
onPressed: () {
|
||||||
|
Provider.of<FlwtchState>(context, listen: false).cwtch.ResetTor();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]))));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,6 +83,7 @@ flutter:
|
||||||
|
|
||||||
assets:
|
assets:
|
||||||
- assets/
|
- assets/
|
||||||
|
- assets/core/
|
||||||
- assets/profiles/
|
- assets/profiles/
|
||||||
|
|
||||||
# To add custom fonts to your application, add a fonts section here,
|
# To add custom fonts to your application, add a fonts section here,
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
|
@ -0,0 +1,72 @@
|
||||||
|
// This is a basic Flutter widget test.
|
||||||
|
//
|
||||||
|
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
|
// utility that Flutter provides. For example, you can send tap and scroll
|
||||||
|
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||||
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_app/opaque.dart';
|
||||||
|
import 'package:flutter_app/settings.dart';
|
||||||
|
import 'package:flutter_app/widgets/cwtchlabel.dart';
|
||||||
|
import 'package:flutter_app/widgets/profileimage.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
var settingsEnglishDark = Settings(Locale("en", ''), Opaque.dark);
|
||||||
|
var settingsEnglishLight = Settings(Locale("en", ''), Opaque.light);
|
||||||
|
ChangeNotifierProvider<Settings> getSettingsEnglishDark() => ChangeNotifierProvider.value(value: settingsEnglishDark);
|
||||||
|
|
||||||
|
String file(String slug) {
|
||||||
|
return "profileimage_" + slug + ".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
testWidgets('ProfileImage widget test', (WidgetTester tester) async {
|
||||||
|
tester.binding.window.physicalSizeTestValue = Size(200, 200);
|
||||||
|
// await tester.pumpWidget(MultiProvider(
|
||||||
|
// providers:[getSettingsEnglishDark()],
|
||||||
|
// child: Directionality(textDirection: TextDirection.ltr, child: CwtchLabel(label: testingStr))
|
||||||
|
// ));
|
||||||
|
|
||||||
|
Widget testWidget = ProfileImage(
|
||||||
|
imagePath: "profiles/001-centaur.png",
|
||||||
|
badgeTextColor: settingsEnglishDark.theme.portraitProfileBadgeTextColor(),
|
||||||
|
badgeColor: settingsEnglishDark.theme.portraitProfileBadgeColor(),
|
||||||
|
maskOut: false,
|
||||||
|
border: settingsEnglishDark.theme.portraitOfflineBorderColor(),
|
||||||
|
diameter: 64.0,
|
||||||
|
badgeCount: 10,
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget testHarness = MultiProvider(
|
||||||
|
providers:[getSettingsEnglishDark()],
|
||||||
|
builder: (context, child) { return MaterialApp(
|
||||||
|
locale: Provider.of<Settings>(context).locale,
|
||||||
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
|
supportedLocales: AppLocalizations.supportedLocales,
|
||||||
|
title: 'Test',
|
||||||
|
theme: mkThemeData(Provider.of<Settings>(context)),
|
||||||
|
home: Card(child: testWidget),
|
||||||
|
);}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify that our counter starts at 0.
|
||||||
|
//expect(find.text(testingStr), findsOneWidget);
|
||||||
|
//expect(find.text('1'), findsNothing);
|
||||||
|
|
||||||
|
await tester.pumpWidget(testHarness);
|
||||||
|
await expectLater(find.byWidget(testHarness), matchesGoldenFile(file('init')));
|
||||||
|
|
||||||
|
// Tap the '+' icon and trigger a frame.
|
||||||
|
// await tester.tap(find.byIcon(Icons.add));
|
||||||
|
// await tester.pump();
|
||||||
|
//
|
||||||
|
// // Verify that our counter has incremented.
|
||||||
|
// expect(find.text('0'), findsNothing);
|
||||||
|
// expect(find.text('1'), findsOneWidget);
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue