mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 00:52:12 +00:00
improve faq
This commit is contained in:
parent
4a8fbdce28
commit
81370d27a9
6 changed files with 91 additions and 22 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit 24d048b4abbe5c266b09965cc6f3ebdf83f97855
|
||||
Subproject commit 4e6d3eb9b7602030bf3d4b6dcb92ecc0f23de386
|
||||
|
|
@ -2,11 +2,13 @@
|
|||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:twonly/src/visual/views/settings/help/faq/faq_markdown.view.dart';
|
||||
|
||||
class FaqView extends StatefulWidget {
|
||||
const FaqView({super.key});
|
||||
|
|
@ -19,7 +21,7 @@ class _FaqViewState extends State<FaqView> {
|
|||
Map<String, dynamic>? _faqData;
|
||||
String? _locale;
|
||||
late String domain;
|
||||
bool noInternet = false;
|
||||
bool _noInternet = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -29,30 +31,40 @@ class _FaqViewState extends State<FaqView> {
|
|||
}
|
||||
|
||||
Future<void> _fetchFAQData() async {
|
||||
final cacheFile = File('${AppEnvironment.cacheDir}/faq.json');
|
||||
try {
|
||||
final response = await http.get(Uri.parse('$domain/faq.json'));
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final jsonData = utf8.decode(response.bodyBytes);
|
||||
setState(() {
|
||||
_faqData =
|
||||
json.decode(utf8.decode(response.bodyBytes))
|
||||
as Map<String, dynamic>?;
|
||||
noInternet = false;
|
||||
_faqData = json.decode(jsonData) as Map<String, dynamic>?;
|
||||
|
||||
_noInternet = false;
|
||||
});
|
||||
cacheFile.writeAsStringSync(jsonData);
|
||||
} else {
|
||||
Log.error('FAQ got ${response.statusCode}');
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
setState(() {
|
||||
noInternet = true;
|
||||
_noInternet = true;
|
||||
});
|
||||
}
|
||||
if (_noInternet && cacheFile.existsSync()) {
|
||||
final jsonData = cacheFile.readAsStringSync();
|
||||
setState(() {
|
||||
_faqData = json.decode(jsonData) as Map<String, dynamic>?;
|
||||
|
||||
_noInternet = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (noInternet) {
|
||||
if (_noInternet) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(context.lang.settingsHelpFAQ),
|
||||
|
|
@ -73,26 +85,39 @@ class _FaqViewState extends State<FaqView> {
|
|||
}
|
||||
|
||||
final faq = _faqData![_locale ?? 'en'] as Map;
|
||||
final sortedCategories = faq.entries.toList()
|
||||
..sort((a, b) {
|
||||
final aPriority = (a.value['meta']['priority'] as num? ?? 0).toInt();
|
||||
final bPriority = (b.value['meta']['priority'] as num? ?? 0).toInt();
|
||||
return bPriority.compareTo(aPriority);
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(context.lang.settingsHelpFAQ),
|
||||
),
|
||||
body: ListView.builder(
|
||||
itemCount: faq.keys.length,
|
||||
itemCount: sortedCategories.length,
|
||||
itemBuilder: (context, index) {
|
||||
final category = faq.keys.elementAt(index);
|
||||
final categoryData = faq[category];
|
||||
final categoryData = sortedCategories[index].value;
|
||||
|
||||
return Card(
|
||||
child: ExpansionTile(
|
||||
title: Text(categoryData['meta']['title'] as String),
|
||||
subtitle: Text(categoryData['meta']['desc'] as String),
|
||||
shape: const RoundedRectangleBorder(),
|
||||
backgroundColor: context.color.surfaceContainer,
|
||||
collapsedShape: const RoundedRectangleBorder(),
|
||||
children:
|
||||
categoryData['questions'].map<Widget>((question) {
|
||||
return ListTile(
|
||||
title: Text(question['title'] as String),
|
||||
onTap: () => _launchURL(question['path'] as String),
|
||||
onTap: () => context.navPush(
|
||||
FaqMarkdownView(
|
||||
markdown: question['body'] as String,
|
||||
title: question['title'] as String,
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList()
|
||||
as List<Widget>,
|
||||
|
|
@ -102,12 +127,4 @@ class _FaqViewState extends State<FaqView> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _launchURL(String path) async {
|
||||
try {
|
||||
await launchUrl(Uri.parse('$domain$path'));
|
||||
} catch (e) {
|
||||
Log.error('Could not launch $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
|
||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||
|
||||
class FaqMarkdownView extends StatelessWidget {
|
||||
const FaqMarkdownView({
|
||||
required this.markdown,
|
||||
required this.title,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final String markdown;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(substringBy(title, 30)),
|
||||
),
|
||||
body: Markdown(
|
||||
data: markdown,
|
||||
padding: const EdgeInsets.only(
|
||||
top: 16,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 40,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,9 @@ import 'dart:async';
|
|||
import 'package:drift/drift.dart' show Value;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/constants/routes.keys.dart';
|
||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||
import 'package:twonly/src/database/twonly.db.dart';
|
||||
import 'package:twonly/src/model/protobuf/client/generated/user_discovery/types.pb.dart';
|
||||
|
|
@ -160,7 +162,7 @@ class _UserDiscoveryEnabledCompState extends State<UserDiscoveryEnabledComp> {
|
|||
subtitle: Text(
|
||||
context.lang.userDiscoveryEnabledFaq,
|
||||
),
|
||||
// onTap: _disableUserDiscovery,
|
||||
onTap: () => context.push(Routes.settingsHelpFaq),
|
||||
),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
|
|
|
|||
15
pubspec.lock
15
pubspec.lock
|
|
@ -760,6 +760,13 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_markdown_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "dependencies/flutter_markdown_plus"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.7"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1261,6 +1268,14 @@ packages:
|
|||
relative: true
|
||||
source: path
|
||||
version: "3.3.2"
|
||||
markdown:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: markdown
|
||||
sha256: ee85086ad7698b42522c6ad42fe195f1b9898e4d974a1af4576c1a3a176cada9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.3.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ dependencies:
|
|||
hand_signature: ^3.0.3
|
||||
flutter_sharing_intent: ^2.0.4
|
||||
no_screenshot: ^0.3.1
|
||||
flutter_markdown_plus: ^1.0.7
|
||||
|
||||
# With high download. (But should be checked nonetheless.)
|
||||
app_links: ^7.0.0 # 1.6 mio
|
||||
|
|
@ -153,6 +154,8 @@ dependency_overrides:
|
|||
path: ./dependencies/qr_flutter
|
||||
no_screenshot:
|
||||
path: ./dependencies/no_screenshot
|
||||
flutter_markdown_plus:
|
||||
path: ./dependencies/flutter_markdown_plus
|
||||
camera_android_camerax:
|
||||
# path: ../flutter-packages/packages/camera/camera_android_camerax
|
||||
git:
|
||||
|
|
|
|||
Loading…
Reference in a new issue