mirror of
https://github.com/go-vikunja/app
synced 2025-05-23 18:08:09 +00:00
feat: add sentry reporting (opt-in)
fix: theme is now always applied right away
This commit is contained in:
parent
459171d41a
commit
9800318df7
141
lib/main.dart
141
lib/main.dart
@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
import 'package:vikunja_app/api/task_implementation.dart';
|
||||
import 'package:vikunja_app/api/client.dart';
|
||||
import 'package:vikunja_app/service/services.dart';
|
||||
@ -126,24 +127,21 @@ void main() async {
|
||||
));
|
||||
}
|
||||
|
||||
final ValueNotifier<bool> updateTheme = ValueNotifier(false);
|
||||
class ThemeModel with ChangeNotifier {
|
||||
FlutterThemeMode _themeMode = FlutterThemeMode.light;
|
||||
FlutterThemeMode get themeMode => _themeMode;
|
||||
|
||||
class VikunjaApp extends StatelessWidget {
|
||||
final Widget home;
|
||||
final GlobalKey<NavigatorState>? navkey;
|
||||
void set themeMode(FlutterThemeMode mode) {
|
||||
_themeMode = mode;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
const VikunjaApp({Key? key, required this.home, this.navkey})
|
||||
: super(key: key);
|
||||
void notify() {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<ThemeData> getThemedata() async {
|
||||
FlutterThemeMode themeMode = FlutterThemeMode.light;
|
||||
try {
|
||||
SettingsManager manager = SettingsManager(new FlutterSecureStorage());
|
||||
themeMode = await manager.getThemeMode();
|
||||
} catch (e) {
|
||||
print("Failed to get theme mode: $e");
|
||||
}
|
||||
switch (themeMode) {
|
||||
ThemeData get themeData {
|
||||
switch (_themeMode) {
|
||||
case FlutterThemeMode.dark:
|
||||
return buildVikunjaDarkTheme();
|
||||
case FlutterThemeMode.materialYouLight:
|
||||
@ -155,30 +153,94 @@ class VikunjaApp extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
ThemeData getWithColorScheme(
|
||||
ColorScheme? lightTheme, ColorScheme? darkTheme) {
|
||||
switch (_themeMode) {
|
||||
case FlutterThemeMode.dark:
|
||||
return buildVikunjaDarkTheme().copyWith(colorScheme: darkTheme);
|
||||
case FlutterThemeMode.materialYouLight:
|
||||
return buildVikunjaMaterialLightTheme()
|
||||
.copyWith(colorScheme: lightTheme);
|
||||
case FlutterThemeMode.materialYouDark:
|
||||
return buildVikunjaMaterialDarkTheme().copyWith(colorScheme: darkTheme);
|
||||
default:
|
||||
return buildVikunjaTheme().copyWith(colorScheme: lightTheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThemeModel themeModel = ThemeModel();
|
||||
|
||||
class VikunjaApp extends StatelessWidget {
|
||||
final Widget home;
|
||||
final GlobalKey<NavigatorState>? navkey;
|
||||
bool sentryEnabled = false;
|
||||
bool sentyInitialized = false;
|
||||
|
||||
VikunjaApp({Key? key, required this.home, this.navkey}) : super(key: key);
|
||||
|
||||
Future<void> getLaunchData() async {
|
||||
try {
|
||||
SettingsManager manager = SettingsManager(new FlutterSecureStorage());
|
||||
await manager.getThemeMode().then((themeMode) {
|
||||
themeModel.themeMode = themeMode;
|
||||
});
|
||||
sentryEnabled = await manager.getSentryEnabled();
|
||||
} catch (e) {
|
||||
print("Failed to get theme mode: $e");
|
||||
return Future.value(false);
|
||||
}
|
||||
return Future.value(true);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new ValueListenableBuilder(
|
||||
valueListenable: updateTheme,
|
||||
builder: (_, mode, __) {
|
||||
return FutureBuilder<ThemeData>(
|
||||
future: getThemedata(),
|
||||
builder: (BuildContext context, AsyncSnapshot<ThemeData> data) {
|
||||
return new ListenableBuilder(
|
||||
listenable: themeModel,
|
||||
builder: (_, mode) {
|
||||
return FutureBuilder<void>(
|
||||
future: getLaunchData(),
|
||||
builder: (BuildContext context, data) {
|
||||
if (data.hasData) {
|
||||
return new DynamicColorBuilder(
|
||||
builder: (lightTheme, darkTheme) {
|
||||
ThemeData? themeData = data.data;
|
||||
if (data.data == FlutterThemeMode.materialYouLight)
|
||||
themeData = themeData?.copyWith(colorScheme: lightTheme);
|
||||
else if (data.data == FlutterThemeMode.materialYouDark)
|
||||
themeData = themeData?.copyWith(colorScheme: darkTheme);
|
||||
return MaterialApp(
|
||||
title: 'Vikunja',
|
||||
theme: themeData,
|
||||
scaffoldMessengerKey: globalSnackbarKey,
|
||||
navigatorKey: navkey,
|
||||
// <= this
|
||||
home: this.home,
|
||||
);
|
||||
if (sentryEnabled) {
|
||||
if (!sentyInitialized) {
|
||||
sentyInitialized = true;
|
||||
print("sentry enabled");
|
||||
SentryFlutter.init((options) {
|
||||
options.dsn =
|
||||
'https://a09618e3bb30e03b93233c21973df869@o1047380.ingest.us.sentry.io/4507995557134336';
|
||||
options.tracesSampleRate = 1.0;
|
||||
options.profilesSampleRate = 1.0;
|
||||
}).then((_) {
|
||||
FlutterError.onError = (details) async {
|
||||
print("sending to sentry");
|
||||
await Sentry.captureException(
|
||||
details.exception,
|
||||
stackTrace: details.stack,
|
||||
);
|
||||
FlutterError.presentError(details);
|
||||
};
|
||||
PlatformDispatcher.instance.onError = (error, stack) {
|
||||
print("sending to sentry (platform)");
|
||||
Sentry.captureException(error, stackTrace: stack);
|
||||
FlutterError.presentError(FlutterErrorDetails(
|
||||
exception: error, stack: stack));
|
||||
return false;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return SentryWidget(
|
||||
child: buildMaterialApp(themeModel.getWithColorScheme(
|
||||
lightTheme, darkTheme)));
|
||||
} else {
|
||||
sentyInitialized = false;
|
||||
}
|
||||
|
||||
return buildMaterialApp(
|
||||
themeModel.getWithColorScheme(lightTheme, darkTheme));
|
||||
});
|
||||
} else {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
@ -186,4 +248,15 @@ class VikunjaApp extends StatelessWidget {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildMaterialApp(ThemeData? themeData) {
|
||||
return MaterialApp(
|
||||
title: 'Vikunja',
|
||||
theme: themeData,
|
||||
scaffoldMessengerKey: globalSnackbarKey,
|
||||
navigatorKey: navkey,
|
||||
// <= this
|
||||
home: this.home,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ class SettingsPageState extends State<SettingsPage> {
|
||||
List<Project>? projectList;
|
||||
int? defaultProject;
|
||||
bool? ignoreCertificates;
|
||||
bool? sentryEnabled;
|
||||
bool? getVersionNotifications;
|
||||
String? versionTag, newestVersionTag;
|
||||
late TextEditingController durationTextController;
|
||||
@ -32,14 +33,15 @@ class SettingsPageState extends State<SettingsPage> {
|
||||
.getAll()
|
||||
.then((value) => setState(() => projectList = value));
|
||||
|
||||
//VikunjaGlobal.of(context).projectService.getDefaultList().then((value) =>
|
||||
// setState(
|
||||
// () => defaultProject = value == null ? null : int.tryParse(value)));
|
||||
|
||||
VikunjaGlobal.of(context).settingsManager.getIgnoreCertificates().then(
|
||||
(value) =>
|
||||
setState(() => ignoreCertificates = value == "1" ? true : false));
|
||||
|
||||
VikunjaGlobal.of(context)
|
||||
.settingsManager
|
||||
.getSentryEnabled()
|
||||
.then((value) => setState(() => sentryEnabled = value));
|
||||
|
||||
VikunjaGlobal.of(context).settingsManager.getVersionNotifications().then(
|
||||
(value) => setState(
|
||||
() => getVersionNotifications = value == "1" ? true : false));
|
||||
@ -71,7 +73,6 @@ class SettingsPageState extends State<SettingsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final global = VikunjaGlobal.of(context);
|
||||
|
||||
if (!initialized) init();
|
||||
return new Scaffold(
|
||||
appBar: AppBar(
|
||||
@ -160,7 +161,7 @@ class SettingsPageState extends State<SettingsPage> {
|
||||
onChanged: (FlutterThemeMode? value) {
|
||||
VikunjaGlobal.of(context).settingsManager.setThemeMode(value!);
|
||||
setState(() => themeMode = value);
|
||||
updateTheme.value = true;
|
||||
if (themeMode != null) themeModel.themeMode = themeMode!;
|
||||
},
|
||||
),
|
||||
),
|
||||
@ -175,6 +176,22 @@ class SettingsPageState extends State<SettingsPage> {
|
||||
})
|
||||
: ListTile(title: Text("...")),
|
||||
Divider(),
|
||||
sentryEnabled != null
|
||||
? CheckboxListTile(
|
||||
title: Text("Enable Sentry"),
|
||||
subtitle: Text(
|
||||
"Help us debug errors better and faster by sending bug reports to us directly. This is completely anonymous."),
|
||||
value: sentryEnabled,
|
||||
onChanged: (value) {
|
||||
if (value == null) return;
|
||||
setState(() => sentryEnabled = value);
|
||||
VikunjaGlobal.of(context)
|
||||
.settingsManager
|
||||
.setSentryEnabled(value)
|
||||
.then((_) => themeModel.notify());
|
||||
})
|
||||
: ListTile(title: Text("...")),
|
||||
Divider(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 15, right: 15),
|
||||
child: Row(children: [
|
||||
|
@ -243,7 +243,8 @@ class SettingsManager {
|
||||
"workmanager-duration": "0",
|
||||
"recent-servers": "[\"https://try.vikunja.io\"]",
|
||||
"theme_mode": "system",
|
||||
"landing-page-due-date-tasks": "1"
|
||||
"landing-page-due-date-tasks": "1",
|
||||
"sentry-enabled": "0",
|
||||
};
|
||||
|
||||
void applydefaults() {
|
||||
@ -268,6 +269,14 @@ class SettingsManager {
|
||||
_storage.write(key: "ignore-certificates", value: value ? "1" : "0");
|
||||
}
|
||||
|
||||
Future<bool> getSentryEnabled() {
|
||||
return _storage.read(key: "sentry-enabled").then((value) => value == "1");
|
||||
}
|
||||
|
||||
Future<void> setSentryEnabled(bool value) {
|
||||
return _storage.write(key: "sentry-enabled", value: value ? "1" : "0");
|
||||
}
|
||||
|
||||
Future<bool> getLandingPageOnlyDueDateTasks() {
|
||||
return _storage
|
||||
.read(key: "landing-page-due-date-tasks")
|
||||
|
16
pubspec.lock
16
pubspec.lock
@ -1141,6 +1141,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.27.7"
|
||||
sentry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sentry
|
||||
sha256: "033287044a6644a93498969449d57c37907e56f5cedb17b88a3ff20a882261dd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.0"
|
||||
sentry_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry_flutter
|
||||
sha256: "3780b5a0bb6afd476857cfbc6c7444d969c29a4d9bd1aa5b6960aa76c65b737a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -42,6 +42,7 @@ dependencies:
|
||||
cronet_http: ^1.2.0
|
||||
package_info_plus: ^4.2.0
|
||||
html_editor_enhanced: ^2.6.0
|
||||
sentry_flutter: ^8.9.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
x
Reference in New Issue
Block a user