From 3f6d14720caa9295a2c9edeee7f3628f1e55ab73 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 14 Aug 2019 01:54:01 +0200 Subject: plugins/phonegap-plugin-mobile-accessibility --- StoneIsland/plugins/android.json | 119 +- StoneIsland/plugins/fetch.json | 227 +-- StoneIsland/plugins/ios.json | 113 +- .../phonegap-plugin-mobile-accessibility/LICENSE | 191 +++ .../phonegap-plugin-mobile-accessibility/NOTICE | 35 + .../phonegap-plugin-mobile-accessibility/README.md | 1073 ++++++++++++ .../package.json | 37 + .../plugin.xml | 83 + .../AbstractMobileAccessibilityHelper.java | 41 + .../DonutMobileAccessibilityHelper.java | 187 ++ .../IceCreamSandwichMobileAccessibilityHelper.java | 104 ++ .../JellyBeanMobileAccessibilityHelper.java | 52 + .../KitKatMobileAccessibilityHelper.java | 99 ++ .../mobileaccessibility/MobileAccessibility.java | 330 ++++ .../src/ios/CDVMobileAccessibility.h | 82 + .../src/ios/CDVMobileAccessibility.m | 511 ++++++ .../src/windows/mobile-accessibility-proxy.js | 261 +++ .../www/MobileAccessibilityNotifications.js | 50 + .../www/android/AndroidVox_v1.js | 1778 ++++++++++++++++++++ .../www/android/chromeandroidvox.js | 1778 ++++++++++++++++++++ .../www/mobile-accessibility.js | 499 ++++++ 21 files changed, 7428 insertions(+), 222 deletions(-) create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/LICENSE create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/NOTICE create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/README.md create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/package.json create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/plugin.xml create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/AbstractMobileAccessibilityHelper.java create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/DonutMobileAccessibilityHelper.java create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/IceCreamSandwichMobileAccessibilityHelper.java create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/JellyBeanMobileAccessibilityHelper.java create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/KitKatMobileAccessibilityHelper.java create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/MobileAccessibility.java create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/ios/CDVMobileAccessibility.h create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/ios/CDVMobileAccessibility.m create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/windows/mobile-accessibility-proxy.js create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/MobileAccessibilityNotifications.js create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/android/AndroidVox_v1.js create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/android/chromeandroidvox.js create mode 100644 StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/mobile-accessibility.js diff --git a/StoneIsland/plugins/android.json b/StoneIsland/plugins/android.json index e9460be9..1285146b 100755 --- a/StoneIsland/plugins/android.json +++ b/StoneIsland/plugins/android.json @@ -1,64 +1,67 @@ { - "prepare_queue": { - "installed": [], - "uninstalled": [] - }, - "config_munge": { - "files": {} - }, - "installed_plugins": { - "cordova-plugin-inappbrowser": { - "PACKAGE_NAME": "us.okfoc.stoneisland" + "prepare_queue": { + "installed": [], + "uninstalled": [] }, - "cordova-plugin-x-socialsharing": { - "PACKAGE_NAME": "us.okfoc.stoneisland" + "config_munge": { + "files": {} }, - "cordova-plugin-customurlscheme": { - "URL_SCHEME": "stoneisland", - "ANDROID_SCHEME": " ", - "ANDROID_HOST": " ", - "ANDROID_PATHPREFIX": "/", - "PACKAGE_NAME": "us.okfoc.stoneisland" + "installed_plugins": { + "cordova-plugin-inappbrowser": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-x-socialsharing": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-customurlscheme": { + "URL_SCHEME": "stoneisland", + "ANDROID_SCHEME": " ", + "ANDROID_HOST": " ", + "ANDROID_PATHPREFIX": "/", + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-whitelist": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-device": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-network-information": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-dialogs": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-geolocation": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "ionic-plugin-keyboard": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-statusbar": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-app-name": { + "APP_NAME": "Stone Island", + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-splashscreen": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "phonegap-plugin-push": { + "SENDER_ID": "85075801930", + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-sim": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "phonegap-plugin-mobile-accessibility": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + } }, - "cordova-plugin-whitelist": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-device": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-network-information": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-dialogs": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-geolocation": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "ionic-plugin-keyboard": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-statusbar": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-app-name": { - "APP_NAME": "Stone Island", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-splashscreen": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "phonegap-plugin-push": { - "SENDER_ID": "85075801930", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-sim": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - } - }, - "dependent_plugins": { - "cordova-plugin-compat": { - "PACKAGE_NAME": "us.okfoc.stoneisland" + "dependent_plugins": { + "cordova-plugin-compat": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + } } - } } \ No newline at end of file diff --git a/StoneIsland/plugins/fetch.json b/StoneIsland/plugins/fetch.json index 8a3ea6e4..766220c5 100755 --- a/StoneIsland/plugins/fetch.json +++ b/StoneIsland/plugins/fetch.json @@ -1,126 +1,135 @@ { - "cordova-plugin-inappbrowser": { - "source": { - "type": "registry", - "id": "cordova-plugin-inappbrowser@1.5.0" + "cordova-plugin-inappbrowser": { + "source": { + "type": "registry", + "id": "cordova-plugin-inappbrowser@1.5.0" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-x-socialsharing": { - "source": { - "type": "registry", - "id": "cordova-plugin-x-socialsharing" + "cordova-plugin-x-socialsharing": { + "source": { + "type": "registry", + "id": "cordova-plugin-x-socialsharing" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-customurlscheme": { - "source": { - "type": "registry", - "id": "cordova-plugin-customurlscheme" + "cordova-plugin-customurlscheme": { + "source": { + "type": "registry", + "id": "cordova-plugin-customurlscheme" + }, + "is_top_level": true, + "variables": { + "URL_SCHEME": "stoneisland" + } }, - "is_top_level": true, - "variables": { - "URL_SCHEME": "stoneisland" - } - }, - "cordova-plugin-whitelist": { - "source": { - "type": "registry", - "id": "cordova-plugin-whitelist@1" + "cordova-plugin-whitelist": { + "source": { + "type": "registry", + "id": "cordova-plugin-whitelist@1" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-device": { - "source": { - "type": "registry", - "id": "cordova-plugin-device" + "cordova-plugin-device": { + "source": { + "type": "registry", + "id": "cordova-plugin-device" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-network-information": { - "source": { - "type": "registry", - "id": "cordova-plugin-network-information" + "cordova-plugin-network-information": { + "source": { + "type": "registry", + "id": "cordova-plugin-network-information" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-dialogs": { - "source": { - "type": "registry", - "id": "cordova-plugin-dialogs" + "cordova-plugin-dialogs": { + "source": { + "type": "registry", + "id": "cordova-plugin-dialogs" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-geolocation": { - "source": { - "type": "registry", - "id": "cordova-plugin-geolocation" + "cordova-plugin-geolocation": { + "source": { + "type": "registry", + "id": "cordova-plugin-geolocation" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-compat": { - "source": { - "type": "registry", - "id": "cordova-plugin-compat" + "cordova-plugin-compat": { + "source": { + "type": "registry", + "id": "cordova-plugin-compat" + }, + "is_top_level": false, + "variables": {} }, - "is_top_level": false, - "variables": {} - }, - "ionic-plugin-keyboard": { - "source": { - "type": "registry", - "id": "ionic-plugin-keyboard" + "ionic-plugin-keyboard": { + "source": { + "type": "registry", + "id": "ionic-plugin-keyboard" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-statusbar": { - "source": { - "type": "registry", - "id": "cordova-plugin-statusbar@2.2.3" + "cordova-plugin-statusbar": { + "source": { + "type": "registry", + "id": "cordova-plugin-statusbar@2.2.3" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-app-name": { - "source": { - "type": "registry", - "id": "cordova-plugin-app-name" + "cordova-plugin-app-name": { + "source": { + "type": "registry", + "id": "cordova-plugin-app-name" + }, + "is_top_level": true, + "variables": { + "APP_NAME": "Stone Island" + } }, - "is_top_level": true, - "variables": { - "APP_NAME": "Stone Island" - } - }, - "cordova-plugin-splashscreen": { - "source": { - "type": "registry", - "id": "cordova-plugin-splashscreen@~4.0.0" + "cordova-plugin-splashscreen": { + "source": { + "type": "registry", + "id": "cordova-plugin-splashscreen@~4.0.0" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "phonegap-plugin-push": { - "source": { - "type": "registry", - "id": "phonegap-plugin-push@1.9.2" + "phonegap-plugin-push": { + "source": { + "type": "registry", + "id": "phonegap-plugin-push@1.9.2" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - }, - "cordova-plugin-sim": { - "source": { - "type": "registry", - "id": "cordova-plugin-sim" + "cordova-plugin-sim": { + "source": { + "type": "registry", + "id": "cordova-plugin-sim" + }, + "is_top_level": true, + "variables": {} }, - "is_top_level": true, - "variables": {} - } + "phonegap-plugin-mobile-accessibility": { + "source": { + "type": "git", + "url": "https://github.com/phonegap/phonegap-mobile-accessibility.git", + "subdir": "." + }, + "is_top_level": true, + "variables": {} + } } \ No newline at end of file diff --git a/StoneIsland/plugins/ios.json b/StoneIsland/plugins/ios.json index 8dd1067c..b95f9dd3 100644 --- a/StoneIsland/plugins/ios.json +++ b/StoneIsland/plugins/ios.json @@ -1,61 +1,64 @@ { - "prepare_queue": { - "installed": [], - "uninstalled": [] - }, - "config_munge": { - "files": {} - }, - "installed_plugins": { - "cordova-plugin-app-name": { - "APP_NAME": "Stone Island", - "PACKAGE_NAME": "us.okfoc.stoneisland" + "prepare_queue": { + "installed": [], + "uninstalled": [] }, - "cordova-plugin-customurlscheme": { - "URL_SCHEME": "stoneisland", - "PACKAGE_NAME": "us.okfoc.stoneisland" + "config_munge": { + "files": {} }, - "cordova-plugin-device": { - "PACKAGE_NAME": "us.okfoc.stoneisland" + "installed_plugins": { + "cordova-plugin-app-name": { + "APP_NAME": "Stone Island", + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-customurlscheme": { + "URL_SCHEME": "stoneisland", + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-device": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-dialogs": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-geolocation": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-inappbrowser": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-network-information": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-splashscreen": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-statusbar": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-whitelist": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-x-socialsharing": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "ionic-plugin-keyboard": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "phonegap-plugin-push": { + "SENDER_ID": "85075801930", + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-sim": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "phonegap-plugin-mobile-accessibility": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + } }, - "cordova-plugin-dialogs": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-geolocation": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-inappbrowser": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-network-information": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-splashscreen": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-statusbar": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-whitelist": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-x-socialsharing": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "ionic-plugin-keyboard": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "phonegap-plugin-push": { - "SENDER_ID": "85075801930", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-sim": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - } - }, - "dependent_plugins": { - "cordova-plugin-compat": { - "PACKAGE_NAME": "us.okfoc.stoneisland" + "dependent_plugins": { + "cordova-plugin-compat": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + } } - } } \ No newline at end of file diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/LICENSE b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/LICENSE new file mode 100644 index 00000000..37ec93a1 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/NOTICE b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/NOTICE new file mode 100644 index 00000000..fd6e4609 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/NOTICE @@ -0,0 +1,35 @@ +PhoneGap Mobile Accessibility plugin + +com.phonegap.plugin.mobile-accessibility + +Copyright 2014 Adobe Systems Incorporated + +This software is licensed under the Apache License, Version 2.0 (see LICENSE file). + +This software bundles the following third party software that may have +licenses differing from that of the software itself. You can find the +libraries and their respective licenses below. + +Third Party Software Notices: +============================= + + - AndroidVox_v1.js - ./www/android/AndroidVox_v1.js + from https://ssl.gstatic.com/accessibility/javascript/android/AndroidVox_v1.js + - chromeandroidvox.js - ./www/android/chromeandroidvox.js + from https://ssl.gstatic.com/accessibility/javascript/android/chromeandroidvox.js + +source url: https://code.google.com/p/google-axs-chrome/source/browse/#svn%2Ftrunk%2Fchromevox + +Copyright 2013 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/README.md b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/README.md new file mode 100644 index 00000000..dc8b25d2 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/README.md @@ -0,0 +1,1073 @@ +# phonegap-plugin-mobile-accessibility +========================================== + +This plugin exposes information on the status of various accessibility features of mobile operating systems, including, for example, whether a screen reader is running, invert colors is enabled, and the preferred scaling for text. It also allows an application to send a string to be spoken by the screen reader, or a command to stop the screen reader from speaking. + +--------------- +## Installation + + $ cordova plugin add https://github.com/phonegap/phonegap-mobile-accessibility.git + +---------------------- +## Supported Platforms + +- Amazon Fire OS +- Android +- iOS + +---------------------- +## MobileAccessibility + +The `MobileAccessibility` object, exposed by `window.MobileAccessibility`, provides methods for determining the status of accessibility features active on the user's device, methods changing the text zoom of the Cordova web view and for using the user's preferred text zoom as set in the operating system settings, and methods for sending a string to be spoken by the screen reader or to stop the screen reader from speaking. + +----------- +### Methods + +- MobileAccessibility.isScreenReaderRunning +- MobileAccessibility.isVoiceOverRunning +- MobileAccessibility.isTalkBackRunning +- MobileAccessibility.isChromeVoxActive +- MobileAccessibility.isClosedCaptioningEnabled +- MobileAccessibility.isGuidedAccessEnabled +- MobileAccessibility.isInvertColorsEnabled +- MobileAccessibility.isMonoAudioEnabled +- MobileAccessibility.isReduceMotionEnabled +- MobileAccessibility.isTouchExplorationEnabled +- MobileAccessibility.getTextZoom +- MobileAccessibility.setTextZoom +- MobileAccessibility.updateTextZoom +- MobileAccessibility.usePreferredTextZoom +- MobileAccessibility.postNotification +- MobileAccessibility.speak +- MobileAccessibility.stop + +-------------------------------------------------------- +#### MobileAccessibility.isScreenReaderRunning(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if a screen reader is running. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isScreenReaderRunningCallback(boolean) { + if (boolean) { + console.log("Screen reader: ON"); + // Do something to improve the behavior of the application while a screen reader is active. + } else { + console.log("Screen reader: OFF"); + } + } + + MobileAccessibility.isScreenReaderRunning(isScreenReaderRunningCallback); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android +- iOS + +----------------------------------------------------- +#### MobileAccessibility.isVoiceOverRunning(callback) + + +An iOS-specific proxy for the `MobileAccessibility.isScreenReaderRunning` method. This method will return `false` on Android and Amazon Fire OS. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isVoiceOverRunningCallback(boolean) { + if (boolean) { + console.log("Screen reader: ON"); + // Do something to improve the behavior of the application while a screen reader is active. + } else { + console.log("Screen reader: OFF"); + } + } + + MobileAccessibility.isVoiceOverRunning(isVoiceOverRunningCallback); +``` + +##### Supported Platforms + +- iOS + +---------------------------------------------------- +#### MobileAccessibility.isTalkBackRunning(callback) + + +An Android/Amazon Fire OS-specific proxy for the `MobileAccessibility.isScreenReaderRunning` method. This method will return `false` on iOS. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isTalkBackRunningCallback(boolean) { + if (boolean) { + console.log("Screen reader: ON"); + // Do something to improve the behavior of the application while a screen reader is active. + } else { + console.log("Screen reader: OFF"); + } + } + + MobileAccessibility.isTalkBackRunning(isTalkBackRunningCallback); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android + +---------------------------------------------------- +#### MobileAccessibility.isChromeVoxActive() + + +On Android, this method returns `true` if ChromeVox is active and properly initialized with access to the text to speech API in the WebView. +If TalkBack is running but ChromeVox is not active, this method is useful to alert the user of a potential problem. + +##### Returns + +- __boolean__ (Boolean) Returns `true` if ChromeVox is active and properly initialized with access to the text to speech API in the WebView. + +##### Usage + +```javascript + MobileAccessibility.isTalkBackRunning( + function (bool) { + console.log('Talkback status: ' + bool); + if (bool) { + /* Use setTimeout to account for latency in initialization of ChromeVox */ + setTimeout(function() { + if (MobileAccessibility.isChromeVoxActive()) { + console.log('ChromeVox is active.'); + } else { + console.log('ChromeVox is not active.'); + + /* Notify the user of a potential problem */ + MobileAccessibility.speak('The ChromeVox screen reader has failed to initialize. You may wish to close and restart this app.'); + } + }, 5000); + } + }); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android + +-------------------------------------------------------- +#### MobileAccessibility.isBoldTextEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if Bold Text is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isBoldTextEnabledCallback(boolean) { + if (boolean) { + console.log("Bold Text: ON"); + // Do something to improve the behavior of the application while Bold Text is enabled. + } else { + console.log("Bold Text: OFF"); + } + } + + MobileAccessibility.isBoldTextEnabled(isBoldTextEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +------------------------------------------------------------ +#### MobileAccessibility.isClosedCaptioningEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if system-level closed captioning is enabled on the device. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isClosedCaptioningEnabledCallback(boolean) { + if (boolean) { + console.log("Closed Captioning: ON"); + // Do something to improve the behavior of the application while closed captioning is enabled. + } else { + console.log("Closed Captioning: OFF"); + } + } + + MobileAccessibility.isClosedCaptioningEnabled(isClosedCaptioningEnabledCallback); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android +- iOS + +-------------------------------------------------------- +#### MobileAccessibility.isDarkerSystemColorsEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if Darker System Colors is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isDarkerSystemColorsEnabledCallback(boolean) { + if (boolean) { + console.log("Darker System Colors: ON"); + // Do something to improve the behavior of the application while Darker System Colors is enabled. + } else { + console.log("Darker System Colors: OFF"); + } + } + + MobileAccessibility.isDarkerSystemColorsEnabled(isDarkerSystemColorsEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +-------------------------------------------------------- +#### MobileAccessibility.isGrayscaleEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if Grayscale is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isGrayscaleEnabledCallback(boolean) { + if (boolean) { + console.log("Grayscale: ON"); + // Do something to improve the behavior of the application while Grayscale is enabled. + } else { + console.log("Grayscale: OFF"); + } + } + + MobileAccessibility.isGrayscaleEnabled(isGrayscaleEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +-------------------------------------------------------- +#### MobileAccessibility.isGuidedAccessEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if Guided Access is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isGuidedAccessEnabledCallback(boolean) { + if (boolean) { + console.log("Guided Access: ON"); + // Do something to improve the behavior of the application while Guided Access is enabled. + } else { + console.log("Guided Access: OFF"); + } + } + + MobileAccessibility.isGuidedAccessEnabledEnabled(isGuidedAccessEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +-------------------------------------------------------- +#### MobileAccessibility.isInvertColorsEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if the display colors have been inverted. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isInvertColorsEnabledCallback(boolean) { + if (boolean) { + console.log("Invert Colors: ON"); + // Do something to improve the behavior of the application while Invert Colors is enabled. + } else { + console.log("Invert Colors: OFF"); + } + } + + MobileAccessibility.isInvertColorsEnabled(isInvertColorsEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +----------------------------------------------------- +#### MobileAccessibility.isMonoAudioEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if mono audio is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isMonoAudioEnabledCallback(boolean) { + if (boolean) { + console.log("Mono Audio: ON"); + // Do something to improve the behavior of the application while Mono Audio is enabled. + } else { + console.log("Mono Audio: OFF"); + } + } + + MobileAccessibility.isMonoAudioEnabled(isMonoAudioEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +---------------------------------------------------- +#### MobileAccessibility.isReduceMotionEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if reduce motion is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isReduceMotionEnabledCallback(boolean) { + if (boolean) { + console.log("Reduce Motion: ON"); + // Do something to improve the behavior of the application when reduce motion is enabled. + } else { + console.log("Reduce Motion: OFF"); + } + } + + MobileAccessibility.isReduceMotionEnabled(isReduceMotionEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +---------------------------------------------------- +#### MobileAccessibility.isReduceTransparencyEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if reduce transparency is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isReduceTransparencyEnabledCallback(boolean) { + if (boolean) { + console.log("Reduce Transparency: ON"); + // Do something to improve the behavior of the application when reduce transparency is enabled. + } else { + console.log("Reduce Transparency: OFF"); + } + } + + MobileAccessibility.isReduceTransparencyEnabled(isReduceTransparencyEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +---------------------------------------------------- +#### MobileAccessibility.isSpeakScreenEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if speak screen is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isSpeakScreenEnabledCallback(boolean) { + if (boolean) { + console.log("Speak Screen: ON"); + // Do something to improve the behavior of the application when Speak Screen is enabled. + } else { + console.log("Speak Screen: OFF"); + } + } + + MobileAccessibility.isSpeakScreenEnabled(isSpeakScreenEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +---------------------------------------------------- +#### MobileAccessibility.isSpeakSelectionEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if speak selection is enabled. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isSpeakSelectionEnabledCallback(boolean) { + if (boolean) { + console.log("Speak Selection: ON"); + // Do something to improve the behavior of the application when Speak Selection is enabled. + } else { + console.log("Speak Selection: OFF"); + } + } + + MobileAccessibility.isSpeakSelectionEnabled(isSpeakSelectionEnabledCallback); +``` + +##### Supported Platforms + +- iOS + +---------------------------------------------------- +#### MobileAccessibility.isSwitchControlRunning(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if switch control is running. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isSwitchControlRunningCallback(boolean) { + if (boolean) { + console.log("Switch Control: ON"); + // Do something to improve the behavior of the application when Switch Control is running. + } else { + console.log("Switch Control: OFF"); + } + } + + MobileAccessibility.isSwitchControlRunning(isSwitchControlRunningCallback); +``` + +##### Supported Platforms + +- iOS + +------------------------------------------------------------ +#### MobileAccessibility.isTouchExplorationEnabled(callback) + +Makes an asynchronous call to native `MobileAccessibility` to determine if Touch Exploration is enabled on Android. + +##### Parameters + +- __callback__ (Function) A callback method to receive the boolean result asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function isTouchExplorationEnabledCallback(boolean) { + if (boolean) { + console.log("Touch Exploration: ON"); + // Do something to improve the behavior of the application with Touch Exploration enabled. + } else { + console.log("Touch Exploration: OFF"); + // Do something to improve the behavior of the application with Touch Exploration disabled. + + } + } + + MobileAccessibility.isTouchExplorationEnabled(isTouchExplorationEnabledCallback); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android + +-------------------------------------------------------- +#### MobileAccessibility.getTextZoom(callback) + +Makes an asynchronous call to native `MobileAccessibility` to return the current text zoom percent value for the WebView. + +##### Parameters + +- __callback__ (Function) A callback method to receive the text zoom percent value asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function getTextZoomCallback(textZoom) { + console.log('Current text zoom = ' + textZoom + '%') + } + + MobileAccessibility.getTextZoom(getTextZoomCallback); +``` +##### Supported Platforms + +- Amazon Fire OS +- Android +- iOS + +-------------------------------------------------------- +#### MobileAccessibility.setTextZoom(textZoom, callback) + +Makes an asynchronous call to native `MobileAccessibility` to set the current text zoom percent value for the WebView. + +##### Parameters + +- __textZoom__ (Number) A percentage value by which text in the WebView should be scaled. +- __callback__ (Function) A callback method to receive the new text zoom percent value asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function setTextZoomCallback(textZoom) { + console.log('WebView text should be scaled ' + textZoom + '%') + } + + MobileAccessibility.setTextZoom(200, setTextZoomCallback); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android +- iOS + +------------------------------------------------- +#### MobileAccessibility.updateTextZoom(callback) + +Makes an asynchronous call to native `MobileAccessibility` to retrieve the user's preferred text zoom from system settings and apply it to the application WebView. + +##### Parameters + +- __callback__ (Function) A callback method to receive the new text zoom percent value asynchronously from the native `MobileAccessibility` plugin. + +##### Usage + +```javascript + function updateTextZoomCallback(textZoom) { + console.log('WebView text should be scaled ' + textZoom + '%') + } + + MobileAccessibility.updateTextZoom(callback); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android +- iOS7+ + +------------------------------------------------------ +#### MobileAccessibility.usePreferredTextZoom(boolean) + +Specifies whether or not the application should use the user's preferred text zoom from system settings to scale text within the WebView. +When set to `true`, this method calls `MobileAccessibility.updateTextZoom()` to apply new text zoom settings to the application WebView. When set to `false`, the application WebView text zoom will be reset to the default value of `100` percent. The plugin uses local storage to retain the preference and will call `MobileAccessibility.updateTextZoom()` after a Cordova `resume` event. + +##### Parameters + +- __boolean__ (Boolean) A Boolean value which specifies whether to use the preferred text zoom of a default percent value of 100. + +##### Usage + +```javascript + MobileAccessibility.usePreferredTextZoom(true); + + function getTextZoomCallback(textZoom) { + console.log('WebView text should be scaled to the preferred value ' + textZoom + '%') + } + + MobileAccessibility.getTextZoom(getTextZoomCallback); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android +- iOS7+ + +-------------------------------------------------------------------------------------------- +#### MobileAccessibility.postNotification(mobileAccessibilityNotification, string, callback) + +Posts a notification with a string for the screen reader to announce if it is running. + +##### Parameters + +- __mobileAccessibilityNotification__ (uint) A numeric constant for the type of notification to send. Constants are defined in `MobileAccessibilityNotifications`. +- __string__ (string) A string to be announced by a screen reader. +- __callback__ (function) A callback method to receive the asynchronous result from the native `MobileAccessibility`, when the announcement is finished, the function should expect an object containing the `stringValue` that was voiced and a boolean indicating that the announcement `wasSuccessful`. + +##### Constants + +The following constants are for sending notifications to the accessibility API using the `MobileAccessibility.postNotification` method. They correspond to notification constants defined in [UIAccessibilityNotifications](https://developer.apple.com/library/ios/documentation/uikit/reference/UIAccessibility_Protocol/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008786-CH1-DontLinkElementID_3) on iOS. + +- MobileAccessibilityNotifications.SCREEN_CHANGED +- MobileAccessibilityNotifications.LAYOUT_CHANGED +- MobileAccessibilityNotifications.ANNOUNCEMENT +- MobileAccessibilityNotifications.PAGE_SCROLLED + +```javascript + MobileAccessibility.postNotification( + MobileAccessibilityNotifications.ANNOUNCEMENT, + 'String to be announced by screen reader.', + function(info) { + if (info) { + console.log("Screen Reader announced \"" + info.stringValue + "\" success : " + info.wasSuccessful); + } + }); +``` + +##### Supported Platforms + +- iOS + +------------------------------------------------------------- +#### MobileAccessibility.speak(string, queueMode, properties) + + +Speaks a given string through the screenreader. On Android, if ChromeVox is active, it will use the specified queueMode and properties. + +##### Parameters + +- __string__ (string) A string to be announced by a screen reader. +- __queueMode__ (Optional number) Valid modes are 0 for flush; 1 for queue. +- __properties__ (Optional Object) Speech properties to use for this utterance. + +```javascript + MobileAccessibility.speak('This string will be announced when a screen reader is active on the device.'); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android +- iOS + +------------------------------- +#### MobileAccessibility.stop() + +Stops speech. + +```javascript + MobileAccessibility.stop(); +``` + +##### Supported Platforms + +- Amazon Fire OS +- Android +- iOS + +---------- +### Events + +-------------- +#### Constants + +The following event constants are for `window` events, to which an application can listen for notification of changes in the status of the accessibility features on the device. + +- MobileAccessibilityNotifications.BOLD_TEXT_STATUS_CHANGED +- MobileAccessibilityNotifications.CLOSED_CAPTIONING_STATUS_CHANGED +- MobileAccessibilityNotifications.DARKER_SYSTEM_COLORS_STATUS_CHANGED +- MobileAccessibilityNotifications.GRAYSCALE_STATUS_CHANGED +- MobileAccessibilityNotifications.GUIDED_ACCESS_STATUS_CHANGED +- MobileAccessibilityNotifications.INVERT_COLORS_STATUS_CHANGED +- MobileAccessibilityNotifications.MONO_AUDIO_STATUS_CHANGED +- MobileAccessibilityNotifications.REDUCE_MOTION_STATUS_CHANGED +- MobileAccessibilityNotifications.REDUCE_TRANSPARENCY_STATUS_CHANGED +- MobileAccessibilityNotifications.SCREEN_READER_STATUS_CHANGED +- MobileAccessibilityNotifications.SPEAK_SCREEN_STATUS_CHANGED +- MobileAccessibilityNotifications.SPEAK_SELECTION_STATUS_CHANGED +- MobileAccessibilityNotifications.SWITCH_CONTROL_STATUS_CHANGED +- MobileAccessibilityNotifications.TOUCH_EXPLORATION_STATUS_CHANGED + +---------------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.BOLD_TEXT_STATUS_CHANGED (boldtextstatuschanged) + +The event fires when Bold Text has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Bold Text is active, `info.isBoldTextEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onBoldTextStatusChanged(info) { + if (info && typeof info.isBoldTextEnabled !== "undefined") { + if (info.isBoldTextEnabled) { + console.log("Bold Text: ON"); + // Do something to improve the behavior of the application while Bold Text is enabled. + } else { + console.log("Bold Text: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.BOLD_TEXT_STATUS_CHANGED, onBoldTextStatusChanged, false); +``` + +------------------------------------------------------------------------------------------------------ +#### MobileAccessibilityNotifications.CLOSED_CAPTIONING_STATUS_CHANGED (closedcaptioningstatuschanged) + +The event fires when system-level closed captioning on the device turns on or off. +The event returns an object, `info`, with the current status of accessibility features on the device. +If closed captioning is active, `info.isClosedCaptioningEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onClosedCaptioningStatusChanged(info) { + if (info && typeof info.isClosedCaptioningEnabled !== "undefined") { + if (info.isClosedCaptioningEnabled) { + console.log("Closed Captioning: ON"); + // Do something to improve the behavior of the application while closed captioning is enabled. + } else { + console.log("Closed Captioning: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.CLOSED_CAPTIONING_STATUS_CHANGED, onClosedCaptioningStatusChanged, false); +``` + +---------------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.DARKER_SYSTEM_COLORS_STATUS_CHANGED (darkersystemcolorsstatuschanged) + +The event fires when Darker System Colors has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Darker System Colors is active, `info.isDarkerSystemColorsEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onDarkerSystemColorsStatusChanged(info) { + if (info && typeof info.isDarkerSystemColorsEnabled !== "undefined") { + if (info.isDarkerSystemColorsEnabled) { + console.log("Darker System Colors: ON"); + // Do something to improve the behavior of the application while Darker System Colors is enabled. + } else { + console.log("Darker System Colors: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.DARKER_SYSTEM_COLORS_STATUS_CHANGED, onDarkerSystemColorsStatusChanged, false); +``` + +---------------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.GRAYSCALE_STATUS_CHANGED (grayscalestatuschanged) + +The event fires when Grayscale has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Grayscale is active, `info.isGrayscaleEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onGrayscaleStatusChanged(info) { + if (info && typeof info.isGrayscaleEnabled !== "undefined") { + if (info.isGrayscaleEnabled) { + console.log("Grayscale: ON"); + // Do something to improve the behavior of the application while Grayscale is enabled. + } else { + console.log("Grayscale: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.GRAYSCALE_STATUS_CHANGED, onGrayscaleStatusChanged, false); +``` + +---------------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.GUIDED_ACCESS_STATUS_CHANGED (guidedaccessstatuschanged) + +The event fires when Guided Access has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Guided Access is active, `info.isGuidedAccessEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onGuidedAccessStatusChanged(info) { + if (info && typeof info.isGuidedAccessEnabled !== "undefined") { + if (info.isGuidedAccessEnabled) { + console.log("Guided Access: ON"); + // Do something to improve the behavior of the application while Guided Access is enabled. + } else { + console.log("Guided Access: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.GUIDED_ACCESS_STATUS_CHANGED, onGuidedAccessStatusChanged, false); +``` + +---------------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.INVERT_COLORS_STATUS_CHANGED (invertcolorsstatuschanged) + +The event fires when Invert Colors has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Invert Colors is active, `info.isInvertColorsEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onInvertColorsStatusChanged(info) { + if (info && typeof info.isInvertColorsEnabled !== "undefined") { + if (info.isInvertColorsEnabled) { + console.log("Invert Colors: ON"); + // Do something to improve the behavior of the application while Invert Colors is enabled. + } else { + console.log("Invert Colors: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.INVERT_COLORS_STATUS_CHANGED, onInvertColorsStatusChanged, false); +``` + +---------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.MONO_AUDIO_STATUS_CHANGED (monoaudiostatuschanged) + +The event fires when Mono Audio has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Mono Audio is active, `info.isMonoAudioEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onMonoAudioStatusChanged(info) { + if (info && typeof info.isMonoAudioEnabled !== "undefined") { + if (info.isMonoAudioEnabled) { + console.log("Mono Audio: ON"); + // Do something to improve the behavior of the application while Mono Audio is enabled. + } else { + console.log("Mono Audio: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.MONO_AUDIO_STATUS_CHANGED, onMonoAudioStatusChanged, false); +``` + +---------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.REDUCE_MOTION_STATUS_CHANGED (reducemotionstatuschanged) + +The event fires when Reduce Motion has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Reduce Motion is active, `info.isReduceMotionEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onReduceMotionStatusChanged(info) { + if (info && typeof info.isReduceMotionEnabled !== "undefined") { + if (info.isReduceMotionEnabled) { + console.log("Reduce Motion: ON"); + // Do something to improve the behavior of the application while Reduce Motion is enabled. + } else { + console.log("Reduce Motion: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.REDUCE_MOTION_STATUS_CHANGED, onMReduceMotionStatusChanged, false); +``` + +---------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.REDUCE_TRANSPARENCY_STATUS_CHANGED (reducetransparencystatuschanged) + +The event fires when Reduce Transparency has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Reduce Transparency is active, `info.isReduceTransparencyEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onReduceTransparencyStatusChanged(info) { + if (info && typeof info.isReduceTransparencyEnabled !== "undefined") { + if (info.isReduceTransparencyEnabled) { + console.log("Reduce Transparency: ON"); + // Do something to improve the behavior of the application while Reduce Transparency is enabled. + } else { + console.log("Reduce Transparency: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.REDUCE_TRANSPARENCY_STATUS_CHANGED, onReduceTransparencyStatusChanged, false); +``` + +---------------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.SCREEN_READER_STATUS_CHANGED (screenreaderstatuschanged) + +The event fires when a screen reader on the device turns on or off. +The event returns an object, `info`, with the current status of accessibility features on the device. +If a screen reader is active, `info.isScreenReaderRunning` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onScreenReaderStatusChanged(info) { + if (info && typeof info.isScreenReaderRunning !== "undefined") { + if (info.isScreenReaderRunning) { + console.log("Screen reader: ON"); + // Do something to improve the behavior of the application while a screen reader is active. + } else { + console.log("Screen reader: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.SCREEN_READER_STATUS_CHANGED, onScreenReaderStatusChanged, false); +``` + +---------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.SPEAK_SCREEN_STATUS_CHANGED (speakscreenstatuschanged) + +The event fires when Speak Screen has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Speak Screen is active, `info.isSpeakScreenEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onSpeakScreenStatusChanged(info) { + if (info && typeof info.isSpeakScreenEnabled !== "undefined") { + if (info.isSpeakScreenEnabled) { + console.log("Speak Screen: ON"); + // Do something to improve the behavior of the application while Speak Screen is enabled. + } else { + console.log("Speak Screen: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.SPEAK_SCREEN_STATUS_CHANGED, onSpeakScreenStatusChanged, false); +``` + +---------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.SPEAK_SELECTION_STATUS_CHANGED (speakselectionstatuschanged) + +The event fires when Speak Selection has been enabled on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Speak Selection is active, `info.isSpeakSelectionEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onSpeakSelectionStatusChanged(info) { + if (info && typeof info.isSpeakSelectionEnabled !== "undefined") { + if (info.isSpeakSelectionEnabled) { + console.log("Speak Selection: ON"); + // Do something to improve the behavior of the application while Speak Selection is enabled. + } else { + console.log("Speak Selection: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.SPEAK_SELECTION_STATUS_CHANGED, onSpeakSelectionStatusChanged, false); +``` + + +---------------------------------------------------------------------------------------- +#### MobileAccessibilityNotifications.SWITCH_CONTROL_STATUS_CHANGED (switchcontrolstatuschanged) + +The event fires when Switch Control is running on an iOS device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Switch Control is running, `info.isSwitchControlRunning` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onSwitchControlStatusChanged(info) { + if (info && typeof info.isSwitchControlRunning !== "undefined") { + if (info.isSwitchControlRunning) { + console.log("Switch Control: ON"); + // Do something to improve the behavior of the application while Switch Control is running. + } else { + console.log("Switch Control: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.SWITCH_CONTROL_STATUS_CHANGED, onSwitchControlStatusChanged, false); +``` + +------------------------------------------------------------------------------------------------------ +#### MobileAccessibilityNotifications.TOUCH_EXPLORATION_STATUS_CHANGED (touchexplorationstatuschanged) + +The event fires when Touch Exploration has been enabled on an Android device. +The event returns an object, `info`, with the current status of accessibility features on the device. +If Touch Exploration is active, `info.isTouchExplorationEnabled` will equal `true`. + +```javascript + // Define a persistent callback method to handle the event + function onTouchExplorationChanged(info) { + if (info && typeof info.isTouchExplorationEnabled !== "undefined") { + if (info.isTouchExplorationEnabled) { + console.log("Touch Exploration: ON"); + // Do something to improve the behavior of the application while Touch Exploration is enabled. + } else { + console.log("Touch Exploration: OFF"); + } + } + } + + // Register the callback method to handle the event + window.addEventListener(MobileAccessibilityNotifications.TOUCH_EXPLORATION_STATUS_CHANGED, onTouchExplorationChanged, false); +``` diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/package.json b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/package.json new file mode 100644 index 00000000..6f6eb1e1 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/package.json @@ -0,0 +1,37 @@ +{ + "name": "phonegap-plugin-mobile-accessibility", + "description": "PhoneGap Mobile Accessibility Plugin", + "version": "1.0.5", + "homepage": "http://github.com/phonegap/phonegap-mobile-accessibility#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/phonegap/phonegap-mobile-accessibility.git" + }, + "bugs": { + "url": "https://github.com/phonegap/phonegap-mobile-accessibility/issues" + }, + "cordova": { + "id": "phonegap-plugin-mobile-accessibility", + "platforms": [ + "ios", + "android", + "windows" + ] + }, + "keywords": [ + "phonegap", + "mobile accessibility", + "ecosystem:cordova", + "cordova-ios", + "cordova-android", + "cordova-windows" + ], + "engines": [ + { + "name": "cordova", + "version": ">=3.0.0" + } + ], + "author": "Adobe PhoneGap Team", + "license": "Apache 2.0" +} diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/plugin.xml b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/plugin.xml new file mode 100644 index 00000000..dc56322a --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/plugin.xml @@ -0,0 +1,83 @@ + + + Mobile Accessibility + PhoneGap Mobile Accessibility Plugin + Apache 2.0 + phonegap, mobile accessibility + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/AbstractMobileAccessibilityHelper.java b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/AbstractMobileAccessibilityHelper.java new file mode 100644 index 00000000..d76a951f --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/AbstractMobileAccessibilityHelper.java @@ -0,0 +1,41 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +package com.phonegap.plugin.mobileaccessibility; + +import android.view.ViewParent; + +abstract class AbstractMobileAccessibilityHelper { + MobileAccessibility mMobileAccessibility; + ViewParent mParent; + public abstract void initialize(MobileAccessibility mobileAccessibility); + public abstract boolean isClosedCaptioningEnabled(); + public abstract boolean isScreenReaderRunning(); + public abstract boolean isTouchExplorationEnabled(); + public abstract void onAccessibilityStateChanged(boolean enabled); + public abstract void onCaptioningEnabledChanged(boolean enabled); + public abstract void onTouchExplorationStateChanged(boolean enabled); + public abstract void addStateChangeListeners(); + public abstract void removeStateChangeListeners(); + public abstract void announceForAccessibility(CharSequence text); + public abstract double getTextZoom(); + public abstract void setTextZoom(double textZoom); +} diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/DonutMobileAccessibilityHelper.java b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/DonutMobileAccessibilityHelper.java new file mode 100644 index 00000000..e6972719 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/DonutMobileAccessibilityHelper.java @@ -0,0 +1,187 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +package com.phonegap.plugin.mobileaccessibility; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.View; +import android.webkit.WebSettings; +import android.webkit.WebView; + +import java.lang.IllegalAccessException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +@TargetApi(Build.VERSION_CODES.DONUT) +public class DonutMobileAccessibilityHelper extends + AbstractMobileAccessibilityHelper { + AccessibilityManager mAccessibilityManager; + View mView; + + @Override + public void initialize(MobileAccessibility mobileAccessibility) { + mMobileAccessibility = mobileAccessibility; + WebView view; + try { + view = (WebView) mobileAccessibility.webView; + mView = view; + } catch(ClassCastException ce) { // cordova-android 4.0+ + try { + Method getView = mobileAccessibility.webView.getClass().getMethod("getView"); + mView = (View) getView.invoke(mobileAccessibility.webView); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + mAccessibilityManager = (AccessibilityManager) mMobileAccessibility.cordova.getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE); + } + + @Override + public boolean isClosedCaptioningEnabled() { + return false; + } + + @Override + public boolean isScreenReaderRunning() { + return mAccessibilityManager.isEnabled(); + } + + @Override + public boolean isTouchExplorationEnabled() { + return false; + } + + @Override + public void onAccessibilityStateChanged(boolean enabled) { + mMobileAccessibility.onAccessibilityStateChanged(enabled); + } + + @Override + public void onCaptioningEnabledChanged(boolean enabled) { + mMobileAccessibility.onCaptioningEnabledChanged(enabled); + } + + @Override + public void onTouchExplorationStateChanged(boolean enabled) { + mMobileAccessibility.onTouchExplorationStateChanged(enabled); + } + + @Override + public void addStateChangeListeners() { + } + + @Override + public void removeStateChangeListeners() { + } + + @Override + public void announceForAccessibility(CharSequence text) { + if (!mAccessibilityManager.isEnabled()) { + return; + } + + final int eventType = AccessibilityEvent.TYPE_VIEW_FOCUSED; + final AccessibilityEvent event = AccessibilityEvent.obtain(eventType); + event.getText().add(text); + event.setEnabled(mView.isEnabled()); + event.setClassName(mView.getClass().getName()); + event.setPackageName(mView.getContext().getPackageName()); + event.setContentDescription(null); + + mAccessibilityManager.sendAccessibilityEvent(event); + } + + @SuppressWarnings("deprecation") + @Override + public double getTextZoom() { + double zoom = 100; + WebSettings.TextSize wTextSize = WebSettings.TextSize.NORMAL; + + try { + Method getSettings = mView.getClass().getMethod("getSettings"); + Object wSettings = getSettings.invoke(mView); + Method getTextSize = wSettings.getClass().getMethod("getTextSize"); + wTextSize = (WebSettings.TextSize) getTextSize.invoke(wSettings); + } catch(ClassCastException ce) { + ce.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + switch (wTextSize) { + case LARGEST: + zoom = 200; + break; + case LARGER: + zoom = 150; + break; + case SMALLER: + zoom = 75; + break; + case SMALLEST: + zoom = 50; + break; + } + + return zoom; + } + + @SuppressWarnings("deprecation") + @Override + public void setTextZoom(double textZoom) { + WebSettings.TextSize wTextSize = WebSettings.TextSize.SMALLEST; + if (textZoom > 115) { + wTextSize = WebSettings.TextSize.LARGEST; + } else if (textZoom > 100) { + wTextSize = WebSettings.TextSize.LARGER; + } else if (textZoom == 100) { + wTextSize = WebSettings.TextSize.NORMAL; + } else if (textZoom > 50) { + wTextSize = WebSettings.TextSize.SMALLER; + } + //Log.i("MobileAccessibility", "fontScale = " + zoom + ", WebSettings.TextSize = " + wTextSize.toString()); + try { + Method getSettings = mView.getClass().getMethod("getSettings"); + Object wSettings = getSettings.invoke(mView); + Method setTextSize = wSettings.getClass().getMethod("setTextSize", WebSettings.TextSize.class); + setTextSize.invoke(wSettings, wTextSize); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } +} diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/IceCreamSandwichMobileAccessibilityHelper.java b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/IceCreamSandwichMobileAccessibilityHelper.java new file mode 100644 index 00000000..f0cd252e --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/IceCreamSandwichMobileAccessibilityHelper.java @@ -0,0 +1,104 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +package com.phonegap.plugin.mobileaccessibility; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.annotation.TargetApi; +import android.os.Build; +import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener; + +import java.lang.IllegalAccessException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) +public class IceCreamSandwichMobileAccessibilityHelper extends + DonutMobileAccessibilityHelper { + private AccessibilityStateChangeListener mAccessibilityStateChangeListener; + + @Override + public boolean isScreenReaderRunning() { + return mAccessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN).size() > 0; + } + + @Override + public void addStateChangeListeners() { + if (mAccessibilityStateChangeListener == null) { + mAccessibilityStateChangeListener = new InternalAccessibilityStateChangeListener(); + } + mAccessibilityManager.addAccessibilityStateChangeListener(mAccessibilityStateChangeListener); + } + + @Override + public void removeStateChangeListeners() { + mAccessibilityManager.removeAccessibilityStateChangeListener(mAccessibilityStateChangeListener); + mAccessibilityStateChangeListener = null; + } + + @Override + public double getTextZoom() { + double zoom = 100; + try { + Method getSettings = mView.getClass().getMethod("getSettings"); + Object wSettings = getSettings.invoke(mView); + Method getTextZoom = wSettings.getClass().getMethod("getTextZoom"); + zoom = Double.valueOf(getTextZoom.invoke(wSettings).toString()); + } catch (ClassCastException ce) { + ce.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return zoom; + } + + @Override + public void setTextZoom(double textZoom) { + //Log.i("MobileAccessibility", "setTextZoom(" + zoom + ")"); + try { + Method getSettings = mView.getClass().getMethod("getSettings"); + Object wSettings = getSettings.invoke(mView); + Method setTextZoom = wSettings.getClass().getMethod("setTextZoom", Integer.TYPE); + setTextZoom.invoke(wSettings, (int) textZoom); + } catch (ClassCastException ce) { + ce.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + private class InternalAccessibilityStateChangeListener + implements AccessibilityStateChangeListener { + + @Override + public void onAccessibilityStateChanged(boolean enabled) { + mMobileAccessibility.onAccessibilityStateChanged(enabled); + } + } +} diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/JellyBeanMobileAccessibilityHelper.java b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/JellyBeanMobileAccessibilityHelper.java new file mode 100644 index 00000000..7c97d247 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/JellyBeanMobileAccessibilityHelper.java @@ -0,0 +1,52 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +package com.phonegap.plugin.mobileaccessibility; + +import com.phonegap.plugin.mobileaccessibility.MobileAccessibility; + +import android.annotation.TargetApi; +import android.os.Build; +import android.view.accessibility.AccessibilityEvent; + +@TargetApi(Build.VERSION_CODES.JELLY_BEAN) +public class JellyBeanMobileAccessibilityHelper extends + IceCreamSandwichMobileAccessibilityHelper { + + @Override + public void initialize(MobileAccessibility mobileAccessibility) { + super.initialize(mobileAccessibility); + mParent = mView.getParentForAccessibility(); + } + + @Override + public void announceForAccessibility(CharSequence text) { + if (mAccessibilityManager.isEnabled() && mParent != null) { + mAccessibilityManager.interrupt(); + AccessibilityEvent event = AccessibilityEvent.obtain( + AccessibilityEvent.TYPE_ANNOUNCEMENT); + mView.onInitializeAccessibilityEvent(event); + event.getText().add(text); + event.setContentDescription(null); + mParent.requestSendAccessibilityEvent(mView, event); + } + } +} diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/KitKatMobileAccessibilityHelper.java b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/KitKatMobileAccessibilityHelper.java new file mode 100644 index 00000000..11d342cb --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/KitKatMobileAccessibilityHelper.java @@ -0,0 +1,99 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +package com.phonegap.plugin.mobileaccessibility; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.annotation.TargetApi; +import android.content.Context; +import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener; +import android.view.accessibility.CaptioningManager; +import android.view.accessibility.CaptioningManager.CaptioningChangeListener; + +@TargetApi(19) +public class KitKatMobileAccessibilityHelper extends + JellyBeanMobileAccessibilityHelper { + private CaptioningManager mCaptioningManager; + private CaptioningChangeListener mCaptioningChangeListener; + private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener; + + @Override + public void initialize(MobileAccessibility mobileAccessibility) { + super.initialize(mobileAccessibility); + mCaptioningManager = (CaptioningManager) mobileAccessibility.cordova.getActivity().getSystemService(Context.CAPTIONING_SERVICE); + } + + @Override + public boolean isScreenReaderRunning() { + return mAccessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_BRAILLE | AccessibilityServiceInfo.FEEDBACK_SPOKEN).size() > 0; + } + + @Override + public boolean isClosedCaptioningEnabled() { + return mCaptioningManager.isEnabled(); + } + + @Override + public boolean isTouchExplorationEnabled() { + return mAccessibilityManager.isTouchExplorationEnabled(); + } + + @Override + public void addStateChangeListeners() { + super.addStateChangeListeners(); + if (mCaptioningChangeListener == null) { + mCaptioningChangeListener = new CaptioningChangeListener() { + @Override + public void onEnabledChanged(boolean enabled) { + onCaptioningEnabledChanged(enabled); + } + }; + } + mCaptioningManager.addCaptioningChangeListener(mCaptioningChangeListener); + + if (mTouchExplorationStateChangeListener == null) { + mTouchExplorationStateChangeListener = new InternalTouchExplorationStateChangeListener(); + } + mAccessibilityManager.addTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); + } + + @Override + public void removeStateChangeListeners() { + super.removeStateChangeListeners(); + if (mCaptioningChangeListener != null) { + mCaptioningManager.removeCaptioningChangeListener(mCaptioningChangeListener); + mCaptioningChangeListener = null; + } + if (mTouchExplorationStateChangeListener != null) { + mAccessibilityManager.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); + mTouchExplorationStateChangeListener = null; + } + } + + private class InternalTouchExplorationStateChangeListener + implements TouchExplorationStateChangeListener { + + @Override + public void onTouchExplorationStateChanged(boolean enabled) { + mMobileAccessibility.onTouchExplorationStateChanged(enabled); + } + } +} diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/MobileAccessibility.java b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/MobileAccessibility.java new file mode 100644 index 00000000..a979420e --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/android/com/phonegap/plugin/mobileaccessibility/MobileAccessibility.java @@ -0,0 +1,330 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +package com.phonegap.plugin.mobileaccessibility; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CordovaWebView; +import org.apache.cordova.PluginResult; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.os.Build; +import android.webkit.WebView; + +import java.lang.IllegalAccessException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * This class provides information on the status of native accessibility services to JavaScript. + */ +public class MobileAccessibility extends CordovaPlugin { + private AbstractMobileAccessibilityHelper mMobileAccessibilityHelper; + private CallbackContext mCallbackContext = null; + private boolean mIsScreenReaderRunning = false; + private boolean mClosedCaptioningEnabled = false; + private boolean mTouchExplorationEnabled = false; + private boolean mCachedIsScreenReaderRunning = false; + private float mFontScale = 1; + + @Override + public void initialize(CordovaInterface cordova, CordovaWebView webView) { + super.initialize(cordova, webView); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + mMobileAccessibilityHelper = new KitKatMobileAccessibilityHelper(); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mMobileAccessibilityHelper = new JellyBeanMobileAccessibilityHelper(); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + mMobileAccessibilityHelper = new IceCreamSandwichMobileAccessibilityHelper(); + } else { + mMobileAccessibilityHelper = new DonutMobileAccessibilityHelper(); + } + mMobileAccessibilityHelper.initialize(this); + } + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + try { + if (action.equals("isScreenReaderRunning")) { + isScreenReaderRunning(callbackContext); + return true; + } else if (action.equals("isClosedCaptioningEnabled")) { + isClosedCaptioningEnabled(callbackContext); + return true; + } else if (action.equals("isTouchExplorationEnabled")) { + isTouchExplorationEnabled(callbackContext); + return true; + } else if (action.equals("postNotification")) { + if (args.length() > 1) { + String string = args.getString(1); + if (!string.isEmpty()) { + announceForAccessibility(string, callbackContext); + } + } + return true; + } else if(action.equals("getTextZoom")) { + getTextZoom(callbackContext); + return true; + } else if(action.equals("setTextZoom")) { + if (args.length() > 0) { + double textZoom = args.getDouble(0); + if (textZoom > 0) { + setTextZoom(textZoom, callbackContext); + } + } + return true; + } else if(action.equals("updateTextZoom")) { + updateTextZoom(callbackContext); + return true; + } else if (action.equals("start")) { + start(callbackContext); + return true; + } else if (action.equals("stop")) { + stop(); + return true; + } + } catch (JSONException e) { + e.printStackTrace(); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION)); + } + return false; + } + + /** + * Called when the system is about to pause the current activity + * + * @param multitasking Flag indicating if multitasking is turned on for app + */ + @Override + public void onPause(boolean multitasking) { + //Log.i("MobileAccessibility", "onPause"); + mCachedIsScreenReaderRunning = mIsScreenReaderRunning; + } + + /** + * Called when the activity will start interacting with the user. + * + * @param multitasking Flag indicating if multitasking is turned on for app + */ + @Override + public void onResume(boolean multitasking) { + //Log.i("MobileAccessibility", "onResume"); + if (mIsScreenReaderRunning && !mCachedIsScreenReaderRunning) { + //Log.i("MobileAccessibility", "Reloading page on reload because the Accessibility State has changed."); + mCachedIsScreenReaderRunning = mIsScreenReaderRunning; + stop(); + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + WebView view; + try { + view = (WebView) webView; + view.reload(); + } catch(ClassCastException ce) { // cordova-android 4.0+ + try { // cordova-android 4.0+ + Method getView = webView.getClass().getMethod("getView"); + Method reload = getView.invoke(webView).getClass().getMethod("reload"); + reload.invoke(webView); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + }); + } + } + + /** + * The final call you receive before your activity is destroyed. + */ + public void onDestroy() { + stop(); + } + + private void isScreenReaderRunning(final CallbackContext callbackContext) { + mIsScreenReaderRunning = mMobileAccessibilityHelper.isScreenReaderRunning(); + cordova.getThreadPool().execute(new Runnable() { + public void run() { + callbackContext.success(mIsScreenReaderRunning ? 1 : 0); + } + }); + } + + protected boolean isScreenReaderRunning() { + mIsScreenReaderRunning = mMobileAccessibilityHelper.isScreenReaderRunning(); + return mIsScreenReaderRunning; + } + + private void isClosedCaptioningEnabled(final CallbackContext callbackContext) { + mClosedCaptioningEnabled = mMobileAccessibilityHelper.isClosedCaptioningEnabled(); + cordova.getThreadPool().execute(new Runnable() { + public void run() { + callbackContext.success(mClosedCaptioningEnabled ? 1 : 0); + } + }); + } + + protected boolean isClosedCaptioningEnabled() { + mClosedCaptioningEnabled = mMobileAccessibilityHelper.isClosedCaptioningEnabled(); + return mClosedCaptioningEnabled; + } + + private void isTouchExplorationEnabled(final CallbackContext callbackContext) { + mTouchExplorationEnabled= mMobileAccessibilityHelper.isTouchExplorationEnabled(); + cordova.getThreadPool().execute(new Runnable() { + public void run() { + callbackContext.success(mTouchExplorationEnabled ? 1 : 0); + } + }); + } + + protected boolean isTouchExplorationEnabled() { + mTouchExplorationEnabled = mMobileAccessibilityHelper.isTouchExplorationEnabled(); + return mTouchExplorationEnabled; + } + + private void announceForAccessibility(CharSequence text, final CallbackContext callbackContext) { + mMobileAccessibilityHelper.announceForAccessibility(text); + if (callbackContext != null) { + JSONObject info = new JSONObject(); + try { + info.put("stringValue", text); + info.put("wasSuccessful", mIsScreenReaderRunning); + } catch (JSONException e) { + e.printStackTrace(); + } + callbackContext.success(info); + } + } + + public void onAccessibilityStateChanged(boolean enabled) { + mIsScreenReaderRunning = enabled; + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + sendMobileAccessibilityStatusChangedCallback(); + } + }); + } + + public void onCaptioningEnabledChanged(boolean enabled) { + mClosedCaptioningEnabled = enabled; + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + sendMobileAccessibilityStatusChangedCallback(); + } + }); + } + + public void onTouchExplorationStateChanged(boolean enabled) { + mTouchExplorationEnabled = enabled; + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + sendMobileAccessibilityStatusChangedCallback(); + } + }); + } + + private void getTextZoom(final CallbackContext callbackContext) { + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + final double textZoom = mMobileAccessibilityHelper.getTextZoom(); + if (callbackContext != null) { + callbackContext.success((int) textZoom); + } + } + }); + } + + private void setTextZoom(final double textZoom, final CallbackContext callbackContext) { + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + mMobileAccessibilityHelper.setTextZoom(textZoom); + if (callbackContext != null) { + callbackContext.success((int) mMobileAccessibilityHelper.getTextZoom()); + } + } + }); + } + + public void setTextZoom(final double textZoom) { + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + mMobileAccessibilityHelper.setTextZoom(textZoom); + } + }); + } + + private void updateTextZoom(final CallbackContext callbackContext) { + float fontScale = cordova.getActivity().getResources().getConfiguration().fontScale; + if (fontScale != mFontScale) { + mFontScale = fontScale; + } + final double textZoom = Math.round(mFontScale * 100); + setTextZoom(textZoom, callbackContext); + } + + private void sendMobileAccessibilityStatusChangedCallback() { + if (this.mCallbackContext != null) { + PluginResult result = new PluginResult(PluginResult.Status.OK, getMobileAccessibilityStatus()); + result.setKeepCallback(true); + this.mCallbackContext.sendPluginResult(result); + } + } + + /* Get the current mobile accessibility status. */ + private JSONObject getMobileAccessibilityStatus() { + JSONObject status = new JSONObject(); + try { + status.put("isScreenReaderRunning", mIsScreenReaderRunning); + status.put("isClosedCaptioningEnabled", mClosedCaptioningEnabled); + status.put("isTouchExplorationEnabled", mTouchExplorationEnabled); + //Log.i("MobileAccessibility", "MobileAccessibility.isScreenReaderRunning == " + status.getString("isScreenReaderRunning") + + // "\nMobileAccessibility.isClosedCaptioningEnabled == " + status.getString("isClosedCaptioningEnabled") + + // "\nMobileAccessibility.isTouchExplorationEnabled == " + status.getString("isTouchExplorationEnabled") ); + } catch (JSONException e) { + e.printStackTrace(); + } + return status; + } + + private void start(CallbackContext callbackContext) { + //Log.i("MobileAccessibility", "MobileAccessibility.start"); + mCallbackContext = callbackContext; + mMobileAccessibilityHelper.addStateChangeListeners(); + sendMobileAccessibilityStatusChangedCallback(); + } + + private void stop() { + //Log.i("MobileAccessibility", "MobileAccessibility.stop"); + if (mCallbackContext != null) { + sendMobileAccessibilityStatusChangedCallback(); + mMobileAccessibilityHelper.removeStateChangeListeners(); + mCallbackContext = null; + } + } +} diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/ios/CDVMobileAccessibility.h b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/ios/CDVMobileAccessibility.h new file mode 100644 index 00000000..662abbea --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/ios/CDVMobileAccessibility.h @@ -0,0 +1,82 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +#import + +static const int BASE_UI_FONT_TEXT_STYLE_BODY_POINT_SIZE = 16; + +@interface CDVMobileAccessibility : CDVPlugin { + NSString* callbackId; + NSString* commandCallbackId; + BOOL boldTextEnabled; + BOOL closedCaptioningEnabled; + BOOL darkerSystemColorsEnabled; + BOOL grayscaleEnabled; + BOOL guidedAccessEnabled; + BOOL invertColorsEnabled; + BOOL monoAudioEnabled; + BOOL reduceMotionEnabled; + BOOL reduceTransparencyEnabled; + BOOL speakScreenEnabled; + BOOL speakSelectionEnabled; + BOOL switchControlRunning; + BOOL voiceOverRunning; +} + +@property (strong) NSString* callbackId; +@property (strong) NSString* commandCallbackId; +@property BOOL boldTextEnabled; +@property BOOL closedCaptioningEnabled; +@property BOOL darkerSystemColorsEnabled; +@property BOOL grayscaleEnabled; +@property BOOL guidedAccessEnabled; +@property BOOL invertColorsEnabled; +@property BOOL monoAudioEnabled; +@property BOOL reduceMotionEnabled; +@property BOOL reduceTransparencyEnabled; +@property BOOL speakScreenEnabled; +@property BOOL speakSelectionEnabled; +@property BOOL switchControlRunning; +@property BOOL voiceOverRunning; +@property double mFontScale; + + +- (void) isBoldTextEnabled:(CDVInvokedUrlCommand*)command; +- (void) isClosedCaptioningEnabled:(CDVInvokedUrlCommand*)command; +- (void) isDarkerSystemColorsEnabled:(CDVInvokedUrlCommand*)command; +- (void) isGrayscaleEnabled:(CDVInvokedUrlCommand*)command; +- (void) isGuidedAccessEnabled:(CDVInvokedUrlCommand*)command; +- (void) isInvertColorsEnabled:(CDVInvokedUrlCommand*)command; +- (void) isMonoAudioEnabled:(CDVInvokedUrlCommand*)command; +- (void) isReduceMotionEnabled:(CDVInvokedUrlCommand*)command; +- (void) isReduceTransparencyEnabled:(CDVInvokedUrlCommand*)command; +- (void) isScreenReaderRunning:(CDVInvokedUrlCommand*)command; +- (void) isSpeakScreenEnabled:(CDVInvokedUrlCommand*)command; +- (void) isSpeakSelectionEnabled:(CDVInvokedUrlCommand*)command; +- (void) isSwitchControlRunning:(CDVInvokedUrlCommand*)command; +- (void) getTextZoom:(CDVInvokedUrlCommand*)command; +- (void) setTextZoom:(CDVInvokedUrlCommand*)command; +- (void) updateTextZoom:(CDVInvokedUrlCommand*)command; +- (void) postNotification:(CDVInvokedUrlCommand*)command; +- (void) start:(CDVInvokedUrlCommand*)command; +- (void) stop:(CDVInvokedUrlCommand*)command; + +@end \ No newline at end of file diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/ios/CDVMobileAccessibility.m b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/ios/CDVMobileAccessibility.m new file mode 100644 index 00000000..ad8da029 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/ios/CDVMobileAccessibility.m @@ -0,0 +1,511 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +#import "CDVMobileAccessibility.h" +#import +#import + +@interface CDVMobileAccessibility () + // add any property overrides + -(double) mGetTextZoom; + -(void) mSetTextZoom:(double)zoom; +@end + +@implementation CDVMobileAccessibility + +@synthesize callbackId; +@synthesize commandCallbackId; +@synthesize boldTextEnabled; +@synthesize closedCaptioningEnabled; +@synthesize darkerSystemColorsEnabled; +@synthesize grayscaleEnabled; +@synthesize guidedAccessEnabled; +@synthesize invertColorsEnabled; +@synthesize monoAudioEnabled; +@synthesize reduceMotionEnabled; +@synthesize reduceTransparencyEnabled; +@synthesize speakScreenEnabled; +@synthesize speakSelectionEnabled; +@synthesize switchControlRunning; +@synthesize voiceOverRunning; +@synthesize mFontScale; + +#define iOS7Delta (([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 ) ? 20 : 0 ) +#define iOS8Delta (([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 ) ? 30 : 0 ) + +// ////////////////////////////////////////////////// + +- (id)settingForKey:(NSString*)key +{ + return [self.commandDelegate.settings objectForKey:[key lowercaseString]]; +} + +- (void)pluginInitialize +{ + // SETTINGS //////////////////////// + + NSString* setting = nil; + + setting = @"YourConfigXmlSettingHere"; + if ([self settingForKey:setting]) { + // set your setting, other init here + } + + mFontScale = 1; + + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPause) name:UIApplicationDidEnterBackgroundNotification object:nil]; + +} + +// ////////////////////////////////////////////////// + +- (void)dealloc +{ + [self stop:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; +} + +- (void)onReset +{ + [self stop:nil]; +} + +- (void) onPause { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume) name:UIApplicationWillEnterForegroundNotification object:nil]; +} + +- (void)onResume +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPause) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onApplicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; +} + +- (void)onApplicationDidBecomeActive +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + [self performSelector:@selector(sendMobileAccessibilityStatusChangedCallback) withObject:nil afterDelay:0.1 ]; +} + +// ////////////////////////////////////////////////// + +#pragma Plugin interface + +- (void)isBoldTextEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + if (iOS8Delta) { + self.boldTextEnabled = UIAccessibilityIsBoldTextEnabled(); + } else { + self.boldTextEnabled = false; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.boldTextEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isClosedCaptioningEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + self.closedCaptioningEnabled = [self getClosedCaptioningEnabledStatus]; + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.closedCaptioningEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isDarkerSystemColorsEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + if (iOS8Delta) { + self.darkerSystemColorsEnabled = UIAccessibilityDarkerSystemColorsEnabled(); + } else { + self.darkerSystemColorsEnabled = false; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.darkerSystemColorsEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isGrayscaleEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + if (iOS8Delta) { + self.grayscaleEnabled = UIAccessibilityIsGrayscaleEnabled(); + } else { + self.grayscaleEnabled = false; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.grayscaleEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isGuidedAccessEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + self.guidedAccessEnabled = UIAccessibilityIsGuidedAccessEnabled(); + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.guidedAccessEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isInvertColorsEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + self.invertColorsEnabled = UIAccessibilityIsInvertColorsEnabled(); + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.invertColorsEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isMonoAudioEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + self.monoAudioEnabled = UIAccessibilityIsMonoAudioEnabled(); + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.monoAudioEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isReduceMotionEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + if (iOS8Delta) { + self.reduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled(); + } else { + self.reduceMotionEnabled = false; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.reduceMotionEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isReduceTransparencyEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + if (iOS8Delta) { + self.reduceTransparencyEnabled = UIAccessibilityIsReduceTransparencyEnabled(); + } else { + self.reduceTransparencyEnabled = false; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.reduceTransparencyEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isScreenReaderRunning:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + self.voiceOverRunning = UIAccessibilityIsVoiceOverRunning(); + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.voiceOverRunning]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isSpeakScreenEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + if (iOS8Delta) { + self.speakScreenEnabled = UIAccessibilityIsSpeakScreenEnabled(); + } else { + self.speakScreenEnabled = false; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.speakScreenEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isSpeakSelectionEnabled:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + if (iOS8Delta) { + self.speakSelectionEnabled = UIAccessibilityIsSpeakSelectionEnabled(); + } else { + self.speakSelectionEnabled = false; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.speakSelectionEnabled]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +- (void)isSwitchControlRunning:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + if (iOS8Delta) { + self.switchControlRunning = UIAccessibilityIsSwitchControlRunning(); + } else { + self.switchControlRunning = false; + } + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.switchControlRunning]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +-(double) mGetFontScale +{ + double fontScale = 1; + if (iOS7Delta) { + fontScale = [[UIFont preferredFontForTextStyle:UIFontTextStyleBody] pointSize] / BASE_UI_FONT_TEXT_STYLE_BODY_POINT_SIZE; + } + return fontScale; +} + +-(double) mGetTextZoom +{ + double zoom = round(mFontScale * 100); + // NSLog(@"mGetTextZoom %f%%", zoom); + return zoom; +} + +- (void) getTextZoom:(CDVInvokedUrlCommand *)command +{ + double zoom = [self mGetTextZoom]; + [self.commandDelegate runInBackground:^{ + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble: zoom]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; +} + +-(void) mSetTextZoom:(double)zoom +{ + // NSLog(@"mSetTextZoom %f%%'", zoom); + mFontScale = zoom/100; + if (iOS7Delta) { + NSString *jsString = [[NSString alloc] initWithFormat:@"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '%f%%'", zoom]; + [self.commandDelegate evalJs:jsString]; + } +} + +- (void) setTextZoom:(CDVInvokedUrlCommand *)command +{ + if (command != nil && [command.arguments count] > 0) { + double zoom = [[command.arguments objectAtIndex:0] doubleValue]; + [self mSetTextZoom:zoom]; + + [self.commandDelegate runInBackground:^{ + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:zoom]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; + } +} + +- (void)updateTextZoom:(CDVInvokedUrlCommand *)command +{ + float fontScale = [self mGetFontScale]; + if (fontScale != mFontScale) { + mFontScale = fontScale; + } + double zoom = [self mGetTextZoom]; + // NSLog(@"updateTextZoom %d%%'", zoom); + [self mSetTextZoom:zoom]; + + if (command != nil && command.callbackId != nil) { + [self.commandDelegate runInBackground:^{ + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:zoom]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + }]; + } +} + +- (void)postNotification:(CDVInvokedUrlCommand *)command +{ + CDVPluginResult* result = nil; + uint32_t notificationType = [[command.arguments objectAtIndex:0] intValue]; + NSString* notificationString = [command.arguments count] > 1 ? [command.arguments objectAtIndex:1] : @""; + + if (notificationString == nil) { + notificationString = @""; + } + if (UIAccessibilityIsVoiceOverRunning() && + [self isValidNotificationType:notificationType]) { + [self.commandDelegate runInBackground:^{ + if (notificationType == UIAccessibilityAnnouncementNotification) { + self.commandCallbackId = command.callbackId; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityAnnouncementDidFinish:) name:UIAccessibilityAnnouncementDidFinishNotification object:nil]; + } + + UIAccessibilityPostNotification(notificationType, notificationString); + + if (notificationType != UIAccessibilityAnnouncementNotification) { + NSMutableDictionary* data = [NSMutableDictionary dictionaryWithCapacity:2]; + [data setObject:notificationString forKey:@"stringValue"]; + [data setObject:@"true" forKey:@"wasSuccessful"]; + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:data]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + } + }]; + } else { + result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; + [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; + } +} + +- (BOOL)isValidNotificationType:(uint32_t)notificationType +{ + return (notificationType == UIAccessibilityScreenChangedNotification + || notificationType == UIAccessibilityLayoutChangedNotification + || notificationType == UIAccessibilityAnnouncementNotification + || notificationType == UIAccessibilityPageScrolledNotification); +} + +- (void)mobileAccessibilityAnnouncementDidFinish:(NSNotification *)dict +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityAnnouncementDidFinishNotification object:nil]; + + NSString* valueSpoken = [[dict userInfo] objectForKey:UIAccessibilityAnnouncementKeyStringValue]; + NSString* wasSuccessful = [[dict userInfo] objectForKey:UIAccessibilityAnnouncementKeyWasSuccessful]; + + NSMutableDictionary* data = [NSMutableDictionary dictionaryWithCapacity:2]; + [data setObject:valueSpoken forKey:@"stringValue"]; + [data setObject:wasSuccessful forKey:@"wasSuccessful"]; + + if (self.commandCallbackId) { + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:data]; + [self.commandDelegate sendPluginResult:result callbackId:self.commandCallbackId]; + self.commandCallbackId = nil; + } +} + +- (BOOL)getClosedCaptioningEnabledStatus +{ + BOOL status = false; + if (&MACaptionAppearanceGetDisplayType) { + status = (MACaptionAppearanceGetDisplayType(kMACaptionAppearanceDomainUser) > kMACaptionAppearanceDisplayTypeAutomatic); + } else { + status = UIAccessibilityIsClosedCaptioningEnabled(); + } + return status; +} + +- (void)mobileAccessibilityStatusChanged:(NSNotification *)notification +{ + [self sendMobileAccessibilityStatusChangedCallback]; +} + +- (void)sendMobileAccessibilityStatusChangedCallback +{ + if (self.callbackId) { + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getMobileAccessibilityStatus]]; + [result setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:result callbackId:self.callbackId]; + } +} + +/* Get the current mobile accessibility status. */ +- (NSDictionary*)getMobileAccessibilityStatus +{ + self.boldTextEnabled = UIAccessibilityIsBoldTextEnabled(); + self.closedCaptioningEnabled = [self getClosedCaptioningEnabledStatus]; + self.darkerSystemColorsEnabled = UIAccessibilityDarkerSystemColorsEnabled(); + self.grayscaleEnabled = UIAccessibilityIsGrayscaleEnabled(); + self.guidedAccessEnabled = UIAccessibilityIsGuidedAccessEnabled(); + self.invertColorsEnabled = UIAccessibilityIsInvertColorsEnabled(); + self.monoAudioEnabled = UIAccessibilityIsMonoAudioEnabled(); + self.reduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled(); + self.reduceTransparencyEnabled = UIAccessibilityIsReduceTransparencyEnabled(); + self.speakScreenEnabled = UIAccessibilityIsSpeakScreenEnabled(); + self.speakSelectionEnabled = UIAccessibilityIsSpeakSelectionEnabled(); + self.switchControlRunning = UIAccessibilityIsSwitchControlRunning(); + self.voiceOverRunning = UIAccessibilityIsVoiceOverRunning(); + + NSMutableDictionary* mobileAccessibilityData = [NSMutableDictionary dictionaryWithCapacity:5]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.boldTextEnabled] forKey:@"isBoldTextEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.closedCaptioningEnabled] forKey:@"isClosedCaptioningEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.darkerSystemColorsEnabled] forKey:@"isDarkerSystemColorsEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.grayscaleEnabled] forKey:@"isGrayscaleEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.guidedAccessEnabled] forKey:@"isGuidedAccessEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.invertColorsEnabled] forKey:@"isInvertColorsEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.monoAudioEnabled] forKey:@"isMonoAudioEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.reduceMotionEnabled] forKey:@"isReduceMotionEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.reduceTransparencyEnabled] forKey:@"isReduceTransparencyEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.speakScreenEnabled] forKey:@"isSpeakScreenEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.speakSelectionEnabled] forKey:@"isSpeakSelectionEnabled"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.switchControlRunning] forKey:@"isSwitchControlRunning"]; + [mobileAccessibilityData setObject:[NSNumber numberWithBool:self.voiceOverRunning] forKey:@"isScreenReaderRunning"]; + return mobileAccessibilityData; +} + + +/* start MobileAccessibility monitoring */ +- (void)start:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + self.callbackId = command.callbackId; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityClosedCaptioningStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityGuidedAccessStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityMonoAudioStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityVoiceOverStatusChanged object:nil]; + + if (iOS8Delta) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityBoldTextStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityDarkerSystemColorsStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityGrayscaleStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityReduceMotionStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityReduceTransparencyStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilitySpeakScreenStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilitySpeakSelectionStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilitySwitchControlStatusDidChangeNotification object:nil]; + } + + // Update the callback on start + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getMobileAccessibilityStatus]]; + [result setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:result callbackId:self.callbackId]; + }]; +} + +/* stop MobileAccessibility monitoring */ +- (void)stop:(CDVInvokedUrlCommand*)command +{ + [self.commandDelegate runInBackground:^{ + // callback one last time to clear the callback function on JS side + if (self.callbackId) + { + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getMobileAccessibilityStatus]]; + [result setKeepCallbackAsBool:NO]; + [self.commandDelegate sendPluginResult:result callbackId:self.callbackId]; + } + self.callbackId = nil; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityClosedCaptioningStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityGuidedAccessStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityAnnouncementDidFinishNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityMonoAudioStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityVoiceOverStatusChanged object:nil]; + + if (iOS8Delta) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityBoldTextStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityDarkerSystemColorsStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityGrayscaleStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityReduceMotionStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityReduceTransparencyStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilitySpeakScreenStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilitySpeakSelectionStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilitySwitchControlStatusDidChangeNotification object:nil]; + } + }]; +} + +@end diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/windows/mobile-accessibility-proxy.js b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/windows/mobile-accessibility-proxy.js new file mode 100644 index 00000000..166c3e5e --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/src/windows/mobile-accessibility-proxy.js @@ -0,0 +1,261 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +/*global Windows:true*/ + +var cordova = require('cordova'), + accessibilitySettings, + uiSettings, + callbackContext, + fontScale = 1, + styleElement, + bodyStyleDeclaration, + audio, + synth; + +function getAccessibilitySettings() { + if (!accessibilitySettings) { + accessibilitySettings = new Windows.UI.ViewManagement.AccessibilitySettings(); + } + return accessibilitySettings; +} + +function getUISettings() { + if (!uiSettings) { + uiSettings = new Windows.UI.ViewManagement.UISettings(); + } + return uiSettings; +} + +function getFontScale() { + if (!uiSettings) { + uiSettings = getUISettings(); + } + var scale = uiSettings.textScaleFactor; + // console.log("getFontScale " + scale); + return scale; +} + +function getTextZoom() { + var zoom = Math.round(fontScale * 100); + // console.log("getTextZoom " + zoom); + return zoom; +} + +function createStyleElement() { + if (!styleElement) { + styleElement = document.createElement("style"); + styleElement.type = "text/css"; + document.head.appendChild(styleElement); + } +} + +function setTextZoom(zoom) { + // console.log("setTextZoom " + zoom); + fontScale = zoom/100; + + createStyleElement(); + + if (bodyStyleDeclaration) { + styleElement.removeChild(bodyStyleDeclaration); + } + + bodyStyleDeclaration = document.createTextNode("body {-ms-text-size-adjust: " + zoom + "%}"); + + styleElement.appendChild(bodyStyleDeclaration); +} + +function onHighContrastChanged(event) { + cordova.fireWindowEvent(MobileAccessibilityNotifications.HIGH_CONTRAST_CHANGED, + getMobileAccessibilityStatus()); + sendMobileAccessibilityStatusChangedCallback(); +} + +function sendMobileAccessibilityStatusChangedCallback() { + console.log("sendMobileAccessibilityStatusChangedCallback"); + if (callbackContext && typeof callbackContext === "function") { + callbackContext(getMobileAccessibilityStatus()); + } +} + +function getMobileAccessibilityStatus() { + return { + isScreenReaderRunning: false, + isClosedCaptioningEnabled: false, + isHighContrastEnabled: accessibilitySettings.highContrast, + highContrastScheme: (accessibilitySettings.highContrast ? accessibilitySettings.highContrastScheme : undefined) + }; +} + +module.exports = { + start:function(win, fail, args) { + if (typeof win === "function") { + callbackContext = win; + } + if (!accessibilitySettings) { + accessibilitySettings = getAccessibilitySettings(); + } + accessibilitySettings.addEventListener("highcontrastchanged", onHighContrastChanged); + + if (!uiSettings) { + uiSettings = getUISettings(); + } + }, + stop:function(win, fail, args) { + if (accessibilitySettings) { + accessibilitySettings.removeEventListener("highcontrastchanged", onHighContrastChanged); + } + + if (synth) { + synth.close(); + synth = null; + } + + if (audio) { + audio = null; + } + + if (callbackContext) { + callbackContext = null; + } + }, + isScreenReaderRunning:function(win, fail, args) { + console && console.error && console.error("Error : Windows 8.1 does not yet have a way to detect that Narrator is running."); + fail && setTimeout(function() { + fail(new Error("Windows Phone 8.1 does not yet have a way to detect that Narrator is running.")); + }, 0); + if (win && typeof win === "function") { + win(false); + } + }, + isClosedCaptioningEnabled:function(win, fail, args) { + console && console.error && console.error("Error : MobileAccessibility.isClosedCaptioningEnabled is not yet implemented on Windows 8.1."); + fail && setTimeout(function() { + fail(new Error("MobileAccessibility.isClosedCaptioningEnabled is not yet implemented on Windows 8.1.")); + }, 0); + if (win && typeof win === "function") { + win(false); + } + }, + isHighContrastEnabled:function(win, fail, args) { + if (!accessibilitySettings) { + accessibilitySettings = getAccessibilitySettings(); + } + + if (win && typeof win === "function") { + win(accessibilitySettings.highContrast); + } + return accessibilitySettings.highContrast; + }, + getHighContrastScheme:function(win, fail, args) { + if (!accessibilitySettings) { + accessibilitySettings = getAccessibilitySettings(); + } + + var highContrastScheme = accessibilitySettings.highContrast ? accessibilitySettings.highContrastScheme : undefined; + + if (win) { + win(highContrastScheme); + } + return highContrastScheme; + }, + getTextZoom:function(win, fail, args) { + var zoom = Math.round(fontScale * 100); + + if (win) { + win(zoom); + } + + return zoom; + }, + setTextZoom:function(win, fail, args) { + var zoom = args[0]; + setTextZoom(args[0]); + + if (win) { + win(zoom); + } + + return zoom; + }, + updateTextZoom:function(win, fail, args) { + var scale = getFontScale(), + zoom; + if (scale !== fontScale) { + fontScale = scale; + } + zoom = getTextZoom(); + setTextZoom(zoom); + + if (win) { + win(zoom); + } + + return zoom; + }, + postNotification:function(win, fail, args) { + var str = args[1]; + + if (str && typeof str === "string") { + // The object for controlling and playing audio. + if (!audio) { + audio = new Audio(); + } else if (audio.pause) { + audio.pause(); + audio.src = null; + } + + // The object for controlling the speech synthesis engine (voice). + if (!synth) { + synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer(); + } + + if (str && str.length && str !== "\u200b") { + + // Generate the audio stream from plain text. + synth.synthesizeTextToStreamAsync(str).then(function (markersStream) { + + // Convert the stream to a URL Blob. + var blob = MSApp.createBlobFromRandomAccessStream(markersStream.contentType, markersStream); + // Send the Blob to the audio object. + audio.src = URL.createObjectURL(blob, { oneTimeOnly: true }); + // Start at beginning when speak is hit + markersStream.seek(0); + audio.AutoPlay = Boolean(true); + + // Audio on completed + audio.onended = function () { + if (win) { + win({ + stringValue: str, + wasSuccessful: true + }); + } + }; + + audio.play(); + }); + } + } + } +}; + +require("cordova/exec/proxy").add("MobileAccessibility", module.exports); diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/MobileAccessibilityNotifications.js b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/MobileAccessibilityNotifications.js new file mode 100644 index 00000000..6972902a --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/MobileAccessibilityNotifications.js @@ -0,0 +1,50 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +/** + * Mobile Accessibility Notification event constants + */ +module.exports = { + /* MobileAccessibility window events */ + SCREEN_READER_STATUS_CHANGED : "screenreaderstatuschanged", + CLOSED_CAPTIONING_STATUS_CHANGED : "closedcaptioningstatuschanged", + GUIDED_ACCESS_STATUS_CHANGED : "guidedaccessstatuschanged", + INVERT_COLORS_STATUS_CHANGED : "invertcolorsstatuschanged", + MONO_AUDIO_STATUS_CHANGED : "monoaudiostatuschanged", + REDUCE_MOTION_STATUS_CHANGED : "reducemotionstatuschanged", + TOUCH_EXPLORATION_STATUS_CHANGED : "touchexplorationstatechanged", + BOLD_TEXT_STATUS_CHANGED : "boldtextstatuschanged", + DARKER_SYSTEM_COLORS_STATUS_CHANGED : "darkersystemcolorsstatuschanged", + GRAYSCALE_STATUS_CHANGED : "grayscalestatuschanged", + REDUCE_TRANSPARENCY_STATUS_CHANGED : "reducetransparencystatuschanged", + SPEAK_SCREEN_STATUS_CHANGED : "speakscreenstatuschanged", + SPEAK_SELECTION_STATUS_CHANGED : "speakselectionstatuschanged", + SWITCH_CONTROL_STATUS_CHANGED : "switchcontrolstatuschanged", + + /* iOS specific UIAccessibilityNotifications */ + SCREEN_CHANGED : 1000, + LAYOUT_CHANGED : 1001, + ANNOUNCEMENT : 1008, + PAGE_SCROLLED : 1009, + + /* Windows specific high contrast event */ + HIGH_CONTRAST_CHANGED : "highcontrastchanged" +}; diff --git a/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/android/AndroidVox_v1.js b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/android/AndroidVox_v1.js new file mode 100644 index 00000000..8229b168 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-mobile-accessibility/www/android/AndroidVox_v1.js @@ -0,0 +1,1778 @@ +// Copyright 2013 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var goog=goog||{};goog.global=this;goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c=c[d]?c[d]:c[d]={}:c[d]=b};goog.define=function(a,b){var c=b;goog.exportPath_(a,c)};goog.DEBUG=!1;goog.LOCALE="en";goog.TRUSTED_SITE=!0;goog.provide=function(a){goog.exportPath_(a)}; +goog.setTestOnly=function(a){if(!goog.DEBUG)throw a=a||"",Error("Importing test-only code into non-debug environment"+a?": "+a:".");};goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]}; +goog.addDependency=function(a,b,c){if(goog.DEPENDENCIES_ENABLED){var d;a=a.replace(/\\/g,"/");for(var e=goog.dependencies_,f=0;d=b[f];f++)e.nameToPath[d]=a,a in e.pathToNames||(e.pathToNames[a]={}),e.pathToNames[a][d]=!0;for(d=0;b=c[d];d++)a in e.requires||(e.requires[a]={}),e.requires[a][b]=!0}};goog.useStrictRequires=!1;goog.ENABLE_DEBUG_LOADER=!0;goog.require=function(){};goog.basePath="";goog.nullFunction=function(){};goog.identityFunction=function(a){return a}; +goog.abstractMethod=function(){throw Error("unimplemented abstract method");};goog.addSingletonGetter=function(a){a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.DEPENDENCIES_ENABLED=!1; +goog.DEPENDENCIES_ENABLED&&(goog.included_={},goog.dependencies_={pathToNames:{},nameToPath:{},requires:{},visited:{},written:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return"undefined"!=typeof a&&"write"in a},goog.findBasePath_=function(){if(goog.global.CLOSURE_BASE_PATH)goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document,a=a.getElementsByTagName("script"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf("?"),d=-1==d? +c.length:d;if("base.js"==c.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a){var b=goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_;!goog.dependencies_.written[a]&&b(a)&&(goog.dependencies_.written[a]=!0)},goog.writeScriptTag_=function(a){if(goog.inHtmlDocument_()){var b=goog.global.document;if("complete"==b.readyState){if(b=/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}b.write('