Display a coach mark to nudge the user to swipe left

This commit is contained in:
vishnukvmd 2022-11-23 16:26:29 +05:30
parent 8e5488eaf9
commit 9bcd107de8
3 changed files with 105 additions and 2 deletions

View file

@ -8,6 +8,7 @@ import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/services/authenticator_service.dart';
import 'package:ente_auth/services/billing_service.dart';
import 'package:ente_auth/services/notification_service.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/services/update_service.dart';
import 'package:ente_auth/services/user_remote_flag_service.dart';
import 'package:ente_auth/services/user_service.dart';
@ -60,6 +61,7 @@ Future _runWithLogs(Function() function, {String prefix = ""}) async {
Future<void> _init(bool bool, {String via}) async {
InAppPurchaseConnection.enablePendingPurchases();
CryptoUtil.init();
await PreferenceService.instance.init();
await CodeStore.instance.init();
await Configuration.instance.init();
await Network.instance.init();

View file

@ -0,0 +1,27 @@
import 'package:shared_preferences/shared_preferences.dart';
class PreferenceService {
PreferenceService._privateConstructor();
static final PreferenceService instance =
PreferenceService._privateConstructor();
late final SharedPreferences _prefs;
static const kHasShownCoachMarkKey = "has_shown_coach_mark";
Future<void> init() async {
_prefs = await SharedPreferences.getInstance();
}
bool hasShownCoachMark() {
if (_prefs.containsKey(kHasShownCoachMarkKey)) {
return _prefs.getBool(kHasShownCoachMarkKey)!;
} else {
return false;
}
}
Future<void> setHasShownCoachMark(bool value) {
return _prefs.setBool(kHasShownCoachMarkKey, value);
}
}

View file

@ -2,6 +2,7 @@
import 'dart:async';
import 'dart:io';
import 'dart:ui';
import 'package:ente_auth/core/event_bus.dart';
import 'package:ente_auth/ente_theme_data.dart';
@ -9,6 +10,7 @@ import 'package:ente_auth/events/codes_updated_event.dart';
import "package:ente_auth/l10n/l10n.dart";
import 'package:ente_auth/models/code.dart';
import 'package:ente_auth/onboarding/view/setup_enter_secret_key_page.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/services/user_service.dart';
import 'package:ente_auth/store/code_store.dart';
import 'package:ente_auth/ui/code_widget.dart';
@ -121,7 +123,11 @@ class _HomePageState extends State<HomePage> {
appBar: AppBar(
title: const Text('ente Authenticator'),
),
floatingActionButton: !_hasLoaded || _codes.isEmpty ? null : _getFab(),
floatingActionButton: !_hasLoaded ||
_codes.isEmpty ||
!PreferenceService.instance.hasShownCoachMark()
? null
: _getFab(),
),
);
}
@ -131,12 +137,22 @@ class _HomePageState extends State<HomePage> {
if (_codes.isEmpty) {
return _getEmptyState();
} else {
return ListView.builder(
final list = ListView.builder(
itemBuilder: ((context, index) {
return CodeWidget(_codes[index]);
}),
itemCount: _codes.length,
);
if (!PreferenceService.instance.hasShownCoachMark()) {
return Stack(
children: [
list,
_getCoachMarkWidget(),
],
);
} else {
return list;
}
}
} else {
return const EnteLoadingWidget();
@ -222,6 +238,64 @@ class _HomePageState extends State<HomePage> {
),
);
}
Widget _getCoachMarkWidget() {
return GestureDetector(
onTap: () async {
await PreferenceService.instance.setHasShownCoachMark(true);
setState(() {});
},
child: Row(
children: [
Expanded(
child: Container(
width: double.infinity,
color: Theme.of(context).colorScheme.background.withOpacity(0.1),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.swipe_left,
size: 42,
),
const SizedBox(
height: 24,
),
Text(
"Swipe left to edit or remove codes",
style: Theme.of(context).textTheme.headline6,
),
const SizedBox(
height: 36,
),
SizedBox(
width: 160,
child: OutlinedButton(
onPressed: () async {
await PreferenceService.instance
.setHasShownCoachMark(true);
setState(() {});
},
child: const Text("OK"),
),
)
],
),
],
),
),
),
),
],
),
);
}
}
class SpeedDialLabelWidget extends StatelessWidget {