michael@0: /* michael@0: Licensed under the Apache License, Version 2.0 (the "License"); michael@0: you may not use this file except in compliance with the License. michael@0: You may obtain a copy of the License at michael@0: michael@0: http://www.apache.org/licenses/LICENSE-2.0 michael@0: michael@0: Unless required by applicable law or agreed to in writing, software michael@0: distributed under the License is distributed on an "AS IS" BASIS, michael@0: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: See the License for the specific language governing permissions and michael@0: limitations under the License. michael@0: */ michael@0: michael@0: using System; michael@0: using System.Windows; michael@0: using System.Windows.Controls; michael@0: using Microsoft.Devices; michael@0: using System.Runtime.Serialization; michael@0: using System.Threading; michael@0: using System.Windows.Resources; michael@0: using Microsoft.Phone.Controls; michael@0: using Microsoft.Xna.Framework.Audio; michael@0: using WPCordovaClassLib.Cordova.UI; michael@0: using System.Diagnostics; michael@0: michael@0: michael@0: namespace WPCordovaClassLib.Cordova.Commands michael@0: { michael@0: public class Notification : BaseCommand michael@0: { michael@0: static ProgressBar progressBar = null; michael@0: const int DEFAULT_DURATION = 5; michael@0: michael@0: private NotificationBox notifyBox; michael@0: michael@0: private class NotifBoxData michael@0: { michael@0: public NotificationBox previous {get;set;} michael@0: public string callbackId { get; set; } michael@0: } michael@0: michael@0: private PhoneApplicationPage Page michael@0: { michael@0: get michael@0: { michael@0: PhoneApplicationPage page = null; michael@0: PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; michael@0: if (frame != null) michael@0: { michael@0: page = frame.Content as PhoneApplicationPage; michael@0: } michael@0: return page; michael@0: } michael@0: } michael@0: michael@0: // blink api - doesn't look like there is an equivalent api we can use... michael@0: michael@0: [DataContract] michael@0: public class AlertOptions michael@0: { michael@0: [OnDeserializing] michael@0: public void OnDeserializing(StreamingContext context) michael@0: { michael@0: // set defaults michael@0: this.message = "message"; michael@0: this.title = "Alert"; michael@0: this.buttonLabel = "ok"; michael@0: } michael@0: michael@0: /// michael@0: /// message to display in the alert box michael@0: /// michael@0: [DataMember] michael@0: public string message; michael@0: michael@0: /// michael@0: /// title displayed on the alert window michael@0: /// michael@0: [DataMember] michael@0: public string title; michael@0: michael@0: /// michael@0: /// text to display on the button michael@0: /// michael@0: [DataMember] michael@0: public string buttonLabel; michael@0: } michael@0: michael@0: [DataContract] michael@0: public class PromptResult michael@0: { michael@0: [DataMember] michael@0: public int buttonIndex; michael@0: michael@0: [DataMember] michael@0: public string input1; michael@0: michael@0: public PromptResult(int index, string text) michael@0: { michael@0: this.buttonIndex = index; michael@0: this.input1 = text; michael@0: } michael@0: } michael@0: michael@0: public void alert(string options) michael@0: { michael@0: string[] args = JSON.JsonHelper.Deserialize(options); michael@0: AlertOptions alertOpts = new AlertOptions(); michael@0: alertOpts.message = args[0]; michael@0: alertOpts.title = args[1]; michael@0: alertOpts.buttonLabel = args[2]; michael@0: string aliasCurrentCommandCallbackId = args[3]; michael@0: michael@0: Deployment.Current.Dispatcher.BeginInvoke(() => michael@0: { michael@0: PhoneApplicationPage page = Page; michael@0: if (page != null) michael@0: { michael@0: Grid grid = page.FindName("LayoutRoot") as Grid; michael@0: if (grid != null) michael@0: { michael@0: var previous = notifyBox; michael@0: notifyBox = new NotificationBox(); michael@0: notifyBox.Tag = new NotifBoxData { previous = previous, callbackId = aliasCurrentCommandCallbackId }; michael@0: notifyBox.PageTitle.Text = alertOpts.title; michael@0: notifyBox.SubTitle.Text = alertOpts.message; michael@0: Button btnOK = new Button(); michael@0: btnOK.Content = alertOpts.buttonLabel; michael@0: btnOK.Click += new RoutedEventHandler(btnOK_Click); michael@0: btnOK.Tag = 1; michael@0: notifyBox.ButtonPanel.Children.Add(btnOK); michael@0: grid.Children.Add(notifyBox); michael@0: michael@0: if (previous == null) michael@0: { michael@0: page.BackKeyPress += page_BackKeyPress; michael@0: } michael@0: } michael@0: } michael@0: else michael@0: { michael@0: DispatchCommandResult(new PluginResult(PluginResult.Status.INSTANTIATION_EXCEPTION)); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: public void prompt(string options) michael@0: { michael@0: string[] args = JSON.JsonHelper.Deserialize(options); michael@0: string message = args[0]; michael@0: string title = args[1]; michael@0: string buttonLabelsArray = args[2]; michael@0: string[] buttonLabels = JSON.JsonHelper.Deserialize(buttonLabelsArray); michael@0: string defaultText = args[3]; michael@0: string aliasCurrentCommandCallbackId = args[4]; michael@0: michael@0: Deployment.Current.Dispatcher.BeginInvoke(() => michael@0: { michael@0: PhoneApplicationPage page = Page; michael@0: if (page != null) michael@0: { michael@0: Grid grid = page.FindName("LayoutRoot") as Grid; michael@0: if (grid != null) michael@0: { michael@0: var previous = notifyBox; michael@0: notifyBox = new NotificationBox(); michael@0: notifyBox.Tag = new NotifBoxData { previous = previous, callbackId = aliasCurrentCommandCallbackId }; michael@0: notifyBox.PageTitle.Text = title; michael@0: notifyBox.SubTitle.Text = message; michael@0: michael@0: //TextBox textBox = new TextBox(); michael@0: //textBox.Text = defaultText; michael@0: //textBox.AcceptsReturn = true; michael@0: //notifyBox.ContentScroller.Content = textBox; michael@0: michael@0: notifyBox.InputText.Text = defaultText; michael@0: notifyBox.InputText.Visibility = Visibility.Visible; michael@0: michael@0: for (int i = 0; i < buttonLabels.Length; ++i) michael@0: { michael@0: Button button = new Button(); michael@0: button.Content = buttonLabels[i]; michael@0: button.Tag = i + 1; michael@0: button.Click += promptBoxbutton_Click; michael@0: notifyBox.ButtonPanel.Orientation = Orientation.Vertical; michael@0: notifyBox.ButtonPanel.Children.Add(button); michael@0: } michael@0: michael@0: grid.Children.Add(notifyBox); michael@0: if (previous != null) michael@0: { michael@0: page.BackKeyPress += page_BackKeyPress; michael@0: } michael@0: } michael@0: } michael@0: else michael@0: { michael@0: DispatchCommandResult(new PluginResult(PluginResult.Status.INSTANTIATION_EXCEPTION)); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: public void confirm(string options) michael@0: { michael@0: string[] args = JSON.JsonHelper.Deserialize(options); michael@0: AlertOptions alertOpts = new AlertOptions(); michael@0: alertOpts.message = args[0]; michael@0: alertOpts.title = args[1]; michael@0: alertOpts.buttonLabel = args[2]; michael@0: string aliasCurrentCommandCallbackId = args[3]; michael@0: michael@0: Deployment.Current.Dispatcher.BeginInvoke(() => michael@0: { michael@0: PhoneApplicationPage page = Page; michael@0: if (page != null) michael@0: { michael@0: Grid grid = page.FindName("LayoutRoot") as Grid; michael@0: if (grid != null) michael@0: { michael@0: var previous = notifyBox; michael@0: notifyBox = new NotificationBox(); michael@0: notifyBox.Tag = new NotifBoxData { previous = previous, callbackId = aliasCurrentCommandCallbackId }; michael@0: notifyBox.PageTitle.Text = alertOpts.title; michael@0: notifyBox.SubTitle.Text = alertOpts.message; michael@0: michael@0: string[] labels = JSON.JsonHelper.Deserialize(alertOpts.buttonLabel); michael@0: michael@0: if (labels == null) michael@0: { michael@0: labels = alertOpts.buttonLabel.Split(','); michael@0: } michael@0: michael@0: for (int n = 0; n < labels.Length; n++) michael@0: { michael@0: Button btn = new Button(); michael@0: btn.Content = labels[n]; michael@0: btn.Tag = n; michael@0: btn.Click += new RoutedEventHandler(btnOK_Click); michael@0: notifyBox.ButtonPanel.Children.Add(btn); michael@0: } michael@0: michael@0: grid.Children.Add(notifyBox); michael@0: if (previous == null) michael@0: { michael@0: page.BackKeyPress += page_BackKeyPress; michael@0: } michael@0: } michael@0: } michael@0: else michael@0: { michael@0: DispatchCommandResult(new PluginResult(PluginResult.Status.INSTANTIATION_EXCEPTION)); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: void promptBoxbutton_Click(object sender, RoutedEventArgs e) michael@0: { michael@0: Button button = sender as Button; michael@0: FrameworkElement promptBox = null; michael@0: int buttonIndex = 0; michael@0: string callbackId = string.Empty; michael@0: string text = string.Empty; michael@0: if (button != null) michael@0: { michael@0: buttonIndex = (int)button.Tag; michael@0: promptBox = button.Parent as FrameworkElement; michael@0: while ((promptBox = promptBox.Parent as FrameworkElement) != null && michael@0: !(promptBox is NotificationBox)) ; michael@0: } michael@0: michael@0: if (promptBox != null) michael@0: { michael@0: NotificationBox box = promptBox as NotificationBox; michael@0: michael@0: text = box.InputText.Text; michael@0: michael@0: PhoneApplicationPage page = Page; michael@0: if (page != null) michael@0: { michael@0: Grid grid = page.FindName("LayoutRoot") as Grid; michael@0: if (grid != null) michael@0: { michael@0: grid.Children.Remove(promptBox); michael@0: } michael@0: michael@0: NotifBoxData data = promptBox.Tag as NotifBoxData; michael@0: promptBox = data.previous as NotificationBox; michael@0: callbackId = data.callbackId as string; michael@0: michael@0: if (promptBox == null) michael@0: { michael@0: page.BackKeyPress -= page_BackKeyPress; michael@0: } michael@0: } michael@0: } michael@0: DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new PromptResult(buttonIndex, text)), callbackId); michael@0: } michael@0: michael@0: void page_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e) michael@0: { michael@0: PhoneApplicationPage page = sender as PhoneApplicationPage; michael@0: string callbackId = ""; michael@0: if (page != null && notifyBox != null) michael@0: { michael@0: Grid grid = page.FindName("LayoutRoot") as Grid; michael@0: if (grid != null) michael@0: { michael@0: grid.Children.Remove(notifyBox); michael@0: NotifBoxData notifBoxData = notifyBox.Tag as NotifBoxData; michael@0: notifyBox = notifBoxData.previous as NotificationBox; michael@0: callbackId = notifBoxData.callbackId as string; michael@0: } michael@0: if (notifyBox == null) michael@0: { michael@0: page.BackKeyPress -= page_BackKeyPress; michael@0: } michael@0: e.Cancel = true; michael@0: } michael@0: michael@0: DispatchCommandResult(new PluginResult(PluginResult.Status.OK, 0), callbackId); michael@0: } michael@0: michael@0: void btnOK_Click(object sender, RoutedEventArgs e) michael@0: { michael@0: Button btn = sender as Button; michael@0: FrameworkElement notifBoxParent = null; michael@0: int retVal = 0; michael@0: string callbackId = ""; michael@0: if (btn != null) michael@0: { michael@0: retVal = (int)btn.Tag + 1; michael@0: michael@0: notifBoxParent = btn.Parent as FrameworkElement; michael@0: while ((notifBoxParent = notifBoxParent.Parent as FrameworkElement) != null && michael@0: !(notifBoxParent is NotificationBox)) ; michael@0: } michael@0: if (notifBoxParent != null) michael@0: { michael@0: PhoneApplicationPage page = Page; michael@0: if (page != null) michael@0: { michael@0: Grid grid = page.FindName("LayoutRoot") as Grid; michael@0: if (grid != null) michael@0: { michael@0: grid.Children.Remove(notifBoxParent); michael@0: } michael@0: michael@0: NotifBoxData notifBoxData = notifBoxParent.Tag as NotifBoxData; michael@0: notifyBox = notifBoxData.previous as NotificationBox; michael@0: callbackId = notifBoxData.callbackId as string; michael@0: michael@0: if (notifyBox == null) michael@0: { michael@0: page.BackKeyPress -= page_BackKeyPress; michael@0: } michael@0: } michael@0: michael@0: } michael@0: DispatchCommandResult(new PluginResult(PluginResult.Status.OK, retVal), callbackId); michael@0: } michael@0: michael@0: michael@0: michael@0: public void beep(string options) michael@0: { michael@0: string[] args = JSON.JsonHelper.Deserialize(options); michael@0: int times = int.Parse(args[0]); michael@0: michael@0: string resourcePath = BaseCommand.GetBaseURL() + "Plugins/org.apache.cordova.dialogs/notification-beep.wav"; michael@0: michael@0: StreamResourceInfo sri = Application.GetResourceStream(new Uri(resourcePath, UriKind.Relative)); michael@0: michael@0: if (sri != null) michael@0: { michael@0: SoundEffect effect = SoundEffect.FromStream(sri.Stream); michael@0: SoundEffectInstance inst = effect.CreateInstance(); michael@0: ThreadPool.QueueUserWorkItem((o) => michael@0: { michael@0: // cannot interact with UI !! michael@0: do michael@0: { michael@0: inst.Play(); michael@0: Thread.Sleep(effect.Duration + TimeSpan.FromMilliseconds(100)); michael@0: } michael@0: while (--times > 0); michael@0: michael@0: }); michael@0: michael@0: } michael@0: michael@0: // TODO: may need a listener to trigger DispatchCommandResult after the alarm has finished executing... michael@0: DispatchCommandResult(); michael@0: } michael@0: michael@0: // Display an indeterminate progress indicator michael@0: public void activityStart(string unused) michael@0: { michael@0: michael@0: Deployment.Current.Dispatcher.BeginInvoke(() => michael@0: { michael@0: PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; michael@0: michael@0: if (frame != null) michael@0: { michael@0: PhoneApplicationPage page = frame.Content as PhoneApplicationPage; michael@0: michael@0: if (page != null) michael@0: { michael@0: var temp = page.FindName("LayoutRoot"); michael@0: Grid grid = temp as Grid; michael@0: if (grid != null) michael@0: { michael@0: if (progressBar != null) michael@0: { michael@0: grid.Children.Remove(progressBar); michael@0: } michael@0: progressBar = new ProgressBar(); michael@0: progressBar.IsIndeterminate = true; michael@0: progressBar.IsEnabled = true; michael@0: michael@0: grid.Children.Add(progressBar); michael@0: } michael@0: } michael@0: } michael@0: }); michael@0: } michael@0: michael@0: michael@0: // Remove our indeterminate progress indicator michael@0: public void activityStop(string unused) michael@0: { michael@0: Deployment.Current.Dispatcher.BeginInvoke(() => michael@0: { michael@0: if (progressBar != null) michael@0: { michael@0: progressBar.IsEnabled = false; michael@0: PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; michael@0: if (frame != null) michael@0: { michael@0: PhoneApplicationPage page = frame.Content as PhoneApplicationPage; michael@0: if (page != null) michael@0: { michael@0: Grid grid = page.FindName("LayoutRoot") as Grid; michael@0: if (grid != null) michael@0: { michael@0: grid.Children.Remove(progressBar); michael@0: } michael@0: } michael@0: } michael@0: progressBar = null; michael@0: } michael@0: }); michael@0: } michael@0: michael@0: public void vibrate(string vibrateDuration) michael@0: { michael@0: michael@0: int msecs = 200; // set default michael@0: michael@0: try michael@0: { michael@0: string[] args = JSON.JsonHelper.Deserialize(vibrateDuration); michael@0: michael@0: msecs = int.Parse(args[0]); michael@0: if (msecs < 1) michael@0: { michael@0: msecs = 1; michael@0: } michael@0: } michael@0: catch (FormatException) michael@0: { michael@0: michael@0: } michael@0: michael@0: VibrateController.Default.Start(TimeSpan.FromMilliseconds(msecs)); michael@0: michael@0: // TODO: may need to add listener to trigger DispatchCommandResult when the vibration ends... michael@0: DispatchCommandResult(); michael@0: } michael@0: } michael@0: }