Open relevant post when notification is clicked

Closes #7
This commit is contained in:
Lea 2023-02-05 18:43:19 +01:00
parent 42423f50ec
commit 43702e5ba0
Signed by: Lea
GPG key ID: 1BAFFE8347019C42
3 changed files with 88 additions and 2 deletions

View file

@ -141,6 +141,11 @@ class APIRequestBuilder {
return this;
}
APIRequestBuilder withIds(List<int> ids) {
_addArg('with_ids=${ids.join(',')}');
return this;
}
/// Executes the API request and returns the JSON data
Future<Map<String, dynamic>> fetch() async {
if (api.apiKey == null || api.apiUrl == null) {

View file

@ -16,13 +16,16 @@ import 'api/api.dart';
// fetching a large list
const FETCH_MAX_POSTS = 1000;
// Store these globally so our notification handler can access them
BuildContext? globalContext;
final api = FeverAPI();
void main() {
setupBackgroundTasks();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final api = FeverAPI();
SharedPreferences? prefs;
MyApp({super.key});
@ -60,6 +63,7 @@ class MyApp extends StatelessWidget {
themeMode: ThemeMode.system,
home: FutureBuilder<bool>(
builder: (context, snapshot) {
globalContext = context;
if (snapshot.hasData && prefs != null) {
return MyHomePage(title: 'Feet', api: api, prefs: prefs!);
}

View file

@ -1,6 +1,8 @@
import 'dart:math';
import 'package:feet/api/api.dart';
import 'package:feet/main.dart';
import 'package:feet/pages/article.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
@ -79,9 +81,11 @@ void callbackDispatcher() {
}
await FlutterLocalNotificationsPlugin().show(
Random().nextInt(10000000), // Can't use the post ID here because FreshRSS's IDs are too large
Random().nextInt(
10000000), // Can't use the post ID here because FreshRSS's IDs are too large
feed != null ? 'New post - ${feed.title}' : 'New post',
item.title,
payload: 'item/${item.id}',
NotificationDetails(
android: AndroidNotificationDetails(
'new_posts',
@ -117,6 +121,35 @@ void setupBackgroundTasks() async {
await Permission.notification.request();
await FlutterLocalNotificationsPlugin().initialize(
const InitializationSettings(
android: AndroidInitializationSettings('@mipmap/ic_launcher'),
),
onSelectNotification: handleNotificationClick,
);
var launchDetails =
await FlutterLocalNotificationsPlugin().getNotificationAppLaunchDetails();
if (launchDetails?.payload != null && launchDetails!.payload!.isNotEmpty) {
handleNotificationClick(launchDetails.payload);
}
// Test notification
//if (kDebugMode) {
// await FlutterLocalNotificationsPlugin().show(
// Random().nextInt(1000000),
// "Test Notification",
// "Test Notification Body",
// const NotificationDetails(
// android: AndroidNotificationDetails(
// 'new_posts',
// 'New posts',
// ),
// ),
// payload: "item/1675609277381551");
//}
// Runs every 15 minutes
await Workmanager().registerPeriodicTask(
'fetch_notifications',
@ -125,3 +158,47 @@ void setupBackgroundTasks() async {
initialDelay: const Duration(seconds: 60),
);
}
Future<void> handleNotificationClick(String? payload) async {
print("Notification click: $payload");
if (globalContext == null) {
print("Global context not available.");
return;
}
if (payload == null) {
print("Didn't receive a payload");
return;
}
try {
if (payload.startsWith('item/')) {
if (!api.loggedIn()) {
print("API client is not logged in");
return;
}
var id = toInt(payload.split('/')[1]);
var item = api.cache.items.get(id);
if (item == null) {
var res = await api.request().withItems().withIds([id]).execute();
item = api.cache.items.get(id);
if (item == null) throw 'Didn\'t receive item $id from API: $res';
}
Navigator.of(globalContext!).push(
MaterialPageRoute(
builder: (context) => ArticlePage(article: item!),
),
);
if (!item.isRead) {
await api
.request()
.markItem(item, ItemMarkType.read)
.execute();
}
}
} catch (e) {
print("Error while handling notification click: $e");
}
}