The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1120 lines
52KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE examples.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. The code included in this file is provided under the terms of the ISC license
  6. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  7. To use, copy, modify, and/or distribute this software for any purpose with or
  8. without fee is hereby granted provided that the above copyright notice and
  9. this permission notice appear in all copies.
  10. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
  11. WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
  12. PURPOSE, ARE DISCLAIMED.
  13. ==============================================================================
  14. */
  15. /*******************************************************************************
  16. The block below describes the properties of this PIP. A PIP is a short snippet
  17. of code that can be read by the Projucer and used to generate a JUCE project.
  18. BEGIN_JUCE_PIP_METADATA
  19. name: PushNotificationsDemo
  20. version: 2.0.0
  21. vendor: JUCE
  22. website: http://juce.com
  23. description: Showcases push notifications features. To run this demo you must enable the
  24. "Push Notifications Capability" option in the Projucer exporter.
  25. dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats,
  26. juce_audio_processors, juce_audio_utils, juce_core,
  27. juce_data_structures, juce_events, juce_graphics,
  28. juce_gui_basics, juce_gui_extra
  29. exporters: xcode_mac, vs2017, xcode_iphone, androidstudio
  30. type: Component
  31. mainClass: PushNotificationsDemo
  32. useLocalCopy: 1
  33. END_JUCE_PIP_METADATA
  34. *******************************************************************************/
  35. #pragma once
  36. #include "../Assets/DemoUtilities.h"
  37. //==============================================================================
  38. class PushNotificationsDemo : public Component,
  39. private ChangeListener,
  40. private ComponentListener,
  41. private PushNotifications::Listener
  42. {
  43. public:
  44. //==============================================================================
  45. PushNotificationsDemo()
  46. {
  47. setupControls();
  48. distributeControls();
  49. #if JUCE_PUSH_NOTIFICATIONS
  50. addAndMakeVisible (headerLabel);
  51. addAndMakeVisible (mainTabs);
  52. addAndMakeVisible (sendButton);
  53. #else
  54. addAndMakeVisible (notAvailableYetLabel);
  55. #endif
  56. headerLabel .setJustificationType (Justification::centred);
  57. notAvailableYetLabel.setJustificationType (Justification::centred);
  58. #if JUCE_MAC
  59. StringArray tabNames { "Params1", "Params2", "Params3", "Params4" };
  60. #else
  61. StringArray tabNames { "Req. params", "Opt. params1", "Opt. params2", "Opt. params3" };
  62. #endif
  63. auto colour = getLookAndFeel().findColour (ResizableWindow::backgroundColourId);
  64. localNotificationsTabs.addTab (tabNames[0], colour, &paramsOneView, false);
  65. localNotificationsTabs.addTab (tabNames[1], colour, &paramsTwoView, false);
  66. #if JUCE_ANDROID
  67. localNotificationsTabs.addTab (tabNames[2], colour, &paramsThreeView, false);
  68. localNotificationsTabs.addTab (tabNames[3], colour, &paramsFourView, false);
  69. #endif
  70. localNotificationsTabs.addTab ("Aux. actions", colour, &auxActionsView, false);
  71. mainTabs.addTab ("Local", colour, &localNotificationsTabs, false);
  72. mainTabs.addTab ("Remote", colour, &remoteView, false);
  73. auto userArea = Desktop::getInstance().getDisplays().getMainDisplay().userArea;
  74. #if JUCE_ANDROID || JUCE_IOS
  75. setSize (userArea.getWidth(), userArea.getHeight());
  76. #else
  77. setSize (userArea.getWidth() / 2, userArea.getHeight() / 2);
  78. #endif
  79. sendButton.onClick = [this] { sendLocalNotification(); };
  80. auxActionsView.getDeliveredNotificationsButton .onClick = [this]
  81. { PushNotifications::getInstance()->getDeliveredNotifications(); };
  82. auxActionsView.removeDeliveredNotifWithIdButton.onClick = [this]
  83. { PushNotifications::getInstance()->removeDeliveredNotification (auxActionsView.deliveredNotifIdentifier.getText()); };
  84. auxActionsView.removeAllDeliveredNotifsButton .onClick = [this]
  85. { PushNotifications::getInstance()->removeAllDeliveredNotifications(); };
  86. #if JUCE_IOS || JUCE_MAC
  87. auxActionsView.getPendingNotificationsButton .onClick = [this]
  88. { PushNotifications::getInstance()->getPendingLocalNotifications(); };
  89. auxActionsView.removePendingNotifWithIdButton.onClick = [this]
  90. { PushNotifications::getInstance()->removePendingLocalNotification (auxActionsView.pendingNotifIdentifier.getText()); };
  91. auxActionsView.removeAllPendingNotifsButton .onClick = [this]
  92. { PushNotifications::getInstance()->removeAllPendingLocalNotifications(); };
  93. #endif
  94. remoteView.getDeviceTokenButton.onClick = [this]
  95. {
  96. String token = PushNotifications::getInstance()->getDeviceToken();
  97. DBG ("token = " + token);
  98. if (token.isEmpty())
  99. showRemoteInstructions();
  100. else
  101. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, "Device token", token);
  102. };
  103. #if JUCE_ANDROID
  104. remoteView.sendRemoteMessageButton.onClick = [this]
  105. {
  106. StringPairArray data;
  107. data.set ("key1", "value1");
  108. data.set ("key2", "value2");
  109. static int id = 100;
  110. PushNotifications::getInstance()->sendUpstreamMessage ("872047750958",
  111. "com.juce.pushnotificationsdemo",
  112. String (id++),
  113. "standardType",
  114. 3600,
  115. data);
  116. };
  117. remoteView.subscribeToSportsButton .onClick = [this]
  118. { PushNotifications::getInstance()->subscribeToTopic ("sports"); };
  119. remoteView.unsubscribeFromSportsButton.onClick = [this]
  120. { PushNotifications::getInstance()->unsubscribeFromTopic ("sports"); };
  121. #endif
  122. paramControls.accentColourButton.onClick = [this] { setupAccentColour(); };
  123. paramControls.ledColourButton .onClick = [this] { setupLedColour(); };
  124. jassert (PushNotifications::getInstance()->areNotificationsEnabled());
  125. PushNotifications::getInstance()->addListener (this);
  126. #if JUCE_IOS || JUCE_MAC
  127. paramControls.fireInComboBox.onChange = [this] { delayNotification(); };
  128. PushNotifications::getInstance()->requestPermissionsWithSettings (getNotificationSettings());
  129. #elif JUCE_ANDROID
  130. PushNotifications::ChannelGroup cg { "demoGroup", "demo group" };
  131. PushNotifications::getInstance()->setupChannels ({ { cg } }, getAndroidChannels());
  132. #endif
  133. }
  134. ~PushNotificationsDemo()
  135. {
  136. PushNotifications::getInstance()->removeListener (this);
  137. }
  138. void paint (Graphics& g) override
  139. {
  140. g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
  141. }
  142. void resized() override
  143. {
  144. auto bounds = getLocalBounds().reduced (getWidth() / 20, getHeight() / 40);
  145. headerLabel.setBounds (bounds.removeFromTop (bounds.proportionOfHeight (0.1f)));
  146. mainTabs .setBounds (bounds.removeFromTop (bounds.proportionOfHeight (0.8f)));
  147. sendButton .setBounds (bounds);
  148. notAvailableYetLabel.setBounds (getLocalBounds());
  149. }
  150. private:
  151. void delayNotification()
  152. {
  153. auto repeatsAllowed = paramControls.fireInComboBox.getSelectedItemIndex() >= 6;
  154. paramControls.repeatButton.setEnabled (repeatsAllowed);
  155. if (! repeatsAllowed)
  156. paramControls.repeatButton.setToggleState (false, NotificationType::sendNotification);
  157. }
  158. void sendLocalNotification()
  159. {
  160. PushNotifications::Notification n;
  161. fillRequiredParams (n);
  162. fillOptionalParamsOne (n);
  163. #if JUCE_ANDROID
  164. fillOptionalParamsTwo (n);
  165. fillOptionalParamsThree (n);
  166. #endif
  167. if (! n.isValid())
  168. {
  169. #if JUCE_IOS
  170. String requiredFields = "identifier (from iOS 10), title, body and category";
  171. #elif JUCE_ANDROID
  172. String requiredFields = "channel ID (from Android O), title, body and icon";
  173. #else
  174. String requiredFields = "all required fields";
  175. #endif
  176. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  177. "Incorrect notifications setup",
  178. "Please make sure that "
  179. + requiredFields + " are set.");
  180. return;
  181. }
  182. PushNotifications::getInstance()->sendLocalNotification (n);
  183. }
  184. void fillRequiredParams (PushNotifications::Notification& n)
  185. {
  186. n.identifier = paramControls.identifierEditor.getText();
  187. n.title = paramControls.titleEditor .getText();
  188. n.body = paramControls.bodyEditor .getText();
  189. #if JUCE_IOS
  190. n.category = paramControls.categoryComboBox.getText();
  191. #elif JUCE_ANDROID || JUCE_MAC
  192. #if JUCE_MAC
  193. String prefix = "Notifications/images/";
  194. String extension = ".png";
  195. #else
  196. String prefix;
  197. String extension;
  198. #endif
  199. if (paramControls.iconComboBox.getSelectedItemIndex() == 0)
  200. n.icon = prefix + "ic_stat_name" + extension;
  201. else if (paramControls.iconComboBox.getSelectedItemIndex() == 1)
  202. n.icon = prefix + "ic_stat_name2" + extension;
  203. else if (paramControls.iconComboBox.getSelectedItemIndex() == 2)
  204. n.icon = prefix + "ic_stat_name3" + extension;
  205. else if (paramControls.iconComboBox.getSelectedItemIndex() == 3)
  206. n.icon = prefix + "ic_stat_name4" + extension;
  207. else if (paramControls.iconComboBox.getSelectedItemIndex() == 4)
  208. n.icon = prefix + "ic_stat_name5" + extension;
  209. #endif
  210. #if JUCE_ANDROID
  211. // Note: this is not strictly speaking required param, just doing it here because it is the fastest way!
  212. n.publicVersion = new PushNotifications::Notification();
  213. n.publicVersion->identifier = "blahblahblah";
  214. n.publicVersion->title = "Public title!";
  215. n.publicVersion->body = "Public body!";
  216. n.publicVersion->icon = n.icon;
  217. n.channelId = String (paramControls.channelIdComboBox.getSelectedItemIndex() + 1);
  218. #endif
  219. }
  220. void fillOptionalParamsOne (PushNotifications::Notification& n)
  221. {
  222. n.subtitle = paramControls.subtitleEditor.getText();
  223. n.badgeNumber = paramControls.badgeNumberComboBox.getSelectedItemIndex();
  224. if (paramControls.soundToPlayComboBox.getSelectedItemIndex() > 0)
  225. n.soundToPlay = URL (paramControls.soundToPlayComboBox.getItemText (paramControls.soundToPlayComboBox.getSelectedItemIndex()));
  226. n.properties = JSON::parse (paramControls.propertiesEditor.getText());
  227. #if JUCE_IOS || JUCE_MAC
  228. n.triggerIntervalSec = double (paramControls.fireInComboBox.getSelectedItemIndex() * 10);
  229. n.repeat = paramControls.repeatButton.getToggleState();
  230. #elif JUCE_ANDROID
  231. if (paramControls.largeIconComboBox.getSelectedItemIndex() == 1)
  232. n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name6.png");
  233. else if (paramControls.largeIconComboBox.getSelectedItemIndex() == 2)
  234. n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name7.png");
  235. else if (paramControls.largeIconComboBox.getSelectedItemIndex() == 3)
  236. n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name8.png");
  237. else if (paramControls.largeIconComboBox.getSelectedItemIndex() == 4)
  238. n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name9.png");
  239. else if (paramControls.largeIconComboBox.getSelectedItemIndex() == 5)
  240. n.largeIcon = getImageFromAssets ("Notifications/images/ic_stat_name10.png");
  241. n.badgeIconType = (PushNotifications::Notification::BadgeIconType) paramControls.badgeIconComboBox.getSelectedItemIndex();
  242. n.tickerText = paramControls.tickerTextEditor.getText();
  243. n.shouldAutoCancel = paramControls.autoCancelButton .getToggleState();
  244. n.alertOnlyOnce = paramControls.alertOnlyOnceButton.getToggleState();
  245. #endif
  246. #if JUCE_ANDROID || JUCE_MAC
  247. if (paramControls.actionsComboBox.getSelectedItemIndex() == 1)
  248. {
  249. PushNotifications::Notification::Action a, a2;
  250. a .style = PushNotifications::Notification::Action::button;
  251. a2.style = PushNotifications::Notification::Action::button;
  252. a .title = a .identifier = "Ok";
  253. a2.title = a2.identifier = "Cancel";
  254. n.actions.add (a);
  255. n.actions.add (a2);
  256. }
  257. else if (paramControls.actionsComboBox.getSelectedItemIndex() == 2)
  258. {
  259. PushNotifications::Notification::Action a, a2;
  260. a .title = a .identifier = "Input Text Here";
  261. a2.title = a2.identifier = "No";
  262. a .style = PushNotifications::Notification::Action::text;
  263. a2.style = PushNotifications::Notification::Action::button;
  264. a .icon = "ic_stat_name4";
  265. a2.icon = "ic_stat_name5";
  266. a.textInputPlaceholder = "placeholder text ...";
  267. n.actions.add (a);
  268. n.actions.add (a2);
  269. }
  270. else if (paramControls.actionsComboBox.getSelectedItemIndex() == 3)
  271. {
  272. PushNotifications::Notification::Action a, a2;
  273. a .title = a .identifier = "Ok";
  274. a2.title = a2.identifier = "Cancel";
  275. a .style = PushNotifications::Notification::Action::button;
  276. a2.style = PushNotifications::Notification::Action::button;
  277. a .icon = "ic_stat_name4";
  278. a2.icon = "ic_stat_name5";
  279. n.actions.add (a);
  280. n.actions.add (a2);
  281. }
  282. else if (paramControls.actionsComboBox.getSelectedItemIndex() == 4)
  283. {
  284. PushNotifications::Notification::Action a, a2;
  285. a .title = a .identifier = "Input Text Here";
  286. a2.title = a2.identifier = "No";
  287. a .style = PushNotifications::Notification::Action::text;
  288. a2.style = PushNotifications::Notification::Action::button;
  289. a .icon = "ic_stat_name4";
  290. a2.icon = "ic_stat_name5";
  291. a.textInputPlaceholder = "placeholder text ...";
  292. a.allowedResponses.add ("Response 1");
  293. a.allowedResponses.add ("Response 2");
  294. a.allowedResponses.add ("Response 3");
  295. n.actions.add (a);
  296. n.actions.add (a2);
  297. }
  298. #endif
  299. }
  300. void fillOptionalParamsTwo (PushNotifications::Notification& n)
  301. {
  302. using Notification = PushNotifications::Notification;
  303. Notification::Progress progress;
  304. progress.max = paramControls.progressMaxComboBox .getSelectedItemIndex() * 10;
  305. progress.current = paramControls.progressCurrentComboBox.getSelectedItemIndex() * 10;
  306. progress.indeterminate = paramControls.progressIndeterminateButton.getToggleState();
  307. n.progress = progress;
  308. n.person = paramControls.personEditor.getText();
  309. n.type = Notification::Type (paramControls.categoryComboBox .getSelectedItemIndex());
  310. n.priority = Notification::Priority (paramControls.priorityComboBox .getSelectedItemIndex() - 2);
  311. n.lockScreenAppearance = Notification::LockScreenAppearance (paramControls.lockScreenVisibilityComboBox.getSelectedItemIndex() - 1);
  312. n.groupId = paramControls.groupIdEditor.getText();
  313. n.groupSortKey = paramControls.sortKeyEditor.getText();
  314. n.groupSummary = paramControls.groupSummaryButton.getToggleState();
  315. n.groupAlertBehaviour = Notification::GroupAlertBehaviour (paramControls.groupAlertBehaviourComboBox.getSelectedItemIndex());
  316. }
  317. void fillOptionalParamsThree (PushNotifications::Notification& n)
  318. {
  319. n.accentColour = paramControls.accentColourButton.findColour (TextButton::buttonColourId, false);
  320. n.ledColour = paramControls.ledColourButton .findColour (TextButton::buttonColourId, false);
  321. using Notification = PushNotifications::Notification;
  322. Notification::LedBlinkPattern ledBlinkPattern;
  323. ledBlinkPattern.msToBeOn = paramControls.ledMsToBeOnComboBox .getSelectedItemIndex() * 200;
  324. ledBlinkPattern.msToBeOff = paramControls.ledMsToBeOffComboBox.getSelectedItemIndex() * 200;
  325. n.ledBlinkPattern = ledBlinkPattern;
  326. Array<int> vibrationPattern;
  327. if (paramControls.vibratorMsToBeOnComboBox .getSelectedItemIndex() > 0 &&
  328. paramControls.vibratorMsToBeOffComboBox.getSelectedItemIndex() > 0)
  329. {
  330. vibrationPattern.add (paramControls.vibratorMsToBeOffComboBox.getSelectedItemIndex() * 500);
  331. vibrationPattern.add (paramControls.vibratorMsToBeOnComboBox .getSelectedItemIndex() * 500);
  332. vibrationPattern.add (2 * paramControls.vibratorMsToBeOffComboBox.getSelectedItemIndex() * 500);
  333. vibrationPattern.add (2 * paramControls.vibratorMsToBeOnComboBox .getSelectedItemIndex() * 500);
  334. }
  335. n.vibrationPattern = vibrationPattern;
  336. n.localOnly = paramControls.localOnlyButton.getToggleState();
  337. n.ongoing = paramControls.ongoingButton.getToggleState();
  338. n.timestampVisibility = Notification::TimestampVisibility (paramControls.timestampVisibilityComboBox.getSelectedItemIndex());
  339. if (paramControls.timeoutAfterComboBox.getSelectedItemIndex() > 0)
  340. {
  341. auto index = paramControls.timeoutAfterComboBox.getSelectedItemIndex();
  342. n.timeoutAfterMs = index * 1000 + 4000;
  343. }
  344. }
  345. void setupAccentColour()
  346. {
  347. paramControls.accentColourSelector = new ColourSelector();
  348. paramControls.accentColourSelector->setName ("accent colour");
  349. paramControls.accentColourSelector->setCurrentColour (paramControls.accentColourButton.findColour (TextButton::buttonColourId));
  350. paramControls.accentColourSelector->setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);
  351. paramControls.accentColourSelector->setSize (200, 200);
  352. paramControls.accentColourSelector->addComponentListener (this);
  353. paramControls.accentColourSelector->addChangeListener (this);
  354. CallOutBox::launchAsynchronously (paramControls.accentColourSelector, paramControls.accentColourButton.getScreenBounds(), nullptr);
  355. }
  356. void setupLedColour()
  357. {
  358. paramControls.ledColourSelector = new ColourSelector();
  359. paramControls.ledColourSelector->setName ("led colour");
  360. paramControls.ledColourSelector->setCurrentColour (paramControls.ledColourButton.findColour (TextButton::buttonColourId));
  361. paramControls.ledColourSelector->setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);
  362. paramControls.ledColourSelector->setSize (200, 200);
  363. paramControls.ledColourSelector->addComponentListener (this);
  364. paramControls.ledColourSelector->addChangeListener (this);
  365. CallOutBox::launchAsynchronously (paramControls.ledColourSelector, paramControls.accentColourButton.getScreenBounds(), nullptr);
  366. }
  367. void changeListenerCallback (ChangeBroadcaster* source) override
  368. {
  369. if (source == paramControls.accentColourSelector)
  370. {
  371. auto c = paramControls.accentColourSelector->getCurrentColour();
  372. paramControls.accentColourButton.setColour (TextButton::buttonColourId, c);
  373. }
  374. else if (source == paramControls.ledColourSelector)
  375. {
  376. auto c = paramControls.ledColourSelector->getCurrentColour();
  377. paramControls.ledColourButton.setColour (TextButton::buttonColourId, c);
  378. }
  379. }
  380. void componentBeingDeleted (Component& component) override
  381. {
  382. if (&component == paramControls.accentColourSelector)
  383. paramControls.accentColourSelector = nullptr;
  384. else if (&component == paramControls.ledColourSelector)
  385. paramControls.ledColourSelector = nullptr;
  386. }
  387. void handleNotification (bool isLocalNotification, const PushNotifications::Notification& n) override
  388. {
  389. ignoreUnused (isLocalNotification);
  390. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  391. "Received notification",
  392. "ID: " + n.identifier
  393. + ", title: " + n.title
  394. + ", body: " + n.body);
  395. }
  396. void handleNotificationAction (bool isLocalNotification,
  397. const PushNotifications::Notification& n,
  398. const juce::String& actionIdentifier,
  399. const juce::String& optionalResponse) override
  400. {
  401. ignoreUnused (isLocalNotification);
  402. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  403. "Received notification action",
  404. "ID: " + n.identifier
  405. + ", title: " + n.title
  406. + ", body: " + n.body
  407. + ", action: " + actionIdentifier
  408. + ", optionalResponse: " + optionalResponse);
  409. PushNotifications::getInstance()->removeDeliveredNotification (n.identifier);
  410. }
  411. void localNotificationDismissedByUser (const PushNotifications::Notification& n) override
  412. {
  413. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  414. "Notification dismissed by a user",
  415. "ID: " + n.identifier
  416. + ", title: " + n.title
  417. + ", body: " + n.body);
  418. }
  419. void deliveredNotificationsListReceived (const Array<PushNotifications::Notification>& notifs) override
  420. {
  421. String text = "Received notifications: ";
  422. for (auto& n : notifs)
  423. text << "(" << n.identifier << ", " << n.title << ", " << n.body << "), ";
  424. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, "Received notification list", text);
  425. }
  426. void pendingLocalNotificationsListReceived (const Array<PushNotifications::Notification>& notifs) override
  427. {
  428. String text = "Pending notifications: ";
  429. for (auto& n : notifs)
  430. text << "(" << n.identifier << ", " << n.title << ", " << n.body << "), ";
  431. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon, "Pending notification list", text);
  432. }
  433. void deviceTokenRefreshed (const String& token) override
  434. {
  435. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  436. "Device token refreshed",
  437. token);
  438. }
  439. #if JUCE_ANDROID
  440. void remoteNotificationsDeleted() override
  441. {
  442. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  443. "Remote notifications deleted",
  444. "Some of the pending messages were removed!");
  445. }
  446. void upstreamMessageSent (const String& messageId) override
  447. {
  448. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  449. "Upstream message sent",
  450. "Message id: " + messageId);
  451. }
  452. void upstreamMessageSendingError (const String& messageId, const String& error) override
  453. {
  454. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  455. "Upstream message sending error",
  456. "Message id: " + messageId
  457. + "\nerror: " + error);
  458. }
  459. static Array<PushNotifications::Channel> getAndroidChannels()
  460. {
  461. using Channel = PushNotifications::Channel;
  462. Channel ch1, ch2, ch3;
  463. ch1.identifier = "1";
  464. ch1.name = "HighImportance";
  465. ch1.importance = PushNotifications::Channel::max;
  466. ch1.lockScreenAppearance = PushNotifications::Notification::showCompletely;
  467. ch1.description = "High Priority Channel for important stuff";
  468. ch1.groupId = "demoGroup";
  469. ch1.ledColour = Colours::red;
  470. ch1.bypassDoNotDisturb = true;
  471. ch1.canShowBadge = true;
  472. ch1.enableLights = true;
  473. ch1.enableVibration = true;
  474. ch1.soundToPlay = URL ("demonstrative");
  475. ch1.vibrationPattern = { 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 };
  476. ch2.identifier = "2";
  477. ch2.name = "MediumImportance";
  478. ch2.importance = PushNotifications::Channel::normal;
  479. ch2.lockScreenAppearance = PushNotifications::Notification::showPartially;
  480. ch2.description = "Medium Priority Channel for standard stuff";
  481. ch2.groupId = "demoGroup";
  482. ch2.ledColour = Colours::yellow;
  483. ch2.canShowBadge = true;
  484. ch2.enableLights = true;
  485. ch2.enableVibration = true;
  486. ch2.soundToPlay = URL ("default_os_sound");
  487. ch2.vibrationPattern = { 1000, 1000 };
  488. ch3.identifier = "3";
  489. ch3.name = "LowImportance";
  490. ch3.importance = PushNotifications::Channel::min;
  491. ch3.lockScreenAppearance = PushNotifications::Notification::dontShow;
  492. ch3.description = "Low Priority Channel for silly stuff";
  493. ch3.groupId = "demoGroup";
  494. return { ch1, ch2, ch3 };
  495. }
  496. #elif JUCE_IOS || JUCE_MAC
  497. static PushNotifications::Settings getNotificationSettings()
  498. {
  499. PushNotifications::Settings settings;
  500. settings.allowAlert = true;
  501. settings.allowBadge = true;
  502. settings.allowSound = true;
  503. #if JUCE_IOS
  504. using Action = PushNotifications::Settings::Action;
  505. using Category = PushNotifications::Settings::Category;
  506. Action okAction;
  507. okAction.identifier = "okAction";
  508. okAction.title = "OK!";
  509. okAction.style = Action::button;
  510. okAction.triggerInBackground = true;
  511. Action cancelAction;
  512. cancelAction.identifier = "cancelAction";
  513. cancelAction.title = "Cancel";
  514. cancelAction.style = Action::button;
  515. cancelAction.triggerInBackground = true;
  516. cancelAction.destructive = true;
  517. Action textAction;
  518. textAction.identifier = "textAction";
  519. textAction.title = "Enter text";
  520. textAction.style = Action::text;
  521. textAction.triggerInBackground = true;
  522. textAction.destructive = false;
  523. textAction.textInputButtonText = "Ok";
  524. textAction.textInputPlaceholder = "Enter text...";
  525. Category okCategory;
  526. okCategory.identifier = "okCategory";
  527. okCategory.actions = { okAction };
  528. Category okCancelCategory;
  529. okCancelCategory.identifier = "okCancelCategory";
  530. okCancelCategory.actions = { okAction, cancelAction };
  531. Category textCategory;
  532. textCategory.identifier = "textCategory";
  533. textCategory.actions = { textAction };
  534. textCategory.sendDismissAction = true;
  535. settings.categories = { okCategory, okCancelCategory, textCategory };
  536. #endif
  537. return settings;
  538. }
  539. #endif
  540. struct RowComponent : public Component
  541. {
  542. RowComponent (Label& l, Component& c, int u = 1)
  543. : label (l),
  544. editor (c),
  545. rowUnits (u)
  546. {
  547. addAndMakeVisible (label);
  548. addAndMakeVisible (editor);
  549. }
  550. void resized() override
  551. {
  552. auto bounds = getLocalBounds();
  553. label .setBounds (bounds.removeFromLeft (getWidth() / 3));
  554. editor.setBounds (bounds);
  555. }
  556. Label& label;
  557. Component& editor;
  558. int rowUnits;
  559. };
  560. struct ParamControls
  561. {
  562. Label identifierLabel { "identifierLabel", "Identifier" };
  563. TextEditor identifierEditor;
  564. Label titleLabel { "titleLabel", "Title" };
  565. TextEditor titleEditor;
  566. Label bodyLabel { "bodyLabel", "Body" };
  567. TextEditor bodyEditor;
  568. Label categoryLabel { "categoryLabel", "Category" };
  569. ComboBox categoryComboBox;
  570. Label channelIdLabel { "channelIdLabel", "Channel ID" };
  571. ComboBox channelIdComboBox;
  572. Label iconLabel { "iconLabel", "Icon" };
  573. ComboBox iconComboBox;
  574. Label subtitleLabel { "subtitleLabel", "Subtitle" };
  575. TextEditor subtitleEditor;
  576. Label badgeNumberLabel { "badgeNumberLabel", "BadgeNumber" };
  577. ComboBox badgeNumberComboBox;
  578. Label soundToPlayLabel { "soundToPlayLabel", "SoundToPlay" };
  579. ComboBox soundToPlayComboBox;
  580. Label propertiesLabel { "propertiesLabel", "Properties" };
  581. TextEditor propertiesEditor;
  582. Label fireInLabel { "fireInLabel", "Fire in" };
  583. ComboBox fireInComboBox;
  584. Label repeatLabel { "repeatLabel", "Repeat" };
  585. ToggleButton repeatButton;
  586. Label largeIconLabel { "largeIconLabel", "Large Icon" };
  587. ComboBox largeIconComboBox;
  588. Label badgeIconLabel { "badgeIconLabel", "Badge Icon" };
  589. ComboBox badgeIconComboBox;
  590. Label tickerTextLabel { "tickerTextLabel", "Ticker Text" };
  591. TextEditor tickerTextEditor;
  592. Label autoCancelLabel { "autoCancelLabel", "AutoCancel" };
  593. ToggleButton autoCancelButton;
  594. Label alertOnlyOnceLabel { "alertOnlyOnceLabel", "AlertOnlyOnce" };
  595. ToggleButton alertOnlyOnceButton;
  596. Label actionsLabel { "actionsLabel", "Actions" };
  597. ComboBox actionsComboBox;
  598. Label progressMaxLabel { "progressMaxLabel", "ProgressMax" };
  599. ComboBox progressMaxComboBox;
  600. Label progressCurrentLabel { "progressCurrentLabel", "ProgressCurrent" };
  601. ComboBox progressCurrentComboBox;
  602. Label progressIndeterminateLabel { "progressIndeterminateLabel", "ProgressIndeterminate" };
  603. ToggleButton progressIndeterminateButton;
  604. Label notifCategoryLabel { "notifCategoryLabel", "Category" };
  605. ComboBox notifCategoryComboBox;
  606. Label priorityLabel { "priorityLabel", "Priority" };
  607. ComboBox priorityComboBox;
  608. Label personLabel { "personLabel", "Person" };
  609. TextEditor personEditor;
  610. Label lockScreenVisibilityLabel { "lockScreenVisibilityLabel", "LockScreenVisibility" };
  611. ComboBox lockScreenVisibilityComboBox;
  612. Label groupIdLabel { "groupIdLabel", "GroupID" };
  613. TextEditor groupIdEditor;
  614. Label sortKeyLabel { "sortKeyLabel", "SortKey" };
  615. TextEditor sortKeyEditor;
  616. Label groupSummaryLabel { "groupSummaryLabel", "GroupSummary" };
  617. ToggleButton groupSummaryButton;
  618. Label groupAlertBehaviourLabel { "groupAlertBehaviourLabel", "GroupAlertBehaviour" };
  619. ComboBox groupAlertBehaviourComboBox;
  620. Label accentColourLabel { "accentColourLabel", "AccentColour" };
  621. TextButton accentColourButton;
  622. Label ledColourLabel { "ledColourLabel", "LedColour" };
  623. TextButton ledColourButton;
  624. Label ledMsToBeOnLabel { "ledMsToBeOnLabel", "LedMsToBeOn" };
  625. ComboBox ledMsToBeOnComboBox;
  626. Label ledMsToBeOffLabel { "ledMsToBeOffLabel", "LedMsToBeOff" };
  627. ComboBox ledMsToBeOffComboBox;
  628. Label vibratorMsToBeOnLabel { "vibratorMsToBeOnLabel", "VibrationMsToBeOn" };
  629. ComboBox vibratorMsToBeOnComboBox;
  630. Label vibratorMsToBeOffLabel { "vibratorMsToBeOffLabel", "VibrationMsToBeOff" };
  631. ComboBox vibratorMsToBeOffComboBox;
  632. Label localOnlyLabel { "localOnlyLabel", "LocalOnly" };
  633. ToggleButton localOnlyButton;
  634. Label ongoingLabel { "ongoingLabel", "Ongoing" };
  635. ToggleButton ongoingButton;
  636. Label timestampVisibilityLabel { "timestampVisibilityLabel", "TimestampMode" };
  637. ComboBox timestampVisibilityComboBox;
  638. Label timeoutAfterLabel { "timeoutAfterLabel", "Timeout After Ms" };
  639. ComboBox timeoutAfterComboBox;
  640. ColourSelector* accentColourSelector = nullptr;
  641. ColourSelector* ledColourSelector = nullptr;
  642. };
  643. void setupControls()
  644. {
  645. auto& pc = paramControls;
  646. StringArray categories { "okCategory", "okCancelCategory", "textCategory" };
  647. for (auto& c : categories)
  648. pc.categoryComboBox.addItem (c, pc.categoryComboBox.getNumItems() + 1);
  649. pc.categoryComboBox.setSelectedItemIndex (0);
  650. for (auto i = 1; i <= 3; ++i)
  651. pc.channelIdComboBox.addItem (String (i), i);
  652. pc.channelIdComboBox.setSelectedItemIndex (0);
  653. for (auto i = 0; i < 5; ++i)
  654. pc.iconComboBox.addItem ("icon" + String (i + 1), i + 1);
  655. pc.iconComboBox.setSelectedItemIndex (0);
  656. #if JUCE_MAC
  657. pc.iconComboBox.addItem ("none", 100);
  658. #endif
  659. pc.fireInComboBox.addItem ("Now", 1);
  660. for (auto i = 1; i < 11; ++i)
  661. pc.fireInComboBox.addItem (String (10 * i) + "seconds", i + 1);
  662. pc.fireInComboBox.setSelectedItemIndex (0);
  663. pc.largeIconComboBox.addItem ("none", 1);
  664. for (auto i = 1; i < 5; ++i)
  665. pc.largeIconComboBox.addItem ("icon" + String (i), i + 1);
  666. pc.largeIconComboBox.setSelectedItemIndex (0);
  667. pc.badgeIconComboBox.addItem ("none", 1);
  668. pc.badgeIconComboBox.addItem ("small", 2);
  669. pc.badgeIconComboBox.addItem ("large", 3);
  670. pc.badgeIconComboBox.setSelectedItemIndex (2);
  671. pc.actionsComboBox.addItem ("none", 1);
  672. pc.actionsComboBox.addItem ("ok-cancel", 2);
  673. pc.actionsComboBox.addItem ("text-input", 3);
  674. #if JUCE_ANDROID
  675. pc.actionsComboBox.addItem ("ok-cancel-icons", 4);
  676. pc.actionsComboBox.addItem ("text-input-limited_responses", 5);
  677. #endif
  678. pc.actionsComboBox.setSelectedItemIndex (0);
  679. for (auto i = 0; i < 7; ++i)
  680. pc.badgeNumberComboBox.addItem (String (i), i + 1);
  681. pc.badgeNumberComboBox.setSelectedItemIndex (0);
  682. #if JUCE_IOS
  683. String prefix = "Notifications/sounds/";
  684. String extension = ".caf";
  685. #else
  686. String prefix;
  687. String extension;
  688. #endif
  689. pc.soundToPlayComboBox.addItem ("none", 1);
  690. pc.soundToPlayComboBox.addItem ("default_os_sound", 2);
  691. pc.soundToPlayComboBox.addItem (prefix + "demonstrative" + extension, 3);
  692. pc.soundToPlayComboBox.addItem (prefix + "isntit" + extension, 4);
  693. pc.soundToPlayComboBox.addItem (prefix + "jinglebellssms" + extension, 5);
  694. pc.soundToPlayComboBox.addItem (prefix + "served" + extension, 6);
  695. pc.soundToPlayComboBox.addItem (prefix + "solemn" + extension, 7);
  696. pc.soundToPlayComboBox.setSelectedItemIndex (1);
  697. for (auto i = 0; i < 11; ++i)
  698. {
  699. pc.progressMaxComboBox .addItem (String (i * 10) + "%", i + 1);
  700. pc.progressCurrentComboBox.addItem (String (i * 10) + "%", i + 1);
  701. }
  702. pc.progressMaxComboBox .setSelectedItemIndex (0);
  703. pc.progressCurrentComboBox.setSelectedItemIndex (0);
  704. pc.notifCategoryComboBox.addItem ("unspecified", 1);
  705. pc.notifCategoryComboBox.addItem ("alarm", 2);
  706. pc.notifCategoryComboBox.addItem ("call", 3);
  707. pc.notifCategoryComboBox.addItem ("email", 4);
  708. pc.notifCategoryComboBox.addItem ("error", 5);
  709. pc.notifCategoryComboBox.addItem ("event", 6);
  710. pc.notifCategoryComboBox.addItem ("message", 7);
  711. pc.notifCategoryComboBox.addItem ("progress", 8);
  712. pc.notifCategoryComboBox.addItem ("promo", 9);
  713. pc.notifCategoryComboBox.addItem ("recommendation", 10);
  714. pc.notifCategoryComboBox.addItem ("reminder", 11);
  715. pc.notifCategoryComboBox.addItem ("service", 12);
  716. pc.notifCategoryComboBox.addItem ("social", 13);
  717. pc.notifCategoryComboBox.addItem ("status", 14);
  718. pc.notifCategoryComboBox.addItem ("system", 15);
  719. pc.notifCategoryComboBox.addItem ("transport", 16);
  720. pc.notifCategoryComboBox.setSelectedItemIndex (0);
  721. for (auto i = -2; i < 3; ++i)
  722. pc.priorityComboBox.addItem (String (i), i + 3);
  723. pc.priorityComboBox.setSelectedItemIndex (2);
  724. pc.lockScreenVisibilityComboBox.addItem ("don't show", 1);
  725. pc.lockScreenVisibilityComboBox.addItem ("show partially", 2);
  726. pc.lockScreenVisibilityComboBox.addItem ("show completely", 3);
  727. pc.lockScreenVisibilityComboBox.setSelectedItemIndex (1);
  728. pc.groupAlertBehaviourComboBox.addItem ("alert all", 1);
  729. pc.groupAlertBehaviourComboBox.addItem ("alert summary", 2);
  730. pc.groupAlertBehaviourComboBox.addItem ("alert children", 3);
  731. pc.groupAlertBehaviourComboBox.setSelectedItemIndex (0);
  732. pc.timeoutAfterComboBox.addItem ("No timeout", 1);
  733. for (auto i = 0; i < 10; ++i)
  734. {
  735. pc.ledMsToBeOnComboBox .addItem (String (i * 200) + "ms", i + 1);
  736. pc.ledMsToBeOffComboBox .addItem (String (i * 200) + "ms", i + 1);
  737. pc.vibratorMsToBeOnComboBox .addItem (String (i * 500) + "ms", i + 1);
  738. pc.vibratorMsToBeOffComboBox.addItem (String (i * 500) + "ms", i + 1);
  739. pc.timeoutAfterComboBox .addItem (String (5000 + 1000 * i) + "ms", i + 2);
  740. }
  741. pc.ledMsToBeOnComboBox .setSelectedItemIndex (5);
  742. pc.ledMsToBeOffComboBox .setSelectedItemIndex (5);
  743. pc.vibratorMsToBeOnComboBox .setSelectedItemIndex (0);
  744. pc.vibratorMsToBeOffComboBox.setSelectedItemIndex (0);
  745. pc.timeoutAfterComboBox .setSelectedItemIndex (0);
  746. pc.timestampVisibilityComboBox.addItem ("off", 1);
  747. pc.timestampVisibilityComboBox.addItem ("on", 2);
  748. pc.timestampVisibilityComboBox.addItem ("chronometer", 3);
  749. pc.timestampVisibilityComboBox.addItem ("count down", 4);
  750. pc.timestampVisibilityComboBox.setSelectedItemIndex (1);
  751. }
  752. void distributeControls()
  753. {
  754. auto& pc = paramControls;
  755. paramsOneView .addRowComponent (new RowComponent (pc.identifierLabel, pc.identifierEditor));
  756. paramsOneView .addRowComponent (new RowComponent (pc.titleLabel, pc.titleEditor));
  757. paramsOneView .addRowComponent (new RowComponent (pc.bodyLabel, pc.bodyEditor, 4));
  758. #if JUCE_IOS
  759. paramsOneView .addRowComponent (new RowComponent (pc.categoryLabel, pc.categoryComboBox));
  760. #elif JUCE_ANDROID
  761. paramsOneView .addRowComponent (new RowComponent (pc.channelIdLabel, pc.channelIdComboBox));
  762. #endif
  763. #if JUCE_ANDROID || JUCE_MAC
  764. paramsOneView .addRowComponent (new RowComponent (pc.iconLabel, pc.iconComboBox));
  765. #endif
  766. paramsTwoView .addRowComponent (new RowComponent (pc.subtitleLabel, pc.subtitleEditor));
  767. #if ! JUCE_MAC
  768. paramsTwoView .addRowComponent (new RowComponent (pc.badgeNumberLabel, pc.badgeNumberComboBox));
  769. #endif
  770. paramsTwoView .addRowComponent (new RowComponent (pc.soundToPlayLabel, pc.soundToPlayComboBox));
  771. paramsTwoView .addRowComponent (new RowComponent (pc.propertiesLabel, pc.propertiesEditor, 3));
  772. #if JUCE_IOS || JUCE_MAC
  773. paramsTwoView .addRowComponent (new RowComponent (pc.fireInLabel, pc.fireInComboBox));
  774. paramsTwoView .addRowComponent (new RowComponent (pc.repeatLabel, pc.repeatButton));
  775. #elif JUCE_ANDROID
  776. paramsTwoView .addRowComponent (new RowComponent (pc.largeIconLabel, pc.largeIconComboBox));
  777. paramsTwoView .addRowComponent (new RowComponent (pc.badgeIconLabel, pc.badgeIconComboBox));
  778. paramsTwoView .addRowComponent (new RowComponent (pc.tickerTextLabel, pc.tickerTextEditor));
  779. paramsTwoView .addRowComponent (new RowComponent (pc.autoCancelLabel, pc.autoCancelButton));
  780. paramsTwoView .addRowComponent (new RowComponent (pc.alertOnlyOnceLabel, pc.alertOnlyOnceButton));
  781. #endif
  782. #if JUCE_ANDROID || JUCE_MAC
  783. paramsTwoView .addRowComponent (new RowComponent (pc.actionsLabel, pc.actionsComboBox));
  784. #endif
  785. #if JUCE_ANDROID
  786. paramsThreeView.addRowComponent (new RowComponent (pc.progressMaxLabel, pc.progressMaxComboBox));
  787. paramsThreeView.addRowComponent (new RowComponent (pc.progressCurrentLabel, pc.progressCurrentComboBox));
  788. paramsThreeView.addRowComponent (new RowComponent (pc.progressIndeterminateLabel, pc.progressIndeterminateButton));
  789. paramsThreeView.addRowComponent (new RowComponent (pc.categoryLabel, pc.categoryComboBox));
  790. paramsThreeView.addRowComponent (new RowComponent (pc.priorityLabel, pc.priorityComboBox));
  791. paramsThreeView.addRowComponent (new RowComponent (pc.personLabel, pc.personEditor));
  792. paramsThreeView.addRowComponent (new RowComponent (pc.lockScreenVisibilityLabel, pc.lockScreenVisibilityComboBox));
  793. paramsThreeView.addRowComponent (new RowComponent (pc.groupIdLabel, pc.groupIdEditor));
  794. paramsThreeView.addRowComponent (new RowComponent (pc.sortKeyLabel, pc.sortKeyEditor));
  795. paramsThreeView.addRowComponent (new RowComponent (pc.groupSummaryLabel, pc.groupSummaryButton));
  796. paramsThreeView.addRowComponent (new RowComponent (pc.groupAlertBehaviourLabel, pc.groupAlertBehaviourComboBox));
  797. paramsFourView .addRowComponent (new RowComponent (pc.accentColourLabel, pc.accentColourButton));
  798. paramsFourView .addRowComponent (new RowComponent (pc.ledColourLabel, pc.ledColourButton));
  799. paramsFourView .addRowComponent (new RowComponent (pc.ledMsToBeOffLabel, pc.ledMsToBeOffComboBox));
  800. paramsFourView .addRowComponent (new RowComponent (pc.ledMsToBeOnLabel, pc.ledMsToBeOnComboBox));
  801. paramsFourView .addRowComponent (new RowComponent (pc.vibratorMsToBeOffLabel, pc.vibratorMsToBeOffComboBox));
  802. paramsFourView .addRowComponent (new RowComponent (pc.vibratorMsToBeOnLabel, pc.vibratorMsToBeOnComboBox));
  803. paramsFourView .addRowComponent (new RowComponent (pc.localOnlyLabel, pc.localOnlyButton));
  804. paramsFourView .addRowComponent (new RowComponent (pc.ongoingLabel, pc.ongoingButton));
  805. paramsFourView .addRowComponent (new RowComponent (pc.timestampVisibilityLabel, pc.timestampVisibilityComboBox));
  806. paramsFourView .addRowComponent (new RowComponent (pc.timeoutAfterLabel, pc.timeoutAfterComboBox));
  807. #endif
  808. }
  809. struct ParamsView : public Component
  810. {
  811. ParamsView()
  812. {
  813. // For now, to be able to dismiss mobile keyboard.
  814. setWantsKeyboardFocus (true);
  815. }
  816. void addRowComponent (RowComponent* rc)
  817. {
  818. rowComponents.add (rc);
  819. addAndMakeVisible (rc);
  820. }
  821. void resized() override
  822. {
  823. auto totalRowUnits = 0;
  824. for (auto* rc : rowComponents)
  825. totalRowUnits += rc->rowUnits;
  826. auto rowHeight = getHeight() / totalRowUnits;
  827. auto bounds = getLocalBounds();
  828. for (auto* rc : rowComponents)
  829. rc->setBounds (bounds.removeFromTop (rc->rowUnits * rowHeight));
  830. auto* last = rowComponents[rowComponents.size() - 1];
  831. last->setBounds (last->getBounds().withHeight (getHeight() - last->getY()));
  832. }
  833. private:
  834. OwnedArray<RowComponent> rowComponents;
  835. };
  836. struct AuxActionsView : public Component
  837. {
  838. AuxActionsView()
  839. {
  840. addAndMakeVisible (getDeliveredNotificationsButton);
  841. addAndMakeVisible (removeDeliveredNotifWithIdButton);
  842. addAndMakeVisible (deliveredNotifIdentifier);
  843. addAndMakeVisible (removeAllDeliveredNotifsButton);
  844. #if JUCE_IOS || JUCE_MAC
  845. addAndMakeVisible (getPendingNotificationsButton);
  846. addAndMakeVisible (removePendingNotifWithIdButton);
  847. addAndMakeVisible (pendingNotifIdentifier);
  848. addAndMakeVisible (removeAllPendingNotifsButton);
  849. #endif
  850. // For now, to be able to dismiss mobile keyboard.
  851. setWantsKeyboardFocus (true);
  852. }
  853. void resized() override
  854. {
  855. auto columnWidth = getWidth();
  856. auto rowHeight = getHeight() / 6;
  857. auto bounds = getLocalBounds();
  858. getDeliveredNotificationsButton .setBounds (bounds.removeFromTop (rowHeight));
  859. auto rowBounds = bounds.removeFromTop (rowHeight);
  860. removeDeliveredNotifWithIdButton.setBounds (rowBounds.removeFromLeft (columnWidth / 2));
  861. deliveredNotifIdentifier .setBounds (rowBounds);
  862. removeAllDeliveredNotifsButton .setBounds (bounds.removeFromTop (rowHeight));
  863. #if JUCE_IOS || JUCE_MAC
  864. getPendingNotificationsButton .setBounds (bounds.removeFromTop (rowHeight));
  865. rowBounds = bounds.removeFromTop (rowHeight);
  866. removePendingNotifWithIdButton.setBounds (rowBounds.removeFromLeft (columnWidth / 2));
  867. pendingNotifIdentifier .setBounds (rowBounds);
  868. removeAllPendingNotifsButton .setBounds (bounds.removeFromTop (rowHeight));
  869. #endif
  870. }
  871. TextButton getDeliveredNotificationsButton { "Get Delivered Notifications" };
  872. TextButton removeDeliveredNotifWithIdButton { "Remove Delivered Notif With ID:" };
  873. TextEditor deliveredNotifIdentifier;
  874. TextButton removeAllDeliveredNotifsButton { "Remove All Delivered Notifs" };
  875. TextButton getPendingNotificationsButton { "Get Pending Notifications" };
  876. TextButton removePendingNotifWithIdButton { "Remove Pending Notif With ID:" };
  877. TextEditor pendingNotifIdentifier;
  878. TextButton removeAllPendingNotifsButton { "Remove All Pending Notifs" };
  879. };
  880. struct RemoteView : public Component
  881. {
  882. RemoteView()
  883. {
  884. addAndMakeVisible (getDeviceTokenButton);
  885. #if JUCE_ANDROID
  886. addAndMakeVisible (sendRemoteMessageButton);
  887. addAndMakeVisible (subscribeToSportsButton);
  888. addAndMakeVisible (unsubscribeFromSportsButton);
  889. #endif
  890. }
  891. void resized()
  892. {
  893. auto rowSize = getHeight () / 10;
  894. auto bounds = getLocalBounds().reduced (getWidth() / 10, getHeight() / 10);
  895. bounds.removeFromTop (2 * rowSize);
  896. getDeviceTokenButton .setBounds (bounds.removeFromTop (rowSize));
  897. sendRemoteMessageButton .setBounds (bounds.removeFromTop (rowSize));
  898. subscribeToSportsButton .setBounds (bounds.removeFromTop (rowSize));
  899. unsubscribeFromSportsButton.setBounds (bounds.removeFromTop (rowSize));
  900. }
  901. TextButton getDeviceTokenButton { "GetDeviceToken" };
  902. TextButton sendRemoteMessageButton { "SendRemoteMessage" };
  903. TextButton subscribeToSportsButton { "SubscribeToSports" };
  904. TextButton unsubscribeFromSportsButton { "UnsubscribeFromSports" };
  905. };
  906. struct DemoTabbedComponent : public TabbedComponent
  907. {
  908. explicit DemoTabbedComponent (TabbedButtonBar::Orientation orientation)
  909. : TabbedComponent (orientation)
  910. {
  911. }
  912. void currentTabChanged (int, const String& newCurrentTabName) override
  913. {
  914. if (! showedRemoteInstructions && newCurrentTabName == "Remote")
  915. {
  916. PushNotificationsDemo::showRemoteInstructions();
  917. showedRemoteInstructions = true;
  918. }
  919. }
  920. private:
  921. bool showedRemoteInstructions = false;
  922. };
  923. static void showRemoteInstructions()
  924. {
  925. #if JUCE_IOS || JUCE_MAC
  926. NativeMessageBox::showMessageBoxAsync (AlertWindow::InfoIcon,
  927. "Remote Notifications instructions",
  928. "In order to be able to test remote notifications "
  929. "ensure that the app is signed and that you register "
  930. "the bundle ID for remote notifications in "
  931. "Apple Developer Center.");
  932. #endif
  933. }
  934. Label headerLabel { "headerLabel", "Push Notifications Demo" };
  935. ParamControls paramControls;
  936. ParamsView paramsOneView, paramsTwoView, paramsThreeView, paramsFourView;
  937. AuxActionsView auxActionsView;
  938. TabbedComponent localNotificationsTabs { TabbedButtonBar::TabsAtTop };
  939. RemoteView remoteView;
  940. DemoTabbedComponent mainTabs { TabbedButtonBar::TabsAtTop };
  941. TextButton sendButton { "Send!" };
  942. Label notAvailableYetLabel { "notAvailableYetLabel",
  943. "Push Notifications feature is not available on this platform yet!" };
  944. //==============================================================================
  945. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PushNotificationsDemo)
  946. };