2022-08-24 21:45:12 +00:00
|
|
|
import 'dart:io';
|
|
|
|
|
2023-07-23 19:56:34 +00:00
|
|
|
import 'package:dynamic_color/dynamic_color.dart';
|
2024-04-05 12:35:23 +00:00
|
|
|
import 'package:flutter/foundation.dart';
|
2018-09-14 16:59:13 +00:00
|
|
|
import 'package:flutter/material.dart';
|
2023-01-07 21:50:32 +00:00
|
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
2023-05-10 21:50:30 +00:00
|
|
|
import 'package:permission_handler/permission_handler.dart';
|
2023-01-07 21:50:32 +00:00
|
|
|
import 'package:vikunja_app/api/task_implementation.dart';
|
|
|
|
import 'package:vikunja_app/api/client.dart';
|
|
|
|
import 'package:vikunja_app/service/services.dart';
|
2023-01-07 15:55:40 +00:00
|
|
|
import 'package:workmanager/workmanager.dart';
|
2018-09-22 20:56:16 +00:00
|
|
|
import 'package:vikunja_app/global.dart';
|
2019-03-16 13:29:00 +00:00
|
|
|
import 'package:vikunja_app/pages/home.dart';
|
|
|
|
import 'package:vikunja_app/pages/user/login.dart';
|
2019-03-11 20:38:05 +00:00
|
|
|
import 'package:vikunja_app/theme/theme.dart';
|
2023-01-07 21:50:32 +00:00
|
|
|
import 'package:timezone/data/latest_all.dart' as tz;
|
2024-01-05 23:04:33 +00:00
|
|
|
import 'package:flutter_downloader/flutter_downloader.dart';
|
2023-01-07 21:50:32 +00:00
|
|
|
|
2024-02-11 22:30:45 +00:00
|
|
|
import 'api/user_implementation.dart';
|
2023-01-07 21:50:32 +00:00
|
|
|
import 'managers/notifications.dart';
|
2022-08-24 21:45:12 +00:00
|
|
|
|
|
|
|
class IgnoreCertHttpOverrides extends HttpOverrides {
|
2022-08-27 21:04:43 +00:00
|
|
|
bool ignoreCerts = false;
|
2023-01-07 21:50:32 +00:00
|
|
|
|
|
|
|
IgnoreCertHttpOverrides(bool _ignore) {
|
|
|
|
ignoreCerts = _ignore;
|
|
|
|
}
|
|
|
|
|
2022-08-24 21:45:12 +00:00
|
|
|
@override
|
2022-08-27 21:04:43 +00:00
|
|
|
HttpClient createHttpClient(SecurityContext? context) {
|
2022-08-24 21:45:12 +00:00
|
|
|
return super.createHttpClient(context)
|
|
|
|
..badCertificateCallback = (_, __, ___) => ignoreCerts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-07 15:55:40 +00:00
|
|
|
@pragma('vm:entry-point')
|
|
|
|
void callbackDispatcher() {
|
2024-04-05 12:35:23 +00:00
|
|
|
if (kIsWeb) {
|
|
|
|
return;
|
|
|
|
}
|
2024-02-11 22:30:45 +00:00
|
|
|
Workmanager().executeTask((task, inputData) async {
|
2024-04-05 20:36:56 +00:00
|
|
|
print(
|
|
|
|
"Native called background task: $task"); //simpleTask will be emitted here.
|
2023-01-07 21:50:32 +00:00
|
|
|
if (task == "update-tasks" && inputData != null) {
|
2023-05-16 23:22:59 +00:00
|
|
|
Client client = Client(null,
|
2023-01-07 21:50:32 +00:00
|
|
|
token: inputData["client_token"],
|
|
|
|
base: inputData["client_base"],
|
|
|
|
authenticated: true);
|
|
|
|
tz.initializeTimeZones();
|
|
|
|
|
|
|
|
return SettingsManager(new FlutterSecureStorage())
|
|
|
|
.getIgnoreCertificates()
|
|
|
|
.then((value) async {
|
|
|
|
print("ignoring: $value");
|
2024-04-05 13:41:48 +00:00
|
|
|
client.reloadIgnoreCerts(value == "1");
|
2023-01-07 21:50:32 +00:00
|
|
|
|
|
|
|
TaskAPIService taskService = TaskAPIService(client);
|
|
|
|
NotificationClass nc = NotificationClass();
|
|
|
|
await nc.notificationInitializer();
|
|
|
|
return nc
|
|
|
|
.scheduleDueNotifications(taskService)
|
|
|
|
.then((value) => Future.value(true));
|
|
|
|
});
|
2024-04-05 20:36:56 +00:00
|
|
|
} else if (task == "refresh-token") {
|
2024-02-11 22:30:45 +00:00
|
|
|
print("running refresh from workmanager");
|
|
|
|
final FlutterSecureStorage _storage = new FlutterSecureStorage();
|
|
|
|
|
|
|
|
var currentUser = await _storage.read(key: 'currentUser');
|
|
|
|
if (currentUser == null) {
|
|
|
|
return Future.value(true);
|
|
|
|
}
|
|
|
|
var token = await _storage.read(key: currentUser);
|
|
|
|
|
|
|
|
var base = await _storage.read(key: '${currentUser}_base');
|
|
|
|
if (token == null || base == null) {
|
|
|
|
return Future.value(true);
|
|
|
|
}
|
|
|
|
Client client = Client(null);
|
|
|
|
client.configure(token: token, base: base, authenticated: true);
|
2024-04-05 20:36:56 +00:00
|
|
|
// load new token from server to avoid expiration
|
|
|
|
String? newToken = await UserAPIService(client).getToken();
|
|
|
|
if (newToken != null) {
|
|
|
|
_storage.write(key: currentUser, value: newToken);
|
|
|
|
}
|
2024-02-11 22:30:45 +00:00
|
|
|
return Future.value(true);
|
2023-01-07 21:50:32 +00:00
|
|
|
} else {
|
|
|
|
return Future.value(true);
|
2023-01-07 15:55:40 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2024-04-05 20:36:56 +00:00
|
|
|
|
2023-05-16 23:22:59 +00:00
|
|
|
final globalSnackbarKey = GlobalKey<ScaffoldMessengerState>();
|
|
|
|
final globalNavigatorKey = GlobalKey<NavigatorState>();
|
2023-01-07 15:55:40 +00:00
|
|
|
|
2023-05-10 21:50:30 +00:00
|
|
|
void main() async {
|
2023-01-07 15:55:40 +00:00
|
|
|
WidgetsFlutterBinding.ensureInitialized();
|
2023-05-10 21:50:30 +00:00
|
|
|
await Permission.notification.isDenied.then((value) {
|
|
|
|
if (value) {
|
|
|
|
Permission.notification.request();
|
|
|
|
}
|
|
|
|
});
|
2024-04-05 12:35:23 +00:00
|
|
|
try {
|
|
|
|
if (!kIsWeb) {
|
|
|
|
await FlutterDownloader.initialize();
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
print("Failed to initialize downloader: $e");
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (!kIsWeb) {
|
|
|
|
Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
print("Failed to initialize workmanager: $e");
|
|
|
|
}
|
2023-01-07 21:50:32 +00:00
|
|
|
runApp(VikunjaGlobal(
|
2024-04-05 12:35:23 +00:00
|
|
|
child: new VikunjaApp(
|
|
|
|
home: HomePage(),
|
|
|
|
key: UniqueKey(),
|
|
|
|
navkey: globalNavigatorKey,
|
|
|
|
),
|
|
|
|
login: new VikunjaApp(
|
|
|
|
home: LoginPage(),
|
|
|
|
key: UniqueKey(),
|
|
|
|
),
|
|
|
|
));
|
2022-08-24 21:45:12 +00:00
|
|
|
}
|
2024-04-05 20:36:56 +00:00
|
|
|
|
2023-05-17 10:52:26 +00:00
|
|
|
final ValueNotifier<bool> updateTheme = ValueNotifier(false);
|
2018-09-14 16:59:13 +00:00
|
|
|
|
2018-09-15 15:01:45 +00:00
|
|
|
class VikunjaApp extends StatelessWidget {
|
2018-09-17 16:16:50 +00:00
|
|
|
final Widget home;
|
2023-05-16 23:22:59 +00:00
|
|
|
final GlobalKey<NavigatorState>? navkey;
|
2018-09-17 16:16:50 +00:00
|
|
|
|
2024-04-05 20:36:56 +00:00
|
|
|
const VikunjaApp({Key? key, required this.home, this.navkey})
|
|
|
|
: super(key: key);
|
2023-01-07 21:50:32 +00:00
|
|
|
|
2024-04-05 12:35:23 +00:00
|
|
|
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) {
|
|
|
|
case FlutterThemeMode.dark:
|
|
|
|
return buildVikunjaDarkTheme();
|
|
|
|
case FlutterThemeMode.materialYouLight:
|
|
|
|
return buildVikunjaMaterialLightTheme();
|
|
|
|
case FlutterThemeMode.materialYouDark:
|
|
|
|
return buildVikunjaMaterialDarkTheme();
|
|
|
|
default:
|
|
|
|
return buildVikunjaTheme();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-14 16:59:13 +00:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2024-04-05 20:36:56 +00:00
|
|
|
return new ValueListenableBuilder(
|
|
|
|
valueListenable: updateTheme,
|
|
|
|
builder: (_, mode, __) {
|
|
|
|
return FutureBuilder<ThemeData>(
|
2024-04-05 12:35:23 +00:00
|
|
|
future: getThemedata(),
|
2024-04-05 20:36:56 +00:00
|
|
|
builder: (BuildContext context, AsyncSnapshot<ThemeData> data) {
|
|
|
|
if (data.hasData) {
|
|
|
|
return new DynamicColorBuilder(
|
|
|
|
builder: (lightTheme, darkTheme) {
|
|
|
|
ThemeData? themeData = data.data;
|
2024-04-05 12:35:23 +00:00
|
|
|
if (data.data == FlutterThemeMode.materialYouLight)
|
2024-04-05 20:36:56 +00:00
|
|
|
themeData = themeData?.copyWith(colorScheme: lightTheme);
|
2024-04-05 12:35:23 +00:00
|
|
|
else if (data.data == FlutterThemeMode.materialYouDark)
|
2024-04-05 20:36:56 +00:00
|
|
|
themeData = themeData?.copyWith(colorScheme: darkTheme);
|
|
|
|
return MaterialApp(
|
|
|
|
title: 'Vikunja',
|
|
|
|
theme: themeData,
|
|
|
|
scaffoldMessengerKey: globalSnackbarKey,
|
|
|
|
navigatorKey: navkey,
|
|
|
|
// <= this
|
|
|
|
home: this.home,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return Center(child: CircularProgressIndicator());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2018-09-14 16:59:13 +00:00
|
|
|
}
|
2018-09-16 19:47:53 +00:00
|
|
|
}
|