Skip to content

Commit 639749f

Browse files
authored
Use showAboutDialog for OSS licenses (#217)
Also: * Verify `onTap` handler that toggles developer mode
1 parent 63971f3 commit 639749f

File tree

9 files changed

+134
-38
lines changed

9 files changed

+134
-38
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ upload the apps to GCS (automatically deleted after 30 days).
2121
- Render HTML with [flutter_widget_from_html](https://pub.dev/packages/flutter_widget_from_html)
2222
- Push notification via [firebase_messaging](https://pub.dev/packages/firebase_messaging)
2323
- Dark mode: on / off / auto
24-
- Developer hidden menu (tap "Version" thrice)
24+
- Developer hidden menu (tap version in about dialog thrice)
2525
- Android, iOS domain association with [built-in deep link support](https://docs.flutter.dev/ui/navigation/deep-linking)
2626

2727
<details>

ios/Runner.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@
224224
97C146E61CF9000F007C117D /* Project object */ = {
225225
isa = PBXProject;
226226
attributes = {
227-
LastUpgradeCheck = 1300;
227+
LastUpgradeCheck = 1430;
228228
ORGANIZATIONNAME = "";
229229
TargetAttributes = {
230230
331C8080294A63A400263BE5 = {

ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1300"
3+
LastUpgradeVersion = "1430"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

lib/src/widgets/menu/dev_tools.dart

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,31 @@ import 'availability/error_reporting.dart';
99
import 'availability/firebase.dart';
1010
import 'availability/push_notification.dart';
1111

12-
class DevTools extends ChangeNotifier {
12+
abstract class DevTools extends ChangeNotifier {
13+
bool get isDeveloper;
14+
set isDeveloper(bool v);
15+
16+
bool get showPerformanceOverlay;
17+
set showPerformanceOverlay(bool v);
18+
19+
static Future<DevTools> create() async {
20+
final developer = _DevTools();
21+
final prefs = await SharedPreferences.getInstance();
22+
developer._isDeveloper = prefs.getBool(kPrefKeyDevToolIsDeveloper);
23+
developer._showPerformanceOverlay =
24+
prefs.getBool(kPrefKeyDevToolShowPerformanceOverlay);
25+
return developer;
26+
}
27+
}
28+
29+
class _DevTools extends ChangeNotifier implements DevTools {
1330
bool? _isDeveloper;
1431
bool? _showPerformanceOverlay;
1532

16-
DevTools._();
17-
33+
@override
1834
bool get isDeveloper => _isDeveloper == true;
1935

36+
@override
2037
set isDeveloper(bool v) {
2138
_isDeveloper = v;
2239
notifyListeners();
@@ -25,24 +42,17 @@ class DevTools extends ChangeNotifier {
2542
.then((prefs) => prefs.setBool(kPrefKeyDevToolIsDeveloper, v));
2643
}
2744

45+
@override
2846
bool get showPerformanceOverlay => _showPerformanceOverlay == true;
2947

48+
@override
3049
set showPerformanceOverlay(bool v) {
3150
_showPerformanceOverlay = v;
3251
notifyListeners();
3352

3453
SharedPreferences.getInstance().then(
3554
(prefs) => prefs.setBool(kPrefKeyDevToolShowPerformanceOverlay, v));
3655
}
37-
38-
static Future<DevTools> create() async {
39-
final developer = DevTools._();
40-
final prefs = await SharedPreferences.getInstance();
41-
developer._isDeveloper = prefs.getBool(kPrefKeyDevToolIsDeveloper);
42-
developer._showPerformanceOverlay =
43-
prefs.getBool(kPrefKeyDevToolShowPerformanceOverlay);
44-
return developer;
45-
}
4656
}
4757

4858
class DeveloperMenu extends StatelessWidget {
Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:package_info_plus/package_info_plus.dart';
33
import 'package:provider/provider.dart';
4+
import 'package:the_app/src/constants.dart';
45
import 'package:the_app/src/intl.dart';
56

67
import 'dev_tools.dart';
@@ -14,31 +15,44 @@ class PackageInfoWidget extends StatefulWidget {
1415

1516
class _PackageInfoState extends State<PackageInfoWidget> {
1617
PackageInfo? _info;
17-
var count = 0;
1818

1919
@override
2020
void initState() {
2121
super.initState();
22-
PackageInfo.fromPlatform().then((info) => setState(() => _info = info));
22+
PackageInfo.fromPlatform().then((info) => _info = info);
2323
}
2424

2525
@override
2626
Widget build(BuildContext context) {
27-
final devTools = context.watch<DevTools>();
28-
final scopedInfo = _info;
2927
return ListTile(
3028
title: Text(l(context).appVersion),
31-
subtitle: Text(scopedInfo != null
32-
? l(context)
33-
.appVersionInfo(scopedInfo.version, scopedInfo.buildNumber)
34-
: l(context).appVersionNotAvailable),
35-
onTap: devTools.isDeveloper
36-
? null
37-
: () {
38-
if (++count >= 3) {
39-
devTools.isDeveloper = true;
40-
}
41-
},
29+
onTap: () => _showAboutDialog(context),
30+
);
31+
}
32+
33+
void _showAboutDialog(BuildContext context) {
34+
var count = 0;
35+
final info = _info;
36+
showAboutDialog(
37+
context: context,
38+
children: [
39+
InkWell(
40+
onTap: () {
41+
final newCount = ++count;
42+
if (newCount >= 3) {
43+
// starting from the the third tap
44+
// each one will toggle developer menu on or off
45+
context.read<DevTools>().isDeveloper = (newCount % 2) > 0;
46+
}
47+
},
48+
child: Padding(
49+
padding: const EdgeInsets.all(kPadding),
50+
child: Text(info != null
51+
? l(context).appVersionInfo(info.version, info.buildNumber)
52+
: l(context).appVersionNotAvailable),
53+
),
54+
),
55+
],
4256
);
4357
}
4458
}

lib/src/widgets/post/actions.dart

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,21 @@ class _PostActionsWidgetState extends State<_PostActionsWidget> {
9494
),
9595
),
9696
itemBuilder: (_) => _buildPopupMenuItems(post),
97-
onSelected: (action) async {
97+
onSelected: (action) {
9898
switch (action) {
9999
case _kPopupActionDelete:
100-
final reason = await showDialog(
100+
showDialog(
101101
context: context,
102102
builder: (context) => _PostActionsDialogReason(
103103
button: l(context).postDelete,
104104
hint: l(context).postDeleteReasonHint,
105105
),
106+
).then(
107+
(reason) {
108+
if (reason == null) return;
109+
_deletePost(post, reason);
110+
},
106111
);
107-
if (reason != null) _deletePost(post, reason);
108112
break;
109113
case _kPopupActionOpenInBrowser:
110114
final permalink = post.links?.permalink;
@@ -113,14 +117,16 @@ class _PostActionsWidgetState extends State<_PostActionsWidget> {
113117
}
114118
break;
115119
case _kPopupActionReport:
116-
final message = await showDialog(
120+
showDialog(
117121
context: context,
118122
builder: (context) => _PostActionsDialogReason(
119123
button: l(context).postReport,
120124
hint: l(context).postReportReasonHint,
121125
),
122-
);
123-
if (message != null) _reportPost(post, message);
126+
).then((message) {
127+
if (message == null) return;
128+
_reportPost(post, message);
129+
});
124130
break;
125131
}
126132
},

macos/Runner.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@
262262
isa = PBXProject;
263263
attributes = {
264264
LastSwiftUpdateCheck = 0920;
265-
LastUpgradeCheck = 1300;
265+
LastUpgradeCheck = 1430;
266266
ORGANIZATIONNAME = "";
267267
TargetAttributes = {
268268
331C80D4294CF70F00263BE5 = {

macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1300"
3+
LastUpgradeVersion = "1430"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:package_info_plus/package_info_plus.dart';
4+
import 'package:provider/provider.dart';
5+
import 'package:the_app/src/widgets/menu/dev_tools.dart';
6+
import 'package:the_app/src/widgets/menu/package_info.dart';
7+
8+
import '../../../test_utils.dart';
9+
10+
void main() {
11+
group('PackageInfoWidget', () {
12+
const version = '1.0.0';
13+
const buildNumber = '2';
14+
15+
setUp(() {
16+
PackageInfo.setMockInitialValues(
17+
appName: 'appName',
18+
packageName: 'packageName',
19+
version: version,
20+
buildNumber: buildNumber,
21+
buildSignature: "buildSignature",
22+
);
23+
});
24+
25+
testWidgets('show about dialog on tap', (tester) async {
26+
final devTools = _MockedDevTools();
27+
await tester.pumpMockedApiApp(
28+
ChangeNotifierProvider<DevTools>.value(
29+
value: devTools,
30+
child: const PackageInfoWidget(),
31+
),
32+
);
33+
34+
await tester.tap(find.text('Version'));
35+
await tester.pumpAndSettle();
36+
37+
expect(devTools.isDeveloper, isFalse);
38+
final target = find.text('$version (build number: $buildNumber)');
39+
await tester.tap(target);
40+
await tester.pumpAndSettle();
41+
expect(devTools.isDeveloper, isFalse);
42+
43+
await tester.tap(target);
44+
await tester.pumpAndSettle();
45+
expect(devTools.isDeveloper, isFalse);
46+
47+
// third tap enables developer mode
48+
await tester.tap(target);
49+
await tester.pumpAndSettle();
50+
expect(devTools.isDeveloper, isTrue);
51+
52+
// the next one disables it again
53+
await tester.tap(target);
54+
await tester.pumpAndSettle();
55+
expect(devTools.isDeveloper, isFalse);
56+
});
57+
});
58+
}
59+
60+
class _MockedDevTools extends ChangeNotifier implements DevTools {
61+
@override
62+
var isDeveloper = false;
63+
64+
@override
65+
var showPerformanceOverlay = false;
66+
}

0 commit comments

Comments
 (0)