Skip to content

Commit d1f75ab

Browse files
authored
feat: update forum dialogue to be the same as the main website (#1572)
* feat(dialog): add new forum dialog * feat: refactor forum help dialog and link generation in LearnService * feat(dialog): update dialog types for asking for help * feat(dialog): update colors in ask for help dialog for better visibility * feat: refactor learn service and helper functions for improved code organization
1 parent 884117b commit d1f75ab

File tree

6 files changed

+530
-61
lines changed

6 files changed

+530
-61
lines changed
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
enum DialogType {
22
basic,
33
buttonForm,
4-
deleteAccount
4+
deleteAccount,
5+
askForHelp,
6+
askForHelpInput
57
}

mobile-app/lib/service/learn/learn_service.dart

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:developer';
22

33
import 'package:dio/dio.dart';
4+
import 'package:flutter/material.dart';
45
import 'package:freecodecamp/app/app.locator.dart';
56
import 'package:freecodecamp/app/app.router.dart';
67
import 'package:freecodecamp/enums/dialog_type.dart';
@@ -9,10 +10,13 @@ import 'package:freecodecamp/models/learn/curriculum_model.dart';
910
import 'package:freecodecamp/service/authentication/authentication_service.dart';
1011
import 'package:freecodecamp/service/dio_service.dart';
1112
import 'package:freecodecamp/service/learn/learn_offline_service.dart';
13+
import 'package:freecodecamp/utils/helpers.dart';
1214
import 'package:shared_preferences/shared_preferences.dart';
1315
import 'package:stacked_services/stacked_services.dart';
1416
import 'package:url_launcher/url_launcher.dart';
1517

18+
const forumLocation = 'https://forum.freecodecamp.org';
19+
1620
class LearnService {
1721
static final LearnService _learnService = LearnService._internal();
1822
final _authenticationService = locator<AuthenticationService>();
@@ -160,16 +164,82 @@ class LearnService {
160164
}
161165
}
162166

163-
Future forumHelpDialog(String url) async {
167+
Future<String> genForumLink(
168+
Challenge challenge,
169+
Block block,
170+
String description,
171+
BuildContext context, {
172+
String editorText = '',
173+
}) async {
174+
Challenge? currChallenge = challenge;
175+
176+
final HelpCategory helpCategory = challenge.helpCategory;
177+
final String blockTitle = block.name;
178+
179+
final userDeviceInfo = await getDeviceInfo(context);
180+
181+
final titleText = '$blockTitle - ${currChallenge.title}';
182+
final String endingText =
183+
'**Your mobile information:**\n```txt\n$userDeviceInfo\n```\n\n**Challenge:** $titleText\n\n**Link to the challenge:**\nhttps://www.freecodecamp.org/learn/${currChallenge.superBlock}/${currChallenge.block}/${currChallenge.dashedName}';
184+
185+
final String userCode = await filesToMarkdown(currChallenge, editorText);
186+
187+
final String textMessage =
188+
"**Tell us what's happening:**\nDescribe your issue in detail here. \n\n$description \n\n**Your code so far**$userCode\n\n$endingText";
189+
final String altTextMessage =
190+
"**Tell us what's happening:**\n\n\n\n**Your code so far**\n\nWARNING\n\nThe challenge seed code and/or your solution exceeded the maximum length we can port over from the challenge.\n\nYou will need to take an additional step here so the code you wrote presents in an easy to read format.\n\nPlease copy/paste all the editor code showing in the challenge from where you just linked.\n\n```\nReplace these two sentences with your copied code.\nPlease leave the ``` line above and the ``` line below,\nbecause they allow your code to properly format in the post.\n\n```\n$endingText";
191+
192+
String studentCode = Uri.encodeComponent(textMessage);
193+
String altStudentCode = Uri.encodeComponent(altTextMessage);
194+
195+
final String baseURL =
196+
'$forumLocation/new-topic?category=${helpCategory.value}&title=$titleText&body=';
197+
final String defaultURL = '$baseURL$studentCode';
198+
final String altURL = '$baseURL$altStudentCode';
199+
200+
return defaultURL.length < 8000 ? defaultURL : altURL;
201+
}
202+
203+
Future forumHelpDialog(
204+
Challenge challenge,
205+
Block block,
206+
BuildContext context,
207+
) async {
164208
DialogResponse? res = await _dialogService.showCustomDialog(
165209
barrierDismissible: true,
166-
variant: DialogType.buttonForm,
210+
variant: DialogType.askForHelp,
167211
title: 'Ask for Help',
168212
description:
169213
"If you've already tried the Read-Search-Ask method, then you can try asking for help on the freeCodeCamp forum.",
170-
mainButtonTitle: 'Create a post');
214+
mainButtonTitle: 'Create a post',
215+
data: {'challengeName': challenge.title, 'blockName': block.name});
171216
if (res != null && res.confirmed) {
172-
launchUrl(Uri.parse(url));
217+
DialogResponse? forumRes = await _dialogService.showCustomDialog(
218+
variant: DialogType.askForHelpInput,
219+
title: 'Create a post',
220+
description:
221+
'You must confirm the following statements before you can submit your post to the forum.',
222+
mainButtonTitle: 'Submit',
223+
secondaryButtonTitle: 'Cancel',
224+
data: {'challengeName': challenge.title, 'blockName': block.name},
225+
);
226+
227+
String description = forumRes?.data ?? '';
228+
229+
if (forumRes != null && forumRes.confirmed) {
230+
try {
231+
final forumLink = await genForumLink(
232+
challenge,
233+
block,
234+
description,
235+
context,
236+
);
237+
238+
await launchUrl(Uri.parse(forumLink));
239+
} catch (e) {
240+
log('Error launching forum link: $e');
241+
}
242+
}
173243
}
174244
}
175245

mobile-app/lib/ui/views/learn/challenge/templates/python-project/python_project_view.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import 'package:freecodecamp/extensions/i18n_extension.dart';
33
import 'package:freecodecamp/models/learn/challenge_model.dart';
44
import 'package:freecodecamp/models/learn/curriculum_model.dart';
55
import 'package:freecodecamp/ui/views/learn/challenge/templates/python-project/python_project_viewmodel.dart';
6-
import 'package:freecodecamp/ui/views/learn/widgets/hint/hint_widget_view.dart';
76
import 'package:freecodecamp/ui/views/news/html_handler/html_handler.dart';
87
import 'package:freecodecamp/ui/widgets/drawer_widget/drawer_widget_view.dart';
98
import 'package:stacked/stacked.dart';
@@ -153,12 +152,11 @@ class PythonProjectView extends StatelessWidget {
153152
),
154153
),
155154
onPressed: () async {
156-
final forumLink = await genForumLink(
155+
model.learnService.forumHelpDialog(
157156
challenge,
158157
block,
159158
context,
160159
);
161-
model.learnService.forumHelpDialog(forumLink);
162160
},
163161
child: Text(
164162
context.t.ask_for_help,

mobile-app/lib/ui/views/learn/widgets/hint/hint_widget_view.dart

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,15 @@
1-
import 'dart:io';
2-
3-
import 'package:device_info_plus/device_info_plus.dart';
41
import 'package:flutter/material.dart';
52
import 'package:freecodecamp/extensions/i18n_extension.dart';
63
import 'package:freecodecamp/models/learn/challenge_model.dart';
74
import 'package:freecodecamp/models/learn/curriculum_model.dart';
5+
import 'package:freecodecamp/service/learn/learn_service.dart';
86
import 'package:freecodecamp/ui/views/learn/challenge/challenge_viewmodel.dart';
97
import 'package:freecodecamp/ui/views/learn/widgets/hint/hint_widget_model.dart';
108
import 'package:freecodecamp/ui/views/news/html_handler/html_handler.dart';
9+
import 'package:freecodecamp/utils/helpers.dart';
1110
import 'package:phone_ide/phone_ide.dart';
12-
import 'package:shared_preferences/shared_preferences.dart';
1311
import 'package:stacked/stacked.dart';
1412

15-
const forumLocation = 'https://forum.freecodecamp.org';
16-
17-
Future<String> filesToMarkdown(
18-
Challenge challenge,
19-
String editorText,
20-
) async {
21-
SharedPreferences prefs = await SharedPreferences.getInstance();
22-
final challengeFiles = challenge.files;
23-
final bool moreThanOneFile = challengeFiles.length > 1;
24-
String markdownStr = '\n';
25-
26-
for (var challengeFile in challengeFiles) {
27-
final fileName = moreThanOneFile
28-
? '/* file: ${challengeFile.name}.${challengeFile.ext} */\n'
29-
: '';
30-
final fileType = challengeFile.ext.name;
31-
final fileContent =
32-
prefs.getString('${challenge.id}.${challengeFile.name}') ??
33-
challengeFile.contents;
34-
markdownStr += '```$fileType\n$fileName$fileContent\n```\n\n';
35-
}
36-
37-
return markdownStr;
38-
}
39-
40-
Future<String> getDeviceInfo(BuildContext context) async {
41-
final deviceInfoPlugin = DeviceInfoPlugin();
42-
43-
if (Platform.isAndroid) {
44-
final deviceInfo = await deviceInfoPlugin.androidInfo;
45-
return '${deviceInfo.model} - Android ${deviceInfo.version.release} - Android SDK ${deviceInfo.version.sdkInt}';
46-
} else if (Platform.isIOS) {
47-
final deviceInfo = await deviceInfoPlugin.iosInfo;
48-
return '${deviceInfo.model} - ${deviceInfo.systemName}${deviceInfo.systemVersion}';
49-
} else {
50-
return context.t.unrecognized_device;
51-
}
52-
}
53-
5413
Future<String> genForumLink(
5514
Challenge challenge,
5615
Block block,
@@ -141,12 +100,11 @@ class HintWidgetView extends StatelessWidget {
141100
children: [
142101
IconButton(
143102
onPressed: () async {
144-
final forumLink = await genForumLink(
145-
challengeModel.challenge as Challenge,
146-
challengeModel.block as Block,
147-
context,
148-
editorText: challengeModel.editorText ?? '');
149-
challengeModel.learnService.forumHelpDialog(forumLink);
103+
challengeModel.learnService.forumHelpDialog(
104+
challengeModel.challenge as Challenge,
105+
challengeModel.block as Block,
106+
context,
107+
);
150108
},
151109
icon: const Icon(Icons.question_mark),
152110
padding: const EdgeInsets.all(16),

0 commit comments

Comments
 (0)