 25bd5d8adb
			
		
	
	25bd5d8adb
	
	
	
		
			
			subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
		
			
				
	
	
		
			1245 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1245 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|   ==============================================================================
 | |
| 
 | |
|    This file is part of the JUCE examples.
 | |
|    Copyright (c) 2020 - Raw Material Software Limited
 | |
| 
 | |
|    The code included in this file is provided under the terms of the ISC license
 | |
|    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 | |
|    To use, copy, modify, and/or distribute this software for any purpose with or
 | |
|    without fee is hereby granted provided that the above copyright notice and
 | |
|    this permission notice appear in all copies.
 | |
| 
 | |
|    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
 | |
|    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
 | |
|    PURPOSE, ARE DISCLAIMED.
 | |
| 
 | |
|   ==============================================================================
 | |
| */
 | |
| 
 | |
| /*******************************************************************************
 | |
|  The block below describes the properties of this PIP. A PIP is a short snippet
 | |
|  of code that can be read by the Projucer and used to generate a JUCE project.
 | |
| 
 | |
|  BEGIN_JUCE_PIP_METADATA
 | |
| 
 | |
|  name:             PushNotificationsDemo
 | |
|  version:          2.0.0
 | |
|  vendor:           JUCE
 | |
|  website:          http://juce.com
 | |
|  description:      Showcases push notifications features. To run this demo you must enable the
 | |
|                    "Push Notifications Capability" option in the Projucer exporter.
 | |
| 
 | |
|  dependencies:     juce_audio_basics, juce_audio_devices, juce_audio_formats,
 | |
|                    juce_audio_processors, juce_audio_utils, juce_core,
 | |
|                    juce_data_structures, juce_events, juce_graphics,
 | |
|                    juce_gui_basics, juce_gui_extra
 | |
|  exporters:        xcode_mac, xcode_iphone, androidstudio
 | |
| 
 | |
|  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1
 | |
|                    JUCE_PUSH_NOTIFICATIONS=1
 | |
| 
 | |
|  type:             Component
 | |
|  mainClass:        PushNotificationsDemo
 | |
| 
 | |
|  useLocalCopy:     1
 | |
| 
 | |
|  END_JUCE_PIP_METADATA
 | |
| 
 | |
| *******************************************************************************/
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include "../Assets/DemoUtilities.h"
 | |
| 
 | |
| /*
 | |
|     To finish the setup of this demo, do the following:
 | |
| 
 | |
| 1. Download google_services.json from your Firebase project.
 | |
| 2. Update "Remote Notifications Config File" path in Android exporter (this can be different for debug and release)
 | |
|    to point to that json file.
 | |
| 3. Add image and sound resources by adding the following to "Extra Android Raw Resources" in Projucer:
 | |
| 
 | |
| ../../Assets/Notifications/images/ic_stat_name.png
 | |
| ../../Assets/Notifications/images/ic_stat_name2.png
 | |
| ../../Assets/Notifications/images/ic_stat_name3.png
 | |
| ../../Assets/Notifications/images/ic_stat_name4.png
 | |
| ../../Assets/Notifications/images/ic_stat_name5.png
 | |
| ../../Assets/Notifications/images/ic_stat_name6.png
 | |
| ../../Assets/Notifications/images/ic_stat_name7.png
 | |
| ../../Assets/Notifications/images/ic_stat_name8.png
 | |
| ../../Assets/Notifications/images/ic_stat_name9.png
 | |
| ../../Assets/Notifications/images/ic_stat_name10.png
 | |
| ../../Assets/Notifications/sounds/demonstrative.mp3
 | |
| ../../Assets/Notifications/sounds/isntit.mp3
 | |
| ../../Assets/Notifications/sounds/jinglebellssms.mp3
 | |
| ../../Assets/Notifications/sounds/served.mp3
 | |
| ../../Assets/Notifications/sounds/solemn.mp3
 | |
| 
 | |
| 4. Set "Remote Notifications" to enabled in Projucer Android exporter.
 | |
| 
 | |
| To verify that remote notifications are configured properly, go to Remote tab in the demo and press "GetDeviceToken"
 | |
| button, a dialog with your token (also printed to console in debug build) should show up.
 | |
| 
 | |
| 
 | |
| The following steps are only necessary if you have a custom activity defined:
 | |
| 
 | |
| 5. Ensure that its launchMode is set to "singleTop" or "singleTask" in Android manifest. This is the default behaviour
 | |
|    in JUCE so you only need to do it if you have custom Android manifest content. You can do it from Projucer by
 | |
|    ensuring that "Custom Manifest XML Content" contains:
 | |
| 
 | |
| <manifest>
 | |
| <application>
 | |
| <activity android:launchMode="singleTask">
 | |
| </activity>
 | |
| </application>
 | |
| </manifest>
 | |
| 
 | |
| 6. Ensure that you override onNewIntent() function in the same way as it is done in JuceActivity.java:
 | |
| 
 | |
| package com.rmsl.juce;
 | |
| 
 | |
| import android.app.Activity;
 | |
| import android.content.Intent;
 | |
| 
 | |
| //==============================================================================
 | |
| public class JuceActivity   extends Activity
 | |
| {
 | |
|     //==============================================================================
 | |
|     private native void appNewIntent (Intent intent);
 | |
| 
 | |
|     @Override
 | |
|     protected void onNewIntent (Intent intent)
 | |
|     {
 | |
|         super.onNewIntent(intent);
 | |
|         setIntent(intent);
 | |
| 
 | |
|         appNewIntent (intent);
 | |
|     }
 | |
| }
 | |
| 
 | |
| */
 | |
| 
 | |
| //==============================================================================
 | |
| class PushNotificationsDemo   : public Component,
 | |
|                                 private ChangeListener,
 | |
|                                 private ComponentListener,
 | |
|                                 private PushNotifications::Listener
 | |
| {
 | |
| public:
 | |
|     //==============================================================================
 | |
|     PushNotificationsDemo()
 | |
|     {
 | |
|         setupControls();
 | |
|         distributeControls();
 | |
| 
 | |
|       #if JUCE_PUSH_NOTIFICATIONS
 | |
|         addAndMakeVisible (headerLabel);
 | |
|         addAndMakeVisible (mainTabs);
 | |
|         addAndMakeVisible (sendButton);
 | |
|       #else
 | |
|         addAndMakeVisible (notAvailableYetLabel);
 | |
|       #endif
 | |
| 
 | |
|         headerLabel         .setJustificationType (Justification::centred);
 | |
|         notAvailableYetLabel.setJustificationType (Justification::centred);
 | |
| 
 | |
|       #if JUCE_MAC
 | |
|         StringArray tabNames { "Params1", "Params2", "Params3", "Params4" };
 | |
|       #else
 | |
|         StringArray tabNames { "Req. params", "Opt. params1", "Opt. params2", "Opt. params3" };
 | |
|       #endif
 | |
| 
 | |
|         auto colour = getLookAndFeel().findColour (ResizableWindow::backgroundColourId);
 | |
|         localNotificationsTabs.addTab (tabNames[0], colour, ¶msOneView, false);
 | |
|         localNotificationsTabs.addTab (tabNames[1], colour, ¶msTwoView, false);
 | |
|       #if JUCE_ANDROID
 | |
|         localNotificationsTabs.addTab (tabNames[2], colour, ¶msThreeView, false);
 | |
|         localNotificationsTabs.addTab (tabNames[3], colour, ¶msFourView,  false);
 | |
|       #endif
 | |
|         localNotificationsTabs.addTab ("Aux. actions", colour, &auxActionsView, false);
 | |
| 
 | |
|         mainTabs.addTab ("Local",  colour, &localNotificationsTabs, false);
 | |
|         mainTabs.addTab ("Remote", colour, &remoteView,             false);
 | |
| 
 | |
|         auto userArea = Desktop::getInstance().getDisplays().getPrimaryDisplay()->userArea;
 | |
|       #if JUCE_ANDROID || JUCE_IOS
 | |
|         setSize (userArea.getWidth(), userArea.getHeight());
 | |
|       #else
 | |
|         setSize (userArea.getWidth() / 2, userArea.getHeight() / 2);
 | |
|       #endif
 | |
| 
 | |
|         sendButton.onClick = [this] { sendLocalNotification(); };
 | |
|         auxActionsView.getDeliveredNotificationsButton .onClick = []
 | |
|             { PushNotifications::getInstance()->getDeliveredNotifications(); };
 | |
|         auxActionsView.removeDeliveredNotifWithIdButton.onClick = [this]
 | |
|             { PushNotifications::getInstance()->removeDeliveredNotification (auxActionsView.deliveredNotifIdentifier.getText()); };
 | |
|         auxActionsView.removeAllDeliveredNotifsButton  .onClick = []
 | |
|             { PushNotifications::getInstance()->removeAllDeliveredNotifications(); };
 | |
|       #if JUCE_IOS || JUCE_MAC
 | |
|         auxActionsView.getPendingNotificationsButton .onClick = []
 | |
|             { PushNotifications::getInstance()->getPendingLocalNotifications(); };
 | |
|         auxActionsView.removePendingNotifWithIdButton.onClick = [this]
 | |
|             { PushNotifications::getInstance()->removePendingLocalNotification (auxActionsView.pendingNotifIdentifier.getText()); };
 | |
|         auxActionsView.removeAllPendingNotifsButton  .onClick = []
 | |
|             { PushNotifications::getInstance()->removeAllPendingLocalNotifications(); };
 | |
|       #endif
 | |
| 
 | |
|         remoteView.getDeviceTokenButton.onClick = []
 | |
|         {
 | |
|             String token = PushNotifications::getInstance()->getDeviceToken();
 | |
| 
 | |
|             DBG ("token = " + token);
 | |
| 
 | |
|             if (token.isEmpty())
 | |
|                 showRemoteInstructions();
 | |
|             else
 | |
|                 NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                                .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                                .withTitle ("Device token")
 | |
|                                                .withMessage (token),
 | |
|                                              nullptr);
 | |
|         };
 | |
| 
 | |
|       #if JUCE_ANDROID
 | |
|         remoteView.sendRemoteMessageButton.onClick = []
 | |
|         {
 | |
|             StringPairArray data;
 | |
|             data.set ("key1", "value1");
 | |
|             data.set ("key2", "value2");
 | |
| 
 | |
|             static int id = 100;
 | |
|             PushNotifications::getInstance()->sendUpstreamMessage ("872047750958",
 | |
|                                                                    "com.juce.pushnotificationsdemo",
 | |
|                                                                    String (id++),
 | |
|                                                                    "standardType",
 | |
|                                                                    3600,
 | |
|                                                                    data);
 | |
|         };
 | |
| 
 | |
|         remoteView.subscribeToSportsButton    .onClick = []
 | |
|             { PushNotifications::getInstance()->subscribeToTopic ("sports"); };
 | |
|         remoteView.unsubscribeFromSportsButton.onClick = []
 | |
|             { PushNotifications::getInstance()->unsubscribeFromTopic ("sports"); };
 | |
|       #endif
 | |
| 
 | |
|         paramControls.accentColourButton.onClick = [this] { setupAccentColour(); };
 | |
|         paramControls.ledColourButton   .onClick = [this] { setupLedColour(); };
 | |
| 
 | |
|         jassert (PushNotifications::getInstance()->areNotificationsEnabled());
 | |
| 
 | |
|         PushNotifications::getInstance()->addListener (this);
 | |
| 
 | |
|       #if JUCE_IOS || JUCE_MAC
 | |
|         paramControls.fireInComboBox.onChange = [this] { delayNotification(); };
 | |
|         PushNotifications::getInstance()->requestPermissionsWithSettings (getNotificationSettings());
 | |
|       #elif JUCE_ANDROID
 | |
|         PushNotifications::ChannelGroup cg { "demoGroup", "demo group" };
 | |
|         PushNotifications::getInstance()->setupChannels ({ { cg } }, getAndroidChannels());
 | |
|       #endif
 | |
| 
 | |
|        #if JUCE_IOS || JUCE_ANDROID
 | |
|         setPortraitOrientationEnabled (true);
 | |
|        #endif
 | |
|     }
 | |
| 
 | |
|     ~PushNotificationsDemo() override
 | |
|     {
 | |
|         PushNotifications::getInstance()->removeListener (this);
 | |
| 
 | |
|        #if JUCE_IOS || JUCE_ANDROID
 | |
|         setPortraitOrientationEnabled (false);
 | |
|        #endif
 | |
|     }
 | |
| 
 | |
|     void setPortraitOrientationEnabled (bool shouldBeEnabled)
 | |
|     {
 | |
|         auto allowedOrientations = Desktop::getInstance().getOrientationsEnabled();
 | |
| 
 | |
|         if (shouldBeEnabled)
 | |
|             allowedOrientations |= Desktop::upright;
 | |
|         else
 | |
|             allowedOrientations &= ~Desktop::upright;
 | |
| 
 | |
|         Desktop::getInstance().setOrientationsEnabled (allowedOrientations);
 | |
|     }
 | |
| 
 | |
|     void paint (Graphics& g) override
 | |
|     {
 | |
|         g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
 | |
|     }
 | |
| 
 | |
|     void resized() override
 | |
|     {
 | |
|         auto bounds = getLocalBounds().reduced (getWidth() / 20, getHeight() / 40);
 | |
| 
 | |
|         headerLabel.setBounds (bounds.removeFromTop (bounds.proportionOfHeight (0.1f)));
 | |
|         mainTabs   .setBounds (bounds.removeFromTop (bounds.proportionOfHeight (0.8f)));
 | |
|         sendButton .setBounds (bounds);
 | |
| 
 | |
|         notAvailableYetLabel.setBounds (getLocalBounds());
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     void delayNotification()
 | |
|     {
 | |
|         auto repeatsAllowed = paramControls.fireInComboBox.getSelectedItemIndex() >= 6;
 | |
| 
 | |
|         paramControls.repeatButton.setEnabled (repeatsAllowed);
 | |
| 
 | |
|         if (! repeatsAllowed)
 | |
|             paramControls.repeatButton.setToggleState (false, NotificationType::sendNotification);
 | |
|     }
 | |
| 
 | |
|     void sendLocalNotification()
 | |
|     {
 | |
|         PushNotifications::Notification n;
 | |
| 
 | |
|         fillRequiredParams (n);
 | |
|         fillOptionalParamsOne (n);
 | |
|       #if JUCE_ANDROID
 | |
|         fillOptionalParamsTwo (n);
 | |
|         fillOptionalParamsThree (n);
 | |
|       #endif
 | |
| 
 | |
|         if (! n.isValid())
 | |
|         {
 | |
|           #if JUCE_IOS
 | |
|             String requiredFields = "identifier (from iOS 10), title, body and category";
 | |
|           #elif JUCE_ANDROID
 | |
|             String requiredFields = "channel ID (from Android O), title, body and icon";
 | |
|           #else
 | |
|             String requiredFields = "all required fields";
 | |
|           #endif
 | |
| 
 | |
|             NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                            .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                            .withTitle ("Incorrect notifications setup")
 | |
|                                            .withMessage ("Please make sure that " + requiredFields + " are set."),
 | |
|                                          nullptr);
 | |
| 
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         PushNotifications::getInstance()->sendLocalNotification (n);
 | |
|     }
 | |
| 
 | |
|     void fillRequiredParams      (PushNotifications::Notification& n)
 | |
|     {
 | |
|         n.identifier = paramControls.identifierEditor.getText();
 | |
|         n.title      = paramControls.titleEditor     .getText();
 | |
|         n.body       = paramControls.bodyEditor      .getText();
 | |
|       #if JUCE_IOS
 | |
|         n.category = paramControls.categoryComboBox.getText();
 | |
|       #elif JUCE_ANDROID || JUCE_MAC
 | |
|        #if JUCE_MAC
 | |
|         String prefix = "Notifications/images/";
 | |
|         String extension = ".png";
 | |
|        #else
 | |
|         String prefix;
 | |
|         String extension;
 | |
|        #endif
 | |
|         if (paramControls.iconComboBox.getSelectedItemIndex() == 0)
 | |
|             n.icon = prefix + "ic_stat_name" + extension;
 | |
|         else if (paramControls.iconComboBox.getSelectedItemIndex() == 1)
 | |
|             n.icon = prefix + "ic_stat_name2" + extension;
 | |
|         else if (paramControls.iconComboBox.getSelectedItemIndex() == 2)
 | |
|             n.icon = prefix + "ic_stat_name3" + extension;
 | |
|         else if (paramControls.iconComboBox.getSelectedItemIndex() == 3)
 | |
|             n.icon = prefix + "ic_stat_name4" + extension;
 | |
|         else if (paramControls.iconComboBox.getSelectedItemIndex() == 4)
 | |
|             n.icon = prefix + "ic_stat_name5" + extension;
 | |
|       #endif
 | |
| 
 | |
|       #if JUCE_ANDROID
 | |
|         // Note: this is not strictly speaking required param, just doing it here because it is the fastest way!
 | |
|         n.publicVersion.reset (new PushNotifications::Notification());
 | |
|         n.publicVersion->identifier = "blahblahblah";
 | |
|         n.publicVersion->title      = "Public title!";
 | |
|         n.publicVersion->body       = "Public body!";
 | |
|         n.publicVersion->icon       = n.icon;
 | |
| 
 | |
|         n.channelId = String (paramControls.channelIdComboBox.getSelectedItemIndex() + 1);
 | |
|       #endif
 | |
|     }
 | |
| 
 | |
|     void fillOptionalParamsOne   (PushNotifications::Notification& n)
 | |
|     {
 | |
|         n.subtitle = paramControls.subtitleEditor.getText();
 | |
|         n.badgeNumber = paramControls.badgeNumberComboBox.getSelectedItemIndex();
 | |
| 
 | |
|         if (paramControls.soundToPlayComboBox.getSelectedItemIndex() > 0)
 | |
|             n.soundToPlay = URL (paramControls.soundToPlayComboBox.getItemText (paramControls.soundToPlayComboBox.getSelectedItemIndex()));
 | |
| 
 | |
|         n.properties = JSON::parse (paramControls.propertiesEditor.getText());
 | |
| 
 | |
|       #if JUCE_IOS || JUCE_MAC
 | |
|         n.triggerIntervalSec = double (paramControls.fireInComboBox.getSelectedItemIndex() * 10);
 | |
|         n.repeat = paramControls.repeatButton.getToggleState();
 | |
|       #elif JUCE_ANDROID
 | |
|         if (paramControls.largeIconComboBox.getSelectedItemIndex() == 1)
 | |
|             n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name6.png");
 | |
|         else if (paramControls.largeIconComboBox.getSelectedItemIndex() == 2)
 | |
|             n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name7.png");
 | |
|         else if (paramControls.largeIconComboBox.getSelectedItemIndex() == 3)
 | |
|             n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name8.png");
 | |
|         else if (paramControls.largeIconComboBox.getSelectedItemIndex() == 4)
 | |
|             n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name9.png");
 | |
|         else if (paramControls.largeIconComboBox.getSelectedItemIndex() == 5)
 | |
|             n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name10.png");
 | |
| 
 | |
|         n.badgeIconType = (PushNotifications::Notification::BadgeIconType) paramControls.badgeIconComboBox.getSelectedItemIndex();
 | |
|         n.tickerText  = paramControls.tickerTextEditor.getText();
 | |
| 
 | |
|         n.shouldAutoCancel = paramControls.autoCancelButton   .getToggleState();
 | |
|         n.alertOnlyOnce    = paramControls.alertOnlyOnceButton.getToggleState();
 | |
|       #endif
 | |
| 
 | |
|       #if JUCE_ANDROID || JUCE_MAC
 | |
|         if (paramControls.actionsComboBox.getSelectedItemIndex() == 1)
 | |
|         {
 | |
|             PushNotifications::Notification::Action a, a2;
 | |
|             a .style = PushNotifications::Notification::Action::button;
 | |
|             a2.style = PushNotifications::Notification::Action::button;
 | |
|             a .title = a .identifier = "Ok";
 | |
|             a2.title = a2.identifier = "Cancel";
 | |
|             n.actions.add (a);
 | |
|             n.actions.add (a2);
 | |
|         }
 | |
|         else if (paramControls.actionsComboBox.getSelectedItemIndex() == 2)
 | |
|         {
 | |
|             PushNotifications::Notification::Action a, a2;
 | |
|             a .title = a .identifier = "Input Text Here";
 | |
|             a2.title = a2.identifier = "No";
 | |
|             a .style = PushNotifications::Notification::Action::text;
 | |
|             a2.style = PushNotifications::Notification::Action::button;
 | |
|             a .icon = "ic_stat_name4";
 | |
|             a2.icon = "ic_stat_name5";
 | |
|             a.textInputPlaceholder = "placeholder text ...";
 | |
|             n.actions.add (a);
 | |
|             n.actions.add (a2);
 | |
|         }
 | |
|         else if (paramControls.actionsComboBox.getSelectedItemIndex() == 3)
 | |
|         {
 | |
|             PushNotifications::Notification::Action a, a2;
 | |
|             a .title = a .identifier = "Ok";
 | |
|             a2.title = a2.identifier = "Cancel";
 | |
|             a .style = PushNotifications::Notification::Action::button;
 | |
|             a2.style = PushNotifications::Notification::Action::button;
 | |
|             a .icon = "ic_stat_name4";
 | |
|             a2.icon = "ic_stat_name5";
 | |
|             n.actions.add (a);
 | |
|             n.actions.add (a2);
 | |
|         }
 | |
|         else if (paramControls.actionsComboBox.getSelectedItemIndex() == 4)
 | |
|         {
 | |
|             PushNotifications::Notification::Action a, a2;
 | |
|             a .title = a .identifier = "Input Text Here";
 | |
|             a2.title = a2.identifier = "No";
 | |
|             a .style = PushNotifications::Notification::Action::text;
 | |
|             a2.style = PushNotifications::Notification::Action::button;
 | |
|             a .icon = "ic_stat_name4";
 | |
|             a2.icon = "ic_stat_name5";
 | |
|             a.textInputPlaceholder = "placeholder text ...";
 | |
|             a.allowedResponses.add ("Response 1");
 | |
|             a.allowedResponses.add ("Response 2");
 | |
|             a.allowedResponses.add ("Response 3");
 | |
|             n.actions.add (a);
 | |
|             n.actions.add (a2);
 | |
|         }
 | |
|       #endif
 | |
|     }
 | |
| 
 | |
|     void fillOptionalParamsTwo   (PushNotifications::Notification& n)
 | |
|     {
 | |
|         using Notification = PushNotifications::Notification;
 | |
| 
 | |
|         Notification::Progress progress;
 | |
|         progress.max           = paramControls.progressMaxComboBox    .getSelectedItemIndex() * 10;
 | |
|         progress.current       = paramControls.progressCurrentComboBox.getSelectedItemIndex() * 10;
 | |
|         progress.indeterminate = paramControls.progressIndeterminateButton.getToggleState();
 | |
| 
 | |
|         n.progress = progress;
 | |
|         n.person   = paramControls.personEditor.getText();
 | |
|         n.type                 = Notification::Type                 (paramControls.categoryComboBox            .getSelectedItemIndex());
 | |
|         n.priority             = Notification::Priority             (paramControls.priorityComboBox            .getSelectedItemIndex() - 2);
 | |
|         n.lockScreenAppearance = Notification::LockScreenAppearance (paramControls.lockScreenVisibilityComboBox.getSelectedItemIndex() - 1);
 | |
|         n.groupId      = paramControls.groupIdEditor.getText();
 | |
|         n.groupSortKey = paramControls.sortKeyEditor.getText();
 | |
|         n.groupSummary = paramControls.groupSummaryButton.getToggleState();
 | |
|         n.groupAlertBehaviour = Notification::GroupAlertBehaviour (paramControls.groupAlertBehaviourComboBox.getSelectedItemIndex());
 | |
|     }
 | |
| 
 | |
|     void fillOptionalParamsThree (PushNotifications::Notification& n)
 | |
|     {
 | |
|         n.accentColour = paramControls.accentColourButton.findColour (TextButton::buttonColourId, false);
 | |
|         n.ledColour    = paramControls.ledColourButton   .findColour (TextButton::buttonColourId, false);
 | |
| 
 | |
|         using Notification = PushNotifications::Notification;
 | |
|         Notification::LedBlinkPattern ledBlinkPattern;
 | |
|         ledBlinkPattern.msToBeOn  = paramControls.ledMsToBeOnComboBox .getSelectedItemIndex() * 200;
 | |
|         ledBlinkPattern.msToBeOff = paramControls.ledMsToBeOffComboBox.getSelectedItemIndex() * 200;
 | |
|         n.ledBlinkPattern = ledBlinkPattern;
 | |
| 
 | |
|         Array<int> vibrationPattern;
 | |
| 
 | |
|         if (paramControls.vibratorMsToBeOnComboBox .getSelectedItemIndex() > 0 &&
 | |
|             paramControls.vibratorMsToBeOffComboBox.getSelectedItemIndex() > 0)
 | |
|         {
 | |
|             vibrationPattern.add     (paramControls.vibratorMsToBeOffComboBox.getSelectedItemIndex() * 500);
 | |
|             vibrationPattern.add     (paramControls.vibratorMsToBeOnComboBox .getSelectedItemIndex() * 500);
 | |
|             vibrationPattern.add (2 * paramControls.vibratorMsToBeOffComboBox.getSelectedItemIndex() * 500);
 | |
|             vibrationPattern.add (2 * paramControls.vibratorMsToBeOnComboBox .getSelectedItemIndex() * 500);
 | |
|         }
 | |
| 
 | |
|         n.vibrationPattern = vibrationPattern;
 | |
| 
 | |
|         n.localOnly = paramControls.localOnlyButton.getToggleState();
 | |
|         n.ongoing = paramControls.ongoingButton.getToggleState();
 | |
|         n.timestampVisibility = Notification::TimestampVisibility (paramControls.timestampVisibilityComboBox.getSelectedItemIndex());
 | |
| 
 | |
|         if (paramControls.timeoutAfterComboBox.getSelectedItemIndex() > 0)
 | |
|         {
 | |
|             auto index = paramControls.timeoutAfterComboBox.getSelectedItemIndex();
 | |
|             n.timeoutAfterMs = index * 1000 + 4000;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void setupAccentColour()
 | |
|     {
 | |
|         auto accentColourSelector = std::make_unique<ColourSelector>();
 | |
| 
 | |
|         accentColourSelector->setName ("accent colour");
 | |
|         accentColourSelector->setCurrentColour (paramControls.accentColourButton.findColour (TextButton::buttonColourId));
 | |
|         accentColourSelector->setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);
 | |
|         accentColourSelector->setSize (200, 200);
 | |
|         accentColourSelector->addComponentListener (this);
 | |
|         accentColourSelector->addChangeListener (this);
 | |
| 
 | |
|         paramControls.accentColourSelector = accentColourSelector.get();
 | |
| 
 | |
|         CallOutBox::launchAsynchronously (std::move (accentColourSelector), paramControls.accentColourButton.getScreenBounds(), nullptr);
 | |
|     }
 | |
| 
 | |
|     void setupLedColour()
 | |
|     {
 | |
|         auto ledColourSelector = std::make_unique<ColourSelector>();
 | |
| 
 | |
|         ledColourSelector->setName ("led colour");
 | |
|         ledColourSelector->setCurrentColour (paramControls.ledColourButton.findColour (TextButton::buttonColourId));
 | |
|         ledColourSelector->setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);
 | |
|         ledColourSelector->setSize (200, 200);
 | |
|         ledColourSelector->addComponentListener (this);
 | |
|         ledColourSelector->addChangeListener (this);
 | |
| 
 | |
|         paramControls.ledColourSelector = ledColourSelector.get();
 | |
| 
 | |
|         CallOutBox::launchAsynchronously (std::move (ledColourSelector), paramControls.accentColourButton.getScreenBounds(), nullptr);
 | |
|     }
 | |
| 
 | |
|     void changeListenerCallback (ChangeBroadcaster* source) override
 | |
|     {
 | |
|         if (source == paramControls.accentColourSelector)
 | |
|         {
 | |
|             auto c = paramControls.accentColourSelector->getCurrentColour();
 | |
|             paramControls.accentColourButton.setColour (TextButton::buttonColourId, c);
 | |
|         }
 | |
|         else if (source == paramControls.ledColourSelector)
 | |
|         {
 | |
|             auto c = paramControls.ledColourSelector->getCurrentColour();
 | |
|             paramControls.ledColourButton.setColour (TextButton::buttonColourId, c);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void componentBeingDeleted (Component& component) override
 | |
|     {
 | |
|         if (&component == paramControls.accentColourSelector)
 | |
|             paramControls.accentColourSelector = nullptr;
 | |
|         else if (&component == paramControls.ledColourSelector)
 | |
|             paramControls.ledColourSelector = nullptr;
 | |
|     }
 | |
| 
 | |
|     void handleNotification (bool isLocalNotification, const PushNotifications::Notification& n) override
 | |
|     {
 | |
|         ignoreUnused (isLocalNotification);
 | |
| 
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Received notification")
 | |
|                                        .withMessage ("ID: " + n.identifier
 | |
|                                                      + ", title: " + n.title
 | |
|                                                      + ", body: " + n.body),
 | |
|                                      nullptr);
 | |
|     }
 | |
| 
 | |
|     void handleNotificationAction (bool isLocalNotification,
 | |
|                                    const PushNotifications::Notification& n,
 | |
|                                    const juce::String& actionIdentifier,
 | |
|                                    const juce::String& optionalResponse) override
 | |
|     {
 | |
|         ignoreUnused (isLocalNotification);
 | |
| 
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Received notification action")
 | |
|                                        .withMessage ("ID: " + n.identifier
 | |
|                                                      + ", title: " + n.title
 | |
|                                                      + ", body: " + n.body
 | |
|                                                      + ", action: " + actionIdentifier
 | |
|                                                      + ", optionalResponse: " + optionalResponse),
 | |
|                                      nullptr);
 | |
| 
 | |
|         PushNotifications::getInstance()->removeDeliveredNotification (n.identifier);
 | |
|     }
 | |
| 
 | |
|     void localNotificationDismissedByUser (const PushNotifications::Notification& n) override
 | |
|     {
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Notification dismissed by a user")
 | |
|                                        .withMessage ("ID: " + n.identifier
 | |
|                                                      + ", title: " + n.title
 | |
|                                                      + ", body: " + n.body),
 | |
|                                      nullptr);
 | |
|     }
 | |
| 
 | |
|     void deliveredNotificationsListReceived (const Array<PushNotifications::Notification>& notifs) override
 | |
|     {
 | |
|         String text = "Received notifications: ";
 | |
| 
 | |
|         for (auto& n : notifs)
 | |
|             text << "(" << n.identifier << ", " << n.title << ", " << n.body << "), ";
 | |
| 
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Received notification list")
 | |
|                                        .withMessage (text),
 | |
|                                      nullptr);
 | |
|     }
 | |
| 
 | |
|     void pendingLocalNotificationsListReceived (const Array<PushNotifications::Notification>& notifs) override
 | |
|     {
 | |
|         String text = "Pending notifications: ";
 | |
| 
 | |
|         for (auto& n : notifs)
 | |
|             text << "(" << n.identifier << ", " << n.title << ", " << n.body << "), ";
 | |
| 
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Pending notification list")
 | |
|                                        .withMessage (text),
 | |
|                                      nullptr);
 | |
|     }
 | |
| 
 | |
|     void deviceTokenRefreshed (const String& token) override
 | |
|     {
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Device token refreshed")
 | |
|                                        .withMessage (token),
 | |
|                                      nullptr);
 | |
|     }
 | |
| 
 | |
|   #if JUCE_ANDROID
 | |
|     void remoteNotificationsDeleted() override
 | |
|     {
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Remote notifications deleted")
 | |
|                                        .withMessage ("Some of the pending messages were removed!"),
 | |
|                                      nullptr);
 | |
|     }
 | |
| 
 | |
|     void upstreamMessageSent (const String& messageId) override
 | |
|     {
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Upstream message sent")
 | |
|                                        .withMessage ("Message id: " + messageId),
 | |
|                                      nullptr);
 | |
|     }
 | |
| 
 | |
|     void upstreamMessageSendingError (const String& messageId, const String& error) override
 | |
|     {
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Upstream message sending error")
 | |
|                                        .withMessage ("Message id: " + messageId
 | |
|                                                      + "\nerror: " + error),
 | |
|                                      nullptr);
 | |
|     }
 | |
| 
 | |
|     static Array<PushNotifications::Channel> getAndroidChannels()
 | |
|     {
 | |
|         using Channel = PushNotifications::Channel;
 | |
| 
 | |
|         Channel ch1, ch2, ch3;
 | |
| 
 | |
|         ch1.identifier = "1";
 | |
|         ch1.name = "HighImportance";
 | |
|         ch1.importance = PushNotifications::Channel::max;
 | |
|         ch1.lockScreenAppearance = PushNotifications::Notification::showCompletely;
 | |
|         ch1.description = "High Priority Channel for important stuff";
 | |
|         ch1.groupId = "demoGroup";
 | |
|         ch1.ledColour = Colours::red;
 | |
|         ch1.bypassDoNotDisturb = true;
 | |
|         ch1.canShowBadge = true;
 | |
|         ch1.enableLights = true;
 | |
|         ch1.enableVibration = true;
 | |
|         ch1.soundToPlay = URL ("demonstrative");
 | |
|         ch1.vibrationPattern = { 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 };
 | |
| 
 | |
|         ch2.identifier = "2";
 | |
|         ch2.name = "MediumImportance";
 | |
|         ch2.importance = PushNotifications::Channel::normal;
 | |
|         ch2.lockScreenAppearance = PushNotifications::Notification::showPartially;
 | |
|         ch2.description = "Medium Priority Channel for standard stuff";
 | |
|         ch2.groupId = "demoGroup";
 | |
|         ch2.ledColour = Colours::yellow;
 | |
|         ch2.canShowBadge = true;
 | |
|         ch2.enableLights = true;
 | |
|         ch2.enableVibration = true;
 | |
|         ch2.soundToPlay = URL ("default_os_sound");
 | |
|         ch2.vibrationPattern = { 1000, 1000 };
 | |
| 
 | |
|         ch3.identifier = "3";
 | |
|         ch3.name = "LowImportance";
 | |
|         ch3.importance = PushNotifications::Channel::min;
 | |
|         ch3.lockScreenAppearance = PushNotifications::Notification::dontShow;
 | |
|         ch3.description = "Low Priority Channel for silly stuff";
 | |
|         ch3.groupId = "demoGroup";
 | |
| 
 | |
|         return { ch1, ch2, ch3 };
 | |
|     }
 | |
| 
 | |
|   #elif JUCE_IOS || JUCE_MAC
 | |
|     static PushNotifications::Settings getNotificationSettings()
 | |
|     {
 | |
|         PushNotifications::Settings settings;
 | |
|         settings.allowAlert = true;
 | |
|         settings.allowBadge = true;
 | |
|         settings.allowSound = true;
 | |
| 
 | |
|       #if JUCE_IOS
 | |
|         using Action   = PushNotifications::Settings::Action;
 | |
|         using Category = PushNotifications::Settings::Category;
 | |
| 
 | |
|         Action okAction;
 | |
|         okAction.identifier = "okAction";
 | |
|         okAction.title = "OK!";
 | |
|         okAction.style = Action::button;
 | |
|         okAction.triggerInBackground = true;
 | |
| 
 | |
|         Action cancelAction;
 | |
|         cancelAction.identifier = "cancelAction";
 | |
|         cancelAction.title = "Cancel";
 | |
|         cancelAction.style = Action::button;
 | |
|         cancelAction.triggerInBackground = true;
 | |
|         cancelAction.destructive = true;
 | |
| 
 | |
|         Action textAction;
 | |
|         textAction.identifier = "textAction";
 | |
|         textAction.title = "Enter text";
 | |
|         textAction.style = Action::text;
 | |
|         textAction.triggerInBackground = true;
 | |
|         textAction.destructive = false;
 | |
|         textAction.textInputButtonText = "Ok";
 | |
|         textAction.textInputPlaceholder = "Enter text...";
 | |
| 
 | |
|         Category okCategory;
 | |
|         okCategory.identifier = "okCategory";
 | |
|         okCategory.actions = { okAction };
 | |
| 
 | |
|         Category okCancelCategory;
 | |
|         okCancelCategory.identifier = "okCancelCategory";
 | |
|         okCancelCategory.actions = { okAction, cancelAction };
 | |
| 
 | |
|         Category textCategory;
 | |
|         textCategory.identifier = "textCategory";
 | |
|         textCategory.actions = { textAction };
 | |
|         textCategory.sendDismissAction = true;
 | |
| 
 | |
|         settings.categories = { okCategory, okCancelCategory, textCategory };
 | |
|       #endif
 | |
| 
 | |
|         return settings;
 | |
|     }
 | |
|   #endif
 | |
| 
 | |
|     struct RowComponent : public Component
 | |
|     {
 | |
|         RowComponent (Label& l, Component& c, int u = 1)
 | |
|             : label (l),
 | |
|               editor (c),
 | |
|               rowUnits (u)
 | |
|         {
 | |
|             addAndMakeVisible (label);
 | |
|             addAndMakeVisible (editor);
 | |
|         }
 | |
| 
 | |
|         void resized() override
 | |
|         {
 | |
|             auto bounds = getLocalBounds();
 | |
|             label .setBounds (bounds.removeFromLeft (getWidth() / 3));
 | |
|             editor.setBounds (bounds);
 | |
|         }
 | |
| 
 | |
|         Label& label;
 | |
|         Component& editor;
 | |
|         int rowUnits;
 | |
|     };
 | |
| 
 | |
|     struct ParamControls
 | |
|     {
 | |
|         Label        identifierLabel            { "identifierLabel",            "Identifier" };
 | |
|         TextEditor   identifierEditor;
 | |
|         Label        titleLabel                 { "titleLabel",                 "Title" };
 | |
|         TextEditor   titleEditor;
 | |
|         Label        bodyLabel                  { "bodyLabel",                  "Body" };
 | |
|         TextEditor   bodyEditor;
 | |
| 
 | |
|         Label        categoryLabel              { "categoryLabel",              "Category" };
 | |
|         ComboBox     categoryComboBox;
 | |
|         Label        channelIdLabel             { "channelIdLabel",             "Channel ID" };
 | |
|         ComboBox     channelIdComboBox;
 | |
|         Label        iconLabel                  { "iconLabel",                  "Icon" };
 | |
|         ComboBox     iconComboBox;
 | |
| 
 | |
|         Label        subtitleLabel              { "subtitleLabel",              "Subtitle" };
 | |
|         TextEditor   subtitleEditor;
 | |
|         Label        badgeNumberLabel           { "badgeNumberLabel",           "BadgeNumber" };
 | |
|         ComboBox     badgeNumberComboBox;
 | |
|         Label        soundToPlayLabel           { "soundToPlayLabel",           "SoundToPlay" };
 | |
|         ComboBox     soundToPlayComboBox;
 | |
|         Label        propertiesLabel            { "propertiesLabel",            "Properties" };
 | |
|         TextEditor   propertiesEditor;
 | |
|         Label        fireInLabel                { "fireInLabel",                "Fire in" };
 | |
|         ComboBox     fireInComboBox;
 | |
|         Label        repeatLabel                { "repeatLabel",                "Repeat" };
 | |
|         ToggleButton repeatButton;
 | |
|         Label        largeIconLabel             { "largeIconLabel",             "Large Icon" };
 | |
|         ComboBox     largeIconComboBox;
 | |
|         Label        badgeIconLabel             { "badgeIconLabel",             "Badge Icon" };
 | |
|         ComboBox     badgeIconComboBox;
 | |
|         Label        tickerTextLabel            { "tickerTextLabel",            "Ticker Text" };
 | |
|         TextEditor   tickerTextEditor;
 | |
|         Label        autoCancelLabel            { "autoCancelLabel",            "AutoCancel" };
 | |
|         ToggleButton autoCancelButton;
 | |
|         Label        alertOnlyOnceLabel         { "alertOnlyOnceLabel",         "AlertOnlyOnce" };
 | |
|         ToggleButton alertOnlyOnceButton;
 | |
|         Label        actionsLabel               { "actionsLabel",               "Actions" };
 | |
|         ComboBox     actionsComboBox;
 | |
| 
 | |
|         Label        progressMaxLabel           { "progressMaxLabel",           "ProgressMax" };
 | |
|         ComboBox     progressMaxComboBox;
 | |
|         Label        progressCurrentLabel       { "progressCurrentLabel",       "ProgressCurrent" };
 | |
|         ComboBox     progressCurrentComboBox;
 | |
|         Label        progressIndeterminateLabel { "progressIndeterminateLabel", "ProgressIndeterminate" };
 | |
|         ToggleButton progressIndeterminateButton;
 | |
|         Label        notifCategoryLabel         { "notifCategoryLabel",         "Category" };
 | |
|         ComboBox     notifCategoryComboBox;
 | |
|         Label        priorityLabel              { "priorityLabel",              "Priority" };
 | |
|         ComboBox     priorityComboBox;
 | |
|         Label        personLabel                { "personLabel",                "Person" };
 | |
|         TextEditor   personEditor;
 | |
|         Label        lockScreenVisibilityLabel  { "lockScreenVisibilityLabel",  "LockScreenVisibility" };
 | |
|         ComboBox     lockScreenVisibilityComboBox;
 | |
|         Label        groupIdLabel               { "groupIdLabel",               "GroupID" };
 | |
|         TextEditor   groupIdEditor;
 | |
|         Label        sortKeyLabel               { "sortKeyLabel",               "SortKey" };
 | |
|         TextEditor   sortKeyEditor;
 | |
|         Label        groupSummaryLabel          { "groupSummaryLabel",          "GroupSummary" };
 | |
|         ToggleButton groupSummaryButton;
 | |
|         Label        groupAlertBehaviourLabel   { "groupAlertBehaviourLabel",   "GroupAlertBehaviour" };
 | |
|         ComboBox     groupAlertBehaviourComboBox;
 | |
| 
 | |
|         Label        accentColourLabel          { "accentColourLabel",          "AccentColour" };
 | |
|         TextButton   accentColourButton;
 | |
|         Label        ledColourLabel             { "ledColourLabel",             "LedColour" };
 | |
|         TextButton   ledColourButton;
 | |
|         Label        ledMsToBeOnLabel           { "ledMsToBeOnLabel",           "LedMsToBeOn" };
 | |
|         ComboBox     ledMsToBeOnComboBox;
 | |
|         Label        ledMsToBeOffLabel          { "ledMsToBeOffLabel",          "LedMsToBeOff" };
 | |
|         ComboBox     ledMsToBeOffComboBox;
 | |
|         Label        vibratorMsToBeOnLabel      { "vibratorMsToBeOnLabel",      "VibrationMsToBeOn" };
 | |
|         ComboBox     vibratorMsToBeOnComboBox;
 | |
|         Label        vibratorMsToBeOffLabel     { "vibratorMsToBeOffLabel",     "VibrationMsToBeOff" };
 | |
|         ComboBox     vibratorMsToBeOffComboBox;
 | |
|         Label        localOnlyLabel             { "localOnlyLabel",             "LocalOnly" };
 | |
|         ToggleButton localOnlyButton;
 | |
|         Label        ongoingLabel               { "ongoingLabel",               "Ongoing" };
 | |
|         ToggleButton ongoingButton;
 | |
|         Label        timestampVisibilityLabel   { "timestampVisibilityLabel",   "TimestampMode" };
 | |
|         ComboBox     timestampVisibilityComboBox;
 | |
|         Label        timeoutAfterLabel          { "timeoutAfterLabel",          "Timeout After Ms" };
 | |
|         ComboBox     timeoutAfterComboBox;
 | |
| 
 | |
|         ColourSelector* accentColourSelector = nullptr;
 | |
|         ColourSelector* ledColourSelector    = nullptr;
 | |
|     };
 | |
| 
 | |
|     void setupControls()
 | |
|     {
 | |
|         auto& pc = paramControls;
 | |
| 
 | |
|         StringArray categories { "okCategory", "okCancelCategory", "textCategory" };
 | |
| 
 | |
|         for (auto& c : categories)
 | |
|             pc.categoryComboBox.addItem (c, pc.categoryComboBox.getNumItems() + 1);
 | |
|         pc.categoryComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|         for (auto i = 1; i <= 3; ++i)
 | |
|             pc.channelIdComboBox.addItem (String (i), i);
 | |
|         pc.channelIdComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|         for (auto i = 0; i < 5; ++i)
 | |
|             pc.iconComboBox.addItem ("icon" + String (i + 1), i + 1);
 | |
|         pc.iconComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|       #if JUCE_MAC
 | |
|         pc.iconComboBox.addItem ("none", 100);
 | |
|       #endif
 | |
| 
 | |
|         pc.fireInComboBox.addItem ("Now", 1);
 | |
| 
 | |
|         for (auto i = 1; i < 11; ++i)
 | |
|             pc.fireInComboBox.addItem (String (10 * i) + "seconds", i + 1);
 | |
|         pc.fireInComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|         pc.largeIconComboBox.addItem ("none", 1);
 | |
| 
 | |
|         for (auto i = 1; i < 5; ++i)
 | |
|             pc.largeIconComboBox.addItem ("icon" + String (i), i + 1);
 | |
|         pc.largeIconComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|         pc.badgeIconComboBox.addItem ("none",  1);
 | |
|         pc.badgeIconComboBox.addItem ("small", 2);
 | |
|         pc.badgeIconComboBox.addItem ("large", 3);
 | |
|         pc.badgeIconComboBox.setSelectedItemIndex (2);
 | |
| 
 | |
|         pc.actionsComboBox.addItem ("none",       1);
 | |
|         pc.actionsComboBox.addItem ("ok-cancel",  2);
 | |
|         pc.actionsComboBox.addItem ("text-input", 3);
 | |
|       #if JUCE_ANDROID
 | |
|         pc.actionsComboBox.addItem ("ok-cancel-icons", 4);
 | |
|         pc.actionsComboBox.addItem ("text-input-limited_responses", 5);
 | |
|       #endif
 | |
|         pc.actionsComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|         for (auto i = 0; i < 7; ++i)
 | |
|             pc.badgeNumberComboBox.addItem (String (i), i + 1);
 | |
|         pc.badgeNumberComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|       #if JUCE_IOS
 | |
|         String prefix = "Notifications/sounds/";
 | |
|         String extension = ".caf";
 | |
|       #else
 | |
|         String prefix;
 | |
|         String extension;
 | |
|       #endif
 | |
| 
 | |
|         pc.soundToPlayComboBox.addItem ("none", 1);
 | |
|         pc.soundToPlayComboBox.addItem ("default_os_sound", 2);
 | |
|         pc.soundToPlayComboBox.addItem (prefix + "demonstrative"  + extension, 3);
 | |
|         pc.soundToPlayComboBox.addItem (prefix + "isntit"         + extension, 4);
 | |
|         pc.soundToPlayComboBox.addItem (prefix + "jinglebellssms" + extension, 5);
 | |
|         pc.soundToPlayComboBox.addItem (prefix + "served"         + extension, 6);
 | |
|         pc.soundToPlayComboBox.addItem (prefix + "solemn"         + extension, 7);
 | |
|         pc.soundToPlayComboBox.setSelectedItemIndex (1);
 | |
| 
 | |
|         for (auto i = 0; i < 11; ++i)
 | |
|         {
 | |
|             pc.progressMaxComboBox    .addItem (String (i * 10) + "%", i + 1);
 | |
|             pc.progressCurrentComboBox.addItem (String (i * 10) + "%", i + 1);
 | |
|         }
 | |
| 
 | |
|         pc.progressMaxComboBox    .setSelectedItemIndex (0);
 | |
|         pc.progressCurrentComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|         pc.notifCategoryComboBox.addItem ("unspecified",     1);
 | |
|         pc.notifCategoryComboBox.addItem ("alarm",           2);
 | |
|         pc.notifCategoryComboBox.addItem ("call",            3);
 | |
|         pc.notifCategoryComboBox.addItem ("email",           4);
 | |
|         pc.notifCategoryComboBox.addItem ("error",           5);
 | |
|         pc.notifCategoryComboBox.addItem ("event",           6);
 | |
|         pc.notifCategoryComboBox.addItem ("message",         7);
 | |
|         pc.notifCategoryComboBox.addItem ("progress",        8);
 | |
|         pc.notifCategoryComboBox.addItem ("promo",           9);
 | |
|         pc.notifCategoryComboBox.addItem ("recommendation", 10);
 | |
|         pc.notifCategoryComboBox.addItem ("reminder",       11);
 | |
|         pc.notifCategoryComboBox.addItem ("service",        12);
 | |
|         pc.notifCategoryComboBox.addItem ("social",         13);
 | |
|         pc.notifCategoryComboBox.addItem ("status",         14);
 | |
|         pc.notifCategoryComboBox.addItem ("system",         15);
 | |
|         pc.notifCategoryComboBox.addItem ("transport",      16);
 | |
|         pc.notifCategoryComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|         for (auto i = -2; i < 3; ++i)
 | |
|             pc.priorityComboBox.addItem (String (i), i + 3);
 | |
|         pc.priorityComboBox.setSelectedItemIndex (2);
 | |
| 
 | |
|         pc.lockScreenVisibilityComboBox.addItem ("don't show",      1);
 | |
|         pc.lockScreenVisibilityComboBox.addItem ("show partially",  2);
 | |
|         pc.lockScreenVisibilityComboBox.addItem ("show completely", 3);
 | |
|         pc.lockScreenVisibilityComboBox.setSelectedItemIndex (1);
 | |
| 
 | |
|         pc.groupAlertBehaviourComboBox.addItem ("alert all",      1);
 | |
|         pc.groupAlertBehaviourComboBox.addItem ("alert summary",  2);
 | |
|         pc.groupAlertBehaviourComboBox.addItem ("alert children", 3);
 | |
|         pc.groupAlertBehaviourComboBox.setSelectedItemIndex (0);
 | |
| 
 | |
|         pc.timeoutAfterComboBox.addItem ("No timeout", 1);
 | |
| 
 | |
|         for (auto i = 0; i < 10; ++i)
 | |
|         {
 | |
|             pc.ledMsToBeOnComboBox      .addItem (String (i * 200) + "ms", i + 1);
 | |
|             pc.ledMsToBeOffComboBox     .addItem (String (i * 200) + "ms", i + 1);
 | |
|             pc.vibratorMsToBeOnComboBox .addItem (String (i * 500) + "ms", i + 1);
 | |
|             pc.vibratorMsToBeOffComboBox.addItem (String (i * 500) + "ms", i + 1);
 | |
|             pc.timeoutAfterComboBox     .addItem (String (5000 + 1000 * i) + "ms", i + 2);
 | |
|         }
 | |
| 
 | |
|         pc.ledMsToBeOnComboBox      .setSelectedItemIndex (5);
 | |
|         pc.ledMsToBeOffComboBox     .setSelectedItemIndex (5);
 | |
|         pc.vibratorMsToBeOnComboBox .setSelectedItemIndex (0);
 | |
|         pc.vibratorMsToBeOffComboBox.setSelectedItemIndex (0);
 | |
|         pc.timeoutAfterComboBox     .setSelectedItemIndex (0);
 | |
| 
 | |
|         pc.timestampVisibilityComboBox.addItem ("off",         1);
 | |
|         pc.timestampVisibilityComboBox.addItem ("on",          2);
 | |
|         pc.timestampVisibilityComboBox.addItem ("chronometer", 3);
 | |
|         pc.timestampVisibilityComboBox.addItem ("count down",  4);
 | |
|         pc.timestampVisibilityComboBox.setSelectedItemIndex (1);
 | |
|     }
 | |
| 
 | |
|     void distributeControls()
 | |
|     {
 | |
|         auto& pc = paramControls;
 | |
| 
 | |
|         paramsOneView  .addRowComponent (new RowComponent (pc.identifierLabel,            pc.identifierEditor));
 | |
|         paramsOneView  .addRowComponent (new RowComponent (pc.titleLabel,                 pc.titleEditor));
 | |
|         paramsOneView  .addRowComponent (new RowComponent (pc.bodyLabel,                  pc.bodyEditor, 4));
 | |
|       #if JUCE_IOS
 | |
|         paramsOneView  .addRowComponent (new RowComponent (pc.categoryLabel,              pc.categoryComboBox));
 | |
|       #elif JUCE_ANDROID
 | |
|         paramsOneView  .addRowComponent (new RowComponent (pc.channelIdLabel,             pc.channelIdComboBox));
 | |
|       #endif
 | |
|       #if JUCE_ANDROID || JUCE_MAC
 | |
|         paramsOneView  .addRowComponent (new RowComponent (pc.iconLabel,                  pc.iconComboBox));
 | |
|       #endif
 | |
| 
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.subtitleLabel,              pc.subtitleEditor));
 | |
|       #if ! JUCE_MAC
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.badgeNumberLabel,           pc.badgeNumberComboBox));
 | |
|       #endif
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.soundToPlayLabel,           pc.soundToPlayComboBox));
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.propertiesLabel,            pc.propertiesEditor, 3));
 | |
|       #if JUCE_IOS || JUCE_MAC
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.fireInLabel,                pc.fireInComboBox));
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.repeatLabel,                pc.repeatButton));
 | |
|       #elif JUCE_ANDROID
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.largeIconLabel,             pc.largeIconComboBox));
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.badgeIconLabel,             pc.badgeIconComboBox));
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.tickerTextLabel,            pc.tickerTextEditor));
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.autoCancelLabel,            pc.autoCancelButton));
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.alertOnlyOnceLabel,         pc.alertOnlyOnceButton));
 | |
|       #endif
 | |
|       #if JUCE_ANDROID || JUCE_MAC
 | |
|         paramsTwoView  .addRowComponent (new RowComponent (pc.actionsLabel,               pc.actionsComboBox));
 | |
|       #endif
 | |
|       #if JUCE_ANDROID
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.progressMaxLabel,           pc.progressMaxComboBox));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.progressCurrentLabel,       pc.progressCurrentComboBox));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.progressIndeterminateLabel, pc.progressIndeterminateButton));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.categoryLabel,              pc.categoryComboBox));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.priorityLabel,              pc.priorityComboBox));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.personLabel,                pc.personEditor));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.lockScreenVisibilityLabel,  pc.lockScreenVisibilityComboBox));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.groupIdLabel,               pc.groupIdEditor));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.sortKeyLabel,               pc.sortKeyEditor));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.groupSummaryLabel,          pc.groupSummaryButton));
 | |
|         paramsThreeView.addRowComponent (new RowComponent (pc.groupAlertBehaviourLabel,   pc.groupAlertBehaviourComboBox));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.accentColourLabel,          pc.accentColourButton));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.ledColourLabel,             pc.ledColourButton));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.ledMsToBeOffLabel,          pc.ledMsToBeOffComboBox));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.ledMsToBeOnLabel,           pc.ledMsToBeOnComboBox));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.vibratorMsToBeOffLabel,     pc.vibratorMsToBeOffComboBox));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.vibratorMsToBeOnLabel,      pc.vibratorMsToBeOnComboBox));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.localOnlyLabel,             pc.localOnlyButton));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.ongoingLabel,               pc.ongoingButton));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.timestampVisibilityLabel,   pc.timestampVisibilityComboBox));
 | |
|         paramsFourView .addRowComponent (new RowComponent (pc.timeoutAfterLabel,          pc.timeoutAfterComboBox));
 | |
|       #endif
 | |
|     }
 | |
| 
 | |
|     struct ParamsView   : public Component
 | |
|     {
 | |
|         ParamsView()
 | |
|         {
 | |
|             // For now, to be able to dismiss mobile keyboard.
 | |
|             setWantsKeyboardFocus (true);
 | |
|         }
 | |
| 
 | |
|         void addRowComponent (RowComponent* rc)
 | |
|         {
 | |
|             rowComponents.add (rc);
 | |
|             addAndMakeVisible (rc);
 | |
|         }
 | |
| 
 | |
|         void resized() override
 | |
|         {
 | |
|             auto totalRowUnits = 0;
 | |
| 
 | |
|             for (auto* rc : rowComponents)
 | |
|                 totalRowUnits += rc->rowUnits;
 | |
| 
 | |
|             auto rowHeight = getHeight() / totalRowUnits;
 | |
| 
 | |
|             auto bounds = getLocalBounds();
 | |
| 
 | |
|             for (auto* rc : rowComponents)
 | |
|                 rc->setBounds (bounds.removeFromTop (rc->rowUnits * rowHeight));
 | |
| 
 | |
|             auto* last = rowComponents[rowComponents.size() - 1];
 | |
|             last->setBounds (last->getBounds().withHeight (getHeight() - last->getY()));
 | |
|         }
 | |
| 
 | |
|     private:
 | |
|         OwnedArray<RowComponent> rowComponents;
 | |
|     };
 | |
| 
 | |
|     struct AuxActionsView   : public Component
 | |
|     {
 | |
|         AuxActionsView()
 | |
|         {
 | |
|             addAndMakeVisible (getDeliveredNotificationsButton);
 | |
|             addAndMakeVisible (removeDeliveredNotifWithIdButton);
 | |
|             addAndMakeVisible (deliveredNotifIdentifier);
 | |
|             addAndMakeVisible (removeAllDeliveredNotifsButton);
 | |
|           #if JUCE_IOS || JUCE_MAC
 | |
|             addAndMakeVisible (getPendingNotificationsButton);
 | |
|             addAndMakeVisible (removePendingNotifWithIdButton);
 | |
|             addAndMakeVisible (pendingNotifIdentifier);
 | |
|             addAndMakeVisible (removeAllPendingNotifsButton);
 | |
|           #endif
 | |
| 
 | |
|             // For now, to be able to dismiss mobile keyboard.
 | |
|             setWantsKeyboardFocus (true);
 | |
|         }
 | |
| 
 | |
|         void resized() override
 | |
|         {
 | |
|             auto columnWidth = getWidth();
 | |
|             auto rowHeight = getHeight() / 6;
 | |
|             auto bounds = getLocalBounds();
 | |
| 
 | |
|             getDeliveredNotificationsButton .setBounds (bounds.removeFromTop (rowHeight));
 | |
| 
 | |
|             auto rowBounds = bounds.removeFromTop (rowHeight);
 | |
|             removeDeliveredNotifWithIdButton.setBounds (rowBounds.removeFromLeft (columnWidth / 2));
 | |
|             deliveredNotifIdentifier        .setBounds (rowBounds);
 | |
| 
 | |
|             removeAllDeliveredNotifsButton  .setBounds (bounds.removeFromTop (rowHeight));
 | |
| 
 | |
|            #if JUCE_IOS || JUCE_MAC
 | |
|             getPendingNotificationsButton .setBounds (bounds.removeFromTop (rowHeight));
 | |
| 
 | |
|             rowBounds = bounds.removeFromTop (rowHeight);
 | |
|             removePendingNotifWithIdButton.setBounds (rowBounds.removeFromLeft (columnWidth / 2));
 | |
|             pendingNotifIdentifier        .setBounds (rowBounds);
 | |
| 
 | |
|             removeAllPendingNotifsButton  .setBounds (bounds.removeFromTop (rowHeight));
 | |
|            #endif
 | |
|         }
 | |
| 
 | |
|         TextButton getDeliveredNotificationsButton  { "Get Delivered Notifications" };
 | |
|         TextButton removeDeliveredNotifWithIdButton { "Remove Delivered Notif With ID:" };
 | |
|         TextEditor deliveredNotifIdentifier;
 | |
|         TextButton removeAllDeliveredNotifsButton   { "Remove All Delivered Notifs" };
 | |
|         TextButton getPendingNotificationsButton    { "Get Pending Notifications" };
 | |
|         TextButton removePendingNotifWithIdButton   { "Remove Pending Notif With ID:" };
 | |
|         TextEditor pendingNotifIdentifier;
 | |
|         TextButton removeAllPendingNotifsButton     { "Remove All Pending Notifs" };
 | |
|     };
 | |
| 
 | |
|     struct RemoteView   : public Component
 | |
|     {
 | |
|         RemoteView()
 | |
|         {
 | |
|             addAndMakeVisible (getDeviceTokenButton);
 | |
|            #if JUCE_ANDROID
 | |
|             addAndMakeVisible (sendRemoteMessageButton);
 | |
|             addAndMakeVisible (subscribeToSportsButton);
 | |
|             addAndMakeVisible (unsubscribeFromSportsButton);
 | |
|            #endif
 | |
|         }
 | |
| 
 | |
|         void resized()
 | |
|         {
 | |
|             auto rowSize = getHeight () / 10;
 | |
| 
 | |
|             auto bounds = getLocalBounds().reduced (getWidth() / 10, getHeight() / 10);
 | |
| 
 | |
|             bounds.removeFromTop (2 * rowSize);
 | |
| 
 | |
|             getDeviceTokenButton       .setBounds (bounds.removeFromTop (rowSize));
 | |
|             sendRemoteMessageButton    .setBounds (bounds.removeFromTop (rowSize));
 | |
|             subscribeToSportsButton    .setBounds (bounds.removeFromTop (rowSize));
 | |
|             unsubscribeFromSportsButton.setBounds (bounds.removeFromTop (rowSize));
 | |
|         }
 | |
| 
 | |
|         TextButton getDeviceTokenButton        { "GetDeviceToken" };
 | |
|         TextButton sendRemoteMessageButton     { "SendRemoteMessage" };
 | |
|         TextButton subscribeToSportsButton     { "SubscribeToSports" };
 | |
|         TextButton unsubscribeFromSportsButton { "UnsubscribeFromSports" };
 | |
|     };
 | |
| 
 | |
|     struct DemoTabbedComponent  : public TabbedComponent
 | |
|     {
 | |
|         explicit DemoTabbedComponent (TabbedButtonBar::Orientation orientation)
 | |
|             : TabbedComponent (orientation)
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         void currentTabChanged (int, const String& newCurrentTabName) override
 | |
|         {
 | |
|             if (! showedRemoteInstructions && newCurrentTabName == "Remote")
 | |
|             {
 | |
|                 PushNotificationsDemo::showRemoteInstructions();
 | |
|                 showedRemoteInstructions = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|     private:
 | |
|         bool showedRemoteInstructions = false;
 | |
|     };
 | |
| 
 | |
|     static void showRemoteInstructions()
 | |
|     {
 | |
|        #if JUCE_IOS || JUCE_MAC
 | |
|         NativeMessageBox::showAsync (MessageBoxOptions()
 | |
|                                        .withIconType (MessageBoxIconType::InfoIcon)
 | |
|                                        .withTitle ("Remote Notifications instructions")
 | |
|                                        .withMessage ("In order to be able to test remote notifications "
 | |
|                                                      "ensure that the app is signed and that you register "
 | |
|                                                      "the bundle ID for remote notifications in "
 | |
|                                                      "Apple Developer Center."),
 | |
|                                      nullptr);
 | |
|        #endif
 | |
|     }
 | |
| 
 | |
|     Label headerLabel { "headerLabel", "Push Notifications Demo" };
 | |
|     ParamControls paramControls;
 | |
|     ParamsView paramsOneView, paramsTwoView, paramsThreeView, paramsFourView;
 | |
|     AuxActionsView auxActionsView;
 | |
|     TabbedComponent localNotificationsTabs { TabbedButtonBar::TabsAtTop };
 | |
|     RemoteView remoteView;
 | |
|     DemoTabbedComponent mainTabs { TabbedButtonBar::TabsAtTop };
 | |
|     TextButton sendButton      { "Send!" };
 | |
|     Label notAvailableYetLabel { "notAvailableYetLabel",
 | |
|                                  "Push Notifications feature is not available on this platform yet!" };
 | |
| 
 | |
|     //==============================================================================
 | |
|     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PushNotificationsDemo)
 | |
| };
 |