├── index.js ├── ios ├── RCTDialogs │ ├── CDVNotification.bundle │ │ └── beep.wav │ ├── CDVNotification.h │ └── CDVNotification.m └── RCTDialogs.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── android ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── remobile │ │ └── dialogs │ │ ├── RCTDialogsPackage.java │ │ └── Notification.java └── build.gradle ├── .npmignore ├── .gitignore ├── package.json ├── LICENSE ├── libs ├── android │ └── notification.js └── notification.js └── README.md /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Notification = require('./libs/notification.js'); 3 | 4 | module.exports = Notification; 5 | -------------------------------------------------------------------------------- /ios/RCTDialogs/CDVNotification.bundle/beep.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/remobile/react-native-dialogs/HEAD/ios/RCTDialogs/CDVNotification.bundle/beep.wav -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | .DS_Store 3 | *Thumbs.db 4 | .gradle 5 | .idea 6 | *.iml 7 | npm-debug.log 8 | node_modules 9 | /android/build 10 | /ios/**/*xcuserdata* 11 | /ios/**/*xcshareddata* 12 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.[aod] 2 | *.DS_Store 3 | .DS_Store 4 | *Thumbs.db 5 | *.iml 6 | .gradle 7 | .idea 8 | node_modules 9 | npm-debug.log 10 | /android/build 11 | /ios/**/*xcuserdata* 12 | /ios/**/*xcshareddata* 13 | -------------------------------------------------------------------------------- /ios/RCTDialogs.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 16 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile 'com.android.support:appcompat-v7:23.0.1' 24 | compile 'com.facebook.react:react-native:+' 25 | compile project(':react-native-cordova') 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@remobile/react-native-dialogs", 3 | "version": "1.0.7", 4 | "description": "A dialogs for react-native, code come from cordova, support for android and ios", 5 | "main": "index.js", 6 | "author": { 7 | "name": "YunJiang.Fang", 8 | "email": "42550564@qq.com" 9 | }, 10 | "license": "MIT", 11 | "keywords": [ 12 | "react-native", 13 | "react-component", 14 | "ios", 15 | "android", 16 | "dialogs", 17 | "alert", 18 | "confirm", 19 | "prompt", 20 | "beep", 21 | "remobile", 22 | "mobile" 23 | ], 24 | "homepage": "https://github.com/remobile/react-native-dialogs", 25 | "bugs": { 26 | "url": "https://github.com/remobile/react-native-dialogs/issues" 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "git://github.com/remobile/react-native-dialogs.git" 31 | }, 32 | "peerDependencies": { 33 | "@remobile/react-native-cordova": "^1.1.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /android/src/main/java/com/remobile/dialogs/RCTDialogsPackage.java: -------------------------------------------------------------------------------- 1 | package com.remobile.dialogs; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.bridge.JavaScriptModule; 9 | import com.facebook.react.bridge.NativeModule; 10 | import com.facebook.react.bridge.ReactApplicationContext; 11 | import com.facebook.react.uimanager.ViewManager; 12 | 13 | public class RCTDialogsPackage implements ReactPackage { 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | return Arrays.asList( 17 | new Notification(reactContext) 18 | ); 19 | } 20 | 21 | public List> createJSModules() { 22 | return Collections.emptyList(); 23 | } 24 | 25 | @Override 26 | public List createViewManagers(ReactApplicationContext reactContext) { 27 | return Arrays.asList(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2015-2016 YunJiang.Fang <42550564@qq.com> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /ios/RCTDialogs/CDVNotification.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import 21 | #import 22 | #import 23 | #import "CDVPlugin.h" 24 | 25 | @interface CDVNotification : CDVPlugin {} 26 | 27 | - (void)alert:(CDVInvokedUrlCommand*)command; 28 | - (void)confirm:(CDVInvokedUrlCommand*)command; 29 | - (void)prompt:(CDVInvokedUrlCommand*)command; 30 | - (void)beep:(CDVInvokedUrlCommand*)command; 31 | 32 | @end 33 | 34 | @interface CDVAlertView : UIAlertView {} 35 | @property (nonatomic, strong) NSString* callbackId; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /libs/android/notification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * 20 | */ 21 | 22 | const exec = require('@remobile/react-native-cordova').exec; 23 | 24 | /** 25 | * Provides Android enhanced notification API. 26 | */ 27 | module.exports = { 28 | activityStart : function(title, message) { 29 | // If title and message not specified then mimic Android behavior of 30 | // using default strings. 31 | if (typeof title === "undefined" && typeof message == "undefined") { 32 | title = "Busy"; 33 | message = 'Please wait...'; 34 | } 35 | 36 | exec(null, null, 'Notification', 'activityStart', [ title, message ]); 37 | }, 38 | 39 | /** 40 | * Close an activity dialog 41 | */ 42 | activityStop : function() { 43 | exec(null, null, 'Notification', 'activityStop', []); 44 | }, 45 | 46 | /** 47 | * Display a progress dialog with progress bar that goes from 0 to 100. 48 | * 49 | * @param {String} 50 | * title Title of the progress dialog. 51 | * @param {String} 52 | * message Message to display in the dialog. 53 | */ 54 | progressStart : function(title, message) { 55 | exec(null, null, 'Notification', 'progressStart', [ title, message ]); 56 | }, 57 | 58 | /** 59 | * Close the progress dialog. 60 | */ 61 | progressStop : function() { 62 | exec(null, null, 'Notification', 'progressStop', []); 63 | }, 64 | 65 | /** 66 | * Set the progress dialog value. 67 | * 68 | * @param {Number} 69 | * value 0-100 70 | */ 71 | progressValue : function(value) { 72 | exec(null, null, 'Notification', 'progressValue', [ value ]); 73 | } 74 | }; 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native Dialogs (remobile) 2 | A dialogs for react-native, code come from cordova, support for android and ios 3 | 4 | ## Installation 5 | ```sh 6 | npm install @remobile/react-native-dialogs --save 7 | ``` 8 | 9 | ### Installation (iOS) 10 | * Drag RCTDialogs.xcodeproj to your project on Xcode. 11 | * Click on your main project file (the one that represents the .xcodeproj) select Build Phases and drag libRCTDialogs.a from the Products folder inside the RCTDialogs.xcodeproj. 12 | * Look for Header Search Paths and make sure it contains $(SRCROOT)/../../../react-native/React as recursive. 13 | * Drag CDVNotification.bundle to your project's resource 14 | 15 | ### Installation (Android) 16 | ```gradle 17 | ... 18 | include ':react-native-dialogs' 19 | project(':react-native-dialogs').projectDir = new File(settingsDir, '../node_modules/@remobile/react-native-dialogs/android') 20 | ``` 21 | 22 | * In `android/app/build.gradle` 23 | 24 | ```gradle 25 | ... 26 | dependencies { 27 | ... 28 | compile project(':react-native-dialogs') 29 | } 30 | ``` 31 | 32 | * register module (in MainApplication.java) 33 | 34 | ```java 35 | ...... 36 | import com.remobile.dialogs.RCTDialogsPackage; // <--- import 37 | 38 | ...... 39 | 40 | @Override 41 | protected List getPackages() { 42 | ...... 43 | new RCTDialogsPackage(), // <------ add here 44 | ...... 45 | } 46 | 47 | 48 | ## Usage 49 | 50 | ### Example 51 | ```js 52 | var React = require('react'); 53 | var ReactNative = require('react-native'); 54 | var { 55 | StyleSheet, 56 | View, 57 | } = ReactNative; 58 | 59 | var Dialogs = require('@remobile/react-native-dialogs'); 60 | var Button = require('@remobile/react-native-simple-button'); 61 | var alert = Dialogs.alert; 62 | 63 | module.exports = React.createClass({ 64 | testAlert () { 65 | function alertDismissed() { 66 | alert('You selected button'); 67 | } 68 | Dialogs.alert( 69 | 'You are the winner!', // message 70 | alertDismissed, // callback 71 | 'Game Over', // title 72 | 'Done' // buttonName 73 | ); 74 | }, 75 | testConfirm () { 76 | function onConfirm(buttonIndex) { 77 | alert('You selected button ' + buttonIndex); 78 | } 79 | Dialogs.confirm( 80 | 'You are the winner!', // message 81 | onConfirm, // callback to invoke with index of button pressed 82 | 'Game Over', // title 83 | ['Restart','Exit'] // buttonLabels 84 | ); 85 | }, 86 | testPrompt () { 87 | function onPrompt(results) { 88 | alert('You selected button number ' + results.buttonIndex + ' and entered ' + results.input1); 89 | } 90 | Dialogs.prompt( 91 | 'Please enter your name', // message 92 | onPrompt, // callback to invoke 93 | 'Registration', // title 94 | ['Ok','Exit'], // buttonLabels 95 | 'Jane Doe' // defaultText 96 | ); 97 | }, 98 | testBeep () { 99 | Dialogs.beep(2); 100 | }, 101 | testActivityStart() { 102 | Dialogs.activityStart('fang', 'fangyunjiang'); 103 | }, 104 | testProgressStart() { 105 | Dialogs.progressStart('fang', 'fangyunjiang'); 106 | }, 107 | render() { 108 | var additional = app.isandroid?[ 109 | , 112 | , 115 | ]:null; 116 | return ( 117 | 118 | 121 | 124 | 127 | 130 | {additional} 131 | 132 | ); 133 | }, 134 | }); 135 | 136 | 137 | var styles = StyleSheet.create({ 138 | container: { 139 | flex: 1, 140 | justifyContent: 'space-around', 141 | alignItems: 'center', 142 | backgroundColor: 'transparent', 143 | paddingVertical: 150, 144 | }, 145 | }); 146 | ``` 147 | 148 | ### HELP 149 | * look https://github.com/apache/cordova-plugin-dialogs 150 | 151 | 152 | ### thanks 153 | * this project come from https://github.com/apache/cordova-plugin-dialogs 154 | 155 | 156 | ### see detail use 157 | * https://github.com/remobile/react-native-template 158 | -------------------------------------------------------------------------------- /libs/notification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * 20 | */ 21 | 22 | const ReactNative = require('react-native'); 23 | const exec = require('@remobile/react-native-cordova').exec; 24 | const AndroidNotification = require('./android/notification'); 25 | 26 | /** 27 | * Provides access to notifications on the device. 28 | */ 29 | 30 | let Notification = { 31 | 32 | /** 33 | * Open a native alert dialog, with a customizable title and button text. 34 | * 35 | * @param {String} message Message to print in the body of the alert 36 | * @param {Function} completeCallback The callback that is called when user clicks on a button. 37 | * @param {String} title Title of the alert dialog (default: Alert) 38 | * @param {String} buttonLabel Label of the close button (default: OK) 39 | */ 40 | alert: function (message, completeCallback, title, buttonLabel) { 41 | const _message = (typeof message === 'string' ? message : JSON.stringify(message)); 42 | const _title = (typeof title === 'string' ? title : 'Alert'); 43 | const _buttonLabel = (buttonLabel || 'OK'); 44 | exec(completeCallback, null, 'Notification', 'alert', [_message, _title, _buttonLabel]); 45 | }, 46 | 47 | /** 48 | * Open a native confirm dialog, with a customizable title and button text. 49 | * The result that the user selects is returned to the result callback. 50 | * 51 | * @param {String} message Message to print in the body of the alert 52 | * @param {Function} resultCallback The callback that is called when user clicks on a button. 53 | * @param {String} title Title of the alert dialog (default: Confirm) 54 | * @param {Array} buttonLabels Array of the labels of the buttons (default: ['OK', 'Cancel']) 55 | */ 56 | confirm: function (message, resultCallback, title, buttonLabels) { 57 | const _message = (typeof message === 'string' ? message : JSON.stringify(message)); 58 | const _title = (typeof title === 'string' ? title : 'Confirm'); 59 | let _buttonLabels = (buttonLabels || ['OK', 'Cancel']); 60 | 61 | // Strings are deprecated! 62 | if (typeof _buttonLabels === 'string') { 63 | console.log('Notification.confirm(string, function, string, string) is deprecated. Use Notification.confirm(string, function, string, array).'); 64 | } 65 | 66 | _buttonLabels = convertButtonLabels(_buttonLabels); 67 | 68 | exec(resultCallback, null, 'Notification', 'confirm', [_message, _title, _buttonLabels]); 69 | }, 70 | 71 | /** 72 | * Open a native prompt dialog, with a customizable title and button text. 73 | * The following results are returned to the result callback: 74 | * buttonIndex Index number of the button selected. 75 | * input1 The text entered in the prompt dialog box. 76 | * 77 | * @param {String} message Dialog message to display (default: "Prompt message") 78 | * @param {Function} resultCallback The callback that is called when user clicks on a button. 79 | * @param {String} title Title of the dialog (default: "Prompt") 80 | * @param {Array} buttonLabels Array of strings for the button labels (default: ["OK","Cancel"]) 81 | * @param {String} defaultText Textbox input value (default: empty string) 82 | */ 83 | prompt: function (message, resultCallback, title, buttonLabels, defaultText) { 84 | const _message = (typeof message === 'string' ? message : JSON.stringify(message)); 85 | const _title = (typeof title === 'string' ? title : 'Prompt'); 86 | let _buttonLabels = (buttonLabels || ['OK', 'Cancel']); 87 | 88 | // Strings are deprecated! 89 | if (typeof _buttonLabels === 'string') { 90 | console.log('Notification.prompt(string, function, string, string) is deprecated. Use Notification.confirm(string, function, string, array).'); 91 | } 92 | 93 | _buttonLabels = convertButtonLabels(_buttonLabels); 94 | 95 | const _defaultText = (defaultText || ''); 96 | exec(resultCallback, null, 'Notification', 'prompt', [_message, _title, _buttonLabels, _defaultText]); 97 | }, 98 | 99 | /** 100 | * Causes the device to beep. 101 | * On Android, the default notification ringtone is played "count" times. 102 | * 103 | * @param {Integer} count The number of beeps. 104 | */ 105 | beep: function (count) { 106 | const defaultedCount = count || 1; 107 | exec(null, null, 'Notification', 'beep', [ defaultedCount ]); 108 | }, 109 | }; 110 | 111 | function convertButtonLabels (buttonLabels) { 112 | if (typeof buttonLabels === 'string') { 113 | buttonLabels = buttonLabels.split(','); // not crazy about changing the const type here 114 | } 115 | 116 | return buttonLabels; 117 | } 118 | 119 | if (ReactNative.Platform.OS === 'android') { 120 | Notification = Object.assign(Notification, AndroidNotification); 121 | } 122 | 123 | module.exports = Notification; 124 | -------------------------------------------------------------------------------- /ios/RCTDialogs.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 32F41D461C167329004A090F /* CDVNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F41D451C167329004A090F /* CDVNotification.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 32285F3A1BFC01E400AD8363 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = "include/$(PRODUCT_NAME)"; 18 | dstSubfolderSpec = 16; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 0; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 32285F3C1BFC01E400AD8363 /* libRCTDialogs.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTDialogs.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 32F41D441C167329004A090F /* CDVNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVNotification.h; path = RCTDialogs/CDVNotification.h; sourceTree = SOURCE_ROOT; }; 28 | 32F41D451C167329004A090F /* CDVNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVNotification.m; path = RCTDialogs/CDVNotification.m; sourceTree = SOURCE_ROOT; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | 32285F391BFC01E400AD8363 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 32285F331BFC01E400AD8363 = { 43 | isa = PBXGroup; 44 | children = ( 45 | 32285F3E1BFC01E400AD8363 /* RCTDialogs */, 46 | 32285F3D1BFC01E400AD8363 /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | 32285F3D1BFC01E400AD8363 /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 32285F3C1BFC01E400AD8363 /* libRCTDialogs.a */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | 32285F3E1BFC01E400AD8363 /* RCTDialogs */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 32F41D441C167329004A090F /* CDVNotification.h */, 62 | 32F41D451C167329004A090F /* CDVNotification.m */, 63 | ); 64 | path = RCTDialogs; 65 | sourceTree = ""; 66 | }; 67 | /* End PBXGroup section */ 68 | 69 | /* Begin PBXNativeTarget section */ 70 | 32285F3B1BFC01E400AD8363 /* RCTDialogs */ = { 71 | isa = PBXNativeTarget; 72 | buildConfigurationList = 32285F501BFC01E400AD8363 /* Build configuration list for PBXNativeTarget "RCTDialogs" */; 73 | buildPhases = ( 74 | 32285F381BFC01E400AD8363 /* Sources */, 75 | 32285F391BFC01E400AD8363 /* Frameworks */, 76 | 32285F3A1BFC01E400AD8363 /* CopyFiles */, 77 | ); 78 | buildRules = ( 79 | ); 80 | dependencies = ( 81 | ); 82 | name = RCTDialogs; 83 | productName = RCTDialogs; 84 | productReference = 32285F3C1BFC01E400AD8363 /* libRCTDialogs.a */; 85 | productType = "com.apple.product-type.library.static"; 86 | }; 87 | /* End PBXNativeTarget section */ 88 | 89 | /* Begin PBXProject section */ 90 | 32285F341BFC01E400AD8363 /* Project object */ = { 91 | isa = PBXProject; 92 | attributes = { 93 | LastUpgradeCheck = 0640; 94 | ORGANIZATIONNAME = remobile; 95 | TargetAttributes = { 96 | 32285F3B1BFC01E400AD8363 = { 97 | CreatedOnToolsVersion = 6.4; 98 | }; 99 | }; 100 | }; 101 | buildConfigurationList = 32285F371BFC01E400AD8363 /* Build configuration list for PBXProject "RCTDialogs" */; 102 | compatibilityVersion = "Xcode 3.2"; 103 | developmentRegion = English; 104 | hasScannedForEncodings = 0; 105 | knownRegions = ( 106 | en, 107 | ); 108 | mainGroup = 32285F331BFC01E400AD8363; 109 | productRefGroup = 32285F3D1BFC01E400AD8363 /* Products */; 110 | projectDirPath = ""; 111 | projectRoot = ""; 112 | targets = ( 113 | 32285F3B1BFC01E400AD8363 /* RCTDialogs */, 114 | ); 115 | }; 116 | /* End PBXProject section */ 117 | 118 | /* Begin PBXSourcesBuildPhase section */ 119 | 32285F381BFC01E400AD8363 /* Sources */ = { 120 | isa = PBXSourcesBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | 32F41D461C167329004A090F /* CDVNotification.m in Sources */, 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXSourcesBuildPhase section */ 128 | 129 | /* Begin XCBuildConfiguration section */ 130 | 32285F4E1BFC01E400AD8363 /* Debug */ = { 131 | isa = XCBuildConfiguration; 132 | buildSettings = { 133 | ALWAYS_SEARCH_USER_PATHS = NO; 134 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 135 | CLANG_CXX_LIBRARY = "libc++"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_WARN_BOOL_CONVERSION = YES; 139 | CLANG_WARN_CONSTANT_CONVERSION = YES; 140 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 141 | CLANG_WARN_EMPTY_BODY = YES; 142 | CLANG_WARN_ENUM_CONVERSION = YES; 143 | CLANG_WARN_INT_CONVERSION = YES; 144 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 145 | CLANG_WARN_UNREACHABLE_CODE = YES; 146 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 147 | COPY_PHASE_STRIP = NO; 148 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 149 | ENABLE_STRICT_OBJC_MSGSEND = YES; 150 | GCC_C_LANGUAGE_STANDARD = gnu99; 151 | GCC_DYNAMIC_NO_PIC = NO; 152 | GCC_NO_COMMON_BLOCKS = YES; 153 | GCC_OPTIMIZATION_LEVEL = 0; 154 | GCC_PREPROCESSOR_DEFINITIONS = ( 155 | "DEBUG=1", 156 | "$(inherited)", 157 | ); 158 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 159 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 160 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 161 | GCC_WARN_UNDECLARED_SELECTOR = YES; 162 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 163 | GCC_WARN_UNUSED_FUNCTION = YES; 164 | GCC_WARN_UNUSED_VARIABLE = YES; 165 | HEADER_SEARCH_PATHS = ( 166 | "$(inherited)", 167 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 168 | "$(SRCROOT)/../../../react-native/React/**", 169 | "$(SRCROOT)/../../../../node_modules/react-native/React/**", 170 | ); 171 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 172 | MTL_ENABLE_DEBUG_INFO = YES; 173 | ONLY_ACTIVE_ARCH = YES; 174 | SDKROOT = iphoneos; 175 | }; 176 | name = Debug; 177 | }; 178 | 32285F4F1BFC01E400AD8363 /* Release */ = { 179 | isa = XCBuildConfiguration; 180 | buildSettings = { 181 | ALWAYS_SEARCH_USER_PATHS = NO; 182 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 183 | CLANG_CXX_LIBRARY = "libc++"; 184 | CLANG_ENABLE_MODULES = YES; 185 | CLANG_ENABLE_OBJC_ARC = YES; 186 | CLANG_WARN_BOOL_CONVERSION = YES; 187 | CLANG_WARN_CONSTANT_CONVERSION = YES; 188 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 189 | CLANG_WARN_EMPTY_BODY = YES; 190 | CLANG_WARN_ENUM_CONVERSION = YES; 191 | CLANG_WARN_INT_CONVERSION = YES; 192 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 193 | CLANG_WARN_UNREACHABLE_CODE = YES; 194 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 195 | COPY_PHASE_STRIP = NO; 196 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 197 | ENABLE_NS_ASSERTIONS = NO; 198 | ENABLE_STRICT_OBJC_MSGSEND = YES; 199 | GCC_C_LANGUAGE_STANDARD = gnu99; 200 | GCC_NO_COMMON_BLOCKS = YES; 201 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 202 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 203 | GCC_WARN_UNDECLARED_SELECTOR = YES; 204 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 205 | GCC_WARN_UNUSED_FUNCTION = YES; 206 | GCC_WARN_UNUSED_VARIABLE = YES; 207 | HEADER_SEARCH_PATHS = ( 208 | "$(inherited)", 209 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 210 | "$(SRCROOT)/../../../react-native/React/**", 211 | "$(SRCROOT)/../../../../node_modules/react-native/React/**", 212 | ); 213 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 214 | MTL_ENABLE_DEBUG_INFO = NO; 215 | SDKROOT = iphoneos; 216 | VALIDATE_PRODUCT = YES; 217 | }; 218 | name = Release; 219 | }; 220 | 32285F511BFC01E400AD8363 /* Debug */ = { 221 | isa = XCBuildConfiguration; 222 | buildSettings = { 223 | HEADER_SEARCH_PATHS = ( 224 | "$(inherited)", 225 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 226 | "$(SRCROOT)/../../react-native-cordova/ios/RCTCordova", 227 | ); 228 | OTHER_LDFLAGS = "-ObjC"; 229 | PRODUCT_NAME = "$(TARGET_NAME)"; 230 | SKIP_INSTALL = YES; 231 | }; 232 | name = Debug; 233 | }; 234 | 32285F521BFC01E400AD8363 /* Release */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | HEADER_SEARCH_PATHS = ( 238 | "$(inherited)", 239 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 240 | "$(SRCROOT)/../../react-native-cordova/ios/RCTCordova", 241 | ); 242 | OTHER_LDFLAGS = "-ObjC"; 243 | PRODUCT_NAME = "$(TARGET_NAME)"; 244 | SKIP_INSTALL = YES; 245 | }; 246 | name = Release; 247 | }; 248 | /* End XCBuildConfiguration section */ 249 | 250 | /* Begin XCConfigurationList section */ 251 | 32285F371BFC01E400AD8363 /* Build configuration list for PBXProject "RCTDialogs" */ = { 252 | isa = XCConfigurationList; 253 | buildConfigurations = ( 254 | 32285F4E1BFC01E400AD8363 /* Debug */, 255 | 32285F4F1BFC01E400AD8363 /* Release */, 256 | ); 257 | defaultConfigurationIsVisible = 0; 258 | defaultConfigurationName = Release; 259 | }; 260 | 32285F501BFC01E400AD8363 /* Build configuration list for PBXNativeTarget "RCTDialogs" */ = { 261 | isa = XCConfigurationList; 262 | buildConfigurations = ( 263 | 32285F511BFC01E400AD8363 /* Debug */, 264 | 32285F521BFC01E400AD8363 /* Release */, 265 | ); 266 | defaultConfigurationIsVisible = 0; 267 | defaultConfigurationName = Release; 268 | }; 269 | /* End XCConfigurationList section */ 270 | }; 271 | rootObject = 32285F341BFC01E400AD8363 /* Project object */; 272 | } 273 | -------------------------------------------------------------------------------- /ios/RCTDialogs/CDVNotification.m: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import "CDVNotification.h" 21 | 22 | #define DIALOG_TYPE_ALERT @"alert" 23 | #define DIALOG_TYPE_PROMPT @"prompt" 24 | 25 | static void soundCompletionCallback(SystemSoundID ssid, void* data); 26 | static NSMutableArray *alertList = nil; 27 | 28 | @implementation CDVNotification 29 | 30 | RCT_EXPORT_MODULE(Notification) 31 | 32 | RCT_EXPORT_CORDOVA_METHOD(alert); 33 | RCT_EXPORT_CORDOVA_METHOD(confirm); 34 | RCT_EXPORT_CORDOVA_METHOD(prompt); 35 | RCT_EXPORT_CORDOVA_METHOD(beep); 36 | 37 | /* 38 | * showDialogWithMessage - Common method to instantiate the alert view for alert, confirm, and prompt notifications. 39 | * Parameters: 40 | * message The alert view message. 41 | * title The alert view title. 42 | * buttons The array of customized strings for the buttons. 43 | * defaultText The input text for the textbox (if textbox exists). 44 | * callbackId The commmand callback id. 45 | * dialogType The type of alert view [alert | prompt]. 46 | */ 47 | - (void)showDialogWithMessage:(NSString*)message title:(NSString*)title buttons:(NSArray*)buttons defaultText:(NSString*)defaultText callbackId:(NSString*)callbackId dialogType:(NSString*)dialogType 48 | { 49 | 50 | int count = (int)[buttons count]; 51 | #ifdef __IPHONE_8_0 52 | if (NSClassFromString(@"UIAlertController")) { 53 | 54 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; 55 | 56 | if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.3) { 57 | 58 | CGRect alertFrame = [UIScreen mainScreen].applicationFrame; 59 | 60 | if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) { 61 | // swap the values for the app frame since it is now in landscape 62 | CGFloat temp = alertFrame.size.width; 63 | alertFrame.size.width = alertFrame.size.height; 64 | alertFrame.size.height = temp; 65 | } 66 | 67 | alertController.view.frame = alertFrame; 68 | } 69 | 70 | __weak CDVNotification* weakNotif = self; 71 | 72 | for (int n = 0; n < count; n++) { 73 | [alertController addAction:[UIAlertAction actionWithTitle:[buttons objectAtIndex:n] 74 | style:UIAlertActionStyleDefault 75 | handler:^(UIAlertAction * action) 76 | { 77 | CDVPluginResult* result; 78 | 79 | if ([dialogType isEqualToString:DIALOG_TYPE_PROMPT]) 80 | { 81 | NSString* value0 = [[alertController.textFields objectAtIndex:0] text]; 82 | NSDictionary* info = @{ 83 | @"buttonIndex":@(n + 1), 84 | @"input1":(value0 ? value0 : [NSNull null]) 85 | }; 86 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:info]; 87 | } 88 | else 89 | { 90 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)(n + 1)]; 91 | } 92 | 93 | [weakNotif.commandDelegate sendPluginResult:result callbackId:callbackId]; 94 | }]]; 95 | } 96 | 97 | if ([dialogType isEqualToString:DIALOG_TYPE_PROMPT]) { 98 | 99 | [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { 100 | textField.text = defaultText; 101 | }]; 102 | } 103 | 104 | if(!alertList) 105 | alertList = [[NSMutableArray alloc] init]; 106 | [alertList addObject:alertController]; 107 | 108 | if ([alertList count]==1) { 109 | [self presentAlertcontroller]; 110 | } 111 | 112 | } 113 | else 114 | { 115 | #endif 116 | 117 | CDVAlertView* alertView = [[CDVAlertView alloc] 118 | initWithTitle:title 119 | message:message 120 | delegate:self 121 | cancelButtonTitle:nil 122 | otherButtonTitles:nil]; 123 | 124 | alertView.callbackId = callbackId; 125 | 126 | 127 | 128 | for (int n = 0; n < count; n++) { 129 | [alertView addButtonWithTitle:[buttons objectAtIndex:n]]; 130 | } 131 | 132 | if ([dialogType isEqualToString:DIALOG_TYPE_PROMPT]) { 133 | alertView.alertViewStyle = UIAlertViewStylePlainTextInput; 134 | UITextField* textField = [alertView textFieldAtIndex:0]; 135 | textField.text = defaultText; 136 | } 137 | 138 | [alertView show]; 139 | #ifdef __IPHONE_8_0 140 | } 141 | #endif 142 | 143 | } 144 | 145 | - (void)alert:(CDVInvokedUrlCommand*)command 146 | { 147 | NSString* callbackId = command.callbackId; 148 | NSString* message = [command argumentAtIndex:0]; 149 | NSString* title = [command argumentAtIndex:1]; 150 | NSString* buttons = [command argumentAtIndex:2]; 151 | 152 | [self showDialogWithMessage:message title:title buttons:@[buttons] defaultText:nil callbackId:callbackId dialogType:DIALOG_TYPE_ALERT]; 153 | } 154 | 155 | - (void)confirm:(CDVInvokedUrlCommand*)command 156 | { 157 | NSString* callbackId = command.callbackId; 158 | NSString* message = [command argumentAtIndex:0]; 159 | NSString* title = [command argumentAtIndex:1]; 160 | NSArray* buttons = [command argumentAtIndex:2]; 161 | 162 | [self showDialogWithMessage:message title:title buttons:buttons defaultText:nil callbackId:callbackId dialogType:DIALOG_TYPE_ALERT]; 163 | } 164 | 165 | - (void)prompt:(CDVInvokedUrlCommand*)command 166 | { 167 | NSString* callbackId = command.callbackId; 168 | NSString* message = [command argumentAtIndex:0]; 169 | NSString* title = [command argumentAtIndex:1]; 170 | NSArray* buttons = [command argumentAtIndex:2]; 171 | NSString* defaultText = [command argumentAtIndex:3]; 172 | 173 | [self showDialogWithMessage:message title:title buttons:buttons defaultText:defaultText callbackId:callbackId dialogType:DIALOG_TYPE_PROMPT]; 174 | } 175 | 176 | /** 177 | * Callback invoked when an alert dialog's buttons are clicked. 178 | */ 179 | - (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 180 | { 181 | CDVAlertView* cdvAlertView = (CDVAlertView*)alertView; 182 | CDVPluginResult* result; 183 | 184 | // Determine what gets returned to JS based on the alert view type. 185 | if (alertView.alertViewStyle == UIAlertViewStyleDefault) { 186 | // For alert and confirm, return button index as int back to JS. 187 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)(buttonIndex + 1)]; 188 | } else { 189 | // For prompt, return button index and input text back to JS. 190 | NSString* value0 = [[alertView textFieldAtIndex:0] text]; 191 | NSDictionary* info = @{ 192 | @"buttonIndex":@(buttonIndex + 1), 193 | @"input1":(value0 ? value0 : [NSNull null]) 194 | }; 195 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:info]; 196 | } 197 | [self.commandDelegate sendPluginResult:result callbackId:cdvAlertView.callbackId]; 198 | } 199 | 200 | - (void)didPresentAlertView:(UIAlertView*)alertView 201 | { 202 | //show keyboard on iOS 8 203 | if (alertView.alertViewStyle == UIAlertViewStylePlainTextInput){ 204 | [[alertView textFieldAtIndex:0] selectAll:nil]; 205 | } 206 | } 207 | 208 | static void playBeep(int count) { 209 | SystemSoundID completeSound; 210 | NSInteger cbDataCount = count; 211 | NSURL* audioPath = [[NSBundle mainBundle] URLForResource:@"CDVNotification.bundle/beep" withExtension:@"wav"]; 212 | #if __has_feature(objc_arc) 213 | AudioServicesCreateSystemSoundID((__bridge CFURLRef)audioPath, &completeSound); 214 | #else 215 | AudioServicesCreateSystemSoundID((CFURLRef)audioPath, &completeSound); 216 | #endif 217 | AudioServicesAddSystemSoundCompletion(completeSound, NULL, NULL, soundCompletionCallback, (void*)(cbDataCount-1)); 218 | AudioServicesPlaySystemSound(completeSound); 219 | } 220 | 221 | static void soundCompletionCallback(SystemSoundID ssid, void* data) { 222 | int count = (int)data; 223 | AudioServicesRemoveSystemSoundCompletion (ssid); 224 | AudioServicesDisposeSystemSoundID(ssid); 225 | if (count > 0) { 226 | playBeep(count); 227 | } 228 | } 229 | 230 | - (void)beep:(CDVInvokedUrlCommand*)command 231 | { 232 | NSNumber* count = [command argumentAtIndex:0 withDefault:[NSNumber numberWithInt:1]]; 233 | playBeep([count intValue]); 234 | } 235 | 236 | -(UIViewController *)getTopPresentedViewController { 237 | UIViewController *presentingViewController = self.viewController; 238 | while(presentingViewController.presentedViewController != nil && ![presentingViewController.presentedViewController isBeingDismissed]) 239 | { 240 | presentingViewController = presentingViewController.presentedViewController; 241 | } 242 | return presentingViewController; 243 | } 244 | 245 | -(void)presentAlertcontroller { 246 | [self.commandDelegate runInUIThread:^{ 247 | __weak CDVNotification* weakNotif = self; 248 | [self.getTopPresentedViewController presentViewController:[alertList firstObject] animated:YES completion:^{ 249 | [alertList removeObject:[alertList firstObject]]; 250 | if ([alertList count]>0) { 251 | [weakNotif presentAlertcontroller]; 252 | } 253 | }]; 254 | }]; 255 | } 256 | 257 | @end 258 | 259 | @implementation CDVAlertView 260 | 261 | @synthesize callbackId; 262 | 263 | @end 264 | -------------------------------------------------------------------------------- /android/src/main/java/com/remobile/dialogs/Notification.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package com.remobile.dialogs; 20 | 21 | import org.json.JSONArray; 22 | import org.json.JSONException; 23 | import org.json.JSONObject; 24 | 25 | import android.annotation.SuppressLint; 26 | import android.app.Activity; 27 | import android.app.AlertDialog; 28 | import android.app.AlertDialog.Builder; 29 | import android.app.ProgressDialog; 30 | import android.content.DialogInterface; 31 | import android.content.res.Resources; 32 | import android.media.Ringtone; 33 | import android.media.RingtoneManager; 34 | import android.net.Uri; 35 | import android.widget.EditText; 36 | import android.widget.TextView; 37 | 38 | import com.facebook.common.logging.FLog; 39 | import com.remobile.cordova.*; 40 | import com.facebook.react.bridge.*; 41 | 42 | /** 43 | * This class provides access to notifications on the device. 44 | *

45 | * Be aware that this implementation gets called on 46 | * navigator.notification.{alert|confirm|prompt}, and that there is a separate 47 | * implementation in org.apache.cordova.CordovaChromeClient that gets 48 | * called on a simple window.{alert|confirm|prompt}. 49 | */ 50 | public class Notification extends CordovaPlugin { 51 | 52 | public int confirmResult = -1; 53 | public ProgressDialog spinnerDialog = null; 54 | public ProgressDialog progressDialog = null; 55 | 56 | public static String LOG_TAG = "Notification"; 57 | 58 | public Notification(ReactApplicationContext reactContext) { 59 | super(reactContext); 60 | } 61 | 62 | @Override 63 | public String getName() { return "Notification"; } 64 | 65 | @ReactMethod 66 | public void beep(ReadableArray args, Callback success, Callback error) { 67 | executeReactMethod("beep", args, success, error); 68 | } 69 | 70 | @ReactMethod 71 | public void alert(ReadableArray args, Callback success, Callback error) { 72 | executeReactMethod("alert", args, success, error); 73 | } 74 | 75 | @ReactMethod 76 | public void confirm(ReadableArray args, Callback success, Callback error) { 77 | executeReactMethod("confirm", args, success, error); 78 | } 79 | 80 | @ReactMethod 81 | public void prompt(ReadableArray args, Callback success, Callback error) { 82 | executeReactMethod("prompt", args, success, error); 83 | } 84 | 85 | @ReactMethod 86 | public void activityStart(ReadableArray args, Callback success, Callback error) { 87 | executeReactMethod("activityStart", args, success, error); 88 | } 89 | 90 | @ReactMethod 91 | public void activityStop(ReadableArray args, Callback success, Callback error) { 92 | executeReactMethod("activityStop", args, success, error); 93 | } 94 | 95 | @ReactMethod 96 | public void progressStart(ReadableArray args, Callback success, Callback error) { 97 | executeReactMethod("progressStart", args, success, error); 98 | } 99 | 100 | @ReactMethod 101 | public void progressValue(ReadableArray args, Callback success, Callback error) { 102 | executeReactMethod("progressValue", args, success, error); 103 | } 104 | 105 | @ReactMethod 106 | public void progressStop(ReadableArray args, Callback success, Callback error) { 107 | executeReactMethod("progressStop", args, success, error); 108 | } 109 | 110 | /** 111 | * Executes the request and returns PluginResult. 112 | * 113 | * @param action The action to execute. 114 | * @param args JSONArray of arguments for the plugin. 115 | * @param callbackContext The callback context used when calling back into JavaScript. 116 | * @return True when the action was valid, false otherwise. 117 | */ 118 | @Override 119 | public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { 120 | /* 121 | * Don't run any of these if the current activity is finishing 122 | * in order to avoid android.view.WindowManager$BadTokenException 123 | * crashing the app. Just return true here since false should only 124 | * be returned in the event of an invalid action. 125 | */ 126 | if (this.cordova.getActivity().isFinishing()) return true; 127 | 128 | if (action.equals("beep")) { 129 | this.beep(args.getLong(0)); 130 | } else if (action.equals("alert")) { 131 | this.alert(args.getString(0), args.getString(1), args.getString(2), callbackContext); 132 | return true; 133 | } else if (action.equals("confirm")) { 134 | this.confirm(args.getString(0), args.getString(1), args.getJSONArray(2), callbackContext); 135 | return true; 136 | } else if (action.equals("prompt")) { 137 | this.prompt(args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), callbackContext); 138 | return true; 139 | } else if (action.equals("activityStart")) { 140 | this.activityStart(args.getString(0), args.getString(1)); 141 | } else if (action.equals("activityStop")) { 142 | this.activityStop(); 143 | } else if (action.equals("progressStart")) { 144 | this.progressStart(args.getString(0), args.getString(1)); 145 | } else if (action.equals("progressValue")) { 146 | this.progressValue(args.getInt(0)); 147 | } else if (action.equals("progressStop")) { 148 | this.progressStop(); 149 | } else { 150 | return false; 151 | } 152 | 153 | // Only alert and confirm are async. 154 | callbackContext.success(); 155 | return true; 156 | } 157 | 158 | //-------------------------------------------------------------------------- 159 | // LOCAL METHODS 160 | //-------------------------------------------------------------------------- 161 | 162 | /** 163 | * Beep plays the default notification ringtone. 164 | * 165 | * @param count Number of times to play notification 166 | */ 167 | public void beep(final long count) { 168 | cordova.getThreadPool().execute(new Runnable() { 169 | public void run() { 170 | Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); 171 | Ringtone notification = RingtoneManager.getRingtone(cordova.getActivity().getBaseContext(), ringtone); 172 | 173 | // If phone is not set to silent mode 174 | if (notification != null) { 175 | for (long i = 0; i < count; ++i) { 176 | notification.play(); 177 | long timeout = 5000; 178 | while (notification.isPlaying() && (timeout > 0)) { 179 | timeout = timeout - 100; 180 | try { 181 | Thread.sleep(100); 182 | } catch (InterruptedException e) { 183 | Thread.currentThread().interrupt(); 184 | } 185 | } 186 | } 187 | } 188 | } 189 | }); 190 | } 191 | 192 | /** 193 | * Builds and shows a native Android alert with given Strings 194 | * @param message The message the alert should display 195 | * @param title The title of the alert 196 | * @param buttonLabel The label of the button 197 | * @param callbackContext The callback context 198 | */ 199 | public synchronized void alert(final String message, final String title, final String buttonLabel, final CallbackContext callbackContext) { 200 | final CordovaInterface cordova = this.cordova; 201 | 202 | Runnable runnable = new Runnable() { 203 | public void run() { 204 | 205 | AlertDialog.Builder dlg = createDialog(cordova); // new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); 206 | dlg.setMessage(message); 207 | dlg.setTitle(title); 208 | dlg.setCancelable(true); 209 | dlg.setPositiveButton(buttonLabel, 210 | new AlertDialog.OnClickListener() { 211 | public void onClick(DialogInterface dialog, int which) { 212 | dialog.dismiss(); 213 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 0)); 214 | } 215 | }); 216 | dlg.setOnCancelListener(new AlertDialog.OnCancelListener() { 217 | public void onCancel(DialogInterface dialog) 218 | { 219 | dialog.dismiss(); 220 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 0)); 221 | } 222 | }); 223 | 224 | changeTextDirection(dlg); 225 | }; 226 | }; 227 | this.cordova.getActivity().runOnUiThread(runnable); 228 | } 229 | 230 | /** 231 | * Builds and shows a native Android confirm dialog with given title, message, buttons. 232 | * This dialog only shows up to 3 buttons. Any labels after that will be ignored. 233 | * The index of the button pressed will be returned to the JavaScript callback identified by callbackId. 234 | * 235 | * @param message The message the dialog should display 236 | * @param title The title of the dialog 237 | * @param buttonLabels A comma separated list of button labels (Up to 3 buttons) 238 | * @param callbackContext The callback context. 239 | */ 240 | public synchronized void confirm(final String message, final String title, final JSONArray buttonLabels, final CallbackContext callbackContext) { 241 | final CordovaInterface cordova = this.cordova; 242 | 243 | Runnable runnable = new Runnable() { 244 | public void run() { 245 | AlertDialog.Builder dlg = createDialog(cordova); // new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); 246 | dlg.setMessage(message); 247 | dlg.setTitle(title); 248 | dlg.setCancelable(true); 249 | 250 | // First button 251 | if (buttonLabels.length() > 0) { 252 | try { 253 | dlg.setNegativeButton(buttonLabels.getString(0), 254 | new AlertDialog.OnClickListener() { 255 | public void onClick(DialogInterface dialog, int which) { 256 | dialog.dismiss(); 257 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 1)); 258 | } 259 | }); 260 | } catch (JSONException e) { 261 | LOG.d(LOG_TAG,"JSONException on first button."); 262 | } 263 | } 264 | 265 | // Second button 266 | if (buttonLabels.length() > 1) { 267 | try { 268 | dlg.setNeutralButton(buttonLabels.getString(1), 269 | new AlertDialog.OnClickListener() { 270 | public void onClick(DialogInterface dialog, int which) { 271 | dialog.dismiss(); 272 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 2)); 273 | } 274 | }); 275 | } catch (JSONException e) { 276 | LOG.d(LOG_TAG,"JSONException on second button."); 277 | } 278 | } 279 | 280 | // Third button 281 | if (buttonLabels.length() > 2) { 282 | try { 283 | dlg.setPositiveButton(buttonLabels.getString(2), 284 | new AlertDialog.OnClickListener() { 285 | public void onClick(DialogInterface dialog, int which) { 286 | dialog.dismiss(); 287 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 3)); 288 | } 289 | }); 290 | } catch (JSONException e) { 291 | LOG.d(LOG_TAG,"JSONException on third button."); 292 | } 293 | } 294 | dlg.setOnCancelListener(new AlertDialog.OnCancelListener() { 295 | public void onCancel(DialogInterface dialog) 296 | { 297 | dialog.dismiss(); 298 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 0)); 299 | } 300 | }); 301 | 302 | changeTextDirection(dlg); 303 | }; 304 | }; 305 | this.cordova.getActivity().runOnUiThread(runnable); 306 | } 307 | 308 | /** 309 | * Builds and shows a native Android prompt dialog with given title, message, buttons. 310 | * This dialog only shows up to 3 buttons. Any labels after that will be ignored. 311 | * The following results are returned to the JavaScript callback identified by callbackId: 312 | * buttonIndex Index number of the button selected 313 | * input1 The text entered in the prompt dialog box 314 | * 315 | * @param message The message the dialog should display 316 | * @param title The title of the dialog 317 | * @param buttonLabels A comma separated list of button labels (Up to 3 buttons) 318 | * @param callbackContext The callback context. 319 | */ 320 | public synchronized void prompt(final String message, final String title, final JSONArray buttonLabels, final String defaultText, final CallbackContext callbackContext) { 321 | 322 | final CordovaInterface cordova = this.cordova; 323 | 324 | Runnable runnable = new Runnable() { 325 | public void run() { 326 | final EditText promptInput = new EditText(cordova.getActivity()); 327 | 328 | /* CB-11677 - By default, prompt input text color is set according current theme. 329 | But for some android versions is not visible (for example 5.1.1). 330 | android.R.color.primary_text_light will make text visible on all versions. */ 331 | Resources resources = cordova.getActivity().getResources(); 332 | int promptInputTextColor = resources.getColor(android.R.color.primary_text_light); 333 | promptInput.setTextColor(promptInputTextColor); 334 | promptInput.setText(defaultText); 335 | AlertDialog.Builder dlg = createDialog(cordova); // new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); 336 | dlg.setMessage(message); 337 | dlg.setTitle(title); 338 | dlg.setCancelable(true); 339 | 340 | dlg.setView(promptInput); 341 | 342 | final JSONObject result = new JSONObject(); 343 | 344 | // First button 345 | if (buttonLabels.length() > 0) { 346 | try { 347 | dlg.setNegativeButton(buttonLabels.getString(0), 348 | new AlertDialog.OnClickListener() { 349 | public void onClick(DialogInterface dialog, int which) { 350 | dialog.dismiss(); 351 | try { 352 | result.put("buttonIndex",1); 353 | result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); 354 | } catch (JSONException e) { 355 | LOG.d(LOG_TAG,"JSONException on first button.", e); 356 | } 357 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); 358 | } 359 | }); 360 | } catch (JSONException e) { 361 | LOG.d(LOG_TAG,"JSONException on first button."); 362 | } 363 | } 364 | 365 | // Second button 366 | if (buttonLabels.length() > 1) { 367 | try { 368 | dlg.setNeutralButton(buttonLabels.getString(1), 369 | new AlertDialog.OnClickListener() { 370 | public void onClick(DialogInterface dialog, int which) { 371 | dialog.dismiss(); 372 | try { 373 | result.put("buttonIndex",2); 374 | result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); 375 | } catch (JSONException e) { 376 | LOG.d(LOG_TAG,"JSONException on second button.", e); 377 | } 378 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); 379 | } 380 | }); 381 | } catch (JSONException e) { 382 | LOG.d(LOG_TAG,"JSONException on second button."); 383 | } 384 | } 385 | 386 | // Third button 387 | if (buttonLabels.length() > 2) { 388 | try { 389 | dlg.setPositiveButton(buttonLabels.getString(2), 390 | new AlertDialog.OnClickListener() { 391 | public void onClick(DialogInterface dialog, int which) { 392 | dialog.dismiss(); 393 | try { 394 | result.put("buttonIndex",3); 395 | result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); 396 | } catch (JSONException e) { 397 | LOG.d(LOG_TAG,"JSONException on third button.", e); 398 | } 399 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); 400 | } 401 | }); 402 | } catch (JSONException e) { 403 | LOG.d(LOG_TAG,"JSONException on third button."); 404 | } 405 | } 406 | dlg.setOnCancelListener(new AlertDialog.OnCancelListener() { 407 | public void onCancel(DialogInterface dialog){ 408 | dialog.dismiss(); 409 | try { 410 | result.put("buttonIndex",0); 411 | result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); 412 | } catch (JSONException e) { e.printStackTrace(); } 413 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); 414 | } 415 | }); 416 | 417 | changeTextDirection(dlg); 418 | }; 419 | }; 420 | this.cordova.getActivity().runOnUiThread(runnable); 421 | } 422 | 423 | /** 424 | * Show the spinner. 425 | * 426 | * @param title Title of the dialog 427 | * @param message The message of the dialog 428 | */ 429 | public synchronized void activityStart(final String title, final String message) { 430 | if (this.spinnerDialog != null) { 431 | this.spinnerDialog.dismiss(); 432 | this.spinnerDialog = null; 433 | } 434 | final Notification notification = this; 435 | final CordovaInterface cordova = this.cordova; 436 | Runnable runnable = new Runnable() { 437 | public void run() { 438 | notification.spinnerDialog = createProgressDialog(cordova); // new ProgressDialog(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); 439 | notification.spinnerDialog.setTitle(title); 440 | notification.spinnerDialog.setMessage(message); 441 | notification.spinnerDialog.setCancelable(true); 442 | notification.spinnerDialog.setIndeterminate(true); 443 | notification.spinnerDialog.setOnCancelListener( 444 | new DialogInterface.OnCancelListener() { 445 | public void onCancel(DialogInterface dialog) { 446 | notification.spinnerDialog = null; 447 | } 448 | }); 449 | notification.spinnerDialog.show(); 450 | } 451 | }; 452 | this.cordova.getActivity().runOnUiThread(runnable); 453 | } 454 | 455 | /** 456 | * Stop spinner. 457 | */ 458 | public synchronized void activityStop() { 459 | if (this.spinnerDialog != null) { 460 | this.spinnerDialog.dismiss(); 461 | this.spinnerDialog = null; 462 | } 463 | } 464 | 465 | /** 466 | * Show the progress dialog. 467 | * 468 | * @param title Title of the dialog 469 | * @param message The message of the dialog 470 | */ 471 | public synchronized void progressStart(final String title, final String message) { 472 | if (this.progressDialog != null) { 473 | this.progressDialog.dismiss(); 474 | this.progressDialog = null; 475 | } 476 | final Notification notification = this; 477 | final CordovaInterface cordova = this.cordova; 478 | Runnable runnable = new Runnable() { 479 | public void run() { 480 | notification.progressDialog = createProgressDialog(cordova); // new ProgressDialog(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); 481 | notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 482 | notification.progressDialog.setTitle(title); 483 | notification.progressDialog.setMessage(message); 484 | notification.progressDialog.setCancelable(true); 485 | notification.progressDialog.setMax(100); 486 | notification.progressDialog.setProgress(0); 487 | notification.progressDialog.setOnCancelListener( 488 | new DialogInterface.OnCancelListener() { 489 | public void onCancel(DialogInterface dialog) { 490 | notification.progressDialog = null; 491 | } 492 | }); 493 | notification.progressDialog.show(); 494 | } 495 | }; 496 | this.cordova.getActivity().runOnUiThread(runnable); 497 | } 498 | 499 | /** 500 | * Set value of progress bar. 501 | * 502 | * @param value 0-100 503 | */ 504 | public synchronized void progressValue(int value) { 505 | if (this.progressDialog != null) { 506 | this.progressDialog.setProgress(value); 507 | } 508 | } 509 | 510 | /** 511 | * Stop progress dialog. 512 | */ 513 | public synchronized void progressStop() { 514 | if (this.progressDialog != null) { 515 | this.progressDialog.dismiss(); 516 | this.progressDialog = null; 517 | } 518 | } 519 | 520 | @SuppressLint("NewApi") 521 | private AlertDialog.Builder createDialog(CordovaInterface cordova) { 522 | int currentapiVersion = android.os.Build.VERSION.SDK_INT; 523 | if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) { 524 | return new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); 525 | } else { 526 | return new AlertDialog.Builder(cordova.getActivity()); 527 | } 528 | } 529 | 530 | @SuppressLint("InlinedApi") 531 | private ProgressDialog createProgressDialog(CordovaInterface cordova) { 532 | int currentapiVersion = android.os.Build.VERSION.SDK_INT; 533 | if (currentapiVersion >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 534 | return new ProgressDialog(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); 535 | } else { 536 | return new ProgressDialog(cordova.getActivity()); 537 | } 538 | } 539 | 540 | @SuppressLint("NewApi") 541 | private void changeTextDirection(Builder dlg){ 542 | int currentapiVersion = android.os.Build.VERSION.SDK_INT; 543 | dlg.create(); 544 | AlertDialog dialog = dlg.show(); 545 | if (currentapiVersion >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { 546 | TextView messageview = (TextView)dialog.findViewById(android.R.id.message); 547 | messageview.setTextDirection(android.view.View.TEXT_DIRECTION_LOCALE); 548 | } 549 | } 550 | } 551 | --------------------------------------------------------------------------------