Commit e50f6f2f by Sebastián Katzer

Merge branch 'x'

parents ee7432f4 3d5f9b5a
/src/windows.old
/src/windows/**/.vs
/src/windows/**/bin
/src/windows/**/obj
\ No newline at end of file
...@@ -3,6 +3,9 @@ ChangeLog ...@@ -3,6 +3,9 @@ ChangeLog
Please also read the [Upgrade Guide](https://github.com/katzer/cordova-plugin-local-notifications/wiki/Upgrade-Guide) for more information. Please also read the [Upgrade Guide](https://github.com/katzer/cordova-plugin-local-notifications/wiki/Upgrade-Guide) for more information.
#### Version 0.8.5 (22.05.2017)
- iOS 10
#### Version 0.8.4 (04.01.2016) #### Version 0.8.4 (04.01.2016)
- Bug fixes - Bug fixes
- SyntaxError: missing ) after argument list - SyntaxError: missing ) after argument list
......
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2013-2015 appPlant UG, Inc. Copyright 2013 appPlant GmbH
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
......
{ {
"name": "cordova-plugin-local-notifications", "name": "cordova-plugin-local-notifications",
"version": "0.8.4", "version": "0.0.9",
"description": "Schedule, trigger and query local notifications on iOS and Android", "description": "Schedules and queries for local notifications",
"cordova": { "cordova": {
"id": "de.appplant.cordova.plugin.local-notification", "id": "cordova-plugin-local-notifications",
"platforms": [ "platforms": [
"ios", "ios",
"android",
"windows" "windows"
] ]
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/katzer/cordova-plugin-local-notifications.git" "url": "git+https://github.com/katzer/cordova-plugin-local-notifications.git#x"
}, },
"keywords": [ "keywords": [
"appplant", "appplant",
"notification", "notification",
"local notification", "local notification",
"user notification",
"ecosystem:cordova", "ecosystem:cordova",
"cordova-ios", "cordova-ios",
"cordova-android", "cordova-android",
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
{ {
"name": "cordova-windows", "name": "cordova-windows",
"version": ">=4.2.0" "version": ">=4.2.0"
},
{
"name": "apple-ios",
"version": ">=10.0.0"
} }
], ],
"author": "Sebastián Katzer", "author": "Sebastián Katzer",
......
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,13 +17,16 @@ ...@@ -17,13 +17,16 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import android.os.Bundle;
import de.appplant.cordova.plugin.notification.Notification; import de.appplant.cordova.plugin.notification.Notification;
import de.appplant.cordova.plugin.notification.receiver.AbstractClearReceiver;
import static de.appplant.cordova.plugin.notification.Request.EXTRA_LAST;
/** /**
...@@ -31,17 +34,24 @@ import de.appplant.cordova.plugin.notification.Notification; ...@@ -31,17 +34,24 @@ import de.appplant.cordova.plugin.notification.Notification;
* notification manually. It un-persists the cleared notification from the * notification manually. It un-persists the cleared notification from the
* shared preferences. * shared preferences.
*/ */
public class ClearReceiver extends de.appplant.cordova.plugin.notification.ClearReceiver { public class ClearReceiver extends AbstractClearReceiver {
/** /**
* Called when a local notification was cleared from outside of the app. * Called when a local notification was cleared from outside of the app.
* *
* @param notification * @param notification Wrapper around the local notification.
* Wrapper around the local notification * @param bundle The bundled extras.
*/ */
@Override @Override
public void onClear (Notification notification) { public void onClear (Notification notification, Bundle bundle) {
super.onClear(notification); boolean isLast = bundle.getBoolean(EXTRA_LAST, false);
if (isLast) {
notification.cancel();
} else {
notification.clear();
}
LocalNotification.fireEvent("clear", notification); LocalNotification.fireEvent("clear", notification);
} }
......
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.Builder;
import de.appplant.cordova.plugin.notification.Notification;
import de.appplant.cordova.plugin.notification.TriggerReceiver;
/**
* The receiver activity is triggered when a notification is clicked by a user.
* The activity calls the background callback and brings the launch intent
* up to foreground.
*/
public class ClickActivity extends de.appplant.cordova.plugin.notification.ClickActivity {
/**
* Called when local notification was clicked by the user.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClick(Notification notification) {
LocalNotification.fireEvent("click", notification);
super.onClick(notification);
if (notification.getOptions().isOngoing())
return;
String event = notification.isRepeating() ? "clear" : "cancel";
LocalNotification.fireEvent(event, notification);
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder
.setTriggerReceiver(TriggerReceiver.class)
.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.localnotification;
import android.os.Bundle;
import android.support.v4.app.RemoteInput;
import org.json.JSONException;
import org.json.JSONObject;
import de.appplant.cordova.plugin.notification.Notification;
import de.appplant.cordova.plugin.notification.receiver.AbstractClickReceiver;
import static de.appplant.cordova.plugin.notification.Options.EXTRA_LAUNCH;
import static de.appplant.cordova.plugin.notification.Request.EXTRA_LAST;
/**
* The receiver activity is triggered when a notification is clicked by a user.
* The activity calls the background callback and brings the launch intent
* up to foreground.
*/
public class ClickReceiver extends AbstractClickReceiver {
/**
* Called when local notification was clicked by the user.
*
* @param notification Wrapper around the local notification.
* @param bundle The bundled extras.
*/
@Override
public void onClick(Notification notification, Bundle bundle) {
String action = getAction();
JSONObject data = new JSONObject();
setTextInput(action, data);
launchAppIf();
LocalNotification.fireEvent(action, notification, data);
if (notification.getOptions().isSticky())
return;
if (isLast()) {
notification.cancel();
} else {
notification.clear();
}
}
/**
* Set the text if any remote input is given.
*
* @param action The action where to look for.
* @param data The object to extend.
*/
private void setTextInput(String action, JSONObject data) {
Bundle input = RemoteInput.getResultsFromIntent(getIntent());
if (input == null)
return;
try {
data.put("text", input.getString(action));
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* Launch app if requested by user.
*/
private void launchAppIf() {
boolean doLaunch = getIntent().getBooleanExtra(EXTRA_LAUNCH, true);
if (!doLaunch)
return;
launchApp();
}
/**
* If the notification was the last scheduled one by request.
*/
private boolean isLast() {
return getIntent().getBooleanExtra(EXTRA_LAST, false);
}
}
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,14 +17,16 @@ ...@@ -17,14 +17,16 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import android.os.Bundle;
import de.appplant.cordova.plugin.notification.Builder; import de.appplant.cordova.plugin.notification.Builder;
import de.appplant.cordova.plugin.notification.Manager;
import de.appplant.cordova.plugin.notification.Notification; import de.appplant.cordova.plugin.notification.Notification;
import de.appplant.cordova.plugin.notification.receiver.AbstractTriggerReceiver;
/** /**
* The alarm receiver is triggered when a scheduled alarm is fired. This class * The alarm receiver is triggered when a scheduled alarm is fired. This class
...@@ -32,38 +34,39 @@ import de.appplant.cordova.plugin.notification.Notification; ...@@ -32,38 +34,39 @@ import de.appplant.cordova.plugin.notification.Notification;
* Android notification bar. The notification uses the default notification * Android notification bar. The notification uses the default notification
* sound and it vibrates the phone. * sound and it vibrates the phone.
*/ */
public class TriggerReceiver extends de.appplant.cordova.plugin.notification.TriggerReceiver { public class TriggerReceiver extends AbstractTriggerReceiver {
/** /**
* Called when a local notification was triggered. Does present the local * Called when a local notification was triggered. Does present the local
* notification, re-schedule the alarm if necessary and fire trigger event. * notification, re-schedule the alarm if necessary and fire trigger event.
* *
* @param notification * @param notification Wrapper around the local notification.
* Wrapper around the local notification * @param bundle The bundled extras.
* @param updated
* If an update has triggered or the original
*/ */
@Override @Override
public void onTrigger (Notification notification, boolean updated) { public void onTrigger (Notification notification, Bundle bundle) {
super.onTrigger(notification, updated); int badge = notification.getOptions().getBadgeNumber();
if (!updated) { if (badge > 0) {
LocalNotification.fireEvent("trigger", notification); Manager.getInstance(notification.getContext()).setBadge(badge);
} }
notification.show();
LocalNotification.fireEvent("trigger", notification);
} }
/** /**
* Build notification specified by options. * Build notification specified by options.
* *
* @param builder * @param builder Notification builder.
* Notification builder * @param bundle The bundled extras.
*/ */
@Override @Override
public Notification buildNotification (Builder builder) { public Notification buildNotification (Builder builder, Bundle bundle) {
return builder return builder
.setTriggerReceiver(TriggerReceiver.class) .setClickActivity(ClickReceiver.class)
.setClickActivity(ClickActivity.class)
.setClearReceiver(ClearReceiver.class) .setClearReceiver(ClearReceiver.class)
.setExtras(bundle)
.build(); .build();
} }
......
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in * Version 2.0 (the 'License'). You may not use this file except in
...@@ -17,28 +13,16 @@ ...@@ -17,28 +13,16 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
package de.appplant.cordova.plugin.notification; repositories {
mavenCentral()
/** }
* The clear intent receiver is triggered when the user clears a
* notification manually. It un-persists the cleared notification from the
* shared preferences.
*/
public class ClearReceiver extends AbstractClearReceiver {
/** if (!project.ext.has('appShortcutBadgerVersion')) {
* Called when a local notification was cleared from outside of the app. ext.appShortcutBadgerVersion = '1.1.19'
* }
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClear (Notification notification) {
notification.clear();
}
dependencies {
compile "me.leolin:ShortcutBadger:${appShortcutBadgerVersion}@aar"
} }
/*
* Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
package de.appplant.cordova.plugin.notification;
import org.json.JSONObject;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import de.appplant.cordova.plugin.notification.trigger.DateTrigger;
import de.appplant.cordova.plugin.notification.trigger.IntervalTrigger;
import de.appplant.cordova.plugin.notification.trigger.MatchTrigger;
import static de.appplant.cordova.plugin.notification.trigger.IntervalTrigger.Unit;
/**
* An object you use to specify a notification’s content and the condition
* that triggers its delivery.
*/
public final class Request {
// Key name for bundled extras
static final String EXTRA_OCCURRENCE = "NOTIFICATION_OCCURRENCE";
// Key name for bundled extras
public static final String EXTRA_LAST = "NOTIFICATION_LAST";
// The options spec
private final Options options;
// The right trigger for the options
private final DateTrigger trigger;
// How often the trigger shall occur
private final int count;
// The trigger spec
private final JSONObject spec;
// The current trigger date
private Date triggerDate;
/**
* Constructor
*
* @param options The options spec.
*/
public Request(Options options) {
this.options = options;
this.spec = options.getTrigger();
this.count = spec.optInt("count", 1);
this.trigger = buildTrigger();
this.triggerDate = trigger.getNextTriggerDate(getBaseDate());
}
/**
* Gets the options spec.
*/
public Options getOptions() {
return options;
}
/**
* The identifier for the request.
*
* @return The notification ID as the string
*/
public String getIdentifier() {
return options.getId().toString() + "-" + getOccurrence();
}
/**
* The value of the internal occurrence counter.
*/
int getOccurrence() {
return trigger.getOccurrence();
}
/**
* If there's one more trigger date to calculate.
*/
private boolean hasNext() {
return triggerDate != null && getOccurrence() < count;
}
/**
* Moves the internal occurrence counter by one.
*/
boolean moveNext() {
if (hasNext()) {
triggerDate = getNextTriggerDate();
} else {
triggerDate = null;
}
return this.triggerDate != null;
}
/**
* Gets the current trigger date.
*
* @return null if there's no trigger date.
*/
Date getTriggerDate() {
Calendar now = Calendar.getInstance();
if (triggerDate == null)
return null;
if ((now.getTimeInMillis() - triggerDate.getTime()) > 60000) {
return null;
}
return triggerDate;
}
/**
* Gets the next trigger date based on the current trigger date.
*/
private Date getNextTriggerDate() {
return trigger.getNextTriggerDate(triggerDate);
}
/**
* Build the trigger specified in options.
*/
private DateTrigger buildTrigger() {
Object every = spec.opt("every");
if (every instanceof JSONObject) {
return new MatchTrigger(getDateMatchingComponents());
}
Unit unit = getUnit();
int ticks = getTicks();
return new IntervalTrigger(ticks, unit);
}
/**
* Gets the unit value.
*/
private Unit getUnit() {
Object every = spec.opt("every");
String unit = "SECOND";
if (spec.has("unit")) {
unit = spec.optString("unit", "second");
} else
if (every instanceof String) {
unit = spec.optString("every", "second");
}
return Unit.valueOf(unit.toUpperCase());
}
/**
* Gets the tick value.
*/
private int getTicks() {
Object every = spec.opt("every");
int ticks = 0;
if (spec.has("at")) {
ticks = 0;
} else
if (spec.has("in")) {
ticks = spec.optInt("in", 0);
} else
if (every instanceof String) {
ticks = 1;
} else
if (!(every instanceof JSONObject)) {
ticks = spec.optInt("every", 0);
}
return ticks;
}
/**
* Gets an array of all date parts to construct a datetime instance.
*
* @return [min, hour, day, month, year]
*/
private List<Integer> getDateMatchingComponents() {
JSONObject every = spec.optJSONObject("every");
return Arrays.asList(
(Integer) every.opt("minute"),
(Integer) every.opt("hour"),
(Integer) every.opt("day"),
(Integer) every.opt("month"),
(Integer) every.opt("year")
);
}
/**
* Gets the base date from where to calculate the next trigger date.
*/
private Date getBaseDate() {
if (spec.has("at")) {
return new Date(spec.optLong("at", 0) * 1000);
} else {
return new Date();
}
}
}
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
package de.appplant.cordova.plugin.notification;
/**
* The alarm receiver is triggered when a scheduled alarm is fired. This class
* reads the information in the intent and displays this information in the
* Android notification bar. The notification uses the default notification
* sound and it vibrates the phone.
*/
public class TriggerReceiver extends AbstractTriggerReceiver {
/**
* Called when a local notification was triggered. Does present the local
* notification and re-schedule the alarm if necessary.
*
* @param notification
* Wrapper around the local notification
* @param updated
* If an update has triggered or the original
*/
@Override
public void onTrigger (Notification notification, boolean updated) {
notification.show();
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification.action;
import android.content.Context;
import android.support.v4.app.RemoteInput;
import org.json.JSONArray;
import org.json.JSONObject;
import de.appplant.cordova.plugin.notification.util.AssetUtil;
/**
* Holds the icon and title components that would be used in a
* NotificationCompat.Action object. Does not include the PendingIntent so
* that it may be generated each time the notification is built. Necessary to
* compensate for missing functionality in the support library.
*/
public final class Action {
// Key name for bundled extras
public static final String EXTRA_ID = "NOTIFICATION_ACTION_ID";
// The id for the click action
public static final String CLICK_ACTION_ID = "click";
// The application context
private final Context context;
// The action spec
private final JSONObject options;
/**
* Structure to encapsulate a named action that can be shown as part of
* this notification.
*
* @param context The application context.
* @param options The action options.
*/
Action (Context context, JSONObject options) {
this.context = context;
this.options = options;
}
/**
* Gets the ID for the action.
*/
public String getId() {
return options.optString("id", getTitle());
}
/**
* Gets the Title for the action.
*/
public String getTitle() {
return options.optString("title", "unknown");
}
/**
* Gets the icon for the action.
*/
public int getIcon() {
AssetUtil assets = AssetUtil.getInstance(context);
String resPath = options.optString("icon");
int resId = assets.getResId(resPath);
if (resId == 0) {
resId = android.R.drawable.screen_background_dark;
}
return resId;
}
/**
* Gets the value of the launch flag.
*/
public boolean isLaunchingApp() {
return options.optBoolean("launch", false);
}
/**
* Gets the type for the action.
*/
public boolean isWithInput() {
String type = options.optString("type");
return type.equals("input");
}
/**
* Gets the input config in case of the action is of type input.
*/
public RemoteInput getInput() {
return new RemoteInput.Builder(getId())
.setLabel(options.optString("emptyText"))
.setAllowFreeFormInput(options.optBoolean("editable", true))
.setChoices(getChoices())
.build();
}
/**
* List of possible choices for input actions.
*/
private String[] getChoices() {
JSONArray opts = options.optJSONArray("choices");
if (opts == null)
return null;
String[] choices = new String[opts.length()];
for (int i = 0; i < choices.length; i++) {
choices[i] = opts.optString(i);
}
return choices;
}
}
\ No newline at end of file
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification.action;
import android.content.Context;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.N;
public final class ActionGroup {
// Default action group id
private static final String GENERAL_ACTION_GROUP = "DEFAULT_GROUP";
// Saves all groups for later lookup.
private static final Map<String, ActionGroup> groups =
new HashMap<String, ActionGroup>();
// The ID of the action group.
private final String id;
// List of actions
private final Action[] actions;
/**
* Lookup the action groups with the specified group id.
*
* @param id The ID of the action group to find.
*
* @return Null if no group was found.
*/
public static ActionGroup lookup(String id) {
return groups.get(id);
}
/**
* Register the action group for later lookup.
*
* @param group The action group to register.
*/
public static void register (ActionGroup group) {
if (!group.getId().equalsIgnoreCase(GENERAL_ACTION_GROUP)) {
groups.put(group.getId(), group);
}
}
/**
* Creates an action group by parsing the specified action specs.
*
* @param spec The action group spec containing the id and list of actions.
*
* @return A new action group.
*/
public static ActionGroup parse (Context context, JSONObject spec) {
String id = spec.optString("actionGroupId", GENERAL_ACTION_GROUP);
JSONArray list = spec.optJSONArray("actions");
if (list == null || list.length() == 0)
return null;
List<Action> actions = new ArrayList<Action>(list.length());
for (int i = 0; i < list.length(); i++) {
JSONObject opts = list.optJSONObject(i);
String type = opts.optString("type", "button");
if (type.equals("input") && SDK_INT < N) {
Log.w("Action", "Type input is not supported");
continue;
}
if (!(type.equals("button") || type.equals("input"))) {
Log.w("Action", "Unknown type: " + type);
continue;
}
actions.add(new Action(context, opts));
}
if (actions.isEmpty())
return null;
return new ActionGroup(id, actions.toArray(new Action[actions.size()]));
}
/**
* Creates an action group.
*
* @param id The ID of the group.
* @param actions The list of actions.
*/
private ActionGroup(String id, Action[] actions) {
this.id = id;
this.actions = actions;
}
/**
* Gets the action group id.
*/
public String getId() {
return id;
}
/**
* Gets the action list.
*/
public Action[] getActions() {
return actions;
}
}
\ No newline at end of file
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,19 +17,17 @@ ...@@ -17,19 +17,17 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
package de.appplant.cordova.plugin.notification; package de.appplant.cordova.plugin.notification.receiver;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import org.json.JSONException; import de.appplant.cordova.plugin.notification.Manager;
import org.json.JSONObject; import de.appplant.cordova.plugin.notification.Notification;
/** /**
* Abstract delete receiver for local notifications. Creates the local * Abstract delete receiver for local notifications. Creates the local
...@@ -40,36 +38,27 @@ abstract public class AbstractClearReceiver extends BroadcastReceiver { ...@@ -40,36 +38,27 @@ abstract public class AbstractClearReceiver extends BroadcastReceiver {
/** /**
* Called when the notification was cleared from the notification center. * Called when the notification was cleared from the notification center.
* *
* @param context * @param context Application context
* Application context * @param intent Received intent with content data
* @param intent
* Received intent with content data
*/ */
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
JSONObject options; int toastId = bundle.getInt(Notification.EXTRA_ID);
Notification toast = Manager.getInstance(context).get(toastId);
try { if (toast == null)
String data = bundle.getString(Options.EXTRA);
options = new JSONObject(data);
} catch (JSONException e) {
e.printStackTrace();
return; return;
}
Notification notification =
new Builder(context, options).build();
onClear(notification); onClear(toast, bundle);
} }
/** /**
* Called when a local notification was cleared from outside of the app. * Called when a local notification was cleared from outside of the app.
* *
* @param notification * @param notification Wrapper around the local notification.
* Wrapper around the local notification * @param bundle The bundled extras.
*/ */
abstract public void onClear (Notification notification); abstract public void onClear (Notification notification, Bundle bundle);
} }
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,54 +17,48 @@ ...@@ -17,54 +17,48 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
package de.appplant.cordova.plugin.notification; package de.appplant.cordova.plugin.notification.receiver;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import org.json.JSONException; import de.appplant.cordova.plugin.notification.Manager;
import org.json.JSONObject; import de.appplant.cordova.plugin.notification.Notification;
import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static de.appplant.cordova.plugin.notification.action.Action.CLICK_ACTION_ID;
import static de.appplant.cordova.plugin.notification.action.Action.EXTRA_ID;
/** /**
* Abstract content receiver activity for local notifications. Creates the * Abstract content receiver activity for local notifications. Creates the
* local notification and calls the event functions for further proceeding. * local notification and calls the event functions for further proceeding.
*/ */
abstract public class AbstractClickActivity extends Activity { abstract public class AbstractClickReceiver extends Activity {
/** /**
* Called when local notification was clicked to launch the main intent. * Called when local notification was clicked to launch the main intent.
* *
* @param state * @param state Saved instance state
* Saved instance state
*/ */
@Override @Override
public void onCreate (Bundle state) { public void onCreate (Bundle state) {
super.onCreate(state); super.onCreate(state);
Intent intent = getIntent(); Intent intent = getIntent();
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
Context context = getApplicationContext(); Context context = getApplicationContext();
int toastId = bundle.getInt(Notification.EXTRA_ID);
try { Notification toast = Manager.getInstance(context).get(toastId);
String data = bundle.getString(Options.EXTRA);
JSONObject options = new JSONObject(data);
Builder builder = if (toast == null)
new Builder(context, options); return;
Notification notification = onClick(toast, bundle);
buildNotification(builder);
onClick(notification);
} catch (JSONException e) {
e.printStackTrace();
}
} }
/** /**
...@@ -80,23 +74,22 @@ abstract public class AbstractClickActivity extends Activity { ...@@ -80,23 +74,22 @@ abstract public class AbstractClickActivity extends Activity {
/** /**
* Called when local notification was clicked by the user. * Called when local notification was clicked by the user.
* *
* @param notification * @param notification Wrapper around the local notification.
* Wrapper around the local notification * @param bundle The bundled extras.
*/ */
abstract public void onClick (Notification notification); abstract public void onClick (Notification notification, Bundle bundle);
/** /**
* Build notification specified by options. * The invoked action.
*
* @param builder
* Notification builder
*/ */
abstract public Notification buildNotification (Builder builder); protected String getAction() {
return getIntent().getExtras().getString(EXTRA_ID, CLICK_ACTION_ID);
}
/** /**
* Launch main intent from package. * Launch main intent from package.
*/ */
public void launchApp() { protected void launchApp() {
Context context = getApplicationContext(); Context context = getApplicationContext();
String pkgName = context.getPackageName(); String pkgName = context.getPackageName();
...@@ -105,7 +98,7 @@ abstract public class AbstractClickActivity extends Activity { ...@@ -105,7 +98,7 @@ abstract public class AbstractClickActivity extends Activity {
.getLaunchIntentForPackage(pkgName); .getLaunchIntentForPackage(pkgName);
intent.addFlags( intent.addFlags(
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); FLAG_ACTIVITY_REORDER_TO_FRONT | FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent); context.startActivity(intent);
} }
......
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,21 +17,19 @@ ...@@ -17,21 +17,19 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
package de.appplant.cordova.plugin.notification; package de.appplant.cordova.plugin.notification.receiver;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import org.json.JSONException; import de.appplant.cordova.plugin.notification.Builder;
import org.json.JSONObject; import de.appplant.cordova.plugin.notification.Manager;
import de.appplant.cordova.plugin.notification.Notification;
import java.util.Calendar; import de.appplant.cordova.plugin.notification.Options;
/** /**
* Abstract broadcast receiver for local notifications. Creates the * Abstract broadcast receiver for local notifications. Creates the
...@@ -42,81 +40,42 @@ abstract public class AbstractTriggerReceiver extends BroadcastReceiver { ...@@ -42,81 +40,42 @@ abstract public class AbstractTriggerReceiver extends BroadcastReceiver {
/** /**
* Called when an alarm was triggered. * Called when an alarm was triggered.
* *
* @param context * @param context Application context
* Application context * @param intent Received intent with content data
* @param intent
* Received intent with content data
*/ */
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
Options options; int toastId = bundle.getInt(Notification.EXTRA_ID);
Options options = Manager.getInstance(context).getOptions(toastId);
try {
String data = bundle.getString(Options.EXTRA);
JSONObject dict = new JSONObject(data);
options = new Options(context).parse(dict);
} catch (JSONException e) {
e.printStackTrace();
return;
}
if (options == null) if (options == null)
return; return;
if (isFirstAlarmInFuture(options)) Builder builder = new Builder(options);
return; Notification toast = buildNotification(builder, bundle);
Builder builder = new Builder(options); if (toast == null)
Notification notification = buildNotification(builder); return;
boolean updated = notification.isUpdate(false);
onTrigger(notification, updated); onTrigger(toast, bundle);
} }
/** /**
* Called when a local notification was triggered. * Called when a local notification was triggered.
* *
* @param notification * @param notification Wrapper around the local notification.
* Wrapper around the local notification * @param bundle The bundled extras.
* @param updated
* If an update has triggered or the original
*/ */
abstract public void onTrigger (Notification notification, boolean updated); abstract public void onTrigger (Notification notification, Bundle bundle);
/** /**
* Build notification specified by options. * Build notification specified by options.
* *
* @param builder * @param builder Notification builder.
* Notification builder * @param bundle The bundled extras.
*/ */
abstract public Notification buildNotification (Builder builder); abstract public Notification buildNotification (Builder builder,
Bundle bundle);
/*
* If you set a repeating alarm at 11:00 in the morning and it
* should trigger every morning at 08:00 o'clock, it will
* immediately fire. E.g. Android tries to make up for the
* 'forgotten' reminder for that day. Therefore we ignore the event
* if Android tries to 'catch up'.
*/
private Boolean isFirstAlarmInFuture (Options options) {
Notification notification = new Builder(options).build();
if (!notification.isRepeating())
return false;
Calendar now = Calendar.getInstance();
Calendar alarm = Calendar.getInstance();
alarm.setTime(notification.getOptions().getTriggerDate());
int alarmHour = alarm.get(Calendar.HOUR_OF_DAY);
int alarmMin = alarm.get(Calendar.MINUTE);
int currentHour = now.get(Calendar.HOUR_OF_DAY);
int currentMin = now.get(Calendar.MINUTE);
return (currentHour != alarmHour && currentMin != alarmMin);
}
} }
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,45 +17,54 @@ ...@@ -17,45 +17,54 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
package de.appplant.cordova.plugin.notification; package de.appplant.cordova.plugin.notification.trigger;
/** import java.util.Calendar;
* The receiver activity is triggered when a notification is clicked by a user. import java.util.Date;
* The activity calls the background callback and brings the launch intent
* up to foreground. abstract public class DateTrigger {
*/
public class ClickActivity extends AbstractClickActivity { // Default unit is SECOND
public enum Unit { SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR }
// Internal counter
private int occurrence = 1;
/** /**
* Called when local notification was clicked by the user. Will * Gets the next trigger date.
* move the app to foreground. *
* @param base The date from where to calculate the trigger date.
* *
* @param notification * @return null if there's none next trigger date.
* Wrapper around the local notification */
abstract public Date getNextTriggerDate(Date base);
/**
* The value of the occurrence.
*/ */
@Override public int getOccurrence() {
public void onClick(Notification notification) { return occurrence;
launchApp();
if (notification.isRepeating()) {
notification.clear();
} else {
notification.cancel();
}
} }
/** /**
* Build notification specified by options. * Increase the occurrence by 1.
*/
void incOccurrence() {
occurrence += 1;
}
/**
* Gets a calendar instance pointing to the specified date.
* *
* @param builder * @param date The date to point.
* Notification builder
*/ */
public Notification buildNotification (Builder builder) { Calendar getCal (Date date) {
return builder.build(); Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal;
} }
} }
\ No newline at end of file
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification.trigger;
import java.util.Calendar;
import java.util.Date;
/**
* Trigger class for interval based notification. Trigger by a fixed interval
* from now.
*/
public class IntervalTrigger extends DateTrigger {
// The number of ticks per interval
private final int ticks;
// The unit of the ticks
final Unit unit;
/**
* Interval trigger based from now.
*
* @param ticks The number of ticks per interval.
* @param unit The unit of the ticks.
*/
public IntervalTrigger(int ticks, Unit unit) {
this.ticks = ticks;
this.unit = unit;
}
/**
* Gets the next trigger date.
*
* @param base The date from where to calculate the trigger date.
*
* @return null if there's none next trigger date.
*/
@Override
public Date getNextTriggerDate(Date base) {
Calendar cal = getCal(base);
addInterval(cal);
incOccurrence();
return cal.getTime();
}
/**
* Adds the amount of ticks to the calendar.
*
* @param cal The calendar to manipulate.
*
* @return The calendar instance.
*/
Calendar addInterval(Calendar cal) {
switch (unit) {
case SECOND:
cal.add(Calendar.SECOND, ticks);
break;
case MINUTE:
cal.add(Calendar.MINUTE, ticks);
break;
case HOUR:
cal.add(Calendar.HOUR_OF_DAY, ticks);
break;
case DAY:
cal.add(Calendar.DAY_OF_YEAR, ticks);
break;
case WEEK:
cal.add(Calendar.WEEK_OF_YEAR, ticks);
break;
case MONTH:
cal.add(Calendar.MONTH, ticks);
break;
case QUARTER:
cal.add(Calendar.MONTH, ticks * 3);
break;
case YEAR:
cal.add(Calendar.YEAR, ticks);
break;
}
return cal;
}
}
\ No newline at end of file
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification.trigger;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.DAY;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.HOUR;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.MINUTE;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.MONTH;
import static de.appplant.cordova.plugin.notification.trigger.DateTrigger.Unit.YEAR;
/**
* Trigger for date matching components.
*/
public class MatchTrigger extends IntervalTrigger {
// Used to determine the interval
private static Unit[] INTERVALS = { null, MINUTE, HOUR, DAY, MONTH, YEAR };
// The date matching components
private final List<Integer> matchers;
/**
* Date matching trigger from now.
*
* @param matchers Describes the date matching parts.
* { day: 15, month: ... }
*/
public MatchTrigger(List<Integer> matchers) {
super(1, INTERVALS[1 + matchers.indexOf(null)]);
this.matchers = matchers;
}
/**
* Gets the date from where to start calculating the initial trigger date.
*/
private Calendar getBaseTriggerDate(Date date) {
Calendar cal = getCal(date);
cal.set(Calendar.SECOND, 0);
if (matchers.get(0) != null) {
cal.set(Calendar.MINUTE, matchers.get(0));
} else {
cal.set(Calendar.MINUTE, 0);
}
if (matchers.get(1) != null) {
cal.set(Calendar.HOUR_OF_DAY, matchers.get(1));
} else {
cal.set(Calendar.HOUR_OF_DAY, 0);
}
if (matchers.get(2) != null) {
cal.set(Calendar.DAY_OF_MONTH, matchers.get(2));
}
if (matchers.get(3) != null) {
cal.set(Calendar.MONTH, matchers.get(3));
}
if (matchers.get(4) != null) {
cal.set(Calendar.YEAR, matchers.get(4));
}
return cal;
}
/**
* Gets the first trigger date.
*
* @param base The date from where to calculate the trigger date.
*
* @return null if there's none trigger date.
*/
private Date getTriggerDate (Date base) {
Calendar date = getBaseTriggerDate(base);
Calendar now = getCal(base);
if (date.compareTo(now) >= 0)
return date.getTime();
if (unit == null || date.get(Calendar.YEAR) < now.get(Calendar.YEAR))
return null;
if (date.get(Calendar.MONTH) < now.get(Calendar.MONTH)) {
switch (unit) {
case MINUTE:
case HOUR:
case DAY:
if (matchers.get(4) == null) {
return addToDate(date, now, Calendar.YEAR, 1);
} else break;
case YEAR:
return addToDate(date, now, Calendar.YEAR, 1);
}
} else
if (date.get(Calendar.DAY_OF_YEAR) < now.get(Calendar.DAY_OF_YEAR)) {
switch (unit) {
case MINUTE:
case HOUR:
if (matchers.get(3) == null) {
return addToDate(date, now, Calendar.MONTH, 1);
} else
if (matchers.get(4) == null) {
return addToDate(date, now, Calendar.YEAR, 1);
}
else break;
case MONTH:
return addToDate(date, now, Calendar.MONTH, 1);
case YEAR:
return addToDate(date, now, Calendar.YEAR, 1);
}
} else
if (date.get(Calendar.HOUR_OF_DAY) < now.get(Calendar.HOUR_OF_DAY)) {
switch (unit) {
case MINUTE:
if (matchers.get(2) == null) {
return addToDate(date, now, Calendar.DAY_OF_YEAR, 1);
} else
if (matchers.get(3) == null) {
return addToDate(date, now, Calendar.MONTH, 1);
}
else break;
case HOUR:
return addToDate(date, now, Calendar.HOUR_OF_DAY, 0);
case DAY:
return addToDate(date, now, Calendar.DAY_OF_YEAR, 1);
case MONTH:
return addToDate(date, now, Calendar.MONTH, 1);
case YEAR:
return addToDate(date, now, Calendar.YEAR, 1);
}
} else
if (date.get(Calendar.MINUTE) < now.get(Calendar.MINUTE)) {
switch (unit) {
case MINUTE:
return addToDate(date, now, Calendar.MINUTE, 1);
case HOUR:
return addToDate(date, now, Calendar.HOUR_OF_DAY, 1);
case DAY:
return addToDate(date, now, Calendar.DAY_OF_YEAR, 1);
case MONTH:
return addToDate(date, now, Calendar.MONTH, 1);
case YEAR:
return addToDate(date, now, Calendar.YEAR, 1);
}
}
return null;
}
/**
* Gets the next trigger date.
*
* @param base The date from where to calculate the trigger date.
*
* @return null if there's none next trigger date.
*/
@Override
public Date getNextTriggerDate (Date base) {
Date date = base;
if (getOccurrence() > 1) {
Calendar cal = getCal(base);
addInterval(cal);
date = cal.getTime();
}
incOccurrence();
return getTriggerDate(date);
}
/**
* Sets the field value of now to date and adds by count.
*
* @return The new date.
*/
private Date addToDate(Calendar date, Calendar now, int field, int count) {
date.set(field, now.get(field));
date.add(field, count);
return date.getTime();
}
}
\ No newline at end of file
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package de.appplant.cordova.plugin.notification.util;
import android.support.v4.content.FileProvider;
public class AssetProvider extends FileProvider {
// Nothing to do here
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,62 +17,58 @@ ...@@ -17,62 +17,58 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h> #import <Cordova/CDVPlugin.h>
@interface APPLocalNotification : CDVPlugin @import UserNotifications;
@interface APPLocalNotification : CDVPlugin <UNUserNotificationCenterDelegate>
// Set launchDetails object
- (void) launch:(CDVInvokedUrlCommand*)command;
// Execute all queued events // Execute all queued events
- (void) deviceready:(CDVInvokedUrlCommand*)command; - (void) ready:(CDVInvokedUrlCommand*)command;
// Check permission to show notifications
- (void) check:(CDVInvokedUrlCommand*)command;
// Request permission to show notifications
- (void) request:(CDVInvokedUrlCommand*)command;
// Inform if the app has the permission to show notifications // Register/update an action group
- (void) hasPermission:(CDVInvokedUrlCommand*)command; - (void) actions:(CDVInvokedUrlCommand*)command;
// Register permission to show notifications
- (void) registerPermission:(CDVInvokedUrlCommand*)command;
// Schedule set of notifications // Schedule notifications
- (void) schedule:(CDVInvokedUrlCommand*)command; - (void) schedule:(CDVInvokedUrlCommand*)command;
// Update set of notifications // Update set of notifications
- (void) update:(CDVInvokedUrlCommand*)command; - (void) update:(CDVInvokedUrlCommand*)command;
// Cancel set of notifications // Clear notifications by id
- (void) cancel:(CDVInvokedUrlCommand*)command;
// Cancel all notifications
- (void) cancelAll:(CDVInvokedUrlCommand*)command;
// Clear set of notifications
- (void) clear:(CDVInvokedUrlCommand*)command; - (void) clear:(CDVInvokedUrlCommand*)command;
// Clear all notifications // Clear all notifications
- (void) clearAll:(CDVInvokedUrlCommand*)command; - (void) clearAll:(CDVInvokedUrlCommand*)command;
// Cancel notifications by id
- (void) cancel:(CDVInvokedUrlCommand*)command;
// Cancel all notifications
- (void) cancelAll:(CDVInvokedUrlCommand*)command;
// If a notification with an ID is present // Notification type
- (void) isPresent:(CDVInvokedUrlCommand*)command; - (void) type:(CDVInvokedUrlCommand*)command;
// If a notification with an ID is scheduled
- (void) isScheduled:(CDVInvokedUrlCommand*)command;
// If a notification with an ID is triggered
- (void) isTriggered:(CDVInvokedUrlCommand*)command;
// List all ids from all local notifications // List of all notification IDs
- (void) getAllIds:(CDVInvokedUrlCommand*)command; - (void) ids:(CDVInvokedUrlCommand*)command;
// List all ids from all pending notifications // List of all scheduled notification IDs
- (void) getScheduledIds:(CDVInvokedUrlCommand*)command; - (void) scheduledIds:(CDVInvokedUrlCommand*)command;
// List all ids from all triggered notifications // List of all triggered notification IDs
- (void) getTriggeredIds:(CDVInvokedUrlCommand*)command; - (void) triggeredIds:(CDVInvokedUrlCommand*)command;
// Propertys for given local notification // Notification by id
- (void) getSingle:(CDVInvokedUrlCommand*)command; - (void) notification:(CDVInvokedUrlCommand*)command;
// Propertya for given scheduled notification
- (void) getSingleScheduled:(CDVInvokedUrlCommand*)command;
// Propertys for given triggered notification
- (void) getSingleTriggered:(CDVInvokedUrlCommand*)command;
// Property list for given local notifications // List of notifications by id
- (void) getAll:(CDVInvokedUrlCommand*)command; - (void) notifications:(CDVInvokedUrlCommand*)command;
// Property list for given scheduled notifications // List of scheduled notifications by id
- (void) getScheduled:(CDVInvokedUrlCommand*)command; - (void) scheduledNotifications:(CDVInvokedUrlCommand*)command;
// Property list for given triggered notifications // List of triggered notifications by id
- (void) getTriggered:(CDVInvokedUrlCommand*)command; - (void) triggeredNotifications:(CDVInvokedUrlCommand*)command;
@end @end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "APPLocalNotificationOptions.h"
// Default sound ressource path
NSString* const DEFAULT_SOUND = @"res://platform_default";
@interface APPLocalNotificationOptions ()
// The dictionary which contains all notification properties
@property(nonatomic, retain) NSDictionary* dict;
@end
@implementation APPLocalNotificationOptions
@synthesize dict;
#pragma mark -
#pragma mark Initialization
/**
* Initialize the object with the given options when calling on JS side:
* notification.local.add(options)
*/
- (id) initWithDict:(NSDictionary*)dictionary
{
self = [self init];
self.dict = dictionary;
return self;
}
#pragma mark -
#pragma mark Attributes
/**
* The notification's ID.
*/
- (NSNumber*) id
{
NSInteger id = [[dict objectForKey:@"id"] integerValue];
return [NSNumber numberWithInteger:id];
}
/**
* The notification's title.
*/
- (NSString*) title
{
return [dict objectForKey:@"title"];
}
/**
* The notification's message.
*/
- (NSString*) text
{
return [dict objectForKey:@"text"];
}
/**
* The notification's badge number.
*/
- (NSInteger) badgeNumber
{
return [[dict objectForKey:@"badge"] intValue];
}
#pragma mark -
#pragma mark Complex Attributes
/**
* The notification's alert body.
*/
- (NSString*) alertBody
{
NSString* title = [self title];
NSString* msg = [self text];
NSString* alertBody = msg;
if (![self stringIsNullOrEmpty:title])
{
alertBody = [NSString stringWithFormat:@"%@\n%@",
title, msg];
}
return alertBody;
}
/**
* The notification's sound path.
*/
- (NSString*) soundName
{
NSString* path = [dict objectForKey:@"sound"];
if ([self stringIsNullOrEmpty:path])
return NULL;
if ([path isEqualToString:DEFAULT_SOUND])
return UILocalNotificationDefaultSoundName;
if ([path hasPrefix:@"file:/"])
return [self soundNameForAsset:path];
if ([path hasPrefix:@"res:"])
return [self soundNameForResource:path];
return NULL;
}
/**
* The notification's fire date.
*/
- (NSDate*) fireDate
{
double timestamp = [[dict objectForKey:@"at"]
doubleValue];
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
/**
* The notification's repeat interval.
*/
- (NSCalendarUnit) repeatInterval
{
NSString* interval = [dict objectForKey:@"every"];
if ([self stringIsNullOrEmpty:interval]) {
return NSCalendarUnitEra;
}
else if ([interval isEqualToString:@"second"]) {
return NSCalendarUnitSecond;
}
else if ([interval isEqualToString:@"minute"]) {
return NSCalendarUnitMinute;
}
else if ([interval isEqualToString:@"hour"]) {
return NSCalendarUnitHour;
}
else if ([interval isEqualToString:@"day"]) {
return NSCalendarUnitDay;
}
else if ([interval isEqualToString:@"week"]) {
return NSCalendarUnitWeekOfYear;
}
else if ([interval isEqualToString:@"month"]) {
return NSCalendarUnitMonth;
}
else if ([interval isEqualToString:@"quarter"]) {
return NSCalendarUnitQuarter;
}
else if ([interval isEqualToString:@"year"]) {
return NSCalendarUnitYear;
}
return NSCalendarUnitEra;
}
#pragma mark -
#pragma mark Methods
/**
* The notification's user info dict.
*/
- (NSDictionary*) userInfo
{
if ([dict objectForKey:@"updatedAt"]) {
NSMutableDictionary* data = [dict mutableCopy];
[data removeObjectForKey:@"updatedAt"];
return data;
}
return dict;
}
/**
* If it's a repeating notification.
*/
- (BOOL) isRepeating
{
NSCalendarUnit interval = self.repeatInterval;
return !(interval == NSCalendarUnitEra || interval == 0);
}
#pragma mark -
#pragma mark Helpers
/**
* Convert relative path to valid sound name attribute.
*/
- (NSString*) soundNameForAsset:(NSString*)path
{
return [path stringByReplacingOccurrencesOfString:@"file:/"
withString:@"www"];
}
/**
* Convert resource path to valid sound name attribute.
*/
- (NSString*) soundNameForResource:(NSString*)path
{
return [path pathComponents].lastObject;
}
/**
* If the string is empty.
*/
- (BOOL) stringIsNullOrEmpty:(NSString*)str
{
if (str == (NSString*)[NSNull null])
return YES;
if ([str isEqualToString:@""])
return YES;
return NO;
}
@end
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,26 +17,17 @@ ...@@ -17,26 +17,17 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface APPLocalNotificationOptions : NSObject #import "APPNotificationOptions.h"
- (id) initWithDict:(NSDictionary*)dict; @import UserNotifications;
@property (readonly, getter=id) NSNumber* id; @interface APPNotificationContent : UNMutableNotificationContent
@property (readonly, getter=badgeNumber) NSInteger badgeNumber;
@property (readonly, getter=alertBody) NSString* alertBody;
@property (readonly, getter=soundName) NSString* soundName;
@property (readonly, getter=fireDate) NSDate* fireDate;
@property (readonly, getter=repeatInterval) NSCalendarUnit repeatInterval;
@property (readonly, getter=userInfo) NSDictionary* userInfo;
// If it's a repeating notification - (id) initWithOptions:(NSDictionary*)dict;
- (BOOL) isRepeating; - (APPNotificationOptions*) options;
- (UNNotificationRequest*) request;
- (UNNotificationCategory*) category;
@end @end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationContent.h"
#import "APPNotificationOptions.h"
#import <objc/runtime.h>
@import UserNotifications;
static char optionsKey;
@implementation APPNotificationContent : UNMutableNotificationContent
#pragma mark -
#pragma mark Init
/**
* Initialize a notification with the given options.
*
* @param [ NSDictionary* ] dict A key-value property map.
*
* @return [ UNMutableNotificationContent ]
*/
- (id) initWithOptions:(NSDictionary*)dict
{
self = [self init];
[self setUserInfo:dict];
[self __init];
return self;
}
/**
* Initialize a notification by using the options found under userInfo.
*
* @return [ Void ]
*/
- (void) __init
{
APPNotificationOptions* options = self.options;
self.title = options.title;
self.subtitle = options.subtitle;
self.body = options.text;
self.sound = options.sound;
self.badge = options.badge;
self.attachments = options.attachments;
self.categoryIdentifier = options.categoryId;
}
#pragma mark -
#pragma mark Public
/**
* The options used to initialize the notification.
*
* @return [ APPNotificationOptions* ] options
*/
- (APPNotificationOptions*) options
{
APPNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPNotificationOptions alloc]
initWithDict:[self userInfo]];
[self setOptions:options];
}
return options;
}
/**
* The notifcations request ready to add to the notification center including
* all informations about trigger behavior.
*
* @return [ UNNotificationRequest* ]
*/
- (UNNotificationRequest*) request
{
APPNotificationOptions* opts = [self getOptions];
return [UNNotificationRequest requestWithIdentifier:opts.identifier
content:self
trigger:opts.trigger];
}
/**
* The category for the notification with all the actions.
*
* @return [ UNNotificationCategory* ]
*/
- (UNNotificationCategory*) category
{
NSString* categoryId = self.categoryIdentifier;
NSArray* actions = self.options.actions;
if (!actions.count)
return NULL;
return [UNNotificationCategory categoryWithIdentifier:categoryId
actions:actions
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
}
#pragma mark -
#pragma mark Private
/**
* The options used to initialize the notification.
*
* @return [ APPNotificationOptions* ]
*/
- (APPNotificationOptions*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
/**
* Set the options used to initialize the notification.
*
* @param [ NSDictionary* ] dict A key-value property map.
*
* @return [ Void ]
*/
- (void) setOptions:(APPNotificationOptions*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
@import UserNotifications;
@interface APPNotificationOptions : NSObject
@property (readonly, getter=id) NSNumber* id;
@property (readonly, getter=identifier) NSString* identifier;
@property (readonly, getter=categoryId) NSString* categoryId;
@property (readonly, getter=title) NSString* title;
@property (readonly, getter=subtitle) NSString* subtitle;
@property (readonly, getter=badge) NSNumber* badge;
@property (readonly, getter=text) NSString* text;
@property (readonly, getter=silent) BOOL silent;
@property (readonly, getter=sound) UNNotificationSound* sound;
@property (readonly, getter=userInfo) NSDictionary* userInfo;
@property (readonly, getter=actions) NSArray<UNNotificationAction *> * actions;
@property (readonly, getter=attachments) NSArray<UNNotificationAttachment *> * attachments;
- (id) initWithDict:(NSDictionary*)dict;
- (UNNotificationTrigger*) trigger;
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UILocalNotification+APPLocalNotification.h"
@interface UIApplication (APPLocalNotification)
@property (readonly, getter=localNotifications) NSArray* localNotifications;
@property (readonly, getter=localNotificationIds) NSArray* localNotificationIds;
// If the app has the permission to schedule local notifications
- (BOOL) hasPermissionToScheduleLocalNotifications;
// Ask for permission to schedule local notifications
- (void) registerPermissionToScheduleLocalNotifications;
// List of all local notification IDs from given type
- (NSArray*) localNotificationIdsByType:(APPLocalNotificationType)type;
// If local notification with ID exists
- (BOOL) localNotificationExist:(NSNumber*)id;
// If local notification with ID and type exists
- (BOOL) localNotificationExist:(NSNumber*)id type:(APPLocalNotificationType)type;
// Local notification by ID
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id;
// Local notification by ID and type
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPLocalNotificationType)type;
// Property list from all local notifications
- (NSArray*) localNotificationOptions;
// Property list from given local notifications
- (NSArray*) localNotificationOptionsById:(NSArray*)ids;
// Property list from all local notifications with type constraint
- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type;
// Property list from given local notifications with type constraint
- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type andId:(NSArray*)ids;
// Clear single local notfications
- (void) clearLocalNotification:(UILocalNotification*)notification;
// Clear all local notfications
- (void) clearAllLocalNotifications;
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UIApplication+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.h"
@implementation UIApplication (APPLocalNotification)
#pragma mark -
#pragma mark Permissions
/**
* If the app has the permission to schedule local notifications.
*/
- (BOOL) hasPermissionToScheduleLocalNotifications
{
if ([[UIApplication sharedApplication]
respondsToSelector:@selector(registerUserNotificationSettings:)])
{
UIUserNotificationType types;
UIUserNotificationSettings *settings;
settings = [[UIApplication sharedApplication]
currentUserNotificationSettings];
types = UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
return (settings.types & types);
} else {
return YES;
}
}
/**
* Ask for permission to schedule local notifications.
*/
- (void) registerPermissionToScheduleLocalNotifications
{
if ([[UIApplication sharedApplication]
respondsToSelector:@selector(registerUserNotificationSettings:)])
{
UIUserNotificationType types;
UIUserNotificationSettings *settings;
settings = [[UIApplication sharedApplication]
currentUserNotificationSettings];
types = settings.types|UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
settings = [UIUserNotificationSettings settingsForTypes:types
categories:nil];
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
}
}
#pragma mark -
#pragma mark LocalNotifications
/**
* List of all local notifications which have been added
* but not yet removed from the notification center.
*/
- (NSArray*) localNotifications
{
NSArray* scheduledNotifications = self.scheduledLocalNotifications;
NSMutableArray* notifications = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in scheduledNotifications)
{
if (notification) {
[notifications addObject:notification];
}
}
return notifications;
}
/**
* List of all triggered local notifications which have been scheduled
* and not yet removed the notification center.
*/
- (NSArray*) triggeredLocalNotifications
{
NSArray* notifications = self.localNotifications;
NSMutableArray* triggeredNotifications = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in notifications)
{
if ([notification isTriggered]) {
[triggeredNotifications addObject:notification];
}
}
return triggeredNotifications;
}
/**
* List of all local notifications IDs.
*/
- (NSArray*) localNotificationIds
{
NSArray* notifications = self.localNotifications;
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/**
* List of all local notifications IDs from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) localNotificationIdsByType:(APPLocalNotificationType)type
{
NSArray* notifications = self.localNotifications;
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in notifications)
{
if (notification.type == type) {
[ids addObject:notification.options.id];
}
}
return ids;
}
/*
* If local notification with ID exists.
*
* @param id
* Notification ID
*/
- (BOOL) localNotificationExist:(NSNumber*)id
{
return [self localNotificationWithId:id] != NULL;
}
/* If local notification with ID and type exists
*
* @param id
* Notification ID
* @param type
* Notification life cycle type
*/
- (BOOL) localNotificationExist:(NSNumber*)id type:(APPLocalNotificationType)type
{
return [self localNotificationWithId:id andType:type] != NULL;
}
/**
* Get local notification with ID.
*
* @param id
* Notification ID
*/
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id
{
NSArray* notifications = self.localNotifications;
for (UILocalNotification* notification in notifications)
{
NSString* fid = [NSString stringWithFormat:@"%@", notification.options.id];
if ([fid isEqualToString:[id stringValue]]) {
return notification;
}
}
return NULL;
}
/*
* Get local notification with ID and type.
*
* @param id
* Notification ID
* @param type
* Notification life cycle type
*/
- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPLocalNotificationType)type
{
UILocalNotification* notification = [self localNotificationWithId:id];
if (notification && notification.type == type)
return notification;
return NULL;
}
/**
* List of properties from all notifications.
*/
- (NSArray*) localNotificationOptions
{
NSArray* notifications = self.localNotifications;
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in notifications)
{
[options addObject:notification.options.userInfo];
}
return options;
}
/**
* List of properties from all local notifications from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type
{
NSArray* notifications = self.localNotifications;
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UILocalNotification* notification in notifications)
{
if (notification.type == type) {
[options addObject:notification.options.userInfo];
}
}
return options;
}
/**
* List of properties from given local notifications.
*
* @param ids
* Notification IDs
*/
- (NSArray*) localNotificationOptionsById:(NSArray*)ids
{
UILocalNotification* notification;
NSMutableArray* options = [[NSMutableArray alloc] init];
for (NSNumber* id in ids)
{
notification = [self localNotificationWithId:id];
if (notification) {
[options addObject:notification.options.userInfo];
}
}
return options;
}
/**
* List of properties from given local notifications.
*
* @param type
* Notification life cycle type
* @param ids
* Notification IDs
*/
- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type andId:(NSArray*)ids
{
UILocalNotification* notification;
NSMutableArray* options = [[NSMutableArray alloc] init];
for (NSNumber* id in ids)
{
notification = [self localNotificationWithId:id];
if (notification && notification.type == type) {
[options addObject:notification.options.userInfo];
}
}
return options;
}
/*
* Clear all local notfications.
*/
- (void) clearAllLocalNotifications
{
NSArray* notifications = self.triggeredLocalNotifications;
for (UILocalNotification* notification in notifications) {
[self clearLocalNotification:notification];
}
}
/*
* Clear single local notfication.
*
* @param notification
* The local notification object
*/
- (void) clearLocalNotification:(UILocalNotification*)notification
{
[self cancelLocalNotification:notification];
if ([notification isRepeating]) {
notification.fireDate = notification.options.fireDate;
[self scheduleLocalNotification:notification];
};
}
@end
/*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
#import "UILocalNotification+APPLocalNotification.h"
#import "APPLocalNotificationOptions.h"
#import <objc/runtime.h>
static char optionsKey;
NSInteger const APPLocalNotificationTypeScheduled = 1;
NSInteger const APPLocalNotificationTypeTriggered = 2;
@implementation UILocalNotification (APPLocalNotification)
#pragma mark -
#pragma mark Init
/**
* Initialize a local notification with the given options when calling on JS side:
* notification.local.add(options)
*/
- (id) initWithOptions:(NSDictionary*)dict
{
self = [self init];
[self setUserInfo:dict];
[self __init];
return self;
}
/**
* Applies the given options when calling on JS side:
* notification.local.add(options)
*/
- (void) __init
{
APPLocalNotificationOptions* options = self.options;
self.fireDate = options.fireDate;
self.timeZone = [NSTimeZone defaultTimeZone];
self.applicationIconBadgeNumber = options.badgeNumber;
self.repeatInterval = options.repeatInterval;
self.alertBody = options.alertBody;
self.soundName = options.soundName;
if ([self wasInThePast]) {
self.fireDate = [NSDate date];
}
}
#pragma mark -
#pragma mark Methods
/**
* The options provided by the plug-in.
*/
- (APPLocalNotificationOptions*) options
{
APPLocalNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPLocalNotificationOptions alloc]
initWithDict:[self userInfo]];
[self setOptions:options];
}
return options;
}
/**
* Get associated option object
*/
- (APPLocalNotificationOptions*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
/**
* Set associated option object
*/
- (void) setOptions:(APPLocalNotificationOptions*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/**
* The repeating interval in seconds.
*/
- (int) repeatIntervalInSeconds
{
switch (self.repeatInterval) {
case NSCalendarUnitMinute:
return 60;
case NSCalendarUnitHour:
return 60000;
case NSCalendarUnitDay:
case NSCalendarUnitWeekOfYear:
case NSCalendarUnitMonth:
case NSCalendarUnitYear:
return 86400;
default:
return 1;
}
}
/**
* Timeinterval since fire date.
*/
- (double) timeIntervalSinceFireDate
{
NSDate* now = [NSDate date];
NSDate* fireDate = self.fireDate;
int timespan = [now timeIntervalSinceDate:fireDate];
return timespan;
}
/**
* Timeinterval since last trigger date.
*/
- (double) timeIntervalSinceLastTrigger
{
int timespan = [self timeIntervalSinceFireDate];
if ([self isRepeating]) {
timespan = timespan % [self repeatIntervalInSeconds];
}
return timespan;
}
/**
* Encode the user info dict to JSON.
*/
- (NSString*) encodeToJSON
{
NSString* json;
NSData* data;
NSMutableDictionary* obj = [self.userInfo mutableCopy];
[obj removeObjectForKey:@"updatedAt"];
if (obj == NULL || obj.count == 0)
return json;
data = [NSJSONSerialization dataWithJSONObject:obj
options:NSJSONWritingPrettyPrinted
error:NULL];
json = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [json stringByReplacingOccurrencesOfString:@"\n"
withString:@""];
}
#pragma mark -
#pragma mark State
/**
* If the fire date was in the past.
*/
- (BOOL) wasInThePast
{
return [self timeIntervalSinceLastTrigger] > 0;
}
// If the notification was already scheduled
- (BOOL) isScheduled
{
return [self isRepeating] || ![self wasInThePast];
}
/**
* If the notification was already triggered.
*/
- (BOOL) isTriggered
{
NSDate* now = [NSDate date];
NSDate* fireDate = self.fireDate;
bool isLaterThanFireDate = !([now compare:fireDate] == NSOrderedAscending);
return isLaterThanFireDate;
}
/**
* If the notification was updated.
*/
- (BOOL) wasUpdated
{
NSDate* now = [NSDate date];
NSDate* updatedAt = [self.userInfo objectForKey:@"updatedAt"];
if (updatedAt == NULL)
return NO;
int timespan = [now timeIntervalSinceDate:updatedAt];
return timespan < 1;
}
/**
* If it's a repeating notification.
*/
- (BOOL) isRepeating
{
return [self.options isRepeating];
}
/**
* Process state type of the local notification.
*/
- (APPLocalNotificationType) type
{
return [self isTriggered] ? NotifcationTypeTriggered : NotifcationTypeScheduled;
}
@end
/* /*
* Copyright (c) 2013-2015 by appPlant UG. All rights reserved. * Apache 2.0 License
* *
* @APPPLANT_LICENSE_HEADER_START@ * Copyright (c) Sebastian Katzer 2017
* *
* This file contains Original Code and/or Modifications of Original Code * This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License * as defined in and that are subject to the Apache License
...@@ -17,40 +17,18 @@ ...@@ -17,40 +17,18 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and * Please see the License for the specific language governing rights and
* limitations under the License. * limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/ */
#import "APPLocalNotificationOptions.h" #import "APPNotificationOptions.h"
typedef NS_ENUM(NSUInteger, APPLocalNotificationType) { @import UserNotifications;
NotifcationTypeAll = 0,
NotifcationTypeScheduled = 1,
NotifcationTypeTriggered = 2
};
@interface UILocalNotification (APPLocalNotification) @interface UNNotificationRequest (APPLocalNotification)
// Initialize a new local notification
- (id) initWithOptions:(NSDictionary*)dict;
// The options provided by the plug-in // The options provided by the plug-in
- (APPLocalNotificationOptions*) options; - (APPNotificationOptions*) options;
// Timeinterval since last trigger date
- (double) timeIntervalSinceLastTrigger;
// Timeinterval since fire date
- (double) timeIntervalSinceFireDate;
// If the fire date was in the past
- (BOOL) wasInThePast;
// If the notification was already scheduled
- (BOOL) isScheduled;
// If the notification was already triggered
- (BOOL) isTriggered;
// If the notification was updated // If the notification was updated
- (BOOL) wasUpdated; - (BOOL) wasUpdated;
// If it's a repeating notification
- (BOOL) isRepeating;
// Notifciation type
- (APPLocalNotificationType) type;
// Encode the user info dict to JSON // Encode the user info dict to JSON
- (NSString*) encodeToJSON; - (NSString*) encodeToJSON;
......
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationOptions.h"
#import "UNNotificationRequest+APPLocalNotification.h"
#import "APPNotificationContent.h"
#import <objc/runtime.h>
@import UserNotifications;
static char optionsKey;
@implementation UNNotificationRequest (APPLocalNotification)
/**
* Get associated option object
*/
- (APPNotificationOptions*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
/**
* Set associated option object
*/
- (void) setOptions:(APPNotificationOptions*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/**
* The options provided by the plug-in.
*/
- (APPNotificationOptions*) options
{
APPNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPNotificationOptions alloc]
initWithDict:[self.content userInfo]];
[self setOptions:options];
}
return options;
}
/**
* If the notification was updated.
*
* @return [ BOOL ]
*/
- (BOOL) wasUpdated
{
return [self.content userInfo][@"updatedAt"] != NULL;
}
/**
* Encode the user info dict to JSON.
*/
- (NSString*) encodeToJSON
{
NSString* json;
NSData* data;
NSMutableDictionary* obj = [self.content.userInfo mutableCopy];
[obj removeObjectForKey:@"updatedAt"];
if (obj == NULL || obj.count == 0)
return json;
data = [NSJSONSerialization dataWithJSONObject:obj
options:NSJSONWritingPrettyPrinted
error:NULL];
json = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [json stringByReplacingOccurrencesOfString:@"\n"
withString:@""];
}
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationContent.h"
@interface UNUserNotificationCenter (APPLocalNotification)
extern NSString * const kAPPGeneralCategory;
typedef NS_ENUM(NSUInteger, APPNotificationType) {
NotifcationTypeAll = 0,
NotifcationTypeScheduled = 1,
NotifcationTypeTriggered = 2,
NotifcationTypeUnknown = 3
};
#define APPNotificationType_DEFINED
@property (readonly, getter=getNotifications) NSArray* localNotifications;
@property (readonly, getter=getNotificationIds) NSArray* localNotificationIds;
// Register general notification category to listen for dismiss actions
- (void) registerGeneralNotificationCategory;
// Add the specified category to the list of categories
- (void) addNotificationCategory:(UNNotificationCategory*)category;
// List of all notification IDs from given type
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type;
// Find notification by ID
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id;
// Find notification type by ID
- (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id;
// Property list from all local notifications
- (NSArray*) getNotificationOptions;
// Property list from given local notifications
- (NSArray*) getNotificationOptionsById:(NSArray*)ids;
// Property list from all local notifications with type constraint
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type;
// Clear specified notfication
- (void) clearNotification:(UNNotificationRequest*)notification;
// Clear all notfications
- (void) clearAllNotifications;
// Cancel specified notfication
- (void) cancelNotification:(UNNotificationRequest*)notification;
// Cancel all notfications
- (void) cancelAllNotifications;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "UNUserNotificationCenter+APPLocalNotification.h"
#import "UNNotificationRequest+APPLocalNotification.h"
@import UserNotifications;
NSString * const kAPPGeneralCategory = @"GENERAL";
@implementation UNUserNotificationCenter (APPLocalNotification)
#pragma mark -
#pragma mark NotificationCategory
/**
* Register general notification category to listen for dismiss actions.
*
* @return [ Void ]
*/
- (void) registerGeneralNotificationCategory
{
UNNotificationCategory* category;
category = [UNNotificationCategory
categoryWithIdentifier:kAPPGeneralCategory
actions:@[]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
[self setNotificationCategories:[NSSet setWithObject:category]];
}
/**
* Add the specified category to the list of categories.
*
* @param [ UNNotificationCategory* ] category The category to add.
*
* @return [ Void ]
*/
- (void) addNotificationCategory:(UNNotificationCategory*)category
{
if (!category)
return;
[self getNotificationCategoriesWithCompletionHandler:^(NSSet<UNNotificationCategory *> *set) {
NSMutableSet* categories = [NSMutableSet setWithSet:set];
for (UNNotificationCategory* item in categories) {
if ([category.identifier isEqualToString:item.identifier]) {
[categories removeObject:item];
break;
}
}
[categories addObject:category];
[self setNotificationCategories:categories];
}];
}
#pragma mark -
#pragma mark LocalNotifications
/**
* List of all delivered or still pending notifications.
*/
- (NSArray*) getNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
[notifications addObjectsFromArray:[self getPendingNotifications]];
[notifications addObjectsFromArray:[self getDeliveredNotifications]];
return notifications;
}
/**
* List of all triggered notifications.
*/
- (NSArray*) getDeliveredNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> *delivered) {
for (UNNotification* notification in delivered) {
[notifications addObject:notification.request];
}
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return notifications;
}
/**
* List of all pending notifications.
*/
- (NSArray*) getPendingNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *requests) {
[notifications addObjectsFromArray:requests];
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return notifications;
}
/**
* List of all notifications from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationsByType:(APPNotificationType)type
{
switch (type) {
case NotifcationTypeScheduled:
return [self getPendingNotifications];
case NotifcationTypeTriggered:
return [self getDeliveredNotifications];
default:
return [self getNotifications];
}
}
/**
* List of all local notifications IDs.
*/
- (NSArray*) getNotificationIds
{
NSArray* notifications = [self getNotifications];
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/**
* List of all notifications IDs from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/**
* Find notification by ID.
*
* @param id
* Notification ID
*/
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id
{
NSArray* notifications = [self getNotifications];
for (UNNotificationRequest* notification in notifications)
{
NSString* fid = [NSString stringWithFormat:@"%@", notification.options.id];
if ([fid isEqualToString:[id stringValue]]) {
return notification;
}
}
return NULL;
}
/**
* Find notification type by ID
*/
- (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id
{
NSArray* ids = [self getNotificationIdsByType:NotifcationTypeTriggered];
if ([ids containsObject:id])
return NotifcationTypeTriggered;
ids = [self getNotificationIdsByType:NotifcationTypeScheduled];
if ([ids containsObject:id])
return NotifcationTypeScheduled;
return NotifcationTypeUnknown;
}
/**
* List of properties from all notifications.
*/
- (NSArray*) getNotificationOptions
{
return [self getNotificationOptionsByType:NotifcationTypeAll];
}
/**
* List of properties from all notifications of given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[options addObject:notification.options.userInfo];
}
return options;
}
/**
* List of properties from given local notifications.
*
* @param ids
* Notification IDs
*/
- (NSArray*) getNotificationOptionsById:(NSArray*)ids
{
NSArray* notifications = [self getNotifications];
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
if ([ids containsObject:notification.options.id]) {
[options addObject:notification.options.userInfo];
}
}
return options;
}
/*
* Clear all notfications.
*/
- (void) clearAllNotifications
{
[self removeAllDeliveredNotifications];
}
/*
* Clear Specified notfication.
*
* @param notification
* The notification object
*/
- (void) clearNotification:(UNNotificationRequest*)notification
{
NSArray* ids = [[NSArray alloc]
initWithObjects:notification.identifier, nil];
[self removeDeliveredNotificationsWithIdentifiers:ids];
}
/*
* Cancel all notfications.
*/
- (void) cancelAllNotifications
{
[self removeAllPendingNotificationRequests];
[self removeAllDeliveredNotifications];
}
/*
* Cancel specified notfication.
*
* @param notification
* The notification object
*/
- (void) cancelNotification:(UNNotificationRequest*)notification
{
NSArray* ids = [[NSArray alloc]
initWithObjects:notification.identifier, nil];
[self removeDeliveredNotificationsWithIdentifiers:ids];
[self removePendingNotificationRequestsWithIdentifiers:ids];
}
@end

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalNotificationProxy", "LocalNotificationProxy\LocalNotificationProxy.csproj", "{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.ActiveCfg = Debug|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.Build.0 = Debug|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.ActiveCfg = Debug|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.Build.0 = Debug|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.ActiveCfg = Debug|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.Build.0 = Debug|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.Build.0 = Release|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.ActiveCfg = Release|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.Build.0 = Release|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.ActiveCfg = Release|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.Build.0 = Release|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.ActiveCfg = Release|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
using Microsoft.Toolkit.Uwp.Notifications;
using Windows.UI.Notifications;
internal class Builder
{
/// <summary>
/// Initializes a new instance of the <see cref="Builder"/> class.
/// </summary>
/// <param name="options">Notification properties to set.</param>
public Builder(Options options)
{
this.Content = new Notification(options);
}
/// <summary>
/// Gets the content.
/// </summary>
public Notification Content { get; private set; }
/// <summary>
/// Gets the options.
/// </summary>
private Options Options { get => this.Content.Options; }
/// <summary>
/// Gets the trigger.
/// </summary>
private Trigger Trigger { get => this.Options.Trigger; }
/// <summary>
/// Build a toast notification specified by the options.
/// </summary>
/// <returns>A fully configured toast notification instance.</returns>
public ScheduledToastNotification Build()
{
var toast = this.InitToast();
this.AddProgressBarToToast(toast);
this.AddAttachmentsToToast(toast);
this.AddActionsToToast(toast);
return this.ConvertToastToNotification(toast);
}
/// <summary>
/// If there is at least one more toast variant to build.
/// </summary>
/// <returns>True if there are more toasts to build.</returns>
public bool HasNext() => this.Trigger.Count >= this.Trigger.Occurrence;
/// <summary>
/// Moves the flag to the next toast variant.
/// </summary>
public void MoveNext() => this.Trigger.Occurrence += this.HasNext() ? 1 : 0;
/// <summary>
/// Gets the initialize skeleton for a toast notification.
/// </summary>
/// <returns>Basic skeleton with sound, image and text.</returns>
private ToastContent InitToast()
{
return new ToastContent()
{
Launch = this.Content.GetXml(),
Audio = this.Content.Sound,
Visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText()
{
Text = this.Options.Title
},
new AdaptiveText()
{
Text = this.Options.Text
}
},
AppLogoOverride = this.Content.Icon
}
},
Actions = new ToastActionsCustom()
{
Buttons = { },
Inputs = { }
}
};
}
/// <summary>
/// Adds optional progress bar to the toast.
/// </summary>
/// <param name="toast">Tho toast to extend for.</param>
private void AddProgressBarToToast(ToastContent toast)
{
var progressBar = this.Content.ProgressBar;
if (progressBar != null)
{
toast.Visual.BindingGeneric.Children.Add(progressBar);
}
}
/// <summary>
/// Adds attachments to the toast.
/// </summary>
/// <param name="toast">Tho toast to extend for.</param>
private void AddAttachmentsToToast(ToastContent toast)
{
foreach (var image in this.Content.Attachments)
{
toast.Visual.BindingGeneric.Children.Add(image);
}
}
/// <summary>
/// Adds buttons and input fields to the toast.
/// </summary>
/// <param name="toast">Tho toast to extend for.</param>
private void AddActionsToToast(ToastContent toast)
{
foreach (var btn in this.Content.Inputs)
{
(toast.Actions as ToastActionsCustom).Inputs.Add(btn);
}
foreach (var btn in this.Content.Buttons)
{
(toast.Actions as ToastActionsCustom).Buttons.Add(btn);
}
}
/// <summary>
/// Converts the toast into a notification.
/// </summary>
/// <param name="toast">The toast to convert.</param>
/// <returns>A notification ready to schedule.</returns>
private ScheduledToastNotification ConvertToastToNotification(ToastContent toast)
{
var xml = toast.GetXml();
var at = this.Content.Date;
ScheduledToastNotification notification;
if (!at.HasValue)
{
return null;
}
try
{
notification = new ScheduledToastNotification(xml, at.Value);
}
catch
{
return null;
}
notification.Id = this.Content.Id;
notification.Tag = this.Options.Id.ToString();
notification.SuppressPopup = this.Options.Silent;
if (this.Trigger.Occurrence > 1)
{
notification.Group = notification.Tag;
}
return notification;
}
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public sealed class Button : IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
public string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
public bool Launch { get; set; } = true;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
using System;
public sealed class Every
{
private static readonly string[] Intervals = { null, "minute", "hour", "day", "month", "year" };
/// <summary>
/// Gets or sets the minute.
/// </summary>
public int? Minute { get; set; }
/// <summary>
/// Gets or sets the hour.
/// </summary>
public int? Hour { get; set; }
/// <summary>
/// Gets or sets the day.
/// </summary>
public int? Day { get; set; }
/// <summary>
/// Gets or sets the month.
/// </summary>
public int? Month { get; set; }
/// <summary>
/// Gets or sets the year.
/// </summary>
public int? Year { get; set; }
/// <summary>
/// Gets the interval as a string representation.
/// </summary>
/// <returns>year, month, ...</returns>
internal string Interval { get => Intervals[Array.IndexOf(this.ToArray(), null) + 1]; }
/// <summary>
/// Converts the date time components into a datetime object.
/// </summary>
/// <param name="now">The relative date to calculate the date from.</param>
/// <returns>A datetime object</returns>
internal DateTime ToDateTime(DateTime now)
{
var p = this.ToArray();
p[0] = this.Minute.GetValueOrDefault();
p[1] = this.Hour.GetValueOrDefault();
p[2] = this.Day.GetValueOrDefault(now.Day);
p[3] = this.Month.GetValueOrDefault(now.Month);
p[4] = this.Year.GetValueOrDefault(now.Year);
return new DateTime(p[4].Value, p[3].Value, p[2].Value, p[1].Value, p[0].Value, 0);
}
/// <summary>
/// Gets an array of all date parts to construct a datetime instance.
/// </summary>
/// <returns>[min, hour, day, month, year]</returns>
private int?[] ToArray()
{
return new int?[] { this.Minute, this.Hour, this.Day, this.Month, this.Year };
}
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public interface IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
string Title { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
bool Launch { get; set; }
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public sealed class Input : IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
public string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets the title of the submit button.
/// </summary>
public string SubmitTitle { get; set; }
/// <summary>
/// Gets or sets placeholder text.
/// </summary>
public string EmptyText { get; set; }
/// <summary>
/// Gets or sets the default text.
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
public bool Launch { get; set; } = true;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
using Windows.Data.Xml.Dom;
public sealed class Options
{
/// <summary>
/// Gets notification event.
/// </summary>
public string Action { get; private set; } = "click";
/// <summary>
/// Gets or sets notification ID.
/// </summary>
public int Id { get; set; } = 0;
/// <summary>
/// Gets or sets notification title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets notification text.
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets or sets app badge number.
/// </summary>
public int Badge { get; set; }
/// <summary>
/// Gets or sets the notification sound.
/// </summary>
public string Sound { get; set; }
/// <summary>
/// Gets or sets the notification image.
/// </summary>
public string Icon { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the popup shall be visible.
/// </summary>
public bool Silent { get; set; } = false;
/// <summary>
/// Gets or sets the notification trigger.
/// </summary>
public Trigger Trigger { get; set; }
/// <summary>
/// Gets or sets the notification user data.
/// </summary>
public string Data { get; set; }
/// <summary>
/// Gets or sets the notification attachments.
/// </summary>
public string[] Attachments { get; set; }
/// <summary>
/// Gets or sets the notification actions.
/// </summary>
public IAction[] Actions { get; set; }
/// <summary>
/// Gets or sets the notification progress bar.
/// </summary>
public ProgressBar ProgressBar { get; set; }
/// <summary>
/// Deserializes the XML string into an instance of Options.
/// </summary>
/// <param name="identifier">The serialized instance of Options as an xml string.</param>
/// <returns>An instance where all properties have been assigned.</returns>
public static Options Parse(string identifier)
{
var doc = new XmlDocument();
doc.LoadXml(identifier);
var options = new Options();
var node = doc.DocumentElement;
options.Id = int.Parse(node.GetAttribute("id"));
options.Badge = int.Parse(node.GetAttribute("badge"));
options.Trigger = Trigger.Parse(node.GetAttribute("trigger"));
if (node.GetAttributeNode("text") != null)
{
options.Text = node.GetAttribute("text");
}
if (node.GetAttributeNode("title") != null)
{
options.Title = node.GetAttribute("title");
}
if (node.GetAttributeNode("sound") != null)
{
options.Sound = node.GetAttribute("sound");
}
if (node.GetAttributeNode("image") != null)
{
options.Icon = node.GetAttribute("image");
}
if (node.GetAttributeNode("data") != null)
{
options.Data = node.GetAttribute("data");
}
if (node.GetAttributeNode("attachments") != null)
{
options.Attachments = node.GetAttribute("attachments").Split(',');
}
if (node.GetAttributeNode("silent") != null)
{
options.Silent = true;
}
if (node.GetAttributeNode("action") != null)
{
options.Action = node.GetAttribute("action");
}
return options;
}
/// <summary>
/// Gets the instance as an serialized xml element.
/// </summary>
/// <returns>Element with all property values set as attributes.</returns>
public string GetXml()
{
return this.GetXml(null);
}
/// <summary>
/// Gets the instance as an serialized xml element.
/// </summary>
/// <param name="action">Optional (internal) event name.</param>
/// <returns>Element with all property values set as attributes.</returns>
internal string GetXml(string action)
{
var node = new XmlDocument().CreateElement("options");
node.SetAttribute("id", this.Id.ToString());
node.SetAttribute("badge", this.Badge.ToString());
node.SetAttribute("trigger", this.Trigger.GetXml());
if (this.Title != null)
{
node.SetAttribute("title", this.Title);
}
if (this.Text != null)
{
node.SetAttribute("text", this.Text);
}
if (this.Sound != null)
{
node.SetAttribute("sound", this.Sound);
}
if (this.Icon != null)
{
node.SetAttribute("image", this.Icon);
}
if (this.Data != null)
{
node.SetAttribute("data", this.Data);
}
if (this.Attachments != null)
{
node.SetAttribute("attachments", string.Join(",", this.Attachments));
}
if (this.Silent)
{
node.SetAttribute("silent", "1");
}
if (action != null)
{
node.SetAttribute("action", action);
}
return node.GetXml();
}
}
}
\ No newline at end of file
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public sealed class ProgressBar
{
/// <summary>
/// Gets or sets a value indicating whether the notification has a progress bar.
/// </summary>
public bool Enabled { get; set; } = false;
/// <summary>
/// Gets or sets the title.
/// </summary>
public string Title { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the value.
/// </summary>
public double Value { get; set; } = 0;
/// <summary>
/// Gets or sets the status.
/// </summary>
public string Status { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the description.
/// </summary>
public string Description { get; set; } = string.Empty;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy
{
using System.Runtime.InteropServices.WindowsRuntime;
using LocalNotification;
public sealed class LocalNotificationProxy
{
/// <summary>
/// Manager wrapps the native SDK methods.
/// </summary>
private Manager manager = new Manager();
/// <summary>
/// Check permission to schedule notifications.
/// </summary>
/// <returns>True if settings are enabled</returns>
public bool HasPermission()
{
return this.manager.Enabled;
}
/// <summary>
/// Schedule notifications.
/// </summary>
/// <param name="notifications">List of key-value properties</param>
public void Schedule([ReadOnlyArray] Options[] notifications)
{
this.manager.Schedule(notifications);
}
/// <summary>
/// Update notifications.
/// </summary>
/// <param name="notifications">List of key-value properties</param>
public void Update([ReadOnlyArray] Options[] notifications)
{
this.manager.Update(notifications);
}
/// <summary>
/// Clear the notifications specified by id.
/// </summary>
/// <param name="ids">The IDs of the notification to clear.</param>
/// <returns>The cleared notifications.</returns>
public Options[] Clear([ReadOnlyArray] int[] ids)
{
return this.manager.Clear(ids).ToArray();
}
/// <summary>
/// Clear all notifications.
/// </summary>
public void ClearAll()
{
this.manager.ClearAll();
}
/// <summary>
/// Cancel the notifications specified by id.
/// </summary>
/// <param name="ids">The IDs of the notification to clear.</param>
/// <returns>The cleared notifications.</returns>
public Options[] Cancel([ReadOnlyArray] int[] ids)
{
return this.manager.Cancel(ids).ToArray();
}
/// <summary>
/// Cancel all notifications.
/// </summary>
public void CancelAll()
{
this.manager.CancelAll();
}
/// <summary>
/// Gets the type of the notification specified by ID.
/// </summary>
/// <param name="id">The ID of the notification to find for.</param>
/// <returns>The type (scheduled, triggered or unknown).</returns>
public string Type(int id)
{
return this.manager.GetType(id.ToString()).ToString().ToLower();
}
/// <summary>
/// List of all notifiation by id.
/// </summary>
/// <returns>List of numbers</returns>
public int[] Ids()
{
return this.manager.GetIds().ToArray();
}
/// <summary>
/// List of all scheduled notifiation by id.
/// </summary>
/// <returns>List of numbers</returns>
public int[] ScheduledIds()
{
return this.manager.GetIdsByType(Notification.Type.Scheduled).ToArray();
}
/// <summary>
/// List of all triggered notifiation by id.
/// </summary>
/// <returns>List of numbers</returns>
public int[] TriggeredIds()
{
return this.manager.GetIdsByType(Notification.Type.Triggered).ToArray();
}
#pragma warning disable SA1300 // Element must begin with upper-case letter
/// <summary>
/// Gets a single notifiation specified by id.
/// </summary>
/// <param name="id">The ID of the notification to find.</param>
/// <returns>List of options instances</returns>
public Options notification(int id)
{
var toast = this.manager.Get(id);
return toast != null ? toast.Options : null;
}
#pragma warning restore SA1300 // Element must begin with upper-case letter
/// <summary>
/// List of (all) notifiation specified by id.
/// </summary>
/// <param name="ids">Optional list of IDs to find.</param>
/// <returns>List of options instances</returns>
public Options[] Notifications([ReadOnlyArray] int[] ids)
{
if (ids == null || ids.Length == 0)
{
return this.manager.GetOptions().ToArray();
}
return this.manager.GetOptions(ids).ToArray();
}
/// <summary>
/// List of all scheduled notifiation.
/// </summary>
/// <returns>List of options instances</returns>
public Options[] ScheduledNotifications()
{
return this.manager.GetOptionsByType(Notification.Type.Scheduled).ToArray();
}
/// <summary>
/// List of all triggered notifiation.
/// </summary>
/// <returns>List of options instances</returns>
public Options[] TriggeredNotifications()
{
return this.manager.GetOptionsByType(Notification.Type.Triggered).ToArray();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}</ProjectGuid>
<OutputType>winmdobj</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LocalNotificationProxy</RootNamespace>
<AssemblyName>LocalNotificationProxy</AssemblyName>
<DefaultLanguage>de-DE</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.15063.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.15063.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<AllowCrossPlatformRetargeting>false</AllowCrossPlatformRetargeting>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="LocalNotificationProxy.cs" />
<Compile Include="LocalNotification\Builder.cs" />
<Compile Include="LocalNotification\Button.cs" />
<Compile Include="LocalNotification\Every.cs" />
<Compile Include="LocalNotification\Notification.cs" />
<Compile Include="LocalNotification\IAction.cs" />
<Compile Include="LocalNotification\Input.cs" />
<Compile Include="LocalNotification\Manager.cs" />
<Compile Include="LocalNotification\Options.cs" />
<Compile Include="LocalNotification\ProgressBar.cs" />
<Compile Include="LocalNotification\Trigger.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore">
<Version>5.0.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.Portable.Compatibility">
<Version>1.0.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Microsoft.Toolkit.Uwp.Notifications.UWP\Microsoft.Toolkit.Uwp.Notifications.UWP.csproj">
<Project>{fb381278-f4ad-4703-a12a-c43ee0b231bd}</Project>
<Name>Microsoft.Toolkit.Uwp.Notifications.UWP</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment