added welcome page with terms of service

This commit is contained in:
Thibault Deckers 2020-06-10 13:35:22 +09:00
parent b92545f059
commit c002291adf
7 changed files with 165 additions and 6 deletions

View file

@ -8,6 +8,7 @@ import 'package:aves/widgets/album/collection_page.dart';
import 'package:aves/widgets/common/data_providers/media_store_collection_provider.dart';
import 'package:aves/widgets/common/icons.dart';
import 'package:aves/widgets/fullscreen/fullscreen_page.dart';
import 'package:aves/widgets/welcome.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -26,9 +27,22 @@ void main() {
enum AppMode { main, pick, view }
class AvesApp extends StatelessWidget {
class AvesApp extends StatefulWidget {
static AppMode mode = AppMode.main;
@override
_AvesAppState createState() => _AvesAppState();
}
class _AvesAppState extends State<AvesApp> {
Future<void> _appSetup;
@override
void initState() {
super.initState();
_appSetup = settings.init();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
@ -50,7 +64,14 @@ class AvesApp extends StatelessWidget {
),
),
),
home: const HomePage(),
home: FutureBuilder(
future: _appSetup,
builder: (context, AsyncSnapshot<void> snapshot) {
if (snapshot.hasError) return const Icon(AIcons.error);
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
return settings.hasAcceptedTerms ? const HomePage() : const WelcomePage();
},
),
);
}
}
@ -69,7 +90,6 @@ class _HomePageState extends State<HomePage> {
@override
void initState() {
debugPrint('$runtimeType initState');
super.initState();
_appSetup = _setup();
imageCache.maximumSizeBytes = 512 * (1 << 20);
@ -93,8 +113,6 @@ class _HomePageState extends State<HomePage> {
// TODO notify when icons are ready for drawer and section header refresh
await androidFileUtils.init(); // 170ms
await settings.init(); // <20ms
final intentData = await ViewerService.getIntentData();
if (intentData != null) {
final action = intentData['action'];

View file

@ -20,6 +20,7 @@ class Settings {
static const collectionTileExtentKey = 'collection_tile_extent';
static const infoMapZoomKey = 'info_map_zoom';
static const catalogTimeZoneKey = 'catalog_time_zone';
static const hasAcceptedTermsKey = 'has_accepted_terms';
Future<void> init() async {
_prefs = await SharedPreferences.getInstance();
@ -69,6 +70,10 @@ class Settings {
set collectionTileExtent(double newValue) => setAndNotify(collectionTileExtentKey, newValue);
bool get hasAcceptedTerms => getBoolOrDefault(hasAcceptedTermsKey, false);
set hasAcceptedTerms(bool newValue) => setAndNotify(hasAcceptedTermsKey, newValue);
// convenience methods
bool getBoolOrDefault(String key, bool defaultValue) => _prefs.getKeys().contains(key) ? _prefs.getBool(key) : defaultValue;

15
lib/model/terms.dart Normal file
View file

@ -0,0 +1,15 @@
const String termsAndConditions = '''
# Terms of Service
Aves is an open-source gallery and metadata explorer app allowing you to access and manage your local photos.
You must use the app for legal, authorized and acceptable purposes.
# Privacy policy
Aves does not collect any personal data in its standard use. We never have access to your photos and videos. This also means that we cannot get them back for you if you delete them without backing them up.
__We collect anonymous data to improve the app.__ We use Google Firebase for Analytics and Crash Reporting, and the anonymous analytics data are stored on their servers. Please note that those are anonymous data, there is absolutely nothing personal about those data.
## Links
[Sources](https://github.com/deckerst/aves)
''';

View file

@ -107,6 +107,12 @@ class Constants {
licenseUrl: 'https://github.com/CaiJingLong/flutter_ijkplayer/blob/master/LICENSE',
sourceUrl: 'https://github.com/CaiJingLong/flutter_ijkplayer',
),
Dependency(
name: 'Flutter Markdown',
license: 'BSD 3-Clause',
licenseUrl: 'https://github.com/flutter/flutter_markdown/blob/master/LICENSE',
sourceUrl: 'https://github.com/flutter/flutter_markdown',
),
Dependency(
name: 'Flutter Native Timezone',
license: 'Apache 2.0',

100
lib/widgets/welcome.dart Normal file
View file

@ -0,0 +1,100 @@
import 'package:aves/main.dart';
import 'package:aves/model/settings.dart';
import 'package:aves/model/terms.dart';
import 'package:aves/widgets/common/aves_logo.dart';
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:url_launcher/url_launcher.dart';
class WelcomePage extends StatefulWidget {
const WelcomePage();
@override
_WelcomePageState createState() => _WelcomePageState();
}
class _WelcomePageState extends State<WelcomePage> {
bool _hasAcceptedTerms = false;
@override
Widget build(BuildContext context) {
final accentColor = Theme.of(context).accentColor;
return Scaffold(
body: SafeArea(
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const AvesLogo(size: 64),
const SizedBox(height: 16),
const Text(
'Welcome to Aves',
style: TextStyle(
fontSize: 22,
fontFamily: 'Concourse',
),
),
const SizedBox(height: 16),
Flexible(
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white10,
),
child: SingleChildScrollView(
child: Container(
child: MarkdownBody(
data: termsAndConditions,
onTapLink: (url) async {
if (await canLaunch(url)) {
await launch(url);
}
},
), // const Text('Terms terms terms'),
),
),
),
),
Text.rich(
TextSpan(
children: [
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Checkbox(
value: _hasAcceptedTerms,
onChanged: (v) => setState(() => _hasAcceptedTerms = v),
activeColor: accentColor,
),
),
const TextSpan(
text: 'I accept the Terms of Service',
),
],
),
),
RaisedButton(
color: accentColor,
child: const Text('Continue'),
onPressed: _hasAcceptedTerms
? () {
settings.hasAcceptedTerms = true;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => const HomePage(),
),
(route) => false,
);
}
: null,
),
],
),
),
),
);
}
}

View file

@ -125,6 +125,13 @@ packages:
relative: true
source: path
version: "0.3.6"
flutter_markdown:
dependency: "direct main"
description:
name: flutter_markdown
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.1"
flutter_native_timezone:
dependency: "direct main"
description:
@ -212,6 +219,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.4"
markdown:
dependency: transitive
description:
name: markdown
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
matcher:
dependency: transitive
description:
@ -555,4 +569,4 @@ packages:
version: "3.6.1"
sdks:
dart: ">=2.7.2 <3.0.0"
flutter: ">=1.16.3 <2.0.0"
flutter: ">=1.17.0 <2.0.0"

View file

@ -53,6 +53,7 @@ dependencies:
path: ../flutter_ijkplayer
# git:
# url: git://github.com/deckerst/flutter_ijkplayer.git
flutter_markdown:
flutter_native_timezone:
flutter_staggered_animations:
flutter_svg: