diff --git a/.circleci/config.yml b/.circleci/config.yml index b94c9d0eb..31cacf956 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,19 +7,9 @@ jobs: steps: - checkout - install-cocoapods: - macos: - xcode: "10.0" - working_directory: /tmp/workspace - steps: - - run: - name: Install CocoaPods - command: | - curl https://cocoapods-specs.circleci.com/fetch-cocoapods-repo-from-s3.sh | bash -s cf - run-cli-tests: macos: - xcode: "10.0" + xcode: "11.1.0" working_directory: /tmp/workspace steps: @@ -39,7 +29,7 @@ jobs: build-ios: macos: - xcode: "10.0" + xcode: "11.1.0" working_directory: /tmp/workspace steps: @@ -51,7 +41,7 @@ jobs: build-android: docker: - - image: circleci/android:api-28-node8-alpha + - image: circleci/android:api-29-node working_directory: /tmp/workspace steps: @@ -65,12 +55,8 @@ workflows: node-ios-android: jobs: - get-cli - - install-cocoapods - run-cli-tests: requires: - get-cli - - install-cocoapods - - build-ios: - requires: - - install-cocoapods + - build-ios - build-android \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b8296282..9ddb921b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,60 @@ +## [1.5.0](https://github.com/ionic-team/capacitor/compare/1.4.0...1.5.0) (2020-02-03) + +### Bug Fixes + +* fix(web/clipboard): allow writing empty string (#2371) ([4a41922](https://github.com/ionic-team/capacitor/commit/4a41922)), closes [#2371](https://github.com/ionic-team/capacitor/issues/2371) +* fix(android): add missing GPS tags to exif data (#2284) ([3b43df1](https://github.com/ionic-team/capacitor/commit/3b43df1)), closes [#2284](https://github.com/ionic-team/capacitor/issues/2284) +* fix(android): implement getDeliveredNotifications and removeDeliveredNotifications (#2266) ([d942523](https://github.com/ionic-team/capacitor/commit/d942523)), closes [#2266](https://github.com/ionic-team/capacitor/issues/2266) +* fix(android): make Browser plugin fire browserFinished (#2332) ([4f5a4fc](https://github.com/ionic-team/capacitor/commit/4f5a4fc)), closes [#2332](https://github.com/ionic-team/capacitor/issues/2332) +* fix(android): make Share properly share file urls (#2338) ([9226d77](https://github.com/ionic-team/capacitor/commit/9226d77)), closes [#2338](https://github.com/ionic-team/capacitor/issues/2338) +* fix(cli): handle edit-config with merge mode on application object (#2322) ([9e56701](https://github.com/ionic-team/capacitor/commit/9e56701)), closes [#2322](https://github.com/ionic-team/capacitor/issues/2322) +* fix(cli): linux not showing error message on open (#2336) ([72d07e0](https://github.com/ionic-team/capacitor/commit/72d07e0)), closes [#2336](https://github.com/ionic-team/capacitor/issues/2336) +* fix(cli): move Android Studio detection to avoid displaying registry errors (#2364) ([60cd80b](https://github.com/ionic-team/capacitor/commit/60cd80b)), closes [#2364](https://github.com/ionic-team/capacitor/issues/2364) +* fix(cli): use proper kebab-case name for npm package (#2276) ([c9f1511](https://github.com/ionic-team/capacitor/commit/c9f1511)), closes [#2276](https://github.com/ionic-team/capacitor/issues/2276) +* fix(cli): use rimraf instead of rm -rf (#2285) ([ec458c8](https://github.com/ionic-team/capacitor/commit/ec458c8)), closes [#2285](https://github.com/ionic-team/capacitor/issues/2285) +* fix(cordova): add new iOS Swift CDVCommandStatus enums (#2328) ([45244d6](https://github.com/ionic-team/capacitor/commit/45244d6)), closes [#2328](https://github.com/ionic-team/capacitor/issues/2328) +* fix(cordova): avoid build failure if plugin uses viewController.webView (#2330) ([69f589b](https://github.com/ionic-team/capacitor/commit/69f589b)), closes [#2330](https://github.com/ionic-team/capacitor/issues/2330) +* fix(cordova): patch CDVCapture bundle path (#2342) ([3f4bd1a](https://github.com/ionic-team/capacitor/commit/3f4bd1a)), closes [#2342](https://github.com/ionic-team/capacitor/issues/2342) +* fix(ios): avoid lock of subsequent plugin calls (#2317) ([02da187](https://github.com/ionic-team/capacitor/commit/02da187)), closes [#2317](https://github.com/ionic-team/capacitor/issues/2317) +* fix(ios): fire appStateChange in incoming calls (#2282) ([7fd0c7c](https://github.com/ionic-team/capacitor/commit/7fd0c7c)), closes [#2282](https://github.com/ionic-team/capacitor/issues/2282) +* fix(ios): incorrect behavior of appendingPathComponent when framework is present (#2309) ([0a25cce](https://github.com/ionic-team/capacitor/commit/0a25cce)), closes [#2309](https://github.com/ionic-team/capacitor/issues/2309) + + +### Features + +* feat(ios/android): allow to position Toast (#2337) ([a1384d5](https://github.com/ionic-team/capacitor/commit/a1384d5)), closes [#2337](https://github.com/ionic-team/capacitor/issues/2337) +* feat(android): add group and groupSummary to LocalNotifications (#2385) ([8e8a157](https://github.com/ionic-team/capacitor/commit/8e8a157)), closes [#2385](https://github.com/ionic-team/capacitor/issues/2385) +* feat(android): add splashFullScreen configuration option (#2302) ([9521e0a](https://github.com/ionic-team/capacitor/commit/9521e0a)), closes [#2302](https://github.com/ionic-team/capacitor/issues/2302) +* feat(android): add support to custom sound on Push Notifications (#2362) ([284d4b2](https://github.com/ionic-team/capacitor/commit/284d4b2)), closes [#2362](https://github.com/ionic-team/capacitor/issues/2362) +* feat(cli): allow to modify cleartext setting from capacitor.config.json (#2397) ([181d564](https://github.com/ionic-team/capacitor/commit/181d564)), closes [#2397](https://github.com/ionic-team/capacitor/issues/2397) +* feat(ios): add configuration option for allowsLinkPreview (#2382) ([47b4d66](https://github.com/ionic-team/capacitor/commit/47b4d66)), closes [#2382](https://github.com/ionic-team/capacitor/issues/2382) +* feat(ios): add threadIdentifier and summaryArgument to LocalNotification (#2396) ([7c5f30b](https://github.com/ionic-team/capacitor/commit/7c5f30b)), closes [#2396](https://github.com/ionic-team/capacitor/issues/2396) +* feat(ios): Allow to configure WebView's ScrollView's content insets (#2392) ([1f7e40d](https://github.com/ionic-team/capacitor/commit/1f7e40d)), closes [#2392](https://github.com/ionic-team/capacitor/issues/2392) + + +### Docs + +* site updates ([64286f8](https://github.com/ionic-team/capacitor/commit/64286f8)) +* docs: add allowsLinkPreview configuration information (#2387) ([e603032](https://github.com/ionic-team/capacitor/commit/e603032)), closes [#2387](https://github.com/ionic-team/capacitor/issues/2387) +* docs: Add how to determine installed plugin version in project (#2319) ([580a236](https://github.com/ionic-team/capacitor/commit/580a236)), closes [#2319](https://github.com/ionic-team/capacitor/issues/2319) +* docs: fix broken link to Cordova project description (#2277) ([88ce7db](https://github.com/ionic-team/capacitor/commit/88ce7db)), closes [#2277](https://github.com/ionic-team/capacitor/issues/2277) +* docs(android-guide): fix typo (#2343) ([4475ed5](https://github.com/ionic-team/capacitor/commit/4475ed5)), closes [#2343](https://github.com/ionic-team/capacitor/issues/2343) +* docs(ce-plugins): add @rdlabo/capacitor-codescanner (#2344) ([b2522ca](https://github.com/ionic-team/capacitor/commit/b2522ca)), closes [#2344](https://github.com/ionic-team/capacitor/issues/2344) +* docs(ce-plugins): add Apple Login Plugin (#2267) ([663657d](https://github.com/ionic-team/capacitor/commit/663657d)), closes [#2267](https://github.com/ionic-team/capacitor/issues/2267) +* docs(ce-plugins): Add capacitor UDP plugin (#2314) ([e904eaa](https://github.com/ionic-team/capacitor/commit/e904eaa)), closes [#2314](https://github.com/ionic-team/capacitor/issues/2314) +* docs(ce-plugins): add capacitor-voice-recorder (#2378) ([9836d05](https://github.com/ionic-team/capacitor/commit/9836d05)), closes [#2378](https://github.com/ionic-team/capacitor/issues/2378) +* docs(ce-plugins): Update capacitor-admob plugin note (#2335) ([5aeb4e6](https://github.com/ionic-team/capacitor/commit/5aeb4e6)), closes [#2335](https://github.com/ionic-team/capacitor/issues/2335) +* docs(core): show array type instead of any (#2318) ([2b9fb4d](https://github.com/ionic-team/capacitor/commit/2b9fb4d)), closes [#2318](https://github.com/ionic-team/capacitor/issues/2318) +* docs(keyboard): Add Keyboard config info (#2245) ([3344af2](https://github.com/ionic-team/capacitor/commit/3344af2)), closes [#2245](https://github.com/ionic-team/capacitor/issues/2245) [#2243](https://github.com/ionic-team/capacitor/issues/2243) +* docs(readme): update for 2020 (#2341) ([2e24d8d](https://github.com/ionic-team/capacitor/commit/2e24d8d)), closes [#2341](https://github.com/ionic-team/capacitor/issues/2341) + + +### Chores + +* chore(cli): add interface for new plugin answers and use arrow function for input validation (#2286) ([0d2826e](https://github.com/ionic-team/capacitor/commit/0d2826e)), closes [#2286](https://github.com/ionic-team/capacitor/issues/2286) + + + ## [1.4.0](https://github.com/ionic-team/capacitor/compare/1.3.0...1.4.0) (2019-12-12) diff --git a/Capacitor.podspec b/Capacitor.podspec index fa181ce1e..013ad3ad1 100644 --- a/Capacitor.podspec +++ b/Capacitor.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Capacitor' - s.version = '1.4.0' + s.version = '1.5.0' s.summary = 'Capacitor for iOS' s.social_media_url = 'http://twitter.com/getcapacitor' s.license = 'MIT' @@ -9,6 +9,6 @@ Pod::Spec.new do |s| s.authors = { 'Ionic Team' => 'hi@ionicframework.com' } s.source = { :git => 'https://github.com/ionic-team/capacitor.git', :tag => s.version.to_s } s.source_files = 'ios/Capacitor/Capacitor/*.{swift,h,m}', 'ios/Capacitor/Capacitor/Plugins/*.{swift,h,m}', 'ios/Capacitor/Capacitor/Plugins/**/*.{swift,h,m}' - s.dependency 'CapacitorCordova', '1.4.0' + s.dependency 'CapacitorCordova', '1.5.0' s.swift_version = '4.2' end diff --git a/CapacitorCordova.podspec b/CapacitorCordova.podspec index 05e4aee48..a71034fa1 100644 --- a/CapacitorCordova.podspec +++ b/CapacitorCordova.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "CapacitorCordova" s.module_name = 'Cordova' - s.version = '1.4.0' + s.version = '1.5.0' s.summary = "Capacitor Cordova Compatibility Layer" s.homepage = "https://ionic-team.github.io/capacitor" s.license = 'MIT' diff --git a/README.md b/README.md index 01ab3ff1c..cee49cdad 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,22 @@ Capacitor is a cross-platform API and code execution layer that makes it easy to call Native SDKs from web code and to write custom Native plugins that your app might need. Additionally, Capacitor provides first-class Progressive Web App support so you can write one app and deploy it to the app stores, _and_ the mobile web. -Capacitor is being designed by the Ionic Framework team as an eventual alternative to Cordova, though backwards compatibility with Cordova plugins is a priority and is actively being worked on. Capacitor can be used without Ionic Framework, but soon it'll become a core part of the Ionic developer experience. +Capacitor was created by the Ionic Framework team as a spiritual successor to Cordova, though it does have backward compatibility with the majority of Cordova plugins. Capacitor can be used without [Ionic Framework](https://ionicframework.com/docs/components), but since it's a core part of the Ionic Platform, it's recommended for the best app development experience. -Capacitor also comes with a Plugin API for building native plugins. On iOS, first-class Swift support is available, and much of the iOS Capacitor runtime is written in Swift. Plugins may also be written in Objective-C. On Android, support for writing plugins with Java and Kotlin is supported. +Capacitor also comes with a Plugin API for building native plugins. On iOS, first-class Swift support is available, and much of the iOS Capacitor runtime is written in Swift. Plugins may also be written in Objective-C. On Android, writing plugins in Java and Kotlin is supported. ## Roadmap _Disclaimer: Our roadmap is subject to change at any time and has no specific date guarantees_ +2020 and beyond: The core Capacitor project is now stable. Maintenance is ongoing (including support for new mobile operating system versions, bugs, etc.). Going forward, most new functionality will be implemented as plugins. For the latest updates, track new releases [here](https://github.com/ionic-team/capacitor/releases) or milestones [here](https://github.com/ionic-team/capacitor/milestones). + [2019](https://blog.ionicframework.com/capacitor-in-2019-native-progressive-web-apps-for-all/) 2018 - __Cordova Plugin Integration__ - Preliminary support for using plugins from the existing Cordova community - - __Native Shell Add-ons__ - - Support for interacting with Native UI shell elements, such as native menus, tabs, and navigation, with 1-1 fallbacks to the web for first-class Progressive Web App and Electron support. - __Electron support__ - Support for building Electron apps and interacting with Node.js libraries - __Enterprise Premium Plugins__ diff --git a/android-template/app/build.gradle b/android-template/app/build.gradle index cf041a62a..d930d899c 100644 --- a/android-template/app/build.gradle +++ b/android-template/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "com.getcapacitor.app" minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/android-template/app/src/main/res/drawable/launch_splash.xml b/android-template/app/src/main/res/drawable/launch_splash.xml deleted file mode 100644 index 468688ef6..000000000 --- a/android-template/app/src/main/res/drawable/launch_splash.xml +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/android-template/build.gradle b/android-template/build.gradle index 937411e8f..300eb889f 100644 --- a/android-template/build.gradle +++ b/android-template/build.gradle @@ -7,8 +7,8 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.2' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.google.gms:google-services:4.3.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/android-template/gradle/wrapper/gradle-wrapper.properties b/android-template/gradle/wrapper/gradle-wrapper.properties index bf8d6baca..751633a2d 100644 --- a/android-template/gradle/wrapper/gradle-wrapper.properties +++ b/android-template/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/android/capacitor/build.gradle b/android/capacitor/build.gradle index 360549b79..c7ac7b382 100644 --- a/android/capacitor/build.gradle +++ b/android/capacitor/build.gradle @@ -4,7 +4,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.2' + classpath 'com.android.tools.build:gradle:3.5.3' classpath 'com.novoda:bintray-release:0.9.1' } } @@ -15,10 +15,10 @@ apply plugin: 'com.android.library' apply plugin: 'com.novoda.bintray-release' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -47,6 +47,7 @@ dependencies { implementation 'com.android.support:design:28.0.0' implementation 'com.android.support:customtabs:28.0.0' implementation 'com.google.firebase:firebase-messaging:18.0.0' + implementation 'com.google.android.gms:play-services-location:16.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' @@ -68,5 +69,3 @@ publish { desc = 'Capacitor Android Runtime' website = 'https://github.com/ionic-team/capacitor' } - - diff --git a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java index e225110b8..e082ac5c9 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java @@ -846,6 +846,15 @@ public void onStop() { } } + /** + * Handle onDestroy lifecycle event and notify the plugins + */ + public void onDestroy() { + for (PluginHandle plugin : plugins.values()) { + plugin.getInstance().handleOnDestroy(); + } + } + public void onBackPressed() { PluginHandle appHandle = getPlugin("App"); if (appHandle != null) { diff --git a/android/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java b/android/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java index 423bcc048..2df2882ea 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java +++ b/android/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java @@ -177,6 +177,7 @@ public void onStop() { @Override public void onDestroy() { super.onDestroy(); + this.bridge.onDestroy(); if (this.mockWebView != null) { mockWebView.handleDestroy(); } diff --git a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java index cedd7c7b9..94e325b8e 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java @@ -300,7 +300,7 @@ public void pluginRequestPermission(String permission, int requestCode) { */ private void addEventListener(String eventName, PluginCall call) { List listeners = eventListeners.get(eventName); - if (listeners == null) { + if (listeners == null || listeners.isEmpty()) { listeners = new ArrayList(); eventListeners.put(eventName, listeners); @@ -335,7 +335,7 @@ private void removeEventListener(String eventName, PluginCall call) { protected void notifyListeners(String eventName, JSObject data, boolean retainUntilConsumed) { Log.v(getLogTag(), "Notifying listeners for event " + eventName); List listeners = eventListeners.get(eventName); - if (listeners == null) { + if (listeners == null || listeners.isEmpty()) { Log.d(getLogTag(), "No listeners found for event " + eventName); if (retainUntilConsumed) { retainedEventArguments.put(eventName, data); @@ -532,6 +532,11 @@ protected void handleOnPause() {} */ protected void handleOnStop() {} + /** + * Handle onDestroy + */ + protected void handleOnDestroy() {} + /** * Start a new Activity. * diff --git a/android/capacitor/src/main/java/com/getcapacitor/Splash.java b/android/capacitor/src/main/java/com/getcapacitor/Splash.java index 1f8593abc..d8181e650 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Splash.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Splash.java @@ -33,6 +33,7 @@ public interface SplashListener { public static final int DEFAULT_FADE_OUT_DURATION = 200; public static final int DEFAULT_SHOW_DURATION = 3000; public static final boolean DEFAULT_AUTO_HIDE = true; + public static final boolean DEFAULT_SPLASH_FULL_SCREEN = false; private static ImageView splashImage; private static ProgressBar spinnerBar; @@ -52,7 +53,14 @@ private static void buildViews(Context c) { } splashImage = new ImageView(c); + + // Hide status bar during splash screen. + Boolean splashFullScreen = Config.getBoolean(CONFIG_KEY_PREFIX + "splashFullScreen", DEFAULT_SPLASH_FULL_SCREEN); + if(splashFullScreen){ + splashImage.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); + } + // Stops flickers dead in their tracks // https://stackoverflow.com/a/21847579/32140 splashImage.setDrawingCacheEnabled(true); diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Browser.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Browser.java index 4c635f299..d10698b6a 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Browser.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Browser.java @@ -31,6 +31,7 @@ public class Browser extends Plugin { private CustomTabsClient customTabsClient; private CustomTabsSession currentSession; + private boolean fireFinished = false; @PluginMethod() public void open(PluginCall call) { @@ -117,6 +118,9 @@ public void load() { } protected void handleOnResume() { + if (fireFinished) { + notifyListeners("browserFinished", new JSObject()); + } boolean ok = CustomTabsClient.bindCustomTabsService(getContext(), CUSTOM_TAB_PACKAGE_NAME, connection); if (!ok) { Log.e(getLogTag(), "Error binding to custom tabs service"); @@ -140,6 +144,12 @@ public void onNavigationEvent(int navigationEvent, Bundle extras) { case NAVIGATION_FINISHED: notifyListeners("browserPageLoaded", new JSObject()); break; + case TAB_HIDDEN: + fireFinished = true; + break; + case TAB_SHOWN: + fireFinished = false; + break; } } }); diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java index ccdba058e..6a4a5e091 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Camera.java @@ -1,6 +1,7 @@ package com.getcapacitor.plugin; import android.Manifest; +import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; @@ -53,7 +54,6 @@ public class Camera extends Plugin { static final int REQUEST_IMAGE_CAPTURE = PluginRequestCodes.CAMERA_IMAGE_CAPTURE; static final int REQUEST_IMAGE_PICK = PluginRequestCodes.CAMERA_IMAGE_PICK; static final int REQUEST_IMAGE_EDIT = PluginRequestCodes.CAMERA_IMAGE_EDIT; - // Message constants private static final String INVALID_RESULT_TYPE_ERROR = "Invalid resultType option"; private static final String PERMISSION_DENIED_ERROR = "Unable to access camera, user denied permission request"; @@ -221,7 +221,7 @@ public void openPhotos(final PluginCall call) { } } - public void processCameraImage(PluginCall call, Intent data) { + public void processCameraImage(PluginCall call) { boolean saveToGallery = call.getBoolean("saveToGallery", CameraSettings.DEFAULT_SAVE_IMAGE_TO_GALLERY); CameraResultType resultType = getResultType(call.getString("resultType")); if(imageFileSavePath == null) { @@ -468,12 +468,15 @@ protected void handleOnActivityResult(int requestCode, int resultCode, Intent da settings = getSettings(savedCall); if (requestCode == REQUEST_IMAGE_CAPTURE) { - processCameraImage(savedCall, data); + processCameraImage(savedCall); } else if (requestCode == REQUEST_IMAGE_PICK) { processPickedImage(savedCall, data); - } else if (requestCode == REQUEST_IMAGE_EDIT) { + } else if (requestCode == REQUEST_IMAGE_EDIT && resultCode == Activity.RESULT_OK) { isEdited = true; processPickedImage(savedCall, data); + } else if (resultCode == Activity.RESULT_CANCELED && imageFileSavePath != null) { + isEdited = true; + processCameraImage(savedCall); } } diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Device.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Device.java index 457843503..9858f974b 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Device.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Device.java @@ -35,9 +35,17 @@ public void getInfo(PluginCall call) { r.put("platform", getPlatform()); r.put("manufacturer", android.os.Build.MANUFACTURER); r.put("uuid", getUuid()); + r.put("isVirtual", isVirtual()); + + call.success(r); + } + + @PluginMethod() + public void getBatteryInfo(PluginCall call) { + JSObject r = new JSObject(); + r.put("batteryLevel", getBatteryLevel()); r.put("isCharging", isCharging()); - r.put("isVirtual", isVirtual()); call.success(r); } diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java index 7f7fdee03..90d12b0c2 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java @@ -326,10 +326,6 @@ public void mkdir(PluginCall call) { saveCall(call); String path = call.getString("path"); String directory = getDirectoryParameter(call); - boolean intermediate = call.getBoolean("createIntermediateDirectories", false).booleanValue(); - if (call.getBoolean("createIntermediateDirectories") != null) { - Log.w(getLogTag(),"createIntermediateDirectories is deprecated, use recursive"); - } boolean recursive = call.getBoolean("recursive", false).booleanValue(); File fileObject = getFileObject(path, directory); @@ -342,7 +338,7 @@ public void mkdir(PluginCall call) { if (!isPublicDirectory(directory) || isStoragePermissionGranted(PluginRequestCodes.FILESYSTEM_REQUEST_WRITE_FOLDER_PERMISSIONS, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { boolean created = false; - if (intermediate || recursive) { + if (recursive) { created = fileObject.mkdirs(); } else { created = fileObject.mkdir(); diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Geolocation.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Geolocation.java index 861b174d6..aa0638da1 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Geolocation.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Geolocation.java @@ -1,14 +1,9 @@ package com.getcapacitor.plugin; import android.Manifest; -import android.content.Context; import android.content.pm.PackageManager; -import android.location.Criteria; import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; import android.os.Build; -import android.os.Bundle; import com.getcapacitor.JSObject; import com.getcapacitor.NativePlugin; @@ -17,15 +12,17 @@ import com.getcapacitor.PluginMethod; import com.getcapacitor.PluginRequestCodes; +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.LocationAvailability; +import com.google.android.gms.location.LocationCallback; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationResult; +import com.google.android.gms.location.LocationServices; + import java.util.HashMap; -import java.util.List; import java.util.Map; -/** - * Geolocation plugin that uses the native location service instead of the browser API. - * - * https://developer.android.com/guide/topics/location/strategies.html - */ + @NativePlugin( permissions={ Manifest.permission.ACCESS_COARSE_LOCATION, @@ -34,30 +31,11 @@ permissionRequestCode = PluginRequestCodes.GEOLOCATION_REQUEST_PERMISSIONS ) public class Geolocation extends Plugin { - private LocationManager locationManager; - private LocationListener locationListener; - - Map watchingCalls = new HashMap<>(); - - public void load() { - locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE); - - locationListener = new LocationListener() { - @Override - public void onLocationChanged(Location location) { - processLocation(location); - } - @Override - public void onStatusChanged(String s, int i, Bundle bundle) {} + private Map watchingCalls = new HashMap<>(); + private FusedLocationProviderClient fusedLocationClient; + private LocationCallback locationCallback; - @Override - public void onProviderEnabled(String s) {} - - @Override - public void onProviderDisabled(String s) {} - }; - } @PluginMethod() public void getCurrentPosition(PluginCall call) { @@ -70,13 +48,7 @@ public void getCurrentPosition(PluginCall call) { } private void sendLocation(PluginCall call) { - String provider = getBestProviderForCall(call); - Location lastLocation = getBestLocation(provider); - if (lastLocation == null) { - call.error("location unavailable"); - } else { - call.success(getJSObjectForLocation(lastLocation)); - } + requestLocationUpdates(call); } @PluginMethod(returnType=PluginMethod.RETURN_CALLBACK) @@ -92,9 +64,7 @@ public void watchPosition(PluginCall call) { @SuppressWarnings("MissingPermission") private void startWatch(PluginCall call) { - String provider = getBestProviderForCall(call); - locationManager.requestLocationUpdates(provider, 0, 0, locationListener); - + requestLocationUpdates(call); watchingCalls.put(call.getCallbackId(), call); } @@ -108,11 +78,9 @@ public void clearWatch(PluginCall call) { removed.release(bridge); } } - if (watchingCalls.size() == 0) { - locationManager.removeUpdates(locationListener); + clearLocationUpdates(); } - call.success(); } @@ -126,47 +94,6 @@ private void processLocation(Location location) { } } - /** - * Given a call and its options, find the best provider that satisfies those - * required options. - * @param call - * @return - */ - private String getBestProviderForCall(PluginCall call) { - Criteria locationCriteria = getCriteriaForCall(call); - return locationManager.getBestProvider(locationCriteria, true); - } - - /** - * Get the best location we can, using the best provider we have available - * that satisfies the requirements of the client - * @param bestProvider - * @return - */ - @SuppressWarnings("MissingPermission") - private Location getBestLocation(String bestProvider) { - List providers = locationManager.getProviders(true); - - Location l = locationManager.getLastKnownLocation(bestProvider); - Location bestLocation = l; - - if (bestLocation != null) { - return bestLocation; - } - - for (String provider : providers) { - l = locationManager.getLastKnownLocation(provider); - if (l == null) { - continue; - } - if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) { - bestLocation = l; - } - } - return bestLocation; - } - - @Override protected void handleRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.handleRequestPermissionsResult(requestCode, permissions, grantResults); @@ -193,29 +120,6 @@ protected void handleRequestPermissionsResult(int requestCode, String[] permissi } } - /** - * Given the call's options, return a Criteria object - * that will indicate which location provider we need to use. - * @param call - * @return - */ - private Criteria getCriteriaForCall(PluginCall call) { - boolean enableHighAccuracy = call.getBoolean("enableHighAccuracy", false); - boolean altitudeRequired = call.getBoolean("altitudeRequired", false); - boolean speedRequired = call.getBoolean("speedRequired", false); - boolean bearingRequired = call.getBoolean("bearingRequired", false); - - int timeout = call.getInt("timeout", 30000); - int maximumAge = call.getInt("maximumAge", 0); - - Criteria c = new Criteria(); - c.setAccuracy(enableHighAccuracy ? Criteria.ACCURACY_FINE : Criteria.ACCURACY_COARSE); - c.setAltitudeRequired(altitudeRequired); - c.setBearingRequired(bearingRequired); - c.setSpeedRequired(speedRequired); - return c; - } - private JSObject getJSObjectForLocation(Location location) { JSObject ret = new JSObject(); JSObject coords = new JSObject(); @@ -233,5 +137,49 @@ private JSObject getJSObjectForLocation(Location location) { return ret; } + @SuppressWarnings("MissingPermission") + private void requestLocationUpdates(final PluginCall call) { + clearLocationUpdates(); + boolean enableHighAccuracy = call.getBoolean("enableHighAccuracy", false); + int timeout = call.getInt("timeout", 10000); + fusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext()); + + LocationRequest locationRequest = new LocationRequest(); + locationRequest.setMaxWaitTime(timeout); + locationRequest.setInterval(10000); + locationRequest.setFastestInterval(5000); + locationRequest.setPriority(enableHighAccuracy ? LocationRequest.PRIORITY_HIGH_ACCURACY : LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); + + locationCallback = new LocationCallback(){ + @Override + public void onLocationResult(LocationResult locationResult) { + if (call.getMethodName().equals("getCurrentPosition")) { + clearLocationUpdates(); + } + Location lastLocation = locationResult.getLastLocation(); + if (lastLocation == null) { + call.error("location unavailable"); + } else { + call.success(getJSObjectForLocation(lastLocation)); + } + } + @Override + public void onLocationAvailability(LocationAvailability availability) { + if (!availability.isLocationAvailable()) { + call.error("location unavailable"); + clearLocationUpdates(); + } + } + }; + + fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null); + } + + private void clearLocationUpdates() { + if (locationCallback != null) { + fusedLocationClient.removeLocationUpdates(locationCallback); + locationCallback = null; + } + } } diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/PushNotifications.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/PushNotifications.java index 4ca92766c..279568744 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/PushNotifications.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/PushNotifications.java @@ -1,10 +1,15 @@ package com.getcapacitor.plugin; +import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.media.AudioAttributes; +import android.os.Build; import android.os.Bundle; +import android.service.notification.StatusBarNotification; import android.support.v4.app.NotificationCompat; import android.net.Uri; @@ -25,6 +30,10 @@ import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.RemoteMessage; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,6 +46,7 @@ public class PushNotifications extends Plugin { public static String CHANNEL_DESCRIPTION = "description"; public static String CHANNEL_IMPORTANCE = "importance"; public static String CHANNEL_VISIBILITY = "visibility"; + public static String CHANNEL_SOUND = "sound"; public static Bridge staticBridge = null; public static RemoteMessage lastMessage = null; @@ -60,7 +70,7 @@ public void load() { protected void handleOnNewIntent(Intent data) { super.handleOnNewIntent(data); Bundle bundle = data.getExtras(); - if(bundle != null && bundle.containsKey("google.message_id")) { + if (bundle != null && bundle.containsKey("google.message_id")) { JSObject notificationJson = new JSObject(); JSObject dataObject = new JSObject(); for (String key : bundle.keySet()) { @@ -83,7 +93,7 @@ protected void handleOnNewIntent(Intent data) { @PluginMethod() public void register(PluginCall call) { FirebaseMessaging.getInstance().setAutoInitEnabled(true); - FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(getActivity(), new OnSuccessListener() { + FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(getActivity(), new OnSuccessListener() { @Override public void onSuccess(InstanceIdResult instanceIdResult) { sendToken(instanceIdResult.getToken()); @@ -101,12 +111,64 @@ public void onFailure(Exception e) { @PluginMethod() public void getDeliveredNotifications(PluginCall call) { - call.unimplemented(); + JSArray notifications = new JSArray(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + StatusBarNotification[] activeNotifications = notificationManager.getActiveNotifications(); + + for (StatusBarNotification notif : activeNotifications) { + JSObject jsNotif = new JSObject(); + + jsNotif.put("id", notif.getId()); + + Notification notification = notif.getNotification(); + if (notification != null) { + jsNotif.put("title", notification.extras.getCharSequence(Notification.EXTRA_TITLE)); + jsNotif.put("body", notification.extras.getCharSequence(Notification.EXTRA_TEXT)); + jsNotif.put("group", notification.getGroup()); + jsNotif.put("groupSummary", 0 != (notification.flags & Notification.FLAG_GROUP_SUMMARY)); + + JSObject extras = new JSObject(); + + for (String key : notification.extras.keySet()) { + extras.put(key, notification.extras.get(key)); + } + + jsNotif.put("data", extras); + } + + notifications.put(jsNotif); + } + } + + JSObject result = new JSObject(); + result.put("notifications", notifications); + call.resolve(result); } @PluginMethod() public void removeDeliveredNotifications(PluginCall call) { - call.unimplemented(); + JSArray notifications = call.getArray("notifications"); + + List ids = new ArrayList<>(); + try { + for (Object o : notifications.toList()) { + if (o instanceof JSONObject) { + JSObject notif = JSObject.fromJSONObject((JSONObject) o); + Integer id = notif.getInteger("id"); + ids.add(id); + } else { + call.reject("Expected notifications to be a list of notification objects"); + } + } + } catch (JSONException e) { + call.reject(e.getMessage()); + } + + for (int id : ids) { + notificationManager.cancel(id); + } + + call.resolve(); } @PluginMethod() @@ -117,13 +179,14 @@ public void removeAllDeliveredNotifications(PluginCall call) { @PluginMethod() public void createChannel(PluginCall call) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { JSObject channel = new JSObject(); channel.put(CHANNEL_ID, call.getString(CHANNEL_ID)); channel.put(CHANNEL_NAME, call.getString(CHANNEL_NAME)); channel.put(CHANNEL_DESCRIPTION, call.getString(CHANNEL_DESCRIPTION, "")); - channel.put(CHANNEL_VISIBILITY, call.getInt(CHANNEL_VISIBILITY, NotificationCompat.VISIBILITY_PUBLIC)); + channel.put(CHANNEL_VISIBILITY, call.getInt(CHANNEL_VISIBILITY, NotificationCompat.VISIBILITY_PUBLIC)); channel.put(CHANNEL_IMPORTANCE, call.getInt(CHANNEL_IMPORTANCE)); + channel.put(CHANNEL_SOUND, call.getString(CHANNEL_SOUND, null)); createChannel(channel); call.success(); } else { @@ -133,7 +196,7 @@ public void createChannel(PluginCall call) { @PluginMethod() public void deleteChannel(PluginCall call) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { String channelId = call.getString("id"); notificationManager.deleteNotificationChannel(channelId); call.success(); @@ -154,6 +217,7 @@ public void listChannels(PluginCall call) { channel.put(CHANNEL_DESCRIPTION, notificationChannel.getDescription()); channel.put(CHANNEL_IMPORTANCE, notificationChannel.getImportance()); channel.put(CHANNEL_VISIBILITY, notificationChannel.getLockscreenVisibility()); + channel.put(CHANNEL_SOUND, notificationChannel.getSound()); Log.d(getLogTag(), "visibility " + notificationChannel.getLockscreenVisibility()); Log.d(getLogTag(), "importance " + notificationChannel.getImportance()); channels.put(channel); @@ -171,6 +235,14 @@ private void createChannel(JSObject channel) { NotificationChannel notificationChannelChannel = new NotificationChannel(channel.getString(CHANNEL_ID), channel.getString(CHANNEL_NAME), channel.getInteger(CHANNEL_IMPORTANCE)); notificationChannelChannel.setDescription(channel.getString(CHANNEL_DESCRIPTION, "")); notificationChannelChannel.setLockscreenVisibility(channel.getInteger(CHANNEL_VISIBILITY, 0)); + String sound = channel.getString(CHANNEL_SOUND, null); + if (sound != null && !sound.isEmpty()) { + AudioAttributes audioAttributes = new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ALARM).build(); + Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getContext().getPackageName() + "/raw/" + sound); + notificationChannelChannel.setSound(soundUri, audioAttributes); + } notificationManager.createNotificationChannel(notificationChannelChannel); } } diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Share.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Share.java index 7808c7ae1..d9c5d3753 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Share.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Share.java @@ -1,12 +1,17 @@ package com.getcapacitor.plugin; import android.content.Intent; +import android.net.Uri; +import android.support.v4.content.FileProvider; +import android.webkit.MimeTypeMap; import com.getcapacitor.NativePlugin; import com.getcapacitor.Plugin; import com.getcapacitor.PluginCall; import com.getcapacitor.PluginMethod; +import java.io.File; + @NativePlugin() public class Share extends Plugin { @@ -21,19 +26,24 @@ public void share(PluginCall call) { call.error("Must provide a URL or Message"); return; } - + Intent intent = new Intent(Intent.ACTION_SEND); // If they supplied both fields, concat em - if (text != null && url != null) { + if (text != null && url != null && url.startsWith("http")) { text = text + " " + url; + intent.setTypeAndNormalize("text/plain"); + intent.putExtra(Intent.EXTRA_TEXT, text); } else if(url != null) { - text = url; + if (url.startsWith("file:")) { + String type = getMimeType(url); + intent.setType(type); + Uri fileUrl = FileProvider.getUriForFile(getActivity(), getContext().getPackageName() + ".fileprovider", new File(Uri.parse(url).getPath())); + intent.putExtra(Intent.EXTRA_STREAM, fileUrl); + } else { + call.error("Unsupported url"); + return; + } } - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setTypeAndNormalize("text/plain"); - - intent.putExtra(Intent.EXTRA_TEXT, text); - if (title != null) { intent.putExtra(Intent.EXTRA_SUBJECT, title); } @@ -44,4 +54,13 @@ public void share(PluginCall call) { getActivity().startActivity(chooser); call.success(); } + + private String getMimeType(String url) { + String type = null; + String extension = MimeTypeMap.getFileExtensionFromUrl(url); + if (extension != null) { + type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + } + return type; + } } diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Toast.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Toast.java index a15e60aea..5e3de683f 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Toast.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Toast.java @@ -1,5 +1,6 @@ package com.getcapacitor.plugin; +import android.view.Gravity; import com.getcapacitor.NativePlugin; import com.getcapacitor.Plugin; import com.getcapacitor.PluginCall; @@ -8,6 +9,9 @@ @NativePlugin() public class Toast extends Plugin { + private static final int GRAVITY_TOP = Gravity.TOP|Gravity.CENTER_HORIZONTAL; + private static final int GRAVITY_CENTER = Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL; + @PluginMethod() public void show(PluginCall call) { CharSequence text = call.getString("text"); @@ -16,7 +20,7 @@ public void show(PluginCall call) { return; } - String durationType = call.getString("durationType", "short"); + String durationType = call.getString("duration", "short"); int duration = android.widget.Toast.LENGTH_SHORT; if("long".equals(durationType)) { @@ -24,6 +28,14 @@ public void show(PluginCall call) { } android.widget.Toast toast = android.widget.Toast.makeText(getContext(), text, duration); + + String position = call.getString("position", "bottom"); + if("top".equals(position)) { + toast.setGravity(GRAVITY_TOP, 0, 40); + } else if("center".equals(position)) { + toast.setGravity(GRAVITY_CENTER, 0, 0); + } + toast.show(); call.success(); } diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/camera/ExifWrapper.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/camera/ExifWrapper.java index 6ec362bb1..61495f3c4 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/camera/ExifWrapper.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/camera/ExifWrapper.java @@ -61,6 +61,10 @@ public JSObject toJson() { // p(ret, TAG_FOCAL_PLANE_RESOLUTION_UNIT); p(ret, TAG_FOCAL_LENGTH); // p(ret, TAG_GAIN_CONTROL); + p(ret, TAG_GPS_LATITUDE); + p(ret, TAG_GPS_LATITUDE_REF); + p(ret, TAG_GPS_LONGITUDE); + p(ret, TAG_GPS_LONGITUDE_REF); p(ret, TAG_GPS_ALTITUDE); p(ret, TAG_GPS_ALTITUDE_REF); // p(ret, TAG_GPS_AREA_INFORMATION); diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotification.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotification.java index 469e37812..7df50102f 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotification.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotification.java @@ -32,6 +32,8 @@ public class LocalNotification { private String sound; private String smallIcon; private String actionTypeId; + private String group; + private boolean groupSummary; private JSObject extra; private List attachments; private LocalNotificationSchedule schedule; @@ -89,6 +91,14 @@ public void setActionTypeId(String actionTypeId) { this.actionTypeId = actionTypeId; } + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + public JSObject getExtra() { return extra; } @@ -105,6 +115,14 @@ public void setId(Integer id) { this.id = id; } + public boolean isGroupSummary() { + return groupSummary; + } + + public void setGroupSummary(boolean groupSummary) { + this.groupSummary = groupSummary; + } + /** * Build list of the notifications from remote plugin call */ @@ -136,10 +154,12 @@ public static List buildNotificationList(PluginCall call) { activeLocalNotification.setId(notification.getInteger("id")); activeLocalNotification.setBody(notification.getString("body")); activeLocalNotification.setActionTypeId(notification.getString("actionTypeId")); + activeLocalNotification.setGroup(notification.getString("group")); activeLocalNotification.setSound(notification.getString("sound")); activeLocalNotification.setTitle(notification.getString("title")); activeLocalNotification.setSmallIcon(notification.getString("smallIcon")); activeLocalNotification.setAttachments(LocalNotificationAttachment.getAttachments(notification)); + activeLocalNotification.setGroupSummary(notification.getBoolean("groupSummary", false)); try { activeLocalNotification.setSchedule(new LocalNotificationSchedule(notification)); } catch (ParseException e) { @@ -234,9 +254,11 @@ public String toString() { ", sound='" + sound + '\'' + ", smallIcon='" + smallIcon + '\'' + ", actionTypeId='" + actionTypeId + '\'' + + ", group='" + group + '\'' + ", extra=" + extra + ", attachments=" + attachments + ", schedule=" + schedule + + ", groupSummary=" + groupSummary + '}'; } @@ -254,9 +276,11 @@ public boolean equals(Object o) { if (smallIcon != null ? !smallIcon.equals(that.smallIcon) : that.smallIcon != null) return false; if (actionTypeId != null ? !actionTypeId.equals(that.actionTypeId) : that.actionTypeId != null) return false; + if (group != null ? !group.equals(that.group) : that.group != null) return false; if (extra != null ? !extra.equals(that.extra) : that.extra != null) return false; if (attachments != null ? !attachments.equals(that.attachments) : that.attachments != null) return false; + if (groupSummary != that.groupSummary) return false; return schedule != null ? schedule.equals(that.schedule) : that.schedule == null; } @@ -268,6 +292,8 @@ public int hashCode() { result = 31 * result + (sound != null ? sound.hashCode() : 0); result = 31 * result + (smallIcon != null ? smallIcon.hashCode() : 0); result = 31 * result + (actionTypeId != null ? actionTypeId.hashCode() : 0); + result = 31 * result + (group != null ? group.hashCode() : 0); + result = 31 * result + Boolean.hashCode(groupSummary); result = 31 * result + (extra != null ? extra.hashCode() : 0); result = 31 * result + (attachments != null ? attachments.hashCode() : 0); result = 31 * result + (schedule != null ? schedule.hashCode() : 0); diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationManager.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationManager.java index effd3ca49..20289a40c 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationManager.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationManager.java @@ -149,6 +149,7 @@ private void buildNotification(NotificationManagerCompat notificationManager, Lo .setAutoCancel(true) .setOngoing(false) .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setGroupSummary(localNotification.isGroupSummary()) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS); String sound = localNotification.getSound(); @@ -161,6 +162,11 @@ private void buildNotification(NotificationManagerCompat notificationManager, Lo mBuilder.setSound(soundUri); } + String group = localNotification.getGroup(); + if (group != null) { + mBuilder.setGroup(group); + } + mBuilder.setVisibility(Notification.VISIBILITY_PRIVATE); mBuilder.setOnlyAlertOnce(true); diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index f715fac11..9bbaef5f8 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/android/package.json b/android/package.json index cba438316..0ded6e906 100644 --- a/android/package.json +++ b/android/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/android", - "version": "1.4.0", + "version": "1.5.0", "description": "Capacitor: cross-platform mobile apps with the web", "homepage": "https://capacitor.ionicframework.com/", "author": "Ionic Team (https://ionicframework.com) ", @@ -16,7 +16,7 @@ "access": "public" }, "peerDependencies": { - "@capacitor/core": "^1.2.1" + "@capacitor/core": "^1.5.0" }, "gitHead": "844c0feba4a801ee5041429a82d0f805c9e665b0" } diff --git a/capacitor-cordova-android-plugins/build.gradle b/capacitor-cordova-android-plugins/build.gradle index 759dfbfdd..86263c61c 100644 --- a/capacitor-cordova-android-plugins/build.gradle +++ b/capacitor-cordova-android-plugins/build.gradle @@ -4,17 +4,17 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.2' + classpath 'com.android.tools.build:gradle:3.5.3' } } apply plugin: 'com.android.library' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" } diff --git a/cli/package.json b/cli/package.json index b98df0552..59540eb60 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/cli", - "version": "1.4.0", + "version": "1.5.0", "description": "Capacitor: Cross-platform apps with JavaScript and the web", "homepage": "https://capacitor.ionicframework.com/", "author": "Ionic Team (https://ionicframework.com) ", diff --git a/cli/src/android/doctor.ts b/cli/src/android/doctor.ts index 2185f9f28..65b5112ea 100644 --- a/cli/src/android/doctor.ts +++ b/cli/src/android/doctor.ts @@ -1,5 +1,5 @@ import { accessSync } from 'fs'; -import { check, isInstalled, logFatal, logSuccess, readXML } from '../common'; +import { check, logFatal, logSuccess, readXML } from '../common'; import { existsAsync, readFileAsync } from '../util/fs'; import { Config } from '../config'; import { join } from 'path'; diff --git a/cli/src/android/open.ts b/cli/src/android/open.ts index 601e3d55d..a10a43202 100644 --- a/cli/src/android/open.ts +++ b/cli/src/android/open.ts @@ -1,7 +1,7 @@ import { Config } from '../config'; import { OS } from '../definitions'; -import { logError, logInfo } from '../common'; -import { existsAsync } from '../util/fs'; +import { logError, logInfo, runCommand } from '../common'; +import { existsAsync, existsSync } from '../util/fs'; import { resolve } from 'path'; export async function openAndroid(config: Config) { @@ -20,10 +20,29 @@ export async function openAndroid(config: Config) { await opn(dir, { app: 'android studio', wait: false }); break; case OS.Windows: - if (config.windows.androidStudioPath) { - opn(dir, { app: config.windows.androidStudioPath, wait: false }); + let androidStudioPath = config.windows.androidStudioPath; + try { + if (!existsSync(androidStudioPath)) { + let commandResult = await runCommand('REG QUERY "HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio" /v Path'); + commandResult = commandResult.replace(/(\r\n|\n|\r)/gm, ''); + const ix = commandResult.indexOf('REG_SZ'); + if (ix > 0) { + androidStudioPath = commandResult.substring(ix + 6).trim() + '\\bin\\studio64.exe'; + } + } + } catch (e) { + androidStudioPath = ''; + } + if (androidStudioPath) { + opn(dir, { app: androidStudioPath, wait: false }); } else { - logError('Unable to launch Android Studio. Make sure the latest version of Android Studio is installed'); + logError('Android Studio not found. Make sure it\'s installed and configure "windowsAndroidStudioPath" ' + + 'in your capacitor.config.json to point to the location of studio64.exe, using JavaScript-escaped paths:\n' + + + 'Example:\n' + + '{\n' + + ' "windowsAndroidStudioPath": "C:\\\\Program Files\\\\Android\\\\Android Studio\\\\bin\\\\studio64.exe"\n' + + '}'); } break; case OS.Linux: @@ -38,7 +57,7 @@ export async function openAndroid(config: Config) { }; try { - await opn(dir, { app: config.linux.androidStudioPath, wait: false }); + await opn(dir, { app: config.linux.androidStudioPath, wait: true }); } catch (e) { linuxError(); } diff --git a/cli/src/android/update.ts b/cli/src/android/update.ts index 5ca0a0396..2b40ecf66 100644 --- a/cli/src/android/update.ts +++ b/cli/src/android/update.ts @@ -1,7 +1,7 @@ import { Config } from '../config'; -import { buildXmlElement, checkPlatformVersions, logFatal, logInfo, parseXML, resolveNode, runTask } from '../common'; +import { buildXmlElement, checkPlatformVersions, logFatal, resolveNode, runTask } from '../common'; import { getAndroidPlugins } from './common'; -import { checkAndInstallDependencies, handleCordovaPluginsJS } from '../cordova'; +import { checkAndInstallDependencies, handleCordovaPluginsJS, writeCordovaAndroidManifest } from '../cordova'; import { convertToUnixPath, copySync, readFileAsync, removeSync, writeFileAsync} from '../util/fs'; import { join, relative, resolve } from 'path'; import { Plugin, PluginType, getAllElements, getFilePath, getPlatformElement, getPluginPlatform, getPluginType, getPlugins, printPlugins } from '../plugin'; @@ -32,7 +32,7 @@ export async function updateAndroid(config: Config) { await handleCordovaPluginsJS(cordovaPlugins, config, platform); await installGradlePlugins(config, capacitorPlugins, cordovaPlugins); await handleCordovaPluginsGradle(config, cordovaPlugins); - await writeCordovaAndroidManifest(cordovaPlugins, config); + await writeCordovaAndroidManifest(cordovaPlugins, config, platform); const incompatibleCordovaPlugins = plugins .filter(p => getPluginType(p, platform) === PluginType.Incompatible); @@ -201,75 +201,3 @@ async function getPluginsTask(config: Config) { return androidPlugins; }); } - -async function writeCordovaAndroidManifest(cordovaPlugins: Plugin[], config: Config) { - const pluginsFolder = resolve(config.app.rootDir, 'android', config.android.assets.pluginsFolderName); - const manifestPath = join(pluginsFolder, 'src', 'main', 'AndroidManifest.xml'); - let rootXMLEntries: Array = []; - let applicationXMLEntries: Array = []; - let applicationXMLAttributes: Array = []; - cordovaPlugins.map(async p => { - const editConfig = getPlatformElement(p, platform, 'edit-config'); - const configFile = getPlatformElement(p, platform, 'config-file'); - editConfig.concat(configFile).map(async (configElement: any) => { - if (configElement.$ && (configElement.$.target && configElement.$.target.includes('AndroidManifest.xml') || configElement.$.file && configElement.$.file.includes('AndroidManifest.xml'))) { - const keys = Object.keys(configElement).filter(k => k !== '$'); - keys.map(k => { - configElement[k].map((e: any) => { - const xmlElement = buildXmlElement(e, k); - const pathParts = getPathParts(configElement.$.parent || configElement.$.target); - if (pathParts.length > 1) { - if (pathParts.pop() === 'application') { - if (configElement.$.mode && configElement.$.mode === 'merge') { - Object.keys(e.$).map((ek: any) => { - applicationXMLAttributes.push(`${ek}="${e.$[ek]}"`); - }); - } else if (!applicationXMLEntries.includes(xmlElement) && !contains(applicationXMLEntries, xmlElement, k)) { - applicationXMLEntries.push(xmlElement); - } - } else { - logInfo(`plugin ${p.id} requires to add \n ${xmlElement} to your AndroidManifest.xml to work`); - } - } else { - if (!rootXMLEntries.includes(xmlElement) && !contains(rootXMLEntries, xmlElement, k)) { - rootXMLEntries.push(xmlElement); - } - } - }); - }); - } - }); - }); - let content = ` - - -${applicationXMLEntries.join('\n')} - -${rootXMLEntries.join('\n')} -`; - content = content.replace(new RegExp(('$PACKAGE_NAME').replace('$', '\\$&'), 'g'), config.app.appId); - await writeFileAsync(manifestPath, content); -} - -function getPathParts(path: string) { - const rootPath = 'manifest'; - path = path.replace('/*', rootPath); - let parts = path.split('/').filter(part => part !== ''); - if (parts.length > 1 || parts.includes(rootPath)) { - return parts; - } - return [rootPath, path]; -} - -function contains(a: Array, obj: any, k: string) { - const element = parseXML(obj); - for (var i = 0; i < a.length; i++) { - const current = parseXML(a[i]); - if (element && current && current[k] && element[k] && current[k].$ && element[k].$ && element[k].$['android:name'] === current[k].$['android:name']) { - return true; - } - } - return false; -} diff --git a/cli/src/common.ts b/cli/src/common.ts index 6aafc2d31..3a90ec3d1 100644 --- a/cli/src/common.ts +++ b/cli/src/common.ts @@ -418,7 +418,7 @@ export function resolveNode(config: Config, ...pathSegments: any[]): string | nu return join(modulePath, ...path); } -function resolveNodeFrom(start: string, id: string): string | null { +export function resolveNodeFrom(start: string, id: string): string | null { const rootPath = parse(start).root; let basePath = resolve(start); let modulePath; @@ -451,3 +451,13 @@ export const hasYarn = async (config: Config, projectDir?: string) => { export async function installDeps(projectDir: string, deps: string[], config: Config) { return runCommand(`cd "${projectDir}" && ${await hasYarn(config, projectDir) ? 'yarn add' : 'npm install --save'} ${deps.join(' ')}`); } + +export async function checkNPMVersion() { + const minVersion = '5.5.0'; + const version = await runCommand('npm -v'); + const semver = await import('semver'); + if (semver.gt(minVersion, version)) { + return `Capacitor CLI requires at least NPM ${minVersion}`; + } + return null; +} diff --git a/cli/src/config.ts b/cli/src/config.ts index 2245af464..4d7dd62c9 100644 --- a/cli/src/config.ts +++ b/cli/src/config.ts @@ -1,8 +1,7 @@ -import { accessSync, existsSync, readFileSync } from 'fs'; +import { accessSync, readFileSync } from 'fs'; import { basename, join, resolve } from 'path'; import { logFatal, readJSON } from './common'; import { CliConfig, ExternalConfig, OS, PackageJson } from './definitions'; -import { execSync } from 'child_process'; let Package: PackageJson; let ExtConfig: ExternalConfig; @@ -91,6 +90,9 @@ export class Config implements CliConfig { templateName: 'app-template', templateDir: '', pluginsTemplateDir: '' + }, + server: { + cleartext: false } }; @@ -197,21 +199,7 @@ export class Config implements CliConfig { if (this.cli.os !== OS.Windows) { return; } - if (this.app.windowsAndroidStudioPath) { - try { - if (!existsSync(this.app.windowsAndroidStudioPath)) { - const buffer = execSync('REG QUERY "HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio" /v Path'); - const bufferString = buffer.toString('utf-8').replace(/(\r\n|\n|\r)/gm, ''); - const ix = bufferString.indexOf('REG_SZ'); - if (ix > 0) { - this.app.windowsAndroidStudioPath = bufferString.substring(ix + 6).trim() + '\\bin\\studio64.exe'; - } - } - this.windows.androidStudioPath = this.app.windowsAndroidStudioPath; - } catch (e) { - this.windows.androidStudioPath = ''; - } - } + this.windows.androidStudioPath = this.app.windowsAndroidStudioPath; } private initLinuxConfig() { diff --git a/cli/src/cordova.ts b/cli/src/cordova.ts index 6be2e06f0..33eba0588 100644 --- a/cli/src/cordova.ts +++ b/cli/src/cordova.ts @@ -2,7 +2,7 @@ import { Config } from './config'; import { Plugin, PluginType, getJSModules, getPlatformElement, getPluginPlatform, getPluginType, getPlugins, printPlugins } from './plugin'; import { copySync, ensureDirSync, readFileAsync, removeSync, writeFileAsync } from './util/fs'; import { basename, extname, join, resolve } from 'path'; -import { buildXmlElement, installDeps, log, logError, logFatal, logInfo, logWarn, readXML, resolveNode, writeXML } from './common'; +import { buildXmlElement, installDeps, log, logError, logFatal, logInfo, logWarn, parseXML, readXML, resolveNode, writeXML } from './common'; import { copy as fsCopy, existsSync } from 'fs-extra'; import { getAndroidPlugins } from './android/common'; import { getIOSPlugins } from './ios/common'; @@ -214,7 +214,7 @@ export async function handleCordovaPluginsJS(cordovaPlugins: Plugin[], config: C await autoGenerateConfig(config, cordovaPlugins, platform); } -export async function copyCordovaJSFiles(config: Config, platform: string) { +export async function getCordovaPlugins(config: Config, platform: string): Promise { const allPlugins = await getPlugins(config); let plugins: Plugin[] = []; if (platform === config.ios.name) { @@ -222,9 +222,8 @@ export async function copyCordovaJSFiles(config: Config, platform: string) { } else if (platform === config.android.name) { plugins = getAndroidPlugins(allPlugins); } - const cordovaPlugins = plugins + return plugins .filter(p => getPluginType(p, platform) === PluginType.Cordova); - await handleCordovaPluginsJS(cordovaPlugins, config, platform); } export async function logCordovaManualSteps(cordovaPlugins: Plugin[], config: Config, platform: string) { @@ -365,3 +364,78 @@ export async function getCordovaPreferences(config: Config) { } return cordova; } + +export async function writeCordovaAndroidManifest(cordovaPlugins: Plugin[], config: Config, platform: string) { + const pluginsFolder = resolve(config.app.rootDir, 'android', config.android.assets.pluginsFolderName); + const manifestPath = join(pluginsFolder, 'src', 'main', 'AndroidManifest.xml'); + let rootXMLEntries: Array = []; + let applicationXMLEntries: Array = []; + let applicationXMLAttributes: Array = []; + cordovaPlugins.map(async p => { + const editConfig = getPlatformElement(p, platform, 'edit-config'); + const configFile = getPlatformElement(p, platform, 'config-file'); + editConfig.concat(configFile).map(async (configElement: any) => { + if (configElement.$ && (configElement.$.target && configElement.$.target.includes('AndroidManifest.xml') || configElement.$.file && configElement.$.file.includes('AndroidManifest.xml'))) { + const keys = Object.keys(configElement).filter(k => k !== '$'); + keys.map(k => { + configElement[k].map((e: any) => { + const xmlElement = buildXmlElement(e, k); + const pathParts = getPathParts(configElement.$.parent || configElement.$.target); + if (pathParts.length > 1) { + if (pathParts.pop() === 'application') { + if (configElement.$.mode && configElement.$.mode === 'merge') { + Object.keys(e.$).map((ek: any) => { + applicationXMLAttributes.push(`${ek}="${e.$[ek]}"`); + }); + } else if (!applicationXMLEntries.includes(xmlElement) && !contains(applicationXMLEntries, xmlElement, k)) { + applicationXMLEntries.push(xmlElement); + } + } else { + logInfo(`plugin ${p.id} requires to add \n ${xmlElement} to your AndroidManifest.xml to work`); + } + } else { + if (!rootXMLEntries.includes(xmlElement) && !contains(rootXMLEntries, xmlElement, k)) { + rootXMLEntries.push(xmlElement); + } + } + }); + }); + } + }); + }); + let cleartext = config.app.extConfig.server?.cleartext ? 'android:usesCleartextTraffic="true"' : ''; + let content = ` + + +${applicationXMLEntries.join('\n')} + +${rootXMLEntries.join('\n')} +`; + content = content.replace(new RegExp(('$PACKAGE_NAME').replace('$', '\\$&'), 'g'), config.app.appId); + if (existsSync(manifestPath)) { + await writeFileAsync(manifestPath, content); + } +} + +function getPathParts(path: string) { + const rootPath = 'manifest'; + path = path.replace('/*', rootPath); + let parts = path.split('/').filter(part => part !== ''); + if (parts.length > 1 || parts.includes(rootPath)) { + return parts; + } + return [rootPath, path]; +} + +function contains(a: Array, obj: any, k: string) { + const element = parseXML(obj); + for (var i = 0; i < a.length; i++) { + const current = parseXML(a[i]); + if (element && current && current[k] && element[k] && current[k].$ && element[k].$ && element[k].$['android:name'] === current[k].$['android:name']) { + return true; + } + } + return false; +} diff --git a/cli/src/definitions.ts b/cli/src/definitions.ts index a93191d92..a2557c0ea 100644 --- a/cli/src/definitions.ts +++ b/cli/src/definitions.ts @@ -24,6 +24,9 @@ export interface ExternalConfig { }; npmClient?: string; cordova?: any; + server?: { + cleartext?: boolean; + } } export interface AppPluginsConfig { diff --git a/cli/src/electron/doctor.ts b/cli/src/electron/doctor.ts new file mode 100644 index 000000000..02db526df --- /dev/null +++ b/cli/src/electron/doctor.ts @@ -0,0 +1,53 @@ +import { check, checkNPMVersion, checkWebDir, logFatal, logSuccess, resolveNodeFrom } from '../common'; +import { Config } from '../config'; +import { existsAsync } from '../util/fs'; +import { join } from 'path'; + +export async function doctorElectron(config: Config) { + try { + await check( + config, + [ + checkWebDir, + checkNPMVersion, + checkAppSrcDirs, + checkElectronInstall + ] + ); + logSuccess('electron looking great! 👌'); + } catch (e) { + logFatal(e); + } + +} + +async function checkAppSrcDirs(config: Config) { + const appDir = join(config.electron.platformDir, 'app'); + if (!await existsAsync(appDir)) { + return `"app" directory is missing in: ${config.electron.platformDir}`; + } + + const appIndexHtml = join(appDir, 'index.html'); + if (!await existsAsync(appIndexHtml)) { + return `"index.html" directory is missing in: ${appDir}`; + } + return checkElectronIndexFile(config, config.electron.platformDir); +} + +async function checkElectronIndexFile(config: Config, electronDir: string) { + const indexFileName = 'index.js'; + const indexFilePath = join(electronDir, indexFileName); + + if (!await existsAsync(indexFilePath)) { + return `"${indexFilePath}" is missing in: ${electronDir}`; + } + return null; +} + +async function checkElectronInstall(config: Config) { + if (resolveNodeFrom(config.electron.platformDir, 'electron')) { + return null; + } else { + return 'electron not installed'; + } +} diff --git a/cli/src/ios/doctor.ts b/cli/src/ios/doctor.ts index 7d7324f7c..9c78c87a1 100644 --- a/cli/src/ios/doctor.ts +++ b/cli/src/ios/doctor.ts @@ -1,5 +1,5 @@ import { checkCocoaPods, checkIOSProject } from './common'; -import { check, checkWebDir, isInstalled, logFatal, logSuccess, runCommand } from '../common'; +import { check, checkNPMVersion, checkWebDir, isInstalled, logFatal, logSuccess } from '../common'; import { Config } from '../config'; import { getPlugins, printPlugins } from '../plugin'; @@ -46,12 +46,4 @@ async function checkXcode() { } -async function checkNPMVersion() { - const minVersion = '5.5.0'; - const version = await runCommand('npm -v'); - const semver = await import('semver'); - if (semver.gt(minVersion, version)) { - return `Capacitor CLI requires at least NPM ${minVersion}`; - } - return null; -} + diff --git a/cli/src/ios/update.ts b/cli/src/ios/update.ts index ab4d3d8fe..5da32c51e 100644 --- a/cli/src/ios/update.ts +++ b/cli/src/ios/update.ts @@ -288,8 +288,9 @@ function copyPluginsNativeFiles(config: Config, cordovaPlugins: Plugin[]) { fileContent = fileContent.replace('@import Firebase;', '#import '); writeFileSync(fileDest, fileContent, 'utf8'); } - if (fileContent.includes('[NSBundle bundleForClass:[self class]]')) { + if (fileContent.includes('[NSBundle bundleForClass:[self class]]') || fileContent.includes('[NSBundle bundleForClass:[CDVCapture class]]')) { fileContent = fileContent.replace('[NSBundle bundleForClass:[self class]]', '[NSBundle mainBundle]'); + fileContent = fileContent.replace('[NSBundle bundleForClass:[CDVCapture class]]', '[NSBundle mainBundle]'); writeFileSync(fileDest, fileContent, 'utf8'); } } diff --git a/cli/src/tasks/copy.ts b/cli/src/tasks/copy.ts index 174f9aaa5..c50167f23 100644 --- a/cli/src/tasks/copy.ts +++ b/cli/src/tasks/copy.ts @@ -6,7 +6,7 @@ import { copyWeb } from '../web/copy'; import { copyElectron } from '../electron/copy'; import { basename, join, relative, resolve } from 'path'; import { copy as fsCopy, remove } from 'fs-extra'; -import { copyCordovaJSFiles } from '../cordova'; +import { getCordovaPlugins, handleCordovaPluginsJS, writeCordovaAndroidManifest } from '../cordova'; import chalk from 'chalk'; export async function copyCommand(config: Config, selectedPlatformName: string) { @@ -34,12 +34,15 @@ export async function copy(config: Config, platformName: string) { await copyWebDir(config, config.ios.webDirAbs); await copyNativeBridge(config, config.ios.webDirAbs); await copyCapacitorConfig(config, join(config.ios.platformDir, config.ios.nativeProjectName, config.ios.nativeProjectName)); - await copyCordovaJSFiles(config, platformName); + const cordovaPlugins = await getCordovaPlugins(config, platformName); + await handleCordovaPluginsJS(cordovaPlugins, config, platformName); } else if (platformName === config.android.name) { await copyWebDir(config, config.android.webDirAbs); await copyNativeBridge(config, config.android.webDirAbs); await copyCapacitorConfig(config, join(config.android.platformDir, 'app/src/main/assets')); - await copyCordovaJSFiles(config, platformName); + const cordovaPlugins = await getCordovaPlugins(config, platformName); + await handleCordovaPluginsJS(cordovaPlugins, config, platformName); + await writeCordovaAndroidManifest(cordovaPlugins, config, platformName); } else if (platformName === config.web.name) { await copyWeb(config); } else if (platformName === config.electron.name) { diff --git a/cli/src/tasks/doctor.ts b/cli/src/tasks/doctor.ts index 47be8b0da..a282cd960 100644 --- a/cli/src/tasks/doctor.ts +++ b/cli/src/tasks/doctor.ts @@ -1,8 +1,8 @@ import { Config } from '../config'; -import { log, readJSON, resolveNode, runCommand } from '../common'; +import { log, readJSON, resolveNode, resolveNodeFrom, runCommand } from '../common'; import { doctorAndroid } from '../android/doctor'; +import { doctorElectron } from '../electron/doctor'; import { doctorIOS } from '../ios/doctor'; -import { existsAsync, readFileAsync } from '../util/fs'; import { emoji as _e } from '../util/emoji'; import { join } from 'path'; @@ -24,12 +24,14 @@ export async function doctorCore(config: Config) { let cliVersion = await runCommand(`npm info @capacitor/cli version`); let coreVersion = await runCommand(`npm info @capacitor/core version`); let androidVersion = await runCommand(`npm info @capacitor/android version`); + let electronVersion = await runCommand(`npm info @capacitor/android version`); let iosVersion = await runCommand(`npm info @capacitor/ios version`); log(`${chalk.bold.blue('Latest Dependencies:')}\n`); log(` ${chalk.bold('@capacitor/cli:')}`, cliVersion); log(` ${chalk.bold('@capacitor/core:')}`, coreVersion); log(` ${chalk.bold('@capacitor/android:')}`, androidVersion); + log(` ${chalk.bold('@capacitor/electron:')}`, electronVersion); log(` ${chalk.bold('@capacitor/ios:')}`, iosVersion); log(`${chalk.bold.blue('Installed Dependencies:')}\n`); @@ -39,17 +41,23 @@ export async function doctorCore(config: Config) { log(''); } -async function printInstalledPackages( config: Config) { +async function printInstalledPackages(config: Config) { const packageNames = ['@capacitor/cli', '@capacitor/core', '@capacitor/android', '@capacitor/ios']; await Promise.all(packageNames.map(async packageName => { - let version; const packagePath = resolveNode(config, packageName, 'package.json'); - if (packagePath) { - version = (await readJSON(packagePath)).version; - } - log(` ${chalk.bold(packageName)}`, version || 'not installed'); - log(''); + printPackageVersion(packageName, packagePath); })); + const packagePath = resolveNodeFrom(config.electron.platformDir, '@capacitor/electron'); + printPackageVersion('@capacitor/electron', packagePath ? join(packagePath, 'package.json') : packagePath); +} + +async function printPackageVersion(packageName: string, packagePath: string | null) { + let version; + if (packagePath) { + version = (await readJSON(packagePath)).version; + } + log(` ${chalk.bold(packageName)}`, version || 'not installed'); + log(''); } export async function doctor(config: Config, platformName: string) { @@ -57,6 +65,8 @@ export async function doctor(config: Config, platformName: string) { await doctorIOS(config); } else if (platformName === config.android.name) { await doctorAndroid(config); + } else if (platformName === config.electron.name) { + await doctorElectron(config); } else if (platformName === config.web.name) { return Promise.resolve(); } else { diff --git a/cli/src/tasks/new-plugin.ts b/cli/src/tasks/new-plugin.ts index e8ee10db5..cf3f15b6d 100644 --- a/cli/src/tasks/new-plugin.ts +++ b/cli/src/tasks/new-plugin.ts @@ -8,6 +8,16 @@ import { copy, mkdirs, unlink } from 'fs-extra'; import { dirname, join } from 'path'; import { isInteractive } from '../util/term'; +interface NewPluginAnswers { + name: string + domain: string + className: string + description: string + git: string + author: string + license: string + confirm: boolean +} export async function newPluginCommand(config: Config) { try { @@ -26,61 +36,42 @@ export async function newPlugin(config: Config) { log(`${emoji('✏️', '*')} Creating new Capacitor plugin`); const inquirer = await import('inquirer'); - const answers = await inquirer.prompt([ + const requiredInput = (input: string): boolean => { + if (!input || input.trim() === '') { + return false; + } + return true; + } + const answers: NewPluginAnswers = await inquirer.prompt([ { type: 'input', name: 'name', message: 'Plugin NPM name (kebab-case):', - validate: function(input) { - if (!input || input.trim() === '') { - return false; - } - return true; - } + validate: requiredInput }, { type: 'input', name: 'domain', message: 'Plugin id (domain-style syntax. ex: com.example.plugin)', - validate: function(input) { - if (!input || input.trim() === '') { - return false; - } - return true; - } + validate: requiredInput }, { type: 'input', name: 'className', message: 'Plugin class name (ex: AwesomePlugin)', - validate: function(input) { - if (!input || input.trim() === '') { - return false; - } - return true; - } + validate: requiredInput }, { type: 'input', name: 'description', message: 'description:', - validate: function(input) { - if (!input || input.trim() === '') { - return false; - } - return true; - } + validate: requiredInput }, { type: 'input', name: 'git', message: 'git repository:', - validate: function(input) { - if (!input || input.trim() === '') { - return false; - } - return true; - } + validate: requiredInput }, { type: 'input', @@ -98,7 +89,7 @@ export async function newPlugin(config: Config) { name: 'confirm', message: `package.json will be created, do you want to continue?` } - ]); + ]) as NewPluginAnswers; console.log('\n'); @@ -142,7 +133,7 @@ export async function newPlugin(config: Config) { } } -async function createTSPlugin(config: Config, pluginPath: string, domain: string, className: string, answers: any) { +async function createTSPlugin(config: Config, pluginPath: string, domain: string, className: string, answers: NewPluginAnswers) { const newPluginPath = join(pluginPath, 'src'); const originalDefinitions = await readFileAsync(join(newPluginPath, 'definitions.ts'), 'utf8'); @@ -154,7 +145,7 @@ async function createTSPlugin(config: Config, pluginPath: string, domain: string await writeFileAsync(join(newPluginPath, `web.ts`), web, 'utf8'); } -async function createIosPlugin(config: Config, pluginPath: string, domain: string, className: string, answers: any) { +async function createIosPlugin(config: Config, pluginPath: string, domain: string, className: string, answers: NewPluginAnswers) { const newPluginPath = join(pluginPath, 'ios', 'Plugin'); const originalPluginSwift = await readFileAsync(join(newPluginPath, 'Plugin.swift'), 'utf8'); @@ -174,7 +165,7 @@ async function createIosPlugin(config: Config, pluginPath: string, domain: strin await writeFileAsync(join(newPluginPath, 'Plugin.m'), pluginObjc, 'utf8'); } -function generatePodspec(config: Config, answers: any) { +function generatePodspec(config: Config, answers: NewPluginAnswers) { return ` Pod::Spec.new do |s| s.name = '${fixName(answers.name)}' @@ -222,7 +213,7 @@ function generateAndroidManifest(domain: string, pluginPath: string) { `; } -function generatePackageJSON(answers: any) { +function generatePackageJSON(answers: NewPluginAnswers) { return { name: answers.name, version: '0.0.1', diff --git a/cli/test/util.ts b/cli/test/util.ts index ef5450707..539f204e9 100644 --- a/cli/test/util.ts +++ b/cli/test/util.ts @@ -88,7 +88,10 @@ export async function makeAppDir(monoRepoLike: boolean = false) { await runCommand(`cd "${rootDir}" && npm install --save ${corePath} ${cliPath}`); // Make a fake cordova plugin - await makeCordovaPlugin(appDir); + const cordovaPluginPath = join(tmpDir, CORDOVA_PLUGIN_ID); + await makeCordovaPlugin(cordovaPluginPath); + + await runCommand(`cd "${rootDir}" && npm install --save ${cordovaPluginPath}`); return { ...appDirObj, @@ -180,14 +183,13 @@ Pod::Spec.new do |s| s.dependency 'CapacitorCordova' end`; -async function makeCordovaPlugin(appDir: string) { - const cordovaPluginPath = join(appDir, 'node_modules', CORDOVA_PLUGIN_ID); +async function makeCordovaPlugin(cordovaPluginPath: string) { const iosPath = join(cordovaPluginPath, 'src', 'ios'); const androidPath = join(cordovaPluginPath, 'android/com/getcapacitor'); await mkdirs(cordovaPluginPath); await writeFileAsync(join(cordovaPluginPath, 'plugin.js'), CODOVA_PLUGIN_JS); await writeFileAsync(join(cordovaPluginPath, 'plugin.xml'), CORDOVA_PLUGIN_XML); - await writeFileAsync(join(cordovaPluginPath, 'package.json'), JSON.stringify(CORDOVA_PLUGIN_PACKAGE)); + await writeFileAsync(join(cordovaPluginPath, 'package.json'), CORDOVA_PLUGIN_PACKAGE); await mkdirs(iosPath); await mkdirs(androidPath); await writeFileAsync(join(iosPath, 'CoolPlugin.m'), ''); diff --git a/core/package.json b/core/package.json index 227bd099a..d0e9f25bb 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/core", - "version": "1.4.0", + "version": "1.5.0", "description": "Capacitor: cross-platform mobile apps with the web", "homepage": "https://capacitor.ionicframework.com/", "author": "Ionic Team (https://ionicframework.com) ", diff --git a/core/src/core-plugin-definitions.ts b/core/src/core-plugin-definitions.ts index e3df9aea0..330ff53f5 100644 --- a/core/src/core-plugin-definitions.ts +++ b/core/src/core-plugin-definitions.ts @@ -395,6 +395,10 @@ export interface DevicePlugin extends Plugin { * Return information about the underlying device/os/platform */ getInfo(): Promise; + /** + * Return information about the battery + */ + getBatteryInfo(): Promise; /** * Get the device's current language locale code */ @@ -455,6 +459,9 @@ export interface DeviceInfo { * The total size of the normal data storage path for the OS, in bytes */ diskTotal?: number; +} + +export interface DeviceBatteryInfo { /** * A percentage (0 to 1) indicating how much the battery is charged */ @@ -663,12 +670,6 @@ export interface MkdirOptions { * The FilesystemDirectory to make the new directory in */ directory?: FilesystemDirectory; - /** - * @deprecated - use recursive - * Whether to create any missing parent directories as well - * Defaults to false - */ - createIntermediateDirectories?: boolean; /** * Whether to create any missing parent directories as well. * Defaults to false @@ -839,19 +840,8 @@ export interface GeolocationPosition { export interface GeolocationOptions { enableHighAccuracy?: boolean; // default: false - timeout?: number; // default: 10000, + timeout?: number; // default: 10000 maximumAge?: number; // default: 0 - /** - * Whether your app needs altitude data or not. This can impact the - * sensor the device uses, increasing energy consumption. - * Note: altitude information may not be available even when - * passing true here. Similarly, altitude data maybe be returned - * even if this value is false, in the case where doing so requires - * no increased energy consumption. - * - * Default: false - */ - requireAltitude?: boolean; // default: false } export type GeolocationWatchCallback = (position: GeolocationPosition, err?: any) => void; @@ -1032,6 +1022,24 @@ export interface LocalNotification { attachments?: LocalNotificationAttachment[]; actionTypeId?: string; extra?: any; + /** + * iOS only: set the thread identifier for notification grouping + */ + threadIdentifier?: string; + /** + * iOS 12+ only: set the summary argument for notification grouping + */ + summaryArgument?: string; + /** + * Android only: set the group identifier for notification grouping, like + * threadIdentifier on iOS. + */ + group?: string; + /** + * Android only: designate this notification as the summary for a group + * (should be used with the `group` property). + */ + groupSummary?: boolean; } export interface LocalNotificationSchedule { @@ -1429,6 +1437,16 @@ export interface PushNotification { data: any; click_action?: string; link?: string; + /** + * Android only: set the group identifier for notification grouping, like + * threadIdentifier on iOS. + */ + group?: string; + /** + * Android only: designate this notification as the summary for a group + * (should be used with the `group` property). + */ + groupSummary?: boolean; } export interface PushNotificationActionPerformed { @@ -1449,6 +1467,7 @@ export interface PushNotificationChannel { id: string; name: string; description: string; + sound: string; importance: 1 | 2 | 3 | 4 | 5; visibility?: -1 | 0 | 1 ; } @@ -1623,7 +1642,11 @@ export interface ToastPlugin extends Plugin { export interface ToastShowOptions { text: string; + /** + * Duration of the toast, either 'short' (2000ms, default) or 'long' (3500ms) + */ duration?: 'short' | 'long'; + position?: 'top' | 'center' | 'bottom'; } export interface WebViewPlugin extends Plugin { diff --git a/core/src/web/clipboard.ts b/core/src/web/clipboard.ts index 698fabde2..f0a74e1df 100644 --- a/core/src/web/clipboard.ts +++ b/core/src/web/clipboard.ts @@ -22,8 +22,8 @@ export class ClipboardPluginWeb extends WebPlugin implements ClipboardPlugin { return Promise.reject('Clipboard API not available in this browser'); } - if (options.string || options.url) { - await navigator.clipboard.writeText(options.string || options.url); + if (options.string !== undefined || options.url) { + await navigator.clipboard.writeText(options.string !== undefined ? options.string : options.url); } else if (options.image) { return Promise.reject('Setting images not supported on the web'); } diff --git a/core/src/web/device.ts b/core/src/web/device.ts index f173d4ed4..4889b5808 100644 --- a/core/src/web/device.ts +++ b/core/src/web/device.ts @@ -1,6 +1,7 @@ import { WebPlugin } from './index'; import { + DeviceBatteryInfo, DeviceInfo, DevicePlugin, DeviceLanguageCodeResult @@ -21,13 +22,6 @@ export class DevicePluginWeb extends WebPlugin implements DevicePlugin { async getInfo(): Promise { const ua = navigator.userAgent; const uaFields = this.parseUa(ua); - let battery: any = {}; - - try { - battery = await navigator.getBattery(); - } catch (e) { - // Let it fail, we don't care - } return Promise.resolve({ model: uaFields.model, @@ -38,12 +32,25 @@ export class DevicePluginWeb extends WebPlugin implements DevicePlugin { osVersion: uaFields.osVersion, manufacturer: navigator.vendor, isVirtual: false, - batteryLevel: battery.level, - isCharging: battery.charging, uuid: this.getUid() }); } + async getBatteryInfo(): Promise { + let battery: any = {}; + + try { + battery = await navigator.getBattery(); + } catch (e) { + // Let it fail, we don't care + } + + return Promise.resolve({ + batteryLevel: battery.level, + isCharging: battery.charging + }); + } + async getLanguageCode(): Promise { return { value: navigator.language diff --git a/core/src/web/filesystem.ts b/core/src/web/filesystem.ts index 8b0ff566e..0e2232cf0 100644 --- a/core/src/web/filesystem.ts +++ b/core/src/web/filesystem.ts @@ -246,12 +246,7 @@ export class FilesystemPluginWeb extends WebPlugin implements FilesystemPlugin { */ async mkdir(options: MkdirOptions): Promise { const path: string = this.getPath(options.directory, options.path); - const createIntermediateDirectories = options.createIntermediateDirectories; - if (options.createIntermediateDirectories !== undefined) { - console.warn('createIntermediateDirectories is deprecated, use recursive'); - } - const recursive = options.recursive; - const doRecursive = (createIntermediateDirectories || recursive); + const doRecursive = options.recursive; const parentPath = path.substr(0, path.lastIndexOf('/')); let depth = (path.match(/\//g) || []).length; diff --git a/core/src/web/toast.ts b/core/src/web/toast.ts index af2eb5e3e..afb686461 100644 --- a/core/src/web/toast.ts +++ b/core/src/web/toast.ts @@ -11,9 +11,9 @@ export class ToastPluginWeb extends WebPlugin implements ToastPlugin { } async show(options: ToastShowOptions) { - let duration = 3000; + let duration = 2000; if (options.duration) { - duration = options.duration === 'long' ? 5000 : 3000; + duration = options.duration === 'long' ? 3500 : 2000; } const toast = document.createElement('pwa-toast') as any; toast.duration = duration; diff --git a/electron-template/index.js b/electron-template/index.js index e2ddd68c7..5034d7fe3 100644 --- a/electron-template/index.js +++ b/electron-template/index.js @@ -51,7 +51,7 @@ async function createWindow () { if(useSplashScreen) { splashScreen = new CapacitorSplashScreen(mainWindow); - splashScreen.init(false); + splashScreen.init(); } else { mainWindow.loadURL(`file://${__dirname}/app/index.html`); mainWindow.webContents.on('dom-ready', () => { diff --git a/electron/index.js b/electron/index.js index 9a1aec775..27f0b3d74 100644 --- a/electron/index.js +++ b/electron/index.js @@ -14,19 +14,6 @@ function getURLFileContents(path) { }); } -const injectCapacitor = async function (url) { - console.warn('\nWARNING: injectCapacitor method is deprecated and will be removed in next major release. Check release notes for migration instructions\n') - try { - let urlFileContents = await getURLFileContents(url.substr(url.indexOf('://') + 3)); - let pathing = path.join(url.substr(url.indexOf('://') + 3), '../../node_modules/@capacitor/electron/dist/electron-bridge.js'); - urlFileContents = urlFileContents.replace('', ``); - return 'data:text/html;charset=UTF-8,' + urlFileContents; - } catch (e) { - console.error(e); - return url; - } -}; - const configCapacitor = async function(mainWindow) { let capConfigJson = JSON.parse(fs.readFileSync(`./capacitor.config.json`, 'utf-8')); const appendUserAgent = capConfigJson.electron && capConfigJson.electron.appendUserAgent ? capConfigJson.electron.appendUserAgent : capConfigJson.appendUserAgent; @@ -103,7 +90,7 @@ class CapacitorSplashScreen { }); } - init(inject = true) { + init() { let rootPath = app.getAppPath(); this.splashWindow = new BrowserWindow({ @@ -152,11 +139,7 @@ class CapacitorSplashScreen { this.splashWindow.webContents.on('dom-ready', async () => { this.splashWindow.show(); setTimeout(async () => { - if (inject) { - this.mainWindowRef.loadURL(await injectCapacitor(`file://${rootPath}/app/index.html`), { baseURLForDataURL: `file://${rootPath}/app/` }); - } else { - this.mainWindowRef.loadURL(`file://${rootPath}/app/index.html`); - } + this.mainWindowRef.loadURL(`file://${rootPath}/app/index.html`); }, 4500); }); @@ -181,7 +164,6 @@ class CapacitorSplashScreen { } module.exports = { - injectCapacitor, configCapacitor, CapacitorSplashScreen }; diff --git a/electron/package.json b/electron/package.json index 15a030702..acaecc42d 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor/electron", - "version": "1.4.0", + "version": "1.5.0", "description": "Capacitor: cross-platform mobile apps with the web", "homepage": "https://capacitor.ionicframework.com/", "author": "Ionic Team (https://ionicframework.com) ", @@ -62,7 +62,7 @@ ] }, "dependencies": { - "@capacitor/core": "^1.4.0" + "@capacitor/core": "^1.5.0" }, "gitHead": "844c0feba4a801ee5041429a82d0f805c9e665b0" } diff --git a/electron/src/electron/device.ts b/electron/src/electron/device.ts index 200d333ff..0c4ea7cff 100644 --- a/electron/src/electron/device.ts +++ b/electron/src/electron/device.ts @@ -1,4 +1,4 @@ -import { DeviceInfo, DeviceLanguageCodeResult, DevicePlugin, DevicePluginWeb, WebPlugin } from "@capacitor/core"; +import { DeviceBatteryInfo, DeviceInfo, DeviceLanguageCodeResult, DevicePlugin, DevicePluginWeb, WebPlugin } from "@capacitor/core"; declare var navigator: any; const webDevice = new DevicePluginWeb(); @@ -23,12 +23,19 @@ export class DevicePluginElectron extends WebPlugin implements DevicePlugin { osVersion: info.osVersion, manufacturer: navigator.vendor, isVirtual: false, - batteryLevel: info.batteryLevel, - isCharging: info.isCharging, uuid: info.uuid }; } + async getBatteryInfo(): Promise { + var batInfo = await webDevice.getBatteryInfo(); + + return { + batteryLevel: batInfo.batteryLevel, + isCharging: batInfo.isCharging + }; + } + async getLanguageCode(): Promise { return webDevice.getLanguageCode(); } diff --git a/electron/src/electron/filesystem.ts b/electron/src/electron/filesystem.ts index 43e7fd8a6..5cfff5e6d 100644 --- a/electron/src/electron/filesystem.ts +++ b/electron/src/electron/filesystem.ts @@ -113,10 +113,7 @@ export class FilesystemPluginElectron extends WebPlugin implements FilesystemPlu if(Object.keys(this.fileLocations).indexOf(options.directory) === -1) reject(`${options.directory} is currently not supported in the Electron implementation.`); let lookupPath = this.fileLocations[options.directory] + options.path; - if (options.createIntermediateDirectories !== undefined) { - console.warn('createIntermediateDirectories is deprecated, use recursive'); - } - const doRecursive = options.createIntermediateDirectories || options.recursive; + const doRecursive = options.recursive; this.NodeFS.mkdir(lookupPath, { recursive: doRecursive }, (err:any) => { if(err) { reject(err); diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 65f008dca..693daa048 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "com.getcapacitor.app" minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/example/android/build.gradle b/example/android/build.gradle index 2c2f10b9c..40584401c 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.2' + classpath 'com.android.tools.build:gradle:3.5.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 8c2e81aa2..e294c0213 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/example/src/pages/clipboard/clipboard.html b/example/src/pages/clipboard/clipboard.html index 0a625c734..00a0819d2 100644 --- a/example/src/pages/clipboard/clipboard.html +++ b/example/src/pages/clipboard/clipboard.html @@ -20,6 +20,9 @@ + @@ -31,6 +34,9 @@ + diff --git a/example/src/pages/clipboard/clipboard.ts b/example/src/pages/clipboard/clipboard.ts index 4b50aea21..76b409748 100644 --- a/example/src/pages/clipboard/clipboard.ts +++ b/example/src/pages/clipboard/clipboard.ts @@ -56,6 +56,19 @@ export class ClipboardPage { console.log('Got string from clipboard:', str.value); } + clipboardSetEmptyString() { + Plugins.Clipboard.write({ + string: "" + }); + } + + async clipboardGetEmptyString() { + let str = await Plugins.Clipboard.read({ + type: "string" + }); + console.log('Got string from clipboard:', str.value); + } + clipboardSetURL() { Plugins.Clipboard.write({ url: "http://google.com/" diff --git a/example/src/pages/toast/toast.html b/example/src/pages/toast/toast.html index 7aea0717e..e154e3e1d 100644 --- a/example/src/pages/toast/toast.html +++ b/example/src/pages/toast/toast.html @@ -13,5 +13,7 @@ - + + + diff --git a/example/src/pages/toast/toast.ts b/example/src/pages/toast/toast.ts index 11c45b7ba..23c780770 100644 --- a/example/src/pages/toast/toast.ts +++ b/example/src/pages/toast/toast.ts @@ -25,9 +25,10 @@ export class ToastPage { console.log('ionViewDidLoad ToastPage'); } - async show() { + async show(position: 'top' | 'center' | 'bottom') { await Toast.show({ - text: 'Hello!' + text: 'Hello!', + position, }); } } diff --git a/ios/Capacitor/Capacitor/CAPBridge.swift b/ios/Capacitor/Capacitor/CAPBridge.swift index efb2f0c4b..bc4a60dfa 100644 --- a/ios/Capacitor/Capacitor/CAPBridge.swift +++ b/ios/Capacitor/Capacitor/CAPBridge.swift @@ -176,7 +176,7 @@ enum BridgeError: Error { self.isActive = true appStatePlugin?.fireChange(isActive: self.isActive) } - NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: OperationQueue.main) { (notification) in + NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: OperationQueue.main) { (notification) in CAPLog.print("APP INACTIVE") self.isActive = false appStatePlugin?.fireChange(isActive: self.isActive) diff --git a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift b/ios/Capacitor/Capacitor/CAPBridgeViewController.swift index 9980c1244..85fce6148 100644 --- a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift +++ b/ios/Capacitor/Capacitor/CAPBridgeViewController.swift @@ -73,11 +73,19 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr webView = WKWebView(frame: .zero, configuration: webViewConfiguration) webView?.scrollView.bounces = false - - webView?.scrollView.contentInsetAdjustmentBehavior = .never - + let availableInsets = ["automatic", "scrollableAxes", "never", "always"] + if let contentInset = (capConfig.getValue("ios.contentInset") as? String), + let index = availableInsets.firstIndex(of: contentInset) { + webView?.scrollView.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior.init(rawValue: index)! + } else { + webView?.scrollView.contentInsetAdjustmentBehavior = .never + } + webView?.uiDelegate = self webView?.navigationDelegate = self + if let allowsLinkPreview = (capConfig.getValue("ios.allowsLinkPreview") as? Bool) { + webView?.allowsLinkPreview = allowsLinkPreview + } webView?.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs") view = webView diff --git a/ios/Capacitor/Capacitor/Plugins/Clipboard.swift b/ios/Capacitor/Capacitor/Plugins/Clipboard.swift index 2f1c5e70d..6bfd992cb 100644 --- a/ios/Capacitor/Capacitor/Plugins/Clipboard.swift +++ b/ios/Capacitor/Capacitor/Plugins/Clipboard.swift @@ -23,32 +23,46 @@ public class CAPClipboardPlugin : CAPPlugin { @objc func read(_ call: CAPPluginCall) { let type = call.options["type"] as? String ?? "string" - - if type == "string" && UIPasteboard.general.hasStrings { - call.success([ - "value": UIPasteboard.general.string! - ]) - return - } - - if type == "url" && UIPasteboard.general.hasURLs { - let url = UIPasteboard.general.url! - call.success([ - "value": url.absoluteString - ]) + + if type == "string" { + if UIPasteboard.general.hasStrings { + call.success([ + "value": UIPasteboard.general.string! + ]) + } else { + call.error("Unable to get string from clipboard") + } return } - - if type == "image" && UIPasteboard.general.hasImages { - let image = UIPasteboard.general.image! - let data = image.pngData() - if let base64 = data?.base64EncodedString() { + + if type == "url" { + if UIPasteboard.general.hasURLs { + let url = UIPasteboard.general.url! call.success([ - "value": base64 + "value": url.absoluteString ]) + } else { + call.error("Unable to get url from clipboard") } return } + + if type == "image" { + if UIPasteboard.general.hasImages { + let image = UIPasteboard.general.image! + let data = image.pngData() + if let base64 = data?.base64EncodedString() { + call.success([ + "value": base64 + ]) + } + } else { + call.error("Unable to get image from clipboard") + } + return + } + + call.error("Invalid type") } } diff --git a/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m b/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m index ed38413ac..8d8b4e895 100644 --- a/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m +++ b/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m @@ -40,6 +40,7 @@ CAP_PLUGIN(CAPDevicePlugin, "Device", CAP_PLUGIN_METHOD(getInfo, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(getBatteryInfo, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(getLanguageCode, CAPPluginReturnPromise); ) diff --git a/ios/Capacitor/Capacitor/Plugins/Device.swift b/ios/Capacitor/Capacitor/Plugins/Device.swift index 04f7cfd83..8444939cc 100644 --- a/ios/Capacitor/Capacitor/Plugins/Device.swift +++ b/ios/Capacitor/Capacitor/Plugins/Device.swift @@ -5,19 +5,17 @@ public typealias DeviceInfo = [String:Any] @objc(CAPDevicePlugin) public class CAPDevicePlugin: CAPPlugin { let diagnostics: Diagnostics = Diagnostics() - + @objc func getInfo(_ call: CAPPluginCall) { var isSimulator = false #if arch(i386) || arch(x86_64) isSimulator = true #endif - - UIDevice.current.isBatteryMonitoringEnabled = true - + let memUsed = diagnostics.getMemoryUsage() let diskFree = diagnostics.getFreeDiskSize() ?? 0 let diskTotal = diagnostics.getTotalDiskSize() ?? 0 - + call.success([ "memUsed": memUsed, "diskFree": diskFree, @@ -30,14 +28,21 @@ public class CAPDevicePlugin: CAPPlugin { "platform": "ios", "manufacturer": "Apple", "uuid": UIDevice.current.identifierForVendor!.uuidString, - "batteryLevel": UIDevice.current.batteryLevel, - "isCharging": UIDevice.current.batteryState == .charging || UIDevice.current.batteryState == .full, "isVirtual": isSimulator ]) - + } + + @objc func getBatteryInfo(_ call: CAPPluginCall) { + UIDevice.current.isBatteryMonitoringEnabled = true + + call.success([ + "batteryLevel": UIDevice.current.batteryLevel, + "isCharging": UIDevice.current.batteryState == .charging || UIDevice.current.batteryState == .full + ]) + UIDevice.current.isBatteryMonitoringEnabled = false } - + @objc func getLanguageCode(_ call: CAPPluginCall) { let code = String(Locale.preferredLanguages[0].prefix(2)) call.success([ diff --git a/ios/Capacitor/Capacitor/Plugins/Filesystem.swift b/ios/Capacitor/Capacitor/Plugins/Filesystem.swift index 9c8046fb5..889c1e9ae 100644 --- a/ios/Capacitor/Capacitor/Plugins/Filesystem.swift +++ b/ios/Capacitor/Capacitor/Plugins/Filesystem.swift @@ -222,10 +222,6 @@ public class CAPFilesystemPlugin : CAPPlugin { return } - let createIntermediateDirectories = call.get("createIntermediateDirectories", Bool.self, false)! - if let _ = call.get("createIntermediateDirectories", Bool.self) { - CAPLog.print("createIntermediateDirectories is deprecated, use recursive") - } let recursive = call.get("recursive", Bool.self, false)! let directoryOption = call.get("directory", String.self, DEFAULT_DIRECTORY)! guard let fileUrl = getFileUrl(path, directoryOption) else { @@ -234,7 +230,7 @@ public class CAPFilesystemPlugin : CAPPlugin { } do { - try FileManager.default.createDirectory(at: fileUrl, withIntermediateDirectories: createIntermediateDirectories || recursive, attributes: nil) + try FileManager.default.createDirectory(at: fileUrl, withIntermediateDirectories: recursive, attributes: nil) call.success() } catch let error as NSError { handleError(call, error.localizedDescription, error) diff --git a/ios/Capacitor/Capacitor/Plugins/Geolocation.swift b/ios/Capacitor/Capacitor/Plugins/Geolocation.swift index 6b16e339c..8f384ad41 100644 --- a/ios/Capacitor/Capacitor/Plugins/Geolocation.swift +++ b/ios/Capacitor/Capacitor/Plugins/Geolocation.swift @@ -14,7 +14,7 @@ public struct GeolocationCoords { class GetLocationHandler: NSObject, CLLocationManagerDelegate { var locationManager = CLLocationManager() var call: CAPPluginCall - + init(call: CAPPluginCall, options: [String:Any]) { self.call = call @@ -23,19 +23,24 @@ class GetLocationHandler: NSObject, CLLocationManagerDelegate { // TODO: Allow user to configure accuracy, request/authorization mode self.locationManager.delegate = self self.locationManager.requestWhenInUseAuthorization() + let shouldWatch = options["watch"] as! Bool if call.getBool("enableHighAccuracy", false)! { + if shouldWatch { self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation - } else { + } else { self.locationManager.desiredAccuracy = kCLLocationAccuracyBest + } + } else { + self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers } - - if let shouldWatch = options["watch"], shouldWatch as? Bool == true { + + if shouldWatch { self.locationManager.startUpdatingLocation() } else { self.locationManager.requestLocation() } } - + public func stopUpdating() { self.locationManager.stopUpdatingLocation() } diff --git a/ios/Capacitor/Capacitor/Plugins/LocalNotifications.swift b/ios/Capacitor/Capacitor/Plugins/LocalNotifications.swift index 8b608fa2d..c19c8c763 100644 --- a/ios/Capacitor/Capacitor/Plugins/LocalNotifications.swift +++ b/ios/Capacitor/Capacitor/Plugins/LocalNotifications.swift @@ -165,6 +165,8 @@ public class CAPLocalNotificationsPlugin : CAPPlugin { let sound = notification["sound"] as? String let attachments = notification["attachments"] as? JSArray let extra = notification["extra"] as? JSObject ?? [:] + let threadIdentifier = notification["threadIdentifier"] as? String + let summaryArgument = notification["summaryArgument"] as? String let content = UNMutableNotificationContent() content.title = NSString.localizedUserNotificationString(forKey: title, arguments: nil) @@ -175,6 +177,14 @@ public class CAPLocalNotificationsPlugin : CAPPlugin { if actionTypeId != nil { content.categoryIdentifier = actionTypeId! } + + if let threadIdentifier = threadIdentifier { + content.threadIdentifier = threadIdentifier + } + + if let summaryArgument = summaryArgument, #available(iOS 12, *) { + content.summaryArgument = summaryArgument + } if sound != nil { content.sound = UNNotificationSound(named: UNNotificationSoundName(sound!)) diff --git a/ios/Capacitor/Capacitor/Plugins/Toast.swift b/ios/Capacitor/Capacitor/Plugins/Toast.swift index 07350f727..ce0f0c58b 100644 --- a/ios/Capacitor/Capacitor/Plugins/Toast.swift +++ b/ios/Capacitor/Capacitor/Plugins/Toast.swift @@ -10,8 +10,9 @@ public class CAPToastPlugin : CAPPlugin { call.error("text must be provided and must be a string.") return } - let durationStyle = call.get("durationStyle", String.self, "long")! - let duration = durationStyle == "short" ? 1500 : 3000 + let durationType = call.get("duration", String.self, "short")! + let duration = durationType == "long" ? 3500 : 2000 + let position = call.get("position", String.self, "bottom") DispatchQueue.main.async { let vc = self.bridge!.viewController @@ -34,11 +35,22 @@ public class CAPToastPlugin : CAPPlugin { let minWidth = min(maxSizeTitle.width, expectedSizeTitle.width) let minHeight = min(maxSizeTitle.height, expectedSizeTitle.height) expectedSizeTitle = CGSize(width: minWidth, height: minHeight) + + let height = expectedSizeTitle.height+32 + let y: CGFloat + if (position == "top") { + y = 40 + } else if (position == "center") { + y = (vc.view.bounds.size.height/2) - (height/2) + } else { + y = vc.view.bounds.size.height - height - (height/2) + } + lb.frame = CGRect( x: ((vc.view.bounds.size.width)/2) - ((expectedSizeTitle.width+32)/2), - y: (vc.view.bounds.size.height-(expectedSizeTitle.height+32)) - ((expectedSizeTitle.height+32)/2), + y: y, width: expectedSizeTitle.width+32, - height: expectedSizeTitle.height+32) + height: height) lb.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) self.toast = lb diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h b/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h index 78a29fbc7..2947af89a 100644 --- a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h +++ b/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h @@ -19,18 +19,35 @@ #import -typedef enum { - CDVCommandStatus_NO_RESULT = 0, - CDVCommandStatus_OK, - CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION, - CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION, - CDVCommandStatus_INSTANTIATION_EXCEPTION, - CDVCommandStatus_MALFORMED_URL_EXCEPTION, - CDVCommandStatus_IO_EXCEPTION, - CDVCommandStatus_INVALID_ACTION, - CDVCommandStatus_JSON_EXCEPTION, - CDVCommandStatus_ERROR -} CDVCommandStatus; +typedef NS_ENUM(NSUInteger, CDVCommandStatus) { + CDVCommandStatus_NO_RESULT NS_SWIFT_NAME(noResult) = 0, + CDVCommandStatus_OK NS_SWIFT_NAME(ok), + CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION NS_SWIFT_NAME(classNotFoundException), + CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION NS_SWIFT_NAME(illegalAccessException), + CDVCommandStatus_INSTANTIATION_EXCEPTION NS_SWIFT_NAME(instantiationException), + CDVCommandStatus_MALFORMED_URL_EXCEPTION NS_SWIFT_NAME(malformedUrlException), + CDVCommandStatus_IO_EXCEPTION NS_SWIFT_NAME(ioException), + CDVCommandStatus_INVALID_ACTION NS_SWIFT_NAME(invalidAction), + CDVCommandStatus_JSON_EXCEPTION NS_SWIFT_NAME(jsonException), + CDVCommandStatus_ERROR NS_SWIFT_NAME(error) +}; + +// This exists to preserve compatibility with early Swift plugins, who are +// using CDVCommandStatus as ObjC-style constants rather than as Swift enum +// values. +// This declares extern'ed constants (implemented in CDVPluginResult.m) +#define SWIFT_ENUM_COMPAT_HACK(enumVal) extern const CDVCommandStatus SWIFT_##enumVal NS_SWIFT_NAME(enumVal) +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_NO_RESULT); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_OK); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_INSTANTIATION_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_MALFORMED_URL_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_IO_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_INVALID_ACTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_JSON_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_ERROR); +#undef SWIFT_ENUM_COMPAT_HACK @interface CDVPluginResult : NSObject {} diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m b/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m index 4d466482a..a2cd71e1b 100644 --- a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m +++ b/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m @@ -19,6 +19,23 @@ Licensed to the Apache Software Foundation (ASF) under one #import "CDVPluginResult.h" +// This exists to preserve compatibility with early Swift plugins, who are +// using CDVCommandStatus as ObjC-style constants rather than as Swift enum +// values. +// These constants alias the enum values back to their previous names. +#define SWIFT_ENUM_COMPAT_HACK(enumVal) const CDVCommandStatus SWIFT_##enumVal NS_SWIFT_NAME(enumVal) = enumVal +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_NO_RESULT); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_OK); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_INSTANTIATION_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_MALFORMED_URL_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_IO_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_INVALID_ACTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_JSON_EXCEPTION); +SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_ERROR); +#undef SWIFT_ENUM_COMPAT_HACK + @interface CDVPluginResult () - (CDVPluginResult*)initWithStatus:(CDVCommandStatus)statusOrdinal message:(id)theMessage; diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h b/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h index e54931c23..81ed0069a 100644 --- a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h +++ b/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h @@ -23,6 +23,7 @@ @property (nonatomic, readonly, strong) NSMutableDictionary* pluginObjects; @property (nonatomic, readonly, strong) NSMutableDictionary* settings; +@property (nonatomic, readonly, weak) UIView* webView; - (id) getCommandInstance:(NSString*)className; diff --git a/lerna.json b/lerna.json index 0e72356fd..21fb2d293 100644 --- a/lerna.json +++ b/lerna.json @@ -8,5 +8,5 @@ "./core/", "./electron/" ], - "version": "1.4.0" + "version": "1.5.0" } diff --git a/plugin-template/android/build.gradle b/plugin-template/android/build.gradle index a73bc9975..f142bee00 100644 --- a/plugin-template/android/build.gradle +++ b/plugin-template/android/build.gradle @@ -4,17 +4,17 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.2' + classpath 'com.android.tools.build:gradle:3.5.3' } } apply plugin: 'com.android.library' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -44,4 +44,3 @@ dependencies { androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } - diff --git a/plugin-template/android/gradle/wrapper/gradle-wrapper.properties b/plugin-template/android/gradle/wrapper/gradle-wrapper.properties index f715fac11..9bbaef5f8 100644 --- a/plugin-template/android/gradle/wrapper/gradle-wrapper.properties +++ b/plugin-template/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/site/docs-md/android/index.md b/site/docs-md/android/index.md index f9ec56b7c..dc33d647f 100644 --- a/site/docs-md/android/index.md +++ b/site/docs-md/android/index.md @@ -64,7 +64,7 @@ If you encountered any issue above, please let us know by filing an issue on the ### Next Steps -If your app ran you are now ready to continue developing and building your app. Use the various APIs available, Capacitor or Cordova plugins, or custom native code to build our the rest of your app. +If your app ran you are now ready to continue developing and building your app. Use the various APIs available, Capacitor or Cordova plugins, or custom native code to build out the rest of your app. ## Further Reading diff --git a/site/docs-md/apis/network/index.md b/site/docs-md/apis/network/index.md index a280e4150..3db53b39d 100644 --- a/site/docs-md/apis/network/index.md +++ b/site/docs-md/apis/network/index.md @@ -48,10 +48,6 @@ The Network API requires the following permission be added to your `AndroidManif This permission allows the app to access information about the current network, such as whether it is connected to wifi or cellular. -## Example Guides - -[Network: Ionic 4 and Network Detection with Capacitor ›](https://developer.school/posts/ionic-4-network-detection-with-capacitor/) - ## API - \ No newline at end of file + diff --git a/site/docs-md/apis/splash-screen/index.md b/site/docs-md/apis/splash-screen/index.md index f8e781ec6..c9da14334 100644 --- a/site/docs-md/apis/splash-screen/index.md +++ b/site/docs-md/apis/splash-screen/index.md @@ -132,38 +132,12 @@ These config parameters are available in `capacitor.config.json`: ### Android -If your splash screen images aren't named "splash.png" but for example "screen.png" you have to change `"androidSplashResourceName": "screen"` in `capacitor.config.json` and change the following files in you're Android app as well: +To use splash screen images named something other than `splash.png`, set `androidSplashResourceName` to the new resource name in `capacitor.config.json`. Additionally, in `android/app/src/main/res/values/styles.xml`, change the resource name in the following block: -`android/app/src/main/res/drawable/launch_splash.xml` - -replace -```xml - -``` -with -```xml - -``` - -`android/app/src/main/res/values/styles.xml` - -replace -```xml - -``` -with ```xml - + ``` ## Example Guides diff --git a/site/docs-md/basics/configuring-your-app.md b/site/docs-md/basics/configuring-your-app.md index efc70394a..3976bf554 100644 --- a/site/docs-md/basics/configuring-your-app.md +++ b/site/docs-md/basics/configuring-your-app.md @@ -110,6 +110,11 @@ The current ones you might configure are: "appendUserAgent": "string to append for iOS", // Background color of Capacitor WebView for iOS only "backgroundColor": "#ffffffff", + // Configure the WebView's UIScrollView's content inset behavior + // Default is never + // Possible values are "automatic", "scrollableAxes", "never" and "always" + // https://developer.apple.com/documentation/uikit/uiscrollview/contentinsetadjustmentbehavior + "contentInset": "always", // Configure the Swift version to be used for Cordova plugins. // Default is 4.0 "cordovaSwiftVersion": "3.0", @@ -117,7 +122,10 @@ The current ones you might configure are: // Default is 11.0 "minVersion": "11.3", // Some Cordova plugins require to configure the linker flags - "cordovaLinkerFlags": ["-ObjC"] + "cordovaLinkerFlags": ["-ObjC"], + // A Boolean value that determines whether pressing on a link displays a preview of + // the destination for the link. + "allowsLinkPreview": false }, "electron": { // User agent of Capacitor WebView for Electron diff --git a/site/docs-md/community/plugins.md b/site/docs-md/community/plugins.md index d47ca7372..a0bad7ed5 100644 --- a/site/docs-md/community/plugins.md +++ b/site/docs-md/community/plugins.md @@ -3,6 +3,7 @@ title: Capacitor Community Plugins description: Capacitor Community Plugins url: /docs/community/plugins contributors: + - AntoninBeaufort --- # Capacitor Community Plugins @@ -50,14 +51,12 @@ Are we missing your awesome plugin? [Add it to this page](https://github.com/ion | Name | NPM package | GitHub | Notes | | ----------------------- | ----------- | ------ | ------ | -| Data Storage SQLite | `capacitor-data-storage-sqlite` | | | | Secure Storage Plugin | `capacitor-secure-storage-plugin` | | | ## Video | Name | NPM package | GitHub | Notes | | ----------------------- | ----------- | ------ | ------ | -| Video Player | `capacitor-video-player` | | | | YouTube | `capacitor-youtube-player` | | | | Twilio iOS | `twilio-ios-capacitor` | | Video calls with Twilio | | Video Recorder | `@teamhive/capacitor-video-recorder` | | | @@ -93,7 +92,7 @@ Are we missing your awesome plugin? [Add it to this page](https://github.com/ion | Name | NPM package | GitHub | Notes | | ----------------------- | ----------- | ------ | ------ | -| Fused Location | `@johannesnormannjensen/capacitor-fused-location` | | | +| Fused Location | `@jonoj/capacitor-fused-location` | | | | Geofence Tracker | `capacitor-geofence-tracker` | | | | Fancy Geo | `capacitor-fancy-geo` | | | | [Radar](https://radar.io) | `capacitor-radar` | | | @@ -106,11 +105,15 @@ Are we missing your awesome plugin? [Add it to this page](https://github.com/ion ## Audio +| Name | NPM package | GitHub | Notes | +| ----------------------- | ----------- | ------ | ------ | +| Voice Recorder | `capacitor-voice-recorder` | | | + ## Ads | Name | NPM package | GitHub | Notes | | ----------------------- | ----------- | ------ | ------ | -| AdMob | `capacitor-admob` | | Android only (currently) | +| AdMob | `capacitor-admob` | | iOS, Android | | AdMob | `@rdlabo/capacitor-admob` | | | ## Notifications @@ -156,6 +159,7 @@ Are we missing your awesome plugin? [Add it to this page](https://github.com/ion | Image Cache | `capacitor-image-cache` | | | | Image Crop | `capacitor-image-crop` | | | | Media Operations | `capacitor-media` | | | +| Code Scanner | `@rdlabo/capacitor-codescanner` | | iOS only (currently) | ## Printers diff --git a/site/docs-md/guides/community.md b/site/docs-md/guides/community.md index 4453ba98a..eef4d475f 100644 --- a/site/docs-md/guides/community.md +++ b/site/docs-md/guides/community.md @@ -24,8 +24,6 @@ contributors: [Camera: Building an Ionic Framework Camera App](/docs/guides/ionic-framework-app) -[Network: Ionic 4 and Network Detection with Capacitor ›](https://developer.school/posts/ionic-4-network-detection-with-capacitor/) - [Push Notifications: Using Push Notifications with Firebase in an Ionic Angular App](/docs/guides/push-notifications-firebase) [Splash Screen: Creating a Dynamic/Adaptable Splash Screen for Capacitor (Android) ›](https://www.joshmorony.com/creating-a-dynamic-universal-splash-screen-for-capacitor-android/) diff --git a/site/package-lock.json b/site/package-lock.json index faf111e61..f2cd7ba8c 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -25,13 +25,10 @@ } }, "@stencil/sass": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-0.1.1.tgz", - "integrity": "sha512-vhEP1Tk+/ADjiohFvjSeNQNGUIAhL4Diolg8TiA5+H1zbtKNoZjoCVEt2+w/s846tpsOCsDZYLe7NZABMSQ1Lw==", - "dev": true, - "requires": { - "node-sass": "4.9.3" - } + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-1.1.1.tgz", + "integrity": "sha512-Nny3JiFkpQa0RdXWCa4pzhKQYnHuDNzC9c4w35FcaZHXBVuZ1UHSHc7wI7By9SS1auYcySqpPOBVzgoCqXcYVQ==", + "dev": true }, "@stencil/state-tunnel": { "version": "0.0.9-1", @@ -102,12 +99,6 @@ "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", "dev": true }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -160,12 +151,6 @@ "uri-js": "^4.2.2" } }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, "ansi-align": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", @@ -236,12 +221,6 @@ "normalize-path": "^2.1.1" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -272,16 +251,6 @@ "readable-stream": "^2.0.0" } }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -315,12 +284,6 @@ "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -375,12 +338,6 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", - "dev": true - }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -528,15 +485,6 @@ "safe-buffer": "^5.1.1" } }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "~2.0.0" - } - }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -758,22 +706,6 @@ "unset-value": "^1.0.0" } }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, "capture-stack-trace": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", @@ -788,7 +720,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -931,23 +863,6 @@ "tiny-emitter": "^2.0.0" } }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -1124,12 +1039,6 @@ } } }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -1234,16 +1143,6 @@ } } }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, "crypto-random-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", @@ -1274,15 +1173,6 @@ "through2": "2.0.1" } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, "cycle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", @@ -1346,12 +1236,6 @@ "ms": "2.0.0" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -1424,12 +1308,6 @@ "dev": true, "optional": true }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -1517,15 +1395,6 @@ "once": "^1.4.0" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, "es5-ext": { "version": "0.10.50", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", @@ -1965,16 +1834,6 @@ "unpipe": "~1.0.0" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, "firebase": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/firebase/-/firebase-2.4.2.tgz", @@ -2803,43 +2662,6 @@ } } }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } - }, "gcp-metadata": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.3.1.tgz", @@ -2850,18 +2672,6 @@ "retry-request": "^3.0.0" } }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -2944,17 +2754,6 @@ "ini": "^1.3.4" } }, - "globule": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", - "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - } - }, "good-listener": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", @@ -3066,12 +2865,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3116,12 +2909,6 @@ "integrity": "sha1-KRfrRL3JByztqUJXlUOEfjAX/k4=", "dev": true }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", @@ -3182,21 +2969,6 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "in-publish": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3240,12 +3012,6 @@ "through": "^2.3.6" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", @@ -3278,12 +3044,6 @@ } } }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -3359,15 +3119,6 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -3482,12 +3233,6 @@ "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", "dev": true }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -3561,12 +3306,6 @@ "valid-url": "^1" } }, - "js-base64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", - "dev": true - }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -3765,15 +3504,6 @@ "readable-stream": "^2.0.5" } }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", @@ -3790,19 +3520,6 @@ "type-check": "~0.3.2" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", @@ -3836,18 +3553,6 @@ "lodash._objecttypes": "~2.4.1" } }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -3910,12 +3615,6 @@ "lodash.isobject": "~2.4.1" } }, - "lodash.mergewith": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", - "dev": true - }, "lodash.noop": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-3.0.1.tgz", @@ -3962,16 +3661,6 @@ "lodash.keys": "~2.4.1" } }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -4020,12 +3709,6 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -4063,24 +3746,6 @@ "timers-ext": "^0.1.5" } }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -4244,7 +3909,8 @@ "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true + "dev": true, + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -4321,167 +3987,6 @@ "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", "dev": true }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "dev": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "node-sass": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.3.tgz", - "integrity": "sha512-XzXyGjO+84wxyH7fV6IwBOTrEBe2f0a6SBze9QWWYR/cL74AcQUks2AsqcCZenl/Fp/JVbuEaLpgrLtocwBUww==", - "dev": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash.assign": "^4.2.0", - "lodash.clonedeep": "^4.3.2", - "lodash.mergewith": "^4.6.0", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.10.0", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "2.87.0", - "sass-graph": "^2.2.4", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, - "requires": { - "ajv": "^5.1.0", - "har-schema": "^2.0.0" - } - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", - "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "requires": { - "punycode": "^1.4.1" - } - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", @@ -4500,18 +4005,6 @@ "path-key": "^2.0.0" } }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -4656,15 +4149,6 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -4699,15 +4183,6 @@ "semver": "^5.1.0" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -4732,15 +4207,6 @@ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -4759,56 +4225,18 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", "dev": true }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, "pkginfo": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", @@ -4949,30 +4377,9 @@ "strip-json-comments": "~2.0.1" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -5007,16 +4414,6 @@ "mute-stream": "0.0.5" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -5070,15 +4467,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -5145,27 +4533,6 @@ "tough-cookie": "^2.3.3" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -5278,45 +4645,12 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", - "dev": true, - "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" - } - }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "dev": true, - "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, "select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", @@ -5380,12 +4714,6 @@ "send": "0.17.1" } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -5574,38 +4902,6 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", - "dev": true - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -5671,15 +4967,6 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", @@ -5724,30 +5011,12 @@ "ansi-regex": "^2.0.0" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -5840,17 +5109,6 @@ "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", "dev": true }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, "tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", @@ -6042,21 +5300,6 @@ "punycode": "^2.1.0" } }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "requires": { - "glob": "^7.1.2" - } - }, "try-require": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/try-require/-/try-require-1.2.1.tgz", @@ -6379,16 +5622,6 @@ "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -6456,21 +5689,6 @@ "isexe": "^2.0.0" } }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "widest-line": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", @@ -6706,16 +5924,6 @@ "integrity": "sha512-IQOUi+RLhvYCiv80RP23KBW/NTtIvzvjex28B8NW1jOm+iV4VIu3VXKXTA6er5/wjjuhmtB28qEAUqADLAyOSg==", "dev": true }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -6764,64 +5972,12 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } - }, "zip-stream": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", diff --git a/site/package.json b/site/package.json index 04dce556d..b8779197c 100644 --- a/site/package.json +++ b/site/package.json @@ -15,7 +15,7 @@ "devDependencies": { "@stencil/core": "^0.17.0", "@stencil/router": "^0.3.1", - "@stencil/sass": "^0.1.1", + "@stencil/sass": "^1.1.1", "@stencil/state-tunnel": "0.0.9-1", "@stencil/utils": "0.0.5", "@types/glob": "^7.1.0", diff --git a/site/src/assets/docs-content/apis/accessibility/api.html b/site/src/assets/docs-content/apis/accessibility/api.html index fc5e79f0d..8762fe82b 100644 --- a/site/src/assets/docs-content/apis/accessibility/api.html +++ b/site/src/assets/docs-content/apis/accessibility/api.html @@ -4,27 +4,27 @@

isScreenReaderEnabled

- isScreenReaderEnabled(): Promise<ScreenReaderEnabledResult> + isScreenReaderEnabled(): Promise<ScreenReaderEnabledResult>
Check if a screen reader is enabled on the device
- Returns: Promise<ScreenReaderEnabledResult> + Returns: Promise<ScreenReaderEnabledResult>

speak

- speak(options: AccessibilitySpeakOptions): Promise<void> + speak(options: AccessibilitySpeakOptions): Promise<void>
Speak a string with a connected screen reader.
options -AccessibilitySpeakOptions +AccessibilitySpeakOptions
@@ -35,7 +35,7 @@

speak

addListener

- addListener(eventName: "accessibilityScreenReaderStateChange", listenerFunc: ScreenReaderStateChangeCallback): PluginListenerHandle + addListener(eventName: "accessibilityScreenReaderStateChange", listenerFunc: ScreenReaderStateChangeCallback): PluginListenerHandle
Listen for screen reader state change (on/off)
@@ -47,7 +47,7 @@

addListener

listenerFunc -ScreenReaderStateChangeCallback +ScreenReaderStateChangeCallback
@@ -57,7 +57,7 @@

addListener

Interfaces Used

-
+

ScreenReaderEnabledResult

interface ScreenReaderEnabledResult @@ -74,7 +74,7 @@

ScreenReaderEnabledResult

} -
+

AccessibilitySpeakOptions

interface AccessibilitySpeakOptions @@ -100,7 +100,7 @@

AccessibilitySpeakOptions

} -
+

ScreenReaderStateChangeCallback

type alias ScreenReaderStateChangeCallback diff --git a/site/src/assets/docs-content/apis/app/api.html b/site/src/assets/docs-content/apis/app/api.html index 19c1c0414..30f71f921 100644 --- a/site/src/assets/docs-content/apis/app/api.html +++ b/site/src/assets/docs-content/apis/app/api.html @@ -36,13 +36,13 @@

exitApp

getLaunchUrl

- getLaunchUrl(): Promise<AppLaunchUrl> + getLaunchUrl(): Promise<AppLaunchUrl>
Get the URL the app was launched with, if any
- Returns: Promise<AppLaunchUrl> + Returns: Promise<AppLaunchUrl>
@@ -67,7 +67,7 @@

openUrl

addListener

- addListener(eventName: "appStateChange", listenerFunc: (state: AppState) => void): PluginListenerHandle + addListener(eventName: "appStateChange", listenerFunc: (state: AppState) => void): PluginListenerHandle
Listen for changes in the App's active state (whether the app is in the foreground or background)
@@ -79,7 +79,7 @@

addListener

listenerFunc -(state: AppState) => void +(state: AppState) => void
@@ -90,7 +90,7 @@

addListener

addListener

- addListener(eventName: "appUrlOpen", listenerFunc: (data: AppUrlOpen) => void): PluginListenerHandle + addListener(eventName: "appUrlOpen", listenerFunc: (data: AppUrlOpen) => void): PluginListenerHandle
Listen for url open events for the app. This handles both custom URL scheme links as well as URLs your app handles (Universal Links on iOS and App Links on Android)
@@ -103,7 +103,7 @@

addListener

listenerFunc -(data: AppUrlOpen) => void +(data: AppUrlOpen) => void
@@ -114,7 +114,7 @@

addListener

addListener

- addListener(eventName: "appRestoredResult", listenerFunc: (data: AppRestoredResult) => void): PluginListenerHandle + addListener(eventName: "appRestoredResult", listenerFunc: (data: AppRestoredResult) => void): PluginListenerHandle
If the app was launched with previously persisted plugin call data, such as on Android when an activity returns to an app that was closed, this call will return any data @@ -128,7 +128,7 @@

addListener

listenerFunc -(data: AppRestoredResult) => void +(data: AppRestoredResult) => void
@@ -139,9 +139,11 @@

addListener

addListener

- addListener(eventName: "backButton", listenerFunc: (data: AppUrlOpen) => void): PluginListenerHandle + addListener(eventName: "backButton", listenerFunc: (data: AppUrlOpen) => void): PluginListenerHandle
-
Listen for the hardware back button event (Android only). If you want to close the app, call `App.exitApp()`
+
Listen for the hardware back button event (Android only). Listening for this event will disable the +default back button behaviour, so you might want to call `window.history.back()` manually. +If you want to close the app, call `App.exitApp()`.
eventName @@ -151,7 +153,7 @@

addListener

listenerFunc -(data: AppUrlOpen) => void +(data: AppUrlOpen) => void
@@ -161,7 +163,7 @@

addListener

Interfaces Used

-
+

AppLaunchUrl

interface AppLaunchUrl diff --git a/site/src/assets/docs-content/apis/background-task/api.html b/site/src/assets/docs-content/apis/background-task/api.html index 57722cbd3..bae39c4ea 100644 --- a/site/src/assets/docs-content/apis/background-task/api.html +++ b/site/src/assets/docs-content/apis/background-task/api.html @@ -4,7 +4,7 @@

beforeExit

- beforeExit(cb: Function): CallbackID + beforeExit(cb: Function): CallbackID
When the app is backgrounded, this method allows you to run a short-lived background task that will ensure that you @@ -21,14 +21,14 @@

beforeExit

- Returns: CallbackID + Returns: CallbackID

finish

- finish(options: { taskId: CallbackID }): void + finish(options: { taskId: CallbackID }): void
Notify the OS that the given task is finished and the OS can continue backgrounding the app.
@@ -36,7 +36,7 @@

finish

options -{ taskId: CallbackID } +{ taskId: CallbackID }
@@ -69,7 +69,7 @@

addListener

Interfaces Used

-
+

CallbackID

type alias CallbackID diff --git a/site/src/assets/docs-content/apis/browser/api.html b/site/src/assets/docs-content/apis/browser/api.html index b89a32653..c5ce2f4ff 100644 --- a/site/src/assets/docs-content/apis/browser/api.html +++ b/site/src/assets/docs-content/apis/browser/api.html @@ -17,14 +17,14 @@

close

open

- open(options: BrowserOpenOptions): Promise<void> + open(options: BrowserOpenOptions): Promise<void>
Open a page with the given URL
options -BrowserOpenOptions +BrowserOpenOptions
@@ -35,7 +35,7 @@

open

prefetch

- prefetch(options: BrowserPrefetchOptions): Promise<void> + prefetch(options: BrowserPrefetchOptions): Promise<void>
Hint to the browser that the given URLs will be accessed to improve initial loading times.
@@ -43,7 +43,7 @@

prefetch

options -BrowserPrefetchOptions +BrowserPrefetchOptions
@@ -99,7 +99,7 @@

addListener

Interfaces Used

-
+

BrowserOpenOptions

interface BrowserOpenOptions @@ -142,7 +142,7 @@

BrowserOpenOptions

} -
+

BrowserPrefetchOptions

interface BrowserPrefetchOptions @@ -154,7 +154,7 @@

BrowserPrefetchOptions

urls : - any; + string[];
} diff --git a/site/src/assets/docs-content/apis/camera/api.html b/site/src/assets/docs-content/apis/camera/api.html index 8eed0100d..afa617f78 100644 --- a/site/src/assets/docs-content/apis/camera/api.html +++ b/site/src/assets/docs-content/apis/camera/api.html @@ -4,7 +4,7 @@

getPhoto

- getPhoto(options: CameraOptions): Promise<CameraPhoto> + getPhoto(options: CameraOptions): Promise<CameraPhoto>
Prompt the user to pick a photo from an album, or take a new photo with the camera.
@@ -12,11 +12,11 @@

getPhoto

options -CameraOptions +CameraOptions
- Returns: Promise<CameraPhoto> + Returns: Promise<CameraPhoto>
@@ -45,7 +45,7 @@

addListener

Interfaces Used

-
+

CameraOptions

interface CameraOptions @@ -76,7 +76,7 @@

CameraOptions

Default: CameraDirection.Rear
direction ?: - CameraDirection; + CameraDirection;
@@ -108,7 +108,7 @@

CameraOptions

// How the data should be returned. Currently, only 'Base64', 'DataUrl' or 'Uri' is supported
resultType : - CameraResultType; + CameraResultType;
@@ -126,7 +126,7 @@

CameraOptions

Default: CameraSource.Prompt
source ?: - CameraSource; + CameraSource;
@@ -139,7 +139,7 @@

CameraOptions

} -
+

CameraPhoto

interface CameraPhoto @@ -198,7 +198,7 @@

CameraPhoto

} -
+

CameraDirection

enum CameraDirection @@ -220,7 +220,7 @@

CameraDirection

} -
+

CameraResultType

enum CameraResultType @@ -249,7 +249,7 @@

CameraResultType

} -
+

CameraSource

enum CameraSource diff --git a/site/src/assets/docs-content/apis/clipboard/api.html b/site/src/assets/docs-content/apis/clipboard/api.html index a6612f2b1..e25d11129 100644 --- a/site/src/assets/docs-content/apis/clipboard/api.html +++ b/site/src/assets/docs-content/apis/clipboard/api.html @@ -4,32 +4,32 @@

read

- read(options: ClipboardRead): Promise<ClipboardReadResult> + read(options: ClipboardRead): Promise<ClipboardReadResult>
Read a value from the clipboard (the "paste" action)
options -ClipboardRead +ClipboardRead
- Returns: Promise<ClipboardReadResult> + Returns: Promise<ClipboardReadResult>

write

- write(options: ClipboardWrite): Promise<void> + write(options: ClipboardWrite): Promise<void>
Write a value to the clipboard (the "copy" action)
options -ClipboardWrite +ClipboardWrite
@@ -62,7 +62,7 @@

addListener

Interfaces Used

-
+

ClipboardRead

interface ClipboardRead @@ -79,7 +79,7 @@

ClipboardRead

} -
+

ClipboardReadResult

interface ClipboardReadResult @@ -96,7 +96,7 @@

ClipboardReadResult

} -
+

ClipboardWrite

interface ClipboardWrite diff --git a/site/src/assets/docs-content/apis/device/api.html b/site/src/assets/docs-content/apis/device/api.html index b9fc311b1..2018b5d3e 100644 --- a/site/src/assets/docs-content/apis/device/api.html +++ b/site/src/assets/docs-content/apis/device/api.html @@ -4,26 +4,26 @@

getInfo

- getInfo(): Promise<DeviceInfo> + getInfo(): Promise<DeviceInfo>
Return information about the underlying device/os/platform
- Returns: Promise<DeviceInfo> + Returns: Promise<DeviceInfo>

getLanguageCode

- getLanguageCode(): Promise<DeviceLanguageCodeResult> + getLanguageCode(): Promise<DeviceLanguageCodeResult>
Get the device's current language locale code
- Returns: Promise<DeviceLanguageCodeResult> + Returns: Promise<DeviceLanguageCodeResult>
@@ -52,7 +52,7 @@

addListener

Interfaces Used

-
+

DeviceInfo

interface DeviceInfo @@ -146,7 +146,7 @@

DeviceInfo

// The operating system of the device
operatingSystem : - 'ios' | 'android' | 'windows' | 'mac' | 'unknown'; + OperatingSystem;
@@ -162,7 +162,7 @@

DeviceInfo

// The device platform (lowercase).
platform : - 'ios' | 'android' | 'electron' | 'web'; + any;
@@ -176,7 +176,7 @@

DeviceInfo

} -
+

DeviceLanguageCodeResult

interface DeviceLanguageCodeResult @@ -192,4 +192,12 @@

DeviceLanguageCodeResult

} + +
+

OperatingSystem

+
+ type alias OperatingSystem + { +
+}
\ No newline at end of file diff --git a/site/src/assets/docs-content/apis/filesystem/api-index.html b/site/src/assets/docs-content/apis/filesystem/api-index.html index 8da63911d..e6300f3cc 100644 --- a/site/src/assets/docs-content/apis/filesystem/api-index.html +++ b/site/src/assets/docs-content/apis/filesystem/api-index.html @@ -1,10 +1,12 @@

Table of Contents

  • appendFile()
  • +
  • copy()
  • deleteFile()
  • getUri()
  • mkdir()
  • readFile()
  • readdir()
  • +
  • rename()
  • rmdir()
  • stat()
  • writeFile()
  • diff --git a/site/src/assets/docs-content/apis/filesystem/api.html b/site/src/assets/docs-content/apis/filesystem/api.html index e8b03cf09..23e391824 100644 --- a/site/src/assets/docs-content/apis/filesystem/api.html +++ b/site/src/assets/docs-content/apis/filesystem/api.html @@ -4,19 +4,39 @@

    appendFile

    - appendFile(options: FileAppendOptions): Promise<FileAppendResult> + appendFile(options: FileAppendOptions): Promise<FileAppendResult>
    Append to a file on disk in the specified location on device
    options -FileAppendOptions +FileAppendOptions
    options for the file append
    - Returns: Promise<FileAppendResult> - a promise that resolves with the file write result + Returns: Promise<FileAppendResult> - a promise that resolves with the file write result + +
    + +
    +
    +

    copy

    +
    + copy(options: CopyOptions): Promise<CopyResult> +
    +
    Copy a file or directory
    +
    +
    + options + +CopyOptions +
    the options for the copy operation
    +
    + +
    + Returns: Promise<CopyResult> - a promise that resolves with the copy result
    @@ -24,19 +44,19 @@

    appendFile

    deleteFile

    - deleteFile(options: FileDeleteOptions): Promise<FileDeleteResult> + deleteFile(options: FileDeleteOptions): Promise<FileDeleteResult>
    Delete a file from disk
    options -FileDeleteOptions +FileDeleteOptions
    options for the file delete
    - Returns: Promise<FileDeleteResult> - a promise that resolves with the deleted file data result + Returns: Promise<FileDeleteResult> - a promise that resolves with the deleted file data result
    @@ -44,19 +64,19 @@

    deleteFile

    getUri

    - getUri(options: GetUriOptions): Promise<GetUriResult> + getUri(options: GetUriOptions): Promise<GetUriResult>
    Return full File URI for a path and directory
    options -GetUriOptions +GetUriOptions
    the options for the stat operation
    - Returns: Promise<GetUriResult> - a promise that resolves with the file stat result + Returns: Promise<GetUriResult> - a promise that resolves with the file stat result
    @@ -64,19 +84,19 @@

    getUri

    mkdir

    - mkdir(options: MkdirOptions): Promise<MkdirResult> + mkdir(options: MkdirOptions): Promise<MkdirResult>
    Create a directory.
    options -MkdirOptions +MkdirOptions
    options for the mkdir
    - Returns: Promise<MkdirResult> - a promise that resolves with the mkdir result + Returns: Promise<MkdirResult> - a promise that resolves with the mkdir result
    @@ -84,19 +104,19 @@

    mkdir

    readFile

    - readFile(options: FileReadOptions): Promise<FileReadResult> + readFile(options: FileReadOptions): Promise<FileReadResult>
    Read a file from disk
    options -FileReadOptions +FileReadOptions
    options for the file read
    - Returns: Promise<FileReadResult> - a promise that resolves with the read file data result + Returns: Promise<FileReadResult> - a promise that resolves with the read file data result
    @@ -104,19 +124,39 @@

    readFile

    readdir

    - readdir(options: ReaddirOptions): Promise<ReaddirResult> + readdir(options: ReaddirOptions): Promise<ReaddirResult>
    Return a list of files from the directory (not recursive)
    options -ReaddirOptions +ReaddirOptions
    the options for the readdir operation
    - Returns: Promise<ReaddirResult> - a promise that resolves with the readdir directory listing result + Returns: Promise<ReaddirResult> - a promise that resolves with the readdir directory listing result + +
    + +
    +
    +

    rename

    +
    + rename(options: RenameOptions): Promise<RenameResult> +
    +
    Rename a file or directory
    +
    +
    + options + +RenameOptions +
    the options for the rename operation
    +
    + +
    + Returns: Promise<RenameResult> - a promise that resolves with the rename result
    @@ -124,39 +164,39 @@

    readdir

    rmdir

    - rmdir(options: RmdirOptions): Promise<RmdirResult> + rmdir(options: RmdirOptions): Promise<RmdirResult>
    Remove a directory
    options -RmdirOptions +RmdirOptions
    the options for the directory remove
    - Returns: Promise<RmdirResult> + Returns: Promise<RmdirResult>

    stat

    - stat(options: StatOptions): Promise<StatResult> + stat(options: StatOptions): Promise<StatResult>
    Return data about a file
    options -StatOptions +StatOptions
    the options for the stat operation
    - Returns: Promise<StatResult> - a promise that resolves with the file stat result + Returns: Promise<StatResult> - a promise that resolves with the file stat result
    @@ -164,19 +204,19 @@

    stat

    writeFile

    - writeFile(options: FileWriteOptions): Promise<FileWriteResult> + writeFile(options: FileWriteOptions): Promise<FileWriteResult>
    Write a file to disk in the specified location on device
    options -FileWriteOptions +FileWriteOptions
    options for the file write
    - Returns: Promise<FileWriteResult> - a promise that resolves with the file write result + Returns: Promise<FileWriteResult> - a promise that resolves with the file write result
    @@ -206,7 +246,7 @@

    addListener

    Interfaces Used

    -
    +

    FileAppendOptions

    interface FileAppendOptions @@ -226,20 +266,21 @@

    FileAppendOptions

    // The FilesystemDirectory to store the file in
    directory ?: - FilesystemDirectory; + FilesystemDirectory;
    -
    // The encoding to write the file in (defautls to utf8)
    +
    // The encoding to write the file in. If not provided, data +is written as base64 encoded data.
    encoding ?: - FilesystemEncoding; + FilesystemEncoding;
    -
    // the filename to write
    +
    // The filename to write
    path : string; @@ -247,7 +288,7 @@

    FileAppendOptions

    } -
    +

    FileAppendResult

    interface FileAppendResult @@ -256,7 +297,58 @@

    FileAppendResult

    } -
    +
    +

    CopyOptions

    +
    + interface CopyOptions + { +
    + + +
    +
    // The FilesystemDirectory containing the existing file or directory
    +
    directory + ?: + FilesystemDirectory; +
    +
    + +
    +
    // The existing file or directory
    +
    from + : + string; +
    +
    + +
    +
    // The destination file or directory
    +
    to + : + string; +
    +
    + +
    +
    // The FilesystemDirectory containing the destination file or directory. If not supplied will use the 'directory' +parameter as the destination
    +
    toDirectory + ?: + FilesystemDirectory; +
    +
    +} + +
    +

    CopyResult

    +
    + interface CopyResult + { +
    + +} + +

    FileDeleteOptions

    interface FileDeleteOptions @@ -268,12 +360,12 @@

    FileDeleteOptions

    // The FilesystemDirectory to delete the file from
    directory ?: - FilesystemDirectory; + FilesystemDirectory;
    -
    // the filename to delete
    +
    // The filename to delete
    path : string; @@ -281,7 +373,7 @@

    FileDeleteOptions

    } -
    +

    FileDeleteResult

    interface FileDeleteResult @@ -290,7 +382,7 @@

    FileDeleteResult

    } -
    +

    GetUriOptions

    interface GetUriOptions @@ -302,7 +394,7 @@

    GetUriOptions

    // The FilesystemDirectory to get the file under
    directory : - FilesystemDirectory; + FilesystemDirectory;
    @@ -315,7 +407,7 @@

    GetUriOptions

    } -
    +

    GetUriResult

    interface GetUriResult @@ -332,7 +424,7 @@

    GetUriResult

    } -
    +

    MkdirOptions

    interface MkdirOptions @@ -341,9 +433,9 @@

    MkdirOptions

    -
    // Whether to create any missing parent directories as well
    +
    // undefined
    createIntermediateDirectories - : + ?: boolean;
    @@ -352,7 +444,7 @@

    MkdirOptions

    // The FilesystemDirectory to make the new directory in
    directory ?: - FilesystemDirectory; + FilesystemDirectory;
    @@ -363,9 +455,18 @@

    MkdirOptions

    string;
    + +
    +
    // Whether to create any missing parent directories as well. +Defaults to false
    +
    recursive + ?: + boolean; +
    +
    } -
    +

    MkdirResult

    interface MkdirResult @@ -374,7 +475,7 @@

    MkdirResult

    } -
    +

    FileReadOptions

    interface FileReadOptions @@ -386,7 +487,7 @@

    FileReadOptions

    // The FilesystemDirectory to read the file from
    directory ?: - FilesystemDirectory; + FilesystemDirectory;
    @@ -395,12 +496,12 @@

    FileReadOptions

    is read as binary and returned as base64 encoded data.
    encoding ?: - FilesystemEncoding; + FilesystemEncoding;
    -
    // the filename to read
    +
    // The filename to read
    path : string; @@ -408,7 +509,7 @@

    FileReadOptions

    } -
    +

    FileReadResult

    interface FileReadResult @@ -425,7 +526,7 @@

    FileReadResult

    } -
    +

    ReaddirOptions

    interface ReaddirOptions @@ -434,15 +535,15 @@

    ReaddirOptions

    -
    // The FilesystemDirectory to remove the directory from
    +
    // The FilesystemDirectory to list files from
    directory ?: - FilesystemDirectory; + FilesystemDirectory;
    -
    // The path of the directory to remove
    +
    // The path of the directory to read
    path : string; @@ -450,7 +551,7 @@

    ReaddirOptions

    } -
    +

    ReaddirResult

    interface ReaddirResult @@ -462,12 +563,63 @@

    ReaddirResult

    files : - any; + string[];
    } -
    +
    +

    RenameOptions

    +
    + interface RenameOptions + { +
    + + +
    +
    // The FilesystemDirectory containing the existing file or directory
    +
    directory + ?: + FilesystemDirectory; +
    +
    + +
    +
    // The existing file or directory
    +
    from + : + string; +
    +
    + +
    +
    // The destination file or directory
    +
    to + : + string; +
    +
    + +
    +
    // The FilesystemDirectory containing the destination file or directory. If not supplied will use the 'directory' +parameter as the destination
    +
    toDirectory + ?: + FilesystemDirectory; +
    +
    +} + +
    +

    RenameResult

    +
    + interface RenameResult + { +
    + +} + +

    RmdirOptions

    interface RmdirOptions @@ -479,7 +631,7 @@

    RmdirOptions

    // The FilesystemDirectory to remove the directory from
    directory ?: - FilesystemDirectory; + FilesystemDirectory;
    @@ -490,9 +642,18 @@

    RmdirOptions

    string;
    + +
    +
    // Whether to recursively remove the contents of the directory +Defaults to false
    +
    recursive + ?: + boolean; +
    +
    } -
    +

    RmdirResult

    interface RmdirResult @@ -501,7 +662,7 @@

    RmdirResult

    } -
    +

    StatOptions

    interface StatOptions @@ -510,15 +671,15 @@

    StatOptions

    -
    // The FilesystemDirectory to remove the directory from
    +
    // The FilesystemDirectory to get the file under
    directory ?: - FilesystemDirectory; + FilesystemDirectory;
    -
    // The path of the directory to remove
    +
    // The path of the file to get data about
    path : string; @@ -526,7 +687,7 @@

    StatOptions

    } -
    +

    StatResult

    interface StatResult @@ -575,7 +736,7 @@

    StatResult

    } -
    +

    FileWriteOptions

    interface FileWriteOptions @@ -595,20 +756,21 @@

    FileWriteOptions

    // The FilesystemDirectory to store the file in
    directory ?: - FilesystemDirectory; + FilesystemDirectory;
    -
    // The encoding to write the file in (defautls to utf8)
    +
    // The encoding to write the file in. If not provided, data +is written as base64 encoded data.
    encoding ?: - FilesystemEncoding; + FilesystemEncoding;
    -
    // the filename to write
    +
    // The filename to write
    path : string; @@ -616,7 +778,7 @@

    FileWriteOptions

    } -
    +

    FileWriteResult

    interface FileWriteResult @@ -625,7 +787,7 @@

    FileWriteResult

    } -
    +

    FilesystemDirectory

    enum FilesystemDirectory @@ -675,7 +837,7 @@

    FilesystemDirectory

    } -
    +

    FilesystemEncoding

    enum FilesystemEncoding diff --git a/site/src/assets/docs-content/apis/geolocation/api.html b/site/src/assets/docs-content/apis/geolocation/api.html index 0cf262997..ddecba61b 100644 --- a/site/src/assets/docs-content/apis/geolocation/api.html +++ b/site/src/assets/docs-content/apis/geolocation/api.html @@ -22,25 +22,25 @@

    clearWatch

    getCurrentPosition

    - getCurrentPosition(options?: GeolocationOptions): Promise<GeolocationPosition> + getCurrentPosition(options?: GeolocationOptions): Promise<GeolocationPosition>
    Get the current GPS location of the device
    options -GeolocationOptions +GeolocationOptions
    - Returns: Promise<GeolocationPosition> + Returns: Promise<GeolocationPosition>

    watchPosition

    - watchPosition(options: GeolocationOptions, callback: GeolocationWatchCallback): CallbackID + watchPosition(options: GeolocationOptions, callback: GeolocationWatchCallback): CallbackID
    Set up a watch for location changes. Note that watching for location changes can consume a large amount of energy. Be smart about listening only when you need to.
    @@ -48,16 +48,16 @@

    watchPosition

    options -GeolocationOptions +GeolocationOptions
    callback -GeolocationWatchCallback +GeolocationWatchCallback
    - Returns: CallbackID + Returns: CallbackID
    @@ -86,7 +86,7 @@

    addListener

    Interfaces Used

    -
    +

    GeolocationOptions

    interface GeolocationOptions @@ -132,7 +132,7 @@

    GeolocationOptions

    } -
    +

    GeolocationPosition

    interface GeolocationPosition @@ -157,7 +157,7 @@

    GeolocationPosition

    } -
    +

    GeolocationWatchCallback

    type alias GeolocationWatchCallback @@ -166,7 +166,7 @@

    GeolocationWatchCallback

    } -
    +

    CallbackID

    type alias CallbackID diff --git a/site/src/assets/docs-content/apis/haptics/api.html b/site/src/assets/docs-content/apis/haptics/api.html index 994a24b36..3bd2a2a4d 100644 --- a/site/src/assets/docs-content/apis/haptics/api.html +++ b/site/src/assets/docs-content/apis/haptics/api.html @@ -4,14 +4,14 @@

    impact

    - impact(options: HapticsImpactOptions): void + impact(options: HapticsImpactOptions): void
    Trigger a haptics "impact" feedback
    options -HapticsImpactOptions +HapticsImpactOptions
    @@ -22,14 +22,14 @@

    impact

    notification

    - notification(options: HapticsNotificationOptions): void + notification(options: HapticsNotificationOptions): void
    Trigger a haptics "notification" feedback
    options -HapticsNotificationOptions +HapticsNotificationOptions
    @@ -117,7 +117,7 @@

    addListener

    Interfaces Used

    -
    +

    HapticsImpactOptions

    interface HapticsImpactOptions @@ -129,12 +129,12 @@

    HapticsImpactOptions

    style : - HapticsImpactStyle; + HapticsImpactStyle;
    } -
    +

    HapticsNotificationOptions

    interface HapticsNotificationOptions @@ -146,12 +146,12 @@

    HapticsNotificationOptions

    type : - HapticsNotificationType; + HapticsNotificationType;
    } -
    +

    HapticsImpactStyle

    enum HapticsImpactStyle @@ -180,7 +180,7 @@

    HapticsImpactStyle

    } -
    +

    HapticsNotificationType

    enum HapticsNotificationType diff --git a/site/src/assets/docs-content/apis/keyboard/api-index.html b/site/src/assets/docs-content/apis/keyboard/api-index.html index ed71a74ed..a56ea5ca2 100644 --- a/site/src/assets/docs-content/apis/keyboard/api-index.html +++ b/site/src/assets/docs-content/apis/keyboard/api-index.html @@ -1,6 +1,9 @@

    Table of Contents

    • hide()
    • setAccessoryBarVisible()
    • +
    • setResizeMode()
    • +
    • setScroll()
    • +
    • setStyle()
    • show()
    • addListener('keyboardWillShow')
    • addListener('keyboardDidShow')
    • diff --git a/site/src/assets/docs-content/apis/keyboard/api.html b/site/src/assets/docs-content/apis/keyboard/api.html index 214b2bf6b..9ce812bbe 100644 --- a/site/src/assets/docs-content/apis/keyboard/api.html +++ b/site/src/assets/docs-content/apis/keyboard/api.html @@ -32,6 +32,60 @@

      setAcces Returns: Promise<void>

    +
    +
    +

    setResizeMode

    +
    + setResizeMode(options: KeyboardResizeOptions): Promise<void> +
    +
    Programmatically set the resize mode
    +
    +
    + options + +KeyboardResizeOptions +
    + +
    + Returns: Promise<void> +
    + +
    +
    +

    setScroll

    +
    + setScroll(options: { isDisabled: boolean }): Promise<void> +
    +
    Programmatically enable or disable the WebView scroll
    +
    +
    + options + +{ isDisabled: boolean } +
    + +
    + Returns: Promise<void> +
    + +
    +
    +

    setStyle

    +
    + setStyle(options: KeyboardStyleOptions): Promise<void> +
    +
    Programmatically set the keyboard style
    +
    +
    + options + +KeyboardStyleOptions +
    + +
    + Returns: Promise<void> +
    +

    show

    @@ -49,7 +103,7 @@

    show

    addListener

    - addListener(eventName: "keyboardWillShow", listenerFunc: (info: KeyboardInfo) => void): PluginListenerHandle + addListener(eventName: "keyboardWillShow", listenerFunc: (info: KeyboardInfo) => void): PluginListenerHandle
    @@ -61,7 +115,7 @@

    addListener

    listenerFunc -(info: KeyboardInfo) => void +(info: KeyboardInfo) => void
    @@ -72,7 +126,7 @@

    addListener

    addListener

    - addListener(eventName: "keyboardDidShow", listenerFunc: (info: KeyboardInfo) => void): PluginListenerHandle + addListener(eventName: "keyboardDidShow", listenerFunc: (info: KeyboardInfo) => void): PluginListenerHandle
    @@ -84,7 +138,7 @@

    addListener

    listenerFunc -(info: KeyboardInfo) => void +(info: KeyboardInfo) => void
    @@ -139,4 +193,96 @@

    addListener

    Interfaces Used

    + +
    +

    KeyboardResizeOptions

    +
    + interface KeyboardResizeOptions + { +
    + + +
    +
    +
    mode + : + KeyboardResize; +
    +
    +} + +
    +

    KeyboardStyleOptions

    +
    + interface KeyboardStyleOptions + { +
    + + +
    +
    +
    style + : + KeyboardStyle; +
    +
    +} + +
    +

    KeyboardResize

    +
    + enum KeyboardResize + { +
    + +
    +
    +
    Body: + "body" +
    +
    + +
    +
    +
    Ionic: + "ionic" +
    +
    + +
    +
    +
    Native: + "native" +
    +
    + +
    +
    +
    None: + "none" +
    +
    +} + +
    +

    KeyboardStyle

    +
    + enum KeyboardStyle + { +
    + +
    +
    +
    Dark: + "DARK" +
    +
    + +
    +
    +
    Light: + "LIGHT" +
    +
    +}
    \ No newline at end of file diff --git a/site/src/assets/docs-content/apis/local-notifications/api.html b/site/src/assets/docs-content/apis/local-notifications/api.html index 369c55e4a..863a6db20 100644 --- a/site/src/assets/docs-content/apis/local-notifications/api.html +++ b/site/src/assets/docs-content/apis/local-notifications/api.html @@ -4,27 +4,27 @@

    areEnabled

    - areEnabled(): Promise<LocalNotificationEnabledResult> + areEnabled(): Promise<LocalNotificationEnabledResult>
    - Returns: Promise<LocalNotificationEnabledResult> + Returns: Promise<LocalNotificationEnabledResult>

    cancel

    - cancel(pending: LocalNotificationPendingList): Promise<void> + cancel(pending: LocalNotificationPendingList): Promise<void>
    pending -LocalNotificationPendingList +LocalNotificationPendingList
    @@ -35,13 +35,13 @@

    cancel

    getPending

    - getPending(): Promise<LocalNotificationPendingList> + getPending(): Promise<LocalNotificationPendingList>
    - Returns: Promise<LocalNotificationPendingList> + Returns: Promise<LocalNotificationPendingList>
    @@ -66,7 +66,7 @@

    registerAct

    schedule

    - schedule(options: { notifications: any }): Promise<LocalNotificationScheduleResult> + schedule(options: { notifications: any }): Promise<LocalNotificationScheduleResult>
    @@ -77,14 +77,14 @@

    schedule

    - Returns: Promise<LocalNotificationScheduleResult> + Returns: Promise<LocalNotificationScheduleResult>

    addListener

    - addListener(eventName: "localNotificationReceived", listenerFunc: (notification: LocalNotification) => void): PluginListenerHandle + addListener(eventName: "localNotificationReceived", listenerFunc: (notification: LocalNotification) => void): PluginListenerHandle
    @@ -96,7 +96,7 @@

    addListener

    listenerFunc -(notification: LocalNotification) => void +(notification: LocalNotification) => void
    @@ -107,7 +107,7 @@

    addListener

    addListener

    - addListener(eventName: "localNotificationActionPerformed", listenerFunc: (notificationAction: LocalNotificationActionPerformed) => void): PluginListenerHandle + addListener(eventName: "localNotificationActionPerformed", listenerFunc: (notificationAction: LocalNotificationActionPerformed) => void): PluginListenerHandle
    @@ -119,7 +119,7 @@

    addListener

    listenerFunc -(notificationAction: LocalNotificationActionPerformed) => void +(notificationAction: LocalNotificationActionPerformed) => void
    @@ -129,7 +129,7 @@

    addListener

    Interfaces Used

    -
    +

    LocalNotificationEnabledResult

    interface LocalNotificationEnabledResult @@ -146,7 +146,7 @@

    LocalNotificationEnabledResult

    } -
    +

    LocalNotificationPendingList

    interface LocalNotificationPendingList @@ -158,12 +158,12 @@

    LocalNotificationPendingList

    notifications : - any; + LocalNotificationRequest[];
    } -
    +

    LocalNotificationScheduleResult

    interface LocalNotificationScheduleResult @@ -175,7 +175,7 @@

    LocalNotificationScheduleResult

    notifications : - any; + LocalNotificationRequest[];
    } diff --git a/site/src/assets/docs-content/apis/modals/api.html b/site/src/assets/docs-content/apis/modals/api.html index 1f5702dfb..ea135d38b 100644 --- a/site/src/assets/docs-content/apis/modals/api.html +++ b/site/src/assets/docs-content/apis/modals/api.html @@ -4,14 +4,14 @@

    alert

    - alert(options: AlertOptions): Promise<void> + alert(options: AlertOptions): Promise<void>
    Show an alert modal
    options -AlertOptions +AlertOptions
    @@ -22,43 +22,43 @@

    alert

    confirm

    - confirm(options: ConfirmOptions): Promise<ConfirmResult> + confirm(options: ConfirmOptions): Promise<ConfirmResult>
    Show a confirmation modal
    options -ConfirmOptions +ConfirmOptions
    - Returns: Promise<ConfirmResult> + Returns: Promise<ConfirmResult>

    prompt

    - prompt(options: PromptOptions): Promise<PromptResult> + prompt(options: PromptOptions): Promise<PromptResult>
    Show a prompt modal
    options -PromptOptions +PromptOptions
    - Returns: Promise<PromptResult> + Returns: Promise<PromptResult>

    showActions

    - showActions(options: ActionSheetOptions): Promise<ActionSheetResult> + showActions(options: ActionSheetOptions): Promise<ActionSheetResult>
    Show an Action Sheet style modal with various options for the user to select.
    @@ -66,11 +66,11 @@

    showActions

    options -ActionSheetOptions +ActionSheetOptions
    - Returns: Promise<ActionSheetResult> + Returns: Promise<ActionSheetResult>
    @@ -99,7 +99,7 @@

    addListener

    Interfaces Used

    -
    +

    AlertOptions

    interface AlertOptions @@ -132,7 +132,7 @@

    AlertOptions

    } -
    +

    ConfirmOptions

    interface ConfirmOptions @@ -173,7 +173,7 @@

    ConfirmOptions

    } -
    +

    ConfirmResult

    interface ConfirmResult @@ -190,7 +190,7 @@

    ConfirmResult

    } -
    +

    PromptOptions

    interface PromptOptions @@ -239,7 +239,7 @@

    PromptOptions

    } -
    +

    PromptResult

    interface PromptResult @@ -264,7 +264,7 @@

    PromptResult

    } -
    +

    ActionSheetOptions

    interface ActionSheetOptions @@ -284,7 +284,7 @@

    ActionSheetOptions

    options : - any; + ActionSheetOption[];
    @@ -297,7 +297,7 @@

    ActionSheetOptions

    } -
    +

    ActionSheetResult

    interface ActionSheetResult diff --git a/site/src/assets/docs-content/apis/motion/api.html b/site/src/assets/docs-content/apis/motion/api.html index cb9918b0d..35be62ba3 100644 --- a/site/src/assets/docs-content/apis/motion/api.html +++ b/site/src/assets/docs-content/apis/motion/api.html @@ -4,7 +4,7 @@

    addListener

    - addListener(eventName: "accel", listenerFunc: (event: MotionEventResult) => void): PluginListenerHandle + addListener(eventName: "accel", listenerFunc: (event: MotionEventResult) => void): PluginListenerHandle
    Listen for accelerometer data
    @@ -16,7 +16,7 @@

    addListener

    listenerFunc -(event: MotionEventResult) => void +(event: MotionEventResult) => void
    @@ -27,7 +27,7 @@

    addListener

    addListener

    - addListener(eventName: "orientation", listenerFunc: (event: MotionOrientationEventResult) => void): PluginListenerHandle + addListener(eventName: "orientation", listenerFunc: (event: MotionOrientationEventResult) => void): PluginListenerHandle
    Listen for device orientation change (compass heading, etc.)
    @@ -39,7 +39,7 @@

    addListener

    listenerFunc -(event: MotionOrientationEventResult) => void +(event: MotionOrientationEventResult) => void
    diff --git a/site/src/assets/docs-content/apis/network/api.html b/site/src/assets/docs-content/apis/network/api.html index aeabd103d..7242283fa 100644 --- a/site/src/assets/docs-content/apis/network/api.html +++ b/site/src/assets/docs-content/apis/network/api.html @@ -4,20 +4,20 @@

    getStatus

    - getStatus(): Promise<NetworkStatus> + getStatus(): Promise<NetworkStatus>
    Query the current network status
    - Returns: Promise<NetworkStatus> + Returns: Promise<NetworkStatus>

    addListener

    - addListener(eventName: "networkStatusChange", listenerFunc: (status: NetworkStatus) => void): PluginListenerHandle + addListener(eventName: "networkStatusChange", listenerFunc: (status: NetworkStatus) => void): PluginListenerHandle
    Listen for network status change events
    @@ -29,7 +29,7 @@

    addListener

    listenerFunc -(status: NetworkStatus) => void +(status: NetworkStatus) => void
    @@ -39,7 +39,7 @@

    addListener

    Interfaces Used

    -
    +

    NetworkStatus

    interface NetworkStatus diff --git a/site/src/assets/docs-content/apis/permissions/api-index.html b/site/src/assets/docs-content/apis/permissions/api-index.html new file mode 100644 index 000000000..129f53349 --- /dev/null +++ b/site/src/assets/docs-content/apis/permissions/api-index.html @@ -0,0 +1,4 @@ +

    Table of Contents

      +
    • query()
    • +
    • addListener()
    • +
    \ No newline at end of file diff --git a/site/src/assets/docs-content/apis/permissions/api.html b/site/src/assets/docs-content/apis/permissions/api.html new file mode 100644 index 000000000..dc5267a80 --- /dev/null +++ b/site/src/assets/docs-content/apis/permissions/api.html @@ -0,0 +1,130 @@ +
    +
    PermissionsPlugin
    + +
    +

    query

    +
    + query(options: PermissionsOptions): Promise<PermissionResult> +
    + +
    +
    + options + +PermissionsOptions +
    + +
    + Returns: Promise<PermissionResult> +
    + +
    +
    +

    addListener

    +
    + addListener(eventName: string, listenerFunc: Function): PluginListenerHandle +
    + +
    +
    + eventName + +string +
    +
    + listenerFunc + +Function +
    + +
    + Returns: PluginListenerHandle +
    + +
    +

    Interfaces Used

    + +
    +

    PermissionsOptions

    +
    + interface PermissionsOptions + { +
    + + +
    +
    +
    name + : + PermissionType; +
    +
    +} + +
    +

    PermissionResult

    +
    + interface PermissionResult + { +
    + + +
    +
    +
    state + : + any; +
    +
    +} + +
    +

    PermissionType

    +
    + enum PermissionType + { +
    + +
    +
    +
    Camera: + "camera" +
    +
    + +
    +
    +
    ClipboardRead: + "clipboard-read" +
    +
    + +
    +
    +
    ClipboardWrite: + "clipboard-write" +
    +
    + +
    +
    +
    Geolocation: + "geolocation" +
    +
    + +
    +
    +
    Notifications: + "notifications" +
    +
    + +
    +
    +
    Photos: + "photos" +
    +
    +} +
    \ No newline at end of file diff --git a/site/src/assets/docs-content/apis/photos/api.html b/site/src/assets/docs-content/apis/photos/api.html index e21bd3798..210043725 100644 --- a/site/src/assets/docs-content/apis/photos/api.html +++ b/site/src/assets/docs-content/apis/photos/api.html @@ -4,14 +4,14 @@

    createAlbum

    - createAlbum(options: PhotosCreateAlbumOptions): Promise<void> + createAlbum(options: PhotosCreateAlbumOptions): Promise<void>
    Create an album in the user's photo library
    options -PhotosCreateAlbumOptions +PhotosCreateAlbumOptions
    @@ -22,54 +22,54 @@

    createAlbum

    getAlbums

    - getAlbums(options?: PhotosAlbumsFetchOptions): Promise<PhotosAlbumsResult> + getAlbums(options?: PhotosAlbumsFetchOptions): Promise<PhotosAlbumsResult>
    Get albums from the user's photo library
    options -PhotosAlbumsFetchOptions +PhotosAlbumsFetchOptions
    - Returns: Promise<PhotosAlbumsResult> + Returns: Promise<PhotosAlbumsResult>

    getPhotos

    - getPhotos(options?: PhotosFetchOptions): Promise<PhotosResult> + getPhotos(options?: PhotosFetchOptions): Promise<PhotosResult>
    Get photos from the user's photo library
    options -PhotosFetchOptions +PhotosFetchOptions
    - Returns: Promise<PhotosResult> + Returns: Promise<PhotosResult>

    savePhoto

    - savePhoto(options?: PhotosSaveOptions): Promise<PhotosSaveResult> + savePhoto(options?: PhotosSaveOptions): Promise<PhotosSaveResult>
    Save a photo the the user's photo library
    options -PhotosSaveOptions +PhotosSaveOptions
    - Returns: Promise<PhotosSaveResult> + Returns: Promise<PhotosSaveResult>
    @@ -98,7 +98,7 @@

    addListener

    Interfaces Used

    -
    +

    PhotosCreateAlbumOptions

    interface PhotosCreateAlbumOptions @@ -115,7 +115,7 @@

    PhotosCreateAlbumOptions

    } -
    +

    PhotosAlbumsFetchOptions

    interface PhotosAlbumsFetchOptions @@ -132,7 +132,7 @@

    PhotosAlbumsFetchOptions

    } -
    +

    PhotosAlbumsResult

    interface PhotosAlbumsResult @@ -144,12 +144,12 @@

    PhotosAlbumsResult

    // The list of albums returned from the query
    albums : - any; + PhotosAlbum[];
    } -
    +

    PhotosFetchOptions

    interface PhotosFetchOptions @@ -206,7 +206,7 @@

    PhotosFetchOptions

    } -
    +

    PhotosResult

    interface PhotosResult @@ -218,12 +218,12 @@

    PhotosResult

    // The list of photos returned from the library
    photos : - any; + PhotoAsset[];
    } -
    +

    PhotosSaveOptions

    interface PhotosSaveOptions @@ -248,7 +248,7 @@

    PhotosSaveOptions

    } -
    +

    PhotosSaveResult

    interface PhotosSaveResult diff --git a/site/src/assets/docs-content/apis/push-notifications/api.html b/site/src/assets/docs-content/apis/push-notifications/api.html index d436a1fe1..db845ea65 100644 --- a/site/src/assets/docs-content/apis/push-notifications/api.html +++ b/site/src/assets/docs-content/apis/push-notifications/api.html @@ -4,14 +4,14 @@

    createChannel

    - createChannel(channel: PushNotificationChannel): Promise<void> + createChannel(channel: PushNotificationChannel): Promise<void>
    channel -PushNotificationChannel +PushNotificationChannel
    @@ -22,14 +22,14 @@

    createChannel

    deleteChannel

    - deleteChannel(channel: PushNotificationChannel): Promise<void> + deleteChannel(channel: PushNotificationChannel): Promise<void>
    channel -PushNotificationChannel +PushNotificationChannel
    @@ -40,26 +40,26 @@

    deleteChannel

    getDeliveredNotifications

    - getDeliveredNotifications(): Promise<PushNotificationDeliveredList> + getDeliveredNotifications(): Promise<PushNotificationDeliveredList>
    - Returns: Promise<PushNotificationDeliveredList> + Returns: Promise<PushNotificationDeliveredList>

    listChannels

    - listChannels(): Promise<PushNotificationChannelList> + listChannels(): Promise<PushNotificationChannelList>
    - Returns: Promise<PushNotificationChannelList> + Returns: Promise<PushNotificationChannelList>
    @@ -92,14 +92,14 @@

    removeDeliveredNotifications

    - removeDeliveredNotifications(delivered: PushNotificationDeliveredList): Promise<void> + removeDeliveredNotifications(delivered: PushNotificationDeliveredList): Promise<void>
    delivered -PushNotificationDeliveredList +PushNotificationDeliveredList
    @@ -110,7 +110,7 @@

    re

    addListener

    - addListener(eventName: "registration", listenerFunc: (token: PushNotificationToken) => void): PluginListenerHandle + addListener(eventName: "registration", listenerFunc: (token: PushNotificationToken) => void): PluginListenerHandle
    @@ -122,7 +122,7 @@

    addListener

    listenerFunc -(token: PushNotificationToken) => void +(token: PushNotificationToken) => void
    @@ -156,7 +156,7 @@

    addListener

    addListener

    - addListener(eventName: "pushNotificationReceived", listenerFunc: (notification: PushNotification) => void): PluginListenerHandle + addListener(eventName: "pushNotificationReceived", listenerFunc: (notification: PushNotification) => void): PluginListenerHandle
    @@ -168,7 +168,7 @@

    addListener

    listenerFunc -(notification: PushNotification) => void +(notification: PushNotification) => void
    @@ -179,7 +179,7 @@

    addListener

    addListener

    - addListener(eventName: "pushNotificationActionPerformed", listenerFunc: (notification: PushNotificationActionPerformed) => void): PluginListenerHandle + addListener(eventName: "pushNotificationActionPerformed", listenerFunc: (notification: PushNotificationActionPerformed) => void): PluginListenerHandle
    @@ -191,7 +191,7 @@

    addListener

    listenerFunc -(notification: PushNotificationActionPerformed) => void +(notification: PushNotificationActionPerformed) => void
    @@ -201,7 +201,7 @@

    addListener

    Interfaces Used

    -
    +

    PushNotificationChannel

    interface PushNotificationChannel @@ -241,6 +241,14 @@

    PushNotificationChannel

    +
    +
    +
    sound + : + string; +
    +
    +
    visibility @@ -250,7 +258,7 @@

    PushNotificationChannel

    } -
    +

    PushNotificationDeliveredList

    interface PushNotificationDeliveredList @@ -262,12 +270,12 @@

    PushNotificationDeliveredList

    notifications : - any; + PushNotification[];
    } -
    +

    PushNotificationChannelList

    interface PushNotificationChannelList @@ -279,7 +287,7 @@

    PushNotificationChannelList

    channels : - any; + PushNotificationChannel[];
    } diff --git a/site/src/assets/docs-content/apis/share/api.html b/site/src/assets/docs-content/apis/share/api.html index d66651a6a..4f2d64c6e 100644 --- a/site/src/assets/docs-content/apis/share/api.html +++ b/site/src/assets/docs-content/apis/share/api.html @@ -4,14 +4,14 @@

    share

    - share(options: ShareOptions): Promise<any> + share(options: ShareOptions): Promise<any>
    Show a Share modal for sharing content in your app with other apps
    options -ShareOptions +ShareOptions
    @@ -44,7 +44,7 @@

    addListener

    Interfaces Used

    -
    +

    ShareOptions

    interface ShareOptions diff --git a/site/src/assets/docs-content/apis/splash-screen/api.html b/site/src/assets/docs-content/apis/splash-screen/api.html index 3be61c9a1..f42a8ce0d 100644 --- a/site/src/assets/docs-content/apis/splash-screen/api.html +++ b/site/src/assets/docs-content/apis/splash-screen/api.html @@ -4,14 +4,14 @@

    hide

    - hide(options?: SplashScreenHideOptions, callback?: Function): Promise<void> + hide(options?: SplashScreenHideOptions, callback?: Function): Promise<void>
    Hide the splash screen
    options -SplashScreenHideOptions +SplashScreenHideOptions
    callback @@ -27,14 +27,14 @@

    hide

    show

    - show(options?: SplashScreenShowOptions, callback?: Function): Promise<void> + show(options?: SplashScreenShowOptions, callback?: Function): Promise<void>
    Show the splash screen
    options -SplashScreenShowOptions +SplashScreenShowOptions
    callback @@ -72,7 +72,7 @@

    addListener

    Interfaces Used

    -
    +

    SplashScreenHideOptions

    interface SplashScreenHideOptions @@ -89,7 +89,7 @@

    SplashScreenHideOptions

    } -
    +

    SplashScreenShowOptions

    interface SplashScreenShowOptions diff --git a/site/src/assets/docs-content/apis/status-bar/api.html b/site/src/assets/docs-content/apis/status-bar/api.html index 12e4b56f9..084ba2f0d 100644 --- a/site/src/assets/docs-content/apis/status-bar/api.html +++ b/site/src/assets/docs-content/apis/status-bar/api.html @@ -4,13 +4,13 @@

    getInfo

    - getInfo(): Promise<StatusBarInfoResult> + getInfo(): Promise<StatusBarInfoResult>
    Get info about the current state of the status bar
    - Returns: Promise<StatusBarInfoResult> + Returns: Promise<StatusBarInfoResult>
    @@ -30,14 +30,14 @@

    hide

    setBackgroundColor

    - setBackgroundColor(options: StatusBarBackgroundColorOptions): Promise<void> + setBackgroundColor(options: StatusBarBackgroundColorOptions): Promise<void>
    Set the background color of the status bar
    options -StatusBarBackgroundColorOptions +StatusBarBackgroundColorOptions
    @@ -48,14 +48,14 @@

    setBackgroun

    setStyle

    - setStyle(options: StatusBarStyleOptions): Promise<void> + setStyle(options: StatusBarStyleOptions): Promise<void>
    Set the current style of the status bar
    options -StatusBarStyleOptions +StatusBarStyleOptions
    @@ -101,7 +101,7 @@

    addListener

    Interfaces Used

    -
    +

    StatusBarInfoResult

    interface StatusBarInfoResult @@ -121,7 +121,7 @@

    StatusBarInfoResult

    style : - StatusBarStyle; + StatusBarStyle;
    @@ -134,7 +134,7 @@

    StatusBarInfoResult

    } -
    +

    StatusBarBackgroundColorOptions

    interface StatusBarBackgroundColorOptions @@ -151,7 +151,7 @@

    StatusBarBackgroundColorOptions

    } -
    +

    StatusBarStyleOptions

    interface StatusBarStyleOptions @@ -163,12 +163,12 @@

    StatusBarStyleOptions

    style : - StatusBarStyle; + StatusBarStyle;
    } -
    +

    StatusBarStyle

    enum StatusBarStyle diff --git a/site/src/assets/docs-content/apis/toast/api.html b/site/src/assets/docs-content/apis/toast/api.html index b9eb098fb..7d0cd4bcf 100644 --- a/site/src/assets/docs-content/apis/toast/api.html +++ b/site/src/assets/docs-content/apis/toast/api.html @@ -4,14 +4,14 @@

    show

    - show(options: ToastShowOptions): Promise<void> + show(options: ToastShowOptions): Promise<void>
    options -ToastShowOptions +ToastShowOptions
    @@ -44,7 +44,7 @@

    addListener

    Interfaces Used

    -
    +

    ToastShowOptions

    interface ToastShowOptions @@ -60,6 +60,14 @@

    ToastShowOptions

    +
    +
    +
    position + ?: + any; +
    +
    +
    text diff --git a/site/src/assets/docs-content/apis/web-view/api.html b/site/src/assets/docs-content/apis/web-view/api.html index cbcc0396a..932bc5551 100644 --- a/site/src/assets/docs-content/apis/web-view/api.html +++ b/site/src/assets/docs-content/apis/web-view/api.html @@ -4,13 +4,13 @@

    getServerBasePath

    - getServerBasePath(): Promise<WebViewPath> + getServerBasePath(): Promise<WebViewPath>
    - Returns: Promise<WebViewPath> + Returns: Promise<WebViewPath>
    @@ -30,14 +30,14 @@

    persistSe

    setServerBasePath

    - setServerBasePath(options: WebViewPath): Promise<void> + setServerBasePath(options: WebViewPath): Promise<void>
    options -WebViewPath +WebViewPath
    @@ -70,7 +70,7 @@

    addListener

    Interfaces Used

    -
    +

    WebViewPath

    interface WebViewPath diff --git a/site/src/components.d.ts b/site/src/components.d.ts index 7ed1701c1..86fb876e8 100644 --- a/site/src/components.d.ts +++ b/site/src/components.d.ts @@ -7,8 +7,8 @@ import '@stencil/core'; -import '@stencil/state-tunnel'; import '@stencil/router'; +import '@stencil/state-tunnel'; import { MarkdownContent, MarkdownHeading,