Skip to content

Commit 2ad701f

Browse files
authored
Fix Windows report issue and pro account routing (#8856)
* Fix Windows report issue and pro account routing * code review updates
1 parent daa7335 commit 2ad701f

5 files changed

Lines changed: 109 additions & 37 deletions

File tree

lantern-core/ffi/ffi.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ func reportIssue(
341341
logPath,
342342
attachmentsJSON,
343343
); err != nil {
344-
return C.CString(fmt.Sprintf("error reporting issue: %v", err))
344+
return SendError(fmt.Errorf("error reporting issue: %w", err))
345345
}
346346
return C.CString("ok")
347347
})

lib/core/utils/pro_utils.dart

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,45 @@
11
import 'package:flutter/material.dart';
22
import 'package:lantern/core/common/common.dart';
3+
import 'package:lantern/core/extensions/user_data.dart';
4+
import 'package:lantern/core/models/user.dart';
5+
6+
bool hasRegisteredProAccount(UserResponseModel? user) {
7+
final userData = user?.legacyUserData;
8+
return userData != null && userData.isPro && userData.unpassRegistered;
9+
}
10+
11+
bool shouldShowProAccountSetupDialog({
12+
required UserResponseModel user,
13+
required bool userLoggedIn,
14+
}) {
15+
final userData = user.legacyUserData;
16+
return userData.isPro && !userLoggedIn && !userData.unpassRegistered;
17+
}
18+
19+
Future<void> openAccountOrProAccountSetup({
20+
required BuildContext context,
21+
required UserResponseModel? user,
22+
required bool userLoggedIn,
23+
}) async {
24+
if (user == null) {
25+
appLogger.warning(
26+
'Unable to open account because user data is unavailable',
27+
);
28+
context.showSnackBarError('it_looks_like_something_went_wrong'.i18n);
29+
return;
30+
}
31+
32+
final userData = user.legacyUserData;
33+
if (shouldShowProAccountSetupDialog(user: user, userLoggedIn: userLoggedIn)) {
34+
await showProAccountFlowDialog(
35+
context: context,
36+
hasEmail: userData.email.isNotEmpty,
37+
);
38+
return;
39+
}
40+
41+
appRouter.push(Account());
42+
}
343

444
Future<void> showProAccountFlowDialog({
545
required BuildContext context,
@@ -22,9 +62,9 @@ Future<void> showProAccountFlowDialog({
2262
hasEmail
2363
? 'set_account_password_message'.i18n
2464
: 'update_pro_account_message'.i18n,
25-
style: Theme.of(context).textTheme.bodySmall!.copyWith(
26-
color: context.textSecondary,
27-
),
65+
style: Theme.of(
66+
context,
67+
).textTheme.bodySmall!.copyWith(color: context.textSecondary),
2868
),
2969
],
3070
),

lib/features/home/home.dart

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
44
import 'package:flutter_screenutil/flutter_screenutil.dart';
55
import 'package:hooks_riverpod/hooks_riverpod.dart';
66
import 'package:lantern/core/common/app_text_styles.dart';
7-
import 'package:lantern/core/extensions/user_data.dart';
87
import 'package:lantern/core/models/feature_flags.dart';
98
import 'package:lantern/core/utils/pro_utils.dart';
109
import 'package:lantern/core/widgets/info_row.dart';
@@ -122,18 +121,11 @@ class _HomeState extends ConsumerState<Home> {
122121
onPressed: () async {
123122
final localUser = ref.read(homeProvider).value;
124123
final userSignedIn = ref.read(appSettingProvider).userLoggedIn;
125-
final email = localUser!.legacyUserData.email;
126-
final isPro = localUser.legacyUserData.isPro;
127-
if (isPro && !userSignedIn) {
128-
// this means user has pro account but not signed in
129-
await showProAccountFlowDialog(
130-
context: context,
131-
hasEmail: email.isNotEmpty,
132-
);
133-
return;
134-
}
135-
136-
appRouter.push(Account());
124+
await openAccountOrProAccountSetup(
125+
context: context,
126+
user: localUser,
127+
userLoggedIn: userSignedIn,
128+
);
137129
},
138130
)
139131
else if (!userLoggedIn)

lib/features/setting/setting.dart

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import 'package:auto_route/auto_route.dart';
22
import 'package:flutter/material.dart';
33
import 'package:hooks_riverpod/hooks_riverpod.dart';
44
import 'package:lantern/core/common/common.dart';
5-
import 'package:lantern/core/extensions/user_data.dart';
65
import 'package:lantern/core/localization/localization_constants.dart';
76
import 'package:lantern/core/updater/updater.dart';
87
import 'package:lantern/core/utils/pro_utils.dart';
@@ -62,9 +61,7 @@ class _SettingState extends ConsumerState<Setting>
6261

6362
final appSetting = ref.watch(appSettingProvider);
6463

65-
final hasProSession =
66-
(user?.legacyUserData.isPro ?? false) &&
67-
(user?.legacyUserData.unpassRegistered ?? false);
64+
final hasProSession = hasRegisteredProAccount(user);
6865

6966
final isAuthenticated = appSetting.userLoggedIn || hasProSession;
7067

@@ -296,23 +293,12 @@ class _SettingState extends ConsumerState<Setting>
296293

297294
case _SettingType.account:
298295
final user = ref.read(homeProvider).value;
299-
if (user == null) {
300-
appRouter.push(const SignInEmail());
301-
return;
302-
}
303-
304296
final userSignedIn = ref.read(appSettingProvider).userLoggedIn;
305-
final email = user.legacyUserData.email;
306-
final isPro = user.legacyUserData.isPro;
307-
if (isPro && !userSignedIn) {
308-
await showProAccountFlowDialog(
309-
context: context,
310-
hasEmail: email.isNotEmpty,
311-
);
312-
return;
313-
}
314-
315-
appRouter.push(Account());
297+
await openAccountOrProAccountSetup(
298+
context: context,
299+
user: user,
300+
userLoggedIn: userSignedIn,
301+
);
316302
break;
317303
case _SettingType.vpnSetting:
318304
appRouter.push(VPNSetting());
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:lantern/core/models/user.dart';
3+
import 'package:lantern/core/utils/pro_utils.dart';
4+
5+
void main() {
6+
group('Pro account helpers', () {
7+
UserResponseModel user({
8+
String userLevel = 'pro',
9+
bool unpassRegistered = false,
10+
}) {
11+
return UserResponseModel(
12+
legacyID: 1,
13+
legacyToken: 'token',
14+
emailConfirmed: true,
15+
success: true,
16+
legacyUserData: UserDataModel(
17+
email: 'person@example.com',
18+
userLevel: userLevel,
19+
unpassRegistered: unpassRegistered,
20+
),
21+
);
22+
}
23+
24+
test('detects locally registered Pro accounts', () {
25+
expect(hasRegisteredProAccount(user(unpassRegistered: true)), isTrue);
26+
expect(hasRegisteredProAccount(user()), isFalse);
27+
expect(
28+
hasRegisteredProAccount(
29+
user(userLevel: 'free', unpassRegistered: true),
30+
),
31+
isFalse,
32+
);
33+
expect(hasRegisteredProAccount(null), isFalse);
34+
});
35+
36+
test('shows setup only for unregistered signed-out Pro accounts', () {
37+
expect(
38+
shouldShowProAccountSetupDialog(user: user(), userLoggedIn: false),
39+
isTrue,
40+
);
41+
expect(
42+
shouldShowProAccountSetupDialog(
43+
user: user(unpassRegistered: true),
44+
userLoggedIn: false,
45+
),
46+
isFalse,
47+
);
48+
expect(
49+
shouldShowProAccountSetupDialog(user: user(), userLoggedIn: true),
50+
isFalse,
51+
);
52+
});
53+
});
54+
}

0 commit comments

Comments
 (0)