Adaptive Notifications + before enabling desktop

This commit is contained in:
warlock
2022-03-06 18:04:53 +05:30
parent 0272b2d1fd
commit f749c4ce8d
6 changed files with 141 additions and 28 deletions

View File

@@ -353,9 +353,10 @@ class _ActivitiesState extends State<Activities> {
size: 20,
),
if (containsMetadata)
Text(
activity.metadata ?? '',
overflow: TextOverflow.ellipsis,
FittedBox(
child: Text(
activity.metadata ?? '',
),
)
]),

View File

@@ -107,6 +107,7 @@ class Settings{
}
static String notification_key= "notification_interval";
static String adaptive_notification_key = "adaptive_notification";
static Future<int> getNotificationInterval() async{
final prefs = await SharedPreferences.getInstance();
@@ -125,8 +126,8 @@ class Settings{
final prefs = await SharedPreferences.getInstance();
prefs.setInt(notification_key, value);
}
static List<String> notificationOptions = <String>['Off','1 hour', '2 hour', '3 hour', '4 hour', '5 hour', '6 hour'];
static List<String> notificationOptions = <String>['Off','1 hour', '2 hour', '3 hour', '4 hour', '5 hour', '6 hour'];
static bool adaptiveNotificationAvailable() {
List<String> dates = [];
if(User.activities.length < 10){
@@ -141,7 +142,24 @@ class Settings{
}
return (dates.length > 2);
}
static Future<bool> getAdaptiveNotification() async{
final prefs = await SharedPreferences.getInstance();
bool _value = true;
if(prefs.containsKey(notification_key)){
_value = await prefs.getBool(adaptive_notification_key) ?? true;
}else{
prefs.setBool(adaptive_notification_key,_value);
}
return _value;
}
static Future<void> setAdaptiveNotification(bool value) async{
final prefs = await SharedPreferences.getInstance();
prefs.setBool(adaptive_notification_key, value);
}
}
final settings = Settings();

View File

@@ -0,0 +1,109 @@
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:intl/intl.dart';
import 'Data.dart';
import 'User.dart' as User;
class NotificationManager{
static void RescheduleNotifications() async{
print("Rescheduling notifications");
var androidInitilize = new AndroidInitializationSettings('@mipmap/ic_launcher');
var iOSinitilize = new IOSInitializationSettings();
var initilizationsSettings =
new InitializationSettings(android: androidInitilize, iOS: iOSinitilize);
var fltrNotification = new FlutterLocalNotificationsPlugin();
fltrNotification.initialize(initilizationsSettings, onSelectNotification: notificationSelected);
await fltrNotification.cancelAll();
int notification_interval = await Settings.getNotificationInterval();
bool adaptive_notification = await Settings.getAdaptiveNotification();
bool adaptive_notification_availabel = await Settings.adaptiveNotificationAvailable();
var androidDetails = const AndroidNotificationDetails("Xperience", "TaskTracker", importance: Importance.max);
var iSODetails = new IOSNotificationDetails();
var generalNotificationDetails =
new NotificationDetails(android: androidDetails, iOS: iSODetails);
if(adaptive_notification && adaptive_notification_availabel){
print("Smart!, Using adaptive huh?");
//Calculate you little thing! CALCULATE!'
DateFormat timeFormat = DateFormat("HH:mm");
DateTime baseline = DateTime(2000,2,2,0,0,0);
Map<int,List<int>> timeMap = <int,List<int>>{};
int totalDays = User.activities[0].startTime.difference(User.activities[User.activities.length-1].startTime).inDays;
int groupingThreshold = 60;
print("Iterating thru ${User.activities.length} activities of $totalDays");
for (var element in User.activities) {
if(element.startTime.difference(DateTime.now()).inDays <30){
//Eligible for adaptation
DateTime thisTime =baseline.add(Duration(hours: element.startTime.hour, minutes: element.startTime.minute));
int thisMin = thisTime.difference(baseline).inMinutes;
int? chosenOne = null;
int bestChoiceDiffer = groupingThreshold;
timeMap.forEach((key, value) {
if(key > thisMin-bestChoiceDiffer && key < thisMin+bestChoiceDiffer){
//Eligible to apply
chosenOne=key;
bestChoiceDiffer = (key - thisMin).abs();
}
});
if(chosenOne==null){
//There were no candidates
timeMap.putIfAbsent(thisMin, () => [thisMin]);
}else{
List<int> tempList = timeMap[chosenOne]!;
tempList.add(thisMin);
int newKey = 0;
for (var element in tempList) {
newKey+=element;
}
newKey = (newKey / tempList.length).toInt();
timeMap.remove(chosenOne);
timeMap.putIfAbsent(newKey, () => tempList);
}
}
}
print("Time Map : ${timeMap.length}");
print(timeMap);
timeMap.forEach((key, value) {
DateTime now = DateTime.now();
DateTime todayStart = DateTime(now.year,now.month,now.day,0,0,0);
DateTime thisTime = todayStart.add(Duration(minutes: key));
if(value.length < (totalDays.clamp(0, 30) / 3).ceil()){
print("${timeFormat.format(thisTime)} this happened only ${value.length} times, Ignoring...");
}else {
print(timeFormat.format(thisTime));
if(thisTime.isBefore(DateTime.now())) {
thisTime = thisTime.add(Duration(days: 1));
}
print("Scheduling at $thisTime");
fltrNotification.schedule(key, "Don't forget to add new activity", "Adaptive notifications suggests that you may have done by now to track.", thisTime, generalNotificationDetails);
}
});
}else if(notification_interval>0) {
var scheduledTime = DateTime.now().add(Duration(hours: notification_interval));
fltrNotification.schedule(1, "What did you do in last $notification_interval hours?", "Click here to track your last activities...",
scheduledTime, generalNotificationDetails,);
print("Sent notification schedule");
}
await Future.delayed(Duration(seconds: 2));
final List<PendingNotificationRequest> pendingNotificationRequests =await fltrNotification.pendingNotificationRequests();
print("Notifications");
pendingNotificationRequests.forEach((element) {
print("${element.id} : ${element.title} -> ${element.body} \n payload:${element.payload}");
});
}
static void notificationSelected(val){
print("Selected notifications : $val");
}
}

View File

@@ -23,9 +23,12 @@ class _NotificationSettingsState extends State<NotificationSettings> {
void updateSettings() async{
int notificationInterval= await Settings.getNotificationInterval();
bool _adaptiveNotification = await Settings.getAdaptiveNotification();
adaptiveNotificationAvailable = Settings.adaptiveNotificationAvailable();
print("adaptive available: ${adaptiveNotificationAvailable}");
setState(() {
dropdownValue=Settings.notificationOptions[notificationInterval];
adaptiveNotification = _adaptiveNotification;
});
}
@@ -44,6 +47,7 @@ class _NotificationSettingsState extends State<NotificationSettings> {
title: Text("Adaptive Notifications"),
trailing:(adaptiveNotificationAvailable) ?Switch.adaptive(value: adaptiveNotification, onChanged: (val){
adaptiveNotification=val;
Settings.setAdaptiveNotification(val);
setState(() {
});

View File

@@ -5,6 +5,7 @@ import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tasktracker/NotificationsManager.dart';
import 'main.dart';
import 'package:http/http.dart' as http;
@@ -68,6 +69,7 @@ Future<void> refreshUserData() async {
await updateTasksList();
await updateActList();
refreshStream.add(false);
NotificationManager.RescheduleNotifications();
}
Future<bool> cacheDbExist() async {
Directory directory = await getApplicationDocumentsDirectory();

View File

@@ -8,6 +8,8 @@ import 'package:http/http.dart' as http;
import 'theme_provider.dart';
import 'package:provider/provider.dart';
import 'newActivity.dart';
import 'NotificationsManager.dart';
class SplashScreen extends StatefulWidget {
const SplashScreen({Key? key}) : super(key: key);
@@ -33,33 +35,10 @@ class _SplashScreenState extends State<SplashScreen> {
// TODO: implement initState
super.initState();
init();
initNotifications();
NotificationManager.RescheduleNotifications();
}
void initNotifications() async{
var androidInitilize = new AndroidInitializationSettings('@mipmap/ic_launcher');
var iOSinitilize = new IOSInitializationSettings();
var initilizationsSettings =
new InitializationSettings(android: androidInitilize, iOS: iOSinitilize);
var fltrNotification = new FlutterLocalNotificationsPlugin();
fltrNotification.initialize(initilizationsSettings,
onSelectNotification: notificationSelected);
int notification_interval = await Settings.getNotificationInterval();
if(notification_interval>0) {
var androidDetails = const AndroidNotificationDetails("Xperience", "TaskTracker", importance: Importance.max);
var iSODetails = new IOSNotificationDetails();
var generalNotificationDetails =
new NotificationDetails(android: androidDetails, iOS: iSODetails);
var scheduledTime = DateTime.now().add(Duration(hours: notification_interval));
fltrNotification.schedule(1, "What did you do in last $notification_interval hours?", "Click here to track your last activities...",
scheduledTime, generalNotificationDetails,);
print("Sent notification schedule");
}
}
void notificationSelected(String? payload) {
if(payload!=null){
if(payload.toLowerCase().contains("activity")){