Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ios, android: background refresh #122

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
platform :ios, '10.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
8 changes: 7 additions & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ PODS:
- Flutter
- webview_flutter (0.0.1):
- Flutter
- workmanager (0.0.1):
- Flutter

DEPENDENCIES:
- device_info (from `.symlinks/plugins/device_info/ios`)
Expand All @@ -43,6 +45,7 @@ DEPENDENCIES:
- video_player (from `.symlinks/plugins/video_player/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
- webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)
- workmanager (from `.symlinks/plugins/workmanager/ios`)

SPEC REPOS:
trunk:
Expand Down Expand Up @@ -75,6 +78,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/wakelock/ios"
webview_flutter:
:path: ".symlinks/plugins/webview_flutter/ios"
workmanager:
:path: ".symlinks/plugins/workmanager/ios"

SPEC CHECKSUMS:
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
Expand All @@ -91,7 +96,8 @@ SPEC CHECKSUMS:
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
wakelock: b0843b2479edbf6504d8d262c2959446f35373aa
webview_flutter: 9f491a9b5a66f2573946a389b2677987b0ff8c0b
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6

PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
PODFILE CHECKSUM: fe0e1ee7f3d1f7d00b11b474b62dd62134535aea

COCOAPODS: 1.10.1
11 changes: 7 additions & 4 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand All @@ -358,6 +358,7 @@
DEVELOPMENT_TEAM = AHDHW7HK24;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -417,7 +418,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -466,7 +467,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand All @@ -487,6 +488,7 @@
DEVELOPMENT_TEAM = AHDHW7HK24;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -510,6 +512,7 @@
DEVELOPMENT_TEAM = AHDHW7HK24;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -548,4 +551,4 @@
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
}
28 changes: 21 additions & 7 deletions ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import UIKit
import Flutter
import workmanager

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
UNUserNotificationCenter.current().delegate = self

WorkmanagerPlugin.setPluginRegistrantCallback { registry in
// registry in this case is the FlutterEngine that is created in Workmanager's performFetchWithCompletionHandler
// This will make other plugins available during a background fetch
GeneratedPluginRegistrant.register(with: registry)
}
UIApplication.shared.setMinimumBackgroundFetchInterval(TimeInterval(60 * 15))

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(.alert) // shows banner even if app is in foreground
}
}
4 changes: 4 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
Expand Down
104 changes: 54 additions & 50 deletions lib/aggregation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,15 @@ import 'package:kanbasu/models/brief_info.dart';
import 'package:kanbasu/utils/courses.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:kanbasu/utils/html.dart';
import 'package:kanbasu/utils/stream_op.dart';
import 'package:pedantic/pedantic.dart';
import 'package:rxdart/rxdart.dart';

Future<List<T>> getListDataFromApi<T>(
List<Stream<T>> stream, bool useOnlineData) async {
if (useOnlineData) {
return await stream.last.toList();
} else {
return await stream.first.toList();
}
}

Future<T> getItemDataFromApi<T>(
List<Future<T>> stream, bool useOnlineData) async {
if (useOnlineData) {
return (await stream.last);
} else {
return (await stream.first);
}
}

Stream<BriefInfo> aggregate(CanvasBufferClient api,
{bool useOnlineData = false}) async* {
Stream<BriefInfo> aggregate(
CanvasBufferClient api, {
bool useOnlineData = false,
bool dryRun = false,
}) async* {
final latestCourses = toLatestCourses(
await getListDataFromApi(api.getCourses(), useOnlineData));
final idToCourse = {
Expand All @@ -41,28 +27,40 @@ Stream<BriefInfo> aggregate(CanvasBufferClient api,
Future<List<BriefInfo>> processCourse(Course course) async {
final aggregations = <BriefInfo?>[];

final assignments =
await getListDataFromApi(api.getAssignments(course.id), useOnlineData);
for (final assignment in assignments) {
final newAgg = aggregateFromAssignment(assignment, course);
aggregations.add(newAgg);
final assignments = await getListDataFromApi(
api.getAssignments(course.id),
useOnlineData,
);
if (!dryRun) {
for (final assignment in assignments) {
final newAgg = aggregateFromAssignment(assignment, course);
aggregations.add(newAgg);

final newAgg2 = aggregateFromAssignmentDue(assignment, course);
aggregations.add(newAgg2);
final newAgg2 = aggregateFromAssignmentDue(assignment, course);
aggregations.add(newAgg2);
}
}

final submissions =
await getListDataFromApi(api.getSubmissions(course.id), useOnlineData);
for (final submission in submissions) {
final newAgg = aggregateFromSubmission(submission, course);
aggregations.add(newAgg);
final submissions = await getListDataFromApi(
api.getSubmissions(course.id),
useOnlineData,
);
if (!dryRun) {
for (final submission in submissions) {
final newAgg = aggregateFromSubmission(submission, course);
aggregations.add(newAgg);
}
}

final files =
await getListDataFromApi(api.getFiles(course.id), useOnlineData);
for (final file in files) {
final newAgg = aggregateFromFile(file, course);
aggregations.add(newAgg);
final files = await getListDataFromApi(
api.getFiles(course.id),
useOnlineData,
);
if (!dryRun) {
for (final file in files) {
final newAgg = aggregateFromFile(file, course);
aggregations.add(newAgg);
}
}

return aggregations.whereType<BriefInfo>().toList();
Expand All @@ -72,13 +70,18 @@ Stream<BriefInfo> aggregate(CanvasBufferClient api,
Future<List<BriefInfo>> processAnnouncements() async {
final aggregations = <BriefInfo?>[];

final planners = await getListDataFromApi(api.getPlanners(), useOnlineData);
for (final planner in planners) {
if (planner.plannableType != 'announcement') continue;
final course = idToCourse[planner.courseId];
if (course != null) {
final newAgg = aggregateFromPlanner(planner, course);
aggregations.add(newAgg);
final planners = await getListDataFromApi(
api.getPlanners(),
useOnlineData,
);
if (!dryRun) {
for (final planner in planners) {
if (planner.plannableType != 'announcement') continue;
final course = idToCourse[planner.courseId];
if (course != null) {
final newAgg = aggregateFromPlanner(planner, course);
aggregations.add(newAgg);
}
}
}

Expand All @@ -87,17 +90,18 @@ Stream<BriefInfo> aggregate(CanvasBufferClient api,

final subject = PublishSubject<List<BriefInfo>>();

unawaited(Future.wait(
[
unawaited(() async {
await Future.wait([
for (final course in latestCourses)
processCourse(course).then((d) => subject.add(d)),
processAnnouncements().then((d) => subject.add(d)),
],
).then((_) => subject.close()));
]);
await subject.close();
}());

final stream = subject.stream.flatMap((value) => Stream.fromIterable(value));
await for (final items in stream) {
yield items;
await for (final item in stream) {
yield item;
}
}

Expand Down
Loading