Capacitor IONIC 6 : Local Notification scheduling every day and on particular time - ionic-framework

I would like to schedule a Local Notification every day at a particular time. According to capacitor docs https://capacitorjs.com/docs/apis/local-notifications I have implemented it, the following pattern.
LocalNotifications.schedule({
notifications: [
{
id: 1,
title: 'Test local notification',
body: "Lorem ipsum",
schedule: { on: { hour: 9, minute: 9}, allowWhileIdle: true, every: 'day' }
}
})
This implementation is not working currently probably because of "on" and "every" options chosen together, which I am not sure of. Any guidance or implementation is much appreciated

same problem here...
To avoid the issue i create all the notifications one by one at the start of the app... (if there is no or less than 10notifications pending)
async setMonthNotif(){
for(let day=0; day <= 30; day++){
let date: Date = new Date();
date.setDate(new Date().getDate()+day);
await this.setNotif(date);
}
}
async setNotif(datePrevue?: Date){
let randomId = Math.floor(Math.random() * 10000) + 1;
// i need it every day at 9:25
const date = datePrevue? datePrevue : new Date();
date.setHours(9);
date.setMinutes(25);
// if time already pass
if(date > new Date()){
await LocalNotifications.schedule({notifications: [{
title: 'Trade disponible !',
body: 'Le trade du jour est maintenant disponible',
id: randomId,
schedule: {
at : date,
allowWhileIdle: true
},
}]})
}

Related

Flutter create multiple weekly local notification for a specified timeframe

For my upcoming Fitness-app
the user should be able to pick multiple days between monday and sunday, choose the hour and the amount of weeks for which the notification should be displayed.
For example:
I choose thursday and friday, 2 pm and 6 weeks.
So I should see the notification on thursday and friday on 2 pm for 6 weeks.
I am working with the 'flutter_local_notifications 0.8.3' Plugin, but it does not seem to have the functionality that I need, if you know any different approach to display notifications like I wrote above, feel free to tell me.
Edit:
code for the scheduled notification which I set with an for-loop.
But its not really a solution
Future<void> scheduleNotification(int id,{int, days,int hour, int minute, int second}) async {
var scheduledNotificationDateTime =
DateTime.now().add(Duration(days: days));
var vibrationPattern = Int64List(4);
vibrationPattern[0] = 0;
vibrationPattern[1] = 1000;
vibrationPattern[2] = 5000;
vibrationPattern[3] = 2000;
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your other channel id',
'your other channel name',
'your other channel description',
icon: 'app_icon',
largeIcon: 'app_icon',
largeIconBitmapSource: BitmapSource.Drawable,
vibrationPattern: vibrationPattern,
enableLights: true,
color: const Color.fromARGB(255, 255, 0, 0),
ledColor: const Color.fromARGB(255, 255, 0, 0),
ledOnMs: 1000,
ledOffMs: 500);
var iOSPlatformChannelSpecifics =
IOSNotificationDetails(sound: "slow_spring_board.aiff");
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.schedule(
id,
'scheduled title',
'scheduled body',
scheduledNotificationDateTime,
platformChannelSpecifics);
}
Code for the weekly notification
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'show weekly channel id',
'show weekly channel name',
'show weekly description');
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.showWeeklyAtDayAndTime(
0,
title,
'Weekly notification shown on Monday at approximately ${_toTwoDigitString(time.hour)}:${_toTwoDigitString(time.minute)}:${_toTwoDigitString(time.second)}',
Day.values[value],
time,
platformChannelSpecifics);
}
The given problem is that I do not know how to stop the weekly Notifcation after x Weeks
This Code is from the Plugin itself, to give you an insight how the function works.
I can specify the day, the time and the repeatinterval but not for how long the notification should be active.
/// Shows a notification on a daily interval at the specified time
Future<void> showWeeklyAtDayAndTime(int id, String title, String body,
Day day, Time notificationTime, NotificationDetails notificationDetails,
{String payload}) async {
_validateId(id);
var serializedPlatformSpecifics =
_retrievePlatformSpecificNotificationDetails(notificationDetails);
await _channel.invokeMethod('showWeeklyAtDayAndTime', <String, dynamic>{
'id': id,
'title': title,
'body': body,
'calledAt': DateTime.now().millisecondsSinceEpoch,
'repeatInterval': RepeatInterval.Weekly.index,
'repeatTime': notificationTime.toMap(),
'day': day.value,
'platformSpecifics': serializedPlatformSpecifics,
'payload': payload ?? ''
});
}
EDIT: code snippet
Future<void> scheduleActivityList() async {
for (int i = 0; i < _savedActivityList.length; i++) {
if ((_savedActivityList[i].startDate
.difference(DateTime.now())
.inMinutes <= 10080) && (_savedActivityList[i].scheduled == false)) {
_savedActivityList[i].scheduled = true;
scheduleNotification(await _getNextAvailableId(),_savedActivityList[i].startDate
.difference(DateTime.now())
.inMinutes, _savedActivityList[i].title);
if (_savedActivityList[i].startDate /// deletes past notification
.difference(DateTime.now())
.inMinutes <= 0){
_savedActivityList.removeAt(i);
}
}
await saveActivityList();
}
}
First of all you need to find the current date say 22-04-2020 and
you have to add the duration as like your wish say 6 weeks to the
current day to get end date say 27-05-2020.
Then you have to loop through the start date and end date.
While looping you have to take each date and find out whether is it
your desired day or not.
If you find your desired day for the given date, for example
Friday for the date 24-04-2020 with your time, then pass this date to the scheduleNotification() and set this date to the variable scheduledNotificationDateTime.

ion picker options overlaps

Currently, I am working on a ionic application which require ion-picker (multi column picker).
I got the data perfectly as I want but just one time means when I open picker for the first time, but after that when I click second time the all options overlapped, I am not able to upload image because of stackoverflow (10 reputation) policy. so please refer the example here
, I have also tried selectedIndex: 0 as suggested in the GitHub link but nothing change.please let me know if anyone know how to solve this.
Thanks in advance
var myColumns = [
{
name: "days",
options: this.day2,
selectedIndex: 1
},
{
name: "Hours",
options: this.hours2,
selectedIndex: 1
},
{
name: "Minutes",
options: this.minutes2,
selectedIndex: 1
},
{
name: "dayType",
options: this.HourType,
selectedIndex: 1
}
];
const picker = await this.pickerCtrl.create({
buttons: [
{
text: "Done"
},
{ text: "Cancel" }
],
mode: "md",
cssClass: ["datePicker"],
columns: myColumns
});
First of all, I found that the problem is that you put the options with an array, I mean you don't put them manually.
Then I think you have 2 options:
first one is put the options manually(in my opinion is not worth it), and the second one, i found that if you put selectedIndex: 0, on the columns properties, the overlap should be gone, but the picker will open always on the first entry. And if you override this selectedIndex: 0, and put a variable that you can change when ever you want, the overlap should be gone, for the most of the entries, except for the first one and the last one.
That's what occur to me.
Hope this help you.
Edit:
I was looking around and just found this:
let picker = await this.pickerCtrl.create(opts);
picker.present();
picker.onDidDismiss().then(async data => {
let num = await picker.getColumn('num');
this.pickerData = num.options[num.selectedIndex].text;
this.pickerDataPrevious = num.selectedIndex;
num.options.forEach(element => {
delete element.selected;
delete element.duration;
delete element.transform;
});
});
If you loop the options (in that case num.options) and delete this properties, the picker data should work correctly
Just before picker.present();
Add these lines :
picker.columns[0].options.forEach(element => {
delete element.selected;
delete element.duration;
delete element.transform;
});
Ref: https://github.com/ionic-team/ionic-framework/issues/17664
Yup, this is a known issue
The problem is that there are 2 properties being added to the original column's options object: duration & transform
As a workaround, you can manually remove these 2 properties. Here's a clean way to do it.
onShowOptions(): void {
const selectedIndex = this.findOptionIndex(this.defaultLanguage, this.languagesList);
this.pickerController
.create({
columns: [
{
selectedIndex: selectedIndex,
name: 'item',
// here's where the magic happens: spread the object, remove duration & transform properties and keep the rest
options: this.options.map(({ duration, transform, ...rest }) => rest),
},
],
buttons: [
{
text: 'Cancel',
},
{
text: 'Done',
handler: ({ item }) => this.optionSelected(item),
},
],
})
.then((picker: HTMLIonPickerElement) => picker.present());
}

ion2-calendar show all days in calendar

I am using ion2-calendar in ionic 3, currently, it's allowing to select day starts from today and not previous. I want to select previous days also Please help in this.
I am using the following code,
optionsRange: CalendarComponentOptions = {
pickMode: 'range',
disableWeeks: [0, 6],
};
Thanks in advance
You can see previous dates by adding canBackwardsSelected: true to the const options: CalendarModalOptions then the code will be as follows using Ionic ModalController.
openCalendar() {
const options: CalendarModalOptions = {
title: 'BASIC',
canBackwardsSelected: true, //By making this true you can access the disabled dates
};
let myCalendar = this.modalCtrl.create(CalendarModal, {
options: options
});
myCalendar.present();
myCalendar.onDidDismiss((date: CalendarResult, type: string) => {
console.log(date);
})
}
Then you just have to call openCalendar() from a button click at the HTML end to see enabled past dates.
edit your ts file this will select date between from and to only not after or before
test: DayConfig[]=[];
public optionsRange: CalendarComponentOptions = {
//from: new Date(2019, 0, 1),
from: new Date(2019, 11, 1),
to: new Date(2020, 2, 15),
pickMode: 'range',
daysConfig: this.test
};

How To Disable Specific Days and Dates Using BeforeShowDay In jQueryUiDatepicker?

I already have functioning code in jQueryUiDatepicker that disables Fridays and Saturdays and all previous days (plus 2 days). My issue is trying to add 2 specific dates to this existing Datepicker code that will also disable these dates.
This is my existing code on starting line 92 in jQueryUiDatepicker:
beforeShowDay: function(date) {
var show = true;
if(date.getDay()==5||date.getDay()==6) show=false
return [show];
},
beforeShow: function(){
var dateTime = new Date();
var hour = dateTime.getHours();
//If Hour is greater or equals to 8AM
if(hour >= 08){
//Disable all past days including tomorrow and today
$(this).datepicker( "option", "minDate", "+2" );
}
},
I am trying to disable 18th and 19th October 2017 and failing, this is the code I have added directly underneath the above code:
beforeShowDay: var array = ['18/10/2017', '19/10/2017']
$('input').datepicker({
beforeShowDay: function(date){
var string = jQuery.datepicker.formatDate('dd/mm/yy', date);
return [ array.indexOf(string) == -1 ]
},
My question is how can I disable all previous dates, all Fridays and Saturdays and these 2 dates in the October?
Note# This coding has to be done in jquery.ui.datepicker, not a script in html
Hope this helps
use inArray instead of indexOf and you can also disable all previous dates using minDate
var array = ["18/10/2017", "19/10/2017"];
$(function() {
$('input').datepicker({
minDate: new Date(),
beforeShowDay: function (date) {
$thisDate = date.getDate() + "/" + (date.getMonth() + 1) + "/" + date.getFullYear();
var day = date.getDay();
if ($.inArray($thisDate, array) == -1&&day!=5&&day!=6) {
return [true, ""];
} else {
return [false, "", "Unavailable"];
}
}
});
});
DEMO

ChartJS / MomentJS - Unable to remove deprecation warning. Graph not showing in firefox/opera

so browsers throw
warning about using momentJS incorrectly.
Deprecation warning: value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.
Arguments:
[0] _isAMomentObject: true, _isUTC: false, _useUTC: false, _l: undefined, _i: 12.30, _f: false, _strict: undefined, _locale: [object Object]
Error
So i looked at my code
data: {
labels: ['01.01', '02.01', '03.01', '04.01', '05.01', '06.01', '07.01', '08.01', '09.01', '10.01', '11.01', '12.01'],
datasets: createChatterData(data, this)
},
And read that I should provide a format when dealing with non iso strings.
labels: [moment('01.01', 'MM.DD'), moment('02.01', 'MM.DD'), ...];
Ok that removed first deprecation.
But my datasets data also contains of date
dataset.data.pushObject({
x: moment(datum).format('MM.DD'),
y: parseInt(moment(datum).format('YYYY'))
});
So I tried different variations to that (premodified ambigious datetime)
x: moment(date, 'YYYY.MM.DD').format('MM.DD')
and
x: moment(date, 'MM.DD')
But my graph doesnt map correctly anymore.
Example of codepen chart working in chrome: http://codepen.io/kristjanrein/pen/wJrQLE
Does not display in firefox/opera
I see a couple of issues here.
1) Since you want your X axis to be a time scale, then you should leave your X data value as a moment object. Your current implementation is creating a moment object from a date string and then formatting it back to a string. When you do this, chart.js then takes the string and tries to create a moment object internally when it builds the chart.
Therefore, It is best to keep the data as either a Date or Moment object and use the time scale configuration properties to determine how the data is displayed on the chart. This prevents chart.js from having to construct the moment object and guess at the string format.
2) You are using the pre-2.0 way to create a chart when you use Chart.Scatter. Instead you should use the new style (new Chart()) and pass in a type property.
Here is a modified version of you code that results in no browser warnings and works in Chrome and Firefox (I did not test in Opera).
var getData = function() {
var dummyDataset = [
'2007-11-09T00:00:00.000Z',
'2006-08-04T00:00:00.000Z',
'2006-08-06T00:00:00.000Z',
'2008-01-10T00:00:00.000Z'
];
return dummyDataset.map(function(datum) {
var myMoment = moment(datum);
return {
x: myMoment,
y: parseInt(myMoment.format('YYYY')),
};
});
};
var ctx = document.getElementById("chart1").getContext("2d");
var myScatter = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "My First dataset",
borderColor: 'rgb(255, 99, 132)',
fill: false,
pointRadius: 4,
pointHoverRadius: 8,
showLine: false,
data: getData()
}]
},
options: {
responsive: true,
title: {
display: true,
text: 'Random Data'
},
legend: {
display: true,
labels: {
fontSize: 10,
boxWidth: 20
}
},
elements: {
point: {
pointStyle: 'rect'
}
},
hover: {
mode: 'nearest'
},
scales: {
xAxes: [{
type: 'time',
position: 'bottom',
scaleLabel: {
display: true,
labelString: 'Months'
},
time: {
unit: 'month',
displayFormats: {
month: 'MM'
},
}
}],
yAxes: [ {
type: 'linear',
ticks: {
min: 2005,
max: 2015,
stepSize: 1
},
scaleLabel: {
display: true,
labelString: 'Year'
}
}]
}
}
});
You can see it in action at this forked codepen.
One other thing to keep in mind is that because your data spans multiple years, you will see duplicate months on the X axis. Remember, a time scale is used to plot dates so even if you only display the months, a data point with the same month but with different years will not be plotted at the same location.
If you are actually only wanting to show month string/number values in the X axis, then you should not use the time scale at all and use the linear scale instead. Then when you build your data values, you would extract the month from the data (the same way you are already doing for your Y value).
var getData = function() {
var dummyDataset = [
'2007-11-09T00:00:00.000Z',
'2006-08-04T00:00:00.000Z',
'2006-08-06T00:00:00.000Z',
'2008-01-10T00:00:00.000Z'
];
return dummyDataset.map(function(datum) {
var myMoment = moment(datum);
return {
x: parseInt(myMoment.format('MM')),
y: parseInt(myMoment.format('YYYY')),
};
});
};
So in addition to jordan's answer
I changed my labels and x axis from
['01.01', '02.01', ...] to [1,2,...]
and
from type: 'time' to type: 'linear'
And to make it map not only by month but also by day. I had to make date objects to correct floats. 05.20 to 5.66
const date = datum.key;
const day = parseInt(moment(date).format('DD')) / 30 * 100;
const fullDate = parseFloat(moment(date).format('MM') + '.' + Math.round(day))
// 05.10 would be 5.3 (10 of 30 is 33%)
{
x: fullDate,
y: parseInt(moment(date).format('YYYY'))
date: date, // for tooltip
count: count // for tooltip
}
And i also had to make corrections to my tooltips
callbacks: {
title: function([tooltipItem], data) {
const tooltipInfo = getTooltip(tooltipItem, data.datasets);
return tooltipInfo.date;
},
label: function(tooltipItem, data) {
const tooltipInfo = getTooltip(tooltipItem, data.datasets);
return i18n.t('chart.count') + ': ' + tooltipInfo.count;
},
}
corresponding tooltip dataset
function getTooltip(tooltipItem, datasets) {
return datasets[tooltipItem.datasetIndex].data.find(datum => {
return datum.x === tooltipItem.xLabel && datum.y === tooltipItem.yLabel;
});
}