From e4f5dc88a21d1eb951de6f09873f1596940fbf38 Mon Sep 17 00:00:00 2001 From: 55nknown Date: Wed, 22 Mar 2023 09:57:20 +0100 Subject: [PATCH] task updates --- filcnaplo/android/app/build.gradle | 11 ++ .../android/app/src/main/AndroidManifest.xml | 16 ++- filcnaplo/android/build.gradle | 22 ++-- filcnaplo/ios/Podfile.lock | 14 ++- filcnaplo/ios/Runner/Info.plist | 117 ++++++++++-------- filcnaplo/ios/livecard/livecard.swift | 99 +++++++++------ .../lib/api/providers/live_card_provider.dart | 11 +- filcnaplo/lib/main.dart | 9 ++ .../Flutter/GeneratedPluginRegistrant.swift | 2 + filcnaplo/pubspec.yaml | 2 + filcnaplo_mobile_ui | 2 +- 11 files changed, 190 insertions(+), 115 deletions(-) diff --git a/filcnaplo/android/app/build.gradle b/filcnaplo/android/app/build.gradle index e003051..93221ea 100644 --- a/filcnaplo/android/app/build.gradle +++ b/filcnaplo/android/app/build.gradle @@ -53,6 +53,14 @@ android { multiDexEnabled true } + compileOptions { + // Flag to enable support for the new language APIs + coreLibraryDesugaringEnabled true + // Sets Java compatibility to Java 8 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + signingConfigs { release { keyAlias keystoreProperties['keyAlias'] @@ -85,4 +93,7 @@ dependencies { implementation 'joda-time:joda-time:2.9.4' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' + implementation 'androidx.window:window:1.0.0' + implementation 'androidx.window:window-java:1.0.0' } diff --git a/filcnaplo/android/app/src/main/AndroidManifest.xml b/filcnaplo/android/app/src/main/AndroidManifest.xml index 948ca87..e37928c 100644 --- a/filcnaplo/android/app/src/main/AndroidManifest.xml +++ b/filcnaplo/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,15 @@ - - - - + + + + diff --git a/filcnaplo/android/build.gradle b/filcnaplo/android/build.gradle index 0fd257a..49daf53 100644 --- a/filcnaplo/android/build.gradle +++ b/filcnaplo/android/build.gradle @@ -13,21 +13,21 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } -// allprojects { -// repositories { -// google() -// jcenter() -// maven { -// // [required] background_fetch -// url "${project(':background_fetch').projectDir}/libs" -// } -// } -// } +allprojects { + repositories { + google() + jcenter() + maven { + // [required] background_fetch + url "${project(':background_fetch').projectDir}/libs" + } + } +} subprojects { afterEvaluate {project -> diff --git a/filcnaplo/ios/Podfile.lock b/filcnaplo/ios/Podfile.lock index 2a05203..19dfdd1 100644 --- a/filcnaplo/ios/Podfile.lock +++ b/filcnaplo/ios/Podfile.lock @@ -1,6 +1,8 @@ PODS: - app_group_directory (1.0.0): - Flutter + - background_fetch (1.1.5): + - Flutter - connectivity_plus (0.0.1): - Flutter - ReachabilitySwift @@ -46,6 +48,8 @@ PODS: - Mantle - SDWebImage - SDWebImageWebPCoder + - flutter_local_notifications (0.0.1): + - Flutter - flutter_native_image (0.0.1): - Flutter - FMDB (2.7.5): @@ -101,12 +105,14 @@ PODS: DEPENDENCIES: - app_group_directory (from `.symlinks/plugins/app_group_directory/ios`) + - background_fetch (from `.symlinks/plugins/background_fetch/ios`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - DKImagePickerController/PhotoGallery (from `https://github.com/zhangao0086/DKImagePickerController.git`) - file_picker (from `.symlinks/plugins/file_picker/ios`) - Flutter (from `Flutter`) - flutter_custom_tabs (from `.symlinks/plugins/flutter_custom_tabs/ios`) - flutter_image_compress (from `.symlinks/plugins/flutter_image_compress/ios`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - flutter_native_image (from `.symlinks/plugins/flutter_native_image/ios`) - home_widget (from `.symlinks/plugins/home_widget/ios`) - image_crop (from `.symlinks/plugins/image_crop/ios`) @@ -136,6 +142,8 @@ SPEC REPOS: EXTERNAL SOURCES: app_group_directory: :path: ".symlinks/plugins/app_group_directory/ios" + background_fetch: + :path: ".symlinks/plugins/background_fetch/ios" connectivity_plus: :path: ".symlinks/plugins/connectivity_plus/ios" DKImagePickerController: @@ -148,6 +156,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_custom_tabs/ios" flutter_image_compress: :path: ".symlinks/plugins/flutter_image_compress/ios" + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" flutter_native_image: :path: ".symlinks/plugins/flutter_native_image/ios" home_widget: @@ -184,6 +194,7 @@ CHECKOUT OPTIONS: SPEC CHECKSUMS: app_group_directory: 7bf9f8f9819ead554de29da7c25fb7a680d6a9a0 + background_fetch: 9a9963128952bfdd197e21786983c7c7a30e1478 connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 @@ -191,6 +202,7 @@ SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_custom_tabs: 7a10a08686955cb748e5d26e0ae586d30689bf89 flutter_image_compress: 5a5e9aee05b6553048b8df1c3bc456d0afaac433 + flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 flutter_native_image: 9c0b7451838484458e5b0fae007b86a4c2d4bdfe FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a home_widget: 2829415127ee92e876f816cbbe44c0b6601b8a37 @@ -215,4 +227,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 862f939bb7e5390bdb8b2534eb81a9457ea9fbdc -COCOAPODS: 1.11.3 +COCOAPODS: 1.12.0 diff --git a/filcnaplo/ios/Runner/Info.plist b/filcnaplo/ios/Runner/Info.plist index 4849263..35e1a8d 100644 --- a/filcnaplo/ios/Runner/Info.plist +++ b/filcnaplo/ios/Runner/Info.plist @@ -1,62 +1,71 @@ - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Filc Napló - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - NSSupportsLiveActivities - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - UIStatusBarHidden - - LSApplicationQueriesSchemes - - https - http - - NSPhotoLibraryUsageDescription - The app requires the photo library to set a custom profile picture. - ITSAppUsesNonExemptEncryption - - CADisableMinimumFrameDurationOnPhone + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Filc Napló + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + ITSAppUsesNonExemptEncryption + + LSApplicationQueriesSchemes + + https + http + + LSRequiresIPhoneOS + + NSPhotoLibraryUsageDescription + The app requires the photo library to set a custom profile picture. + NSSupportsLiveActivities UIApplicationSupportsIndirectInputEvents + UIBackgroundModes + + fetch + processing + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + BGTaskSchedulerPermittedIdentifiers + + com.transistorsoft.fetch + + UIViewControllerBasedStatusBarAppearance + diff --git a/filcnaplo/ios/livecard/livecard.swift b/filcnaplo/ios/livecard/livecard.swift index d3e5d23..1af4622 100644 --- a/filcnaplo/ios/livecard/livecard.swift +++ b/filcnaplo/ios/livecard/livecard.swift @@ -18,48 +18,67 @@ struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable { var id = UUID() } +struct LockScreenLiveActivityView: View { + let context: ActivityViewContext + + let lesson = LessonData() + + var body: some View { + HStack(alignment: .center) { + Image(systemName: lesson!.icon) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: CGFloat(30), height: CGFloat(30)) + .padding(.leading, CGFloat(24)) + + VStack(alignment: .leading) { + HStack(alignment: .center) { + Text(lesson!.index + lesson!.title) + .font(.title3) + .bold() + + Text(lesson!.subtitle) + .font(.subheadline) + .padding(.trailing, 12) + } + + if (lesson!.description != "") { + Text(lesson!.description) + .font(.subheadline) + } + + HStack { + Image(systemName: "arrow.right") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: CGFloat(8), height: CGFloat(8)) + Text(lesson!.nextSubject) + .font(.caption) + Text(lesson!.nextRoom) + .font(.caption2) + } + }.padding(15) + + Spacer() + + Text(timerInterval: lesson!.date, countsDown: true) + .multilineTextAlignment(.center) + .frame(width: 85) + .font(.title) + .monospacedDigit() + .padding(.trailing, CGFloat(24)) + } + .activitySystemActionForegroundColor(.teal) + .activityBackgroundTint(.teal) + } +} + @available(iOSApplicationExtension 16.1, *) struct LiveCardWidget: Widget { var body: some WidgetConfiguration { /// Live Activity Notification ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in - let lesson = LessonData() - - HStack(alignment: .center) { - Image(systemName: lesson!.icon) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: CGFloat(30), height: CGFloat(30)) - .padding(.leading, CGFloat(8)) - - VStack(alignment: .leading) { - Text(lesson!.index + lesson!.title) - .font(.title3) - .bold() - - Text(lesson!.description) - .font(.subheadline) - - Spacer() - - HStack { - Image(systemName: "arrow.right") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: CGFloat(12), height: CGFloat(12)) - Text(lesson!.nextSubject) - .font(.caption) - Text(lesson!.nextRoom) - .font(.caption2) - } - }.padding(15) - - Spacer() - - Text(lesson!.subtitle) - .font(.subheadline) - .padding(.trailing, 12) - }.padding(12) + LockScreenLiveActivityView(context: context) /// Dynamic Island } dynamicIsland: { context in let lesson = LessonData() @@ -109,9 +128,9 @@ struct LiveCardWidget: Widget { .font(.caption2) } compactTrailing: { Text(timerInterval: lesson!.date, countsDown: true) - .multilineTextAlignment(.center) - .frame(width: 40) - .font(.caption2) + .multilineTextAlignment(.center) + .frame(width: 40) + .font(.caption2) /// Collapsed } minimal: { diff --git a/filcnaplo/lib/api/providers/live_card_provider.dart b/filcnaplo/lib/api/providers/live_card_provider.dart index c665e62..ad191a6 100644 --- a/filcnaplo/lib/api/providers/live_card_provider.dart +++ b/filcnaplo/lib/api/providers/live_card_provider.dart @@ -9,7 +9,7 @@ import 'package:filcnaplo_kreta_api/models/lesson.dart'; import 'package:filcnaplo_kreta_api/models/week.dart'; import 'package:filcnaplo/utils/format.dart'; import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart'; -import 'package:flutter/widgets.dart'; +import 'package:flutter/foundation.dart'; import 'package:live_activities/live_activities.dart'; import 'package:filcnaplo_mobile_ui/pages/home/live_card/live_card.i18n.dart'; @@ -38,6 +38,9 @@ class LiveCardProvider extends ChangeNotifier { }) : _timetable = timetable, _settings = settings { _liveActivitiesPlugin.init(appGroupId: "group.filcnaplo.livecard"); + _liveActivitiesPlugin.getAllActivitiesIds().then((value) { + _latestActivityId = value.isNotEmpty ? value.first : null; + }); _timer = Timer.periodic(const Duration(seconds: 1), (timer) => update()); _delay = settings.bellDelayEnabled ? Duration(seconds: settings.bellDelay) : Duration.zero; update(); @@ -98,10 +101,10 @@ class LiveCardProvider extends ChangeNotifier { return { "icon": iconFloorMap[diff] ?? "cup.and.saucer", "title": "Szünet", - "description": diff.i18n.fill([diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room]), + "description": "go $diff".i18n.fill([diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room]), "startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(), "endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) - _delay.inMilliseconds).toString(), - "nextSubject": nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject) : "", + "nextSubject": (nextLesson != null ? ShortSubject.resolve(subject: nextLesson?.subject) : "").capital(), "nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "", "index": "", "subtitle": "", @@ -114,7 +117,7 @@ class LiveCardProvider extends ChangeNotifier { void update() async { if (Platform.isIOS) { final cmap = toMap(); - if (cmap != _lastActivity) { + if (!mapEquals(cmap, _lastActivity)) { _lastActivity = cmap; if (_lastActivity.isNotEmpty) { diff --git a/filcnaplo/lib/main.dart b/filcnaplo/lib/main.dart index 5d660e9..1e3ddde 100644 --- a/filcnaplo/lib/main.dart +++ b/filcnaplo/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:background_fetch/background_fetch.dart'; import 'package:filcnaplo/api/providers/user_provider.dart'; import 'package:filcnaplo/api/providers/database_provider.dart'; import 'package:filcnaplo/database/init.dart'; @@ -22,6 +23,8 @@ void main() async { // Custom error page ErrorWidget.builder = errorBuilder; + BackgroundFetch.registerHeadlessTask(backgroundHeadlessTask); + // Run App runApp(App(database: startup.database, settings: startup.settings, user: startup.user)); } @@ -65,3 +68,9 @@ Widget errorBuilder(FlutterErrorDetails details) { return Container(); }); } + +@pragma('vm:entry-point') +void backgroundHeadlessTask(HeadlessTask task) { + print('[BackgroundFetch] Headless event received.'); + BackgroundFetch.finish(task.taskId); +} diff --git a/filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift b/filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift index 42024fc..a68520e 100644 --- a/filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import connectivity_plus import dynamic_color import flutter_acrylic +import flutter_local_notifications import path_provider_macos import share_plus_macos import sqflite @@ -17,6 +18,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FlutterAcrylicPlugin.register(with: registry.registrar(forPlugin: "FlutterAcrylicPlugin")) + FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/filcnaplo/pubspec.yaml b/filcnaplo/pubspec.yaml index 2d9ab62..44be61f 100644 --- a/filcnaplo/pubspec.yaml +++ b/filcnaplo/pubspec.yaml @@ -66,6 +66,8 @@ dependencies: image_picker: ^0.8.6 image_crop: ^0.4.1 animations: ^2.0.1 + background_fetch: ^1.1.5 + flutter_local_notifications: ^13.0.0 dev_dependencies: flutter_lints: ^2.0.1 diff --git a/filcnaplo_mobile_ui b/filcnaplo_mobile_ui index 1052401..8951710 160000 --- a/filcnaplo_mobile_ui +++ b/filcnaplo_mobile_ui @@ -1 +1 @@ -Subproject commit 1052401036388f8a69ac30cad1262854dad5a1de +Subproject commit 89517109d7d74ecc9b8c40566021d0366e5f7c66