Allow configuring the Home Screen

It can either be the Folders view or the All Notes view.
This commit is contained in:
Vishesh Handa
2020-05-08 19:30:25 +02:00
parent cc45894a07
commit faf561f104
8 changed files with 137 additions and 62 deletions

View File

@ -13,6 +13,7 @@ settings:
display: display:
title: Display Settings title: Display Settings
darkTheme: Dark Theme darkTheme: Dark Theme
homeScreen: Home Screen
gitAuthor: Git Author Settings gitAuthor: Git Author Settings
versionInfo: Version Info versionInfo: Version Info
analytics: Analytics analytics: Analytics
@ -23,3 +24,4 @@ settings:
editors: editors:
checklist: checklist:
add: Add Item add: Add Item
pro: Pro

View File

@ -143,6 +143,9 @@ class JournalApp extends StatelessWidget {
if (!stateContainer.appState.onBoardingCompleted) { if (!stateContainer.appState.onBoardingCompleted) {
initialRoute = '/onBoarding'; initialRoute = '/onBoarding';
} }
if (Settings.instance.homeScreen == SettingsHomeScreen.AllFolders) {
initialRoute = '/folders';
}
return MaterialApp( return MaterialApp(
key: const ValueKey("App"), key: const ValueKey("App"),

View File

@ -1,3 +1,4 @@
import 'package:gitjournal/app.dart';
import 'package:gitjournal/utils/logger.dart'; import 'package:gitjournal/utils/logger.dart';
import 'package:purchases_flutter/purchases_flutter.dart'; import 'package:purchases_flutter/purchases_flutter.dart';
@ -13,6 +14,10 @@ class InAppPurchases {
return; return;
} }
if (JournalApp.isInDebugMode) {
return;
}
Purchases.setDebugLogsEnabled(false); Purchases.setDebugLogsEnabled(false);
await Purchases.setup( await Purchases.setup(
environment['revenueCat'], environment['revenueCat'],

View File

@ -50,7 +50,8 @@ class SettingsEditorsScreenState extends State<SettingsEditorsScreen> {
), ),
if (Features.purchaseProModeAvailable) SettingsHeader("Journal Editor"), if (Features.purchaseProModeAvailable) SettingsHeader("Journal Editor"),
if (Features.purchaseProModeAvailable) if (Features.purchaseProModeAvailable)
ProListTile( ProSettingOverlay(
child: ListTile(
title: const Text("Default Folder"), title: const Text("Default Folder"),
subtitle: Text(defaultNewFolder), subtitle: Text(defaultNewFolder),
onTap: () async { onTap: () async {
@ -65,6 +66,7 @@ class SettingsEditorsScreenState extends State<SettingsEditorsScreen> {
setState(() {}); setState(() {});
}, },
), ),
),
]); ]);
return Scaffold( return Scaffold(

View File

@ -142,6 +142,21 @@ class SettingsListState extends State<SettingsList> {
dynamicTheme.setBrightness(b); dynamicTheme.setBrightness(b);
}, },
), ),
ProSettingOverlay(
child: ListPreference(
title: tr('settings.display.homeScreen'),
currentOption: settings.homeScreen.toPublicString(),
options: SettingsHomeScreen.options
.map((f) => f.toPublicString())
.toList(),
onChange: (String publicStr) {
var s = SettingsHomeScreen.fromPublicString(publicStr);
Settings.instance.homeScreen = s;
Settings.instance.save();
setState(() {});
},
),
),
SettingsHeader('Note Settings'), SettingsHeader('Note Settings'),
ListTile( ListTile(
title: const Text("Default Folder for new notes"), title: const Text("Default Folder for new notes"),

View File

@ -1,3 +1,4 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gitjournal/settings.dart'; import 'package:gitjournal/settings.dart';
@ -63,32 +64,23 @@ class ListPreference extends StatelessWidget {
} }
} }
class ProListTile extends StatelessWidget { class ProSettingOverlay extends StatelessWidget {
final Widget title; final Widget child;
final Widget subtitle;
final Function onTap;
ProListTile({this.title, this.subtitle, this.onTap}); ProSettingOverlay({@required this.child});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var isPro = Settings.instance.proMode; if (Settings.instance.proMode) {
var tile = ListTile( return child;
title: title,
subtitle: subtitle,
onTap: onTap,
);
if (isPro) {
return tile;
} }
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: Banner( child: Banner(
message: 'Pro', message: tr('pro'),
location: BannerLocation.topStart, location: BannerLocation.topEnd,
color: Colors.purple, color: Theme.of(context).accentColor,
child: IgnorePointer(child: tile), child: IgnorePointer(child: Opacity(opacity: 0.5, child: child)),
), ),
onTap: () { onTap: () {
Navigator.pushNamed(context, "/purchase"); Navigator.pushNamed(context, "/purchase");

View File

@ -41,6 +41,8 @@ class Settings {
String _pseudoId; String _pseudoId;
String get pseudoId => _pseudoId; String get pseudoId => _pseudoId;
SettingsHomeScreen homeScreen = SettingsHomeScreen.Default;
SettingsMarkdownDefaultView markdownDefaultView = SettingsMarkdownDefaultView markdownDefaultView =
SettingsMarkdownDefaultView.Default; SettingsMarkdownDefaultView.Default;
@ -89,6 +91,9 @@ class Settings {
_pseudoId = Uuid().v4(); _pseudoId = Uuid().v4();
pref.setString("pseudoId", _pseudoId); pref.setString("pseudoId", _pseudoId);
} }
homeScreen =
SettingsHomeScreen.fromInternalString(pref.getString("homeScreen"));
} }
Future save() async { Future save() async {
@ -115,6 +120,7 @@ class Settings {
pref.setString("proExpirationDate", proExpirationDate); pref.setString("proExpirationDate", proExpirationDate);
pref.setInt("settingsVersion", version); pref.setInt("settingsVersion", version);
pref.setBool("proMode", proMode); pref.setBool("proMode", proMode);
pref.setString("homeScreen", homeScreen.toInternalString());
// Shouldn't we check if something has actually changed? // Shouldn't we check if something has actually changed?
for (var f in changeObservers) { for (var f in changeObservers) {
@ -144,6 +150,7 @@ class Settings {
"proMode": proMode.toString(), "proMode": proMode.toString(),
'pseudoId': pseudoId, 'pseudoId': pseudoId,
'markdownDefaultView': markdownDefaultView.toInternalString(), 'markdownDefaultView': markdownDefaultView.toInternalString(),
'homeScreen': homeScreen.toInternalString(),
}; };
} }
@ -466,3 +473,50 @@ class SettingsMarkdownDefaultView {
return ""; return "";
} }
} }
class SettingsHomeScreen {
static const AllNotes = SettingsHomeScreen("All Notes", "all_notes");
static const AllFolders = SettingsHomeScreen("All Folders", "all_folders");
static const Default = AllNotes;
final String _str;
final String _publicString;
const SettingsHomeScreen(this._publicString, this._str);
String toInternalString() {
return _str;
}
String toPublicString() {
return _publicString;
}
static const options = <SettingsHomeScreen>[
AllNotes,
AllFolders,
];
static SettingsHomeScreen fromInternalString(String str) {
for (var opt in options) {
if (opt.toInternalString() == str) {
return opt;
}
}
return Default;
}
static SettingsHomeScreen fromPublicString(String str) {
for (var opt in options) {
if (opt.toPublicString() == str) {
return opt;
}
}
return Default;
}
@override
String toString() {
assert(false, "SettingsHomeScreen toString should never be called");
return "";
}
}

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart'; import 'package:flutter_email_sender/flutter_email_sender.dart';
import 'package:gitjournal/features.dart'; import 'package:gitjournal/features.dart';
import 'package:gitjournal/settings.dart'; import 'package:gitjournal/settings.dart';
import 'package:gitjournal/utils/logger.dart';
import 'package:launch_review/launch_review.dart'; import 'package:launch_review/launch_review.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:share/share.dart'; import 'package:share/share.dart';
@ -84,43 +85,14 @@ class AppDrawer extends StatelessWidget {
context, context,
icon: Icons.note, icon: Icons.note,
title: "All Notes", title: "All Notes",
onTap: () { onTap: () => _navTopLevel(context, '/'),
var m = ModalRoute.of(context);
if (m.settings.name == "/") {
Navigator.pop(context);
} else {
Navigator.popUntil(
context, (route) => route.settings.name == '/');
}
},
selected: currentRoute == '/', selected: currentRoute == '/',
), ),
_buildDrawerTile( _buildDrawerTile(
context, context,
icon: Icons.folder, icon: Icons.folder,
title: "Folders", title: "Folders",
onTap: () { onTap: () => _navTopLevel(context, '/folders'),
var m = ModalRoute.of(context);
if (m.settings.name == '/') {
Navigator.pop(context);
Navigator.pushNamed(context, '/folders');
} else if (m.settings.name == '/folders') {
Navigator.pop(context);
} else {
// Check if '/folders' is a parent
var wasParent = false;
Navigator.popUntil(
context,
(route) {
wasParent = route.settings.name == '/folders';
return wasParent;
},
);
if (!wasParent) {
Navigator.pushNamed(context, '/folders');
}
}
},
selected: currentRoute == "/folders", selected: currentRoute == "/folders",
), ),
divider, divider,
@ -253,3 +225,33 @@ class AppDrawer extends StatelessWidget {
); );
} }
} }
void _navTopLevel(BuildContext context, String toRoute) {
var fromRoute = ModalRoute.of(context).settings.name;
Log.i("Routing from $fromRoute -> $toRoute");
// Always first pop the AppBar
Navigator.pop(context);
if (fromRoute == toRoute) {
return;
}
var wasParent = false;
Navigator.popUntil(
context,
(route) {
if (route.isFirst) {
return true;
}
wasParent = route.settings.name == toRoute;
if (wasParent) {
Log.i("Router popping ${route.settings.name}");
}
return wasParent;
},
);
if (!wasParent) {
Navigator.pushNamed(context, toRoute);
}
}