--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD5BV11yD1v1Oan
+QyW2WHluF5lAd5JGcTITIOsN39l/jhw+N4RdjutQG9/TJBk11ieKvVafjX3ebSYf
+NnpXbufBug8xny8xKl5CUDTBxCGzV1rzuJV/4x6/b6V7ApEkRR7hcrE3/yx6Oc/r
+rsu/28YeKdGBWaMWJGiARoHp6OuimhJgET//UsegEnEpNG/O7sZfb6U47ignt/jO
+k4ZbDqlEZVSSsKygcOG0AeJ1BSWR+ekkckRUD+6dalVtJ8QPX62TNFhS5Q/GvBhV
+fbKreY9cbNb10lqE88ePKqWXJ0YnEK6F1Octd1BtIJI6/tTC8pwCtoONVlyHy4Y4
+cIP69vpLAgMBAAECggEAM+8ugrX0OjKIuDGE1/azvIYnbA6D7zUEYIDpBMe+sJ+O
+vFsPvANmiBqIH5zTtSqorIK4YiY8LftNjAzsjveOVhTbvlmYmgRgDCx2FEM3VBPP
+4CyK4VUYwIwkUvdCFfJkclhdJXSObh9Igbq+u5C2TOwjyXpMTP3i3X3W8lWlbw+R
+mtNHrP8zJ1UOFMquQrWMNABicOXIFgSd1NmhjRy/3MdNXSmIxFuI7CRIlU1SbK2t
+6BJhEpp/3zwhPJkohkVHyK75VtOXLDSQMoVvHBKLXdyzepXEvMvk1x08tBcvDTxz
+gRqprFnN2XtZxwbeRXU96IFv4oO3hWAL8HEPfLuPAQKBgQD/eNUOGsvqrE0GlrrT
+SQ6suRBM3Lv5dbtd8jNpbEyRqJcKoPlxUs73bCVk4rESr4+9WMC+XVp0sSqmROlW
+zmKlSV4CuIw7uL/CjU3mCPAtsFAk9DdNtXO0vmxS5accyKNAHkzkssgukaSwjtlF
+ekZenybBCYB4ezsQ7tLsIpQ5YQKBgQD5iR6hN8iQj9MZn98R+IF/SWLlQn6U9tMa
+MlF1b6bNomoU0UvV+gRCsRnC16sPecAOK29sP3a45c4/Semr+OHMUOcnRNitsxz+
+EYCbYnMQ5sXWp8D41Xtl2EV7MzA9EJhr0/lixPBrvcsV2MliZqZVQWkYEvBy+Z4k
+0JoSwS23KwKBgGOw3UMBxe0vi2c0znbAnY9dMDUuNdQk0xbX+qP69O4qIbauFmjY
+bZczhmwV4g9unuK+jYg7mZ7Lu97iKUQMiYYCWUMqjN6JO5tJ1ModVswdb0jcW/Bh
+DGPNoyu+HjYnPT06Fbtw4Jj7kI6tT6/DBU7LQC437QAW5ne3Gmu3GqxBAoGBAL+s
+F572XlTMZPZ12r7PB4liMViwbtK1lQm2ROPT02h4rMs4yOufk842gvcq+fZ1KpS3
+wGqBhQwZWQc8GwVBsw9hxWxgcZ9ayZZOk17HjGMbIDP1v0Bjmtlr+lLbyt3c9Xc9
+5316kMHxkyFA18+B0ZoDGFqpkZB/NH5KzU5CnH7pAoGACHgNUxqdjUrDjR/acy4m
+tH5UA09WmEvdJCYxCco0EPAlx1j9UTH0XIlfvTXgwcEL1MXS7GrsJdBj/URw+br4
+FcLIZJp9ov2wN6QdfwseTIamIgtd0MQHMLd3tQ1fdhiKJRilLdCiXMGefdHCx8MB
+0kq72fFs7urSyHuM485Ft9A=
+-----END PRIVATE KEY-----
--- /dev/null
+QAAAAJ2ASW5L+vb6g3A4hsuHXFaNg7YCnPLC1P46kiBtUHct59SFrhAnRieXpSqPx/OEWtL11mxcj3mrsn1VGLzGD+VSWDSTrV8PxCdtVWqd7g9URHIk6fmRJQV14gG04XCgrLCSVGVEqQ5bhpPO+LcnKO44pW9fxu7ObzQpcRKgx1L/PxFgEpqi6+jpgUaAaCQWo1mB0Skextu/y67rzzl6LP83sXLhHkUkkQJ7pW+/HuN/lbjzWlezIcTBNFBCXioxL58xD7rB525XejYfJm3efY2fVr2KJ9Y1GSTT3xtQ645dhDc+HI5/2d8N6yATMnFGkndAmRdueVi2JUOn5tRvPch1XQX5R+SjoBuYl+jrvN+qh73s39vgOlt9mOfBksjCwLQWWgu85DfwawJmt2p9c0sFXAC39fQCYJQCJDrYjFtvnVa6L/qIgbtmz9WWl1PHa/1aQYnih8GprTeKuj/ASYKuwYYdN+Z8iOxkP1zboRjf3btkRELFZkjkkBkixFc5ZiwiwIg+lcWvSVpOP1CxbsVDwEn77J/s+p2iYfGyCf6djNRCTwjQj+2z7+8uKhxaeShWfQf1BN0buZnVr3noBpH3RyHvyBxdKzUZiXfEzdwCmqCLKzmS44+F5X/tggtdA4bCjspHhlFt0WaW0Eu0szWlnlN7qp2ghFk4bYfUxYieM5AR9wEAAQA= @unknown
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+fetchstatus() {
+ curl \
+ -o /dev/null \
+ --silent \
+ --head \
+ --write-out '%{http_code}' \
+ -m 45 \
+ "https://salon.home.tortuga.enhydra.fr"
+}
+
+urlstatus=$(fetchstatus)
+echo $urlstatus
+if [ "$urlstatus" = "200" ]; then
+ exit 0
+fi
+docker restart tortugahome
+
--- /dev/null
+alias
+backup
+bin
+daemon
+ftp
+games
+gnats
+guest
+irc
+lp
+mail
+man
+nobody
+operator
+proxy
+qmaild
+qmaill
+qmailp
+qmailq
+qmailr
+qmails
+sync
+sys
--- /dev/null
+#
+# This is the main Apache HTTP server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path. If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
+# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
+# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
+# will be interpreted as '/logs/access_log'.
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path. If you point
+# ServerRoot at a non-local disk, be sure to specify a local disk on the
+# Mutex directive, if file-based mutexes are used. If you wish to share the
+# same ServerRoot for multiple httpd daemons, you will need to change at
+# least PidFile.
+#
+ServerRoot "/usr/local/apache2"
+
+#
+# Mutex: Allows you to set the mutex mechanism and mutex file directory
+# for individual mutexes, or change the global defaults
+#
+# Uncomment and change the directory if mutexes are file-based and the default
+# mutex file directory is not on a local disk or is not appropriate for some
+# other reason.
+#
+# Mutex default:logs
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses.
+#
+#Listen 12.34.56.78:80
+Listen 80
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+LoadModule mpm_event_module modules/mod_mpm_event.so
+#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
+#LoadModule mpm_worker_module modules/mod_mpm_worker.so
+LoadModule authn_file_module modules/mod_authn_file.so
+#LoadModule authn_dbm_module modules/mod_authn_dbm.so
+#LoadModule authn_anon_module modules/mod_authn_anon.so
+#LoadModule authn_dbd_module modules/mod_authn_dbd.so
+#LoadModule authn_socache_module modules/mod_authn_socache.so
+LoadModule authn_core_module modules/mod_authn_core.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_user_module modules/mod_authz_user.so
+#LoadModule authz_dbm_module modules/mod_authz_dbm.so
+#LoadModule authz_owner_module modules/mod_authz_owner.so
+#LoadModule authz_dbd_module modules/mod_authz_dbd.so
+LoadModule authz_core_module modules/mod_authz_core.so
+#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
+#LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so
+LoadModule access_compat_module modules/mod_access_compat.so
+LoadModule auth_basic_module modules/mod_auth_basic.so
+#LoadModule auth_form_module modules/mod_auth_form.so
+#LoadModule auth_digest_module modules/mod_auth_digest.so
+#LoadModule allowmethods_module modules/mod_allowmethods.so
+#LoadModule isapi_module modules/mod_isapi.so
+#LoadModule file_cache_module modules/mod_file_cache.so
+#LoadModule cache_module modules/mod_cache.so
+#LoadModule cache_disk_module modules/mod_cache_disk.so
+#LoadModule cache_socache_module modules/mod_cache_socache.so
+#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
+#LoadModule socache_dbm_module modules/mod_socache_dbm.so
+#LoadModule socache_memcache_module modules/mod_socache_memcache.so
+#LoadModule socache_redis_module modules/mod_socache_redis.so
+#LoadModule watchdog_module modules/mod_watchdog.so
+#LoadModule macro_module modules/mod_macro.so
+#LoadModule dbd_module modules/mod_dbd.so
+#LoadModule bucketeer_module modules/mod_bucketeer.so
+#LoadModule dumpio_module modules/mod_dumpio.so
+#LoadModule echo_module modules/mod_echo.so
+#LoadModule example_hooks_module modules/mod_example_hooks.so
+#LoadModule case_filter_module modules/mod_case_filter.so
+#LoadModule case_filter_in_module modules/mod_case_filter_in.so
+#LoadModule example_ipc_module modules/mod_example_ipc.so
+#LoadModule buffer_module modules/mod_buffer.so
+#LoadModule data_module modules/mod_data.so
+#LoadModule ratelimit_module modules/mod_ratelimit.so
+LoadModule reqtimeout_module modules/mod_reqtimeout.so
+#LoadModule ext_filter_module modules/mod_ext_filter.so
+#LoadModule request_module modules/mod_request.so
+#LoadModule include_module modules/mod_include.so
+LoadModule filter_module modules/mod_filter.so
+#LoadModule reflector_module modules/mod_reflector.so
+#LoadModule substitute_module modules/mod_substitute.so
+#LoadModule sed_module modules/mod_sed.so
+#LoadModule charset_lite_module modules/mod_charset_lite.so
+#LoadModule deflate_module modules/mod_deflate.so
+#LoadModule xml2enc_module modules/mod_xml2enc.so
+#LoadModule proxy_html_module modules/mod_proxy_html.so
+#LoadModule brotli_module modules/mod_brotli.so
+LoadModule mime_module modules/mod_mime.so
+#LoadModule ldap_module modules/mod_ldap.so
+LoadModule log_config_module modules/mod_log_config.so
+#LoadModule log_debug_module modules/mod_log_debug.so
+#LoadModule log_forensic_module modules/mod_log_forensic.so
+#LoadModule logio_module modules/mod_logio.so
+#LoadModule lua_module modules/mod_lua.so
+LoadModule env_module modules/mod_env.so
+#LoadModule mime_magic_module modules/mod_mime_magic.so
+#LoadModule cern_meta_module modules/mod_cern_meta.so
+#LoadModule expires_module modules/mod_expires.so
+LoadModule headers_module modules/mod_headers.so
+#LoadModule ident_module modules/mod_ident.so
+#LoadModule usertrack_module modules/mod_usertrack.so
+#LoadModule unique_id_module modules/mod_unique_id.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule version_module modules/mod_version.so
+LoadModule remoteip_module modules/mod_remoteip.so
+LoadModule proxy_module modules/mod_proxy.so
+#LoadModule proxy_connect_module modules/mod_proxy_connect.so
+#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
+#LoadModule proxy_http_module modules/mod_proxy_http.so
+LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
+#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
+#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
+#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
+#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
+#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
+#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
+#LoadModule proxy_express_module modules/mod_proxy_express.so
+#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
+#LoadModule session_module modules/mod_session.so
+#LoadModule session_cookie_module modules/mod_session_cookie.so
+#LoadModule session_crypto_module modules/mod_session_crypto.so
+#LoadModule session_dbd_module modules/mod_session_dbd.so
+#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
+#LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
+#LoadModule ssl_module modules/mod_ssl.so
+#LoadModule optional_hook_export_module modules/mod_optional_hook_export.so
+#LoadModule optional_hook_import_module modules/mod_optional_hook_import.so
+#LoadModule optional_fn_import_module modules/mod_optional_fn_import.so
+#LoadModule optional_fn_export_module modules/mod_optional_fn_export.so
+#LoadModule dialup_module modules/mod_dialup.so
+#LoadModule http2_module modules/mod_http2.so
+#LoadModule proxy_http2_module modules/mod_proxy_http2.so
+#LoadModule md_module modules/mod_md.so
+#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
+#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
+#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
+#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
+LoadModule unixd_module modules/mod_unixd.so
+#LoadModule heartbeat_module modules/mod_heartbeat.so
+#LoadModule heartmonitor_module modules/mod_heartmonitor.so
+#LoadModule dav_module modules/mod_dav.so
+LoadModule status_module modules/mod_status.so
+LoadModule autoindex_module modules/mod_autoindex.so
+#LoadModule asis_module modules/mod_asis.so
+#LoadModule info_module modules/mod_info.so
+#LoadModule suexec_module modules/mod_suexec.so
+<IfModule !mpm_prefork_module>
+ #LoadModule cgid_module modules/mod_cgid.so
+</IfModule>
+<IfModule mpm_prefork_module>
+ #LoadModule cgi_module modules/mod_cgi.so
+</IfModule>
+#LoadModule dav_fs_module modules/mod_dav_fs.so
+#LoadModule dav_lock_module modules/mod_dav_lock.so
+#LoadModule vhost_alias_module modules/mod_vhost_alias.so
+#LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule dir_module modules/mod_dir.so
+#LoadModule imagemap_module modules/mod_imagemap.so
+#LoadModule actions_module modules/mod_actions.so
+#LoadModule speling_module modules/mod_speling.so
+#LoadModule userdir_module modules/mod_userdir.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule rewrite_module modules/mod_rewrite.so
+
+<IfModule unixd_module>
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+#
+User www-data
+Group www-data
+
+</IfModule>
+
+# 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition. These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed. This address appears on some server-generated pages, such
+# as error documents. e.g. admin@your-domain.com
+#
+ServerAdmin you@example.com
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+#
+#ServerName www.example.com:80
+
+#
+# Deny access to the entirety of your server's filesystem. You must
+# explicitly permit access to web content directories in other
+# <Directory> blocks below.
+#
+<Directory />
+ AllowOverride none
+ Require all denied
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/usr/local/apache2/htdocs"
+<Directory "/usr/local/apache2/htdocs">
+ #
+ # Possible values for the Options directive are "None", "All",
+ # or any combination of:
+ # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+ #
+ # Note that "MultiViews" must be named *explicitly* --- "Options All"
+ # doesn't give it to you.
+ #
+ # The Options directive is both complicated and important. Please see
+ # http://httpd.apache.org/docs/2.4/mod/core.html#options
+ # for more information.
+ #
+ Options Indexes FollowSymLinks
+
+ #
+ # AllowOverride controls what directives may be placed in .htaccess files.
+ # It can be "All", "None", or any combination of the keywords:
+ # AllowOverride FileInfo AuthConfig Limit
+ #
+ AllowOverride All
+
+ #
+ # Controls who can get stuff from this server.
+ #
+ Require all granted
+</Directory>
+
+ProxyPassMatch ^/(.*\.php(/.*)?)$ "fcgi://tortugahome:9000/application/$1" timeout=1800
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+<IfModule dir_module>
+ DirectoryIndex index.html index.php
+</IfModule>
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<Files ".ht*">
+ Require all denied
+</Files>
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog /proc/self/fd/2
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+<IfModule log_config_module>
+ #
+ # The following directives define some format nicknames for use with
+ # a CustomLog directive (see below).
+ #
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+ LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+ <IfModule logio_module>
+ # You need to enable mod_logio.c to use %I and %O
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+ </IfModule>
+
+ #
+ # The location and format of the access logfile (Common Logfile Format).
+ # If you do not define any access logfiles within a <VirtualHost>
+ # container, they will be logged here. Contrariwise, if you *do*
+ # define per-<VirtualHost> access logfiles, transactions will be
+ # logged therein and *not* in this file.
+ #
+ CustomLog /proc/self/fd/1 common
+
+ #
+ # If you prefer a logfile with access, agent, and referer information
+ # (Combined Logfile Format) you can use the following directive.
+ #
+ #CustomLog "logs/access_log" combined
+</IfModule>
+
+<IfModule alias_module>
+ #
+ # Redirect: Allows you to tell clients about documents that used to
+ # exist in your server's namespace, but do not anymore. The client
+ # will make a new request for the document at its new location.
+ # Example:
+ # Redirect permanent /foo http://www.example.com/bar
+
+ #
+ # Alias: Maps web paths into filesystem paths and is used to
+ # access content that does not live under the DocumentRoot.
+ # Example:
+ # Alias /webpath /full/filesystem/path
+ #
+ # If you include a trailing / on /webpath then the server will
+ # require it to be present in the URL. You will also likely
+ # need to provide a <Directory> section to allow access to
+ # the filesystem path.
+
+ #
+ # ScriptAlias: This controls which directories contain server scripts.
+ # ScriptAliases are essentially the same as Aliases, except that
+ # documents in the target directory are treated as applications and
+ # run by the server when requested rather than as documents sent to the
+ # client. The same rules about trailing "/" apply to ScriptAlias
+ # directives as to Alias.
+ #
+ ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"
+
+</IfModule>
+
+<IfModule cgid_module>
+ #
+ # ScriptSock: On threaded servers, designate the path to the UNIX
+ # socket used to communicate with the CGI daemon of mod_cgid.
+ #
+ #Scriptsock cgisock
+</IfModule>
+
+#
+# "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+<Directory "/usr/local/apache2/cgi-bin">
+ AllowOverride None
+ Options None
+ Require all granted
+</Directory>
+
+<IfModule headers_module>
+ #
+ # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied
+ # backend servers which have lingering "httpoxy" defects.
+ # 'Proxy' request header is undefined by the IETF, not listed by IANA
+ #
+ RequestHeader unset Proxy early
+</IfModule>
+
+<IfModule mime_module>
+ #
+ # TypesConfig points to the file containing the list of mappings from
+ # filename extension to MIME-type.
+ #
+ TypesConfig conf/mime.types
+
+ #
+ # AddType allows you to add to or override the MIME configuration
+ # file specified in TypesConfig for specific file types.
+ #
+ #AddType application/x-gzip .tgz
+ #
+ # AddEncoding allows you to have certain browsers uncompress
+ # information on the fly. Note: Not all browsers support this.
+ #
+ #AddEncoding x-compress .Z
+ #AddEncoding x-gzip .gz .tgz
+ #
+ # If the AddEncoding directives above are commented-out, then you
+ # probably should define those extensions to indicate media types:
+ #
+ AddType application/x-compress .Z
+ AddType application/x-gzip .gz .tgz
+
+ #
+ # AddHandler allows you to map certain file extensions to "handlers":
+ # actions unrelated to filetype. These can be either built into the server
+ # or added with the Action directive (see below)
+ #
+ # To use CGI scripts outside of ScriptAliased directories:
+ # (You will also need to add "ExecCGI" to the "Options" directive.)
+ #
+ #AddHandler cgi-script .cgi
+
+ # For type maps (negotiated resources):
+ #AddHandler type-map var
+
+ #
+ # Filters allow you to process content before it is sent to the client.
+ #
+ # To parse .shtml files for server-side includes (SSI):
+ # (You will also need to add "Includes" to the "Options" directive.)
+ #
+ #AddType text/html .shtml
+ #AddOutputFilter INCLUDES .shtml
+</IfModule>
+
+#
+# The mod_mime_magic module allows the server to use various hints from the
+# contents of the file itself to determine its type. The MIMEMagicFile
+# directive tells the module where the hint definitions are located.
+#
+#MIMEMagicFile conf/magic
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# MaxRanges: Maximum number of Ranges in a request before
+# returning the entire resource, or one of the special
+# values 'default', 'none' or 'unlimited'.
+# Default setting is to accept 200 Ranges.
+#MaxRanges unlimited
+
+#
+# EnableMMAP and EnableSendfile: On systems that support it,
+# memory-mapping or the sendfile syscall may be used to deliver
+# files. This usually improves server performance, but must
+# be turned off when serving from networked-mounted
+# filesystems or if support for these functions is otherwise
+# broken on your system.
+# Defaults: EnableMMAP On, EnableSendfile Off
+#
+#EnableMMAP off
+#EnableSendfile on
+
+# Supplemental configuration
+#
+# The configuration files in the conf/extra/ directory can be
+# included to add extra features or to modify the default configuration of
+# the server, or you may simply copy their contents here and change as
+# necessary.
+
+# Server-pool management (MPM specific)
+#Include conf/extra/httpd-mpm.conf
+
+# Multi-language error messages
+#Include conf/extra/httpd-multilang-errordoc.conf
+
+# Fancy directory listings
+#Include conf/extra/httpd-autoindex.conf
+
+# Language settings
+#Include conf/extra/httpd-languages.conf
+
+# User home directories
+#Include conf/extra/httpd-userdir.conf
+
+# Real-time info on requests and configuration
+#Include conf/extra/httpd-info.conf
+
+# Virtual hosts
+#Include conf/extra/httpd-vhosts.conf
+
+# Local access to the Apache HTTP Server Manual
+#Include conf/extra/httpd-manual.conf
+
+# Distributed authoring and versioning (WebDAV)
+#Include conf/extra/httpd-dav.conf
+
+# Various default settings
+#Include conf/extra/httpd-default.conf
+
+# Configure mod_proxy_html to understand HTML4/XHTML1
+<IfModule proxy_html_module>
+Include conf/extra/proxy-html.conf
+</IfModule>
+
+# Secure (SSL/TLS) connections
+#Include conf/extra/httpd-ssl.conf
+#
+# Note: The following must must be present to support
+# starting without SSL on platforms with no /dev/random equivalent
+# but a statically compiled-in mod_ssl.
+#
+<IfModule ssl_module>
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+</IfModule>
+
--- /dev/null
+check process atd
+ with pidfile "/var/run/atd.pid"
+ start program = "/usr/sbin/service atd start"
+ stop program = "/usr/sbin/service atd stop"
--- /dev/null
+set alert vincent@enhydra.fr
+
+set mailserver smtp.gmail.com port 587
+ username "monitoring.cubedesigners@gmail.com" password "vwkjhyvzrznyrdzh"
+ using tlsv1
+
+set httpd
+ port 2812
+ allow "monit":"mi6QeSR0SNMgT709oGpwdW"
--- /dev/null
+check process home-hue
+ with pidfile "/var/run/home-hue.pid"
+ group homeautomation
+ start program = "/home/tortugahome/www/servers/startdaemon hue"
+ stop program = "/home/tortugahome/www/servers/stopdaemon hue"
+
+check process home-domoticz
+ with pidfile "/var/run/home-domoticz.pid"
+ group homeautomation
+ start program = "/home/tortugahome/www/servers/startdaemon domoticz"
+ stop program = "/home/tortugahome/www/servers/stopdaemon domoticz"
+
+check process home-cron
+ with pidfile "/var/run/home-cron.pid"
+ group homeautomation
+ start program = "/home/tortugahome/www/servers/startdaemon cron"
+ stop program = "/home/tortugahome/www/servers/stopdaemon cron"
+
+check process home-squeezebox
+ with pidfile "/var/run/home-squeezebox.pid"
+ group homeautomation
+ start program = "/home/tortugahome/www/servers/startdaemon squeezebox"
+ stop program = "/home/tortugahome/www/servers/stopdaemon squeezebox"
+
+check process home-logcat-salon
+ with pidfile "/var/run/home-logcats.pid"
+ group homeautomation
+ start program = "/home/tortugahome/www/servers/startdaemon logcats"
+ stop program = "/home/tortugahome/www/servers/stopdaemon logcats"
+
+check process home-logcat-bureau
+ with pidfile "/var/run/home-logcatb.pid"
+ group homeautomation
+ start program = "/home/tortugahome/www/servers/startdaemon logcatb"
+ stop program = "/home/tortugahome/www/servers/stopdaemon logcatb"
--- /dev/null
+93bd27ae102b7b0fffc9fce7f2e47321
--- /dev/null
+[www]
+pm.max_children = 15
+pm.max_requests = 500
\ No newline at end of file
--- /dev/null
+upload_max_filesize = 100M
+post_max_size = 108M
--- /dev/null
+version: '3.1'
+services:
+ redis:
+ container_name: tortugahome-redis
+ image: 'redis:alpine'
+ networks:
+ - tortugahome
+ volumes:
+ - './redis/data/:/data/'
+ restart: unless-stopped
+
+ webserver:
+ container_name: tortugahome-httpd
+ image: 'httpd:alpine'
+ working_dir: /application
+ volumes:
+ - './src/:/usr/local/apache2/htdocs/'
+ - './src/.docker/config/httpd/httpd.conf:/usr/local/apache2/conf/httpd.conf'
+ ports:
+ - '3001:80'
+ environment:
+ VIRTUAL_HOST: home.tortuga.enhydra.fr, entree.home.tortuga.enhydra.fr, cuisine.home.tortuga.enhydra.fr, salon.home.tortuga.enhydra.fr, bureau.home.tortuga.enhydra.fr, chambre.home.tortuga.enhydra.fr, litvincent.home.tortuga.enhydra.fr, litjerome.home.tortuga.enhydra.fr, sdb.home.tortuga.enhydra.fr, wc.home.tortuga.enhydra.fr, bureausun.home.tortuga.enhydra.fr, cour.home.tortuga.enhydra.fr, balcon.home.tortuga.enhydra.fr, cave.home.tortuga.enhydra.fr
+ LETSENCRYPT_HOST: home.tortuga.enhydra.fr, entree.home.tortuga.enhydra.fr, cuisine.home.tortuga.enhydra.fr, salon.home.tortuga.enhydra.fr, bureau.home.tortuga.enhydra.fr, chambre.home.tortuga.enhydra.fr, litvincent.home.tortuga.enhydra.fr, litjerome.home.tortuga.enhydra.fr, sdb.home.tortuga.enhydra.fr, wc.home.tortuga.enhydra.fr, bureausun.home.tortuga.enhydra.fr, cour.home.tortuga.enhydra.fr, balcon.home.tortuga.enhydra.fr, cave.home.tortuga.enhydra.fr
+ networks:
+ - tortugahome
+ restart: unless-stopped
+
+ php-fpm:
+ container_name: tortugahome
+ build: src/.docker/phpdocker/php-fpm
+ working_dir: /application
+ environment:
+ ADB_HOST: host.docker.internal
+ ports:
+ - '2813:2812'
+ - '5037:5037'
+ volumes:
+ - '/etc/timezone:/etc/timezone:ro'
+ - '/etc/localtime:/etc/localtime:ro'
+ - '/etc/ssl/certs:/etc/ssl/certs:ro'
+ - './src:/application'
+ - './phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/7.4/fpm/conf.d/99-overrides.ini'
+ - './src/:/home/tortugahome/www/'
+ - './src/bin/:/usr/local/bin/'
+# - './sessions:/var/lib/php/sessions'
+ - 'share:/nas/'
+ - 'share:/volume1/Share/'
+ - 'share:/Share/'
+ - './log:/var/log/tortugahome'
+ - './src/.docker/config/at.allow:/etc/at.allow:ro'
+ - './src/.docker/config/at.deny:/etc/at.deny:ro'
+ - './src/.docker/android/:/root/.android/'
+ - './src/.docker/config/monit/conf.d/:/etc/monit/conf.d/'
+ - './src/.docker/config/monit/id:/var/lib/monit/id'
+ - '/dev/bus/usb:/dev/bus/usb'
+ - './src/.docker/config/php/php.ini:/etc/php/7.4/fpm/conf.d/00-php-override.ini'
+ - './src/.docker/config/php/fpm.conf:/etc/php/7.4/fpm/pool.d/zz-overrides.conf'
+ networks:
+ - tortugahome
+ extra_hosts:
+ - "host.docker.internal:host-gateway"
+ restart: unless-stopped
+ privileged: true
+ healthcheck:
+ test: ["CMD", "/application/bin/healthcheck"]
+ interval: 1m
+ timeout: 60s
+ retries: 1
+
+networks:
+ tortugahome:
+ external:
+ name: tortugahome
+
+volumes:
+ share:
+ driver_opts:
+ type: cifs
+ o: "username=Share,password=RQpZHMDLtbc229FQV3,rw,file_mode=0777,dir_mode=0777"
+ device: "//192.168.13.1/1.42.6-25556"
--- /dev/null
+@echo off
+cls
+C:\tools\cygwin\bin\ssh.exe -tt root@home.tortuga.enhydra.fr 'docker exec -it -u root tortugahome /bin/bash'
--- /dev/null
+<html>
+<head>
+ <title>PHPDocker.io Readme</title>
+ <link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
+
+ <style>
+ code {
+ background-color : #ddd;
+ padding : 2px 5px;
+ font-family : monospace;
+ font-size : 16px;
+ }
+ </style>
+</head>
+<body>
+
+<div class="pure-g">
+ <div class="pure-u-1-24"></div>
+ <div class="pure-u-22-24">
+ <h1>PHPDocker.io generated environment</h1>
+
+<h1>Add to your project</h1>
+
+<p>Simply, unzip the file into your project, this will create <code>docker-compose.yml</code> on the root of your project and a folder
+named <code>phpdocker</code> containing nginx and php-fpm config for it.</p>
+
+<p>Ensure the webserver config on <code>phpdocker/nginx/nginx.conf</code> is correct for your project. PHPDocker.io will have
+customised this file according to the front controller location relative to the docker-compose file you chose on the
+generator (by default <code>public/index.php</code>).</p>
+
+<p>Note: you may place the files elsewhere in your project. Make sure you modify the locations for the php-fpm dockerfile,
+the php.ini overrides and nginx config on <code>docker-compose.yml</code> if you do so.</p>
+
+<h1>How to run</h1>
+
+<p>Dependencies:</p>
+
+<ul>
+<li>docker. See <a href="https://docs.docker.com/engine/installation">https://docs.docker.com/engine/installation</a></li>
+<li>docker-compose. See <a href="https://docs.docker.com/compose/install/">docs.docker.com/compose/install</a></li>
+</ul>
+
+<p>Once you're done, simply <code>cd</code> to your project and run <code>docker-compose up -d</code>. This will initialise and start all the
+containers, then leave them running in the background.</p>
+
+<h2>Services exposed outside your environment</h2>
+
+<p>You can access your application via <strong><code>localhost</code></strong>. Mailhog and nginx both respond to any hostname, in case you want to
+add your own hostname on your <code>/etc/hosts</code></p>
+
+<table>
+<thead>
+<tr>
+ <th>Service</th>
+ <th>Address outside containers</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+ <td>Webserver</td>
+ <td><a href="http://localhost:29000">localhost:29000</a></td>
+</tr>
+</tbody>
+</table>
+
+<h2>Hosts within your environment</h2>
+
+<p>You'll need to configure your application to use any services you enabled:</p>
+
+<table>
+<thead>
+<tr>
+ <th>Service</th>
+ <th>Hostname</th>
+ <th>Port number</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+ <td>php-fpm</td>
+ <td>php-fpm</td>
+ <td>9000</td>
+</tr>
+<tr>
+ <td>Redis</td>
+ <td>redis</td>
+ <td>6379 (default)</td>
+</tr>
+</tbody>
+</table>
+
+<h1>Docker compose cheatsheet</h1>
+
+<p><strong>Note:</strong> you need to cd first to where your docker-compose.yml file lives.</p>
+
+<ul>
+<li>Start containers in the background: <code>docker-compose up -d</code></li>
+<li>Start containers on the foreground: <code>docker-compose up</code>. You will see a stream of logs for every container running.
+ctrl+c stops containers.</li>
+<li>Stop containers: <code>docker-compose stop</code></li>
+<li>Kill containers: <code>docker-compose kill</code></li>
+<li>View container logs: <code>docker-compose logs</code> for all containers or <code>docker-compose logs SERVICE_NAME</code> for the logs of
+all containers in <code>SERVICE_NAME</code>.</li>
+<li>Execute command inside of container: <code>docker-compose exec SERVICE_NAME COMMAND</code> where <code>COMMAND</code> is whatever you want
+to run. Examples:
+
+<ul>
+<li>Shell into the PHP container, <code>docker-compose exec php-fpm bash</code></li>
+<li>Run symfony console, <code>docker-compose exec php-fpm bin/console</code></li>
+<li>Open a mysql shell, <code>docker-compose exec mysql mysql -uroot -pCHOSEN_ROOT_PASSWORD</code></li>
+</ul></li>
+</ul>
+
+<h1>Application file permissions</h1>
+
+<p>As in all server environments, your application needs the correct file permissions to work properly. You can change the
+files throughout the container, so you won't care if the user exists or has the same ID on your host.</p>
+
+<p><code>docker-compose exec php-fpm chown -R www-data:www-data /application/public</code></p>
+
+<h1>Recommendations</h1>
+
+<p>It's hard to avoid file permission issues when fiddling about with containers due to the fact that, from your OS point
+of view, any files created within the container are owned by the process that runs the docker engine (this is usually
+root). Different OS will also have different problems, for instance you can run stuff in containers
+using <code>docker exec -it -u $(id -u):$(id -g) CONTAINER_NAME COMMAND</code> to force your current user ID into the process, but
+this will only work if your host OS is Linux, not mac. Follow a couple of simple rules and save yourself a world of
+hurt.</p>
+
+<ul>
+<li>Run composer outside of the php container, as doing so would install all your dependencies owned by <code>root</code> within your
+vendor folder.</li>
+<li>Run commands (ie Symfony's console, or Laravel's artisan) straight inside of your container. You can easily open a
+shell as described above and do your thing from there.</li>
+</ul>
+
+<h1>Simple basic Xdebug configuration with integration to PHPStorm</h1>
+
+<h2>Xdebug 2</h2>
+
+<p>To configure <strong>Xdebug 2</strong> you need add these lines in php-fpm/php-ini-overrides.ini:</p>
+
+<h3>For linux:</h3>
+
+<pre><code>xdebug.remote_enable = 1
+xdebug.remote_connect_back = 1
+xdebug.remote_autostart = 1
+</code></pre>
+
+<h3>For macOS and Windows:</h3>
+
+<pre><code>xdebug.remote_enable = 1
+xdebug.remote_host = host.docker.internal
+xdebug.remote_autostart = 1
+</code></pre>
+
+<h2>Xdebug 3</h2>
+
+<p>To configure <strong>Xdebug 3</strong> you need add these lines in php-fpm/php-ini-overrides.ini:</p>
+
+<h3>For linux:</h3>
+
+<pre><code>xdebug.mode = debug
+xdebug.remote_connect_back = true
+xdebug.start_with_request = yes
+</code></pre>
+
+<h3>For macOS and Windows:</h3>
+
+<pre><code>xdebug.mode = debug
+xdebug.remote_host = host.docker.internal
+xdebug.start_with_request = yes
+</code></pre>
+
+<h2>Add the section “environment” to the php-fpm service in docker-compose.yml:</h2>
+
+<pre><code>environment:
+ PHP_IDE_CONFIG: "serverName=Docker"
+</code></pre>
+
+<h3>Create a server configuration in PHPStorm:</h3>
+
+<ul>
+<li>In PHPStorm open Preferences | Languages & Frameworks | PHP | Servers</li>
+<li>Add new server</li>
+<li>The “Name” field should be the same as the parameter “serverName” value in “environment” in docker-compose.yml (i.e. *
+Docker* in the example above)</li>
+<li>A value of the "port" field should be the same as first port(before a colon) in "webserver" service in
+docker-compose.yml</li>
+<li>Select "Use path mappings" and set mappings between a path to your project on a host system and the Docker container.</li>
+<li>Finally, add “Xdebug helper” extension in your browser, set breakpoints and start debugging</li>
+</ul>
+ </div>
+ <div class="pure-u-1-24"></div>
+</div>
+
+<script>
+ var tables = document.getElementsByTagName('table')
+ for (var i = 0; i < tables.length; i++) {
+ tables[i].className = 'pure-table'
+ }
+</script>
+</body>
+</html>
--- /dev/null
+PHPDocker.io generated environment
+==================================
+
+# Add to your project #
+
+Simply, unzip the file into your project, this will create `docker-compose.yml` on the root of your project and a folder
+named `phpdocker` containing nginx and php-fpm config for it.
+
+Ensure the webserver config on `phpdocker/nginx/nginx.conf` is correct for your project. PHPDocker.io will have
+customised this file according to the front controller location relative to the docker-compose file you chose on the
+generator (by default `public/index.php`).
+
+Note: you may place the files elsewhere in your project. Make sure you modify the locations for the php-fpm dockerfile,
+the php.ini overrides and nginx config on `docker-compose.yml` if you do so.
+
+# How to run #
+
+Dependencies:
+
+* docker. See [https://docs.docker.com/engine/installation](https://docs.docker.com/engine/installation)
+* docker-compose. See [docs.docker.com/compose/install](https://docs.docker.com/compose/install/)
+
+Once you're done, simply `cd` to your project and run `docker-compose up -d`. This will initialise and start all the
+containers, then leave them running in the background.
+
+## Services exposed outside your environment ##
+
+You can access your application via **`localhost`**. Mailhog and nginx both respond to any hostname, in case you want to
+add your own hostname on your `/etc/hosts`
+
+Service|Address outside containers
+-------|--------------------------
+Webserver|[localhost:29000](http://localhost:29000)
+
+## Hosts within your environment ##
+
+You'll need to configure your application to use any services you enabled:
+
+Service|Hostname|Port number
+------|---------|-----------
+php-fpm|php-fpm|9000
+Redis|redis|6379 (default)
+
+# Docker compose cheatsheet #
+
+**Note:** you need to cd first to where your docker-compose.yml file lives.
+
+* Start containers in the background: `docker-compose up -d`
+* Start containers on the foreground: `docker-compose up`. You will see a stream of logs for every container running.
+ ctrl+c stops containers.
+* Stop containers: `docker-compose stop`
+* Kill containers: `docker-compose kill`
+* View container logs: `docker-compose logs` for all containers or `docker-compose logs SERVICE_NAME` for the logs of
+ all containers in `SERVICE_NAME`.
+* Execute command inside of container: `docker-compose exec SERVICE_NAME COMMAND` where `COMMAND` is whatever you want
+ to run. Examples:
+ * Shell into the PHP container, `docker-compose exec php-fpm bash`
+ * Run symfony console, `docker-compose exec php-fpm bin/console`
+ * Open a mysql shell, `docker-compose exec mysql mysql -uroot -pCHOSEN_ROOT_PASSWORD`
+
+# Application file permissions #
+
+As in all server environments, your application needs the correct file permissions to work properly. You can change the
+files throughout the container, so you won't care if the user exists or has the same ID on your host.
+
+`docker-compose exec php-fpm chown -R www-data:www-data /application/public`
+
+# Recommendations #
+
+It's hard to avoid file permission issues when fiddling about with containers due to the fact that, from your OS point
+of view, any files created within the container are owned by the process that runs the docker engine (this is usually
+root). Different OS will also have different problems, for instance you can run stuff in containers
+using `docker exec -it -u $(id -u):$(id -g) CONTAINER_NAME COMMAND` to force your current user ID into the process, but
+this will only work if your host OS is Linux, not mac. Follow a couple of simple rules and save yourself a world of
+hurt.
+
+* Run composer outside of the php container, as doing so would install all your dependencies owned by `root` within your
+ vendor folder.
+* Run commands (ie Symfony's console, or Laravel's artisan) straight inside of your container. You can easily open a
+ shell as described above and do your thing from there.
+
+# Simple basic Xdebug configuration with integration to PHPStorm
+
+## Xdebug 2
+
+To configure **Xdebug 2** you need add these lines in php-fpm/php-ini-overrides.ini:
+
+### For linux:
+
+```
+xdebug.remote_enable = 1
+xdebug.remote_connect_back = 1
+xdebug.remote_autostart = 1
+```
+
+### For macOS and Windows:
+
+```
+xdebug.remote_enable = 1
+xdebug.remote_host = host.docker.internal
+xdebug.remote_autostart = 1
+```
+
+## Xdebug 3
+
+To configure **Xdebug 3** you need add these lines in php-fpm/php-ini-overrides.ini:
+
+### For linux:
+
+```
+xdebug.mode = debug
+xdebug.remote_connect_back = true
+xdebug.start_with_request = yes
+```
+
+### For macOS and Windows:
+
+```
+xdebug.mode = debug
+xdebug.remote_host = host.docker.internal
+xdebug.start_with_request = yes
+```
+
+## Add the section “environment” to the php-fpm service in docker-compose.yml:
+
+```
+environment:
+ PHP_IDE_CONFIG: "serverName=Docker"
+```
+
+### Create a server configuration in PHPStorm:
+
+* In PHPStorm open Preferences | Languages & Frameworks | PHP | Servers
+* Add new server
+* The “Name” field should be the same as the parameter “serverName” value in “environment” in docker-compose.yml (i.e. *
+ Docker* in the example above)
+* A value of the "port" field should be the same as first port(before a colon) in "webserver" service in
+ docker-compose.yml
+* Select "Use path mappings" and set mappings between a path to your project on a host system and the Docker container.
+* Finally, add “Xdebug helper” extension in your browser, set breakpoints and start debugging
+
+
+
--- /dev/null
+server {
+ listen 80 default;
+
+ client_max_body_size 108M;
+
+ access_log /var/log/nginx/application.access.log;
+
+ root /application/public;
+ index index.php;
+
+ # try to serve file directly, fallback to index.php
+ location / {
+ try_files $uri /index.php$is_args$args;
+ }
+
+ if (!-e $request_filename) {
+ rewrite ^.*$ /index.php last;
+ }
+
+ location ~ \.php$ {
+ fastcgi_pass php-fpm:9000;
+ fastcgi_index index.php;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
+ fastcgi_buffers 16 16k;
+ fastcgi_buffer_size 32k;
+ include fastcgi_params;
+ }
+}
--- /dev/null
+FROM phpdockerio/php:7.4-fpm
+WORKDIR "/application"
+
+RUN apt-get update
+RUN apt-get -y --no-install-recommends install php7.4-bz2 php7.4-gd php7.4-igbinary php7.4-imap php7.4-xsl php7.4-curl php7.4-json php7.4-imagick php7.4-intl php7.4-memcached php7.4-mysql php7.4-redis php7.4-soap php7.4-ssh2 php7.4-tidy
+RUN apt-get -y --no-install-recommends install monit less nano wakeonlan lynx at xplanet ffmpeg wget curl composer adb git
+RUN apt-get clean;rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
+
+COPY startup /usr/bin/startup
+CMD exec /usr/bin/startup
+
+EXPOSE 2812
+EXPOSE 5037
--- /dev/null
+#!/bin/sh
+/application/bin/restarthome
+/usr/sbin/php-fpm7.4 -O
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+/usr/bin/docker start tortugahome
--- /dev/null
+#!/bin/sh
+cd /docker/tortugahome
+chmod -R 777 ./log
+rm -f monit/conf.d/*.save
+docker network create --driver bridge tortugahome
+docker-compose build --pull
+docker-compose pull
+docker-compose down
+docker-compose up -d
+#docker exec -it tortugahome /application/bin/restarthome
+docker restart nginx-proxy
--- /dev/null
+APP_NAME=TortugaHome
+APP_ENV=local
+APP_KEY=base64:8FOwR397LKkyMdWBepTOzrXTWkFZegmJst/yZZWmI60=
+APP_DEBUG=true
+APP_URL=http://home2.tortuga.enhydra.fr
+
+LOG_CHANNEL=stack
+
+DB_CONNECTION=mysql
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=home
+DB_USERNAME=home
+DB_PASSWORD=atacama
+
+BROADCAST_DRIVER=log
+CACHE_DRIVER=file
+QUEUE_CONNECTION=sync
+SESSION_DRIVER=file
+SESSION_LIFETIME=120
+
+REDIS_HOST=127.0.0.1
+REDIS_PASSWORD=null
+REDIS_PORT=6379
+
+MAIL_MAILER=smtp
+MAIL_HOST=smtp.mailtrap.io
+MAIL_PORT=2525
+MAIL_USERNAME=null
+MAIL_PASSWORD=null
+MAIL_ENCRYPTION=null
+MAIL_FROM_ADDRESS=null
+MAIL_FROM_NAME="${APP_NAME}"
+
+AWS_ACCESS_KEY_ID=
+AWS_SECRET_ACCESS_KEY=
+AWS_DEFAULT_REGION=us-east-1
+AWS_BUCKET=
+
+PUSHER_APP_ID=
+PUSHER_APP_KEY=
+PUSHER_APP_SECRET=
+PUSHER_APP_CLUSTER=mt1
+
+MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
+MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
-Require ip 192.168.1.0/24 192.168.13.0/24 127.0.0.0/8 88.190.245.49 192.168.17.0/24
+Require ip 192.168.1.0/24 192.168.13.0/24 127.0.0.0/8 88.190.245.49 192.168.17.0/24 172.0.0.0/8
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
- #
- # Redirection to www. subdomain
- RewriteCond %{HTTP_HOST} =home.tortuga
- RewriteRule ^(.*)$ https://home.tortuga.enhydra.fr/$1 [R=301,L]
- RewriteCond %{HTTPS} off
- RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
-
-
-
- # Block browser access to the framework folder and sensitive files
-# RewriteRule ^framework/.*$ - [F]
-# RewriteRule ^.*\.ini$ - [F]
-#
-# # Redirect auth header to env
-# RewriteRule ^.*$ - [E=REMOTE_USER:%{HTTP:Authorization}]
-# # Skip static files
-# RewriteRule ^css/ - [NC,L]
-# RewriteRule ^js/ - [NC,L]
-# RewriteRule ^images/ - [NC,L]
-# RewriteRule ^files/ - [NC,L]
-# # Redirect CMS files to the right URL
-# RewriteRule ^([a-f0-9]{6,})-([a-z0-9-.])([a-z0-9-.])([a-z0-9-.]*)$ files/$2/$3/$1-$2$3$4 [NC,L]
-# # Ignore static files or directories
+ # Ignore static files or directories
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^apk(.*)$ app/build/outputs/apk/debug/app-debug.apk [F]
- RewriteRule ^s$ https://salon.home.tortuga.enhydra.fr/ [L,R=301]
- RewriteRule ^b$ https://bureau.home.tortuga.enhydra.fr/ [L,R=301]
+ RewriteRule ^s$ https://salon.home.tortuga.enhydra.fr/ [L,R=301]
+ RewriteRule ^b$ https://bureau.home.tortuga.enhydra.fr/ [L,R=301]
# Finally, redirect all other cases to the index.php
RewriteRule ^.*$ index.php [NC,L]
</IfModule>
--- /dev/null
+
+# Datasource local storage ignored files
+/dataSources.local.xml
+/dataSources/
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ComposerJsonPluginSettings">
+ <unboundedVersionInspectionSettings>
+ <excludedPackages />
+ </unboundedVersionInspectionSettings>
+ <customRepositories />
+ <composerUpdateOptions />
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="dataSourceStorageLocal" created-in="IU-222.4345.14">
+ <data-source name="LFY(3).db" uuid="e5a3291d-855f-44b2-be41-76fe6b0c2136">
+ <database-info product="SQLite" version="3.25.1" jdbc-version="2.1" driver-name="SQLite JDBC" driver-version="3.25.1" dbms="SQLITE" exact-version="3.25.1" exact-driver-version="3.25">
+ <identifier-quote-string>"</identifier-quote-string>
+ </database-info>
+ <case-sensitivity plain-identifiers="mixed" quoted-identifiers="mixed" />
+ <secret-storage>master_key</secret-storage>
+ <auth-provider>no-auth</auth-provider>
+ <schema-mapping>
+ <introspection-scope>
+ <node kind="schema" qname="@" />
+ </introspection-scope>
+ </schema-mapping>
+ </data-source>
+ <data-source name="LFY_ZiGate.db" uuid="7a96a13f-795b-43c9-b1de-56e65d9fcf95">
+ <database-info product="SQLite" version="3.25.1" jdbc-version="2.1" driver-name="SQLite JDBC" driver-version="3.25.1" dbms="SQLITE" exact-version="3.25.1" exact-driver-version="3.25">
+ <identifier-quote-string>"</identifier-quote-string>
+ </database-info>
+ <case-sensitivity plain-identifiers="mixed" quoted-identifiers="mixed" />
+ <secret-storage>master_key</secret-storage>
+ <auth-provider>no-auth</auth-provider>
+ <schema-mapping>
+ <introspection-scope>
+ <node kind="schema" qname="@" />
+ </introspection-scope>
+ </schema-mapping>
+ </data-source>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
+ <data-source source="LOCAL" name="LFY(3).db" uuid="e5a3291d-855f-44b2-be41-76fe6b0c2136">
+ <driver-ref>sqlite.xerial</driver-ref>
+ <synchronize>true</synchronize>
+ <jdbc-driver>org.sqlite.JDBC</jdbc-driver>
+ <jdbc-url>jdbc:sqlite:$USER_HOME$/Downloads/LFY(3).db</jdbc-url>
+ </data-source>
+ <data-source source="LOCAL" name="LFY_ZiGate.db" uuid="7a96a13f-795b-43c9-b1de-56e65d9fcf95">
+ <driver-ref>sqlite.xerial</driver-ref>
+ <synchronize>true</synchronize>
+ <jdbc-driver>org.sqlite.JDBC</jdbc-driver>
+ <jdbc-url>jdbc:sqlite:$USER_HOME$/Downloads/LFY_ZiGate.db</jdbc-url>
+ </data-source>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<dataSource name="LFY_ZiGate.db">
+ <database-model serializer="dbm" dbms="SQLITE" family-id="SQLITE" format-version="4.43">
+ <root id="1"/>
+ <collation id="2" parent="1" name="BINARY"/>
+ <collation id="3" parent="1" name="NOCASE"/>
+ <collation id="4" parent="1" name="RTRIM"/>
+ <schema id="5" parent="1" name="main">
+ <Current>1</Current>
+ </schema>
+ <table id="6" parent="5" name="BackupLog"/>
+ <table id="7" parent="5" name="Cameras"/>
+ <table id="8" parent="5" name="CamerasActiveDevices"/>
+ <table id="9" parent="5" name="CustomImages"/>
+ <table id="10" parent="5" name="DeviceStatus"/>
+ <table id="11" parent="5" name="DeviceToPlansMap"/>
+ <table id="12" parent="5" name="EnoceanSensors"/>
+ <table id="13" parent="5" name="EventMaster"/>
+ <table id="14" parent="5" name="EventRules"/>
+ <table id="15" parent="5" name="Fan"/>
+ <table id="16" parent="5" name="Fan_Calendar"/>
+ <table id="17" parent="5" name="FibaroLink"/>
+ <table id="18" parent="5" name="Floorplans"/>
+ <table id="19" parent="5" name="GooglePubSubLink"/>
+ <table id="20" parent="5" name="Hardware"/>
+ <table id="21" parent="5" name="HttpLink"/>
+ <table id="22" parent="5" name="LightSubDevices"/>
+ <table id="23" parent="5" name="LightingLog"/>
+ <table id="24" parent="5" name="Meter"/>
+ <table id="25" parent="5" name="Meter_Calendar"/>
+ <table id="26" parent="5" name="MobileDevices"/>
+ <table id="27" parent="5" name="MultiMeter"/>
+ <table id="28" parent="5" name="MultiMeter_Calendar"/>
+ <table id="29" parent="5" name="MySensors"/>
+ <table id="30" parent="5" name="MySensorsChilds"/>
+ <table id="31" parent="5" name="MySensorsVars"/>
+ <table id="32" parent="5" name="Notifications"/>
+ <table id="33" parent="5" name="Percentage"/>
+ <table id="34" parent="5" name="Percentage_Calendar"/>
+ <table id="35" parent="5" name="Plans"/>
+ <table id="36" parent="5" name="Preferences"/>
+ <table id="37" parent="5" name="PushLink"/>
+ <table id="38" parent="5" name="Rain"/>
+ <table id="39" parent="5" name="Rain_Calendar"/>
+ <table id="40" parent="5" name="SceneDevices"/>
+ <table id="41" parent="5" name="SceneLog"/>
+ <table id="42" parent="5" name="SceneTimers"/>
+ <table id="43" parent="5" name="Scenes"/>
+ <table id="44" parent="5" name="SetpointTimers"/>
+ <table id="45" parent="5" name="SharedDevices"/>
+ <table id="46" parent="5" name="Temperature"/>
+ <table id="47" parent="5" name="Temperature_Calendar"/>
+ <table id="48" parent="5" name="TimerPlans"/>
+ <table id="49" parent="5" name="Timers"/>
+ <table id="50" parent="5" name="ToonDevices"/>
+ <table id="51" parent="5" name="UV"/>
+ <table id="52" parent="5" name="UV_Calendar"/>
+ <table id="53" parent="5" name="UserSessions"/>
+ <table id="54" parent="5" name="UserVariables"/>
+ <table id="55" parent="5" name="Users"/>
+ <table id="56" parent="5" name="WOLNodes"/>
+ <table id="57" parent="5" name="Wind"/>
+ <table id="58" parent="5" name="Wind_Calendar"/>
+ <table id="59" parent="5" name="ZWaveNodes"/>
+ <table id="60" parent="5" name="sqlite_master">
+ <System>1</System>
+ </table>
+ <table id="61" parent="5" name="sqlite_stat1"/>
+ <column id="62" parent="6" name="Key">
+ <DataType>VARCHAR(50)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="63" parent="6" name="nValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="64" parent="7" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="65" parent="7" name="Name">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="66" parent="7" name="Enabled">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="67" parent="7" name="Address">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <Position>4</Position>
+ </column>
+ <column id="68" parent="7" name="Port">
+ <DataType>INTEGER|0s</DataType>
+ <Position>5</Position>
+ </column>
+ <column id="69" parent="7" name="Protocol">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="70" parent="7" name="Username">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="71" parent="7" name="Password">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="72" parent="7" name="ImageURL">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <key id="73" parent="7">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="74" parent="8" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="75" parent="8" name="CameraRowID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="76" parent="8" name="DevSceneType">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="77" parent="8" name="DevSceneRowID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="78" parent="8" name="DevSceneWhen">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="79" parent="8" name="DevSceneDelay">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>6</Position>
+ </column>
+ <key id="80" parent="8">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="81" parent="9" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="82" parent="9" name="Base">
+ <DataType>VARCHAR(80)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="83" parent="9" name="Name">
+ <DataType>VARCHAR(80)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="84" parent="9" name="Description">
+ <DataType>VARCHAR(80)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="85" parent="9" name="IconSmall">
+ <DataType>BLOB|0s</DataType>
+ <Position>5</Position>
+ </column>
+ <column id="86" parent="9" name="IconOn">
+ <DataType>BLOB|0s</DataType>
+ <Position>6</Position>
+ </column>
+ <column id="87" parent="9" name="IconOff">
+ <DataType>BLOB|0s</DataType>
+ <Position>7</Position>
+ </column>
+ <key id="88" parent="9">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="89" parent="10" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="90" parent="10" name="HardwareID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="91" parent="10" name="DeviceID">
+ <DataType>VARCHAR(25)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="92" parent="10" name="Unit">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="93" parent="10" name="Name">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>Unknown</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="94" parent="10" name="Used">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="95" parent="10" name="Type">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>7</Position>
+ </column>
+ <column id="96" parent="10" name="SubType">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>8</Position>
+ </column>
+ <column id="97" parent="10" name="SwitchType">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <column id="98" parent="10" name="Favorite">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <column id="99" parent="10" name="SignalLevel">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>11</Position>
+ </column>
+ <column id="100" parent="10" name="BatteryLevel">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>12</Position>
+ </column>
+ <column id="101" parent="10" name="nValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>13</Position>
+ </column>
+ <column id="102" parent="10" name="sValue">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>null</DefaultExpression>
+ <Position>14</Position>
+ </column>
+ <column id="103" parent="10" name="LastUpdate">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>15</Position>
+ </column>
+ <column id="104" parent="10" name="Order">
+ <DataType>INTEGER BIGINT(10)|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>16</Position>
+ </column>
+ <column id="105" parent="10" name="AddjValue">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>17</Position>
+ </column>
+ <column id="106" parent="10" name="AddjMulti">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>18</Position>
+ </column>
+ <column id="107" parent="10" name="AddjValue2">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>19</Position>
+ </column>
+ <column id="108" parent="10" name="AddjMulti2">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>20</Position>
+ </column>
+ <column id="109" parent="10" name="StrParam1">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>21</Position>
+ </column>
+ <column id="110" parent="10" name="StrParam2">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>22</Position>
+ </column>
+ <column id="111" parent="10" name="LastLevel">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>23</Position>
+ </column>
+ <column id="112" parent="10" name="Protected">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>24</Position>
+ </column>
+ <column id="113" parent="10" name="CustomImage">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>25</Position>
+ </column>
+ <column id="114" parent="10" name="Description">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>26</Position>
+ </column>
+ <column id="115" parent="10" name="Options">
+ <DataType>TEXT|0s</DataType>
+ <DefaultExpression>null</DefaultExpression>
+ <Position>27</Position>
+ </column>
+ <column id="116" parent="10" name="Color">
+ <DataType>TEXT|0s</DataType>
+ <DefaultExpression>NULL</DefaultExpression>
+ <Position>28</Position>
+ </column>
+ <index id="117" parent="10" name="ds_hduts_idx">
+ <ColNames>HardwareID
+DeviceID
+Unit
+Type
+SubType</ColNames>
+ </index>
+ <key id="118" parent="10">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <trigger id="119" parent="10" name="devicestatusupdate">
+ <Events>I</Events>
+ <SourceTextLength>181</SourceTextLength>
+ <Turn>after-row</Turn>
+ </trigger>
+ <column id="120" parent="11" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="121" parent="11" name="DeviceRowID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="122" parent="11" name="DevSceneType">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="123" parent="11" name="PlanID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="124" parent="11" name="Order">
+ <DataType>INTEGER BIGINT(10)|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="125" parent="11" name="XOffset">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="126" parent="11" name="YOffset">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <key id="127" parent="11">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <trigger id="128" parent="11" name="deviceplantatusupdate">
+ <Events>I</Events>
+ <SourceTextLength>200</SourceTextLength>
+ <Turn>after-row</Turn>
+ </trigger>
+ <column id="129" parent="12" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="130" parent="12" name="HardwareID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="131" parent="12" name="DeviceID">
+ <DataType>VARCHAR(25)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="132" parent="12" name="Manufacturer">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="133" parent="12" name="Profile">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="134" parent="12" name="Type">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>6</Position>
+ </column>
+ <key id="135" parent="12">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="136" parent="13" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="137" parent="13" name="Name">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="138" parent="13" name="Interpreter">
+ <DataType>VARCHAR(10)|0s</DataType>
+ <DefaultExpression>'Blockly'</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="139" parent="13" name="Type">
+ <DataType>VARCHAR(10)|0s</DataType>
+ <DefaultExpression>'All'</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="140" parent="13" name="XMLStatement">
+ <DataType>TEXT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="141" parent="13" name="Status">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <key id="142" parent="13">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="143" parent="14" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="144" parent="14" name="EMID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>2</Position>
+ </column>
+ <column id="145" parent="14" name="Conditions">
+ <DataType>TEXT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="146" parent="14" name="Actions">
+ <DataType>TEXT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="147" parent="14" name="SequenceNo">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <foreign-key id="148" parent="14">
+ <ColNames>EMID</ColNames>
+ <RefColNames>ID</RefColNames>
+ <RefTableName>EventMaster</RefTableName>
+ </foreign-key>
+ <key id="149" parent="14">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="150" parent="15" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="151" parent="15" name="Speed">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="152" parent="15" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <index id="153" parent="15" name="f_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="154" parent="15" name="f_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="155" parent="16" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="156" parent="16" name="Speed_Min">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="157" parent="16" name="Speed_Max">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="158" parent="16" name="Speed_Avg">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="159" parent="16" name="Date">
+ <DataType>DATE|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <index id="160" parent="16" name="fc_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="161" parent="16" name="fc_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="162" parent="17" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="163" parent="17" name="DeviceID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="164" parent="17" name="DelimitedValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="165" parent="17" name="TargetType">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="166" parent="17" name="TargetVariable">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>5</Position>
+ </column>
+ <column id="167" parent="17" name="TargetDeviceID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>6</Position>
+ </column>
+ <column id="168" parent="17" name="TargetProperty">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>7</Position>
+ </column>
+ <column id="169" parent="17" name="Enabled">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="170" parent="17" name="IncludeUnit">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <key id="171" parent="17">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="172" parent="18" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="173" parent="18" name="Name">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="174" parent="18" name="Image">
+ <DataType>BLOB|0s</DataType>
+ <Position>3</Position>
+ </column>
+ <column id="175" parent="18" name="ScaleFactor">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>1.0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="176" parent="18" name="Order">
+ <DataType>INTEGER BIGINT(10)|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <key id="177" parent="18">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <trigger id="178" parent="18" name="floorplanordertrigger">
+ <Events>I</Events>
+ <SourceTextLength>176</SourceTextLength>
+ <Turn>after-row</Turn>
+ </trigger>
+ <column id="179" parent="19" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="180" parent="19" name="DeviceID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="181" parent="19" name="DelimitedValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="182" parent="19" name="TargetType">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="183" parent="19" name="TargetVariable">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>5</Position>
+ </column>
+ <column id="184" parent="19" name="TargetDeviceID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>6</Position>
+ </column>
+ <column id="185" parent="19" name="TargetProperty">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>7</Position>
+ </column>
+ <column id="186" parent="19" name="Enabled">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="187" parent="19" name="IncludeUnit">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <key id="188" parent="19">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="189" parent="20" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="190" parent="20" name="Name">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="191" parent="20" name="Enabled">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="192" parent="20" name="Type">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="193" parent="20" name="Address">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <Position>5</Position>
+ </column>
+ <column id="194" parent="20" name="Port">
+ <DataType>INTEGER|0s</DataType>
+ <Position>6</Position>
+ </column>
+ <column id="195" parent="20" name="SerialPort">
+ <DataType>TEXT|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="196" parent="20" name="Username">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>8</Position>
+ </column>
+ <column id="197" parent="20" name="Password">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>9</Position>
+ </column>
+ <column id="198" parent="20" name="Extra">
+ <DataType>TEXT|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <column id="199" parent="20" name="Mode1">
+ <DataType>CHAR|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>11</Position>
+ </column>
+ <column id="200" parent="20" name="Mode2">
+ <DataType>CHAR|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>12</Position>
+ </column>
+ <column id="201" parent="20" name="Mode3">
+ <DataType>CHAR|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>13</Position>
+ </column>
+ <column id="202" parent="20" name="Mode4">
+ <DataType>CHAR|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>14</Position>
+ </column>
+ <column id="203" parent="20" name="Mode5">
+ <DataType>CHAR|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>15</Position>
+ </column>
+ <column id="204" parent="20" name="Mode6">
+ <DataType>CHAR|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>16</Position>
+ </column>
+ <column id="205" parent="20" name="DataTimeout">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>17</Position>
+ </column>
+ <column id="206" parent="20" name="Configuration">
+ <DataType>TEXT|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>18</Position>
+ </column>
+ <key id="207" parent="20">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="208" parent="21" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="209" parent="21" name="DeviceID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="210" parent="21" name="DelimitedValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="211" parent="21" name="TargetType">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="212" parent="21" name="TargetVariable">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>5</Position>
+ </column>
+ <column id="213" parent="21" name="TargetDeviceID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>6</Position>
+ </column>
+ <column id="214" parent="21" name="TargetProperty">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>7</Position>
+ </column>
+ <column id="215" parent="21" name="Enabled">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="216" parent="21" name="IncludeUnit">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <key id="217" parent="21">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="218" parent="22" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="219" parent="22" name="DeviceRowID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="220" parent="22" name="ParentID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <key id="221" parent="22">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="222" parent="23" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="223" parent="23" name="nValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="224" parent="23" name="sValue">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <Position>3</Position>
+ </column>
+ <column id="225" parent="23" name="User">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="226" parent="23" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <index id="227" parent="23" name="ll_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="228" parent="23" name="ll_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="229" parent="24" name="DeviceRowID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="230" parent="24" name="Value">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="231" parent="24" name="Usage">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="232" parent="24" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <index id="233" parent="24" name="m_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="234" parent="24" name="m_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="235" parent="25" name="DeviceRowID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="236" parent="25" name="Value">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="237" parent="25" name="Counter">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="238" parent="25" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <index id="239" parent="25" name="mc_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="240" parent="25" name="mc_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="241" parent="26" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="242" parent="26" name="Active">
+ <DataType>BOOLEAN|0s</DataType>
+ <DefaultExpression>false</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="243" parent="26" name="Name">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="244" parent="26" name="DeviceType">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="245" parent="26" name="SenderID">
+ <DataType>TEXT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="246" parent="26" name="UUID">
+ <DataType>TEXT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>6</Position>
+ </column>
+ <column id="247" parent="26" name="LastUpdate">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now', 'localtime')</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <key id="248" parent="26">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="249" parent="27" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="250" parent="27" name="Value1">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="251" parent="27" name="Value2">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="252" parent="27" name="Value3">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="253" parent="27" name="Value4">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="254" parent="27" name="Value5">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="255" parent="27" name="Value6">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="256" parent="27" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <index id="257" parent="27" name="mm_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="258" parent="27" name="mm_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="259" parent="28" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="260" parent="28" name="Value1">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="261" parent="28" name="Value2">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="262" parent="28" name="Value3">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="263" parent="28" name="Value4">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="264" parent="28" name="Value5">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>6</Position>
+ </column>
+ <column id="265" parent="28" name="Value6">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>7</Position>
+ </column>
+ <column id="266" parent="28" name="Counter1">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="267" parent="28" name="Counter2">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <column id="268" parent="28" name="Counter3">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <column id="269" parent="28" name="Counter4">
+ <DataType>BIGINT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>11</Position>
+ </column>
+ <column id="270" parent="28" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>12</Position>
+ </column>
+ <index id="271" parent="28" name="mmc_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="272" parent="28" name="mmc_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="273" parent="29" name="HardwareID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="274" parent="29" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="275" parent="29" name="Name">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>Unknown</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="276" parent="29" name="SketchName">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>Unknown</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="277" parent="29" name="SketchVersion">
+ <DataType>VARCHAR(40)|0s</DataType>
+ <DefaultExpression>1.0</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="278" parent="30" name="HardwareID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="279" parent="30" name="NodeID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="280" parent="30" name="ChildID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="281" parent="30" name="Name">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="282" parent="30" name="Type">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="283" parent="30" name="UseAck">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="284" parent="30" name="AckTimeout">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>1200</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="285" parent="31" name="HardwareID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="286" parent="31" name="NodeID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="287" parent="31" name="ChildID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="288" parent="31" name="VarID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="289" parent="31" name="Value">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="290" parent="32" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="291" parent="32" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="292" parent="32" name="Params">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>3</Position>
+ </column>
+ <column id="293" parent="32" name="CustomMessage">
+ <DataType>VARCHAR(300)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="294" parent="32" name="ActiveSystems">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="295" parent="32" name="Priority">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="296" parent="32" name="SendAlways">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="297" parent="32" name="LastSend">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <key id="298" parent="32">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="299" parent="33" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="300" parent="33" name="Percentage">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="301" parent="33" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <index id="302" parent="33" name="p_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="303" parent="33" name="p_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="304" parent="34" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="305" parent="34" name="Percentage_Min">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="306" parent="34" name="Percentage_Max">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="307" parent="34" name="Percentage_Avg">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="308" parent="34" name="Date">
+ <DataType>DATE|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <index id="309" parent="34" name="pc_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="310" parent="34" name="pc_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="311" parent="35" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="312" parent="35" name="Order">
+ <DataType>INTEGER BIGINT(10)|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="313" parent="35" name="Name">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="314" parent="35" name="FloorplanID">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="315" parent="35" name="Area">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <key id="316" parent="35">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <trigger id="317" parent="35" name="planordertrigger">
+ <Events>I</Events>
+ <SourceTextLength>151</SourceTextLength>
+ <Turn>after-row</Turn>
+ </trigger>
+ <column id="318" parent="36" name="Key">
+ <DataType>VARCHAR(50)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="319" parent="36" name="nValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="320" parent="36" name="sValue">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <Position>3</Position>
+ </column>
+ <column id="321" parent="37" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="322" parent="37" name="PushType">
+ <DataType>INTEGER|0s</DataType>
+ <Position>2</Position>
+ </column>
+ <column id="323" parent="37" name="DeviceID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="324" parent="37" name="DelimitedValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="325" parent="37" name="TargetType">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="326" parent="37" name="TargetVariable">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>6</Position>
+ </column>
+ <column id="327" parent="37" name="TargetDeviceID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>7</Position>
+ </column>
+ <column id="328" parent="37" name="TargetProperty">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <Position>8</Position>
+ </column>
+ <column id="329" parent="37" name="Enabled">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <column id="330" parent="37" name="IncludeUnit">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <key id="331" parent="37">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="332" parent="38" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="333" parent="38" name="Total">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="334" parent="38" name="Rate">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="335" parent="38" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <index id="336" parent="38" name="r_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="337" parent="38" name="r_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="338" parent="39" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="339" parent="39" name="Total">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="340" parent="39" name="Rate">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="341" parent="39" name="Date">
+ <DataType>DATE|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <index id="342" parent="39" name="rc_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="343" parent="39" name="rc_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="344" parent="40" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="345" parent="40" name="Order">
+ <DataType>INTEGER BIGINT(10)|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="346" parent="40" name="SceneRowID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="347" parent="40" name="DeviceRowID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="348" parent="40" name="Cmd">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>1</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="349" parent="40" name="Level">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>100</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="350" parent="40" name="Color">
+ <DataType>TEXT|0s</DataType>
+ <DefaultExpression>NULL</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="351" parent="40" name="OnDelay">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="352" parent="40" name="OffDelay">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <key id="353" parent="40">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <trigger id="354" parent="40" name="scenedevicesupdate">
+ <Events>I</Events>
+ <SourceTextLength>181</SourceTextLength>
+ <Turn>after-row</Turn>
+ </trigger>
+ <column id="355" parent="41" name="SceneRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="356" parent="41" name="nValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="357" parent="41" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <index id="358" parent="41" name="sl_id_date_idx">
+ <ColNames>SceneRowID
+Date</ColNames>
+ </index>
+ <index id="359" parent="41" name="sl_id_idx">
+ <ColNames>SceneRowID</ColNames>
+ </index>
+ <column id="360" parent="42" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="361" parent="42" name="Active">
+ <DataType>BOOLEAN|0s</DataType>
+ <DefaultExpression>true</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="362" parent="42" name="SceneRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="363" parent="42" name="Date">
+ <DataType>DATE|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="364" parent="42" name="Time">
+ <DataType>TIME|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="365" parent="42" name="Type">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>6</Position>
+ </column>
+ <column id="366" parent="42" name="Cmd">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>7</Position>
+ </column>
+ <column id="367" parent="42" name="Level">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>15</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="368" parent="42" name="UseRandomness">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <column id="369" parent="42" name="TimerPlan">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <column id="370" parent="42" name="Days">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>11</Position>
+ </column>
+ <column id="371" parent="42" name="Month">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>12</Position>
+ </column>
+ <column id="372" parent="42" name="MDay">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>13</Position>
+ </column>
+ <column id="373" parent="42" name="Occurence">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>14</Position>
+ </column>
+ <key id="374" parent="42">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="375" parent="43" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="376" parent="43" name="Name">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="377" parent="43" name="Favorite">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="378" parent="43" name="Order">
+ <DataType>INTEGER BIGINT(10)|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="379" parent="43" name="nValue">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="380" parent="43" name="SceneType">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="381" parent="43" name="Protected">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="382" parent="43" name="OnAction">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="383" parent="43" name="OffAction">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <column id="384" parent="43" name="Description">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <column id="385" parent="43" name="Activators">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <DefaultExpression>''</DefaultExpression>
+ <Position>11</Position>
+ </column>
+ <column id="386" parent="43" name="LastUpdate">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>12</Position>
+ </column>
+ <key id="387" parent="43">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <trigger id="388" parent="43" name="scenesupdate">
+ <Events>I</Events>
+ <SourceTextLength>151</SourceTextLength>
+ <Turn>after-row</Turn>
+ </trigger>
+ <column id="389" parent="44" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="390" parent="44" name="Active">
+ <DataType>BOOLEAN|0s</DataType>
+ <DefaultExpression>true</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="391" parent="44" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="392" parent="44" name="Date">
+ <DataType>DATE|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="393" parent="44" name="Time">
+ <DataType>TIME|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="394" parent="44" name="Type">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>6</Position>
+ </column>
+ <column id="395" parent="44" name="Temperature">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="396" parent="44" name="TimerPlan">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="397" parent="44" name="Days">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>9</Position>
+ </column>
+ <column id="398" parent="44" name="Month">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <column id="399" parent="44" name="MDay">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>11</Position>
+ </column>
+ <column id="400" parent="44" name="Occurence">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>12</Position>
+ </column>
+ <key id="401" parent="44">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="402" parent="45" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="403" parent="45" name="SharedUserID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="404" parent="45" name="DeviceRowID">
+ <DataType>BIGINT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <key id="405" parent="45">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="406" parent="46" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="407" parent="46" name="Temperature">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="408" parent="46" name="Chill">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="409" parent="46" name="Humidity">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="410" parent="46" name="Barometer">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="411" parent="46" name="DewPoint">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="412" parent="46" name="SetPoint">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="413" parent="46" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <index id="414" parent="46" name="t_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="415" parent="46" name="t_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="416" parent="47" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="417" parent="47" name="Temp_Min">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="418" parent="47" name="Temp_Max">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="419" parent="47" name="Temp_Avg">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="420" parent="47" name="Chill_Min">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="421" parent="47" name="Chill_Max">
+ <DataType>FLOAT|0s</DataType>
+ <Position>6</Position>
+ </column>
+ <column id="422" parent="47" name="Humidity">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <column id="423" parent="47" name="Barometer">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="424" parent="47" name="DewPoint">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <column id="425" parent="47" name="SetPoint_Min">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <column id="426" parent="47" name="SetPoint_Max">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>11</Position>
+ </column>
+ <column id="427" parent="47" name="SetPoint_Avg">
+ <DataType>FLOAT|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>12</Position>
+ </column>
+ <column id="428" parent="47" name="Date">
+ <DataType>DATE|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>13</Position>
+ </column>
+ <index id="429" parent="47" name="tc_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="430" parent="47" name="tc_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="431" parent="48" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="432" parent="48" name="Name">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <key id="433" parent="48">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="434" parent="49" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="435" parent="49" name="Active">
+ <DataType>BOOLEAN|0s</DataType>
+ <DefaultExpression>true</DefaultExpression>
+ <Position>2</Position>
+ </column>
+ <column id="436" parent="49" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="437" parent="49" name="Date">
+ <DataType>DATE|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="438" parent="49" name="Time">
+ <DataType>TIME|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="439" parent="49" name="Type">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>6</Position>
+ </column>
+ <column id="440" parent="49" name="Cmd">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>7</Position>
+ </column>
+ <column id="441" parent="49" name="Level">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>15</DefaultExpression>
+ <Position>8</Position>
+ </column>
+ <column id="442" parent="49" name="Color">
+ <DataType>TEXT|0s</DataType>
+ <DefaultExpression>NULL</DefaultExpression>
+ <Position>9</Position>
+ </column>
+ <column id="443" parent="49" name="UseRandomness">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>10</Position>
+ </column>
+ <column id="444" parent="49" name="TimerPlan">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>11</Position>
+ </column>
+ <column id="445" parent="49" name="Days">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>12</Position>
+ </column>
+ <column id="446" parent="49" name="Month">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>13</Position>
+ </column>
+ <column id="447" parent="49" name="MDay">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>14</Position>
+ </column>
+ <column id="448" parent="49" name="Occurence">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>15</Position>
+ </column>
+ <key id="449" parent="49">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="450" parent="50" name="HardwareID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="451" parent="50" name="UUID">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="452" parent="51" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="453" parent="51" name="Level">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="454" parent="51" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <index id="455" parent="51" name="u_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="456" parent="51" name="u_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="457" parent="52" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="458" parent="52" name="Level">
+ <DataType>FLOAT|0s</DataType>
+ <Position>2</Position>
+ </column>
+ <column id="459" parent="52" name="Date">
+ <DataType>DATE|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <index id="460" parent="52" name="uv_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="461" parent="52" name="uv_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="462" parent="53" name="SessionID">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="463" parent="53" name="Username">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="464" parent="53" name="AuthToken">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="465" parent="53" name="ExpirationDate">
+ <DataType>DATETIME|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="466" parent="53" name="RemoteHost">
+ <DataType>VARCHAR(50)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="467" parent="53" name="LastUpdate">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now', 'localtime')</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <index id="468" parent="53" name="sqlite_autoindex_UserSessions_2">
+ <ColNames>SessionID</ColNames>
+ <NameSurrogate>1</NameSurrogate>
+ <Unique>1</Unique>
+ </index>
+ <index id="469" parent="53" name="sqlite_autoindex_UserSessions_1">
+ <ColNames>AuthToken</ColNames>
+ <NameSurrogate>1</NameSurrogate>
+ <Unique>1</Unique>
+ </index>
+ <key id="470" parent="53">
+ <ColNames>SessionID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexName>sqlite_autoindex_UserSessions_2</UnderlyingIndexName>
+ </key>
+ <key id="471" parent="53">
+ <ColNames>AuthToken</ColNames>
+ <UnderlyingIndexName>sqlite_autoindex_UserSessions_1</UnderlyingIndexName>
+ </key>
+ <column id="472" parent="54" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="473" parent="54" name="Name">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <Position>2</Position>
+ </column>
+ <column id="474" parent="54" name="ValueType">
+ <DataType>INT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="475" parent="54" name="Value">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <Position>4</Position>
+ </column>
+ <column id="476" parent="54" name="LastUpdate">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now', 'localtime')</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <key id="477" parent="54">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="478" parent="55" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="479" parent="55" name="Active">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="480" parent="55" name="Username">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="481" parent="55" name="Password">
+ <DataType>VARCHAR(200)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="482" parent="55" name="Rights">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>255</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="483" parent="55" name="TabsEnabled">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>255</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="484" parent="55" name="RemoteSharing">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <key id="485" parent="55">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="486" parent="56" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="487" parent="56" name="HardwareID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="488" parent="56" name="Name">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>Unknown</DefaultExpression>
+ <Position>3</Position>
+ </column>
+ <column id="489" parent="56" name="MacAddress">
+ <DataType>VARCHAR(50)|0s</DataType>
+ <DefaultExpression>Unknown</DefaultExpression>
+ <Position>4</Position>
+ </column>
+ <column id="490" parent="56" name="Timeout">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>5</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <key id="491" parent="56">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="492" parent="57" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="493" parent="57" name="Direction">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="494" parent="57" name="Speed">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="495" parent="57" name="Gust">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="496" parent="57" name="Date">
+ <DataType>DATETIME|0s</DataType>
+ <DefaultExpression>datetime('now','localtime')</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <index id="497" parent="57" name="w_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="498" parent="57" name="w_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="499" parent="58" name="DeviceRowID">
+ <DataType>BIGINT(10)|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>1</Position>
+ </column>
+ <column id="500" parent="58" name="Direction">
+ <DataType>FLOAT|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="501" parent="58" name="Speed_Min">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="502" parent="58" name="Speed_Max">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="503" parent="58" name="Gust_Min">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>5</Position>
+ </column>
+ <column id="504" parent="58" name="Gust_Max">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>6</Position>
+ </column>
+ <column id="505" parent="58" name="Date">
+ <DataType>DATE|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>7</Position>
+ </column>
+ <index id="506" parent="58" name="wc_id_date_idx">
+ <ColNames>DeviceRowID
+Date</ColNames>
+ </index>
+ <index id="507" parent="58" name="wc_id_idx">
+ <ColNames>DeviceRowID</ColNames>
+ </index>
+ <column id="508" parent="59" name="ID">
+ <DataType>INTEGER|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="509" parent="59" name="HardwareID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>2</Position>
+ </column>
+ <column id="510" parent="59" name="HomeID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>3</Position>
+ </column>
+ <column id="511" parent="59" name="NodeID">
+ <DataType>INTEGER|0s</DataType>
+ <NotNull>1</NotNull>
+ <Position>4</Position>
+ </column>
+ <column id="512" parent="59" name="Name">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>Unknown</DefaultExpression>
+ <Position>5</Position>
+ </column>
+ <column id="513" parent="59" name="ProductDescription">
+ <DataType>VARCHAR(100)|0s</DataType>
+ <DefaultExpression>Unknown</DefaultExpression>
+ <Position>6</Position>
+ </column>
+ <column id="514" parent="59" name="PollTime">
+ <DataType>INTEGER|0s</DataType>
+ <DefaultExpression>0</DefaultExpression>
+ <Position>7</Position>
+ </column>
+ <key id="515" parent="59">
+ <ColNames>ID</ColNames>
+ <Primary>1</Primary>
+ <UnderlyingIndexColNames>ID</UnderlyingIndexColNames>
+ </key>
+ <column id="516" parent="60" name="type">
+ <DataType>text|0s</DataType>
+ <Position>1</Position>
+ </column>
+ <column id="517" parent="60" name="name">
+ <DataType>text|0s</DataType>
+ <Position>2</Position>
+ </column>
+ <column id="518" parent="60" name="tbl_name">
+ <DataType>text|0s</DataType>
+ <Position>3</Position>
+ </column>
+ <column id="519" parent="60" name="rootpage">
+ <DataType>int|0s</DataType>
+ <Position>4</Position>
+ </column>
+ <column id="520" parent="60" name="sql">
+ <DataType>text|0s</DataType>
+ <Position>5</Position>
+ </column>
+ <column id="521" parent="61" name="tbl">
+ <Position>1</Position>
+ </column>
+ <column id="522" parent="61" name="idx">
+ <Position>2</Position>
+ </column>
+ <column id="523" parent="61" name="stat">
+ <Position>3</Position>
+ </column>
+ </database-model>
+</dataSource>
\ No newline at end of file
--- /dev/null
+øe
\ No newline at end of file
--- /dev/null
+#n:main
\ No newline at end of file
--- /dev/null
+øe
\ No newline at end of file
--- /dev/null
+#n:main
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
- <component name="PublishConfigData" autoUpload="On explicit save action" serverName="home.tortuga.enhydra.fr" autoUploadExternalChanges="true" showAutoUploadSettingsWarning="false">
+ <component name="PublishConfigData" autoUpload="On explicit save action" serverName="home.tortuga.enhydra.fr" confirmBeforeUploading="false" autoUploadExternalChanges="true" showAutoUploadSettingsWarning="false">
+ <option name="confirmBeforeUploading" value="false" />
<serverData>
<paths name="dev-redbr.enhydra.fr">
<serverdata>
<mapping deploy="/" local="$PROJECT_DIR$" web="/" />
</mappings>
<excludedPaths>
- <excludedPath local="true" path="vendor" />
+ <excludedPath local="true" path="$PROJECT_DIR$/vendor" />
</excludedPaths>
</serverdata>
</paths>
</mappings>
</serverdata>
</paths>
+ <paths name="songbook.enhydra.fr">
+ <serverdata>
+ <mappings>
+ <mapping local="$PROJECT_DIR$" web="/" />
+ </mappings>
+ </serverdata>
+ </paths>
</serverData>
<option name="myAutoUpload" value="ON_EXPLICIT_SAVE" />
</component>
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android API 30 Platform" project-jdk-type="Android SDK" />
- <component name="SwUserDefinedSpecifications">
- <option name="specTypeByUrl">
- <map />
- </option>
- </component>
</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="SqlDialectMappings">
+ <file url="file://$PROJECT_DIR$/scripts/lib/kodi.php" dialect="GenericSQL" />
+ <file url="PROJECT" dialect="MySQL" />
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectTasksOptions">
+ <TaskOptions isEnabled="true">
+ <option name="arguments" value="--no-color $FileName$" />
+ <option name="checkSyntaxErrors" value="true" />
+ <option name="description" />
+ <option name="exitCodeBehavior" value="ERROR" />
+ <option name="fileExtension" value="less" />
+ <option name="immediateSync" value="true" />
+ <option name="name" value="Less" />
+ <option name="output" value="$FileNameWithoutExtension$.css" />
+ <option name="outputFilters">
+ <array>
+ <FilterInfo>
+ <option name="description" value="" />
+ <option name="name" value="" />
+ <option name="regExp" value="$MESSAGE$\Q in \E$FILE_PATH$\Q on line \E$LINE$\Q, column \E$COLUMN$" />
+ </FilterInfo>
+ </array>
+ </option>
+ <option name="outputFromStdout" value="true" />
+ <option name="program" value="$USER_HOME$/AppData/Roaming/npm/lessc.cmd" />
+ <option name="runOnExternalChanges" value="true" />
+ <option name="scopeName" value="Project Files" />
+ <option name="trackOnlyRoot" value="true" />
+ <option name="workingDir" value="$FileDir$" />
+ <envs />
+ </TaskOptions>
+ </component>
+</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
- <list default="true" id="352ce63a-b52a-41a2-979b-becda7920939" name="Default" comment=".">
- <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/scripts/lib/ecomode.php" beforeDir="false" afterPath="$PROJECT_DIR$/scripts/lib/ecomode.php" afterDir="false" />
- </list>
+ <list default="true" id="352ce63a-b52a-41a2-979b-becda7920939" name="Default" comment="." />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
</map>
</option>
</component>
- <component name="JsFlowSettings">
- <service-enabled>true</service-enabled>
- <exe-path />
- <other-services-enabled>true</other-services-enabled>
- <auto-save>true</auto-save>
- </component>
<component name="JupyterTrust" id="3f62eec0-7d7b-45be-bd97-06244d65817c" />
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
"WebServerToolWindowPanel.toolwindow.show.date": "false",
"WebServerToolWindowPanel.toolwindow.show.permissions": "false",
"WebServerToolWindowPanel.toolwindow.show.size": "false",
+ "deletionFromPopupRequiresConfirmation": "false",
+ "last_opened_file_path": "C:/Users/vince/Drive/Works/home/.docker/dockerterminal.bat",
"nodejs_package_manager_path": "npm",
+ "project.structure.last.edited": "Project",
+ "project.structure.proportion": "0.0",
+ "project.structure.side.proportion": "0.0",
"ruby.rails.projectView.checked": "true",
+ "settings.editor.selected.configurable": "terminal",
"vue.rearranger.settings.migration": "true"
}
}</component>
<recent name="T:\Drive\Works\home\images" />
</key>
<key name="MoveFile.RECENT_KEYS">
+ <recent name="C:\Users\vince\Drive\Works\home\.docker\config\php" />
+ <recent name="C:\Users\vince\Drive\Works\home\images" />
<recent name="T:\Drive\Works\home\images" />
<recent name="T:\Drive\Works\home\images\rooms" />
<recent name="T:\Drive\Works\home\js\mmenu" />
- <recent name="T:\Drive\Works\home\tools\xplanet" />
- <recent name="T:\Drive\Works\home\style\fonts\webfonts" />
</key>
</component>
- <component name="RunManager">
+ <component name="RunManager" selected="Shell Script.Docker terminal">
<configuration default="true" type="Applet">
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
+ <configuration name="Docker terminal" type="ShConfigurationType">
+ <option name="SCRIPT_TEXT" value="" />
+ <option name="INDEPENDENT_SCRIPT_PATH" value="true" />
+ <option name="SCRIPT_PATH" value="$PROJECT_DIR$/.docker/dockerterminal.bat" />
+ <option name="SCRIPT_OPTIONS" value="" />
+ <option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
+ <option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$/.docker/" />
+ <option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
+ <option name="INTERPRETER_PATH" value="" />
+ <option name="INTERPRETER_OPTIONS" value="" />
+ <option name="EXECUTE_IN_TERMINAL" value="true" />
+ <option name="EXECUTE_SCRIPT_FILE" value="true" />
+ <envs />
+ <method v="2" />
+ </configuration>
+ <configuration name="adb-connect" type="ShConfigurationType" temporary="true">
+ <option name="SCRIPT_TEXT" value="" />
+ <option name="INDEPENDENT_SCRIPT_PATH" value="true" />
+ <option name="SCRIPT_PATH" value="$PROJECT_DIR$/bin/adb-connect" />
+ <option name="SCRIPT_OPTIONS" value="" />
+ <option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
+ <option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$/bin" />
+ <option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
+ <option name="INTERPRETER_PATH" value="" />
+ <option name="INTERPRETER_OPTIONS" value="" />
+ <option name="EXECUTE_IN_TERMINAL" value="true" />
+ <option name="EXECUTE_SCRIPT_FILE" value="true" />
+ <envs />
+ <method v="2" />
+ </configuration>
<configuration default="true" type="TestNG">
<option name="TEST_OBJECT" value="CLASS" />
<option name="VM_PARAMETERS" />
<envs />
<method v="2" />
</configuration>
+ <list>
+ <item itemvalue="Shell Script.Docker terminal" />
+ <item itemvalue="Shell Script.adb-connect" />
+ </list>
+ <recent_temporary>
+ <list>
+ <item itemvalue="Shell Script.adb-connect" />
+ </list>
+ </recent_temporary>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="SvnConfiguration">
<workItem from="1649833630727" duration="738000" />
<workItem from="1649835938314" duration="1458000" />
<workItem from="1649877396831" duration="7495000" />
- <workItem from="1650019142255" duration="346000" />
- </task>
- <task id="LOCAL-00477" summary=".">
- <created>1619798145186</created>
- <option name="number" value="00477" />
- <option name="presentableId" value="LOCAL-00477" />
- <option name="project" value="LOCAL" />
- <updated>1619798145186</updated>
+ <workItem from="1650019142255" duration="406000" />
+ <workItem from="1650020991518" duration="191000" />
+ <workItem from="1650022285687" duration="1210000" />
+ <workItem from="1650122983742" duration="77000" />
+ <workItem from="1651101686768" duration="3835000" />
+ <workItem from="1652689035546" duration="112000" />
+ <workItem from="1653131999125" duration="7579000" />
+ <workItem from="1653221086901" duration="7848000" />
+ <workItem from="1653295650996" duration="1758000" />
+ <workItem from="1653410840689" duration="11000" />
+ <workItem from="1653482413285" duration="1162000" />
+ <workItem from="1653487974788" duration="6289000" />
+ <workItem from="1653731363124" duration="1269000" />
+ <workItem from="1653828690573" duration="2603000" />
+ <workItem from="1653944862561" duration="3688000" />
+ <workItem from="1654015956523" duration="534000" />
+ <workItem from="1654016528165" duration="45000" />
+ <workItem from="1654066163233" duration="2418000" />
+ <workItem from="1654072109236" duration="2315000" />
+ <workItem from="1654150156491" duration="3843000" />
+ <workItem from="1654540144631" duration="1456000" />
+ <workItem from="1654632661922" duration="3772000" />
+ <workItem from="1654866191211" duration="3574000" />
+ <workItem from="1654942859604" duration="1208000" />
+ <workItem from="1654967340155" duration="1233000" />
+ <workItem from="1655023978491" duration="4051000" />
+ <workItem from="1655622417279" duration="6642000" />
+ <workItem from="1656144764864" duration="368000" />
+ <workItem from="1656665258733" duration="3879000" />
+ <workItem from="1657006964661" duration="3676000" />
+ <workItem from="1657176254685" duration="3187000" />
+ <workItem from="1657872723181" duration="2096000" />
+ <workItem from="1658566813950" duration="45000" />
+ <workItem from="1659896018944" duration="565000" />
+ <workItem from="1660245454198" duration="6800000" />
+ <workItem from="1660762947848" duration="7189000" />
+ <workItem from="1661099387668" duration="529000" />
+ <workItem from="1661156985917" duration="1439000" />
+ <workItem from="1661611710710" duration="2114000" />
+ <workItem from="1661758537494" duration="1879000" />
+ <workItem from="1661850823289" duration="1209000" />
+ <workItem from="1662046325001" duration="704000" />
+ <workItem from="1663766008034" duration="50000" />
+ <workItem from="1663835882828" duration="107000" />
+ <workItem from="1663836114512" duration="20000" />
+ <workItem from="1664097860042" duration="14849000" />
+ <workItem from="1664730523704" duration="1895000" />
+ <workItem from="1664791402037" duration="1351000" />
+ <workItem from="1664987779048" duration="543000" />
+ <workItem from="1664988360545" duration="634000" />
+ <workItem from="1665630775990" duration="1219000" />
</task>
<task id="LOCAL-00478" summary=".">
<created>1619802642365</created>
<option name="project" value="LOCAL" />
<updated>1650019206915</updated>
</task>
- <option name="localTasksCounter" value="526" />
+ <task id="LOCAL-00526" summary=".">
+ <created>1650019587439</created>
+ <option name="number" value="00526" />
+ <option name="presentableId" value="LOCAL-00526" />
+ <option name="project" value="LOCAL" />
+ <updated>1650019587440</updated>
+ </task>
+ <option name="localTasksCounter" value="527" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 86 86" style="enable-background:new 0 0 86 86;" xml:space="preserve">
+<path d="M25.12,20.25c-1.43,0.01-2.88,0.2-4.32,0.59L8.2,24.21c-0.97,0.26-1.6,1.15-1.53,2.15c0.07,1,0.82,1.79,1.82,1.91l5.96,0.71
+ c2.5,0.3,4.92,0.95,7.24,1.88c-0.02,0.02-0.03,0.03-0.05,0.04c-5.81,6-9.61,13.47-11.07,21.54l-2.45,0.49
+ c-2.21,0.44-3.81,2.39-3.81,4.64s1.6,4.2,3.8,4.64l1.77,0.35v3.21c0,5.81,4.73,10.53,10.53,10.53h4.02l0.31,1.53
+ c0.44,2.2,2.39,3.8,4.64,3.8s4.2-1.6,4.64-3.8l0.47-2.36c7.76-1.56,14.92-5.29,20.73-10.89c0.86,2.23,1.47,4.54,1.75,6.92l0.71,5.96
+ c0.12,1,0.91,1.75,1.91,1.82c0.05,0,0.1,0.01,0.15,0.01c0.94,0,1.75-0.61,2-1.54l3.37-12.59c1.51-5.64,0.04-11.48-3.75-15.7
+ c-0.02-0.7-0.07-1.39-0.17-2.09c-0.17-1.26-0.45-2.48-0.8-3.68c-0.01-0.03,0-0.06-0.01-0.09c-0.01-0.03-0.03-0.05-0.04-0.08
+ C60,42.29,59.54,41.1,59,39.96l2.05-3.42c1.08-1.8,1.65-3.86,1.65-5.96V26.9c0-2.01-1.63-3.64-3.64-3.64h-3.7
+ c-2.08,0-4.13,0.56-5.92,1.63l-3.58,2.13c-2.21-0.99-4.58-1.7-7.06-2.04c-0.69-0.09-1.37-0.15-2.06-0.17
+ C33.57,21.84,29.42,20.22,25.12,20.25z M24.56,22.41c3.2-0.14,6.34,0.76,8.96,2.55c-3.66,0.47-7.17,1.95-10.07,4.29
+ c-2.79-1.22-5.72-2.04-8.75-2.4l-5.57-0.66l12.22-3.28C22.42,22.62,23.49,22.46,24.56,22.41z M55.36,25.26h3.7
+ c0.91,0,1.64,0.74,1.64,1.64v3.68c0,1.73-0.47,3.44-1.37,4.93l-1.42,2.37c-2.37-4.09-5.8-7.48-9.93-9.79l2.48-1.48
+ C51.95,25.72,53.64,25.26,55.36,25.26z M36.09,26.79c0.81,0,1.63,0.06,2.44,0.17c9.17,1.26,16.7,7.68,19.61,16.23l-11.5,3.16
+ c-0.09-0.13-0.2-0.26-0.31-0.37l-6.35-6.35c-0.14-0.14-0.3-0.26-0.47-0.38l1.11-4.05c0.15-0.53-0.17-1.08-0.7-1.23
+ c-0.53-0.15-1.08,0.17-1.23,0.7l-1.13,4.09c-0.2,0.02-0.4,0.05-0.59,0.11l-8.66,2.65c-0.14,0.04-0.27,0.11-0.4,0.18l-7-6.99
+ c0.69-0.83,1.4-1.64,2.15-2.42C26.51,28.76,31.23,26.79,36.09,26.79z M19.7,36.3l6.82,6.82c-0.06,0.13-0.13,0.26-0.18,0.4
+ l-2.65,8.66c-0.05,0.16-0.08,0.33-0.1,0.49l-11.48,3.15C12.84,48.72,15.45,42.02,19.7,36.3z M58.71,45.1
+ c0.21,0.84,0.39,1.69,0.51,2.56c0.78,5.67-1.21,11.44-5.32,15.43c-0.78,0.76-1.6,1.48-2.43,2.16l-7.22-7.22
+ c0.06-0.13,0.14-0.26,0.18-0.4l2.65-8.66c0.07-0.23,0.11-0.47,0.12-0.71L58.71,45.1z M61.2,52.77c2.22,3.44,2.95,7.7,1.85,11.84
+ l-3.26,12.38l-0.68-5.73c-0.35-2.91-1.13-5.72-2.27-8.41C59.21,59.95,60.71,56.45,61.2,52.77z M24.01,54.63
+ c0.12,0.2,0.26,0.38,0.43,0.55l6.35,6.35c0.14,0.14,0.29,0.27,0.45,0.37l-3.4,12.38c-0.54,0.02-1.07,0.04-1.61,0.04h-5.8v0
+ c-4.7,0-8.53-3.83-8.53-8.53v-5.83c0-0.67,0.02-1.34,0.05-2.01L24.01,54.63z M10.23,54.7c-0.1,0.76-0.17,1.53-0.23,2.3
+ c-0.01,0.03,0,0.06-0.01,0.09c-0.06,0.95-0.11,1.9-0.11,2.86v0.43l-1.35-0.27c-1.2-0.24-2.08-1.31-2.08-2.54s0.87-2.29,2.08-2.54
+ L10.23,54.7z M42.84,59.44l7.05,7.05c-5.83,4.33-12.69,6.97-19.94,7.64l3.22-11.75c0.2-0.02,0.41-0.05,0.61-0.11l8.66-2.65
+ C42.58,59.57,42.71,59.5,42.84,59.44z M32.23,75.88l-0.31,1.54c-0.24,1.2-1.31,2.08-2.54,2.08s-2.29-0.87-2.54-2.08l-0.22-1.12
+ c0.66-0.01,1.31-0.03,1.97-0.06c0,0,0.01,0,0.02,0c0.01,0,0.02-0.01,0.04-0.01C29.85,76.16,31.05,76.05,32.23,75.88z"/>
+<path d="M78.41,24.06l2.77,0.02C81.25,13.49,72.7,4.82,62.12,4.74L62.1,7.52C71.15,7.58,78.47,15,78.41,24.06z"/>
+<path d="M76.39,24.04c0.05-7.94-6.36-14.45-14.31-14.5l-0.02,2.77c6.41,0.05,11.59,5.31,11.56,11.71L76.39,24.04z"/>
+<path d="M62.05,14.49l-0.02,2.77c3.69,0.03,6.67,3.05,6.64,6.73l2.78,0.02C71.48,18.79,67.26,14.52,62.05,14.49z"/>
+</svg>
--- /dev/null
+/*
+ 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.
+*/
+
+apply plugin: 'com.android.application'
+
+if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoolean()) {
+ apply plugin: 'kotlin-android'
+ apply plugin: 'kotlin-android-extensions'
+}
+
+buildscript {
+ apply from: '../CordovaLib/cordova.gradle'
+
+ if(cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoolean()) {
+ String defaultGradlePluginKotlinVersion = kotlin_version
+
+ /**
+ * Fetches the user's defined Kotlin Version from config.xml.
+ * If the version is not set or invalid, it will default to the ${defaultGradlePluginKotlinVersion}
+ */
+ String gradlePluginKotlinVersion = cdvHelpers.getConfigPreference('GradlePluginKotlinVersion', defaultGradlePluginKotlinVersion)
+ if(!cdvHelpers.isVersionValid(gradlePluginKotlinVersion)) {
+ println("The defined Kotlin version (${gradlePluginKotlinVersion}) does not appear to be a valid version. Falling back to version: ${defaultGradlePluginKotlinVersion}.")
+ gradlePluginKotlinVersion = defaultGradlePluginKotlinVersion
+ }
+
+ // Change the version to be used.
+ ext.kotlin_version = gradlePluginKotlinVersion
+ }
+
+ repositories {
+ mavenCentral()
+ google()
+ jcenter()
+ }
+
+ dependencies {
+ apply from: '../CordovaLib/cordova.gradle'
+
+ classpath 'com.android.tools.build:gradle:4.0.0'
+
+ if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoolean()) {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+
+ if(cdvHelpers.getConfigPreference('GradlePluginGoogleServicesEnabled', 'false').toBoolean()) {
+ String defaultGradlePluginGoogleServicesVersion = '4.2.0'
+
+ /**
+ * Fetches the user's defined Google Services Plugin Version from config.xml.
+ * If the version is not set or invalid, it will default to the ${defaultGradlePluginGoogleServicesVersion}
+ */
+ String gradlePluginGoogleServicesVersion = cdvHelpers.getConfigPreference('GradlePluginGoogleServicesVersion', defaultGradlePluginGoogleServicesVersion)
+ if(!cdvHelpers.isVersionValid(gradlePluginGoogleServicesVersion)) {
+ println("The defined Google Services plugin version (${gradlePluginGoogleServicesVersion}) does not appear to be a valid version. Falling back to version: ${defaultGradlePluginGoogleServicesVersion}.")
+ gradlePluginGoogleServicesVersion = defaultGradlePluginGoogleServicesVersion
+ }
+
+ // Create the Google Services classpath and set it.
+ String gradlePluginGoogleServicesClassPath = "com.google.gms:google-services:${gradlePluginGoogleServicesVersion}"
+ println "Adding classpath: ${gradlePluginGoogleServicesClassPath}"
+ classpath gradlePluginGoogleServicesClassPath
+ }
+ }
+}
+
+// Allow plugins to declare Maven dependencies via build-extras.gradle.
+allprojects {
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
+}
+
+task wrapper(type: Wrapper) {
+ gradleVersion = '6.5'
+}
+
+// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
+// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
+ext {
+ apply from: '../CordovaLib/cordova.gradle'
+
+ // The value for android.compileSdkVersion.
+ if (!project.hasProperty('cdvCompileSdkVersion')) {
+ cdvCompileSdkVersion = null;
+ }
+ // The value for android.buildToolsVersion.
+ if (!project.hasProperty('cdvBuildToolsVersion')) {
+ cdvBuildToolsVersion = null;
+ }
+ // Sets the versionCode to the given value.
+ if (!project.hasProperty('cdvVersionCode')) {
+ cdvVersionCode = null
+ }
+ // Sets the minSdkVersion to the given value.
+ if (!project.hasProperty('cdvMinSdkVersion')) {
+ cdvMinSdkVersion = null
+ }
+ // Sets the maxSdkVersion to the given value.
+ if (!project.hasProperty('cdvMaxSdkVersion')) {
+ cdvMaxSdkVersion = null
+ }
+ // The value for android.targetSdkVersion.
+ if (!project.hasProperty('cdvTargetSdkVersion')) {
+ cdvTargetSdkVersion = null;
+ }
+ // Whether to build architecture-specific APKs.
+ if (!project.hasProperty('cdvBuildMultipleApks')) {
+ cdvBuildMultipleApks = null
+ }
+ // Whether to append a 0 "abi digit" to versionCode when only a single APK is build
+ if (!project.hasProperty('cdvVersionCodeForceAbiDigit')) {
+ cdvVersionCodeForceAbiDigit = null
+ }
+ // .properties files to use for release signing.
+ if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
+ cdvReleaseSigningPropertiesFile = null
+ }
+ // .properties files to use for debug signing.
+ if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
+ cdvDebugSigningPropertiesFile = null
+ }
+ // Set by build.js script.
+ if (!project.hasProperty('cdvBuildArch')) {
+ cdvBuildArch = null
+ }
+
+ // Plugin gradle extensions can append to this to have code run at the end.
+ cdvPluginPostBuildExtras = []
+}
+
+// PLUGIN GRADLE EXTENSIONS START
+// PLUGIN GRADLE EXTENSIONS END
+
+def hasBuildExtras1 = file('build-extras.gradle').exists()
+if (hasBuildExtras1) {
+ apply from: 'build-extras.gradle'
+}
+
+def hasBuildExtras2 = file('../build-extras.gradle').exists()
+if (hasBuildExtras2) {
+ apply from: '../build-extras.gradle'
+}
+
+// Set property defaults after extension .gradle files.
+ext.cdvCompileSdkVersion = cdvCompileSdkVersion == null ? (
+ defaultCompileSdkVersion == null
+ ? privateHelpers.getProjectTarget()
+ : defaultCompileSdkVersion
+) : Integer.parseInt('' + cdvCompileSdkVersion);
+
+if (ext.cdvBuildToolsVersion == null) {
+ ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
+ //ext.cdvBuildToolsVersion = project.ext.defaultBuildToolsVersion
+}
+if (ext.cdvDebugSigningPropertiesFile == null && file('../debug-signing.properties').exists()) {
+ ext.cdvDebugSigningPropertiesFile = '../debug-signing.properties'
+}
+if (ext.cdvReleaseSigningPropertiesFile == null && file('../release-signing.properties').exists()) {
+ ext.cdvReleaseSigningPropertiesFile = '../release-signing.properties'
+}
+
+// Cast to appropriate types.
+ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
+ext.cdvVersionCodeForceAbiDigit = cdvVersionCodeForceAbiDigit == null ? false : cdvVersionCodeForceAbiDigit.toBoolean();
+
+// minSdkVersion, maxSdkVersion and targetSdkVersion
+ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? defaultMinSdkVersion : Integer.parseInt('' + cdvMinSdkVersion)
+if (cdvMaxSdkVersion != null) {
+ ext.cdvMaxSdkVersion = Integer.parseInt('' + cdvMaxSdkVersion)
+}
+ext.cdvTargetSdkVersion = cdvTargetSdkVersion == null ? defaultTargetSdkVersion : Integer.parseInt('' + cdvTargetSdkVersion)
+
+ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)
+
+def computeBuildTargetName(debugBuild) {
+ def ret = 'assemble'
+ if (cdvBuildMultipleApks && cdvBuildArch) {
+ def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
+ ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
+ }
+ return ret + (debugBuild ? 'Debug' : 'Release')
+}
+
+// Make cdvBuild a task that depends on the debug/arch-sepecific task.
+task cdvBuildDebug
+cdvBuildDebug.dependsOn {
+ return computeBuildTargetName(true)
+}
+
+task cdvBuildRelease
+cdvBuildRelease.dependsOn {
+ return computeBuildTargetName(false)
+}
+
+task cdvPrintProps {
+ doLast {
+ println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
+ println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
+ println('cdvVersionCode=' + cdvVersionCode)
+ println('cdvVersionCodeForceAbiDigit=' + cdvVersionCodeForceAbiDigit)
+ println('cdvMinSdkVersion=' + cdvMinSdkVersion)
+ println('cdvMaxSdkVersion=' + cdvMaxSdkVersion)
+ println('cdvTargetSdkVersion=' + cdvTargetSdkVersion)
+ println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
+ println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
+ println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
+ println('cdvBuildArch=' + cdvBuildArch)
+ println('computedVersionCode=' + android.defaultConfig.versionCode)
+ android.productFlavors.each { flavor ->
+ println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
+ }
+ }
+}
+
+android {
+ defaultConfig {
+ versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
+ applicationId privateHelpers.extractStringFromManifest("package")
+
+ if (cdvMinSdkVersion != null) {
+ minSdkVersion cdvMinSdkVersion
+ }
+
+ if (cdvMaxSdkVersion != null) {
+ maxSdkVersion cdvMaxSdkVersion
+ }
+
+ if(cdvTargetSdkVersion != null) {
+ targetSdkVersion cdvTargetSdkVersion
+ }
+ }
+
+ lintOptions {
+ abortOnError false;
+ }
+
+ compileSdkVersion cdvCompileSdkVersion
+ buildToolsVersion cdvBuildToolsVersion
+
+ // This code exists for Crosswalk and other Native APIs.
+ // By default, we multiply the existing version code in the
+ // Android Manifest by 10 and add a number for each architecture.
+ // If you are not using Crosswalk or SQLite, you can
+ // ignore this chunk of code, and your version codes will be respected.
+
+ if (Boolean.valueOf(cdvBuildMultipleApks)) {
+ flavorDimensions "default"
+
+ productFlavors {
+ armeabi {
+ versionCode defaultConfig.versionCode*10 + 1
+ ndk {
+ abiFilters = ["armeabi"]
+ }
+ }
+ armv7 {
+ versionCode defaultConfig.versionCode*10 + 2
+ ndk {
+ abiFilters = ["armeabi-v7a"]
+ }
+ }
+ arm64 {
+ versionCode defaultConfig.versionCode*10 + 3
+ ndk {
+ abiFilters = ["arm64-v8a"]
+ }
+ }
+ x86 {
+ versionCode defaultConfig.versionCode*10 + 4
+ ndk {
+ abiFilters = ["x86"]
+ }
+ }
+ x86_64 {
+ versionCode defaultConfig.versionCode*10 + 5
+ ndk {
+ abiFilters = ["x86_64"]
+ }
+ }
+ }
+ } else if (Boolean.valueOf(cdvVersionCodeForceAbiDigit)) {
+ // This provides compatibility to the default logic for versionCode before cordova-android 5.2.0
+ defaultConfig {
+ versionCode defaultConfig.versionCode*10
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ if (cdvReleaseSigningPropertiesFile) {
+ signingConfigs {
+ release {
+ // These must be set or Gradle will complain (even if they are overridden).
+ keyAlias = ""
+ keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
+ storeFile = null
+ storePassword = "__unset"
+ }
+ }
+ buildTypes {
+ release {
+ signingConfig signingConfigs.release
+ }
+ }
+ addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
+ }
+
+ if (cdvDebugSigningPropertiesFile) {
+ addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+}
+
+/*
+ * WARNING: Cordova Lib and platform scripts do management inside of this code here,
+ * if you are adding the dependencies manually, do so outside the comments, otherwise
+ * the Cordova tools will overwrite them
+ */
+
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: '*.jar')
+
+ if (cdvHelpers.getConfigPreference('GradlePluginKotlinEnabled', 'false').toBoolean()) {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ }
+
+ // SUB-PROJECT DEPENDENCIES START
+ implementation(project(path: ":CordovaLib"))
+ implementation "androidx.core:core:1.1.0"
+ // SUB-PROJECT DEPENDENCIES END
+}
+
+def promptForReleaseKeyPassword() {
+ if (!cdvReleaseSigningPropertiesFile) {
+ return;
+ }
+ if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
+ android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
+ }
+ if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
+ android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
+ }
+}
+
+gradle.taskGraph.whenReady { taskGraph ->
+ taskGraph.getAllTasks().each() { task ->
+ if(['validateReleaseSigning', 'validateSigningRelease', 'validateSigningArmv7Release', 'validateSigningX76Release'].contains(task.name)) {
+ promptForReleaseKeyPassword()
+ }
+ }
+}
+
+def addSigningProps(propsFilePath, signingConfig) {
+ def propsFile = file(propsFilePath)
+ def props = new Properties()
+ propsFile.withReader { reader ->
+ props.load(reader)
+ }
+
+ def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
+ if (!storeFile.isAbsolute()) {
+ storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
+ }
+ if (!storeFile.exists()) {
+ throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
+ }
+ signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
+ signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
+ signingConfig.storeFile = storeFile
+ signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
+ def storeType = props.get('storeType', props.get('key.store.type', ''))
+ if (!storeType) {
+ def filename = storeFile.getName().toLowerCase();
+ if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
+ storeType = 'pkcs12'
+ } else {
+ storeType = signingConfig.storeType // "jks"
+ }
+ }
+ signingConfig.storeType = storeType
+}
+
+for (def func : cdvPluginPostBuildExtras) {
+ func()
+}
+
+// This can be defined within build-extras.gradle as:
+// ext.postBuildExtras = { ... code here ... }
+if (hasProperty('postBuildExtras')) {
+ postBuildExtras()
+}
+
+if (cdvHelpers.getConfigPreference('GradlePluginGoogleServicesEnabled', 'false').toBoolean()) {
+ apply plugin: 'com.google.gms.google-services'
+}
--- /dev/null
+/**
+ * Automatically generated file. DO NOT MODIFY
+ */
+package fr.enhydra.tortuga.home;
+
+public final class BuildConfig {
+ public static final boolean DEBUG = Boolean.parseBoolean("true");
+ public static final String APPLICATION_ID = "fr.enhydra.tortuga.home";
+ public static final String BUILD_TYPE = "debug";
+ public static final int VERSION_CODE = 10000;
+ public static final String VERSION_NAME = "1.0.0";
+}
--- /dev/null
+{}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-az_values-az.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-az\\values-az.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-hu_values-hu.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-hu\\values-hu.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ko_values-ko.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ko\\values-ko.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-af_values-af.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-af\\values-af.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ru_values-ru.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ru\\values-ru.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-v21_values-v21.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-v21\\values-v21.xml",
+ "from": {
+ "startLines": "2,3,4,5,6,7,8,9,10,13",
+ "startColumns": "4,4,4,4,4,4,4,4,4,4",
+ "startOffsets": "55,159,223,290,354,470,596,722,850,1022",
+ "endLines": "2,3,4,5,6,7,8,9,12,17",
+ "endColumns": "103,63,66,63,115,125,125,127,12,12",
+ "endOffsets": "154,218,285,349,465,591,717,845,1017,1355"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-or_values-or.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-or\\values-or.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-lo_values-lo.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-lo\\values-lo.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-th_values-th.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-th\\values-th.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-mk_values-mk.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-mk\\values-mk.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-en-rCA_values-en-rCA.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rCA\\values-en-rCA.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-zh-rHK_values-zh-rHK.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-zh-rHK\\values-zh-rHK.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-gu_values-gu.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-gu\\values-gu.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-as_values-as.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-as\\values-as.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-zu_values-zu.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-zu\\values-zu.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-uz_values-uz.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-uz\\values-uz.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-pl_values-pl.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pl\\values-pl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-nb_values-nb.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-nb\\values-nb.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ja_values-ja.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ja\\values-ja.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-fi_values-fi.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-fi\\values-fi.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-sq_values-sq.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sq\\values-sq.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-lv_values-lv.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-lv\\values-lv.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-is_values-is.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-is\\values-is.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-pa_values-pa.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pa\\values-pa.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-pt_values-pt.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pt\\values-pt.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-bs_values-bs.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-bs\\values-bs.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-kk_values-kk.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-kk\\values-kk.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-fa_values-fa.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-fa\\values-fa.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-de_values-de.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-de\\values-de.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-sw_values-sw.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sw\\values-sw.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-in_values-in.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-in\\values-in.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ne_values-ne.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ne\\values-ne.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ro_values-ro.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ro\\values-ro.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-en-rAU_values-en-rAU.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rAU\\values-en-rAU.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-hr_values-hr.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-hr\\values-hr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-vi_values-vi.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-vi\\values-vi.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-hy_values-hy.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-hy\\values-hy.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-iw_values-iw.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-iw\\values-iw.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-es-rUS_values-es-rUS.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-es-rUS\\values-es-rUS.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-mn_values-mn.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-mn\\values-mn.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-en-rIN_values-en-rIN.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rIN\\values-en-rIN.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-en-rGB_values-en-rGB.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rGB\\values-en-rGB.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-en-rXC_values-en-rXC.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rXC\\values-en-rXC.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "202",
+ "endOffsets": "253"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ms_values-ms.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ms\\values-ms.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-et_values-et.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-et\\values-et.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-nl_values-nl.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-nl\\values-nl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-b+sr+Latn_values-b+sr+Latn.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-b+sr+Latn\\values-b+sr+Latn.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-fr_values-fr.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-fr\\values-fr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-uk_values-uk.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-uk\\values-uk.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ta_values-ta.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ta\\values-ta.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ur_values-ur.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ur\\values-ur.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-kn_values-kn.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-kn\\values-kn.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-tr_values-tr.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-tr\\values-tr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-si_values-si.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-si\\values-si.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ky_values-ky.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ky\\values-ky.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-zh-rCN_values-zh-rCN.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-zh-rCN\\values-zh-rCN.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ml_values-ml.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ml\\values-ml.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-it_values-it.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-it\\values-it.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-be_values-be.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-be\\values-be.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-bn_values-bn.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-bn\\values-bn.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-sr_values-sr.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sr\\values-sr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-te_values-te.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-te\\values-te.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-da_values-da.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-da\\values-da.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-bg_values-bg.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-bg\\values-bg.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-hi_values-hi.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-hi\\values-hi.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-cs_values-cs.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-cs\\values-cs.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-fr-rCA_values-fr-rCA.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-fr-rCA\\values-fr-rCA.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-pt-rPT_values-pt-rPT.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pt-rPT\\values-pt-rPT.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-sk_values-sk.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sk\\values-sk.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ca_values-ca.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ca\\values-ca.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-sv_values-sv.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sv\\values-sv.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-pt-rBR_values-pt-rBR.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pt-rBR\\values-pt-rBR.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ka_values-ka.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ka\\values-ka.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-tl_values-tl.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-tl\\values-tl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-v16_values-v16.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-v16\\values-v16.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "65",
+ "endOffsets": "116"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-el_values-el.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-el\\values-el.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-zh-rTW_values-zh-rTW.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-zh-rTW\\values-zh-rTW.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-am_values-am.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-am\\values-am.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-eu_values-eu.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-eu\\values-eu.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values_values.arsc.flat",
+ "map": [
+ {
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\values\\strings.xml",
+ "from": {
+ "startLines": "4,2,3",
+ "startColumns": "4,4,4",
+ "startOffsets": "159,55,100",
+ "endColumns": "63,44,58",
+ "endOffsets": "218,95,154"
+ },
+ "to": {
+ "startLines": "78,79,80",
+ "startColumns": "4,4,4",
+ "startOffsets": "4653,4717,4762",
+ "endColumns": "63,44,58",
+ "endOffsets": "4712,4757,4816"
+ }
+ },
+ {
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\values\\colors.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "57",
+ "endColumns": "44",
+ "endOffsets": "97"
+ },
+ "to": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "44",
+ "endOffsets": "95"
+ }
+ },
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values\\values.xml",
+ "from": {
+ "startLines": "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,83,84,88,89,90,91,98,141,173,210",
+ "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4",
+ "startOffsets": "55,124,187,245,319,389,457,529,599,660,734,807,868,929,991,1055,1117,1178,1246,1346,1406,1472,1545,1614,1671,1723,1785,1857,1933,1998,2057,2116,2176,2236,2296,2356,2416,2476,2536,2596,2656,2716,2775,2835,2895,2955,3015,3075,3135,3195,3255,3315,3375,3434,3494,3554,3613,3672,3731,3790,3849,3908,3943,3978,4033,4096,4151,4209,4266,4316,4377,4434,4468,4503,4538,4608,4679,4796,4997,5107,5308,5437,5509,5576,5874,8780,10845,12605",
+ "endLines": "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,82,83,87,88,89,90,97,140,172,209,216",
+ "endColumns": "68,62,57,73,69,67,71,69,60,73,72,60,60,61,63,61,60,67,99,59,65,72,68,56,51,61,71,75,64,58,58,59,59,59,59,59,59,59,59,59,59,58,59,59,59,59,59,59,59,59,59,59,58,59,59,58,58,58,58,58,58,34,34,54,62,54,57,56,49,60,56,33,34,34,69,70,116,12,109,12,128,71,66,24,24,24,24,24",
+ "endOffsets": "119,182,240,314,384,452,524,594,655,729,802,863,924,986,1050,1112,1173,1241,1341,1401,1467,1540,1609,1666,1718,1780,1852,1928,1993,2052,2111,2171,2231,2291,2351,2411,2471,2531,2591,2651,2711,2770,2830,2890,2950,3010,3070,3130,3190,3250,3310,3370,3429,3489,3549,3608,3667,3726,3785,3844,3903,3938,3973,4028,4091,4146,4204,4261,4311,4372,4429,4463,4498,4533,4603,4674,4791,4992,5102,5303,5432,5504,5571,5869,8775,10840,12600,12977"
+ },
+ "to": {
+ "startLines": "3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,81,82,83,87,88,92,93,94,95,102,145,177,214",
+ "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4",
+ "startOffsets": "100,169,232,290,364,434,502,574,644,705,779,852,913,974,1036,1100,1162,1223,1291,1391,1451,1517,1590,1659,1716,1768,1830,1902,1978,2043,2102,2161,2221,2281,2341,2401,2461,2521,2581,2641,2701,2761,2820,2880,2940,3000,3060,3120,3180,3240,3300,3360,3420,3479,3539,3599,3658,3717,3776,3835,3894,3953,3988,4023,4078,4141,4196,4254,4311,4361,4422,4479,4513,4548,4583,4821,4892,5009,5210,5320,5521,5650,5722,5789,6087,8993,11058,12818",
+ "endLines": "3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,81,82,86,87,91,92,93,94,101,144,176,213,220",
+ "endColumns": "68,62,57,73,69,67,71,69,60,73,72,60,60,61,63,61,60,67,99,59,65,72,68,56,51,61,71,75,64,58,58,59,59,59,59,59,59,59,59,59,59,58,59,59,59,59,59,59,59,59,59,59,58,59,59,58,58,58,58,58,58,34,34,54,62,54,57,56,49,60,56,33,34,34,69,70,116,12,109,12,128,71,66,24,24,24,24,24",
+ "endOffsets": "164,227,285,359,429,497,569,639,700,774,847,908,969,1031,1095,1157,1218,1286,1386,1446,1512,1585,1654,1711,1763,1825,1897,1973,2038,2097,2156,2216,2276,2336,2396,2456,2516,2576,2636,2696,2756,2815,2875,2935,2995,3055,3115,3175,3235,3295,3355,3415,3474,3534,3594,3653,3712,3771,3830,3889,3948,3983,4018,4073,4136,4191,4249,4306,4356,4417,4474,4508,4543,4578,4648,4887,5004,5205,5315,5516,5645,5717,5784,6082,8988,11053,12813,13190"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-sl_values-sl.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sl\\values-sl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-km_values-km.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-km\\values-km.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-lt_values-lt.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-lt\\values-lt.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-mr_values-mr.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-mr\\values-mr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-ar_values-ar.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ar\\values-ar.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-es_values-es.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-es\\values-es.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-my_values-my.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-my\\values-my.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ },
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\values-gl_values-gl.arsc.flat",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-gl\\values-gl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-af\\values-af.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-af\\values-af.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-am\\values-am.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-am\\values-am.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ar\\values-ar.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ar\\values-ar.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-as\\values-as.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-as\\values-as.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-az\\values-az.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-az\\values-az.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-b+sr+Latn\\values-b+sr+Latn.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-b+sr+Latn\\values-b+sr+Latn.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-be\\values-be.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-be\\values-be.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-bg\\values-bg.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-bg\\values-bg.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-bn\\values-bn.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-bn\\values-bn.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-bs\\values-bs.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-bs\\values-bs.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ca\\values-ca.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ca\\values-ca.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-cs\\values-cs.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-cs\\values-cs.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-da\\values-da.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-da\\values-da.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-de\\values-de.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-de\\values-de.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-el\\values-el.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-el\\values-el.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-en-rAU\\values-en-rAU.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rAU\\values-en-rAU.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-en-rCA\\values-en-rCA.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rCA\\values-en-rCA.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-en-rGB\\values-en-rGB.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rGB\\values-en-rGB.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-en-rIN\\values-en-rIN.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rIN\\values-en-rIN.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-en-rXC\\values-en-rXC.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-en-rXC\\values-en-rXC.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "202",
+ "endOffsets": "253"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-es-rUS\\values-es-rUS.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-es-rUS\\values-es-rUS.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-es\\values-es.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-es\\values-es.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-et\\values-et.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-et\\values-et.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-eu\\values-eu.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-eu\\values-eu.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-fa\\values-fa.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-fa\\values-fa.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-fi\\values-fi.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-fi\\values-fi.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-fr-rCA\\values-fr-rCA.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-fr-rCA\\values-fr-rCA.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-fr\\values-fr.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-fr\\values-fr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-gl\\values-gl.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-gl\\values-gl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-gu\\values-gu.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-gu\\values-gu.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-hi\\values-hi.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-hi\\values-hi.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-hr\\values-hr.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-hr\\values-hr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-hu\\values-hu.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-hu\\values-hu.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-hy\\values-hy.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-hy\\values-hy.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-in\\values-in.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-in\\values-in.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-is\\values-is.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-is\\values-is.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-it\\values-it.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-it\\values-it.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-iw\\values-iw.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-iw\\values-iw.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ja\\values-ja.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ja\\values-ja.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ka\\values-ka.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ka\\values-ka.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-kk\\values-kk.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-kk\\values-kk.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-km\\values-km.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-km\\values-km.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-kn\\values-kn.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-kn\\values-kn.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ko\\values-ko.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ko\\values-ko.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ky\\values-ky.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ky\\values-ky.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-lo\\values-lo.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-lo\\values-lo.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-lt\\values-lt.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-lt\\values-lt.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-lv\\values-lv.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-lv\\values-lv.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-mk\\values-mk.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-mk\\values-mk.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ml\\values-ml.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ml\\values-ml.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-mn\\values-mn.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-mn\\values-mn.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-mr\\values-mr.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-mr\\values-mr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ms\\values-ms.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ms\\values-ms.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-my\\values-my.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-my\\values-my.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-nb\\values-nb.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-nb\\values-nb.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ne\\values-ne.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ne\\values-ne.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-nl\\values-nl.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-nl\\values-nl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-or\\values-or.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-or\\values-or.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-pa\\values-pa.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pa\\values-pa.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-pl\\values-pl.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pl\\values-pl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-pt-rBR\\values-pt-rBR.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pt-rBR\\values-pt-rBR.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-pt-rPT\\values-pt-rPT.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pt-rPT\\values-pt-rPT.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-pt\\values-pt.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-pt\\values-pt.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ro\\values-ro.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ro\\values-ro.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ru\\values-ru.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ru\\values-ru.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-si\\values-si.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-si\\values-si.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-sk\\values-sk.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sk\\values-sk.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-sl\\values-sl.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sl\\values-sl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-sq\\values-sq.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sq\\values-sq.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-sr\\values-sr.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sr\\values-sr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-sv\\values-sv.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sv\\values-sv.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-sw\\values-sw.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-sw\\values-sw.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ta\\values-ta.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ta\\values-ta.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-te\\values-te.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-te\\values-te.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-th\\values-th.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-th\\values-th.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-tl\\values-tl.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-tl\\values-tl.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-tr\\values-tr.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-tr\\values-tr.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-uk\\values-uk.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-uk\\values-uk.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-ur\\values-ur.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-ur\\values-ur.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-uz\\values-uz.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-uz\\values-uz.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-v16\\values-v16.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-v16\\values-v16.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "65",
+ "endOffsets": "116"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-v21\\values-v21.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-v21\\values-v21.xml",
+ "from": {
+ "startLines": "2,3,4,5,6,7,8,9,10,13",
+ "startColumns": "4,4,4,4,4,4,4,4,4,4",
+ "startOffsets": "55,159,223,290,354,470,596,722,850,1022",
+ "endLines": "2,3,4,5,6,7,8,9,12,17",
+ "endColumns": "103,63,66,63,115,125,125,127,12,12",
+ "endOffsets": "154,218,285,349,465,591,717,845,1017,1355"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-vi\\values-vi.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-vi\\values-vi.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-zh-rCN\\values-zh-rCN.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-zh-rCN\\values-zh-rCN.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-zh-rHK\\values-zh-rHK.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-zh-rHK\\values-zh-rHK.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-zh-rTW\\values-zh-rTW.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-zh-rTW\\values-zh-rTW.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values-zu\\values-zu.xml",
+ "map": [
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values-zu\\values-zu.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "100",
+ "endOffsets": "151"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "logs": [
+ {
+ "outputFile": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\incremental\\mergeDebugResources\\merged.dir\\values\\values.xml",
+ "map": [
+ {
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\values\\strings.xml",
+ "from": {
+ "startLines": "4,2,3",
+ "startColumns": "4,4,4",
+ "startOffsets": "159,55,100",
+ "endColumns": "63,44,58",
+ "endOffsets": "218,95,154"
+ },
+ "to": {
+ "startLines": "78,79,80",
+ "startColumns": "4,4,4",
+ "startOffsets": "4653,4717,4762",
+ "endColumns": "63,44,58",
+ "endOffsets": "4712,4757,4816"
+ }
+ },
+ {
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\values\\colors.xml",
+ "from": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "57",
+ "endColumns": "44",
+ "endOffsets": "97"
+ },
+ "to": {
+ "startLines": "2",
+ "startColumns": "4",
+ "startOffsets": "55",
+ "endColumns": "44",
+ "endOffsets": "95"
+ }
+ },
+ {
+ "source": "C:\\Users\\Vincent\\.gradle\\caches\\transforms-2\\files-2.1\\57b7f42ffa61e27821b7c87274482ce6\\core-1.1.0\\res\\values\\values.xml",
+ "from": {
+ "startLines": "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,83,84,88,89,90,91,98,141,173,210",
+ "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4",
+ "startOffsets": "55,124,187,245,319,389,457,529,599,660,734,807,868,929,991,1055,1117,1178,1246,1346,1406,1472,1545,1614,1671,1723,1785,1857,1933,1998,2057,2116,2176,2236,2296,2356,2416,2476,2536,2596,2656,2716,2775,2835,2895,2955,3015,3075,3135,3195,3255,3315,3375,3434,3494,3554,3613,3672,3731,3790,3849,3908,3943,3978,4033,4096,4151,4209,4266,4316,4377,4434,4468,4503,4538,4608,4679,4796,4997,5107,5308,5437,5509,5576,5874,8780,10845,12605",
+ "endLines": "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,82,83,87,88,89,90,97,140,172,209,216",
+ "endColumns": "68,62,57,73,69,67,71,69,60,73,72,60,60,61,63,61,60,67,99,59,65,72,68,56,51,61,71,75,64,58,58,59,59,59,59,59,59,59,59,59,59,58,59,59,59,59,59,59,59,59,59,59,58,59,59,58,58,58,58,58,58,34,34,54,62,54,57,56,49,60,56,33,34,34,69,70,116,12,109,12,128,71,66,24,24,24,24,24",
+ "endOffsets": "119,182,240,314,384,452,524,594,655,729,802,863,924,986,1050,1112,1173,1241,1341,1401,1467,1540,1609,1666,1718,1780,1852,1928,1993,2052,2111,2171,2231,2291,2351,2411,2471,2531,2591,2651,2711,2770,2830,2890,2950,3010,3070,3130,3190,3250,3310,3370,3429,3489,3549,3608,3667,3726,3785,3844,3903,3938,3973,4028,4091,4146,4204,4261,4311,4372,4429,4463,4498,4533,4603,4674,4791,4992,5102,5303,5432,5504,5571,5869,8775,10840,12600,12977"
+ },
+ "to": {
+ "startLines": "3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,81,82,83,87,88,92,93,94,95,102,145,177,214",
+ "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4",
+ "startOffsets": "100,169,232,290,364,434,502,574,644,705,779,852,913,974,1036,1100,1162,1223,1291,1391,1451,1517,1590,1659,1716,1768,1830,1902,1978,2043,2102,2161,2221,2281,2341,2401,2461,2521,2581,2641,2701,2761,2820,2880,2940,3000,3060,3120,3180,3240,3300,3360,3420,3479,3539,3599,3658,3717,3776,3835,3894,3953,3988,4023,4078,4141,4196,4254,4311,4361,4422,4479,4513,4548,4583,4821,4892,5009,5210,5320,5521,5650,5722,5789,6087,8993,11058,12818",
+ "endLines": "3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,81,82,86,87,91,92,93,94,101,144,176,213,220",
+ "endColumns": "68,62,57,73,69,67,71,69,60,73,72,60,60,61,63,61,60,67,99,59,65,72,68,56,51,61,71,75,64,58,58,59,59,59,59,59,59,59,59,59,59,58,59,59,59,59,59,59,59,59,59,59,58,59,59,58,58,58,58,58,58,34,34,54,62,54,57,56,49,60,56,33,34,34,69,70,116,12,109,12,128,71,66,24,24,24,24,24",
+ "endOffsets": "164,227,285,359,429,497,569,639,700,774,847,908,969,1031,1095,1157,1218,1286,1386,1446,1512,1585,1654,1711,1763,1825,1897,1973,2038,2097,2156,2216,2276,2336,2396,2456,2516,2576,2636,2696,2756,2815,2875,2935,2995,3055,3115,3175,3235,3295,3355,3415,3474,3534,3594,3653,3712,3771,3830,3889,3948,3983,4018,4073,4136,4191,4249,4306,4356,4417,4474,4508,4543,4578,4648,4887,5004,5205,5315,5516,5645,5717,5784,6082,8988,11053,12813,13190"
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+[
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xhdpi-v26_ic_launcher_foreground.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xhdpi-v26\\ic_launcher_foreground.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-hdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-hdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-xxxhdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-xxxhdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-mdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-mdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-xhdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-xhdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-mdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-mdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxhdpi-v26_ic_launcher.xml.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxhdpi-v26\\ic_launcher.xml"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-mdpi-v26_ic_launcher.xml.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-mdpi-v26\\ic_launcher.xml"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-hdpi_ic_launcher.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-hdpi\\ic_launcher.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxxhdpi_ic_launcher.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxxhdpi\\ic_launcher.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-xxhdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-xxhdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-xhdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-xhdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-mdpi-v26_ic_launcher_foreground.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-mdpi-v26\\ic_launcher_foreground.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xhdpi-v26_ic_launcher.xml.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xhdpi-v26\\ic_launcher.xml"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxhdpi_ic_launcher.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxhdpi\\ic_launcher.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-ldpi-v26_ic_launcher.xml.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-ldpi-v26\\ic_launcher.xml"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-xxhdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-xxhdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxhdpi-v26_ic_launcher_foreground.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxhdpi-v26\\ic_launcher_foreground.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\xml_provider_paths.xml.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\xml\\provider_paths.xml"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-hdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-hdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-hdpi-v26_ic_launcher.xml.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-hdpi-v26\\ic_launcher.xml"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-xxxhdpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-xxxhdpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxxhdpi-v26_ic_launcher_foreground.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxxhdpi-v26\\ic_launcher_foreground.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-mdpi_ic_launcher.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-mdpi\\ic_launcher.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\xml_config.xml.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\xml\\config.xml"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxxhdpi-v26_ic_launcher.xml.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxxhdpi-v26\\ic_launcher.xml"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xhdpi_ic_launcher.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xhdpi\\ic_launcher.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-ldpi_ic_launcher.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-ldpi\\ic_launcher.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-ldpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-ldpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-ldpi-v26_ic_launcher_foreground.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-ldpi-v26\\ic_launcher_foreground.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-ldpi_screen.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-ldpi\\screen.png"
+ },
+ {
+ "merged": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-hdpi-v26_ic_launcher_foreground.png.flat",
+ "source": "T:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-hdpi-v26\\ic_launcher_foreground.png"
+ }
+]
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="fr.enhydra.tortuga.home"
+ android:hardwareAccelerated="true"
+ android:versionCode="10000"
+ android:versionName="1.0.0" >
+
+ <uses-sdk
+ android:minSdkVersion="22"
+ android:targetSdkVersion="29" />
+
+ <supports-screens
+ android:anyDensity="true"
+ android:largeScreens="true"
+ android:normalScreens="true"
+ android:resizeable="true"
+ android:smallScreens="true"
+ android:xlargeScreens="true" />
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+
+ <application
+ android:appComponentFactory="androidx.core.app.CoreComponentFactory"
+ android:debuggable="true"
+ android:hardwareAccelerated="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:supportsRtl="true" >
+ <activity
+ android:name="fr.enhydra.tortuga.home.MainActivity"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
+ android:label="@string/activity_name"
+ android:launchMode="singleTask"
+ android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+ android:windowSoftInputMode="adjustResize" >
+ <intent-filter android:label="@string/launcher_name" >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="com.darryncampbell.cordova.plugin.intent.ACTION" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <action android:name="android.intent.action.SEND_MULTIPLE" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+
+ <data android:mimeType="*/*" />
+ </intent-filter>
+ </activity>
+
+ <provider
+ android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider"
+ android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true" >
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/provider_paths" />
+ </provider>
+ <provider
+ android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider"
+ android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true" >
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/provider_paths" />
+ </provider>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+{
+ "version": 1,
+ "applicationId": "fr.enhydra.tortuga.home",
+ "variantType": "BASE_APK",
+ "elements": [
+ {
+ "outputType": {
+ "type": "BUNDLE_MANIFEST"
+ },
+ "apkData": {
+ "type": "MAIN",
+ "splits": [],
+ "versionCode": 10000,
+ "versionName": "1.0.0",
+ "outputFile": "app-debug.apk",
+ "fullName": "debug",
+ "baseName": "debug",
+ "dirName": ""
+ },
+ "path": "AndroidManifest.xml",
+ "properties": {
+ "packageId": "fr.enhydra.tortuga.home",
+ "split": "",
+ "minSdkVersion": "22"
+ }
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "version": 1,
+ "applicationId": "fr.enhydra.tortuga.home",
+ "variantType": "BASE_APK",
+ "elements": []
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<merger version="3"><dataSet config=":CordovaLib" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\CordovaLib\build\intermediates\library_assets\debug\out"/></dataSet><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets"><file name="www/cordova-js-src/android/nativeapiprovider.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\cordova-js-src\android\nativeapiprovider.js"/><file name="www/cordova-js-src/android/promptbasednativeapi.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\cordova-js-src\android\promptbasednativeapi.js"/><file name="www/cordova-js-src/exec.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\cordova-js-src\exec.js"/><file name="www/cordova-js-src/platform.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\cordova-js-src\platform.js"/><file name="www/cordova-js-src/plugin/android/app.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\cordova-js-src\plugin\android\app.js"/><file name="www/cordova.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\cordova.js"/><file name="www/cordova_plugins.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\cordova_plugins.js"/><file name="www/css/index.css" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\css\index.css"/><file name="www/img/logo.png" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\img\logo.png"/><file name="www/index.html" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\index.html"/><file name="www/js/index.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\js\index.js"/><file name="www/plugins/cordova-plugin-file/www/fileSystems-roots.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\fileSystems-roots.js"/><file name="www/plugins/cordova-plugin-file/www/fileSystemPaths.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\fileSystemPaths.js"/><file name="www/plugins/cordova-plugin-file/www/FileUploadResult.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\FileUploadResult.js"/><file name="www/plugins/cordova-plugin-file/www/FileUploadOptions.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\FileUploadOptions.js"/><file name="www/plugins/cordova-plugin-file/www/FileSystem.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\FileSystem.js"/><file name="www/plugins/cordova-plugin-file/www/FileReader.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\FileReader.js"/><file name="www/plugins/cordova-plugin-file/www/ProgressEvent.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\ProgressEvent.js"/><file name="www/plugins/cordova-plugin-file/www/Entry.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\Entry.js"/><file name="www/plugins/cordova-plugin-file/www/LocalFileSystem.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\LocalFileSystem.js"/><file name="www/plugins/cordova-plugin-file/www/requestFileSystem.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\requestFileSystem.js"/><file name="www/plugins/cordova-plugin-file/www/File.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\File.js"/><file name="www/plugins/cordova-plugin-file/www/FileError.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\FileError.js"/><file name="www/plugins/es6-promise-plugin/www/promise.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\es6-promise-plugin\www\promise.js"/><file name="www/plugins/cordova-plugin-file/www/FileEntry.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\FileEntry.js"/><file name="www/plugins/cordova-plugin-file/www/android/FileSystem.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\android\FileSystem.js"/><file name="www/plugins/cordova-plugin-file/www/Metadata.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\Metadata.js"/><file name="www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\resolveLocalFileSystemURI.js"/><file name="www/plugins/cordova-plugin-device/www/device.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-device\www\device.js"/><file name="www/plugins/cordova-plugin-file/www/browser/isChrome.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\browser\isChrome.js"/><file name="www/plugins/cordova-plugin-file/www/DirectoryEntry.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\DirectoryEntry.js"/><file name="www/plugins/cordova-plugin-screen-orientation/www/screenorientation.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-screen-orientation\www\screenorientation.js"/><file name="www/plugins/cordova-plugin-file/www/DirectoryReader.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\DirectoryReader.js"/><file name="www/plugins/cordova-plugin-file/www/fileSystems.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\fileSystems.js"/><file name="www/plugins/cordova-plugin-file/www/Flags.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\Flags.js"/><file name="www/plugins/cordova-plugin-file/www/FileWriter.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-file\www\FileWriter.js"/><file name="www/plugins/cordova-plugin-statusbar/www/statusbar.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\cordova-plugin-statusbar\www\statusbar.js"/><file name="www/plugins/com-darryncampbell-cordova-plugin-intent/www/IntentShim.js" path="T:\Drive\Works\home-android\platforms\android\app\src\main\assets\www\plugins\com-darryncampbell-cordova-plugin-intent\www\IntentShim.js"/></source><source path="T:\Drive\Works\home-android\platforms\android\app\build\intermediates\shader_assets\debug\out"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\debug\assets"/></dataSet></merger>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\main\jniLibs"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\debug\jniLibs"/></dataSet></merger>
\ No newline at end of file
--- /dev/null
+#Wed Nov 11 20:58:52 CET 2020
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxxhdpi-v26\\ic_launcher.xml=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxxhdpi-v26_ic_launcher.xml.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxhdpi\\ic_launcher.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxhdpi_ic_launcher.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxxhdpi-v26\\ic_launcher_background.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxxhdpi-v26_ic_launcher_background.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxhdpi-v26\\ic_launcher_background.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxhdpi-v26_ic_launcher_background.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xhdpi-v26\\ic_launcher_background.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xhdpi-v26_ic_launcher_background.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-ldpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-ldpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\xml\\config.xml=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\xml_config.xml.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-ldpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-ldpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-ldpi-v26\\ic_launcher_background.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-ldpi-v26_ic_launcher_background.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxxhdpi-v26\\ic_launcher_foreground.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxxhdpi-v26_ic_launcher_foreground.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-hdpi\\ic_launcher.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-hdpi_ic_launcher.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxhdpi-v26\\ic_launcher_foreground.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxhdpi-v26_ic_launcher_foreground.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xhdpi-v26\\ic_launcher_foreground.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xhdpi-v26_ic_launcher_foreground.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-hdpi-v26\\ic_launcher_background.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-hdpi-v26_ic_launcher_background.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-ldpi-v26\\ic_launcher.xml=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-ldpi-v26_ic_launcher.xml.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-xxxhdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-xxxhdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-hdpi-v26\\ic_launcher.xml=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-hdpi-v26_ic_launcher.xml.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-ldpi-v26\\ic_launcher_foreground.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-ldpi-v26_ic_launcher_foreground.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-xhdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-xhdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-mdpi-v26\\ic_launcher_background.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-mdpi-v26_ic_launcher_background.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-xhdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-xhdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-xxhdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-xxhdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\xml\\provider_paths.xml=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\xml_provider_paths.xml.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-hdpi-v26\\ic_launcher_foreground.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-hdpi-v26_ic_launcher_foreground.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-mdpi-v26\\ic_launcher.xml=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-mdpi-v26_ic_launcher.xml.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xhdpi-v26\\ic_launcher.xml=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xhdpi-v26_ic_launcher.xml.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-mdpi-v26\\ic_launcher_foreground.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-mdpi-v26_ic_launcher_foreground.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxhdpi-v26\\ic_launcher.xml=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxhdpi-v26_ic_launcher.xml.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xxxhdpi\\ic_launcher.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xxxhdpi_ic_launcher.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-xxhdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-xxhdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-xxxhdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-xxxhdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-hdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-hdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-hdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-hdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-mdpi\\ic_launcher.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-mdpi_ic_launcher.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-land-mdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-land-mdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\drawable-port-mdpi\\screen.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\drawable-port-mdpi_screen.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-ldpi\\ic_launcher.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-ldpi_ic_launcher.png.flat
+T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\src\\main\\res\\mipmap-xhdpi\\ic_launcher.png=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\res\\merged\\debug\\mipmap-xhdpi_ic_launcher.png.flat
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<merger version="3"><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="androidx.core:core:1.1.0$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="androidx.core:core:1.1.0" from-dependency="true" generated-set="androidx.core:core:1.1.0$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res"><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values\values.xml" qualifiers=""><color name="notification_action_color_filter">#ffffffff</color><color name="notification_icon_bg_color">#ff9e9e9e</color><color name="ripple_material_light">#1f000000</color><color name="secondary_text_default_material_light">#8a000000</color><dimen name="compat_button_inset_horizontal_material">4dp</dimen><dimen name="compat_button_inset_vertical_material">6dp</dimen><dimen name="compat_button_padding_horizontal_material">8dp</dimen><dimen name="compat_button_padding_vertical_material">4dp</dimen><dimen name="compat_control_corner_material">2dp</dimen><dimen name="compat_notification_large_icon_max_height">320dp</dimen><dimen name="compat_notification_large_icon_max_width">320dp</dimen><dimen name="notification_action_icon_size">32dp</dimen><dimen name="notification_action_text_size">13sp</dimen><dimen name="notification_big_circle_margin">12dp</dimen><dimen name="notification_content_margin_start">8dp</dimen><dimen name="notification_large_icon_height">64dp</dimen><dimen name="notification_large_icon_width">64dp</dimen><dimen name="notification_main_column_padding_top">10dp</dimen><dimen name="notification_media_narrow_margin">@dimen/notification_content_margin_start</dimen><dimen name="notification_right_icon_size">16dp</dimen><dimen name="notification_right_side_padding_top">2dp</dimen><dimen name="notification_small_icon_background_padding">3dp</dimen><dimen name="notification_small_icon_size_as_large">24dp</dimen><dimen name="notification_subtext_size">13sp</dimen><dimen name="notification_top_pad">10dp</dimen><dimen name="notification_top_pad_large_text">5dp</dimen><drawable name="notification_template_icon_bg">#3333B5E5</drawable><drawable name="notification_template_icon_low_bg">#0cffffff</drawable><item name="accessibility_action_clickable_span" type="id"/><item name="accessibility_custom_action_0" type="id"/><item name="accessibility_custom_action_1" type="id"/><item name="accessibility_custom_action_10" type="id"/><item name="accessibility_custom_action_11" type="id"/><item name="accessibility_custom_action_12" type="id"/><item name="accessibility_custom_action_13" type="id"/><item name="accessibility_custom_action_14" type="id"/><item name="accessibility_custom_action_15" type="id"/><item name="accessibility_custom_action_16" type="id"/><item name="accessibility_custom_action_17" type="id"/><item name="accessibility_custom_action_18" type="id"/><item name="accessibility_custom_action_19" type="id"/><item name="accessibility_custom_action_2" type="id"/><item name="accessibility_custom_action_20" type="id"/><item name="accessibility_custom_action_21" type="id"/><item name="accessibility_custom_action_22" type="id"/><item name="accessibility_custom_action_23" type="id"/><item name="accessibility_custom_action_24" type="id"/><item name="accessibility_custom_action_25" type="id"/><item name="accessibility_custom_action_26" type="id"/><item name="accessibility_custom_action_27" type="id"/><item name="accessibility_custom_action_28" type="id"/><item name="accessibility_custom_action_29" type="id"/><item name="accessibility_custom_action_3" type="id"/><item name="accessibility_custom_action_30" type="id"/><item name="accessibility_custom_action_31" type="id"/><item name="accessibility_custom_action_4" type="id"/><item name="accessibility_custom_action_5" type="id"/><item name="accessibility_custom_action_6" type="id"/><item name="accessibility_custom_action_7" type="id"/><item name="accessibility_custom_action_8" type="id"/><item name="accessibility_custom_action_9" type="id"/><item name="line1" type="id"/><item name="line3" type="id"/><item name="tag_accessibility_actions" type="id"/><item name="tag_accessibility_clickable_spans" type="id"/><item name="tag_accessibility_heading" type="id"/><item name="tag_accessibility_pane_title" type="id"/><item name="tag_screen_reader_focusable" type="id"/><item name="tag_transition_group" type="id"/><item name="tag_unhandled_key_event_manager" type="id"/><item name="tag_unhandled_key_listeners" type="id"/><item name="text" type="id"/><item name="text2" type="id"/><item name="title" type="id"/><integer name="status_bar_notification_info_maxnum">999</integer><string name="status_bar_notification_info_overflow">999+</string><style name="TextAppearance.Compat.Notification" parent="@android:style/TextAppearance.StatusBar.EventContent"/><style name="TextAppearance.Compat.Notification.Info">
+ <item name="android:textSize">12sp</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ </style><style name="TextAppearance.Compat.Notification.Line2" parent="TextAppearance.Compat.Notification.Info"/><style name="TextAppearance.Compat.Notification.Time">
+ <item name="android:textSize">12sp</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ </style><style name="TextAppearance.Compat.Notification.Title" parent="@android:style/TextAppearance.StatusBar.EventContent.Title"/><style name="Widget.Compat.NotificationActionContainer" parent=""/><style name="Widget.Compat.NotificationActionText" parent=""/><declare-styleable name="ColorStateListItem">
+
+ <attr name="android:color"/>
+
+ <attr format="float" name="alpha"/>
+ <attr name="android:alpha"/>
+ </declare-styleable><declare-styleable name="FontFamily">
+
+ <attr format="string" name="fontProviderAuthority"/>
+
+ <attr format="string" name="fontProviderPackage"/>
+
+ <attr format="string" name="fontProviderQuery"/>
+
+ <attr format="reference" name="fontProviderCerts"/>
+
+ <attr name="fontProviderFetchStrategy">
+
+ <enum name="blocking" value="0"/>
+
+ <enum name="async" value="1"/>
+ </attr>
+
+ <attr format="integer" name="fontProviderFetchTimeout">
+
+ <enum name="forever" value="-1"/>
+ </attr>
+ </declare-styleable><declare-styleable name="FontFamilyFont">
+
+ <attr name="fontStyle">
+ <enum name="normal" value="0"/>
+ <enum name="italic" value="1"/>
+ </attr>
+
+ <attr format="reference" name="font"/>
+
+ <attr format="integer" name="fontWeight"/>
+
+ <attr format="string" name="fontVariationSettings"/>
+
+ <attr format="integer" name="ttcIndex"/>
+
+ <attr name="android:fontStyle"/>
+ <attr name="android:font"/>
+ <attr name="android:fontWeight"/>
+ <attr name="android:fontVariationSettings"/>
+ <attr name="android:ttcIndex"/>
+ </declare-styleable><declare-styleable name="GradientColor">
+
+ <attr name="android:startColor"/>
+
+ <attr name="android:centerColor"/>
+
+ <attr name="android:endColor"/>
+
+ <attr name="android:type"/>
+
+
+
+ <attr name="android:gradientRadius"/>
+
+
+
+ <attr name="android:centerX"/>
+
+ <attr name="android:centerY"/>
+
+
+
+ <attr name="android:startX"/>
+
+ <attr name="android:startY"/>
+
+ <attr name="android:endX"/>
+
+ <attr name="android:endY"/>
+
+
+ <attr name="android:tileMode"/>
+ </declare-styleable><declare-styleable name="GradientColorItem">
+
+ <attr name="android:offset"/>
+
+ <attr name="android:color"/>
+ </declare-styleable></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-af\values-af.xml" qualifiers="af"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-am\values-am.xml" qualifiers="am"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ar\values-ar.xml" qualifiers="ar"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-as\values-as.xml" qualifiers="as"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"৯৯৯+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-az\values-az.xml" qualifiers="az"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-b+sr+Latn\values-b+sr+Latn.xml" qualifiers="b+sr+Latn"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-be\values-be.xml" qualifiers="be"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-bg\values-bg.xml" qualifiers="bg"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-bn\values-bn.xml" qualifiers="bn"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"৯৯৯+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-bs\values-bs.xml" qualifiers="bs"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ca\values-ca.xml" qualifiers="ca"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-cs\values-cs.xml" qualifiers="cs"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-da\values-da.xml" qualifiers="da"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-de\values-de.xml" qualifiers="de"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-el\values-el.xml" qualifiers="el"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-en-rAU\values-en-rAU.xml" qualifiers="en-rAU"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-en-rCA\values-en-rCA.xml" qualifiers="en-rCA"><string msgid="7988687684186075107" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-en-rGB\values-en-rGB.xml" qualifiers="en-rGB"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-en-rIN\values-en-rIN.xml" qualifiers="en-rIN"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-en-rXC\values-en-rXC.xml" qualifiers="en-rXC"><string msgid="7988687684186075107" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-es\values-es.xml" qualifiers="es"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-es-rUS\values-es-rUS.xml" qualifiers="es-rUS"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-et\values-et.xml" qualifiers="et"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-eu\values-eu.xml" qualifiers="eu"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-fa\values-fa.xml" qualifiers="fa"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-fi\values-fi.xml" qualifiers="fi"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-fr\values-fr.xml" qualifiers="fr"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-fr-rCA\values-fr-rCA.xml" qualifiers="fr-rCA"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-gl\values-gl.xml" qualifiers="gl"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">">999"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-gu\values-gu.xml" qualifiers="gu"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-hi\values-hi.xml" qualifiers="hi"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-hr\values-hr.xml" qualifiers="hr"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-hu\values-hu.xml" qualifiers="hu"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-hy\values-hy.xml" qualifiers="hy"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-in\values-in.xml" qualifiers="in"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-is\values-is.xml" qualifiers="is"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-it\values-it.xml" qualifiers="it"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-iw\values-iw.xml" qualifiers="iw"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ja\values-ja.xml" qualifiers="ja"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ka\values-ka.xml" qualifiers="ka"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-kk\values-kk.xml" qualifiers="kk"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-km\values-km.xml" qualifiers="km"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-kn\values-kn.xml" qualifiers="kn"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ko\values-ko.xml" qualifiers="ko"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ky\values-ky.xml" qualifiers="ky"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-lo\values-lo.xml" qualifiers="lo"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-lt\values-lt.xml" qualifiers="lt"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-lv\values-lv.xml" qualifiers="lv"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-mk\values-mk.xml" qualifiers="mk"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ml\values-ml.xml" qualifiers="ml"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-mn\values-mn.xml" qualifiers="mn"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-mr\values-mr.xml" qualifiers="mr"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"९९९+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ms\values-ms.xml" qualifiers="ms"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-my\values-my.xml" qualifiers="my"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"၉၉၉+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-nb\values-nb.xml" qualifiers="nb"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ne\values-ne.xml" qualifiers="ne"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"९९९+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-nl\values-nl.xml" qualifiers="nl"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-or\values-or.xml" qualifiers="or"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-pa\values-pa.xml" qualifiers="pa"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-pl\values-pl.xml" qualifiers="pl"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-pt\values-pt.xml" qualifiers="pt"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-pt-rBR\values-pt-rBR.xml" qualifiers="pt-rBR"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-pt-rPT\values-pt-rPT.xml" qualifiers="pt-rPT"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ro\values-ro.xml" qualifiers="ro"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ru\values-ru.xml" qualifiers="ru"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">">999"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-si\values-si.xml" qualifiers="si"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-sk\values-sk.xml" qualifiers="sk"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-sl\values-sl.xml" qualifiers="sl"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-sq\values-sq.xml" qualifiers="sq"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-sr\values-sr.xml" qualifiers="sr"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-sv\values-sv.xml" qualifiers="sv"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-sw\values-sw.xml" qualifiers="sw"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ta\values-ta.xml" qualifiers="ta"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-te\values-te.xml" qualifiers="te"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-th\values-th.xml" qualifiers="th"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-tl\values-tl.xml" qualifiers="tl"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-tr\values-tr.xml" qualifiers="tr"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-uk\values-uk.xml" qualifiers="uk"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-ur\values-ur.xml" qualifiers="ur"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"+999"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-uz\values-uz.xml" qualifiers="uz"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-v16\values-v16.xml" qualifiers="v16"><dimen name="notification_right_side_padding_top">4dp</dimen></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-v21\values-v21.xml" qualifiers="v21"><color name="notification_action_color_filter">@color/secondary_text_default_material_light</color><dimen name="notification_content_margin_start">0dp</dimen><dimen name="notification_main_column_padding_top">0dp</dimen><dimen name="notification_media_narrow_margin">12dp</dimen><style name="TextAppearance.Compat.Notification" parent="@android:style/TextAppearance.Material.Notification"/><style name="TextAppearance.Compat.Notification.Info" parent="@android:style/TextAppearance.Material.Notification.Info"/><style name="TextAppearance.Compat.Notification.Time" parent="@android:style/TextAppearance.Material.Notification.Time"/><style name="TextAppearance.Compat.Notification.Title" parent="@android:style/TextAppearance.Material.Notification.Title"/><style name="Widget.Compat.NotificationActionContainer" parent="">
+ <item name="android:background">@drawable/notification_action_background</item>
+ </style><style name="Widget.Compat.NotificationActionText" parent="">
+ <item name="android:textAppearance">?android:attr/textAppearanceButton</item>
+ <item name="android:textColor">@color/secondary_text_default_material_light</item>
+ <item name="android:textSize">@dimen/notification_action_text_size</item>
+ </style></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-vi\values-vi.xml" qualifiers="vi"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-zh-rCN\values-zh-rCN.xml" qualifiers="zh-rCN"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-zh-rHK\values-zh-rHK.xml" qualifiers="zh-rHK"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-zh-rTW\values-zh-rTW.xml" qualifiers="zh-rTW"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file><file path="C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\res\values-zu\values-zu.xml" qualifiers="zu"><string msgid="8106346172024741305" name="status_bar_notification_info_overflow">"999+"</string></file></source></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config=":CordovaLib$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\CordovaLib\build\intermediates\packaged_res\debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config=":CordovaLib" from-dependency="true" generated-set=":CordovaLib$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\CordovaLib\build\intermediates\packaged_res\debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\main\res"/><source path="T:\Drive\Works\home-android\platforms\android\app\build\generated\res\rs\debug"/><source path="T:\Drive\Works\home-android\platforms\android\app\build\generated\res\resValues\debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main" generated-set="main$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\main\res"><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-land-hdpi\screen.png" qualifiers="land-hdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-land-ldpi\screen.png" qualifiers="land-ldpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-land-mdpi\screen.png" qualifiers="land-mdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-land-xhdpi\screen.png" qualifiers="land-xhdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-land-xxhdpi\screen.png" qualifiers="land-xxhdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-land-xxxhdpi\screen.png" qualifiers="land-xxxhdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-port-hdpi\screen.png" qualifiers="port-hdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-port-ldpi\screen.png" qualifiers="port-ldpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-port-mdpi\screen.png" qualifiers="port-mdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-port-xhdpi\screen.png" qualifiers="port-xhdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-port-xxhdpi\screen.png" qualifiers="port-xxhdpi-v4" type="drawable"/><file name="screen" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\drawable-port-xxxhdpi\screen.png" qualifiers="port-xxxhdpi-v4" type="drawable"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-hdpi\ic_launcher.png" qualifiers="hdpi-v4" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-hdpi-v26\ic_launcher.xml" qualifiers="hdpi-v26" type="mipmap"/><file name="ic_launcher_foreground" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-hdpi-v26\ic_launcher_foreground.png" qualifiers="hdpi-v26" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-ldpi\ic_launcher.png" qualifiers="ldpi-v4" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-ldpi-v26\ic_launcher.xml" qualifiers="ldpi-v26" type="mipmap"/><file name="ic_launcher_foreground" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-ldpi-v26\ic_launcher_foreground.png" qualifiers="ldpi-v26" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-mdpi\ic_launcher.png" qualifiers="mdpi-v4" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-mdpi-v26\ic_launcher.xml" qualifiers="mdpi-v26" type="mipmap"/><file name="ic_launcher_foreground" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-mdpi-v26\ic_launcher_foreground.png" qualifiers="mdpi-v26" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xhdpi\ic_launcher.png" qualifiers="xhdpi-v4" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xhdpi-v26\ic_launcher.xml" qualifiers="xhdpi-v26" type="mipmap"/><file name="ic_launcher_foreground" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xhdpi-v26\ic_launcher_foreground.png" qualifiers="xhdpi-v26" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xxhdpi\ic_launcher.png" qualifiers="xxhdpi-v4" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xxhdpi-v26\ic_launcher.xml" qualifiers="xxhdpi-v26" type="mipmap"/><file name="ic_launcher_foreground" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xxhdpi-v26\ic_launcher_foreground.png" qualifiers="xxhdpi-v26" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xxxhdpi\ic_launcher.png" qualifiers="xxxhdpi-v4" type="mipmap"/><file name="ic_launcher" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xxxhdpi-v26\ic_launcher.xml" qualifiers="xxxhdpi-v26" type="mipmap"/><file name="ic_launcher_foreground" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\mipmap-xxxhdpi-v26\ic_launcher_foreground.png" qualifiers="xxxhdpi-v26" type="mipmap"/><file path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\values\colors.xml" qualifiers=""><color name="background">#0a4a9e</color></file><file path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\values\strings.xml" qualifiers=""><string name="app_name">Tortuga</string><string name="launcher_name">@string/app_name</string><string name="activity_name">@string/launcher_name</string></file><file name="config" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\xml\config.xml" qualifiers="" type="xml"/><file name="provider_paths" path="T:\Drive\Works\home-android\platforms\android\app\src\main\res\xml\provider_paths.xml" qualifiers="" type="xml"/></source><source path="T:\Drive\Works\home-android\platforms\android\app\build\generated\res\rs\debug"/><source path="T:\Drive\Works\home-android\platforms\android\app\build\generated\res\resValues\debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\debug\res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug" generated-set="debug$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\debug\res"/></dataSet><mergedItems><configuration qualifiers=""><declare-styleable name="FontFamilyFont">
+
+ <attr name="fontStyle">
+ <enum name="normal" value="0"/>
+ <enum name="italic" value="1"/>
+ </attr>
+
+ <attr format="reference" name="font"/>
+
+ <attr format="integer" name="fontWeight"/>
+
+ <attr format="string" name="fontVariationSettings"/>
+
+ <attr format="integer" name="ttcIndex"/>
+
+ <attr name="android:fontStyle"/>
+ <attr name="android:font"/>
+ <attr name="android:fontWeight"/>
+ <attr name="android:fontVariationSettings"/>
+ <attr name="android:ttcIndex"/>
+ </declare-styleable><declare-styleable name="GradientColorItem">
+
+ <attr name="android:offset"/>
+
+ <attr name="android:color"/>
+ </declare-styleable><declare-styleable name="FontFamily">
+
+ <attr format="string" name="fontProviderAuthority"/>
+
+ <attr format="string" name="fontProviderPackage"/>
+
+ <attr format="string" name="fontProviderQuery"/>
+
+ <attr format="reference" name="fontProviderCerts"/>
+
+ <attr name="fontProviderFetchStrategy">
+
+ <enum name="blocking" value="0"/>
+
+ <enum name="async" value="1"/>
+ </attr>
+
+ <attr format="integer" name="fontProviderFetchTimeout">
+
+ <enum name="forever" value="-1"/>
+ </attr>
+ </declare-styleable><declare-styleable name="GradientColor">
+
+ <attr name="android:startColor"/>
+
+ <attr name="android:centerColor"/>
+
+ <attr name="android:endColor"/>
+
+ <attr name="android:type"/>
+
+
+
+ <attr name="android:gradientRadius"/>
+
+
+
+ <attr name="android:centerX"/>
+
+ <attr name="android:centerY"/>
+
+
+
+ <attr name="android:startX"/>
+
+ <attr name="android:startY"/>
+
+ <attr name="android:endX"/>
+
+ <attr name="android:endY"/>
+
+
+ <attr name="android:tileMode"/>
+ </declare-styleable><declare-styleable name="ColorStateListItem">
+
+ <attr name="android:color"/>
+
+ <attr format="float" name="alpha"/>
+ <attr name="android:alpha"/>
+ </declare-styleable></configuration></mergedItems></merger>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\main\shaders"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="T:\Drive\Works\home-android\platforms\android\app\src\debug\shaders"/></dataSet></merger>
\ No newline at end of file
--- /dev/null
+#Wed Nov 11 20:59:00 CET 2020
+path.2=classes_0.dex
+path.1=classes.dex
+path.0=classes.dex
+renamed.2=classes3.dex
+renamed.1=classes2.dex
+renamed.0=classes.dex
+base.2=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\dex\\debug\\mergeLibDexDebug\\classes_0.dex
+base.1=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\dex\\debug\\mergeProjectDexDebug\\classes.dex
+base.0=T\:\\Drive\\Works\\home-android\\platforms\\android\\app\\build\\intermediates\\dex\\debug\\mergeExtDexDebug\\classes.dex
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="fr.enhydra.tortuga.home"
+ android:hardwareAccelerated="true"
+ android:targetSandboxVersion="2"
+ android:versionCode="10000"
+ android:versionName="1.0.0" >
+
+ <uses-sdk
+ android:minSdkVersion="22"
+ android:targetSdkVersion="29" />
+
+ <supports-screens
+ android:anyDensity="true"
+ android:largeScreens="true"
+ android:normalScreens="true"
+ android:resizeable="true"
+ android:smallScreens="true"
+ android:xlargeScreens="true" />
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+
+ <application
+ android:appComponentFactory="androidx.core.app.CoreComponentFactory"
+ android:debuggable="true"
+ android:hardwareAccelerated="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:supportsRtl="true" >
+ <activity
+ android:name="fr.enhydra.tortuga.home.MainActivity"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
+ android:label="@string/activity_name"
+ android:launchMode="singleTask"
+ android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+ android:windowSoftInputMode="adjustResize" >
+ <intent-filter android:label="@string/launcher_name" >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="com.darryncampbell.cordova.plugin.intent.ACTION" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <action android:name="android.intent.action.SEND_MULTIPLE" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+
+ <data android:mimeType="*/*" />
+ </intent-filter>
+ </activity>
+
+ <provider
+ android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider"
+ android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true" >
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/provider_paths" />
+ </provider>
+ <provider
+ android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider"
+ android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true" >
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/provider_paths" />
+ </provider>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+{
+ "version": 1,
+ "applicationId": "fr.enhydra.tortuga.home",
+ "variantType": "BASE_APK",
+ "elements": [
+ {
+ "outputType": {
+ "type": "INSTANT_APP_MANIFEST"
+ },
+ "apkData": {
+ "type": "MAIN",
+ "splits": [],
+ "versionCode": 10000,
+ "versionName": "1.0.0",
+ "outputFile": "app-debug.apk",
+ "fullName": "debug",
+ "baseName": "debug",
+ "dirName": ""
+ },
+ "path": "AndroidManifest.xml",
+ "properties": {
+ "packageId": "fr.enhydra.tortuga.home",
+ "split": "",
+ "minSdkVersion": "22"
+ }
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+1<?xml version="1.0" encoding="utf-8"?>
+2<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+3 package="fr.enhydra.tortuga.home"
+4 android:hardwareAccelerated="true"
+5 android:versionCode="10000"
+6 android:versionName="1.0.0" >
+7
+8 <uses-sdk
+9 android:minSdkVersion="22"
+9-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+10 android:targetSdkVersion="29" />
+10-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+11
+12 <supports-screens
+12-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:5-191
+13 android:anyDensity="true"
+13-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:23-48
+14 android:largeScreens="true"
+14-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:49-76
+15 android:normalScreens="true"
+15-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:77-105
+16 android:resizeable="true"
+16-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:106-131
+17 android:smallScreens="true"
+17-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:132-159
+18 android:xlargeScreens="true" />
+18-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:160-188
+19
+20 <uses-permission android:name="android.permission.INTERNET" />
+20-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:4:5-67
+20-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:4:22-64
+21 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+21-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:29:5-81
+21-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:29:22-78
+22 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+22-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:30:5-80
+22-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:30:22-77
+23 <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+23-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:31:5-83
+23-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:31:22-80
+24
+25 <application
+25-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:5-28:19
+26 android:appComponentFactory="androidx.core.app.CoreComponentFactory"
+26-->[androidx.core:core:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\AndroidManifest.xml:24:18-86
+27 android:debuggable="true"
+28 android:hardwareAccelerated="true"
+28-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:18-52
+29 android:icon="@mipmap/ic_launcher"
+29-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:53-87
+30 android:label="@string/app_name"
+30-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:88-120
+31 android:supportsRtl="true" >
+31-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:121-147
+32 <activity
+32-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:9-21:20
+33 android:name="fr.enhydra.tortuga.home.MainActivity"
+33-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:206-233
+34 android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
+34-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:19-135
+35 android:label="@string/activity_name"
+35-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:136-173
+36 android:launchMode="singleTask"
+36-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:174-205
+37 android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+37-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:234-296
+38 android:windowSoftInputMode="adjustResize" >
+38-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:297-339
+39 <intent-filter android:label="@string/launcher_name" >
+39-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:7:13-10:29
+39-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:7:28-65
+40 <action android:name="android.intent.action.MAIN" />
+40-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:8:17-69
+40-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:8:25-66
+41
+42 <category android:name="android.intent.category.LAUNCHER" />
+42-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:9:17-77
+42-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:9:27-74
+43 </intent-filter>
+44 <intent-filter>
+44-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:11:13-14:29
+45 <action android:name="com.darryncampbell.cordova.plugin.intent.ACTION" />
+45-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:12:17-90
+45-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:12:25-87
+46
+47 <category android:name="android.intent.category.DEFAULT" />
+47-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:13:17-76
+47-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:13:27-73
+48 </intent-filter>
+49 <intent-filter>
+49-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:15:13-20:29
+50 <action android:name="android.intent.action.SEND" />
+50-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:16:17-69
+50-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:16:25-66
+51 <action android:name="android.intent.action.SEND_MULTIPLE" />
+51-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:17:17-78
+51-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:17:25-75
+52
+53 <category android:name="android.intent.category.DEFAULT" />
+53-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:13:17-76
+53-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:13:27-73
+54
+55 <data android:mimeType="*/*" />
+55-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:19:17-48
+55-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:19:23-45
+56 </intent-filter>
+57 </activity>
+58
+59 <provider
+60 android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider"
+60-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:175-262
+61 android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider"
+61-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:19-114
+62 android:exported="false"
+62-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:115-139
+63 android:grantUriPermissions="true" >
+63-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:140-174
+64 <meta-data
+64-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:13-116
+65 android:name="android.support.FILE_PROVIDER_PATHS"
+65-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:24-74
+66 android:resource="@xml/provider_paths" />
+66-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:75-113
+67 </provider>
+68 <provider
+69 android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider"
+69-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:175-262
+70 android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider"
+70-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:19-114
+71 android:exported="false"
+71-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:115-139
+72 android:grantUriPermissions="true" >
+72-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:140-174
+73 <meta-data
+73-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:13-116
+74 android:name="android.support.FILE_PROVIDER_PATHS"
+74-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:24-74
+75 android:resource="@xml/provider_paths" />
+75-->T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:75-113
+76 </provider>
+77 </application>
+78
+79</manifest>
--- /dev/null
+/*
+ * 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.
+*/
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+ get: function () { return currentApi; },
+ setPreferPrompt: function (value) {
+ currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+ },
+ // Used only by tests.
+ set: function (value) {
+ currentApi = value;
+ }
+};
--- /dev/null
+/*
+ * 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.
+*/
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+ exec: function (bridgeSecret, service, action, callbackId, argsJson) {
+ return prompt(argsJson, 'gap:' + JSON.stringify([bridgeSecret, service, action, callbackId]));
+ },
+ setNativeToJsBridgeMode: function (bridgeSecret, value) {
+ prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+ },
+ retrieveJsMessages: function (bridgeSecret, fromOnlineEvent) {
+ return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+ }
+};
--- /dev/null
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Execute a cordova command. It is up to the native side whether this action
+ * is synchronous or asynchronous. The native side can return:
+ * Synchronous: PluginResult object as a JSON string
+ * Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success The success callback
+ * @param {Function} fail The fail callback
+ * @param {String} service The name of the service to use
+ * @param {String} action Action to be run in cordova
+ * @param {String[]} [args] Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova');
+var nativeApiProvider = require('cordova/android/nativeapiprovider');
+var utils = require('cordova/utils');
+var base64 = require('cordova/base64');
+var channel = require('cordova/channel');
+var jsToNativeModes = {
+ PROMPT: 0,
+ JS_OBJECT: 1
+};
+var nativeToJsModes = {
+ // Polls for messages using the JS->Native bridge.
+ POLLING: 0,
+ // For LOAD_URL to be viable, it would need to have a work-around for
+ // the bug where the soft-keyboard gets dismissed when a message is sent.
+ LOAD_URL: 1,
+ // For the ONLINE_EVENT to be viable, it would need to intercept all event
+ // listeners (both through addEventListener and window.ononline) as well
+ // as set the navigator property itself.
+ ONLINE_EVENT: 2,
+ EVAL_BRIDGE: 3
+};
+var jsToNativeBridgeMode; // Set lazily.
+var nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE;
+var pollEnabled = false;
+var bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise === 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function (fn) { resolvedPromise.then(fn); } : function (fn) { setTimeout(fn); };
+
+function androidExec (success, fail, service, action, args) {
+ if (bridgeSecret < 0) {
+ // If we ever catch this firing, we'll need to queue up exec()s
+ // and fire them once we get a secret. For now, I don't think
+ // it's possible for exec() to be called since plugins are parsed but
+ // not run until until after onNativeReady.
+ throw new Error('exec() called without bridgeSecret');
+ }
+ // Set default bridge modes if they have not already been set.
+ // By default, we use the failsafe, since addJavascriptInterface breaks too often
+ if (jsToNativeBridgeMode === undefined) {
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+ }
+
+ // If args is not provided, default to an empty array
+ args = args || [];
+
+ // Process any ArrayBuffers in the args into a string.
+ for (var i = 0; i < args.length; i++) {
+ if (utils.typeName(args[i]) === 'ArrayBuffer') {
+ args[i] = base64.fromArrayBuffer(args[i]);
+ }
+ }
+
+ var callbackId = service + cordova.callbackId++;
+ var argsJson = JSON.stringify(args);
+ if (success || fail) {
+ cordova.callbacks[callbackId] = { success: success, fail: fail };
+ }
+
+ var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+ // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+ // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
+ if (jsToNativeBridgeMode === jsToNativeModes.JS_OBJECT && msgs === '@Null arguments.') {
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+ androidExec(success, fail, service, action, args);
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+ } else if (msgs) {
+ messagesFromNative.push(msgs);
+ // Always process async to avoid exceptions messing up stack.
+ nextTick(processMessages);
+ }
+}
+
+androidExec.init = function () {
+ bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+ channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent () {
+ pollOnce(true);
+}
+
+function pollOnce (opt_fromOnlineEvent) {
+ if (bridgeSecret < 0) {
+ // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+ // We know there's nothing to retrieve, so no need to poll.
+ return;
+ }
+ var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+ if (msgs) {
+ messagesFromNative.push(msgs);
+ // Process sync since we know we're already top-of-stack.
+ processMessages();
+ }
+}
+
+function pollingTimerFunc () {
+ if (pollEnabled) {
+ pollOnce();
+ setTimeout(pollingTimerFunc, 50);
+ }
+}
+
+function hookOnlineApis () {
+ function proxyEvent (e) {
+ cordova.fireWindowEvent(e.type);
+ }
+ // The network module takes care of firing online and offline events.
+ // It currently fires them only on document though, so we bridge them
+ // to window here (while first listening for exec()-releated online/offline
+ // events).
+ window.addEventListener('online', pollOnceFromOnlineEvent, false);
+ window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+ cordova.addWindowEventHandler('online');
+ cordova.addWindowEventHandler('offline');
+ document.addEventListener('online', proxyEvent, false);
+ document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function (mode) {
+ if (mode === jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+ mode = jsToNativeModes.PROMPT;
+ }
+ nativeApiProvider.setPreferPrompt(mode === jsToNativeModes.PROMPT);
+ jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function (mode) {
+ if (mode === nativeToJsBridgeMode) {
+ return;
+ }
+ if (nativeToJsBridgeMode === nativeToJsModes.POLLING) {
+ pollEnabled = false;
+ }
+
+ nativeToJsBridgeMode = mode;
+ // Tell the native side to switch modes.
+ // Otherwise, it will be set by androidExec.init()
+ if (bridgeSecret >= 0) {
+ nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+ }
+
+ if (mode === nativeToJsModes.POLLING) {
+ pollEnabled = true;
+ setTimeout(pollingTimerFunc, 1);
+ }
+};
+
+function buildPayload (payload, message) {
+ var payloadKind = message.charAt(0);
+ if (payloadKind === 's') {
+ payload.push(message.slice(1));
+ } else if (payloadKind === 't') {
+ payload.push(true);
+ } else if (payloadKind === 'f') {
+ payload.push(false);
+ } else if (payloadKind === 'N') {
+ payload.push(null);
+ } else if (payloadKind === 'n') {
+ payload.push(+message.slice(1));
+ } else if (payloadKind === 'A') {
+ var data = message.slice(1);
+ payload.push(base64.toArrayBuffer(data));
+ } else if (payloadKind === 'S') {
+ payload.push(window.atob(message.slice(1)));
+ } else if (payloadKind === 'M') {
+ var multipartMessages = message.slice(1);
+ while (multipartMessages !== '') {
+ var spaceIdx = multipartMessages.indexOf(' ');
+ var msgLen = +multipartMessages.slice(0, spaceIdx);
+ var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+ multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+ buildPayload(payload, multipartMessage);
+ }
+ } else {
+ payload.push(JSON.parse(message));
+ }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage (message) {
+ var firstChar = message.charAt(0);
+ if (firstChar === 'J') {
+ // This is deprecated on the .java side. It doesn't work with CSP enabled.
+ // eslint-disable-next-line no-eval
+ eval(message.slice(1));
+ } else if (firstChar === 'S' || firstChar === 'F') {
+ var success = firstChar === 'S';
+ var keepCallback = message.charAt(1) === '1';
+ var spaceIdx = message.indexOf(' ', 2);
+ var status = +message.slice(2, spaceIdx);
+ var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+ var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+ var payloadMessage = message.slice(nextSpaceIdx + 1);
+ var payload = [];
+ buildPayload(payload, payloadMessage);
+ cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+ } else {
+ console.log('processMessage failed: invalid message: ' + JSON.stringify(message));
+ }
+}
+
+function processMessages () {
+ // Check for the reentrant case.
+ if (isProcessing) {
+ return;
+ }
+ if (messagesFromNative.length === 0) {
+ return;
+ }
+ isProcessing = true;
+ try {
+ var msg = popMessageFromQueue();
+ // The Java side can send a * message to indicate that it
+ // still has messages waiting to be retrieved.
+ if (msg === '*' && messagesFromNative.length === 0) {
+ nextTick(pollOnce);
+ return;
+ }
+ processMessage(msg);
+ } finally {
+ isProcessing = false;
+ if (messagesFromNative.length > 0) {
+ nextTick(processMessages);
+ }
+ }
+}
+
+function popMessageFromQueue () {
+ var messageBatch = messagesFromNative.shift();
+ if (messageBatch === '*') {
+ return '*';
+ }
+
+ var spaceIdx = messageBatch.indexOf(' ');
+ var msgLen = +messageBatch.slice(0, spaceIdx);
+ var message = messageBatch.substr(spaceIdx + 1, msgLen);
+ messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+ if (messageBatch) {
+ messagesFromNative.unshift(messageBatch);
+ }
+ return message;
+}
+
+module.exports = androidExec;
--- /dev/null
+/*
+ *
+ * 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.
+ *
+*/
+
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
+
+module.exports = {
+ id: 'android',
+ bootstrap: function () {
+ var channel = require('cordova/channel');
+ var cordova = require('cordova');
+ var exec = require('cordova/exec');
+ var modulemapper = require('cordova/modulemapper');
+
+ // Get the shared secret needed to use the bridge.
+ exec.init();
+
+ // TODO: Extract this as a proper plugin.
+ modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+
+ var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+ // Inject a listener for the backbutton on the document.
+ var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+ backButtonChannel.onHasSubscribersChange = function () {
+ // If we just attached the first handler or detached the last handler,
+ // let native know we need to override the back button.
+ exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [this.numHandlers === 1]);
+ };
+
+ // Add hardware MENU and SEARCH button handlers
+ cordova.addDocumentEventHandler('menubutton');
+ cordova.addDocumentEventHandler('searchbutton');
+
+ function bindButtonChannel (buttonName) {
+ // generic button bind used for volumeup/volumedown buttons
+ var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+ volumeButtonChannel.onHasSubscribersChange = function () {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [buttonName, this.numHandlers === 1]);
+ };
+ }
+ // Inject a listener for the volume buttons on the document.
+ bindButtonChannel('volumeup');
+ bindButtonChannel('volumedown');
+
+ // The resume event is not "sticky", but it is possible that the event
+ // will contain the result of a plugin call. We need to ensure that the
+ // plugin result is delivered even after the event is fired (CB-10498)
+ var cordovaAddEventListener = document.addEventListener;
+
+ document.addEventListener = function (evt, handler, capture) {
+ cordovaAddEventListener(evt, handler, capture);
+
+ if (evt === 'resume' && lastResumeEvent) {
+ handler(lastResumeEvent);
+ }
+ };
+
+ // Let native code know we are all done on the JS side.
+ // Native code will then un-hide the WebView.
+ channel.onCordovaReady.subscribe(function () {
+ exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+ exec(null, null, APP_PLUGIN_NAME, 'show', []);
+ });
+ }
+};
+
+function onMessageFromNative (msg) {
+ var cordova = require('cordova');
+ var action = msg.action;
+
+ switch (action) {
+ // pause and resume are Android app life cycle events
+ case 'backbutton':
+ case 'menubutton':
+ case 'searchbutton':
+ case 'pause':
+ case 'volumedownbutton':
+ case 'volumeupbutton':
+ cordova.fireDocumentEvent(action);
+ break;
+ case 'resume':
+ if (arguments.length > 1 && msg.pendingResult) {
+ if (arguments.length === 2) {
+ msg.pendingResult.result = arguments[1];
+ } else {
+ // The plugin returned a multipart message
+ var res = [];
+ for (var i = 1; i < arguments.length; i++) {
+ res.push(arguments[i]);
+ }
+ msg.pendingResult.result = res;
+ }
+
+ // Save the plugin result so that it can be delivered to the js
+ // even if they miss the initial firing of the event
+ lastResumeEvent = msg;
+ }
+ cordova.fireDocumentEvent(action, msg);
+ break;
+ default:
+ throw new Error('Unknown event action ' + action);
+ }
+}
--- /dev/null
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+ /**
+ * Clear the resource cache.
+ */
+ clearCache: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'clearCache', []);
+ },
+
+ /**
+ * Load the url into the webview or into new browser instance.
+ *
+ * @param url The URL to load
+ * @param props Properties that can be passed in to the activity:
+ * wait: int => wait msec before loading URL
+ * loadingDialog: "Title,Message" => display a native loading dialog
+ * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
+ * clearHistory: boolean => clear webview history (default=false)
+ * openExternal: boolean => open in a new browser (default=false)
+ *
+ * Example:
+ * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+ */
+ loadUrl: function (url, props) {
+ exec(null, null, APP_PLUGIN_NAME, 'loadUrl', [url, props]);
+ },
+
+ /**
+ * Cancel loadUrl that is waiting to be loaded.
+ */
+ cancelLoadUrl: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'cancelLoadUrl', []);
+ },
+
+ /**
+ * Clear web history in this web view.
+ * Instead of BACK button loading the previous web page, it will exit the app.
+ */
+ clearHistory: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'clearHistory', []);
+ },
+
+ /**
+ * Go to previous page displayed.
+ * This is the same as pressing the backbutton on Android device.
+ */
+ backHistory: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'backHistory', []);
+ },
+
+ /**
+ * Override the default behavior of the Android back button.
+ * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+ *
+ * Note: The user should not have to call this method. Instead, when the user
+ * registers for the "backbutton" event, this is automatically done.
+ *
+ * @param override T=override, F=cancel override
+ */
+ overrideBackbutton: function (override) {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [override]);
+ },
+
+ /**
+ * Override the default behavior of the Android volume button.
+ * If overridden, when the volume button is pressed, the "volume[up|down]button"
+ * JavaScript event will be fired.
+ *
+ * Note: The user should not have to call this method. Instead, when the user
+ * registers for the "volume[up|down]button" event, this is automatically done.
+ *
+ * @param button volumeup, volumedown
+ * @param override T=override, F=cancel override
+ */
+ overrideButton: function (button, override) {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [button, override]);
+ },
+
+ /**
+ * Exit and terminate the application.
+ */
+ exitApp: function () {
+ return exec(null, null, APP_PLUGIN_NAME, 'exitApp', []);
+ }
+};
--- /dev/null
+// Platform: android
+// 538a985db128858c0a0eb4dd40fb9c8e5433fc94
+/*
+ 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.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '9.0.0';
+// file: src/scripts/require.js
+var require;
+var define;
+
+(function () {
+ var modules = {};
+ // Stack of moduleIds currently being built.
+ var requireStack = [];
+ // Map of module ID -> index into requireStack of modules currently being built.
+ var inProgressModules = {};
+ var SEPARATOR = '.';
+
+ function build (module) {
+ var factory = module.factory;
+ var localRequire = function (id) {
+ var resultantId = id;
+ // Its a relative path, so lop off the last portion and add the id (minus "./")
+ if (id.charAt(0) === '.') {
+ resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+ }
+ return require(resultantId);
+ };
+ module.exports = {};
+ delete module.factory;
+ factory(localRequire, module.exports, module);
+ return module.exports;
+ }
+
+ require = function (id) {
+ if (!modules[id]) {
+ throw new Error('module ' + id + ' not found');
+ } else if (id in inProgressModules) {
+ var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+ throw new Error('Cycle in require graph: ' + cycle);
+ }
+ if (modules[id].factory) {
+ try {
+ inProgressModules[id] = requireStack.length;
+ requireStack.push(id);
+ return build(modules[id]);
+ } finally {
+ delete inProgressModules[id];
+ requireStack.pop();
+ }
+ }
+ return modules[id].exports;
+ };
+
+ define = function (id, factory) {
+ if (Object.prototype.hasOwnProperty.call(modules, id)) {
+ throw new Error('module ' + id + ' already defined');
+ }
+
+ modules[id] = {
+ id: id,
+ factory: factory
+ };
+ };
+
+ define.remove = function (id) {
+ delete modules[id];
+ };
+
+ define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+ module.exports.require = require;
+ module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) {
+ throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ if (typeof documentEventHandlers[e] !== 'undefined') {
+ documentEventHandlers[e].subscribe(handler);
+ } else {
+ m_document_addEventListener.call(document, evt, handler, capture);
+ }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ if (typeof windowEventHandlers[e] !== 'undefined') {
+ windowEventHandlers[e].subscribe(handler);
+ } else {
+ m_window_addEventListener.call(window, evt, handler, capture);
+ }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ // If unsubscribing from an event that is handled by a plugin
+ if (typeof documentEventHandlers[e] !== 'undefined') {
+ documentEventHandlers[e].unsubscribe(handler);
+ } else {
+ m_document_removeEventListener.call(document, evt, handler, capture);
+ }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ // If unsubscribing from an event that is handled by a plugin
+ if (typeof windowEventHandlers[e] !== 'undefined') {
+ windowEventHandlers[e].unsubscribe(handler);
+ } else {
+ m_window_removeEventListener.call(window, evt, handler, capture);
+ }
+};
+
+function createEvent (type, data) {
+ var event = document.createEvent('Events');
+ event.initEvent(type, false, false);
+ if (data) {
+ for (var i in data) {
+ if (Object.prototype.hasOwnProperty.call(data, i)) {
+ event[i] = data[i];
+ }
+ }
+ }
+ return event;
+}
+
+var cordova = {
+ define: define,
+ require: require,
+ version: PLATFORM_VERSION_BUILD_LABEL,
+ platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+ platformId: platform.id,
+
+ /**
+ * Methods to add/remove your own addEventListener hijacking on document + window.
+ */
+ addWindowEventHandler: function (event) {
+ return (windowEventHandlers[event] = channel.create(event));
+ },
+ addStickyDocumentEventHandler: function (event) {
+ return (documentEventHandlers[event] = channel.createSticky(event));
+ },
+ addDocumentEventHandler: function (event) {
+ return (documentEventHandlers[event] = channel.create(event));
+ },
+ removeWindowEventHandler: function (event) {
+ delete windowEventHandlers[event];
+ },
+ removeDocumentEventHandler: function (event) {
+ delete documentEventHandlers[event];
+ },
+
+ /**
+ * Retrieve original event handlers that were replaced by Cordova
+ *
+ * @return object
+ */
+ getOriginalHandlers: function () {
+ return {
+ document: {
+ addEventListener: m_document_addEventListener,
+ removeEventListener: m_document_removeEventListener
+ },
+ window: {
+ addEventListener: m_window_addEventListener,
+ removeEventListener: m_window_removeEventListener
+ }
+ };
+ },
+
+ /**
+ * Method to fire event from native code
+ * bNoDetach is required for events which cause an exception which needs to be caught in native code
+ */
+ fireDocumentEvent: function (type, data, bNoDetach) {
+ var evt = createEvent(type, data);
+ if (typeof documentEventHandlers[type] !== 'undefined') {
+ if (bNoDetach) {
+ documentEventHandlers[type].fire(evt);
+ } else {
+ setTimeout(function () {
+ // Fire deviceready on listeners that were registered before cordova.js was loaded.
+ if (type === 'deviceready') {
+ document.dispatchEvent(evt);
+ }
+ documentEventHandlers[type].fire(evt);
+ }, 0);
+ }
+ } else {
+ document.dispatchEvent(evt);
+ }
+ },
+
+ fireWindowEvent: function (type, data) {
+ var evt = createEvent(type, data);
+ if (typeof windowEventHandlers[type] !== 'undefined') {
+ setTimeout(function () {
+ windowEventHandlers[type].fire(evt);
+ }, 0);
+ } else {
+ window.dispatchEvent(evt);
+ }
+ },
+
+ /**
+ * Plugin callback mechanism.
+ */
+ // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+ // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+ callbackId: Math.floor(Math.random() * 2000000000),
+ callbacks: {},
+ callbackStatus: {
+ NO_RESULT: 0,
+ OK: 1,
+ CLASS_NOT_FOUND_EXCEPTION: 2,
+ ILLEGAL_ACCESS_EXCEPTION: 3,
+ INSTANTIATION_EXCEPTION: 4,
+ MALFORMED_URL_EXCEPTION: 5,
+ IO_EXCEPTION: 6,
+ INVALID_ACTION: 7,
+ JSON_EXCEPTION: 8,
+ ERROR: 9
+ },
+
+ /**
+ * Called by native code when returning successful result from an action.
+ */
+ callbackSuccess: function (callbackId, args) {
+ cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+ },
+
+ /**
+ * Called by native code when returning error result from an action.
+ */
+ callbackError: function (callbackId, args) {
+ // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+ // Derive success from status.
+ cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+ },
+
+ /**
+ * Called by native code when returning the result from an action.
+ */
+ callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+ try {
+ var callback = cordova.callbacks[callbackId];
+ if (callback) {
+ if (isSuccess && status === cordova.callbackStatus.OK) {
+ callback.success && callback.success.apply(null, args);
+ } else if (!isSuccess) {
+ callback.fail && callback.fail.apply(null, args);
+ }
+ /*
+ else
+ Note, this case is intentionally not caught.
+ this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+ which is used to remove a callback from the list without calling the callbacks
+ typically keepCallback is false in this case
+ */
+ // Clear callback if not expecting any more results
+ if (!keepCallback) {
+ delete cordova.callbacks[callbackId];
+ }
+ }
+ } catch (err) {
+ var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+ cordova.fireWindowEvent('cordovacallbackerror', { message: msg, error: err });
+ throw err;
+ }
+ },
+
+ addConstructor: function (func) {
+ channel.onCordovaReady.subscribe(function () {
+ try {
+ func();
+ } catch (e) {
+ console.log('Failed to run constructor: ' + e);
+ }
+ });
+ }
+};
+
+module.exports = cordova;
+
+});
+
+// file: ../cordova-android/cordova-js-src/android/nativeapiprovider.js
+define("cordova/android/nativeapiprovider", function(require, exports, module) {
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+ get: function () { return currentApi; },
+ setPreferPrompt: function (value) {
+ currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+ },
+ // Used only by tests.
+ set: function (value) {
+ currentApi = value;
+ }
+};
+
+});
+
+// file: ../cordova-android/cordova-js-src/android/promptbasednativeapi.js
+define("cordova/android/promptbasednativeapi", function(require, exports, module) {
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+ exec: function (bridgeSecret, service, action, callbackId, argsJson) {
+ return prompt(argsJson, 'gap:' + JSON.stringify([bridgeSecret, service, action, callbackId]));
+ },
+ setNativeToJsBridgeMode: function (bridgeSecret, value) {
+ prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+ },
+ retrieveJsMessages: function (bridgeSecret, fromOnlineEvent) {
+ return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+ }
+};
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+ A: 'Array',
+ D: 'Date',
+ N: 'Number',
+ S: 'String',
+ F: 'Function',
+ O: 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+ return (/\(\s*([^)]*?)\s*\)/).exec(callee)[1].split(/\s*,\s*/)[argIndex];
+}
+
+/**
+ * Checks the given arguments' types and throws if they are not as expected.
+ *
+ * `spec` is a string where each character stands for the required type of the
+ * argument at the same position. In other words: the character at `spec[i]`
+ * specifies the required type for `args[i]`. The characters in `spec` are the
+ * first letter of the required type's name. The supported types are:
+ *
+ * Array, Date, Number, String, Function, Object
+ *
+ * Lowercase characters specify arguments that must not be `null` or `undefined`
+ * while uppercase characters allow those values to be passed.
+ *
+ * Finally, `*` can be used to allow any type at the corresponding position.
+ *
+ * @example
+ * function foo (arr, opts) {
+ * // require `arr` to be an Array and `opts` an Object, null or undefined
+ * checkArgs('aO', 'my.package.foo', arguments);
+ * // ...
+ * }
+ * @param {String} spec - the type specification for `args` as described above
+ * @param {String} functionName - full name of the callee.
+ * Used in the error message
+ * @param {Array|arguments} args - the arguments to be checked against `spec`
+ * @param {Function} [opt_callee=args.callee] - the recipient of `args`.
+ * Used to extract parameter names for the error message
+ * @throws {TypeError} if args do not satisfy spec
+ */
+function checkArgs (spec, functionName, args, opt_callee) {
+ if (!moduleExports.enableChecks) {
+ return;
+ }
+ var errMsg = null;
+ var typeName;
+ for (var i = 0; i < spec.length; ++i) {
+ var c = spec.charAt(i);
+ var cUpper = c.toUpperCase();
+ var arg = args[i];
+ // Asterix means allow anything.
+ if (c === '*') {
+ continue;
+ }
+ typeName = utils.typeName(arg);
+ if ((arg === null || arg === undefined) && c === cUpper) {
+ continue;
+ }
+ if (typeName !== typeMap[cUpper]) {
+ errMsg = 'Expected ' + typeMap[cUpper];
+ break;
+ }
+ }
+ if (errMsg) {
+ errMsg += ', but got ' + typeName + '.';
+ errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+ // Don't log when running unit tests.
+ if (typeof jasmine === 'undefined') {
+ console.error(errMsg);
+ }
+ throw TypeError(errMsg);
+ }
+}
+
+function getValue (value, defaultValue) {
+ return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+ var array = new Uint8Array(arrayBuffer);
+ return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+ var decodedStr = atob(str);
+ var arrayBuffer = new ArrayBuffer(decodedStr.length);
+ var array = new Uint8Array(arrayBuffer);
+ for (var i = 0, len = decodedStr.length; i < len; i++) {
+ array[i] = decodedStr.charCodeAt(i);
+ }
+ return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+ b64_12bit = [];
+ for (var i = 0; i < 64; i++) {
+ for (var j = 0; j < 64; j++) {
+ b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+ }
+ }
+ b64_12bitTable = function () { return b64_12bit; };
+ return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+ var numBytes = rawData.byteLength;
+ var output = '';
+ var segment;
+ var table = b64_12bitTable();
+ for (var i = 0; i < numBytes - 2; i += 3) {
+ segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+ output += table[segment >> 12];
+ output += table[segment & 0xfff];
+ }
+ if (numBytes - i === 2) {
+ segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+ output += table[segment >> 12];
+ output += b64_6bit[(segment & 0xfff) >> 6];
+ output += '=';
+ } else if (numBytes - i === 1) {
+ segment = (rawData[i] << 16);
+ output += table[segment >> 12];
+ output += '==';
+ }
+ return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+ for (var prop in objects) {
+ if (Object.prototype.hasOwnProperty.call(objects, prop)) {
+ func.apply(context, [objects[prop], prop]);
+ }
+ }
+}
+
+function clobber (obj, key, value) {
+ var needsProperty = false;
+ try {
+ obj[key] = value;
+ } catch (e) {
+ needsProperty = true;
+ }
+ // Getters can only be overridden by getters.
+ if (needsProperty || obj[key] !== value) {
+ utils.defineGetter(obj, key, function () {
+ return value;
+ });
+ }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+ if (message) {
+ utils.defineGetter(obj, key, function () {
+ console.log(message);
+ delete obj[key];
+ clobber(obj, key, value);
+ return value;
+ });
+ } else {
+ clobber(obj, key, value);
+ }
+}
+
+function include (parent, objects, clobber, merge) {
+ each(objects, function (obj, key) {
+ try {
+ var result = obj.path ? require(obj.path) : {};
+
+ if (clobber) {
+ // Clobber if it doesn't exist.
+ if (typeof parent[key] === 'undefined') {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ } else if (typeof obj.path !== 'undefined') {
+ // If merging, merge properties onto parent, otherwise, clobber.
+ if (merge) {
+ recursiveMerge(parent[key], result);
+ } else {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ }
+ }
+ result = parent[key];
+ } else {
+ // Overwrite if not currently defined.
+ if (typeof parent[key] === 'undefined') {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ } else {
+ // Set result to what already exists, so we can build children into it if they exist.
+ result = parent[key];
+ }
+ }
+
+ if (obj.children) {
+ include(result, obj.children, clobber, merge);
+ }
+ } catch (e) {
+ utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+ }
+ });
+}
+
+/**
+ * Merge properties from one object onto another recursively. Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+ for (var prop in src) {
+ if (Object.prototype.hasOwnProperty.call(src, prop)) {
+ if (target.prototype && target.prototype.constructor === target) {
+ // If the target object is a constructor override off prototype.
+ clobber(target.prototype, prop, src[prop]);
+ } else {
+ if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+ recursiveMerge(target[prop], src[prop]);
+ } else {
+ clobber(target, prop, src[prop]);
+ }
+ }
+ }
+ }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+ include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+ include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+ include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded* Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady* Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady* Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady* User event fired to indicate that Cordova is ready
+ * onResume User event fired to indicate a start/resume lifecycle event
+ * onPause User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ * deviceready Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ * pause App has moved to background
+ * resume App has returned to foreground
+ *
+ * Listeners can be registered as:
+ * document.addEventListener("deviceready", myDeviceReadyListener, false);
+ * document.addEventListener("resume", myResumeListener, false);
+ * document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ * window.onload
+ * window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type String the channel name
+ */
+var Channel = function (type, sticky) {
+ this.type = type;
+ // Map of guid -> function.
+ this.handlers = {};
+ // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+ this.state = sticky ? 1 : 0;
+ // Used in sticky mode to remember args passed to fire().
+ this.fireArgs = null;
+ // Used by onHasSubscribersChange to know if there are any listeners.
+ this.numHandlers = 0;
+ // Function that is called when the first listener is subscribed, or when
+ // the last listener is unsubscribed.
+ this.onHasSubscribersChange = null;
+};
+var channel = {
+ /**
+ * Calls the provided function only after all of the channels specified
+ * have been fired. All channels must be sticky channels.
+ */
+ join: function (h, c) {
+ var len = c.length;
+ var i = len;
+ var f = function () {
+ if (!(--i)) h();
+ };
+ for (var j = 0; j < len; j++) {
+ if (c[j].state === 0) {
+ throw Error('Can only use join with sticky channels.');
+ }
+ c[j].subscribe(f);
+ }
+ if (!len) h();
+ },
+
+ create: function (type) {
+ return (channel[type] = new Channel(type, false));
+ },
+ createSticky: function (type) {
+ return (channel[type] = new Channel(type, true));
+ },
+
+ /**
+ * cordova Channels that must fire before "deviceready" is fired.
+ */
+ deviceReadyChannelsArray: [],
+ deviceReadyChannelsMap: {},
+
+ /**
+ * Indicate that a feature needs to be initialized before it is ready to be used.
+ * This holds up Cordova's "deviceready" event until the feature has been initialized
+ * and Cordova.initComplete(feature) is called.
+ *
+ * @param feature {String} The unique feature name
+ */
+ waitForInitialization: function (feature) {
+ if (feature) {
+ var c = channel[feature] || this.createSticky(feature);
+ this.deviceReadyChannelsMap[feature] = c;
+ this.deviceReadyChannelsArray.push(c);
+ }
+ },
+
+ /**
+ * Indicate that initialization code has completed and the feature is ready to be used.
+ *
+ * @param feature {String} The unique feature name
+ */
+ initializationComplete: function (feature) {
+ var c = this.deviceReadyChannelsMap[feature];
+ if (c) {
+ c.fire();
+ }
+ }
+};
+
+function checkSubscriptionArgument (argument) {
+ if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+ throw new Error(
+ 'Must provide a function or an EventListener object ' +
+ 'implementing the handleEvent interface.'
+ );
+ }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+ checkSubscriptionArgument(eventListenerOrFunction);
+ var handleEvent, guid;
+
+ if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+ // Received an EventListener object implementing the handleEvent interface
+ handleEvent = eventListenerOrFunction.handleEvent;
+ eventListener = eventListenerOrFunction;
+ } else {
+ // Received a function to handle event
+ handleEvent = eventListenerOrFunction;
+ }
+
+ if (this.state === 2) {
+ handleEvent.apply(eventListener || this, this.fireArgs);
+ return;
+ }
+
+ guid = eventListenerOrFunction.observer_guid;
+ if (typeof eventListener === 'object') {
+ handleEvent = utils.close(eventListener, handleEvent);
+ }
+
+ if (!guid) {
+ // First time any channel has seen this subscriber
+ guid = '' + nextGuid++;
+ }
+ handleEvent.observer_guid = guid;
+ eventListenerOrFunction.observer_guid = guid;
+
+ // Don't add the same handler more than once.
+ if (!this.handlers[guid]) {
+ this.handlers[guid] = handleEvent;
+ this.numHandlers++;
+ if (this.numHandlers === 1) {
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+ checkSubscriptionArgument(eventListenerOrFunction);
+ var handleEvent, guid, handler;
+
+ if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+ // Received an EventListener object implementing the handleEvent interface
+ handleEvent = eventListenerOrFunction.handleEvent;
+ } else {
+ // Received a function to handle event
+ handleEvent = eventListenerOrFunction;
+ }
+
+ guid = handleEvent.observer_guid;
+ handler = this.handlers[guid];
+ if (handler) {
+ delete this.handlers[guid];
+ this.numHandlers--;
+ if (this.numHandlers === 0) {
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+ var fireArgs = Array.prototype.slice.call(arguments);
+ // Apply stickiness.
+ if (this.state === 1) {
+ this.state = 2;
+ this.fireArgs = fireArgs;
+ }
+ if (this.numHandlers) {
+ // Copy the values first so that it is safe to modify it from within
+ // callbacks.
+ var toCall = [];
+ for (var item in this.handlers) {
+ toCall.push(this.handlers[item]);
+ }
+ for (var i = 0; i < toCall.length; ++i) {
+ toCall[i].apply(this, fireArgs);
+ }
+ if (this.state === 2 && this.numHandlers) {
+ this.numHandlers = 0;
+ this.handlers = {};
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: ../cordova-android/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/**
+ * Execute a cordova command. It is up to the native side whether this action
+ * is synchronous or asynchronous. The native side can return:
+ * Synchronous: PluginResult object as a JSON string
+ * Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success The success callback
+ * @param {Function} fail The fail callback
+ * @param {String} service The name of the service to use
+ * @param {String} action Action to be run in cordova
+ * @param {String[]} [args] Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova');
+var nativeApiProvider = require('cordova/android/nativeapiprovider');
+var utils = require('cordova/utils');
+var base64 = require('cordova/base64');
+var channel = require('cordova/channel');
+var jsToNativeModes = {
+ PROMPT: 0,
+ JS_OBJECT: 1
+};
+var nativeToJsModes = {
+ // Polls for messages using the JS->Native bridge.
+ POLLING: 0,
+ // For LOAD_URL to be viable, it would need to have a work-around for
+ // the bug where the soft-keyboard gets dismissed when a message is sent.
+ LOAD_URL: 1,
+ // For the ONLINE_EVENT to be viable, it would need to intercept all event
+ // listeners (both through addEventListener and window.ononline) as well
+ // as set the navigator property itself.
+ ONLINE_EVENT: 2,
+ EVAL_BRIDGE: 3
+};
+var jsToNativeBridgeMode; // Set lazily.
+var nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE;
+var pollEnabled = false;
+var bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise === 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function (fn) { resolvedPromise.then(fn); } : function (fn) { setTimeout(fn); };
+
+function androidExec (success, fail, service, action, args) {
+ if (bridgeSecret < 0) {
+ // If we ever catch this firing, we'll need to queue up exec()s
+ // and fire them once we get a secret. For now, I don't think
+ // it's possible for exec() to be called since plugins are parsed but
+ // not run until until after onNativeReady.
+ throw new Error('exec() called without bridgeSecret');
+ }
+ // Set default bridge modes if they have not already been set.
+ // By default, we use the failsafe, since addJavascriptInterface breaks too often
+ if (jsToNativeBridgeMode === undefined) {
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+ }
+
+ // If args is not provided, default to an empty array
+ args = args || [];
+
+ // Process any ArrayBuffers in the args into a string.
+ for (var i = 0; i < args.length; i++) {
+ if (utils.typeName(args[i]) === 'ArrayBuffer') {
+ args[i] = base64.fromArrayBuffer(args[i]);
+ }
+ }
+
+ var callbackId = service + cordova.callbackId++;
+ var argsJson = JSON.stringify(args);
+ if (success || fail) {
+ cordova.callbacks[callbackId] = { success: success, fail: fail };
+ }
+
+ var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+ // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+ // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
+ if (jsToNativeBridgeMode === jsToNativeModes.JS_OBJECT && msgs === '@Null arguments.') {
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+ androidExec(success, fail, service, action, args);
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+ } else if (msgs) {
+ messagesFromNative.push(msgs);
+ // Always process async to avoid exceptions messing up stack.
+ nextTick(processMessages);
+ }
+}
+
+androidExec.init = function () {
+ bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+ channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent () {
+ pollOnce(true);
+}
+
+function pollOnce (opt_fromOnlineEvent) {
+ if (bridgeSecret < 0) {
+ // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+ // We know there's nothing to retrieve, so no need to poll.
+ return;
+ }
+ var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+ if (msgs) {
+ messagesFromNative.push(msgs);
+ // Process sync since we know we're already top-of-stack.
+ processMessages();
+ }
+}
+
+function pollingTimerFunc () {
+ if (pollEnabled) {
+ pollOnce();
+ setTimeout(pollingTimerFunc, 50);
+ }
+}
+
+function hookOnlineApis () {
+ function proxyEvent (e) {
+ cordova.fireWindowEvent(e.type);
+ }
+ // The network module takes care of firing online and offline events.
+ // It currently fires them only on document though, so we bridge them
+ // to window here (while first listening for exec()-releated online/offline
+ // events).
+ window.addEventListener('online', pollOnceFromOnlineEvent, false);
+ window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+ cordova.addWindowEventHandler('online');
+ cordova.addWindowEventHandler('offline');
+ document.addEventListener('online', proxyEvent, false);
+ document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function (mode) {
+ if (mode === jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+ mode = jsToNativeModes.PROMPT;
+ }
+ nativeApiProvider.setPreferPrompt(mode === jsToNativeModes.PROMPT);
+ jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function (mode) {
+ if (mode === nativeToJsBridgeMode) {
+ return;
+ }
+ if (nativeToJsBridgeMode === nativeToJsModes.POLLING) {
+ pollEnabled = false;
+ }
+
+ nativeToJsBridgeMode = mode;
+ // Tell the native side to switch modes.
+ // Otherwise, it will be set by androidExec.init()
+ if (bridgeSecret >= 0) {
+ nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+ }
+
+ if (mode === nativeToJsModes.POLLING) {
+ pollEnabled = true;
+ setTimeout(pollingTimerFunc, 1);
+ }
+};
+
+function buildPayload (payload, message) {
+ var payloadKind = message.charAt(0);
+ if (payloadKind === 's') {
+ payload.push(message.slice(1));
+ } else if (payloadKind === 't') {
+ payload.push(true);
+ } else if (payloadKind === 'f') {
+ payload.push(false);
+ } else if (payloadKind === 'N') {
+ payload.push(null);
+ } else if (payloadKind === 'n') {
+ payload.push(+message.slice(1));
+ } else if (payloadKind === 'A') {
+ var data = message.slice(1);
+ payload.push(base64.toArrayBuffer(data));
+ } else if (payloadKind === 'S') {
+ payload.push(window.atob(message.slice(1)));
+ } else if (payloadKind === 'M') {
+ var multipartMessages = message.slice(1);
+ while (multipartMessages !== '') {
+ var spaceIdx = multipartMessages.indexOf(' ');
+ var msgLen = +multipartMessages.slice(0, spaceIdx);
+ var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+ multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+ buildPayload(payload, multipartMessage);
+ }
+ } else {
+ payload.push(JSON.parse(message));
+ }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage (message) {
+ var firstChar = message.charAt(0);
+ if (firstChar === 'J') {
+ // This is deprecated on the .java side. It doesn't work with CSP enabled.
+ // eslint-disable-next-line no-eval
+ eval(message.slice(1));
+ } else if (firstChar === 'S' || firstChar === 'F') {
+ var success = firstChar === 'S';
+ var keepCallback = message.charAt(1) === '1';
+ var spaceIdx = message.indexOf(' ', 2);
+ var status = +message.slice(2, spaceIdx);
+ var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+ var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+ var payloadMessage = message.slice(nextSpaceIdx + 1);
+ var payload = [];
+ buildPayload(payload, payloadMessage);
+ cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+ } else {
+ console.log('processMessage failed: invalid message: ' + JSON.stringify(message));
+ }
+}
+
+function processMessages () {
+ // Check for the reentrant case.
+ if (isProcessing) {
+ return;
+ }
+ if (messagesFromNative.length === 0) {
+ return;
+ }
+ isProcessing = true;
+ try {
+ var msg = popMessageFromQueue();
+ // The Java side can send a * message to indicate that it
+ // still has messages waiting to be retrieved.
+ if (msg === '*' && messagesFromNative.length === 0) {
+ nextTick(pollOnce);
+ return;
+ }
+ processMessage(msg);
+ } finally {
+ isProcessing = false;
+ if (messagesFromNative.length > 0) {
+ nextTick(processMessages);
+ }
+ }
+}
+
+function popMessageFromQueue () {
+ var messageBatch = messagesFromNative.shift();
+ if (messageBatch === '*') {
+ return '*';
+ }
+
+ var spaceIdx = messageBatch.indexOf(' ');
+ var msgLen = +messageBatch.slice(0, spaceIdx);
+ var message = messageBatch.substr(spaceIdx + 1, msgLen);
+ messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+ if (messageBatch) {
+ messagesFromNative.unshift(messageBatch);
+ }
+ return message;
+}
+
+module.exports = androidExec;
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+ // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+ add: function (id, proxyObj) {
+ console.log('adding proxy for ' + id);
+ CommandProxyMap[id] = proxyObj;
+ return proxyObj;
+ },
+
+ // cordova.commandProxy.remove("Accelerometer");
+ remove: function (id) {
+ var proxy = CommandProxyMap[id];
+ delete CommandProxyMap[id];
+ CommandProxyMap[id] = null;
+ return proxy;
+ },
+
+ get: function (service, action) {
+ return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+ }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+ for (var i = 0; i < arr.length; ++i) {
+ if (arr[i].state !== 2) {
+ console.log('Channel not fired: ' + arr[i].type);
+ }
+ }
+}
+
+window.setTimeout(function () {
+ if (channel.onDeviceReady.state !== 2) {
+ console.log('deviceready has not fired after 5 seconds.');
+ logUnfiredChannels(platformInitChannelsArray);
+ logUnfiredChannels(channel.deviceReadyChannelsArray);
+ }
+}, 5000);
+
+if (!window.console) {
+ window.console = {
+ log: function () {}
+ };
+}
+if (!window.console.warn) {
+ window.console.warn = function (msg) {
+ this.log('warn: ' + msg);
+ };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+ channel.onDOMContentLoaded.fire();
+} else {
+ document.addEventListener('DOMContentLoaded', function () {
+ channel.onDOMContentLoaded.fire();
+ }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+ channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+ pluginloader.load(function () {
+ channel.onPluginsReady.fire();
+ });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+ modulemapper.mapModules(window);
+
+ platform.initialize && platform.initialize();
+
+ // Fire event to notify that all objects are created
+ channel.onCordovaReady.fire();
+
+ // Fire onDeviceReady event once page has fully loaded, all
+ // constructors have run and cordova info has been received from native
+ // side.
+ channel.join(function () {
+ require('cordova').fireDocumentEvent('deviceready');
+ }, channel.deviceReadyChannelsArray);
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap;
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+ symbolList = [];
+ deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+ if (!(moduleName in moduleMap)) {
+ throw new Error('Module ' + moduleName + ' does not exist.');
+ }
+ symbolList.push(strategy, moduleName, symbolPath);
+ if (opt_deprecationMessage) {
+ deprecationMap[symbolPath] = opt_deprecationMessage;
+ }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+ addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+ if (!symbolPath) {
+ return context;
+ }
+ return symbolPath.split('.').reduce(function (cur, part) {
+ return (cur[part] = cur[part] || {});
+ }, context);
+}
+
+exports.mapModules = function (context) {
+ var origSymbols = {};
+ context.CDV_origSymbols = origSymbols;
+ for (var i = 0, len = symbolList.length; i < len; i += 3) {
+ var strategy = symbolList[i];
+ var moduleName = symbolList[i + 1];
+ var module = require(moduleName);
+ // <runs/>
+ if (strategy === 'r') {
+ continue;
+ }
+ var symbolPath = symbolList[i + 2];
+ var lastDot = symbolPath.lastIndexOf('.');
+ var namespace = symbolPath.substr(0, lastDot);
+ var lastName = symbolPath.substr(lastDot + 1);
+
+ var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+ var parentObj = prepareNamespace(namespace, context);
+ var target = parentObj[lastName];
+
+ if (strategy === 'm' && target) {
+ builder.recursiveMerge(target, module);
+ } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+ if (!(symbolPath in origSymbols)) {
+ origSymbols[symbolPath] = target;
+ }
+ builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+ }
+ }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+ var origSymbols = context.CDV_origSymbols;
+ if (origSymbols && (symbolPath in origSymbols)) {
+ return origSymbols[symbolPath];
+ }
+ var parts = symbolPath.split('.');
+ var obj = context;
+ for (var i = 0; i < parts.length; ++i) {
+ obj = obj && obj[parts[i]];
+ }
+ return obj;
+};
+
+exports.reset();
+
+});
+
+// file: ../cordova-android/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
+
+module.exports = {
+ id: 'android',
+ bootstrap: function () {
+ var channel = require('cordova/channel');
+ var cordova = require('cordova');
+ var exec = require('cordova/exec');
+ var modulemapper = require('cordova/modulemapper');
+
+ // Get the shared secret needed to use the bridge.
+ exec.init();
+
+ // TODO: Extract this as a proper plugin.
+ modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+
+ var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+ // Inject a listener for the backbutton on the document.
+ var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+ backButtonChannel.onHasSubscribersChange = function () {
+ // If we just attached the first handler or detached the last handler,
+ // let native know we need to override the back button.
+ exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [this.numHandlers === 1]);
+ };
+
+ // Add hardware MENU and SEARCH button handlers
+ cordova.addDocumentEventHandler('menubutton');
+ cordova.addDocumentEventHandler('searchbutton');
+
+ function bindButtonChannel (buttonName) {
+ // generic button bind used for volumeup/volumedown buttons
+ var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+ volumeButtonChannel.onHasSubscribersChange = function () {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [buttonName, this.numHandlers === 1]);
+ };
+ }
+ // Inject a listener for the volume buttons on the document.
+ bindButtonChannel('volumeup');
+ bindButtonChannel('volumedown');
+
+ // The resume event is not "sticky", but it is possible that the event
+ // will contain the result of a plugin call. We need to ensure that the
+ // plugin result is delivered even after the event is fired (CB-10498)
+ var cordovaAddEventListener = document.addEventListener;
+
+ document.addEventListener = function (evt, handler, capture) {
+ cordovaAddEventListener(evt, handler, capture);
+
+ if (evt === 'resume' && lastResumeEvent) {
+ handler(lastResumeEvent);
+ }
+ };
+
+ // Let native code know we are all done on the JS side.
+ // Native code will then un-hide the WebView.
+ channel.onCordovaReady.subscribe(function () {
+ exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+ exec(null, null, APP_PLUGIN_NAME, 'show', []);
+ });
+ }
+};
+
+function onMessageFromNative (msg) {
+ var cordova = require('cordova');
+ var action = msg.action;
+
+ switch (action) {
+ // pause and resume are Android app life cycle events
+ case 'backbutton':
+ case 'menubutton':
+ case 'searchbutton':
+ case 'pause':
+ case 'volumedownbutton':
+ case 'volumeupbutton':
+ cordova.fireDocumentEvent(action);
+ break;
+ case 'resume':
+ if (arguments.length > 1 && msg.pendingResult) {
+ if (arguments.length === 2) {
+ msg.pendingResult.result = arguments[1];
+ } else {
+ // The plugin returned a multipart message
+ var res = [];
+ for (var i = 1; i < arguments.length; i++) {
+ res.push(arguments[i]);
+ }
+ msg.pendingResult.result = res;
+ }
+
+ // Save the plugin result so that it can be delivered to the js
+ // even if they miss the initial firing of the event
+ lastResumeEvent = msg;
+ }
+ cordova.fireDocumentEvent(action, msg);
+ break;
+ default:
+ throw new Error('Unknown event action ' + action);
+ }
+}
+
+});
+
+// file: ../cordova-android/cordova-js-src/plugin/android/app.js
+define("cordova/plugin/android/app", function(require, exports, module) {
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+ /**
+ * Clear the resource cache.
+ */
+ clearCache: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'clearCache', []);
+ },
+
+ /**
+ * Load the url into the webview or into new browser instance.
+ *
+ * @param url The URL to load
+ * @param props Properties that can be passed in to the activity:
+ * wait: int => wait msec before loading URL
+ * loadingDialog: "Title,Message" => display a native loading dialog
+ * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
+ * clearHistory: boolean => clear webview history (default=false)
+ * openExternal: boolean => open in a new browser (default=false)
+ *
+ * Example:
+ * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+ */
+ loadUrl: function (url, props) {
+ exec(null, null, APP_PLUGIN_NAME, 'loadUrl', [url, props]);
+ },
+
+ /**
+ * Cancel loadUrl that is waiting to be loaded.
+ */
+ cancelLoadUrl: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'cancelLoadUrl', []);
+ },
+
+ /**
+ * Clear web history in this web view.
+ * Instead of BACK button loading the previous web page, it will exit the app.
+ */
+ clearHistory: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'clearHistory', []);
+ },
+
+ /**
+ * Go to previous page displayed.
+ * This is the same as pressing the backbutton on Android device.
+ */
+ backHistory: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'backHistory', []);
+ },
+
+ /**
+ * Override the default behavior of the Android back button.
+ * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+ *
+ * Note: The user should not have to call this method. Instead, when the user
+ * registers for the "backbutton" event, this is automatically done.
+ *
+ * @param override T=override, F=cancel override
+ */
+ overrideBackbutton: function (override) {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [override]);
+ },
+
+ /**
+ * Override the default behavior of the Android volume button.
+ * If overridden, when the volume button is pressed, the "volume[up|down]button"
+ * JavaScript event will be fired.
+ *
+ * Note: The user should not have to call this method. Instead, when the user
+ * registers for the "volume[up|down]button" event, this is automatically done.
+ *
+ * @param button volumeup, volumedown
+ * @param override T=override, F=cancel override
+ */
+ overrideButton: function (button, override) {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [button, override]);
+ },
+
+ /**
+ * Exit and terminate the application.
+ */
+ exitApp: function () {
+ return exec(null, null, APP_PLUGIN_NAME, 'exitApp', []);
+ }
+};
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+ var script = document.createElement('script');
+ // onload fires even when script fails loads with an error.
+ script.onload = onload;
+ // onerror fires for malformed URLs.
+ script.onerror = onerror;
+ script.src = url;
+ document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+ onerror = onerror || onload;
+ if (id in define.moduleMap) {
+ onload();
+ } else {
+ exports.injectScript(url, function () {
+ if (id in define.moduleMap) {
+ onload();
+ } else {
+ onerror();
+ }
+ }, onerror);
+ }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+ // Loop through all the plugins and then through their clobbers and merges.
+ for (var i = 0, module; (module = moduleList[i]); i++) {
+ if (module.clobbers && module.clobbers.length) {
+ for (var j = 0; j < module.clobbers.length; j++) {
+ modulemapper.clobbers(module.id, module.clobbers[j]);
+ }
+ }
+
+ if (module.merges && module.merges.length) {
+ for (var k = 0; k < module.merges.length; k++) {
+ modulemapper.merges(module.id, module.merges[k]);
+ }
+ }
+
+ // Finally, if runs is truthy we want to simply require() the module.
+ if (module.runs) {
+ modulemapper.runs(module.id);
+ }
+ }
+
+ finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+ // Now inject the scripts.
+ var scriptCounter = moduleList.length;
+
+ if (!scriptCounter) {
+ finishPluginLoading();
+ return;
+ }
+ function scriptLoadedCallback () {
+ if (!--scriptCounter) {
+ onScriptLoadingComplete(moduleList, finishPluginLoading);
+ }
+ }
+
+ for (var i = 0; i < moduleList.length; i++) {
+ injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+ }
+}
+
+function findCordovaPath () {
+ var path = null;
+ var scripts = document.getElementsByTagName('script');
+ var term = '/cordova.js';
+ for (var n = scripts.length - 1; n > -1; n--) {
+ var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+ if (src.indexOf(term) === (src.length - term.length)) {
+ path = src.substring(0, src.length - term.length) + '/';
+ break;
+ }
+ }
+ return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+ var pathPrefix = findCordovaPath();
+ if (pathPrefix === null) {
+ console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+ pathPrefix = '';
+ }
+ injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+ var moduleList = require('cordova/plugin_list');
+ handlePluginsObject(pathPrefix, moduleList, callback);
+ }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+ var anchorEl = document.createElement('a');
+ anchorEl.href = url;
+ return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+ if (Object.defineProperty) {
+ var desc = {
+ get: getFunc,
+ configurable: true
+ };
+ if (opt_setFunc) {
+ desc.set = opt_setFunc;
+ }
+ Object.defineProperty(obj, key, desc);
+ } else {
+ obj.__defineGetter__(key, getFunc);
+ if (opt_setFunc) {
+ obj.__defineSetter__(key, opt_setFunc);
+ }
+ }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+ if (a.indexOf) {
+ return a.indexOf(item);
+ }
+ var len = a.length;
+ for (var i = 0; i < len; ++i) {
+ if (a[i] === item) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+ var index = utils.arrayIndexOf(a, item);
+ if (index !== -1) {
+ a.splice(index, 1);
+ }
+ return index !== -1;
+};
+
+utils.typeName = function (val) {
+ return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+ function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+ return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+ if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+ return obj;
+ }
+
+ var retVal, i;
+
+ if (utils.isArray(obj)) {
+ retVal = [];
+ for (i = 0; i < obj.length; ++i) {
+ retVal.push(utils.clone(obj[i]));
+ }
+ return retVal;
+ }
+
+ retVal = {};
+ for (i in obj) {
+ // 'unknown' type may be returned in custom protocol activation case on
+ // Windows Phone 8.1 causing "No such interface supported" exception on
+ // cloning (https://issues.apache.org/jira/browse/CB-11522)
+ // eslint-disable-next-line valid-typeof
+ if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') {
+ retVal[i] = utils.clone(obj[i]);
+ }
+ }
+ return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+ return function () {
+ var args = params || arguments;
+ return func.apply(context, args);
+ };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+ var uuidpart = '';
+ for (var i = 0; i < length; i++) {
+ var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+ if (uuidchar.length === 1) {
+ uuidchar = '0' + uuidchar;
+ }
+ uuidpart += uuidchar;
+ }
+ return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+ return UUIDcreatePart(4) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+ // proxy used to establish prototype chain
+ var F = function () {};
+ // extend Child from Parent
+ return function (Child, Parent) {
+ F.prototype = Parent.prototype;
+ Child.prototype = new F();
+ Child.__super__ = Parent.prototype;
+ Child.prototype.constructor = Child;
+ };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+ if (window.alert) {
+ window.alert(msg);
+ } else if (console && console.log) {
+ console.log(msg);
+ }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+require('cordova/init');
+
+})();
--- /dev/null
+cordova.define('cordova/plugin_list', function(require, exports, module) {
+ module.exports = [
+ {
+ "id": "cordova-plugin-device.device",
+ "file": "plugins/cordova-plugin-device/www/device.js",
+ "pluginId": "cordova-plugin-device",
+ "clobbers": [
+ "device"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.DirectoryEntry",
+ "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.DirectoryEntry"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.DirectoryReader",
+ "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.DirectoryReader"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.Entry",
+ "file": "plugins/cordova-plugin-file/www/Entry.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Entry"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.File",
+ "file": "plugins/cordova-plugin-file/www/File.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.File"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileEntry",
+ "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileEntry"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileError",
+ "file": "plugins/cordova-plugin-file/www/FileError.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileError"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileReader",
+ "file": "plugins/cordova-plugin-file/www/FileReader.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileReader"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileSystem",
+ "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileSystem"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileUploadOptions",
+ "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileUploadOptions"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileUploadResult",
+ "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileUploadResult"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileWriter",
+ "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileWriter"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.Flags",
+ "file": "plugins/cordova-plugin-file/www/Flags.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Flags"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.LocalFileSystem",
+ "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.LocalFileSystem"
+ ],
+ "merges": [
+ "window"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.Metadata",
+ "file": "plugins/cordova-plugin-file/www/Metadata.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Metadata"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.ProgressEvent",
+ "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.ProgressEvent"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.fileSystems",
+ "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+ "pluginId": "cordova-plugin-file"
+ },
+ {
+ "id": "cordova-plugin-file.requestFileSystem",
+ "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.requestFileSystem"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+ "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "window"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.isChrome",
+ "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "id": "cordova-plugin-file.androidFileSystem",
+ "file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "FileSystem"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.fileSystems-roots",
+ "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "id": "cordova-plugin-file.fileSystemPaths",
+ "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "cordova"
+ ],
+ "runs": true
+ },
+ {
+ "id": "es6-promise-plugin.Promise",
+ "file": "plugins/es6-promise-plugin/www/promise.js",
+ "pluginId": "es6-promise-plugin",
+ "runs": true
+ },
+ {
+ "id": "cordova-plugin-screen-orientation.screenorientation",
+ "file": "plugins/cordova-plugin-screen-orientation/www/screenorientation.js",
+ "pluginId": "cordova-plugin-screen-orientation",
+ "clobbers": [
+ "cordova.plugins.screenorientation"
+ ]
+ },
+ {
+ "id": "cordova-plugin-statusbar.statusbar",
+ "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+ "pluginId": "cordova-plugin-statusbar",
+ "clobbers": [
+ "window.StatusBar"
+ ]
+ },
+ {
+ "id": "com-darryncampbell-cordova-plugin-intent.IntentShim",
+ "file": "plugins/com-darryncampbell-cordova-plugin-intent/www/IntentShim.js",
+ "pluginId": "com-darryncampbell-cordova-plugin-intent",
+ "clobbers": [
+ "intentShim"
+ ]
+ }
+ ];
+ module.exports.metadata = {
+ "cordova-plugin-whitelist": "1.3.4",
+ "cordova-plugin-device": "2.0.3",
+ "cordova-plugin-file": "6.0.2",
+ "es6-promise-plugin": "4.2.2",
+ "cordova-plugin-screen-orientation": "3.0.2",
+ "cordova-plugin-statusbar": "2.4.3",
+ "com-darryncampbell-cordova-plugin-intent": "2.0.0"
+ };
+});
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ */
+* {
+ -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
+}
+
+body {
+ -webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */
+ -webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */
+ -webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */
+ background-color:#E4E4E4;
+ background-image:linear-gradient(to bottom, #A7A7A7 0%, #E4E4E4 51%);
+ font-family: system-ui, -apple-system, -apple-system-font, 'Segoe UI', 'Roboto', sans-serif;
+ font-size:12px;
+ height:100vh;
+ margin:0px;
+ padding:0px;
+ /* Padding to avoid the "unsafe" areas behind notches in the screen */
+ padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
+ text-transform:uppercase;
+ width:100%;
+}
+
+/* Portrait layout (default) */
+.app {
+ background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
+ position:absolute; /* position in the center of the screen */
+ left:50%;
+ top:50%;
+ height:50px; /* text area height */
+ width:225px; /* text area width */
+ text-align:center;
+ padding:180px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */
+ margin:-115px 0px 0px -112px; /* offset vertical: half of image height and text area height */
+ /* offset horizontal: half of text area width */
+}
+
+/* Landscape layout (with min-width) */
+@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
+ .app {
+ background-position:left center;
+ padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */
+ margin:-90px 0px 0px -198px; /* offset vertical: half of image height */
+ /* offset horizontal: half of image width and text area width */
+ }
+}
+
+h1 {
+ font-size:24px;
+ font-weight:normal;
+ margin:0px;
+ overflow:visible;
+ padding:0px;
+ text-align:center;
+}
+
+.event {
+ border-radius:4px;
+ color:#FFFFFF;
+ font-size:12px;
+ margin:0px 30px;
+ padding:2px 0px;
+}
+
+.event.listening {
+ background-color:#333333;
+ display:block;
+}
+
+.event.received {
+ background-color:#4B946A;
+ display:none;
+}
+
+#deviceready.ready .event.listening { display: none; }
+#deviceready.ready .event.received { display: block; }
+
+@keyframes fade {
+ from { opacity: 1.0; }
+ 50% { opacity: 0.4; }
+ to { opacity: 1.0; }
+}
+
+.blink {
+ animation:fade 3000ms infinite;
+ -webkit-animation:fade 3000ms infinite;
+}
+
+
+@media screen and (prefers-color-scheme: dark) {
+ body {
+ background-image:linear-gradient(to bottom, #585858 0%, #1B1B1B 51%);
+ }
+}
--- /dev/null
+<!DOCTYPE html>
+<!--
+ 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.
+-->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <!--
+ Customize this policy to fit your own app's needs. For more guidance, see:
+ https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
+ Some notes:
+ * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
+ * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
+ * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
+ * Enable inline JS: add 'unsafe-inline' to default-src
+ -->
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
+ <meta name="format-detection" content="telephone=no">
+ <meta name="msapplication-tap-highlight" content="no">
+ <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
+ <meta name="color-scheme" content="light dark">
+ <link rel="stylesheet" href="css/index.css">
+ <title>Hello World</title>
+ </head>
+ <body>
+ <div class="app">
+ <h1>Apache Cordova</h1>
+ <div id="deviceready" class="blink">
+ <p class="event listening">Connecting to Device</p>
+ <p class="event received">Device is Ready</p>
+ </div>
+ </div>
+ <script src="cordova.js"></script>
+ <script src="js/index.js"></script>
+ </body>
+</html>
--- /dev/null
+/*
+ * 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.
+ */
+
+// Wait for the deviceready event before using any of Cordova's device APIs.
+// See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready
+document.addEventListener('deviceready', onDeviceReady, false);
+
+function onDeviceReady() {
+ // Cordova is now initialized. Have fun!
+
+ console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
+ document.getElementById('deviceready').classList.add('ready');
+}
--- /dev/null
+cordova.define("com-darryncampbell-cordova-plugin-intent.IntentShim", function(require, exports, module) {
+var argscheck = require('cordova/argscheck'),
+ channel = require('cordova/channel'),
+ utils = require('cordova/utils'),
+ exec = require('cordova/exec'),
+ cordova = require('cordova');
+
+
+/**
+ * This represents a thin shim layer over the Android Intent implementation
+ * @constructor
+ */
+function IntentShim() {
+ var me = this;
+}
+
+IntentShim.prototype.ACTION_SEND = "android.intent.action.SEND";
+IntentShim.prototype.ACTION_VIEW= "android.intent.action.VIEW";
+IntentShim.prototype.ACTION_INSTALL_PACKAGE="android.intent.action.INSTALL_PACKAGE";
+IntentShim.prototype.ACTION_UNINSTALL_PACKAGE= "android.intent.action.UNINSTALL_PACKAGE";
+IntentShim.prototype.EXTRA_TEXT = "android.intent.extra.TEXT";
+IntentShim.prototype.EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
+IntentShim.prototype.EXTRA_STREAM = "android.intent.extra.STREAM";
+IntentShim.prototype.EXTRA_EMAIL = "android.intent.extra.EMAIL";
+IntentShim.prototype.ACTION_CALL = "android.intent.action.CALL";
+IntentShim.prototype.ACTION_SENDTO = "android.intent.action.SENDTO";
+// StartActivityForResult
+IntentShim.prototype.ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT";
+IntentShim.prototype.ACTION_PICK = "android.intent.action.PICK";
+IntentShim.prototype.RESULT_CANCELED = 0; // Activity.RESULT_CANCELED
+IntentShim.prototype.RESULT_OK = -1; // Activity.RESULT_OK
+
+IntentShim.prototype.startActivity = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.startActivity', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "startActivity", [params]);
+};
+
+IntentShim.prototype.startActivityForResult = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.startActivityForResult', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "startActivityForResult", [params]);
+};
+
+IntentShim.prototype.sendBroadcast = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.sendBroadcast', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "sendBroadcast", [params]);
+};
+
+IntentShim.prototype.startService = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.startService', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "startService", [params]);
+};
+
+IntentShim.prototype.registerBroadcastReceiver = function(params, callback) {
+ argscheck.checkArgs('of', 'IntentShim.registerBroadcastReceiver', arguments);
+ exec(callback, null, "IntentShim", "registerBroadcastReceiver", [params]);
+};
+
+IntentShim.prototype.unregisterBroadcastReceiver = function() {
+ argscheck.checkArgs('', 'IntentShim.unregisterBroadcastReceiver', arguments);
+ exec(null, null, "IntentShim", "unregisterBroadcastReceiver", []);
+};
+
+IntentShim.prototype.onIntent = function(callback) {
+ argscheck.checkArgs('f', 'IntentShim.onIntent', arguments);
+ exec(callback, null, "IntentShim", "onIntent", [callback]);
+};
+
+IntentShim.prototype.onActivityResult = function(callback) {
+ argscheck.checkArgs('f', 'IntentShim.onActivityResult', arguments);
+ exec(callback, null, "IntentShim", "onActivityResult", [callback]);
+};
+
+IntentShim.prototype.getIntent = function(successCallback, failureCallback) {
+ argscheck.checkArgs('ff', 'IntentShim.getIntent', arguments);
+ exec(successCallback, failureCallback, "IntentShim", "getIntent", []);
+};
+
+IntentShim.prototype.sendResult = function(params, callback) {
+ argscheck.checkArgs('of', 'IntentShim.sendResult', arguments);
+ exec(callback, null, "IntentShim", "sendResult", [params]);
+}
+
+IntentShim.prototype.realPathFromUri = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.realPathFromUri', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "realPathFromUri", [params]);
+};
+
+window.intentShim = new IntentShim();
+window.plugins = window.plugins || {};
+window.plugins.intentShim = window.intentShim;
+});
--- /dev/null
+cordova.define("cordova-plugin-device.device", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+ this.available = false;
+ this.platform = null;
+ this.version = null;
+ this.uuid = null;
+ this.cordova = null;
+ this.model = null;
+ this.manufacturer = null;
+ this.isVirtual = null;
+ this.serial = null;
+
+ var me = this;
+
+ channel.onCordovaReady.subscribe(function () {
+ me.getInfo(function (info) {
+ // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+ // TODO: CB-5105 native implementations should not return info.cordova
+ var buildLabel = cordova.version;
+ me.available = true;
+ me.platform = info.platform;
+ me.version = info.version;
+ me.uuid = info.uuid;
+ me.cordova = buildLabel;
+ me.model = info.model;
+ me.isVirtual = info.isVirtual;
+ me.manufacturer = info.manufacturer || 'unknown';
+ me.serial = info.serial || 'unknown';
+ channel.onCordovaInfoReady.fire();
+ }, function (e) {
+ me.available = false;
+ utils.alert('[ERROR] Error initializing Cordova: ' + e);
+ });
+ });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+ argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+ exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileError = require('./FileError');
+var DirectoryReader = require('./DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) {
+
+ // add trailing slash if it is missing
+ if ((fullPath) && !/\/$/.test(fullPath)) {
+ fullPath += '/';
+ }
+ // add trailing slash if it is missing
+ if (nativeURL && !/\/$/.test(nativeURL)) {
+ nativeURL += '/';
+ }
+ DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function () {
+ return new DirectoryReader(this.toInternalURL());
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
+ argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
+ argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var FileEntry = require('./FileEntry');
+ var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader (localURL) {
+ this.localURL = localURL || null;
+ this.hasReadEntries = false;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
+ // If we've already read and passed on this directory's entries, return an empty list.
+ if (this.hasReadEntries) {
+ successCallback([]);
+ return;
+ }
+ var reader = this;
+ var win = typeof successCallback !== 'function' ? null : function (result) {
+ var retVal = [];
+ for (var i = 0; i < result.length; i++) {
+ var entry = null;
+ if (result[i].isDirectory) {
+ entry = new (require('./DirectoryEntry'))();
+ } else if (result[i].isFile) {
+ entry = new (require('./FileEntry'))();
+ }
+ entry.isDirectory = result[i].isDirectory;
+ entry.isFile = result[i].isFile;
+ entry.name = result[i].name;
+ entry.fullPath = result[i].fullPath;
+ entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
+ entry.nativeURL = result[i].nativeURL;
+ retVal.push(entry);
+ }
+ reader.hasReadEntries = true;
+ successCallback(retVal);
+ };
+ var fail = typeof errorCallback !== 'function' ? null : function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'readEntries', [this.localURL]);
+};
+
+module.exports = DirectoryReader;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var Metadata = require('./Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ * {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ * {boolean} true if Entry is a directory (readonly)
+ * @param name
+ * {DOMString} name of the file or directory, excluding the path
+ * leading to it (readonly)
+ * @param fullPath
+ * {DOMString} the absolute full path to the file or directory
+ * (readonly)
+ * @param fileSystem
+ * {FileSystem} the filesystem on which this entry resides
+ * (readonly)
+ * @param nativeURL
+ * {DOMString} an alternate URL which can be used by native
+ * webview controls, for example media players.
+ * (optional, readonly)
+ */
+function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
+ this.isFile = !!isFile;
+ this.isDirectory = !!isDirectory;
+ this.name = name || '';
+ this.fullPath = fullPath || '';
+ this.filesystem = fileSystem || null;
+ this.nativeURL = nativeURL || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ * {Function} is called with a Metadata object
+ * @param errorCallback
+ * {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+ var success = successCallback && function (entryMetadata) {
+ var metadata = new Metadata({
+ size: entryMetadata.size,
+ modificationTime: entryMetadata.lastModifiedDate
+ });
+ successCallback(metadata);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ * {Function} is called with a Metadata object
+ * @param errorCallback
+ * {Function} is called with a FileError
+ * @param metadataObject
+ * {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) {
+ argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+ exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ * {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ * {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ * {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ * {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
+ argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ var srcURL = this.toInternalURL();
+ // entry name
+ var name = newName || this.name;
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+ var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+ var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ }
+ } else {
+ // no Entry object returned
+ if (fail) {
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ }
+ };
+
+ // copy
+ exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ * {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ * {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ * {Function} called with the new Entry object
+ * @param errorCallback
+ * {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
+ argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ var srcURL = this.toInternalURL();
+ // entry name
+ var name = newName || this.name;
+ // success callback
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+ var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+ var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ }
+ } else {
+ // no Entry object returned
+ if (fail) {
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ }
+ };
+
+ // copy
+ exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Return a URL that can be passed across the bridge to identify this entry.
+ */
+Entry.prototype.toInternalURL = function () {
+ if (this.filesystem && this.filesystem.__format__) {
+ return this.filesystem.__format__(this.fullPath, this.nativeURL);
+ }
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ * Use a URL that can be used to as the src attribute of a <video> or
+ * <audio> tag. If that is not possible, construct a cdvfile:// URL.
+ */
+Entry.prototype.toURL = function () {
+ if (this.nativeURL) {
+ return this.nativeURL;
+ }
+ // fullPath attribute may contain the full URL in the case that
+ // toInternalURL fails.
+ return this.toInternalURL() || 'file://localhost' + this.fullPath;
+};
+
+/**
+ * Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
+ * cdvfile:// URL, and this method was necessary to obtain URLs usable by the
+ * webview.
+ * See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
+ * and CB-6300.
+ */
+Entry.prototype.toNativeURL = function () {
+ console.log("DEPRECATED: Update your code to use 'toURL'");
+ return this.toURL();
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function (mimeType) {
+ console.log("DEPRECATED: Update your code to use 'toURL'");
+ return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.remove', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(successCallback, fail, 'File', 'remove', [this.toInternalURL()]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var DirectoryEntry = require('./DirectoryEntry');
+ var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getParent', [this.toInternalURL()]);
+};
+
+module.exports = Entry;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.File", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function (name, localURL, type, lastModifiedDate, size) {
+ this.name = name || '';
+ this.localURL = localURL || null;
+ this.type = type || null;
+ this.lastModified = lastModifiedDate || null;
+ // For backwards compatibility, store the timestamp in lastModifiedDate as well
+ this.lastModifiedDate = lastModifiedDate || null;
+ this.size = size || 0;
+
+ // These store the absolute start and end for slicing the file.
+ this.start = 0;
+ this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function (start, end) {
+ var size = this.end - this.start;
+ var newStart = 0;
+ var newEnd = size;
+ if (arguments.length) {
+ if (start < 0) {
+ newStart = Math.max(size + start, 0);
+ } else {
+ newStart = Math.min(size, start);
+ }
+ }
+
+ if (arguments.length >= 2) {
+ if (end < 0) {
+ newEnd = Math.max(size + end, 0);
+ } else {
+ newEnd = Math.min(end, size);
+ }
+ }
+
+ var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
+ newFile.start = this.start + newStart;
+ newFile.end = this.start + newEnd;
+ return newFile;
+};
+
+module.exports = File;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileWriter = require('./FileWriter');
+var File = require('./File');
+var FileError = require('./FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function (name, fullPath, fileSystem, nativeURL) {
+ // remove trailing slash if it is present
+ if (fullPath && /\/$/.test(fullPath)) {
+ fullPath = fullPath.substring(0, fullPath.length - 1);
+ }
+ if (nativeURL && /\/$/.test(nativeURL)) {
+ nativeURL = nativeURL.substring(0, nativeURL.length - 1);
+ }
+
+ FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
+ this.file(function (filePointer) {
+ var writer = new FileWriter(filePointer);
+
+ if (writer.localURL === null || writer.localURL === '') {
+ if (errorCallback) {
+ errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+ }
+ } else {
+ if (successCallback) {
+ successCallback(writer);
+ }
+ }
+ }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function (successCallback, errorCallback) {
+ var localURL = this.toInternalURL();
+ var win = successCallback && function (f) {
+ var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
+ successCallback(file);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getFileMetadata', [localURL]);
+};
+
+module.exports = FileEntry;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileError
+ */
+function FileError (error) {
+ this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var modulemapper = require('cordova/modulemapper');
+var utils = require('cordova/utils');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+var origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ * The root directory is the root of the file system.
+ * To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function () {
+ this._readyState = 0;
+ this._error = null;
+ this._result = null;
+ this._progress = null;
+ this._localURL = '';
+ this._realReader = origFileReader ? new origFileReader() : {}; // eslint-disable-line new-cap
+};
+
+/**
+ * Defines the maximum size to read at a time via the native API. The default value is a compromise between
+ * minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
+ * (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
+ * OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
+ */
+FileReader.READ_CHUNK_SIZE = 256 * 1024;
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function () {
+ return this._localURL ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function () {
+ return this._localURL ? this._error : this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function () {
+ return this._localURL ? this._result : this._realReader.result;
+});
+
+function defineEvent (eventName) {
+ utils.defineGetterSetter(FileReader.prototype, eventName, function () {
+ return this._realReader[eventName] || null;
+ }, function (value) {
+ this._realReader[eventName] = value;
+ });
+}
+defineEvent('onloadstart'); // When the read starts.
+defineEvent('onprogress'); // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload'); // When the read has successfully completed.
+defineEvent('onerror'); // When the read has failed (see errors).
+defineEvent('onloadend'); // When the request has completed (either in success or failure).
+defineEvent('onabort'); // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead (reader, file) {
+ // Already loading something
+ if (reader.readyState === FileReader.LOADING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ reader._result = null;
+ reader._error = null;
+ reader._progress = 0;
+ reader._readyState = FileReader.LOADING;
+
+ if (typeof file.localURL === 'string') {
+ reader._localURL = file.localURL;
+ } else {
+ reader._localURL = '';
+ return true;
+ }
+
+ if (reader.onloadstart) {
+ reader.onloadstart(new ProgressEvent('loadstart', {target: reader}));
+ }
+}
+
+/**
+ * Callback used by the following read* functions to handle incremental or final success.
+ * Must be bound to the FileReader's this along with all but the last parameter,
+ * e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
+ * @param readType The name of the read function to call.
+ * @param encoding Text encoding, or null if this is not a text type read.
+ * @param offset Starting offset of the read.
+ * @param totalSize Total number of bytes or chars to read.
+ * @param accumulate A function that takes the callback result and accumulates it in this._result.
+ * @param r Callback result returned by the last read exec() call, or null to begin reading.
+ */
+function readSuccessCallback (readType, encoding, offset, totalSize, accumulate, r) {
+ if (this._readyState === FileReader.DONE) {
+ return;
+ }
+
+ var CHUNK_SIZE = FileReader.READ_CHUNK_SIZE;
+ if (readType === 'readAsDataURL') {
+ // Windows proxy does not support reading file slices as Data URLs
+ // so read the whole file at once.
+ CHUNK_SIZE = cordova.platformId === 'windows' ? totalSize : // eslint-disable-line no-undef
+ // Calculate new chunk size for data URLs to be multiply of 3
+ // Otherwise concatenated base64 chunks won't be valid base64 data
+ FileReader.READ_CHUNK_SIZE - (FileReader.READ_CHUNK_SIZE % 3) + 3;
+ }
+
+ if (typeof r !== 'undefined') {
+ accumulate(r);
+ this._progress = Math.min(this._progress + CHUNK_SIZE, totalSize);
+
+ if (typeof this.onprogress === 'function') {
+ this.onprogress(new ProgressEvent('progress', {loaded: this._progress, total: totalSize}));
+ }
+ }
+
+ if (typeof r === 'undefined' || this._progress < totalSize) {
+ var execArgs = [
+ this._localURL,
+ offset + this._progress,
+ offset + this._progress + Math.min(totalSize - this._progress, CHUNK_SIZE)];
+ if (encoding) {
+ execArgs.splice(1, 0, encoding);
+ }
+ exec(
+ readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
+ readFailureCallback.bind(this),
+ 'File', readType, execArgs);
+ } else {
+ this._readyState = FileReader.DONE;
+
+ if (typeof this.onload === 'function') {
+ this.onload(new ProgressEvent('load', {target: this}));
+ }
+
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+ }
+}
+
+/**
+ * Callback used by the following read* functions to handle errors.
+ * Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
+ */
+function readFailureCallback (e) {
+ if (this._readyState === FileReader.DONE) {
+ return;
+ }
+
+ this._readyState = FileReader.DONE;
+ this._result = null;
+ this._error = new FileError(e);
+
+ if (typeof this.onerror === 'function') {
+ this.onerror(new ProgressEvent('error', {target: this}));
+ }
+
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function () {
+ if (origFileReader && !this._localURL) {
+ return this._realReader.abort();
+ }
+ this._result = null;
+
+ if (this._readyState === FileReader.DONE || this._readyState === FileReader.EMPTY) {
+ return;
+ }
+
+ this._readyState = FileReader.DONE;
+
+ // If abort callback
+ if (typeof this.onabort === 'function') {
+ this.onabort(new ProgressEvent('abort', {target: this}));
+ }
+ // If load end callback
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file {File} File object containing file properties
+ * @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function (file, encoding) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsText(file, encoding);
+ }
+
+ // Default encoding is UTF-8
+ var enc = encoding || 'UTF-8';
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsText', enc, file.start, totalSize, function (r) {
+ if (this._progress === 0) {
+ this._result = '';
+ }
+ this._result += r;
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ * data:[<mediatype>][;base64],<data>
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsDataURL(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsDataURL', null, file.start, totalSize, function (r) {
+ var commaIndex = r.indexOf(',');
+ if (this._progress === 0) {
+ this._result = r;
+ } else {
+ this._result += r.substring(commaIndex + 1);
+ }
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsBinaryString(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsBinaryString', null, file.start, totalSize, function (r) {
+ if (this._progress === 0) {
+ this._result = '';
+ }
+ this._result += r;
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsArrayBuffer(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsArrayBuffer', null, file.start, totalSize, function (r) {
+ var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
+ resultArray.set(new Uint8Array(r), this._progress);
+ this._result = resultArray.buffer;
+ }.bind(this));
+};
+
+module.exports = FileReader;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var DirectoryEntry = require('./DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function (name, root) {
+ this.name = name;
+ if (root) {
+ this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
+ } else {
+ this.root = new DirectoryEntry(this.name, '/', this);
+ }
+};
+
+FileSystem.prototype.__format__ = function (fullPath, nativeUrl) {
+ return fullPath;
+};
+
+FileSystem.prototype.toJSON = function () {
+ return '<FileSystem: ' + this.name + '>';
+};
+
+// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
+FileSystem.encodeURIPath = function (path) {
+ // Because # is a valid filename character, it must be encoded to prevent part of the
+ // path from being parsed as a URI fragment.
+ return encodeURI(path).replace(/#/g, '%23');
+};
+
+module.exports = FileSystem;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Options to customize the HTTP request used to upload files.
+ * @constructor
+ * @param fileKey {String} Name of file request parameter.
+ * @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
+ * @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
+ * @param params {Object} Object with key: value params to send to the server.
+ * @param headers {Object} Keys are header names, values are header values. Multiple
+ * headers of the same name are not supported.
+ */
+var FileUploadOptions = function (fileKey, fileName, mimeType, params, headers, httpMethod) {
+ this.fileKey = fileKey || null;
+ this.fileName = fileName || null;
+ this.mimeType = mimeType || null;
+ this.params = params || null;
+ this.headers = headers || null;
+ this.httpMethod = httpMethod || null;
+};
+
+module.exports = FileUploadOptions;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileUploadResult
+ * @constructor
+ */
+module.exports = function FileUploadResult (size, code, content) {
+ this.bytesSent = size;
+ this.responseCode = code;
+ this.response = content;
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var FileReader = require('./FileReader');
+var ProgressEvent = require('./ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ * The root directory is the root of the file system.
+ * To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function (file) {
+ this.fileName = '';
+ this.length = 0;
+ if (file) {
+ this.localURL = file.localURL || file;
+ this.length = file.size || 0;
+ }
+ // default is to write at the beginning of the file
+ this.position = 0;
+
+ this.readyState = 0; // EMPTY
+
+ this.result = null;
+
+ // Error
+ this.error = null;
+
+ // Event handlers
+ this.onwritestart = null; // When writing starts
+ this.onprogress = null; // While writing the file, and reporting partial file data
+ this.onwrite = null; // When the write has successfully completed.
+ this.onwriteend = null; // When the request has completed (either in success or failure).
+ this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
+ this.onerror = null; // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function () {
+ // check for invalid state
+ if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // set error
+ this.error = new FileError(FileError.ABORT_ERR);
+
+ this.readyState = FileWriter.DONE;
+
+ // If abort callback
+ if (typeof this.onabort === 'function') {
+ this.onabort(new ProgressEvent('abort', {'target': this}));
+ }
+
+ // If write end callback
+ if (typeof this.onwriteend === 'function') {
+ this.onwriteend(new ProgressEvent('writeend', {'target': this}));
+ }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param data text or blob to be written
+ * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
+ */
+FileWriter.prototype.write = function (data, isPendingBlobReadResult) {
+
+ var that = this;
+ var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
+ /* eslint-disable no-undef */
+ var isProxySupportBlobNatively = (cordova.platformId === 'windows8' || cordova.platformId === 'windows');
+ var isBinary;
+
+ // Check to see if the incoming data is a blob
+ if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
+ var fileReader = new FileReader();
+ /* eslint-enable no-undef */
+ fileReader.onload = function () {
+ // Call this method again, with the arraybuffer as argument
+ FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
+ };
+ fileReader.onerror = function () {
+ // DONE state
+ that.readyState = FileWriter.DONE;
+
+ // Save error
+ that.error = this.error;
+
+ // If onerror callback
+ if (typeof that.onerror === 'function') {
+ that.onerror(new ProgressEvent('error', {'target': that}));
+ }
+
+ // If onwriteend callback
+ if (typeof that.onwriteend === 'function') {
+ that.onwriteend(new ProgressEvent('writeend', {'target': that}));
+ }
+ };
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ if (supportsBinary) {
+ fileReader.readAsArrayBuffer(data);
+ } else {
+ fileReader.readAsText(data);
+ }
+ return;
+ }
+
+ // Mark data type for safer transport over the binary bridge
+ isBinary = supportsBinary && (data instanceof ArrayBuffer);
+ if (isBinary && cordova.platformId === 'windowsphone') { // eslint-disable-line no-undef
+ // create a plain array, using the keys from the Uint8Array view so that we can serialize it
+ data = Array.apply(null, new Uint8Array(data));
+ }
+
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ var me = this;
+
+ // If onwritestart callback
+ if (typeof me.onwritestart === 'function') {
+ me.onwritestart(new ProgressEvent('writestart', {'target': me}));
+ }
+
+ // Write file
+ exec(
+ // Success callback
+ function (r) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // position always increases by bytes written because file would be extended
+ me.position += r;
+ // The length of the file is now where we are done writing.
+
+ me.length = me.position;
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // If onwrite callback
+ if (typeof me.onwrite === 'function') {
+ me.onwrite(new ProgressEvent('write', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ },
+ // Error callback
+ function (e) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Save error
+ me.error = new FileError(e);
+
+ // If onerror callback
+ if (typeof me.onerror === 'function') {
+ me.onerror(new ProgressEvent('error', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ }, 'File', 'write', [this.localURL, data, this.position, isBinary]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound. If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function (offset) {
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ if (!offset && offset !== 0) {
+ return;
+ }
+
+ // See back from end of file.
+ if (offset < 0) {
+ this.position = Math.max(offset + this.length, 0);
+ // Offset is bigger than file size so set position
+ // to the end of the file.
+ } else if (offset > this.length) {
+ this.position = this.length;
+ // Offset is between 0 and file size so set the position
+ // to start writing.
+ } else {
+ this.position = offset;
+ }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function (size) {
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ var me = this;
+
+ // If onwritestart callback
+ if (typeof me.onwritestart === 'function') {
+ me.onwritestart(new ProgressEvent('writestart', {'target': this}));
+ }
+
+ // Write file
+ exec(
+ // Success callback
+ function (r) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Update the length of the file
+ me.length = r;
+ me.position = Math.min(me.position, r);
+
+ // If onwrite callback
+ if (typeof me.onwrite === 'function') {
+ me.onwrite(new ProgressEvent('write', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ },
+ // Error callback
+ function (e) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Save error
+ me.error = new FileError(e);
+
+ // If onerror callback
+ if (typeof me.onerror === 'function') {
+ me.onerror(new ProgressEvent('error', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ }, 'File', 'truncate', [this.localURL, size]);
+};
+
+module.exports = FileWriter;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ *
+ * @param create
+ * {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ * {boolean} used with create; if true the command will fail if
+ * target path exists
+ */
+function Flags (create, exclusive) {
+ this.create = create || false;
+ this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+exports.TEMPORARY = 0;
+exports.PERSISTENT = 1;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Information about the state of the file or directory
+ *
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function (metadata) {
+ if (typeof metadata === 'object') {
+ this.modificationTime = new Date(metadata.modificationTime);
+ this.size = metadata.size || 0;
+ } else if (typeof metadata === 'undefined') {
+ this.modificationTime = null;
+ this.size = 0;
+ } else {
+ /* Backwards compatiblity with platforms that only return a timestamp */
+ this.modificationTime = new Date(metadata);
+ }
+};
+
+module.exports = Metadata;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function () {
+ /*
+ var createEvent = function(data) {
+ var event = document.createEvent('Events');
+ event.initEvent('ProgressEvent', false, false);
+ if (data) {
+ for (var i in data) {
+ if (data.hasOwnProperty(i)) {
+ event[i] = data[i];
+ }
+ }
+ if (data.target) {
+ // TODO: cannot call <some_custom_object>.dispatchEvent
+ // need to first figure out how to implement EventTarget
+ }
+ }
+ return event;
+ };
+ try {
+ var ev = createEvent({type:"abort",target:document});
+ return function ProgressEvent(type, data) {
+ data.type = type;
+ return createEvent(data);
+ };
+ } catch(e){
+ */
+ return function ProgressEvent (type, dict) {
+ this.type = type;
+ this.bubbles = false;
+ this.cancelBubble = false;
+ this.cancelable = false;
+ this.lengthComputable = false;
+ this.loaded = dict && dict.loaded ? dict.loaded : 0;
+ this.total = dict && dict.total ? dict.total : 0;
+ this.target = dict && dict.target ? dict.target : null;
+ };
+ // }
+})();
+
+module.exports = ProgressEvent;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.androidFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+FILESYSTEM_PROTOCOL = 'cdvfile'; // eslint-disable-line no-undef
+
+module.exports = {
+ __format__: function (fullPath, nativeUrl) {
+ var path;
+ var contentUrlMatch = /^content:\/\//.exec(nativeUrl);
+ if (contentUrlMatch) {
+ // When available, use the path from a native content URL, which was already encoded by Android.
+ // This is necessary because JavaScript's encodeURI() does not encode as many characters as
+ // Android, which can result in permission exceptions when the encoding of a content URI
+ // doesn't match the string for which permission was originally granted.
+ path = nativeUrl.substring(contentUrlMatch[0].length - 1);
+ } else {
+ path = FileSystem.encodeURIPath(fullPath); // eslint-disable-line no-undef
+ if (!/^\//.test(path)) {
+ path = '/' + path;
+ }
+
+ var m = /\?.*/.exec(nativeUrl);
+ if (m) {
+ path += m[0];
+ }
+ }
+
+ return FILESYSTEM_PROTOCOL + '://localhost/' + this.name + path; // eslint-disable-line no-undef
+ }
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+ */
+
+module.exports = function () {
+ // window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and
+ // possibly a good flag to indicate that we're running in Chrome
+ return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+
+exports.file = {
+ // Read-only directory where the application is installed.
+ applicationDirectory: null,
+ // Root of app's private writable storage
+ applicationStorageDirectory: null,
+ // Where to put app-specific data files.
+ dataDirectory: null,
+ // Cached files that should survive app restarts.
+ // Apps should not rely on the OS to delete files in here.
+ cacheDirectory: null,
+ // Android: the application space on external storage.
+ externalApplicationStorageDirectory: null,
+ // Android: Where to put app-specific data files on external storage.
+ externalDataDirectory: null,
+ // Android: the application cache on external storage.
+ externalCacheDirectory: null,
+ // Android: the external storage (SD card) root.
+ externalRootDirectory: null,
+ // iOS: Temp directory that the OS can clear at will.
+ tempDirectory: null,
+ // iOS: Holds app-specific files that should be synced (e.g. to iCloud).
+ syncedDataDirectory: null,
+ // iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
+ documentsDirectory: null,
+ // BlackBerry10: Files globally available to all apps
+ sharedDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function () {
+ function after (paths) {
+ for (var k in paths) {
+ exports.file[k] = paths[k];
+ }
+ channel.initializationComplete('onFileSystemPathsReady');
+ }
+ exec(after, null, 'File', 'requestAllPaths', []);
+});
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Map of fsName -> FileSystem.
+var fsMap = null;
+var FileSystem = require('./FileSystem');
+var exec = require('cordova/exec');
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+require('./fileSystems').getFs = function (name, callback) {
+ function success (response) {
+ fsMap = {};
+ for (var i = 0; i < response.length; ++i) {
+ var fsRoot = response[i];
+ if (fsRoot) {
+ var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
+ fsMap[fs.name] = fs;
+ }
+ }
+ callback(fsMap[name]);
+ }
+
+ if (fsMap) {
+ callback(fsMap[name]);
+ } else {
+ exec(success, null, 'File', 'requestAllFileSystems', []);
+ }
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+module.exports.getFs = function (name, callback) {
+ callback(null);
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+ // For browser platform: not all browsers use this file.
+ function checkBrowser () {
+ if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+ module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
+ return true;
+ }
+ return false;
+ }
+ if (checkBrowser()) {
+ return;
+ }
+
+ var argscheck = require('cordova/argscheck');
+ var FileError = require('./FileError');
+ var FileSystem = require('./FileSystem');
+ var exec = require('cordova/exec');
+ var fileSystems = require('./fileSystems');
+
+ /**
+ * Request a file system in which to store application data.
+ * @param type local file system type
+ * @param size indicates how much storage space, in bytes, the application expects to need
+ * @param successCallback invoked with a FileSystem object
+ * @param errorCallback invoked if error occurs retrieving file system
+ */
+ var requestFileSystem = function (type, size, successCallback, errorCallback) {
+ argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
+ var fail = function (code) {
+ if (errorCallback) {
+ errorCallback(new FileError(code));
+ }
+ };
+
+ if (type < 0) {
+ fail(FileError.SYNTAX_ERR);
+ } else {
+ // if successful, return a FileSystem object
+ var success = function (file_system) {
+ if (file_system) {
+ if (successCallback) {
+ fileSystems.getFs(file_system.name, function (fs) {
+ // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+ if (!fs) {
+ fs = new FileSystem(file_system.name, file_system.root);
+ }
+ successCallback(fs);
+ });
+ }
+ } else {
+ // no FileSystem object returned
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ };
+ exec(success, fail, 'File', 'requestFileSystem', [type, size]);
+ }
+ };
+
+ module.exports = requestFileSystem;
+})();
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+(function () {
+ // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
+ function checkBrowser () {
+ if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+ module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+ return true;
+ }
+ return false;
+ }
+ if (checkBrowser()) {
+ return;
+ }
+
+ var argscheck = require('cordova/argscheck');
+ var DirectoryEntry = require('./DirectoryEntry');
+ var FileEntry = require('./FileEntry');
+ var FileError = require('./FileError');
+ var exec = require('cordova/exec');
+ var fileSystems = require('./fileSystems');
+
+ /**
+ * Look up file system Entry referred to by local URI.
+ * @param {DOMString} uri URI referring to a local file or directory
+ * @param successCallback invoked with Entry object corresponding to URI
+ * @param errorCallback invoked if error occurs retrieving file system entry
+ */
+ module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function (uri, successCallback, errorCallback) {
+ argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
+ // error callback
+ var fail = function (error) {
+ if (errorCallback) {
+ errorCallback(new FileError(error));
+ }
+ };
+ // sanity check for 'not:valid:filename' or '/not:valid:filename'
+ // file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
+ if (!uri || uri.split(':').length > 2) {
+ setTimeout(function () {
+ fail(FileError.ENCODING_ERR);
+ }, 0);
+ return;
+ }
+ // if successful, return either a file or directory entry
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem === window.PERSISTENT ? 'persistent' : 'temporary'); // eslint-disable-line no-undef
+ fileSystems.getFs(fsName, function (fs) {
+ // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+ if (!fs) {
+ fs = new FileSystem(fsName, {name: '', fullPath: '/'}); // eslint-disable-line no-undef
+ }
+ var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ });
+ }
+ } else {
+ // no Entry object returned
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ };
+
+ exec(success, fail, 'File', 'resolveLocalFileSystemURI', [uri]);
+ };
+
+ module.exports.resolveLocalFileSystemURI = function () {
+ console.log('resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.');
+ module.exports.resolveLocalFileSystemURL.apply(this, arguments);
+ };
+})();
+
+});
--- /dev/null
+cordova.define("cordova-plugin-screen-orientation.screenorientation", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+ */
+var screenOrientation = {};
+if (!window.OrientationType) {
+ window.OrientationType = {
+ 'portrait-primary': 0,
+ 'portrait-secondary': 180,
+ 'landscape-primary': 90,
+ 'landscape-secondary': -90
+ };
+}
+if (!window.OrientationLockType) {
+ window.OrientationLockType = {
+ 'portrait-primary': 1,
+ 'portrait-secondary': 2,
+ 'landscape-primary': 4,
+ 'landscape-secondary': 8,
+ 'portrait': 3, // either portrait-primary or portrait-secondary.
+ 'landscape': 12, // either landscape-primary or landscape-secondary.
+ 'any': 15 // All orientations are supported (unlocked orientation)
+ };
+}
+var orientationMask = 1;
+screenOrientation.setOrientation = function(orientation) {
+ orientationMask = window.OrientationLockType[orientation];
+ cordova.exec(null, null, "CDVOrientation", "screenOrientation", [orientationMask, orientation]);
+};
+
+if (!screen.orientation) {
+ screen.orientation = {};
+}
+
+setOrientationProperties();
+
+function addScreenOrientationApi(screenObject) {
+
+ if (screenObject.unlock || screenObject.lock) {
+ screenObject.nativeLock = screenObject.lock;
+ }
+
+ screenObject.lock = function(orientation) {
+ var promiseLock;
+ var p = new Promise(function(resolve, reject) {
+ if (screenObject.nativeLock) {
+ promiseLock = screenObject.nativeLock(orientation);
+ promiseLock.then(function success(res) {
+ resolve();
+ }, function error(err) {
+ screenObject.nativeLock = null;
+ resolveOrientation(orientation, resolve, reject);
+ });
+ } else {
+ resolveOrientation(orientation, resolve, reject);
+ }
+ });
+ return p;
+ };
+ screenObject.unlock = function() {
+ screenOrientation.setOrientation('any');
+ };
+}
+
+function resolveOrientation(orientation, resolve, reject) {
+ if (!OrientationLockType.hasOwnProperty(orientation)) {
+ var err = new Error();
+ err.name = "NotSupportedError";
+ reject(err); //"cannot change orientation");
+ } else {
+ screenOrientation.setOrientation(orientation);
+ resolve("Orientation set"); // orientation change successful
+ }
+
+}
+
+addScreenOrientationApi(screen.orientation);
+
+var onChangeListener = null;
+
+Object.defineProperty(screen.orientation, 'onchange', {
+ set: function(listener) {
+
+ if (onChangeListener) {
+ screen.orientation.removeEventListener('change', onChangeListener);
+ }
+ onChangeListener = listener;
+ if (onChangeListener) {
+ screen.orientation.addEventListener('change', onChangeListener);
+ }
+ },
+ get: function() {
+ return (onChangeListener ? onChangeListener : null);
+ },
+ enumerable: true,
+});
+
+
+var evtTarget = new XMLHttpRequest(); //document.createElement('div');
+var orientationchange = function() {
+ setOrientationProperties();
+ var event = document.createEvent('Events');
+ event.initEvent("change", false, false);
+ evtTarget.dispatchEvent(event);
+};
+
+screen.orientation.addEventListener = function(a,b,c) {
+ return evtTarget.addEventListener(a,b,c);
+};
+
+screen.orientation.removeEventListener = function(a,b,c) {
+ return evtTarget.removeEventListener(a,b,c);
+};
+
+function setOrientationProperties() {
+ switch (window.orientation) {
+ case 0:
+ screen.orientation.type = 'portrait-primary';
+ break;
+ case 90:
+ screen.orientation.type = 'landscape-primary';
+ break;
+ case 180:
+ screen.orientation.type = 'portrait-secondary';
+ break;
+ case -90:
+ screen.orientation.type = 'landscape-secondary';
+ break;
+ default:
+ screen.orientation.type = 'portrait-primary';
+ break;
+ }
+ screen.orientation.angle = window.orientation || 0;
+
+}
+window.addEventListener("orientationchange", orientationchange, true);
+
+module.exports = screenOrientation;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) {
+/*
+ *
+ * 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 cordova */
+
+var exec = require('cordova/exec');
+
+var namedColors = {
+ "black": "#000000",
+ "darkGray": "#A9A9A9",
+ "lightGray": "#D3D3D3",
+ "white": "#FFFFFF",
+ "gray": "#808080",
+ "red": "#FF0000",
+ "green": "#00FF00",
+ "blue": "#0000FF",
+ "cyan": "#00FFFF",
+ "yellow": "#FFFF00",
+ "magenta": "#FF00FF",
+ "orange": "#FFA500",
+ "purple": "#800080",
+ "brown": "#A52A2A"
+};
+
+var StatusBar = {
+
+ isVisible: true,
+
+ overlaysWebView: function (doOverlay) {
+ exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
+ },
+
+ styleDefault: function () {
+ // dark text ( to be used on a light background )
+ exec(null, null, "StatusBar", "styleDefault", []);
+ },
+
+ styleLightContent: function () {
+ // light text ( to be used on a dark background )
+ exec(null, null, "StatusBar", "styleLightContent", []);
+ },
+
+ styleBlackTranslucent: function () {
+ // #88000000 ? Apple says to use lightContent instead
+ exec(null, null, "StatusBar", "styleBlackTranslucent", []);
+ },
+
+ styleBlackOpaque: function () {
+ // #FF000000 ? Apple says to use lightContent instead
+ exec(null, null, "StatusBar", "styleBlackOpaque", []);
+ },
+
+ backgroundColorByName: function (colorname) {
+ return StatusBar.backgroundColorByHexString(namedColors[colorname]);
+ },
+
+ backgroundColorByHexString: function (hexString) {
+ if (hexString.charAt(0) !== "#") {
+ hexString = "#" + hexString;
+ }
+
+ if (hexString.length === 4) {
+ var split = hexString.split("");
+ hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3];
+ }
+
+ exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
+ },
+
+ hide: function () {
+ exec(null, null, "StatusBar", "hide", []);
+ StatusBar.isVisible = false;
+ },
+
+ show: function () {
+ exec(null, null, "StatusBar", "show", []);
+ StatusBar.isVisible = true;
+ }
+
+};
+
+// prime it. setTimeout so that proxy gets time to init
+window.setTimeout(function () {
+ exec(function (res) {
+ if (typeof res == 'object') {
+ if (res.type == 'tap') {
+ cordova.fireWindowEvent('statusTap');
+ }
+ } else {
+ StatusBar.isVisible = res;
+ }
+ }, null, "StatusBar", "_ready", []);
+}, 0);
+
+module.exports = StatusBar;
+
+});
--- /dev/null
+cordova.define("es6-promise-plugin.Promise", function(require, exports, module) {
+/*!
+ * @overview es6-promise - a tiny implementation of Promises/A+.
+ * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
+ * @license Licensed under MIT license
+ * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
+ * @version v4.2.2+97478eb6
+ */
+
+!function t(e,n,r){function o(u,s){if(!n[u]){if(!e[u]){var c="function"==typeof require&&require;if(!s&&c)return c(u,!0);if(i)return i(u,!0);var f=new Error("Cannot find module '"+u+"'");throw f.code="MODULE_NOT_FOUND",f}var a=n[u]={exports:{}};e[u][0].call(a.exports,function(t){var n=e[u][1][t];return o(n?n:t)},a,a.exports,t,e,n,r)}return n[u].exports}for(var i="function"==typeof require&&require,u=0;u<r.length;u++)o(r[u]);return o}({1:[function(t){void 0===window.Promise&&t("es6-promise").polyfill()},{"es6-promise":2}],2:[function(t,e,n){(function(r,o){!function(t,r){"object"==typeof n&&"undefined"!=typeof e?e.exports=r():"function"==typeof define&&define.amd?define(r):t.ES6Promise=r()}(this,function(){"use strict";function e(t){var e=typeof t;return null!==t&&("object"===e||"function"===e)}function n(t){return"function"==typeof t}function i(t){J=t}function u(t){Q=t}function s(){return function(){return r.nextTick(h)}}function c(){return"undefined"!=typeof I?function(){I(h)}:l()}function f(){var t=0,e=new X(h),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}function a(){var t=new MessageChannel;return t.port1.onmessage=h,function(){return t.port2.postMessage(0)}}function l(){var t=setTimeout;return function(){return t(h,1)}}function h(){for(var t=0;H>t;t+=2){var e=te[t],n=te[t+1];e(n),te[t]=void 0,te[t+1]=void 0}H=0}function p(){try{var e=t,n=e("vertx");return I=n.runOnLoop||n.runOnContext,c()}catch(r){return l()}}function d(t,e){var n=this,r=new this.constructor(y);void 0===r[ne]&&D(r);var o=n._state;if(o){var i=arguments[o-1];Q(function(){return L(o,r,i,n._result)})}else O(n,r,t,e);return r}function v(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(y);return E(n,t),n}function y(){}function m(){return new TypeError("You cannot resolve a promise with itself")}function _(){return new TypeError("A promises callback cannot return that same promise.")}function w(t){try{return t.then}catch(e){return ue.error=e,ue}}function g(t,e,n,r){try{t.call(e,n,r)}catch(o){return o}}function b(t,e,n){Q(function(t){var r=!1,o=g(n,e,function(n){r||(r=!0,e!==n?E(t,n):j(t,n))},function(e){r||(r=!0,x(t,e))},"Settle: "+(t._label||" unknown promise"));!r&&o&&(r=!0,x(t,o))},t)}function T(t,e){e._state===oe?j(t,e._result):e._state===ie?x(t,e._result):O(e,void 0,function(e){return E(t,e)},function(e){return x(t,e)})}function A(t,e,r){e.constructor===t.constructor&&r===d&&e.constructor.resolve===v?T(t,e):r===ue?(x(t,ue.error),ue.error=null):void 0===r?j(t,e):n(r)?b(t,e,r):j(t,e)}function E(t,n){t===n?x(t,m()):e(n)?A(t,n,w(n)):j(t,n)}function S(t){t._onerror&&t._onerror(t._result),M(t)}function j(t,e){t._state===re&&(t._result=e,t._state=oe,0!==t._subscribers.length&&Q(M,t))}function x(t,e){t._state===re&&(t._state=ie,t._result=e,Q(S,t))}function O(t,e,n,r){var o=t._subscribers,i=o.length;t._onerror=null,o[i]=e,o[i+oe]=n,o[i+ie]=r,0===i&&t._state&&Q(M,t)}function M(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r=void 0,o=void 0,i=t._result,u=0;u<e.length;u+=3)r=e[u],o=e[u+n],r?L(n,r,o,i):o(i);t._subscribers.length=0}}function P(){this.error=null}function C(t,e){try{return t(e)}catch(n){return se.error=n,se}}function L(t,e,r,o){var i=n(r),u=void 0,s=void 0,c=void 0,f=void 0;if(i){if(u=C(r,o),u===se?(f=!0,s=u.error,u.error=null):c=!0,e===u)return x(e,_()),void 0}else u=o,c=!0;e._state!==re||(i&&c?E(e,u):f?x(e,s):t===oe?j(e,u):t===ie&&x(e,u))}function k(t,e){try{e(function(e){E(t,e)},function(e){x(t,e)})}catch(n){x(t,n)}}function q(){return ce++}function D(t){t[ne]=ce++,t._state=void 0,t._result=void 0,t._subscribers=[]}function F(){return new Error("Array Methods must be provided an Array")}function F(){return new Error("Array Methods must be provided an Array")}function N(t){return new fe(this,t).promise}function U(t){var e=this;return G(t)?new e(function(n,r){for(var o=t.length,i=0;o>i;i++)e.resolve(t[i]).then(n,r)}):new e(function(t,e){return e(new TypeError("You must pass an array to race."))})}function Y(t){var e=this,n=new e(y);return x(n,t),n}function K(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function W(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function z(){var t=void 0;if("undefined"!=typeof o)t=o;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=t.Promise;if(n){var r=null;try{r=Object.prototype.toString.call(n.resolve())}catch(e){}if("[object Promise]"===r&&!n.cast)return}t.Promise=ae}var B=void 0;B=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var G=B,H=0,I=void 0,J=void 0,Q=function(t,e){te[H]=t,te[H+1]=e,H+=2,2===H&&(J?J(h):ee())},R="undefined"!=typeof window?window:void 0,V=R||{},X=V.MutationObserver||V.WebKitMutationObserver,Z="undefined"==typeof self&&"undefined"!=typeof r&&"[object process]"==={}.toString.call(r),$="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,te=new Array(1e3),ee=void 0;ee=Z?s():X?f():$?a():void 0===R&&"function"==typeof t?p():l();var ne=Math.random().toString(36).substring(16),re=void 0,oe=1,ie=2,ue=new P,se=new P,ce=0,fe=function(){function t(t,e){this._instanceConstructor=t,this.promise=new t(y),this.promise[ne]||D(this.promise),G(e)?(this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?j(this.promise,this._result):(this.length=this.length||0,this._enumerate(e),0===this._remaining&&j(this.promise,this._result))):x(this.promise,F())}return t.prototype._enumerate=function(t){for(var e=0;this._state===re&&e<t.length;e++)this._eachEntry(t[e],e)},t.prototype._eachEntry=function(t,e){var n=this._instanceConstructor,r=n.resolve;if(r===v){var o=w(t);if(o===d&&t._state!==re)this._settledAt(t._state,e,t._result);else if("function"!=typeof o)this._remaining--,this._result[e]=t;else if(n===ae){var i=new n(y);A(i,t,o),this._willSettleAt(i,e)}else this._willSettleAt(new n(function(e){return e(t)}),e)}else this._willSettleAt(r(t),e)},t.prototype._settledAt=function(t,e,n){var r=this.promise;r._state===re&&(this._remaining--,t===ie?x(r,n):this._result[e]=n),0===this._remaining&&j(r,this._result)},t.prototype._willSettleAt=function(t,e){var n=this;O(t,void 0,function(t){return n._settledAt(oe,e,t)},function(t){return n._settledAt(ie,e,t)})},t}(),ae=function(){function t(e){this[ne]=q(),this._result=this._state=void 0,this._subscribers=[],y!==e&&("function"!=typeof e&&K(),this instanceof t?k(this,e):W())}return t.prototype.catch=function(t){return this.then(null,t)},t.prototype.finally=function(t){var e=this,n=e.constructor;return e.then(function(e){return n.resolve(t()).then(function(){return e})},function(e){return n.resolve(t()).then(function(){throw e})})},t}();return ae.prototype.then=d,ae.all=N,ae.race=U,ae.resolve=v,ae.reject=Y,ae._setScheduler=i,ae._setAsap=u,ae._asap=Q,ae.polyfill=z,ae.Promise=ae,ae})}).call(this,t("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:3}],3:[function(t,e){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(t){if(a===setTimeout)return setTimeout(t,0);if((a===n||!a)&&setTimeout)return a=setTimeout,setTimeout(t,0);try{return a(t,0)}catch(e){try{return a.call(null,t,0)}catch(e){return a.call(this,t,0)}}}function i(t){if(l===clearTimeout)return clearTimeout(t);if((l===r||!l)&&clearTimeout)return l=clearTimeout,clearTimeout(t);try{return l(t)}catch(e){try{return l.call(null,t)}catch(e){return l.call(this,t)}}}function u(){v&&p&&(v=!1,p.length?d=p.concat(d):y=-1,d.length&&s())}function s(){if(!v){var t=o(u);v=!0;for(var e=d.length;e;){for(p=d,d=[];++y<e;)p&&p[y].run();y=-1,e=d.length}p=null,v=!1,i(t)}}function c(t,e){this.fun=t,this.array=e}function f(){}var a,l,h=e.exports={};!function(){try{a="function"==typeof setTimeout?setTimeout:n}catch(t){a=n}try{l="function"==typeof clearTimeout?clearTimeout:r}catch(t){l=r}}();var p,d=[],v=!1,y=-1;h.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];d.push(new c(t,e)),1!==d.length||v||o(s)},c.prototype.run=function(){this.fun.apply(null,this.array)},h.title="browser",h.browser=!0,h.env={},h.argv=[],h.version="",h.versions={},h.on=f,h.addListener=f,h.once=f,h.off=f,h.removeListener=f,h.removeAllListeners=f,h.emit=f,h.prependListener=f,h.prependOnceListener=f,h.listeners=function(){return[]},h.binding=function(){throw new Error("process.binding is not supported")},h.cwd=function(){return"/"},h.chdir=function(){throw new Error("process.chdir is not supported")},h.umask=function(){return 0}},{}]},{},[1]);
+
+
+});
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="fr.enhydra.tortuga.home"
+ android:hardwareAccelerated="true"
+ android:versionCode="10000"
+ android:versionName="1.0.0" >
+
+ <uses-sdk
+ android:minSdkVersion="22"
+ android:targetSdkVersion="29" />
+
+ <supports-screens
+ android:anyDensity="true"
+ android:largeScreens="true"
+ android:normalScreens="true"
+ android:resizeable="true"
+ android:smallScreens="true"
+ android:xlargeScreens="true" />
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+
+ <application
+ android:appComponentFactory="androidx.core.app.CoreComponentFactory"
+ android:debuggable="true"
+ android:hardwareAccelerated="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:supportsRtl="true" >
+ <activity
+ android:name="fr.enhydra.tortuga.home.MainActivity"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
+ android:label="@string/activity_name"
+ android:launchMode="singleTask"
+ android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+ android:windowSoftInputMode="adjustResize" >
+ <intent-filter android:label="@string/launcher_name" >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="com.darryncampbell.cordova.plugin.intent.ACTION" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <action android:name="android.intent.action.SEND_MULTIPLE" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+
+ <data android:mimeType="*/*" />
+ </intent-filter>
+ </activity>
+
+ <provider
+ android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider"
+ android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true" >
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/provider_paths" />
+ </provider>
+ <provider
+ android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider"
+ android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true" >
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/provider_paths" />
+ </provider>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+{
+ "version": 1,
+ "applicationId": "fr.enhydra.tortuga.home",
+ "variantType": "BASE_APK",
+ "elements": [
+ {
+ "outputType": {
+ "type": "MERGED_MANIFESTS"
+ },
+ "apkData": {
+ "type": "MAIN",
+ "splits": [],
+ "versionCode": 10000,
+ "versionName": "1.0.0",
+ "outputFile": "app-debug.apk",
+ "fullName": "debug",
+ "baseName": "debug",
+ "dirName": ""
+ },
+ "path": "AndroidManifest.xml",
+ "properties": {
+ "packageId": "fr.enhydra.tortuga.home",
+ "split": "",
+ "minSdkVersion": "22"
+ }
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "version": 1,
+ "applicationId": "fr.enhydra.tortuga.home",
+ "variantType": "BASE_APK",
+ "elements": [
+ {
+ "outputType": {
+ "type": "METADATA_FEATURE_MANIFEST"
+ },
+ "apkData": {
+ "type": "MAIN",
+ "splits": [],
+ "versionCode": 10000,
+ "versionName": "1.0.0",
+ "outputFile": "app-debug.apk",
+ "fullName": "debug",
+ "baseName": "debug",
+ "dirName": ""
+ },
+ "path": "AndroidManifest.xml",
+ "properties": {}
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+[]
\ No newline at end of file
--- /dev/null
+{
+ "version": 1,
+ "applicationId": "fr.enhydra.tortuga.home",
+ "variantType": "BASE_APK",
+ "elements": [
+ {
+ "outputType": {
+ "type": "PROCESSED_RES"
+ },
+ "apkData": {
+ "type": "MAIN",
+ "splits": [],
+ "versionCode": 10000,
+ "versionName": "1.0.0",
+ "outputFile": "app-debug.apk",
+ "fullName": "debug",
+ "baseName": "debug",
+ "dirName": ""
+ },
+ "path": "resources-debug.ap_",
+ "properties": {
+ "packageId": "fr.enhydra.tortuga.home",
+ "split": "",
+ "minSdkVersion": "22"
+ }
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+int attr alpha 0x7f010000
+int attr font 0x7f010001
+int attr fontProviderAuthority 0x7f010002
+int attr fontProviderCerts 0x7f010003
+int attr fontProviderFetchStrategy 0x7f010004
+int attr fontProviderFetchTimeout 0x7f010005
+int attr fontProviderPackage 0x7f010006
+int attr fontProviderQuery 0x7f010007
+int attr fontStyle 0x7f010008
+int attr fontVariationSettings 0x7f010009
+int attr fontWeight 0x7f01000a
+int attr ttcIndex 0x7f01000b
+int color background 0x7f020000
+int color notification_action_color_filter 0x7f020001
+int color notification_icon_bg_color 0x7f020002
+int color ripple_material_light 0x7f020003
+int color secondary_text_default_material_light 0x7f020004
+int dimen compat_button_inset_horizontal_material 0x7f030000
+int dimen compat_button_inset_vertical_material 0x7f030001
+int dimen compat_button_padding_horizontal_material 0x7f030002
+int dimen compat_button_padding_vertical_material 0x7f030003
+int dimen compat_control_corner_material 0x7f030004
+int dimen compat_notification_large_icon_max_height 0x7f030005
+int dimen compat_notification_large_icon_max_width 0x7f030006
+int dimen notification_action_icon_size 0x7f030007
+int dimen notification_action_text_size 0x7f030008
+int dimen notification_big_circle_margin 0x7f030009
+int dimen notification_content_margin_start 0x7f03000a
+int dimen notification_large_icon_height 0x7f03000b
+int dimen notification_large_icon_width 0x7f03000c
+int dimen notification_main_column_padding_top 0x7f03000d
+int dimen notification_media_narrow_margin 0x7f03000e
+int dimen notification_right_icon_size 0x7f03000f
+int dimen notification_right_side_padding_top 0x7f030010
+int dimen notification_small_icon_background_padding 0x7f030011
+int dimen notification_small_icon_size_as_large 0x7f030012
+int dimen notification_subtext_size 0x7f030013
+int dimen notification_top_pad 0x7f030014
+int dimen notification_top_pad_large_text 0x7f030015
+int drawable notification_action_background 0x7f040000
+int drawable notification_bg 0x7f040001
+int drawable notification_bg_low 0x7f040002
+int drawable notification_bg_low_normal 0x7f040003
+int drawable notification_bg_low_pressed 0x7f040004
+int drawable notification_bg_normal 0x7f040005
+int drawable notification_bg_normal_pressed 0x7f040006
+int drawable notification_icon_background 0x7f040007
+int drawable notification_template_icon_bg 0x7f040008
+int drawable notification_template_icon_low_bg 0x7f040009
+int drawable notification_tile_bg 0x7f04000a
+int drawable notify_panel_notification_icon_bg 0x7f04000b
+int drawable screen 0x7f04000c
+int id accessibility_action_clickable_span 0x7f050000
+int id accessibility_custom_action_0 0x7f050001
+int id accessibility_custom_action_1 0x7f050002
+int id accessibility_custom_action_10 0x7f050003
+int id accessibility_custom_action_11 0x7f050004
+int id accessibility_custom_action_12 0x7f050005
+int id accessibility_custom_action_13 0x7f050006
+int id accessibility_custom_action_14 0x7f050007
+int id accessibility_custom_action_15 0x7f050008
+int id accessibility_custom_action_16 0x7f050009
+int id accessibility_custom_action_17 0x7f05000a
+int id accessibility_custom_action_18 0x7f05000b
+int id accessibility_custom_action_19 0x7f05000c
+int id accessibility_custom_action_2 0x7f05000d
+int id accessibility_custom_action_20 0x7f05000e
+int id accessibility_custom_action_21 0x7f05000f
+int id accessibility_custom_action_22 0x7f050010
+int id accessibility_custom_action_23 0x7f050011
+int id accessibility_custom_action_24 0x7f050012
+int id accessibility_custom_action_25 0x7f050013
+int id accessibility_custom_action_26 0x7f050014
+int id accessibility_custom_action_27 0x7f050015
+int id accessibility_custom_action_28 0x7f050016
+int id accessibility_custom_action_29 0x7f050017
+int id accessibility_custom_action_3 0x7f050018
+int id accessibility_custom_action_30 0x7f050019
+int id accessibility_custom_action_31 0x7f05001a
+int id accessibility_custom_action_4 0x7f05001b
+int id accessibility_custom_action_5 0x7f05001c
+int id accessibility_custom_action_6 0x7f05001d
+int id accessibility_custom_action_7 0x7f05001e
+int id accessibility_custom_action_8 0x7f05001f
+int id accessibility_custom_action_9 0x7f050020
+int id action_container 0x7f050021
+int id action_divider 0x7f050022
+int id action_image 0x7f050023
+int id action_text 0x7f050024
+int id actions 0x7f050025
+int id async 0x7f050026
+int id blocking 0x7f050027
+int id chronometer 0x7f050028
+int id dialog_button 0x7f050029
+int id forever 0x7f05002a
+int id icon 0x7f05002b
+int id icon_group 0x7f05002c
+int id info 0x7f05002d
+int id italic 0x7f05002e
+int id line1 0x7f05002f
+int id line3 0x7f050030
+int id normal 0x7f050031
+int id notification_background 0x7f050032
+int id notification_main_column 0x7f050033
+int id notification_main_column_container 0x7f050034
+int id right_icon 0x7f050035
+int id right_side 0x7f050036
+int id tag_accessibility_actions 0x7f050037
+int id tag_accessibility_clickable_spans 0x7f050038
+int id tag_accessibility_heading 0x7f050039
+int id tag_accessibility_pane_title 0x7f05003a
+int id tag_screen_reader_focusable 0x7f05003b
+int id tag_transition_group 0x7f05003c
+int id tag_unhandled_key_event_manager 0x7f05003d
+int id tag_unhandled_key_listeners 0x7f05003e
+int id text 0x7f05003f
+int id text2 0x7f050040
+int id time 0x7f050041
+int id title 0x7f050042
+int integer status_bar_notification_info_maxnum 0x7f060000
+int layout custom_dialog 0x7f070000
+int layout notification_action 0x7f070001
+int layout notification_action_tombstone 0x7f070002
+int layout notification_template_custom_big 0x7f070003
+int layout notification_template_icon_group 0x7f070004
+int layout notification_template_part_chronometer 0x7f070005
+int layout notification_template_part_time 0x7f070006
+int mipmap ic_launcher 0x7f080000
+int mipmap ic_launcher_foreground 0x7f080001
+int string activity_name 0x7f090000
+int string app_name 0x7f090001
+int string launcher_name 0x7f090002
+int string status_bar_notification_info_overflow 0x7f090003
+int style TextAppearance_Compat_Notification 0x7f0a0000
+int style TextAppearance_Compat_Notification_Info 0x7f0a0001
+int style TextAppearance_Compat_Notification_Line2 0x7f0a0002
+int style TextAppearance_Compat_Notification_Time 0x7f0a0003
+int style TextAppearance_Compat_Notification_Title 0x7f0a0004
+int style Widget_Compat_NotificationActionContainer 0x7f0a0005
+int style Widget_Compat_NotificationActionText 0x7f0a0006
+int[] styleable ColorStateListItem { 0x010101a5, 0x0101031f, 0x7f010000 }
+int styleable ColorStateListItem_android_color 0
+int styleable ColorStateListItem_android_alpha 1
+int styleable ColorStateListItem_alpha 2
+int[] styleable FontFamily { 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005, 0x7f010006, 0x7f010007 }
+int styleable FontFamily_fontProviderAuthority 0
+int styleable FontFamily_fontProviderCerts 1
+int styleable FontFamily_fontProviderFetchStrategy 2
+int styleable FontFamily_fontProviderFetchTimeout 3
+int styleable FontFamily_fontProviderPackage 4
+int styleable FontFamily_fontProviderQuery 5
+int[] styleable FontFamilyFont { 0x01010532, 0x01010533, 0x0101053f, 0x0101056f, 0x01010570, 0x7f010001, 0x7f010008, 0x7f010009, 0x7f01000a, 0x7f01000b }
+int styleable FontFamilyFont_android_font 0
+int styleable FontFamilyFont_android_fontWeight 1
+int styleable FontFamilyFont_android_fontStyle 2
+int styleable FontFamilyFont_android_ttcIndex 3
+int styleable FontFamilyFont_android_fontVariationSettings 4
+int styleable FontFamilyFont_font 5
+int styleable FontFamilyFont_fontStyle 6
+int styleable FontFamilyFont_fontVariationSettings 7
+int styleable FontFamilyFont_fontWeight 8
+int styleable FontFamilyFont_ttcIndex 9
+int[] styleable GradientColor { 0x0101019d, 0x0101019e, 0x010101a1, 0x010101a2, 0x010101a3, 0x010101a4, 0x01010201, 0x0101020b, 0x01010510, 0x01010511, 0x01010512, 0x01010513 }
+int styleable GradientColor_android_startColor 0
+int styleable GradientColor_android_endColor 1
+int styleable GradientColor_android_type 2
+int styleable GradientColor_android_centerX 3
+int styleable GradientColor_android_centerY 4
+int styleable GradientColor_android_gradientRadius 5
+int styleable GradientColor_android_tileMode 6
+int styleable GradientColor_android_centerColor 7
+int styleable GradientColor_android_startX 8
+int styleable GradientColor_android_startY 9
+int styleable GradientColor_android_endX 10
+int styleable GradientColor_android_endY 11
+int[] styleable GradientColorItem { 0x010101a5, 0x01010514 }
+int styleable GradientColorItem_android_color 0
+int styleable GradientColorItem_android_offset 1
+int xml config 0x7f0c0000
+int xml provider_paths 0x7f0c0001
--- /dev/null
+fr.enhydra.tortuga.home
+attr alpha
+attr font
+attr fontProviderAuthority
+attr fontProviderCerts
+attr fontProviderFetchStrategy
+attr fontProviderFetchTimeout
+attr fontProviderPackage
+attr fontProviderQuery
+attr fontStyle
+attr fontVariationSettings
+attr fontWeight
+attr ttcIndex
+color background
+color notification_action_color_filter
+color notification_icon_bg_color
+color ripple_material_light
+color secondary_text_default_material_light
+dimen compat_button_inset_horizontal_material
+dimen compat_button_inset_vertical_material
+dimen compat_button_padding_horizontal_material
+dimen compat_button_padding_vertical_material
+dimen compat_control_corner_material
+dimen compat_notification_large_icon_max_height
+dimen compat_notification_large_icon_max_width
+dimen notification_action_icon_size
+dimen notification_action_text_size
+dimen notification_big_circle_margin
+dimen notification_content_margin_start
+dimen notification_large_icon_height
+dimen notification_large_icon_width
+dimen notification_main_column_padding_top
+dimen notification_media_narrow_margin
+dimen notification_right_icon_size
+dimen notification_right_side_padding_top
+dimen notification_small_icon_background_padding
+dimen notification_small_icon_size_as_large
+dimen notification_subtext_size
+dimen notification_top_pad
+dimen notification_top_pad_large_text
+drawable notification_action_background
+drawable notification_bg
+drawable notification_bg_low
+drawable notification_bg_low_normal
+drawable notification_bg_low_pressed
+drawable notification_bg_normal
+drawable notification_bg_normal_pressed
+drawable notification_icon_background
+drawable notification_template_icon_bg
+drawable notification_template_icon_low_bg
+drawable notification_tile_bg
+drawable notify_panel_notification_icon_bg
+drawable screen
+id accessibility_action_clickable_span
+id accessibility_custom_action_0
+id accessibility_custom_action_1
+id accessibility_custom_action_10
+id accessibility_custom_action_11
+id accessibility_custom_action_12
+id accessibility_custom_action_13
+id accessibility_custom_action_14
+id accessibility_custom_action_15
+id accessibility_custom_action_16
+id accessibility_custom_action_17
+id accessibility_custom_action_18
+id accessibility_custom_action_19
+id accessibility_custom_action_2
+id accessibility_custom_action_20
+id accessibility_custom_action_21
+id accessibility_custom_action_22
+id accessibility_custom_action_23
+id accessibility_custom_action_24
+id accessibility_custom_action_25
+id accessibility_custom_action_26
+id accessibility_custom_action_27
+id accessibility_custom_action_28
+id accessibility_custom_action_29
+id accessibility_custom_action_3
+id accessibility_custom_action_30
+id accessibility_custom_action_31
+id accessibility_custom_action_4
+id accessibility_custom_action_5
+id accessibility_custom_action_6
+id accessibility_custom_action_7
+id accessibility_custom_action_8
+id accessibility_custom_action_9
+id action_container
+id action_divider
+id action_image
+id action_text
+id actions
+id async
+id blocking
+id chronometer
+id dialog_button
+id forever
+id icon
+id icon_group
+id info
+id italic
+id line1
+id line3
+id normal
+id notification_background
+id notification_main_column
+id notification_main_column_container
+id right_icon
+id right_side
+id tag_accessibility_actions
+id tag_accessibility_clickable_spans
+id tag_accessibility_heading
+id tag_accessibility_pane_title
+id tag_screen_reader_focusable
+id tag_transition_group
+id tag_unhandled_key_event_manager
+id tag_unhandled_key_listeners
+id text
+id text2
+id time
+id title
+integer status_bar_notification_info_maxnum
+layout custom_dialog
+layout notification_action
+layout notification_action_tombstone
+layout notification_template_custom_big
+layout notification_template_icon_group
+layout notification_template_part_chronometer
+layout notification_template_part_time
+mipmap ic_launcher
+mipmap ic_launcher_foreground
+string activity_name
+string app_name
+string launcher_name
+string status_bar_notification_info_overflow
+style TextAppearance_Compat_Notification
+style TextAppearance_Compat_Notification_Info
+style TextAppearance_Compat_Notification_Line2
+style TextAppearance_Compat_Notification_Time
+style TextAppearance_Compat_Notification_Title
+style Widget_Compat_NotificationActionContainer
+style Widget_Compat_NotificationActionText
+styleable ColorStateListItem android_color android_alpha alpha
+styleable FontFamily fontProviderAuthority fontProviderCerts fontProviderFetchStrategy fontProviderFetchTimeout fontProviderPackage fontProviderQuery
+styleable FontFamilyFont android_font android_fontWeight android_fontStyle android_ttcIndex android_fontVariationSettings font fontStyle fontVariationSettings fontWeight ttcIndex
+styleable GradientColor android_startColor android_endColor android_type android_centerX android_centerY android_gradientRadius android_tileMode android_centerColor android_startX android_startY android_endX android_endY
+styleable GradientColorItem android_color android_offset
+xml config
+xml provider_paths
--- /dev/null
+{
+ "version": 1,
+ "artifactType": {
+ "type": "APK",
+ "kind": "Directory"
+ },
+ "applicationId": "fr.enhydra.tortuga.home",
+ "variantName": "debug",
+ "elements": [
+ {
+ "type": "SINGLE",
+ "filters": [],
+ "properties": [],
+ "versionCode": 10000,
+ "versionName": "10000",
+ "enabled": true,
+ "outputFile": "app-debug.apk"
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+-- Merging decision tree log ---
+provider#com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:25:9-27:20
+ android:grantUriPermissions
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:140-174
+ android:authorities
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:19-114
+ android:exported
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:115-139
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:22:175-262
+manifest
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:1-32:12
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:1-32:12
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:1-32:12
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:1-32:12
+MERGED from [:CordovaLib] T:\Drive\Works\home-android\platforms\android\CordovaLib\build\intermediates\library_manifest\debug\AndroidManifest.xml:20:1-27:12
+MERGED from [androidx.core:core:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\AndroidManifest.xml:17:1-26:12
+MERGED from [androidx.versionedparcelable:versionedparcelable:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\e6bb7e01f8e83b7b07e98d45a8a1ae6f\versionedparcelable-1.1.0\AndroidManifest.xml:17:1-27:12
+MERGED from [androidx.lifecycle:lifecycle-runtime:2.0.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\b8939781ced048a1fb4e2d944fa2aae9\lifecycle-runtime-2.0.0\AndroidManifest.xml:17:1-22:12
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:1-32:12
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:1-32:12
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:1-32:12
+ package
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:102-135
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ android:versionName
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:74-101
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ android:hardwareAccelerated
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:11-45
+ xmlns:android
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:136-194
+ android:versionCode
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:2:46-73
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+supports-screens
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:5-191
+ android:largeScreens
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:49-76
+ android:smallScreens
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:132-159
+ android:normalScreens
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:77-105
+ android:xlargeScreens
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:160-188
+ android:resizeable
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:106-131
+ android:anyDensity
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:3:23-48
+uses-permission#android.permission.INTERNET
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:4:5-67
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:4:22-64
+application
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:5-28:19
+MERGED from [androidx.core:core:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\AndroidManifest.xml:24:5-89
+MERGED from [androidx.core:core:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\AndroidManifest.xml:24:5-89
+MERGED from [androidx.versionedparcelable:versionedparcelable:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\e6bb7e01f8e83b7b07e98d45a8a1ae6f\versionedparcelable-1.1.0\AndroidManifest.xml:24:5-25:19
+MERGED from [androidx.versionedparcelable:versionedparcelable:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\e6bb7e01f8e83b7b07e98d45a8a1ae6f\versionedparcelable-1.1.0\AndroidManifest.xml:24:5-25:19
+ android:appComponentFactory
+ ADDED from [androidx.core:core:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\AndroidManifest.xml:24:18-86
+ android:supportsRtl
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:121-147
+ android:label
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:88-120
+ android:hardwareAccelerated
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:18-52
+ android:icon
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:5:53-87
+activity#fr.enhydra.tortuga.home.MainActivity
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:9-21:20
+ android:label
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:136-173
+ android:launchMode
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:174-205
+ android:windowSoftInputMode
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:297-339
+ android:configChanges
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:19-135
+ android:theme
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:234-296
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:6:206-233
+intent-filter#action:name:android.intent.action.MAIN+category:name:android.intent.category.LAUNCHER
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:7:13-10:29
+ android:label
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:7:28-65
+action#android.intent.action.MAIN
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:8:17-69
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:8:25-66
+category#android.intent.category.LAUNCHER
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:9:17-77
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:9:27-74
+intent-filter#action:name:com.darryncampbell.cordova.plugin.intent.ACTION+category:name:android.intent.category.DEFAULT
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:11:13-14:29
+action#com.darryncampbell.cordova.plugin.intent.ACTION
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:12:17-90
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:12:25-87
+category#android.intent.category.DEFAULT
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:13:17-76
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:13:27-73
+intent-filter#action:name:android.intent.action.SEND+action:name:android.intent.action.SEND_MULTIPLE+category:name:android.intent.category.DEFAULT+data:mimeType:*/*
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:15:13-20:29
+action#android.intent.action.SEND
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:16:17-69
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:16:25-66
+action#android.intent.action.SEND_MULTIPLE
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:17:17-78
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:17:25-75
+data
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:19:17-48
+ android:mimeType
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:19:23-45
+uses-permission#android.permission.WRITE_EXTERNAL_STORAGE
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:29:5-81
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:29:22-78
+uses-permission#android.permission.READ_EXTERNAL_STORAGE
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:30:5-80
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:30:22-77
+uses-permission#android.permission.REQUEST_INSTALL_PACKAGES
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:31:5-83
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:31:22-80
+uses-sdk
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml reason: use-sdk injection requested
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+MERGED from [:CordovaLib] T:\Drive\Works\home-android\platforms\android\CordovaLib\build\intermediates\library_manifest\debug\AndroidManifest.xml:25:5-44
+MERGED from [:CordovaLib] T:\Drive\Works\home-android\platforms\android\CordovaLib\build\intermediates\library_manifest\debug\AndroidManifest.xml:25:5-44
+MERGED from [androidx.core:core:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\AndroidManifest.xml:20:5-22:41
+MERGED from [androidx.core:core:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\57b7f42ffa61e27821b7c87274482ce6\core-1.1.0\AndroidManifest.xml:20:5-22:41
+MERGED from [androidx.versionedparcelable:versionedparcelable:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\e6bb7e01f8e83b7b07e98d45a8a1ae6f\versionedparcelable-1.1.0\AndroidManifest.xml:20:5-22:41
+MERGED from [androidx.versionedparcelable:versionedparcelable:1.1.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\e6bb7e01f8e83b7b07e98d45a8a1ae6f\versionedparcelable-1.1.0\AndroidManifest.xml:20:5-22:41
+MERGED from [androidx.lifecycle:lifecycle-runtime:2.0.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\b8939781ced048a1fb4e2d944fa2aae9\lifecycle-runtime-2.0.0\AndroidManifest.xml:20:5-44
+MERGED from [androidx.lifecycle:lifecycle-runtime:2.0.0] C:\Users\Vincent\.gradle\caches\transforms-2\files-2.1\b8939781ced048a1fb4e2d944fa2aae9\lifecycle-runtime-2.0.0\AndroidManifest.xml:20:5-44
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ android:targetSdkVersion
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ android:minSdkVersion
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+ INJECTED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml
+meta-data#android.support.FILE_PROVIDER_PATHS
+ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:13-116
+ android:resource
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:75-113
+ android:name
+ ADDED from T:\Drive\Works\home-android\platforms\android\app\src\main\AndroidManifest.xml:23:24-74
--- /dev/null
+org/apache/cordova/device/Device.java
+ org.apache.cordova.device.Device
+org/apache/cordova/file/AssetFilesystem.java
+ org.apache.cordova.file.AssetFilesystem
+org/apache/cordova/file/InvalidModificationException.java
+ org.apache.cordova.file.InvalidModificationException
+org/apache/cordova/whitelist/WhitelistPlugin.java
+ org.apache.cordova.whitelist.WhitelistPlugin
+ org.apache.cordova.whitelist.WhitelistPlugin$1
+ org.apache.cordova.whitelist.WhitelistPlugin$CustomConfigXmlParser
+fr/enhydra/tortuga/home/MainActivity.java
+ fr.enhydra.tortuga.home.MainActivity
+org/apache/cordova/file/Filesystem.java
+ org.apache.cordova.file.Filesystem
+ org.apache.cordova.file.Filesystem$LimitedInputStream
+ org.apache.cordova.file.Filesystem$ReadFileCallback
+org/apache/cordova/file/NoModificationAllowedException.java
+ org.apache.cordova.file.NoModificationAllowedException
+org/apache/cordova/file/TypeMismatchException.java
+ org.apache.cordova.file.TypeMismatchException
+org/apache/cordova/file/ContentFilesystem.java
+ org.apache.cordova.file.ContentFilesystem
+org/apache/cordova/file/FileUtils.java
+ org.apache.cordova.file.FileUtils
+ org.apache.cordova.file.FileUtils$1
+ org.apache.cordova.file.FileUtils$10
+ org.apache.cordova.file.FileUtils$11
+ org.apache.cordova.file.FileUtils$12
+ org.apache.cordova.file.FileUtils$13
+ org.apache.cordova.file.FileUtils$14
+ org.apache.cordova.file.FileUtils$15
+ org.apache.cordova.file.FileUtils$16
+ org.apache.cordova.file.FileUtils$17
+ org.apache.cordova.file.FileUtils$18
+ org.apache.cordova.file.FileUtils$19
+ org.apache.cordova.file.FileUtils$2
+ org.apache.cordova.file.FileUtils$20
+ org.apache.cordova.file.FileUtils$21
+ org.apache.cordova.file.FileUtils$22
+ org.apache.cordova.file.FileUtils$23
+ org.apache.cordova.file.FileUtils$24
+ org.apache.cordova.file.FileUtils$25
+ org.apache.cordova.file.FileUtils$26
+ org.apache.cordova.file.FileUtils$27
+ org.apache.cordova.file.FileUtils$28
+ org.apache.cordova.file.FileUtils$29
+ org.apache.cordova.file.FileUtils$3
+ org.apache.cordova.file.FileUtils$4
+ org.apache.cordova.file.FileUtils$5
+ org.apache.cordova.file.FileUtils$6
+ org.apache.cordova.file.FileUtils$7
+ org.apache.cordova.file.FileUtils$8
+ org.apache.cordova.file.FileUtils$9
+ org.apache.cordova.file.FileUtils$FileOp
+com/darryncampbell/plugin/intent/CordovaPluginIntentFileProvider.java
+ com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider
+org/apache/cordova/file/LocalFilesystemURL.java
+ org.apache.cordova.file.LocalFilesystemURL
+org/apache/cordova/file/DirectoryManager.java
+ org.apache.cordova.file.DirectoryManager
+fr/enhydra/tortuga/home/BuildConfig.java
+ fr.enhydra.tortuga.home.BuildConfig
+org/apache/cordova/file/LocalFilesystem.java
+ org.apache.cordova.file.LocalFilesystem
+org/apache/cordova/file/PendingRequests.java
+ org.apache.cordova.file.PendingRequests
+ org.apache.cordova.file.PendingRequests$1
+ org.apache.cordova.file.PendingRequests$Request
+org/apache/cordova/statusbar/StatusBar.java
+ org.apache.cordova.statusbar.StatusBar
+ org.apache.cordova.statusbar.StatusBar$1
+ org.apache.cordova.statusbar.StatusBar$2
+ org.apache.cordova.statusbar.StatusBar$3
+ org.apache.cordova.statusbar.StatusBar$4
+ org.apache.cordova.statusbar.StatusBar$5
+ org.apache.cordova.statusbar.StatusBar$6
+ org.apache.cordova.statusbar.StatusBar$7
+ org.apache.cordova.statusbar.StatusBar$8
+ org.apache.cordova.statusbar.StatusBar$9
+org/apache/cordova/file/FileExistsException.java
+ org.apache.cordova.file.FileExistsException
+cordova/plugins/screenorientation/CDVOrientation.java
+ cordova.plugins.screenorientation.CDVOrientation
+com/darryncampbell/plugin/intent/IntentShim.java
+ com.darryncampbell.cordova.plugin.intent.IntentShim
+ com.darryncampbell.cordova.plugin.intent.IntentShim$1
+org/apache/cordova/file/EncodingException.java
+ org.apache.cordova.file.EncodingException
--- /dev/null
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
--- /dev/null
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# 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
+#
+# https://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.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
--- /dev/null
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
--- /dev/null
+<?xml version='1.0' encoding='utf-8'?>
+<manifest android:hardwareAccelerated="true" android:versionCode="10000" android:versionName="1.0.0" package="fr.enhydra.tortuga.home" xmlns:android="http://schemas.android.com/apk/res/android">
+ <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <application android:hardwareAccelerated="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true">
+ <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" android:label="@string/activity_name" android:launchMode="singleTask" android:name="MainActivity" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
+ <intent-filter android:label="@string/launcher_name">
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="com.darryncampbell.cordova.plugin.intent.ACTION" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <action android:name="android.intent.action.SEND_MULTIPLE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="*/*" />
+ </intent-filter>
+ </activity>
+ <provider android:authorities="fr.enhydra.tortuga.home.darryncampbell.cordova.plugin.intent.fileprovider" android:exported="false" android:grantUriPermissions="true" android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider">
+ <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
+ </provider>
+ <provider android:authorities="${applicationId}.darryncampbell.cordova.plugin.intent.fileprovider" android:exported="false" android:grantUriPermissions="true" android:name="com.darryncampbell.cordova.plugin.intent.CordovaPluginIntentFileProvider">
+ <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
+ </provider>
+ </application>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+</manifest>
--- /dev/null
+/*
+ * 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.
+*/
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+ get: function () { return currentApi; },
+ setPreferPrompt: function (value) {
+ currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+ },
+ // Used only by tests.
+ set: function (value) {
+ currentApi = value;
+ }
+};
--- /dev/null
+/*
+ * 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.
+*/
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+ exec: function (bridgeSecret, service, action, callbackId, argsJson) {
+ return prompt(argsJson, 'gap:' + JSON.stringify([bridgeSecret, service, action, callbackId]));
+ },
+ setNativeToJsBridgeMode: function (bridgeSecret, value) {
+ prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+ },
+ retrieveJsMessages: function (bridgeSecret, fromOnlineEvent) {
+ return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+ }
+};
--- /dev/null
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Execute a cordova command. It is up to the native side whether this action
+ * is synchronous or asynchronous. The native side can return:
+ * Synchronous: PluginResult object as a JSON string
+ * Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success The success callback
+ * @param {Function} fail The fail callback
+ * @param {String} service The name of the service to use
+ * @param {String} action Action to be run in cordova
+ * @param {String[]} [args] Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova');
+var nativeApiProvider = require('cordova/android/nativeapiprovider');
+var utils = require('cordova/utils');
+var base64 = require('cordova/base64');
+var channel = require('cordova/channel');
+var jsToNativeModes = {
+ PROMPT: 0,
+ JS_OBJECT: 1
+};
+var nativeToJsModes = {
+ // Polls for messages using the JS->Native bridge.
+ POLLING: 0,
+ // For LOAD_URL to be viable, it would need to have a work-around for
+ // the bug where the soft-keyboard gets dismissed when a message is sent.
+ LOAD_URL: 1,
+ // For the ONLINE_EVENT to be viable, it would need to intercept all event
+ // listeners (both through addEventListener and window.ononline) as well
+ // as set the navigator property itself.
+ ONLINE_EVENT: 2,
+ EVAL_BRIDGE: 3
+};
+var jsToNativeBridgeMode; // Set lazily.
+var nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE;
+var pollEnabled = false;
+var bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise === 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function (fn) { resolvedPromise.then(fn); } : function (fn) { setTimeout(fn); };
+
+function androidExec (success, fail, service, action, args) {
+ if (bridgeSecret < 0) {
+ // If we ever catch this firing, we'll need to queue up exec()s
+ // and fire them once we get a secret. For now, I don't think
+ // it's possible for exec() to be called since plugins are parsed but
+ // not run until until after onNativeReady.
+ throw new Error('exec() called without bridgeSecret');
+ }
+ // Set default bridge modes if they have not already been set.
+ // By default, we use the failsafe, since addJavascriptInterface breaks too often
+ if (jsToNativeBridgeMode === undefined) {
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+ }
+
+ // If args is not provided, default to an empty array
+ args = args || [];
+
+ // Process any ArrayBuffers in the args into a string.
+ for (var i = 0; i < args.length; i++) {
+ if (utils.typeName(args[i]) === 'ArrayBuffer') {
+ args[i] = base64.fromArrayBuffer(args[i]);
+ }
+ }
+
+ var callbackId = service + cordova.callbackId++;
+ var argsJson = JSON.stringify(args);
+ if (success || fail) {
+ cordova.callbacks[callbackId] = { success: success, fail: fail };
+ }
+
+ var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+ // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+ // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
+ if (jsToNativeBridgeMode === jsToNativeModes.JS_OBJECT && msgs === '@Null arguments.') {
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+ androidExec(success, fail, service, action, args);
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+ } else if (msgs) {
+ messagesFromNative.push(msgs);
+ // Always process async to avoid exceptions messing up stack.
+ nextTick(processMessages);
+ }
+}
+
+androidExec.init = function () {
+ bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+ channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent () {
+ pollOnce(true);
+}
+
+function pollOnce (opt_fromOnlineEvent) {
+ if (bridgeSecret < 0) {
+ // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+ // We know there's nothing to retrieve, so no need to poll.
+ return;
+ }
+ var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+ if (msgs) {
+ messagesFromNative.push(msgs);
+ // Process sync since we know we're already top-of-stack.
+ processMessages();
+ }
+}
+
+function pollingTimerFunc () {
+ if (pollEnabled) {
+ pollOnce();
+ setTimeout(pollingTimerFunc, 50);
+ }
+}
+
+function hookOnlineApis () {
+ function proxyEvent (e) {
+ cordova.fireWindowEvent(e.type);
+ }
+ // The network module takes care of firing online and offline events.
+ // It currently fires them only on document though, so we bridge them
+ // to window here (while first listening for exec()-releated online/offline
+ // events).
+ window.addEventListener('online', pollOnceFromOnlineEvent, false);
+ window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+ cordova.addWindowEventHandler('online');
+ cordova.addWindowEventHandler('offline');
+ document.addEventListener('online', proxyEvent, false);
+ document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function (mode) {
+ if (mode === jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+ mode = jsToNativeModes.PROMPT;
+ }
+ nativeApiProvider.setPreferPrompt(mode === jsToNativeModes.PROMPT);
+ jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function (mode) {
+ if (mode === nativeToJsBridgeMode) {
+ return;
+ }
+ if (nativeToJsBridgeMode === nativeToJsModes.POLLING) {
+ pollEnabled = false;
+ }
+
+ nativeToJsBridgeMode = mode;
+ // Tell the native side to switch modes.
+ // Otherwise, it will be set by androidExec.init()
+ if (bridgeSecret >= 0) {
+ nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+ }
+
+ if (mode === nativeToJsModes.POLLING) {
+ pollEnabled = true;
+ setTimeout(pollingTimerFunc, 1);
+ }
+};
+
+function buildPayload (payload, message) {
+ var payloadKind = message.charAt(0);
+ if (payloadKind === 's') {
+ payload.push(message.slice(1));
+ } else if (payloadKind === 't') {
+ payload.push(true);
+ } else if (payloadKind === 'f') {
+ payload.push(false);
+ } else if (payloadKind === 'N') {
+ payload.push(null);
+ } else if (payloadKind === 'n') {
+ payload.push(+message.slice(1));
+ } else if (payloadKind === 'A') {
+ var data = message.slice(1);
+ payload.push(base64.toArrayBuffer(data));
+ } else if (payloadKind === 'S') {
+ payload.push(window.atob(message.slice(1)));
+ } else if (payloadKind === 'M') {
+ var multipartMessages = message.slice(1);
+ while (multipartMessages !== '') {
+ var spaceIdx = multipartMessages.indexOf(' ');
+ var msgLen = +multipartMessages.slice(0, spaceIdx);
+ var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+ multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+ buildPayload(payload, multipartMessage);
+ }
+ } else {
+ payload.push(JSON.parse(message));
+ }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage (message) {
+ var firstChar = message.charAt(0);
+ if (firstChar === 'J') {
+ // This is deprecated on the .java side. It doesn't work with CSP enabled.
+ // eslint-disable-next-line no-eval
+ eval(message.slice(1));
+ } else if (firstChar === 'S' || firstChar === 'F') {
+ var success = firstChar === 'S';
+ var keepCallback = message.charAt(1) === '1';
+ var spaceIdx = message.indexOf(' ', 2);
+ var status = +message.slice(2, spaceIdx);
+ var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+ var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+ var payloadMessage = message.slice(nextSpaceIdx + 1);
+ var payload = [];
+ buildPayload(payload, payloadMessage);
+ cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+ } else {
+ console.log('processMessage failed: invalid message: ' + JSON.stringify(message));
+ }
+}
+
+function processMessages () {
+ // Check for the reentrant case.
+ if (isProcessing) {
+ return;
+ }
+ if (messagesFromNative.length === 0) {
+ return;
+ }
+ isProcessing = true;
+ try {
+ var msg = popMessageFromQueue();
+ // The Java side can send a * message to indicate that it
+ // still has messages waiting to be retrieved.
+ if (msg === '*' && messagesFromNative.length === 0) {
+ nextTick(pollOnce);
+ return;
+ }
+ processMessage(msg);
+ } finally {
+ isProcessing = false;
+ if (messagesFromNative.length > 0) {
+ nextTick(processMessages);
+ }
+ }
+}
+
+function popMessageFromQueue () {
+ var messageBatch = messagesFromNative.shift();
+ if (messageBatch === '*') {
+ return '*';
+ }
+
+ var spaceIdx = messageBatch.indexOf(' ');
+ var msgLen = +messageBatch.slice(0, spaceIdx);
+ var message = messageBatch.substr(spaceIdx + 1, msgLen);
+ messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+ if (messageBatch) {
+ messagesFromNative.unshift(messageBatch);
+ }
+ return message;
+}
+
+module.exports = androidExec;
--- /dev/null
+/*
+ *
+ * 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.
+ *
+*/
+
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
+
+module.exports = {
+ id: 'android',
+ bootstrap: function () {
+ var channel = require('cordova/channel');
+ var cordova = require('cordova');
+ var exec = require('cordova/exec');
+ var modulemapper = require('cordova/modulemapper');
+
+ // Get the shared secret needed to use the bridge.
+ exec.init();
+
+ // TODO: Extract this as a proper plugin.
+ modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+
+ var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+ // Inject a listener for the backbutton on the document.
+ var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+ backButtonChannel.onHasSubscribersChange = function () {
+ // If we just attached the first handler or detached the last handler,
+ // let native know we need to override the back button.
+ exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [this.numHandlers === 1]);
+ };
+
+ // Add hardware MENU and SEARCH button handlers
+ cordova.addDocumentEventHandler('menubutton');
+ cordova.addDocumentEventHandler('searchbutton');
+
+ function bindButtonChannel (buttonName) {
+ // generic button bind used for volumeup/volumedown buttons
+ var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+ volumeButtonChannel.onHasSubscribersChange = function () {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [buttonName, this.numHandlers === 1]);
+ };
+ }
+ // Inject a listener for the volume buttons on the document.
+ bindButtonChannel('volumeup');
+ bindButtonChannel('volumedown');
+
+ // The resume event is not "sticky", but it is possible that the event
+ // will contain the result of a plugin call. We need to ensure that the
+ // plugin result is delivered even after the event is fired (CB-10498)
+ var cordovaAddEventListener = document.addEventListener;
+
+ document.addEventListener = function (evt, handler, capture) {
+ cordovaAddEventListener(evt, handler, capture);
+
+ if (evt === 'resume' && lastResumeEvent) {
+ handler(lastResumeEvent);
+ }
+ };
+
+ // Let native code know we are all done on the JS side.
+ // Native code will then un-hide the WebView.
+ channel.onCordovaReady.subscribe(function () {
+ exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+ exec(null, null, APP_PLUGIN_NAME, 'show', []);
+ });
+ }
+};
+
+function onMessageFromNative (msg) {
+ var cordova = require('cordova');
+ var action = msg.action;
+
+ switch (action) {
+ // pause and resume are Android app life cycle events
+ case 'backbutton':
+ case 'menubutton':
+ case 'searchbutton':
+ case 'pause':
+ case 'volumedownbutton':
+ case 'volumeupbutton':
+ cordova.fireDocumentEvent(action);
+ break;
+ case 'resume':
+ if (arguments.length > 1 && msg.pendingResult) {
+ if (arguments.length === 2) {
+ msg.pendingResult.result = arguments[1];
+ } else {
+ // The plugin returned a multipart message
+ var res = [];
+ for (var i = 1; i < arguments.length; i++) {
+ res.push(arguments[i]);
+ }
+ msg.pendingResult.result = res;
+ }
+
+ // Save the plugin result so that it can be delivered to the js
+ // even if they miss the initial firing of the event
+ lastResumeEvent = msg;
+ }
+ cordova.fireDocumentEvent(action, msg);
+ break;
+ default:
+ throw new Error('Unknown event action ' + action);
+ }
+}
--- /dev/null
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+ /**
+ * Clear the resource cache.
+ */
+ clearCache: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'clearCache', []);
+ },
+
+ /**
+ * Load the url into the webview or into new browser instance.
+ *
+ * @param url The URL to load
+ * @param props Properties that can be passed in to the activity:
+ * wait: int => wait msec before loading URL
+ * loadingDialog: "Title,Message" => display a native loading dialog
+ * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
+ * clearHistory: boolean => clear webview history (default=false)
+ * openExternal: boolean => open in a new browser (default=false)
+ *
+ * Example:
+ * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+ */
+ loadUrl: function (url, props) {
+ exec(null, null, APP_PLUGIN_NAME, 'loadUrl', [url, props]);
+ },
+
+ /**
+ * Cancel loadUrl that is waiting to be loaded.
+ */
+ cancelLoadUrl: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'cancelLoadUrl', []);
+ },
+
+ /**
+ * Clear web history in this web view.
+ * Instead of BACK button loading the previous web page, it will exit the app.
+ */
+ clearHistory: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'clearHistory', []);
+ },
+
+ /**
+ * Go to previous page displayed.
+ * This is the same as pressing the backbutton on Android device.
+ */
+ backHistory: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'backHistory', []);
+ },
+
+ /**
+ * Override the default behavior of the Android back button.
+ * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+ *
+ * Note: The user should not have to call this method. Instead, when the user
+ * registers for the "backbutton" event, this is automatically done.
+ *
+ * @param override T=override, F=cancel override
+ */
+ overrideBackbutton: function (override) {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [override]);
+ },
+
+ /**
+ * Override the default behavior of the Android volume button.
+ * If overridden, when the volume button is pressed, the "volume[up|down]button"
+ * JavaScript event will be fired.
+ *
+ * Note: The user should not have to call this method. Instead, when the user
+ * registers for the "volume[up|down]button" event, this is automatically done.
+ *
+ * @param button volumeup, volumedown
+ * @param override T=override, F=cancel override
+ */
+ overrideButton: function (button, override) {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [button, override]);
+ },
+
+ /**
+ * Exit and terminate the application.
+ */
+ exitApp: function () {
+ return exec(null, null, APP_PLUGIN_NAME, 'exitApp', []);
+ }
+};
--- /dev/null
+// Platform: android
+// 538a985db128858c0a0eb4dd40fb9c8e5433fc94
+/*
+ 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.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '9.0.0';
+// file: src/scripts/require.js
+var require;
+var define;
+
+(function () {
+ var modules = {};
+ // Stack of moduleIds currently being built.
+ var requireStack = [];
+ // Map of module ID -> index into requireStack of modules currently being built.
+ var inProgressModules = {};
+ var SEPARATOR = '.';
+
+ function build (module) {
+ var factory = module.factory;
+ var localRequire = function (id) {
+ var resultantId = id;
+ // Its a relative path, so lop off the last portion and add the id (minus "./")
+ if (id.charAt(0) === '.') {
+ resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+ }
+ return require(resultantId);
+ };
+ module.exports = {};
+ delete module.factory;
+ factory(localRequire, module.exports, module);
+ return module.exports;
+ }
+
+ require = function (id) {
+ if (!modules[id]) {
+ throw new Error('module ' + id + ' not found');
+ } else if (id in inProgressModules) {
+ var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+ throw new Error('Cycle in require graph: ' + cycle);
+ }
+ if (modules[id].factory) {
+ try {
+ inProgressModules[id] = requireStack.length;
+ requireStack.push(id);
+ return build(modules[id]);
+ } finally {
+ delete inProgressModules[id];
+ requireStack.pop();
+ }
+ }
+ return modules[id].exports;
+ };
+
+ define = function (id, factory) {
+ if (Object.prototype.hasOwnProperty.call(modules, id)) {
+ throw new Error('module ' + id + ' already defined');
+ }
+
+ modules[id] = {
+ id: id,
+ factory: factory
+ };
+ };
+
+ define.remove = function (id) {
+ delete modules[id];
+ };
+
+ define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+ module.exports.require = require;
+ module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) {
+ throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ if (typeof documentEventHandlers[e] !== 'undefined') {
+ documentEventHandlers[e].subscribe(handler);
+ } else {
+ m_document_addEventListener.call(document, evt, handler, capture);
+ }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ if (typeof windowEventHandlers[e] !== 'undefined') {
+ windowEventHandlers[e].subscribe(handler);
+ } else {
+ m_window_addEventListener.call(window, evt, handler, capture);
+ }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ // If unsubscribing from an event that is handled by a plugin
+ if (typeof documentEventHandlers[e] !== 'undefined') {
+ documentEventHandlers[e].unsubscribe(handler);
+ } else {
+ m_document_removeEventListener.call(document, evt, handler, capture);
+ }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+ var e = evt.toLowerCase();
+ // If unsubscribing from an event that is handled by a plugin
+ if (typeof windowEventHandlers[e] !== 'undefined') {
+ windowEventHandlers[e].unsubscribe(handler);
+ } else {
+ m_window_removeEventListener.call(window, evt, handler, capture);
+ }
+};
+
+function createEvent (type, data) {
+ var event = document.createEvent('Events');
+ event.initEvent(type, false, false);
+ if (data) {
+ for (var i in data) {
+ if (Object.prototype.hasOwnProperty.call(data, i)) {
+ event[i] = data[i];
+ }
+ }
+ }
+ return event;
+}
+
+var cordova = {
+ define: define,
+ require: require,
+ version: PLATFORM_VERSION_BUILD_LABEL,
+ platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+ platformId: platform.id,
+
+ /**
+ * Methods to add/remove your own addEventListener hijacking on document + window.
+ */
+ addWindowEventHandler: function (event) {
+ return (windowEventHandlers[event] = channel.create(event));
+ },
+ addStickyDocumentEventHandler: function (event) {
+ return (documentEventHandlers[event] = channel.createSticky(event));
+ },
+ addDocumentEventHandler: function (event) {
+ return (documentEventHandlers[event] = channel.create(event));
+ },
+ removeWindowEventHandler: function (event) {
+ delete windowEventHandlers[event];
+ },
+ removeDocumentEventHandler: function (event) {
+ delete documentEventHandlers[event];
+ },
+
+ /**
+ * Retrieve original event handlers that were replaced by Cordova
+ *
+ * @return object
+ */
+ getOriginalHandlers: function () {
+ return {
+ document: {
+ addEventListener: m_document_addEventListener,
+ removeEventListener: m_document_removeEventListener
+ },
+ window: {
+ addEventListener: m_window_addEventListener,
+ removeEventListener: m_window_removeEventListener
+ }
+ };
+ },
+
+ /**
+ * Method to fire event from native code
+ * bNoDetach is required for events which cause an exception which needs to be caught in native code
+ */
+ fireDocumentEvent: function (type, data, bNoDetach) {
+ var evt = createEvent(type, data);
+ if (typeof documentEventHandlers[type] !== 'undefined') {
+ if (bNoDetach) {
+ documentEventHandlers[type].fire(evt);
+ } else {
+ setTimeout(function () {
+ // Fire deviceready on listeners that were registered before cordova.js was loaded.
+ if (type === 'deviceready') {
+ document.dispatchEvent(evt);
+ }
+ documentEventHandlers[type].fire(evt);
+ }, 0);
+ }
+ } else {
+ document.dispatchEvent(evt);
+ }
+ },
+
+ fireWindowEvent: function (type, data) {
+ var evt = createEvent(type, data);
+ if (typeof windowEventHandlers[type] !== 'undefined') {
+ setTimeout(function () {
+ windowEventHandlers[type].fire(evt);
+ }, 0);
+ } else {
+ window.dispatchEvent(evt);
+ }
+ },
+
+ /**
+ * Plugin callback mechanism.
+ */
+ // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+ // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+ callbackId: Math.floor(Math.random() * 2000000000),
+ callbacks: {},
+ callbackStatus: {
+ NO_RESULT: 0,
+ OK: 1,
+ CLASS_NOT_FOUND_EXCEPTION: 2,
+ ILLEGAL_ACCESS_EXCEPTION: 3,
+ INSTANTIATION_EXCEPTION: 4,
+ MALFORMED_URL_EXCEPTION: 5,
+ IO_EXCEPTION: 6,
+ INVALID_ACTION: 7,
+ JSON_EXCEPTION: 8,
+ ERROR: 9
+ },
+
+ /**
+ * Called by native code when returning successful result from an action.
+ */
+ callbackSuccess: function (callbackId, args) {
+ cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+ },
+
+ /**
+ * Called by native code when returning error result from an action.
+ */
+ callbackError: function (callbackId, args) {
+ // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+ // Derive success from status.
+ cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+ },
+
+ /**
+ * Called by native code when returning the result from an action.
+ */
+ callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+ try {
+ var callback = cordova.callbacks[callbackId];
+ if (callback) {
+ if (isSuccess && status === cordova.callbackStatus.OK) {
+ callback.success && callback.success.apply(null, args);
+ } else if (!isSuccess) {
+ callback.fail && callback.fail.apply(null, args);
+ }
+ /*
+ else
+ Note, this case is intentionally not caught.
+ this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+ which is used to remove a callback from the list without calling the callbacks
+ typically keepCallback is false in this case
+ */
+ // Clear callback if not expecting any more results
+ if (!keepCallback) {
+ delete cordova.callbacks[callbackId];
+ }
+ }
+ } catch (err) {
+ var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+ cordova.fireWindowEvent('cordovacallbackerror', { message: msg, error: err });
+ throw err;
+ }
+ },
+
+ addConstructor: function (func) {
+ channel.onCordovaReady.subscribe(function () {
+ try {
+ func();
+ } catch (e) {
+ console.log('Failed to run constructor: ' + e);
+ }
+ });
+ }
+};
+
+module.exports = cordova;
+
+});
+
+// file: ../cordova-android/cordova-js-src/android/nativeapiprovider.js
+define("cordova/android/nativeapiprovider", function(require, exports, module) {
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+ get: function () { return currentApi; },
+ setPreferPrompt: function (value) {
+ currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+ },
+ // Used only by tests.
+ set: function (value) {
+ currentApi = value;
+ }
+};
+
+});
+
+// file: ../cordova-android/cordova-js-src/android/promptbasednativeapi.js
+define("cordova/android/promptbasednativeapi", function(require, exports, module) {
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+ exec: function (bridgeSecret, service, action, callbackId, argsJson) {
+ return prompt(argsJson, 'gap:' + JSON.stringify([bridgeSecret, service, action, callbackId]));
+ },
+ setNativeToJsBridgeMode: function (bridgeSecret, value) {
+ prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+ },
+ retrieveJsMessages: function (bridgeSecret, fromOnlineEvent) {
+ return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+ }
+};
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+ A: 'Array',
+ D: 'Date',
+ N: 'Number',
+ S: 'String',
+ F: 'Function',
+ O: 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+ return (/\(\s*([^)]*?)\s*\)/).exec(callee)[1].split(/\s*,\s*/)[argIndex];
+}
+
+/**
+ * Checks the given arguments' types and throws if they are not as expected.
+ *
+ * `spec` is a string where each character stands for the required type of the
+ * argument at the same position. In other words: the character at `spec[i]`
+ * specifies the required type for `args[i]`. The characters in `spec` are the
+ * first letter of the required type's name. The supported types are:
+ *
+ * Array, Date, Number, String, Function, Object
+ *
+ * Lowercase characters specify arguments that must not be `null` or `undefined`
+ * while uppercase characters allow those values to be passed.
+ *
+ * Finally, `*` can be used to allow any type at the corresponding position.
+ *
+ * @example
+ * function foo (arr, opts) {
+ * // require `arr` to be an Array and `opts` an Object, null or undefined
+ * checkArgs('aO', 'my.package.foo', arguments);
+ * // ...
+ * }
+ * @param {String} spec - the type specification for `args` as described above
+ * @param {String} functionName - full name of the callee.
+ * Used in the error message
+ * @param {Array|arguments} args - the arguments to be checked against `spec`
+ * @param {Function} [opt_callee=args.callee] - the recipient of `args`.
+ * Used to extract parameter names for the error message
+ * @throws {TypeError} if args do not satisfy spec
+ */
+function checkArgs (spec, functionName, args, opt_callee) {
+ if (!moduleExports.enableChecks) {
+ return;
+ }
+ var errMsg = null;
+ var typeName;
+ for (var i = 0; i < spec.length; ++i) {
+ var c = spec.charAt(i);
+ var cUpper = c.toUpperCase();
+ var arg = args[i];
+ // Asterix means allow anything.
+ if (c === '*') {
+ continue;
+ }
+ typeName = utils.typeName(arg);
+ if ((arg === null || arg === undefined) && c === cUpper) {
+ continue;
+ }
+ if (typeName !== typeMap[cUpper]) {
+ errMsg = 'Expected ' + typeMap[cUpper];
+ break;
+ }
+ }
+ if (errMsg) {
+ errMsg += ', but got ' + typeName + '.';
+ errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+ // Don't log when running unit tests.
+ if (typeof jasmine === 'undefined') {
+ console.error(errMsg);
+ }
+ throw TypeError(errMsg);
+ }
+}
+
+function getValue (value, defaultValue) {
+ return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+ var array = new Uint8Array(arrayBuffer);
+ return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+ var decodedStr = atob(str);
+ var arrayBuffer = new ArrayBuffer(decodedStr.length);
+ var array = new Uint8Array(arrayBuffer);
+ for (var i = 0, len = decodedStr.length; i < len; i++) {
+ array[i] = decodedStr.charCodeAt(i);
+ }
+ return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+ b64_12bit = [];
+ for (var i = 0; i < 64; i++) {
+ for (var j = 0; j < 64; j++) {
+ b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+ }
+ }
+ b64_12bitTable = function () { return b64_12bit; };
+ return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+ var numBytes = rawData.byteLength;
+ var output = '';
+ var segment;
+ var table = b64_12bitTable();
+ for (var i = 0; i < numBytes - 2; i += 3) {
+ segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+ output += table[segment >> 12];
+ output += table[segment & 0xfff];
+ }
+ if (numBytes - i === 2) {
+ segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+ output += table[segment >> 12];
+ output += b64_6bit[(segment & 0xfff) >> 6];
+ output += '=';
+ } else if (numBytes - i === 1) {
+ segment = (rawData[i] << 16);
+ output += table[segment >> 12];
+ output += '==';
+ }
+ return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+ for (var prop in objects) {
+ if (Object.prototype.hasOwnProperty.call(objects, prop)) {
+ func.apply(context, [objects[prop], prop]);
+ }
+ }
+}
+
+function clobber (obj, key, value) {
+ var needsProperty = false;
+ try {
+ obj[key] = value;
+ } catch (e) {
+ needsProperty = true;
+ }
+ // Getters can only be overridden by getters.
+ if (needsProperty || obj[key] !== value) {
+ utils.defineGetter(obj, key, function () {
+ return value;
+ });
+ }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+ if (message) {
+ utils.defineGetter(obj, key, function () {
+ console.log(message);
+ delete obj[key];
+ clobber(obj, key, value);
+ return value;
+ });
+ } else {
+ clobber(obj, key, value);
+ }
+}
+
+function include (parent, objects, clobber, merge) {
+ each(objects, function (obj, key) {
+ try {
+ var result = obj.path ? require(obj.path) : {};
+
+ if (clobber) {
+ // Clobber if it doesn't exist.
+ if (typeof parent[key] === 'undefined') {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ } else if (typeof obj.path !== 'undefined') {
+ // If merging, merge properties onto parent, otherwise, clobber.
+ if (merge) {
+ recursiveMerge(parent[key], result);
+ } else {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ }
+ }
+ result = parent[key];
+ } else {
+ // Overwrite if not currently defined.
+ if (typeof parent[key] === 'undefined') {
+ assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+ } else {
+ // Set result to what already exists, so we can build children into it if they exist.
+ result = parent[key];
+ }
+ }
+
+ if (obj.children) {
+ include(result, obj.children, clobber, merge);
+ }
+ } catch (e) {
+ utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+ }
+ });
+}
+
+/**
+ * Merge properties from one object onto another recursively. Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+ for (var prop in src) {
+ if (Object.prototype.hasOwnProperty.call(src, prop)) {
+ if (target.prototype && target.prototype.constructor === target) {
+ // If the target object is a constructor override off prototype.
+ clobber(target.prototype, prop, src[prop]);
+ } else {
+ if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+ recursiveMerge(target[prop], src[prop]);
+ } else {
+ clobber(target, prop, src[prop]);
+ }
+ }
+ }
+ }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+ include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+ include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+ include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded* Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady* Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady* Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady* User event fired to indicate that Cordova is ready
+ * onResume User event fired to indicate a start/resume lifecycle event
+ * onPause User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ * deviceready Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ * pause App has moved to background
+ * resume App has returned to foreground
+ *
+ * Listeners can be registered as:
+ * document.addEventListener("deviceready", myDeviceReadyListener, false);
+ * document.addEventListener("resume", myResumeListener, false);
+ * document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ * window.onload
+ * window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type String the channel name
+ */
+var Channel = function (type, sticky) {
+ this.type = type;
+ // Map of guid -> function.
+ this.handlers = {};
+ // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+ this.state = sticky ? 1 : 0;
+ // Used in sticky mode to remember args passed to fire().
+ this.fireArgs = null;
+ // Used by onHasSubscribersChange to know if there are any listeners.
+ this.numHandlers = 0;
+ // Function that is called when the first listener is subscribed, or when
+ // the last listener is unsubscribed.
+ this.onHasSubscribersChange = null;
+};
+var channel = {
+ /**
+ * Calls the provided function only after all of the channels specified
+ * have been fired. All channels must be sticky channels.
+ */
+ join: function (h, c) {
+ var len = c.length;
+ var i = len;
+ var f = function () {
+ if (!(--i)) h();
+ };
+ for (var j = 0; j < len; j++) {
+ if (c[j].state === 0) {
+ throw Error('Can only use join with sticky channels.');
+ }
+ c[j].subscribe(f);
+ }
+ if (!len) h();
+ },
+
+ create: function (type) {
+ return (channel[type] = new Channel(type, false));
+ },
+ createSticky: function (type) {
+ return (channel[type] = new Channel(type, true));
+ },
+
+ /**
+ * cordova Channels that must fire before "deviceready" is fired.
+ */
+ deviceReadyChannelsArray: [],
+ deviceReadyChannelsMap: {},
+
+ /**
+ * Indicate that a feature needs to be initialized before it is ready to be used.
+ * This holds up Cordova's "deviceready" event until the feature has been initialized
+ * and Cordova.initComplete(feature) is called.
+ *
+ * @param feature {String} The unique feature name
+ */
+ waitForInitialization: function (feature) {
+ if (feature) {
+ var c = channel[feature] || this.createSticky(feature);
+ this.deviceReadyChannelsMap[feature] = c;
+ this.deviceReadyChannelsArray.push(c);
+ }
+ },
+
+ /**
+ * Indicate that initialization code has completed and the feature is ready to be used.
+ *
+ * @param feature {String} The unique feature name
+ */
+ initializationComplete: function (feature) {
+ var c = this.deviceReadyChannelsMap[feature];
+ if (c) {
+ c.fire();
+ }
+ }
+};
+
+function checkSubscriptionArgument (argument) {
+ if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+ throw new Error(
+ 'Must provide a function or an EventListener object ' +
+ 'implementing the handleEvent interface.'
+ );
+ }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+ checkSubscriptionArgument(eventListenerOrFunction);
+ var handleEvent, guid;
+
+ if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+ // Received an EventListener object implementing the handleEvent interface
+ handleEvent = eventListenerOrFunction.handleEvent;
+ eventListener = eventListenerOrFunction;
+ } else {
+ // Received a function to handle event
+ handleEvent = eventListenerOrFunction;
+ }
+
+ if (this.state === 2) {
+ handleEvent.apply(eventListener || this, this.fireArgs);
+ return;
+ }
+
+ guid = eventListenerOrFunction.observer_guid;
+ if (typeof eventListener === 'object') {
+ handleEvent = utils.close(eventListener, handleEvent);
+ }
+
+ if (!guid) {
+ // First time any channel has seen this subscriber
+ guid = '' + nextGuid++;
+ }
+ handleEvent.observer_guid = guid;
+ eventListenerOrFunction.observer_guid = guid;
+
+ // Don't add the same handler more than once.
+ if (!this.handlers[guid]) {
+ this.handlers[guid] = handleEvent;
+ this.numHandlers++;
+ if (this.numHandlers === 1) {
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+ checkSubscriptionArgument(eventListenerOrFunction);
+ var handleEvent, guid, handler;
+
+ if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+ // Received an EventListener object implementing the handleEvent interface
+ handleEvent = eventListenerOrFunction.handleEvent;
+ } else {
+ // Received a function to handle event
+ handleEvent = eventListenerOrFunction;
+ }
+
+ guid = handleEvent.observer_guid;
+ handler = this.handlers[guid];
+ if (handler) {
+ delete this.handlers[guid];
+ this.numHandlers--;
+ if (this.numHandlers === 0) {
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+ var fireArgs = Array.prototype.slice.call(arguments);
+ // Apply stickiness.
+ if (this.state === 1) {
+ this.state = 2;
+ this.fireArgs = fireArgs;
+ }
+ if (this.numHandlers) {
+ // Copy the values first so that it is safe to modify it from within
+ // callbacks.
+ var toCall = [];
+ for (var item in this.handlers) {
+ toCall.push(this.handlers[item]);
+ }
+ for (var i = 0; i < toCall.length; ++i) {
+ toCall[i].apply(this, fireArgs);
+ }
+ if (this.state === 2 && this.numHandlers) {
+ this.numHandlers = 0;
+ this.handlers = {};
+ this.onHasSubscribersChange && this.onHasSubscribersChange();
+ }
+ }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: ../cordova-android/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/**
+ * Execute a cordova command. It is up to the native side whether this action
+ * is synchronous or asynchronous. The native side can return:
+ * Synchronous: PluginResult object as a JSON string
+ * Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success The success callback
+ * @param {Function} fail The fail callback
+ * @param {String} service The name of the service to use
+ * @param {String} action Action to be run in cordova
+ * @param {String[]} [args] Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova');
+var nativeApiProvider = require('cordova/android/nativeapiprovider');
+var utils = require('cordova/utils');
+var base64 = require('cordova/base64');
+var channel = require('cordova/channel');
+var jsToNativeModes = {
+ PROMPT: 0,
+ JS_OBJECT: 1
+};
+var nativeToJsModes = {
+ // Polls for messages using the JS->Native bridge.
+ POLLING: 0,
+ // For LOAD_URL to be viable, it would need to have a work-around for
+ // the bug where the soft-keyboard gets dismissed when a message is sent.
+ LOAD_URL: 1,
+ // For the ONLINE_EVENT to be viable, it would need to intercept all event
+ // listeners (both through addEventListener and window.ononline) as well
+ // as set the navigator property itself.
+ ONLINE_EVENT: 2,
+ EVAL_BRIDGE: 3
+};
+var jsToNativeBridgeMode; // Set lazily.
+var nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE;
+var pollEnabled = false;
+var bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise === 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function (fn) { resolvedPromise.then(fn); } : function (fn) { setTimeout(fn); };
+
+function androidExec (success, fail, service, action, args) {
+ if (bridgeSecret < 0) {
+ // If we ever catch this firing, we'll need to queue up exec()s
+ // and fire them once we get a secret. For now, I don't think
+ // it's possible for exec() to be called since plugins are parsed but
+ // not run until until after onNativeReady.
+ throw new Error('exec() called without bridgeSecret');
+ }
+ // Set default bridge modes if they have not already been set.
+ // By default, we use the failsafe, since addJavascriptInterface breaks too often
+ if (jsToNativeBridgeMode === undefined) {
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+ }
+
+ // If args is not provided, default to an empty array
+ args = args || [];
+
+ // Process any ArrayBuffers in the args into a string.
+ for (var i = 0; i < args.length; i++) {
+ if (utils.typeName(args[i]) === 'ArrayBuffer') {
+ args[i] = base64.fromArrayBuffer(args[i]);
+ }
+ }
+
+ var callbackId = service + cordova.callbackId++;
+ var argsJson = JSON.stringify(args);
+ if (success || fail) {
+ cordova.callbacks[callbackId] = { success: success, fail: fail };
+ }
+
+ var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+ // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+ // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
+ if (jsToNativeBridgeMode === jsToNativeModes.JS_OBJECT && msgs === '@Null arguments.') {
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+ androidExec(success, fail, service, action, args);
+ androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+ } else if (msgs) {
+ messagesFromNative.push(msgs);
+ // Always process async to avoid exceptions messing up stack.
+ nextTick(processMessages);
+ }
+}
+
+androidExec.init = function () {
+ bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+ channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent () {
+ pollOnce(true);
+}
+
+function pollOnce (opt_fromOnlineEvent) {
+ if (bridgeSecret < 0) {
+ // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+ // We know there's nothing to retrieve, so no need to poll.
+ return;
+ }
+ var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+ if (msgs) {
+ messagesFromNative.push(msgs);
+ // Process sync since we know we're already top-of-stack.
+ processMessages();
+ }
+}
+
+function pollingTimerFunc () {
+ if (pollEnabled) {
+ pollOnce();
+ setTimeout(pollingTimerFunc, 50);
+ }
+}
+
+function hookOnlineApis () {
+ function proxyEvent (e) {
+ cordova.fireWindowEvent(e.type);
+ }
+ // The network module takes care of firing online and offline events.
+ // It currently fires them only on document though, so we bridge them
+ // to window here (while first listening for exec()-releated online/offline
+ // events).
+ window.addEventListener('online', pollOnceFromOnlineEvent, false);
+ window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+ cordova.addWindowEventHandler('online');
+ cordova.addWindowEventHandler('offline');
+ document.addEventListener('online', proxyEvent, false);
+ document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function (mode) {
+ if (mode === jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+ mode = jsToNativeModes.PROMPT;
+ }
+ nativeApiProvider.setPreferPrompt(mode === jsToNativeModes.PROMPT);
+ jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function (mode) {
+ if (mode === nativeToJsBridgeMode) {
+ return;
+ }
+ if (nativeToJsBridgeMode === nativeToJsModes.POLLING) {
+ pollEnabled = false;
+ }
+
+ nativeToJsBridgeMode = mode;
+ // Tell the native side to switch modes.
+ // Otherwise, it will be set by androidExec.init()
+ if (bridgeSecret >= 0) {
+ nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+ }
+
+ if (mode === nativeToJsModes.POLLING) {
+ pollEnabled = true;
+ setTimeout(pollingTimerFunc, 1);
+ }
+};
+
+function buildPayload (payload, message) {
+ var payloadKind = message.charAt(0);
+ if (payloadKind === 's') {
+ payload.push(message.slice(1));
+ } else if (payloadKind === 't') {
+ payload.push(true);
+ } else if (payloadKind === 'f') {
+ payload.push(false);
+ } else if (payloadKind === 'N') {
+ payload.push(null);
+ } else if (payloadKind === 'n') {
+ payload.push(+message.slice(1));
+ } else if (payloadKind === 'A') {
+ var data = message.slice(1);
+ payload.push(base64.toArrayBuffer(data));
+ } else if (payloadKind === 'S') {
+ payload.push(window.atob(message.slice(1)));
+ } else if (payloadKind === 'M') {
+ var multipartMessages = message.slice(1);
+ while (multipartMessages !== '') {
+ var spaceIdx = multipartMessages.indexOf(' ');
+ var msgLen = +multipartMessages.slice(0, spaceIdx);
+ var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+ multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+ buildPayload(payload, multipartMessage);
+ }
+ } else {
+ payload.push(JSON.parse(message));
+ }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage (message) {
+ var firstChar = message.charAt(0);
+ if (firstChar === 'J') {
+ // This is deprecated on the .java side. It doesn't work with CSP enabled.
+ // eslint-disable-next-line no-eval
+ eval(message.slice(1));
+ } else if (firstChar === 'S' || firstChar === 'F') {
+ var success = firstChar === 'S';
+ var keepCallback = message.charAt(1) === '1';
+ var spaceIdx = message.indexOf(' ', 2);
+ var status = +message.slice(2, spaceIdx);
+ var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+ var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+ var payloadMessage = message.slice(nextSpaceIdx + 1);
+ var payload = [];
+ buildPayload(payload, payloadMessage);
+ cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+ } else {
+ console.log('processMessage failed: invalid message: ' + JSON.stringify(message));
+ }
+}
+
+function processMessages () {
+ // Check for the reentrant case.
+ if (isProcessing) {
+ return;
+ }
+ if (messagesFromNative.length === 0) {
+ return;
+ }
+ isProcessing = true;
+ try {
+ var msg = popMessageFromQueue();
+ // The Java side can send a * message to indicate that it
+ // still has messages waiting to be retrieved.
+ if (msg === '*' && messagesFromNative.length === 0) {
+ nextTick(pollOnce);
+ return;
+ }
+ processMessage(msg);
+ } finally {
+ isProcessing = false;
+ if (messagesFromNative.length > 0) {
+ nextTick(processMessages);
+ }
+ }
+}
+
+function popMessageFromQueue () {
+ var messageBatch = messagesFromNative.shift();
+ if (messageBatch === '*') {
+ return '*';
+ }
+
+ var spaceIdx = messageBatch.indexOf(' ');
+ var msgLen = +messageBatch.slice(0, spaceIdx);
+ var message = messageBatch.substr(spaceIdx + 1, msgLen);
+ messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+ if (messageBatch) {
+ messagesFromNative.unshift(messageBatch);
+ }
+ return message;
+}
+
+module.exports = androidExec;
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+ // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+ add: function (id, proxyObj) {
+ console.log('adding proxy for ' + id);
+ CommandProxyMap[id] = proxyObj;
+ return proxyObj;
+ },
+
+ // cordova.commandProxy.remove("Accelerometer");
+ remove: function (id) {
+ var proxy = CommandProxyMap[id];
+ delete CommandProxyMap[id];
+ CommandProxyMap[id] = null;
+ return proxy;
+ },
+
+ get: function (service, action) {
+ return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+ }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+ for (var i = 0; i < arr.length; ++i) {
+ if (arr[i].state !== 2) {
+ console.log('Channel not fired: ' + arr[i].type);
+ }
+ }
+}
+
+window.setTimeout(function () {
+ if (channel.onDeviceReady.state !== 2) {
+ console.log('deviceready has not fired after 5 seconds.');
+ logUnfiredChannels(platformInitChannelsArray);
+ logUnfiredChannels(channel.deviceReadyChannelsArray);
+ }
+}, 5000);
+
+if (!window.console) {
+ window.console = {
+ log: function () {}
+ };
+}
+if (!window.console.warn) {
+ window.console.warn = function (msg) {
+ this.log('warn: ' + msg);
+ };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+ channel.onDOMContentLoaded.fire();
+} else {
+ document.addEventListener('DOMContentLoaded', function () {
+ channel.onDOMContentLoaded.fire();
+ }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+ channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+ pluginloader.load(function () {
+ channel.onPluginsReady.fire();
+ });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+ modulemapper.mapModules(window);
+
+ platform.initialize && platform.initialize();
+
+ // Fire event to notify that all objects are created
+ channel.onCordovaReady.fire();
+
+ // Fire onDeviceReady event once page has fully loaded, all
+ // constructors have run and cordova info has been received from native
+ // side.
+ channel.join(function () {
+ require('cordova').fireDocumentEvent('deviceready');
+ }, channel.deviceReadyChannelsArray);
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap;
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+ symbolList = [];
+ deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+ if (!(moduleName in moduleMap)) {
+ throw new Error('Module ' + moduleName + ' does not exist.');
+ }
+ symbolList.push(strategy, moduleName, symbolPath);
+ if (opt_deprecationMessage) {
+ deprecationMap[symbolPath] = opt_deprecationMessage;
+ }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+ addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+ addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+ if (!symbolPath) {
+ return context;
+ }
+ return symbolPath.split('.').reduce(function (cur, part) {
+ return (cur[part] = cur[part] || {});
+ }, context);
+}
+
+exports.mapModules = function (context) {
+ var origSymbols = {};
+ context.CDV_origSymbols = origSymbols;
+ for (var i = 0, len = symbolList.length; i < len; i += 3) {
+ var strategy = symbolList[i];
+ var moduleName = symbolList[i + 1];
+ var module = require(moduleName);
+ // <runs/>
+ if (strategy === 'r') {
+ continue;
+ }
+ var symbolPath = symbolList[i + 2];
+ var lastDot = symbolPath.lastIndexOf('.');
+ var namespace = symbolPath.substr(0, lastDot);
+ var lastName = symbolPath.substr(lastDot + 1);
+
+ var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+ var parentObj = prepareNamespace(namespace, context);
+ var target = parentObj[lastName];
+
+ if (strategy === 'm' && target) {
+ builder.recursiveMerge(target, module);
+ } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+ if (!(symbolPath in origSymbols)) {
+ origSymbols[symbolPath] = target;
+ }
+ builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+ }
+ }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+ var origSymbols = context.CDV_origSymbols;
+ if (origSymbols && (symbolPath in origSymbols)) {
+ return origSymbols[symbolPath];
+ }
+ var parts = symbolPath.split('.');
+ var obj = context;
+ for (var i = 0; i < parts.length; ++i) {
+ obj = obj && obj[parts[i]];
+ }
+ return obj;
+};
+
+exports.reset();
+
+});
+
+// file: ../cordova-android/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
+
+module.exports = {
+ id: 'android',
+ bootstrap: function () {
+ var channel = require('cordova/channel');
+ var cordova = require('cordova');
+ var exec = require('cordova/exec');
+ var modulemapper = require('cordova/modulemapper');
+
+ // Get the shared secret needed to use the bridge.
+ exec.init();
+
+ // TODO: Extract this as a proper plugin.
+ modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+
+ var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+ // Inject a listener for the backbutton on the document.
+ var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+ backButtonChannel.onHasSubscribersChange = function () {
+ // If we just attached the first handler or detached the last handler,
+ // let native know we need to override the back button.
+ exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [this.numHandlers === 1]);
+ };
+
+ // Add hardware MENU and SEARCH button handlers
+ cordova.addDocumentEventHandler('menubutton');
+ cordova.addDocumentEventHandler('searchbutton');
+
+ function bindButtonChannel (buttonName) {
+ // generic button bind used for volumeup/volumedown buttons
+ var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+ volumeButtonChannel.onHasSubscribersChange = function () {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [buttonName, this.numHandlers === 1]);
+ };
+ }
+ // Inject a listener for the volume buttons on the document.
+ bindButtonChannel('volumeup');
+ bindButtonChannel('volumedown');
+
+ // The resume event is not "sticky", but it is possible that the event
+ // will contain the result of a plugin call. We need to ensure that the
+ // plugin result is delivered even after the event is fired (CB-10498)
+ var cordovaAddEventListener = document.addEventListener;
+
+ document.addEventListener = function (evt, handler, capture) {
+ cordovaAddEventListener(evt, handler, capture);
+
+ if (evt === 'resume' && lastResumeEvent) {
+ handler(lastResumeEvent);
+ }
+ };
+
+ // Let native code know we are all done on the JS side.
+ // Native code will then un-hide the WebView.
+ channel.onCordovaReady.subscribe(function () {
+ exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+ exec(null, null, APP_PLUGIN_NAME, 'show', []);
+ });
+ }
+};
+
+function onMessageFromNative (msg) {
+ var cordova = require('cordova');
+ var action = msg.action;
+
+ switch (action) {
+ // pause and resume are Android app life cycle events
+ case 'backbutton':
+ case 'menubutton':
+ case 'searchbutton':
+ case 'pause':
+ case 'volumedownbutton':
+ case 'volumeupbutton':
+ cordova.fireDocumentEvent(action);
+ break;
+ case 'resume':
+ if (arguments.length > 1 && msg.pendingResult) {
+ if (arguments.length === 2) {
+ msg.pendingResult.result = arguments[1];
+ } else {
+ // The plugin returned a multipart message
+ var res = [];
+ for (var i = 1; i < arguments.length; i++) {
+ res.push(arguments[i]);
+ }
+ msg.pendingResult.result = res;
+ }
+
+ // Save the plugin result so that it can be delivered to the js
+ // even if they miss the initial firing of the event
+ lastResumeEvent = msg;
+ }
+ cordova.fireDocumentEvent(action, msg);
+ break;
+ default:
+ throw new Error('Unknown event action ' + action);
+ }
+}
+
+});
+
+// file: ../cordova-android/cordova-js-src/plugin/android/app.js
+define("cordova/plugin/android/app", function(require, exports, module) {
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+ /**
+ * Clear the resource cache.
+ */
+ clearCache: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'clearCache', []);
+ },
+
+ /**
+ * Load the url into the webview or into new browser instance.
+ *
+ * @param url The URL to load
+ * @param props Properties that can be passed in to the activity:
+ * wait: int => wait msec before loading URL
+ * loadingDialog: "Title,Message" => display a native loading dialog
+ * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
+ * clearHistory: boolean => clear webview history (default=false)
+ * openExternal: boolean => open in a new browser (default=false)
+ *
+ * Example:
+ * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+ */
+ loadUrl: function (url, props) {
+ exec(null, null, APP_PLUGIN_NAME, 'loadUrl', [url, props]);
+ },
+
+ /**
+ * Cancel loadUrl that is waiting to be loaded.
+ */
+ cancelLoadUrl: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'cancelLoadUrl', []);
+ },
+
+ /**
+ * Clear web history in this web view.
+ * Instead of BACK button loading the previous web page, it will exit the app.
+ */
+ clearHistory: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'clearHistory', []);
+ },
+
+ /**
+ * Go to previous page displayed.
+ * This is the same as pressing the backbutton on Android device.
+ */
+ backHistory: function () {
+ exec(null, null, APP_PLUGIN_NAME, 'backHistory', []);
+ },
+
+ /**
+ * Override the default behavior of the Android back button.
+ * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+ *
+ * Note: The user should not have to call this method. Instead, when the user
+ * registers for the "backbutton" event, this is automatically done.
+ *
+ * @param override T=override, F=cancel override
+ */
+ overrideBackbutton: function (override) {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [override]);
+ },
+
+ /**
+ * Override the default behavior of the Android volume button.
+ * If overridden, when the volume button is pressed, the "volume[up|down]button"
+ * JavaScript event will be fired.
+ *
+ * Note: The user should not have to call this method. Instead, when the user
+ * registers for the "volume[up|down]button" event, this is automatically done.
+ *
+ * @param button volumeup, volumedown
+ * @param override T=override, F=cancel override
+ */
+ overrideButton: function (button, override) {
+ exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [button, override]);
+ },
+
+ /**
+ * Exit and terminate the application.
+ */
+ exitApp: function () {
+ return exec(null, null, APP_PLUGIN_NAME, 'exitApp', []);
+ }
+};
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+ var script = document.createElement('script');
+ // onload fires even when script fails loads with an error.
+ script.onload = onload;
+ // onerror fires for malformed URLs.
+ script.onerror = onerror;
+ script.src = url;
+ document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+ onerror = onerror || onload;
+ if (id in define.moduleMap) {
+ onload();
+ } else {
+ exports.injectScript(url, function () {
+ if (id in define.moduleMap) {
+ onload();
+ } else {
+ onerror();
+ }
+ }, onerror);
+ }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+ // Loop through all the plugins and then through their clobbers and merges.
+ for (var i = 0, module; (module = moduleList[i]); i++) {
+ if (module.clobbers && module.clobbers.length) {
+ for (var j = 0; j < module.clobbers.length; j++) {
+ modulemapper.clobbers(module.id, module.clobbers[j]);
+ }
+ }
+
+ if (module.merges && module.merges.length) {
+ for (var k = 0; k < module.merges.length; k++) {
+ modulemapper.merges(module.id, module.merges[k]);
+ }
+ }
+
+ // Finally, if runs is truthy we want to simply require() the module.
+ if (module.runs) {
+ modulemapper.runs(module.id);
+ }
+ }
+
+ finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+ // Now inject the scripts.
+ var scriptCounter = moduleList.length;
+
+ if (!scriptCounter) {
+ finishPluginLoading();
+ return;
+ }
+ function scriptLoadedCallback () {
+ if (!--scriptCounter) {
+ onScriptLoadingComplete(moduleList, finishPluginLoading);
+ }
+ }
+
+ for (var i = 0; i < moduleList.length; i++) {
+ injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+ }
+}
+
+function findCordovaPath () {
+ var path = null;
+ var scripts = document.getElementsByTagName('script');
+ var term = '/cordova.js';
+ for (var n = scripts.length - 1; n > -1; n--) {
+ var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+ if (src.indexOf(term) === (src.length - term.length)) {
+ path = src.substring(0, src.length - term.length) + '/';
+ break;
+ }
+ }
+ return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+ var pathPrefix = findCordovaPath();
+ if (pathPrefix === null) {
+ console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+ pathPrefix = '';
+ }
+ injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+ var moduleList = require('cordova/plugin_list');
+ handlePluginsObject(pathPrefix, moduleList, callback);
+ }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+ var anchorEl = document.createElement('a');
+ anchorEl.href = url;
+ return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+ if (Object.defineProperty) {
+ var desc = {
+ get: getFunc,
+ configurable: true
+ };
+ if (opt_setFunc) {
+ desc.set = opt_setFunc;
+ }
+ Object.defineProperty(obj, key, desc);
+ } else {
+ obj.__defineGetter__(key, getFunc);
+ if (opt_setFunc) {
+ obj.__defineSetter__(key, opt_setFunc);
+ }
+ }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+ if (a.indexOf) {
+ return a.indexOf(item);
+ }
+ var len = a.length;
+ for (var i = 0; i < len; ++i) {
+ if (a[i] === item) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+ var index = utils.arrayIndexOf(a, item);
+ if (index !== -1) {
+ a.splice(index, 1);
+ }
+ return index !== -1;
+};
+
+utils.typeName = function (val) {
+ return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+ function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+ return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+ if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+ return obj;
+ }
+
+ var retVal, i;
+
+ if (utils.isArray(obj)) {
+ retVal = [];
+ for (i = 0; i < obj.length; ++i) {
+ retVal.push(utils.clone(obj[i]));
+ }
+ return retVal;
+ }
+
+ retVal = {};
+ for (i in obj) {
+ // 'unknown' type may be returned in custom protocol activation case on
+ // Windows Phone 8.1 causing "No such interface supported" exception on
+ // cloning (https://issues.apache.org/jira/browse/CB-11522)
+ // eslint-disable-next-line valid-typeof
+ if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') {
+ retVal[i] = utils.clone(obj[i]);
+ }
+ }
+ return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+ return function () {
+ var args = params || arguments;
+ return func.apply(context, args);
+ };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+ var uuidpart = '';
+ for (var i = 0; i < length; i++) {
+ var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+ if (uuidchar.length === 1) {
+ uuidchar = '0' + uuidchar;
+ }
+ uuidpart += uuidchar;
+ }
+ return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+ return UUIDcreatePart(4) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(2) + '-' +
+ UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+ // proxy used to establish prototype chain
+ var F = function () {};
+ // extend Child from Parent
+ return function (Child, Parent) {
+ F.prototype = Parent.prototype;
+ Child.prototype = new F();
+ Child.__super__ = Parent.prototype;
+ Child.prototype.constructor = Child;
+ };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+ if (window.alert) {
+ window.alert(msg);
+ } else if (console && console.log) {
+ console.log(msg);
+ }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+require('cordova/init');
+
+})();
--- /dev/null
+cordova.define('cordova/plugin_list', function(require, exports, module) {
+ module.exports = [
+ {
+ "id": "cordova-plugin-device.device",
+ "file": "plugins/cordova-plugin-device/www/device.js",
+ "pluginId": "cordova-plugin-device",
+ "clobbers": [
+ "device"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.DirectoryEntry",
+ "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.DirectoryEntry"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.DirectoryReader",
+ "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.DirectoryReader"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.Entry",
+ "file": "plugins/cordova-plugin-file/www/Entry.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Entry"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.File",
+ "file": "plugins/cordova-plugin-file/www/File.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.File"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileEntry",
+ "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileEntry"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileError",
+ "file": "plugins/cordova-plugin-file/www/FileError.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileError"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileReader",
+ "file": "plugins/cordova-plugin-file/www/FileReader.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileReader"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileSystem",
+ "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileSystem"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileUploadOptions",
+ "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileUploadOptions"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileUploadResult",
+ "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileUploadResult"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.FileWriter",
+ "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.FileWriter"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.Flags",
+ "file": "plugins/cordova-plugin-file/www/Flags.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Flags"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.LocalFileSystem",
+ "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.LocalFileSystem"
+ ],
+ "merges": [
+ "window"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.Metadata",
+ "file": "plugins/cordova-plugin-file/www/Metadata.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.Metadata"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.ProgressEvent",
+ "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.ProgressEvent"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.fileSystems",
+ "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+ "pluginId": "cordova-plugin-file"
+ },
+ {
+ "id": "cordova-plugin-file.requestFileSystem",
+ "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+ "pluginId": "cordova-plugin-file",
+ "clobbers": [
+ "window.requestFileSystem"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+ "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "window"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.isChrome",
+ "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "id": "cordova-plugin-file.androidFileSystem",
+ "file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "FileSystem"
+ ]
+ },
+ {
+ "id": "cordova-plugin-file.fileSystems-roots",
+ "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
+ "pluginId": "cordova-plugin-file",
+ "runs": true
+ },
+ {
+ "id": "cordova-plugin-file.fileSystemPaths",
+ "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+ "pluginId": "cordova-plugin-file",
+ "merges": [
+ "cordova"
+ ],
+ "runs": true
+ },
+ {
+ "id": "es6-promise-plugin.Promise",
+ "file": "plugins/es6-promise-plugin/www/promise.js",
+ "pluginId": "es6-promise-plugin",
+ "runs": true
+ },
+ {
+ "id": "cordova-plugin-screen-orientation.screenorientation",
+ "file": "plugins/cordova-plugin-screen-orientation/www/screenorientation.js",
+ "pluginId": "cordova-plugin-screen-orientation",
+ "clobbers": [
+ "cordova.plugins.screenorientation"
+ ]
+ },
+ {
+ "id": "cordova-plugin-statusbar.statusbar",
+ "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+ "pluginId": "cordova-plugin-statusbar",
+ "clobbers": [
+ "window.StatusBar"
+ ]
+ },
+ {
+ "id": "com-darryncampbell-cordova-plugin-intent.IntentShim",
+ "file": "plugins/com-darryncampbell-cordova-plugin-intent/www/IntentShim.js",
+ "pluginId": "com-darryncampbell-cordova-plugin-intent",
+ "clobbers": [
+ "intentShim"
+ ]
+ }
+ ];
+ module.exports.metadata = {
+ "cordova-plugin-whitelist": "1.3.4",
+ "cordova-plugin-device": "2.0.3",
+ "cordova-plugin-file": "6.0.2",
+ "es6-promise-plugin": "4.2.2",
+ "cordova-plugin-screen-orientation": "3.0.2",
+ "cordova-plugin-statusbar": "2.4.3",
+ "com-darryncampbell-cordova-plugin-intent": "2.0.0"
+ };
+});
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ */
+* {
+ -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
+}
+
+body {
+ -webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */
+ -webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */
+ -webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */
+ background-color:#E4E4E4;
+ background-image:linear-gradient(to bottom, #A7A7A7 0%, #E4E4E4 51%);
+ font-family: system-ui, -apple-system, -apple-system-font, 'Segoe UI', 'Roboto', sans-serif;
+ font-size:12px;
+ height:100vh;
+ margin:0px;
+ padding:0px;
+ /* Padding to avoid the "unsafe" areas behind notches in the screen */
+ padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
+ text-transform:uppercase;
+ width:100%;
+}
+
+/* Portrait layout (default) */
+.app {
+ background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
+ position:absolute; /* position in the center of the screen */
+ left:50%;
+ top:50%;
+ height:50px; /* text area height */
+ width:225px; /* text area width */
+ text-align:center;
+ padding:180px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */
+ margin:-115px 0px 0px -112px; /* offset vertical: half of image height and text area height */
+ /* offset horizontal: half of text area width */
+}
+
+/* Landscape layout (with min-width) */
+@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
+ .app {
+ background-position:left center;
+ padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */
+ margin:-90px 0px 0px -198px; /* offset vertical: half of image height */
+ /* offset horizontal: half of image width and text area width */
+ }
+}
+
+h1 {
+ font-size:24px;
+ font-weight:normal;
+ margin:0px;
+ overflow:visible;
+ padding:0px;
+ text-align:center;
+}
+
+.event {
+ border-radius:4px;
+ color:#FFFFFF;
+ font-size:12px;
+ margin:0px 30px;
+ padding:2px 0px;
+}
+
+.event.listening {
+ background-color:#333333;
+ display:block;
+}
+
+.event.received {
+ background-color:#4B946A;
+ display:none;
+}
+
+#deviceready.ready .event.listening { display: none; }
+#deviceready.ready .event.received { display: block; }
+
+@keyframes fade {
+ from { opacity: 1.0; }
+ 50% { opacity: 0.4; }
+ to { opacity: 1.0; }
+}
+
+.blink {
+ animation:fade 3000ms infinite;
+ -webkit-animation:fade 3000ms infinite;
+}
+
+
+@media screen and (prefers-color-scheme: dark) {
+ body {
+ background-image:linear-gradient(to bottom, #585858 0%, #1B1B1B 51%);
+ }
+}
--- /dev/null
+<!DOCTYPE html>
+<!--
+ 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.
+-->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <!--
+ Customize this policy to fit your own app's needs. For more guidance, see:
+ https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
+ Some notes:
+ * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
+ * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
+ * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
+ * Enable inline JS: add 'unsafe-inline' to default-src
+ -->
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
+ <meta name="format-detection" content="telephone=no">
+ <meta name="msapplication-tap-highlight" content="no">
+ <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
+ <meta name="color-scheme" content="light dark">
+ <link rel="stylesheet" href="css/index.css">
+ <title>Hello World</title>
+ </head>
+ <body>
+ <div class="app">
+ <h1>Apache Cordova</h1>
+ <div id="deviceready" class="blink">
+ <p class="event listening">Connecting to Device</p>
+ <p class="event received">Device is Ready</p>
+ </div>
+ </div>
+ <script src="cordova.js"></script>
+ <script src="js/index.js"></script>
+ </body>
+</html>
--- /dev/null
+/*
+ * 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.
+ */
+
+// Wait for the deviceready event before using any of Cordova's device APIs.
+// See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready
+document.addEventListener('deviceready', onDeviceReady, false);
+
+function onDeviceReady() {
+ // Cordova is now initialized. Have fun!
+
+ console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
+ document.getElementById('deviceready').classList.add('ready');
+}
--- /dev/null
+cordova.define("com-darryncampbell-cordova-plugin-intent.IntentShim", function(require, exports, module) {
+var argscheck = require('cordova/argscheck'),
+ channel = require('cordova/channel'),
+ utils = require('cordova/utils'),
+ exec = require('cordova/exec'),
+ cordova = require('cordova');
+
+
+/**
+ * This represents a thin shim layer over the Android Intent implementation
+ * @constructor
+ */
+function IntentShim() {
+ var me = this;
+}
+
+IntentShim.prototype.ACTION_SEND = "android.intent.action.SEND";
+IntentShim.prototype.ACTION_VIEW= "android.intent.action.VIEW";
+IntentShim.prototype.ACTION_INSTALL_PACKAGE="android.intent.action.INSTALL_PACKAGE";
+IntentShim.prototype.ACTION_UNINSTALL_PACKAGE= "android.intent.action.UNINSTALL_PACKAGE";
+IntentShim.prototype.EXTRA_TEXT = "android.intent.extra.TEXT";
+IntentShim.prototype.EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
+IntentShim.prototype.EXTRA_STREAM = "android.intent.extra.STREAM";
+IntentShim.prototype.EXTRA_EMAIL = "android.intent.extra.EMAIL";
+IntentShim.prototype.ACTION_CALL = "android.intent.action.CALL";
+IntentShim.prototype.ACTION_SENDTO = "android.intent.action.SENDTO";
+// StartActivityForResult
+IntentShim.prototype.ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT";
+IntentShim.prototype.ACTION_PICK = "android.intent.action.PICK";
+IntentShim.prototype.RESULT_CANCELED = 0; // Activity.RESULT_CANCELED
+IntentShim.prototype.RESULT_OK = -1; // Activity.RESULT_OK
+
+IntentShim.prototype.startActivity = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.startActivity', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "startActivity", [params]);
+};
+
+IntentShim.prototype.startActivityForResult = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.startActivityForResult', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "startActivityForResult", [params]);
+};
+
+IntentShim.prototype.sendBroadcast = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.sendBroadcast', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "sendBroadcast", [params]);
+};
+
+IntentShim.prototype.startService = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.startService', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "startService", [params]);
+};
+
+IntentShim.prototype.registerBroadcastReceiver = function(params, callback) {
+ argscheck.checkArgs('of', 'IntentShim.registerBroadcastReceiver', arguments);
+ exec(callback, null, "IntentShim", "registerBroadcastReceiver", [params]);
+};
+
+IntentShim.prototype.unregisterBroadcastReceiver = function() {
+ argscheck.checkArgs('', 'IntentShim.unregisterBroadcastReceiver', arguments);
+ exec(null, null, "IntentShim", "unregisterBroadcastReceiver", []);
+};
+
+IntentShim.prototype.onIntent = function(callback) {
+ argscheck.checkArgs('f', 'IntentShim.onIntent', arguments);
+ exec(callback, null, "IntentShim", "onIntent", [callback]);
+};
+
+IntentShim.prototype.onActivityResult = function(callback) {
+ argscheck.checkArgs('f', 'IntentShim.onActivityResult', arguments);
+ exec(callback, null, "IntentShim", "onActivityResult", [callback]);
+};
+
+IntentShim.prototype.getIntent = function(successCallback, failureCallback) {
+ argscheck.checkArgs('ff', 'IntentShim.getIntent', arguments);
+ exec(successCallback, failureCallback, "IntentShim", "getIntent", []);
+};
+
+IntentShim.prototype.sendResult = function(params, callback) {
+ argscheck.checkArgs('of', 'IntentShim.sendResult', arguments);
+ exec(callback, null, "IntentShim", "sendResult", [params]);
+}
+
+IntentShim.prototype.realPathFromUri = function(params, successCallback, errorCallback) {
+ argscheck.checkArgs('off', 'IntentShim.realPathFromUri', arguments);
+ exec(successCallback, errorCallback, "IntentShim", "realPathFromUri", [params]);
+};
+
+window.intentShim = new IntentShim();
+window.plugins = window.plugins || {};
+window.plugins.intentShim = window.intentShim;
+});
--- /dev/null
+cordova.define("cordova-plugin-device.device", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+ this.available = false;
+ this.platform = null;
+ this.version = null;
+ this.uuid = null;
+ this.cordova = null;
+ this.model = null;
+ this.manufacturer = null;
+ this.isVirtual = null;
+ this.serial = null;
+
+ var me = this;
+
+ channel.onCordovaReady.subscribe(function () {
+ me.getInfo(function (info) {
+ // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+ // TODO: CB-5105 native implementations should not return info.cordova
+ var buildLabel = cordova.version;
+ me.available = true;
+ me.platform = info.platform;
+ me.version = info.version;
+ me.uuid = info.uuid;
+ me.cordova = buildLabel;
+ me.model = info.model;
+ me.isVirtual = info.isVirtual;
+ me.manufacturer = info.manufacturer || 'unknown';
+ me.serial = info.serial || 'unknown';
+ channel.onCordovaInfoReady.fire();
+ }, function (e) {
+ me.available = false;
+ utils.alert('[ERROR] Error initializing Cordova: ' + e);
+ });
+ });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+ argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+ exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileError = require('./FileError');
+var DirectoryReader = require('./DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) {
+
+ // add trailing slash if it is missing
+ if ((fullPath) && !/\/$/.test(fullPath)) {
+ fullPath += '/';
+ }
+ // add trailing slash if it is missing
+ if (nativeURL && !/\/$/.test(nativeURL)) {
+ nativeURL += '/';
+ }
+ DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function () {
+ return new DirectoryReader(this.toInternalURL());
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
+ argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
+ argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var FileEntry = require('./FileEntry');
+ var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader (localURL) {
+ this.localURL = localURL || null;
+ this.hasReadEntries = false;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
+ // If we've already read and passed on this directory's entries, return an empty list.
+ if (this.hasReadEntries) {
+ successCallback([]);
+ return;
+ }
+ var reader = this;
+ var win = typeof successCallback !== 'function' ? null : function (result) {
+ var retVal = [];
+ for (var i = 0; i < result.length; i++) {
+ var entry = null;
+ if (result[i].isDirectory) {
+ entry = new (require('./DirectoryEntry'))();
+ } else if (result[i].isFile) {
+ entry = new (require('./FileEntry'))();
+ }
+ entry.isDirectory = result[i].isDirectory;
+ entry.isFile = result[i].isFile;
+ entry.name = result[i].name;
+ entry.fullPath = result[i].fullPath;
+ entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
+ entry.nativeURL = result[i].nativeURL;
+ retVal.push(entry);
+ }
+ reader.hasReadEntries = true;
+ successCallback(retVal);
+ };
+ var fail = typeof errorCallback !== 'function' ? null : function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'readEntries', [this.localURL]);
+};
+
+module.exports = DirectoryReader;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var Metadata = require('./Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ * {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ * {boolean} true if Entry is a directory (readonly)
+ * @param name
+ * {DOMString} name of the file or directory, excluding the path
+ * leading to it (readonly)
+ * @param fullPath
+ * {DOMString} the absolute full path to the file or directory
+ * (readonly)
+ * @param fileSystem
+ * {FileSystem} the filesystem on which this entry resides
+ * (readonly)
+ * @param nativeURL
+ * {DOMString} an alternate URL which can be used by native
+ * webview controls, for example media players.
+ * (optional, readonly)
+ */
+function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
+ this.isFile = !!isFile;
+ this.isDirectory = !!isDirectory;
+ this.name = name || '';
+ this.fullPath = fullPath || '';
+ this.filesystem = fileSystem || null;
+ this.nativeURL = nativeURL || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ * {Function} is called with a Metadata object
+ * @param errorCallback
+ * {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+ var success = successCallback && function (entryMetadata) {
+ var metadata = new Metadata({
+ size: entryMetadata.size,
+ modificationTime: entryMetadata.lastModifiedDate
+ });
+ successCallback(metadata);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ * {Function} is called with a Metadata object
+ * @param errorCallback
+ * {Function} is called with a FileError
+ * @param metadataObject
+ * {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) {
+ argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+ exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ * {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ * {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ * {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ * {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
+ argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ var srcURL = this.toInternalURL();
+ // entry name
+ var name = newName || this.name;
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+ var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+ var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ }
+ } else {
+ // no Entry object returned
+ if (fail) {
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ }
+ };
+
+ // copy
+ exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ * {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ * {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ * {Function} called with the new Entry object
+ * @param errorCallback
+ * {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
+ argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ var srcURL = this.toInternalURL();
+ // entry name
+ var name = newName || this.name;
+ // success callback
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+ var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+ var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ }
+ } else {
+ // no Entry object returned
+ if (fail) {
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ }
+ };
+
+ // copy
+ exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Return a URL that can be passed across the bridge to identify this entry.
+ */
+Entry.prototype.toInternalURL = function () {
+ if (this.filesystem && this.filesystem.__format__) {
+ return this.filesystem.__format__(this.fullPath, this.nativeURL);
+ }
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ * Use a URL that can be used to as the src attribute of a <video> or
+ * <audio> tag. If that is not possible, construct a cdvfile:// URL.
+ */
+Entry.prototype.toURL = function () {
+ if (this.nativeURL) {
+ return this.nativeURL;
+ }
+ // fullPath attribute may contain the full URL in the case that
+ // toInternalURL fails.
+ return this.toInternalURL() || 'file://localhost' + this.fullPath;
+};
+
+/**
+ * Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
+ * cdvfile:// URL, and this method was necessary to obtain URLs usable by the
+ * webview.
+ * See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
+ * and CB-6300.
+ */
+Entry.prototype.toNativeURL = function () {
+ console.log("DEPRECATED: Update your code to use 'toURL'");
+ return this.toURL();
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function (mimeType) {
+ console.log("DEPRECATED: Update your code to use 'toURL'");
+ return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.remove', arguments);
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(successCallback, fail, 'File', 'remove', [this.toInternalURL()]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function (successCallback, errorCallback) {
+ argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+ var fs = this.filesystem;
+ var win = successCallback && function (result) {
+ var DirectoryEntry = require('./DirectoryEntry');
+ var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+ successCallback(entry);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getParent', [this.toInternalURL()]);
+};
+
+module.exports = Entry;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.File", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function (name, localURL, type, lastModifiedDate, size) {
+ this.name = name || '';
+ this.localURL = localURL || null;
+ this.type = type || null;
+ this.lastModified = lastModifiedDate || null;
+ // For backwards compatibility, store the timestamp in lastModifiedDate as well
+ this.lastModifiedDate = lastModifiedDate || null;
+ this.size = size || 0;
+
+ // These store the absolute start and end for slicing the file.
+ this.start = 0;
+ this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function (start, end) {
+ var size = this.end - this.start;
+ var newStart = 0;
+ var newEnd = size;
+ if (arguments.length) {
+ if (start < 0) {
+ newStart = Math.max(size + start, 0);
+ } else {
+ newStart = Math.min(size, start);
+ }
+ }
+
+ if (arguments.length >= 2) {
+ if (end < 0) {
+ newEnd = Math.max(size + end, 0);
+ } else {
+ newEnd = Math.min(end, size);
+ }
+ }
+
+ var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
+ newFile.start = this.start + newStart;
+ newFile.end = this.start + newEnd;
+ return newFile;
+};
+
+module.exports = File;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileWriter = require('./FileWriter');
+var File = require('./File');
+var FileError = require('./FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function (name, fullPath, fileSystem, nativeURL) {
+ // remove trailing slash if it is present
+ if (fullPath && /\/$/.test(fullPath)) {
+ fullPath = fullPath.substring(0, fullPath.length - 1);
+ }
+ if (nativeURL && /\/$/.test(nativeURL)) {
+ nativeURL = nativeURL.substring(0, nativeURL.length - 1);
+ }
+
+ FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
+ this.file(function (filePointer) {
+ var writer = new FileWriter(filePointer);
+
+ if (writer.localURL === null || writer.localURL === '') {
+ if (errorCallback) {
+ errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+ }
+ } else {
+ if (successCallback) {
+ successCallback(writer);
+ }
+ }
+ }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function (successCallback, errorCallback) {
+ var localURL = this.toInternalURL();
+ var win = successCallback && function (f) {
+ var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
+ successCallback(file);
+ };
+ var fail = errorCallback && function (code) {
+ errorCallback(new FileError(code));
+ };
+ exec(win, fail, 'File', 'getFileMetadata', [localURL]);
+};
+
+module.exports = FileEntry;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileError
+ */
+function FileError (error) {
+ this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var modulemapper = require('cordova/modulemapper');
+var utils = require('cordova/utils');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+var origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ * The root directory is the root of the file system.
+ * To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function () {
+ this._readyState = 0;
+ this._error = null;
+ this._result = null;
+ this._progress = null;
+ this._localURL = '';
+ this._realReader = origFileReader ? new origFileReader() : {}; // eslint-disable-line new-cap
+};
+
+/**
+ * Defines the maximum size to read at a time via the native API. The default value is a compromise between
+ * minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
+ * (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
+ * OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
+ */
+FileReader.READ_CHUNK_SIZE = 256 * 1024;
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function () {
+ return this._localURL ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function () {
+ return this._localURL ? this._error : this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function () {
+ return this._localURL ? this._result : this._realReader.result;
+});
+
+function defineEvent (eventName) {
+ utils.defineGetterSetter(FileReader.prototype, eventName, function () {
+ return this._realReader[eventName] || null;
+ }, function (value) {
+ this._realReader[eventName] = value;
+ });
+}
+defineEvent('onloadstart'); // When the read starts.
+defineEvent('onprogress'); // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload'); // When the read has successfully completed.
+defineEvent('onerror'); // When the read has failed (see errors).
+defineEvent('onloadend'); // When the request has completed (either in success or failure).
+defineEvent('onabort'); // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead (reader, file) {
+ // Already loading something
+ if (reader.readyState === FileReader.LOADING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ reader._result = null;
+ reader._error = null;
+ reader._progress = 0;
+ reader._readyState = FileReader.LOADING;
+
+ if (typeof file.localURL === 'string') {
+ reader._localURL = file.localURL;
+ } else {
+ reader._localURL = '';
+ return true;
+ }
+
+ if (reader.onloadstart) {
+ reader.onloadstart(new ProgressEvent('loadstart', {target: reader}));
+ }
+}
+
+/**
+ * Callback used by the following read* functions to handle incremental or final success.
+ * Must be bound to the FileReader's this along with all but the last parameter,
+ * e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
+ * @param readType The name of the read function to call.
+ * @param encoding Text encoding, or null if this is not a text type read.
+ * @param offset Starting offset of the read.
+ * @param totalSize Total number of bytes or chars to read.
+ * @param accumulate A function that takes the callback result and accumulates it in this._result.
+ * @param r Callback result returned by the last read exec() call, or null to begin reading.
+ */
+function readSuccessCallback (readType, encoding, offset, totalSize, accumulate, r) {
+ if (this._readyState === FileReader.DONE) {
+ return;
+ }
+
+ var CHUNK_SIZE = FileReader.READ_CHUNK_SIZE;
+ if (readType === 'readAsDataURL') {
+ // Windows proxy does not support reading file slices as Data URLs
+ // so read the whole file at once.
+ CHUNK_SIZE = cordova.platformId === 'windows' ? totalSize : // eslint-disable-line no-undef
+ // Calculate new chunk size for data URLs to be multiply of 3
+ // Otherwise concatenated base64 chunks won't be valid base64 data
+ FileReader.READ_CHUNK_SIZE - (FileReader.READ_CHUNK_SIZE % 3) + 3;
+ }
+
+ if (typeof r !== 'undefined') {
+ accumulate(r);
+ this._progress = Math.min(this._progress + CHUNK_SIZE, totalSize);
+
+ if (typeof this.onprogress === 'function') {
+ this.onprogress(new ProgressEvent('progress', {loaded: this._progress, total: totalSize}));
+ }
+ }
+
+ if (typeof r === 'undefined' || this._progress < totalSize) {
+ var execArgs = [
+ this._localURL,
+ offset + this._progress,
+ offset + this._progress + Math.min(totalSize - this._progress, CHUNK_SIZE)];
+ if (encoding) {
+ execArgs.splice(1, 0, encoding);
+ }
+ exec(
+ readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
+ readFailureCallback.bind(this),
+ 'File', readType, execArgs);
+ } else {
+ this._readyState = FileReader.DONE;
+
+ if (typeof this.onload === 'function') {
+ this.onload(new ProgressEvent('load', {target: this}));
+ }
+
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+ }
+}
+
+/**
+ * Callback used by the following read* functions to handle errors.
+ * Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
+ */
+function readFailureCallback (e) {
+ if (this._readyState === FileReader.DONE) {
+ return;
+ }
+
+ this._readyState = FileReader.DONE;
+ this._result = null;
+ this._error = new FileError(e);
+
+ if (typeof this.onerror === 'function') {
+ this.onerror(new ProgressEvent('error', {target: this}));
+ }
+
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function () {
+ if (origFileReader && !this._localURL) {
+ return this._realReader.abort();
+ }
+ this._result = null;
+
+ if (this._readyState === FileReader.DONE || this._readyState === FileReader.EMPTY) {
+ return;
+ }
+
+ this._readyState = FileReader.DONE;
+
+ // If abort callback
+ if (typeof this.onabort === 'function') {
+ this.onabort(new ProgressEvent('abort', {target: this}));
+ }
+ // If load end callback
+ if (typeof this.onloadend === 'function') {
+ this.onloadend(new ProgressEvent('loadend', {target: this}));
+ }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file {File} File object containing file properties
+ * @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function (file, encoding) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsText(file, encoding);
+ }
+
+ // Default encoding is UTF-8
+ var enc = encoding || 'UTF-8';
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsText', enc, file.start, totalSize, function (r) {
+ if (this._progress === 0) {
+ this._result = '';
+ }
+ this._result += r;
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ * data:[<mediatype>][;base64],<data>
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsDataURL(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsDataURL', null, file.start, totalSize, function (r) {
+ var commaIndex = r.indexOf(',');
+ if (this._progress === 0) {
+ this._result = r;
+ } else {
+ this._result += r.substring(commaIndex + 1);
+ }
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsBinaryString(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsBinaryString', null, file.start, totalSize, function (r) {
+ if (this._progress === 0) {
+ this._result = '';
+ }
+ this._result += r;
+ }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function (file) {
+ if (initRead(this, file)) {
+ return this._realReader.readAsArrayBuffer(file);
+ }
+
+ var totalSize = file.end - file.start;
+ readSuccessCallback.bind(this)('readAsArrayBuffer', null, file.start, totalSize, function (r) {
+ var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
+ resultArray.set(new Uint8Array(r), this._progress);
+ this._result = resultArray.buffer;
+ }.bind(this));
+};
+
+module.exports = FileReader;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var DirectoryEntry = require('./DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function (name, root) {
+ this.name = name;
+ if (root) {
+ this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
+ } else {
+ this.root = new DirectoryEntry(this.name, '/', this);
+ }
+};
+
+FileSystem.prototype.__format__ = function (fullPath, nativeUrl) {
+ return fullPath;
+};
+
+FileSystem.prototype.toJSON = function () {
+ return '<FileSystem: ' + this.name + '>';
+};
+
+// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
+FileSystem.encodeURIPath = function (path) {
+ // Because # is a valid filename character, it must be encoded to prevent part of the
+ // path from being parsed as a URI fragment.
+ return encodeURI(path).replace(/#/g, '%23');
+};
+
+module.exports = FileSystem;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Options to customize the HTTP request used to upload files.
+ * @constructor
+ * @param fileKey {String} Name of file request parameter.
+ * @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
+ * @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
+ * @param params {Object} Object with key: value params to send to the server.
+ * @param headers {Object} Keys are header names, values are header values. Multiple
+ * headers of the same name are not supported.
+ */
+var FileUploadOptions = function (fileKey, fileName, mimeType, params, headers, httpMethod) {
+ this.fileKey = fileKey || null;
+ this.fileName = fileName || null;
+ this.mimeType = mimeType || null;
+ this.params = params || null;
+ this.headers = headers || null;
+ this.httpMethod = httpMethod || null;
+};
+
+module.exports = FileUploadOptions;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileUploadResult
+ * @constructor
+ */
+module.exports = function FileUploadResult (size, code, content) {
+ this.bytesSent = size;
+ this.responseCode = code;
+ this.response = content;
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var FileReader = require('./FileReader');
+var ProgressEvent = require('./ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ * The root directory is the root of the file system.
+ * To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function (file) {
+ this.fileName = '';
+ this.length = 0;
+ if (file) {
+ this.localURL = file.localURL || file;
+ this.length = file.size || 0;
+ }
+ // default is to write at the beginning of the file
+ this.position = 0;
+
+ this.readyState = 0; // EMPTY
+
+ this.result = null;
+
+ // Error
+ this.error = null;
+
+ // Event handlers
+ this.onwritestart = null; // When writing starts
+ this.onprogress = null; // While writing the file, and reporting partial file data
+ this.onwrite = null; // When the write has successfully completed.
+ this.onwriteend = null; // When the request has completed (either in success or failure).
+ this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
+ this.onerror = null; // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function () {
+ // check for invalid state
+ if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // set error
+ this.error = new FileError(FileError.ABORT_ERR);
+
+ this.readyState = FileWriter.DONE;
+
+ // If abort callback
+ if (typeof this.onabort === 'function') {
+ this.onabort(new ProgressEvent('abort', {'target': this}));
+ }
+
+ // If write end callback
+ if (typeof this.onwriteend === 'function') {
+ this.onwriteend(new ProgressEvent('writeend', {'target': this}));
+ }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param data text or blob to be written
+ * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
+ */
+FileWriter.prototype.write = function (data, isPendingBlobReadResult) {
+
+ var that = this;
+ var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
+ /* eslint-disable no-undef */
+ var isProxySupportBlobNatively = (cordova.platformId === 'windows8' || cordova.platformId === 'windows');
+ var isBinary;
+
+ // Check to see if the incoming data is a blob
+ if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
+ var fileReader = new FileReader();
+ /* eslint-enable no-undef */
+ fileReader.onload = function () {
+ // Call this method again, with the arraybuffer as argument
+ FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
+ };
+ fileReader.onerror = function () {
+ // DONE state
+ that.readyState = FileWriter.DONE;
+
+ // Save error
+ that.error = this.error;
+
+ // If onerror callback
+ if (typeof that.onerror === 'function') {
+ that.onerror(new ProgressEvent('error', {'target': that}));
+ }
+
+ // If onwriteend callback
+ if (typeof that.onwriteend === 'function') {
+ that.onwriteend(new ProgressEvent('writeend', {'target': that}));
+ }
+ };
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ if (supportsBinary) {
+ fileReader.readAsArrayBuffer(data);
+ } else {
+ fileReader.readAsText(data);
+ }
+ return;
+ }
+
+ // Mark data type for safer transport over the binary bridge
+ isBinary = supportsBinary && (data instanceof ArrayBuffer);
+ if (isBinary && cordova.platformId === 'windowsphone') { // eslint-disable-line no-undef
+ // create a plain array, using the keys from the Uint8Array view so that we can serialize it
+ data = Array.apply(null, new Uint8Array(data));
+ }
+
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ var me = this;
+
+ // If onwritestart callback
+ if (typeof me.onwritestart === 'function') {
+ me.onwritestart(new ProgressEvent('writestart', {'target': me}));
+ }
+
+ // Write file
+ exec(
+ // Success callback
+ function (r) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // position always increases by bytes written because file would be extended
+ me.position += r;
+ // The length of the file is now where we are done writing.
+
+ me.length = me.position;
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // If onwrite callback
+ if (typeof me.onwrite === 'function') {
+ me.onwrite(new ProgressEvent('write', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ },
+ // Error callback
+ function (e) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Save error
+ me.error = new FileError(e);
+
+ // If onerror callback
+ if (typeof me.onerror === 'function') {
+ me.onerror(new ProgressEvent('error', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ }, 'File', 'write', [this.localURL, data, this.position, isBinary]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound. If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function (offset) {
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ if (!offset && offset !== 0) {
+ return;
+ }
+
+ // See back from end of file.
+ if (offset < 0) {
+ this.position = Math.max(offset + this.length, 0);
+ // Offset is bigger than file size so set position
+ // to the end of the file.
+ } else if (offset > this.length) {
+ this.position = this.length;
+ // Offset is between 0 and file size so set the position
+ // to start writing.
+ } else {
+ this.position = offset;
+ }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function (size) {
+ // Throw an exception if we are already writing a file
+ if (this.readyState === FileWriter.WRITING) {
+ throw new FileError(FileError.INVALID_STATE_ERR);
+ }
+
+ // WRITING state
+ this.readyState = FileWriter.WRITING;
+
+ var me = this;
+
+ // If onwritestart callback
+ if (typeof me.onwritestart === 'function') {
+ me.onwritestart(new ProgressEvent('writestart', {'target': this}));
+ }
+
+ // Write file
+ exec(
+ // Success callback
+ function (r) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Update the length of the file
+ me.length = r;
+ me.position = Math.min(me.position, r);
+
+ // If onwrite callback
+ if (typeof me.onwrite === 'function') {
+ me.onwrite(new ProgressEvent('write', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ },
+ // Error callback
+ function (e) {
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState === FileWriter.DONE) {
+ return;
+ }
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // Save error
+ me.error = new FileError(e);
+
+ // If onerror callback
+ if (typeof me.onerror === 'function') {
+ me.onerror(new ProgressEvent('error', {'target': me}));
+ }
+
+ // If onwriteend callback
+ if (typeof me.onwriteend === 'function') {
+ me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+ }
+ }, 'File', 'truncate', [this.localURL, size]);
+};
+
+module.exports = FileWriter;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ *
+ * @param create
+ * {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ * {boolean} used with create; if true the command will fail if
+ * target path exists
+ */
+function Flags (create, exclusive) {
+ this.create = create || false;
+ this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+exports.TEMPORARY = 0;
+exports.PERSISTENT = 1;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Information about the state of the file or directory
+ *
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function (metadata) {
+ if (typeof metadata === 'object') {
+ this.modificationTime = new Date(metadata.modificationTime);
+ this.size = metadata.size || 0;
+ } else if (typeof metadata === 'undefined') {
+ this.modificationTime = null;
+ this.size = 0;
+ } else {
+ /* Backwards compatiblity with platforms that only return a timestamp */
+ this.modificationTime = new Date(metadata);
+ }
+};
+
+module.exports = Metadata;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function () {
+ /*
+ var createEvent = function(data) {
+ var event = document.createEvent('Events');
+ event.initEvent('ProgressEvent', false, false);
+ if (data) {
+ for (var i in data) {
+ if (data.hasOwnProperty(i)) {
+ event[i] = data[i];
+ }
+ }
+ if (data.target) {
+ // TODO: cannot call <some_custom_object>.dispatchEvent
+ // need to first figure out how to implement EventTarget
+ }
+ }
+ return event;
+ };
+ try {
+ var ev = createEvent({type:"abort",target:document});
+ return function ProgressEvent(type, data) {
+ data.type = type;
+ return createEvent(data);
+ };
+ } catch(e){
+ */
+ return function ProgressEvent (type, dict) {
+ this.type = type;
+ this.bubbles = false;
+ this.cancelBubble = false;
+ this.cancelable = false;
+ this.lengthComputable = false;
+ this.loaded = dict && dict.loaded ? dict.loaded : 0;
+ this.total = dict && dict.total ? dict.total : 0;
+ this.target = dict && dict.target ? dict.target : null;
+ };
+ // }
+})();
+
+module.exports = ProgressEvent;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.androidFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+FILESYSTEM_PROTOCOL = 'cdvfile'; // eslint-disable-line no-undef
+
+module.exports = {
+ __format__: function (fullPath, nativeUrl) {
+ var path;
+ var contentUrlMatch = /^content:\/\//.exec(nativeUrl);
+ if (contentUrlMatch) {
+ // When available, use the path from a native content URL, which was already encoded by Android.
+ // This is necessary because JavaScript's encodeURI() does not encode as many characters as
+ // Android, which can result in permission exceptions when the encoding of a content URI
+ // doesn't match the string for which permission was originally granted.
+ path = nativeUrl.substring(contentUrlMatch[0].length - 1);
+ } else {
+ path = FileSystem.encodeURIPath(fullPath); // eslint-disable-line no-undef
+ if (!/^\//.test(path)) {
+ path = '/' + path;
+ }
+
+ var m = /\?.*/.exec(nativeUrl);
+ if (m) {
+ path += m[0];
+ }
+ }
+
+ return FILESYSTEM_PROTOCOL + '://localhost/' + this.name + path; // eslint-disable-line no-undef
+ }
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+ */
+
+module.exports = function () {
+ // window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and
+ // possibly a good flag to indicate that we're running in Chrome
+ return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+
+exports.file = {
+ // Read-only directory where the application is installed.
+ applicationDirectory: null,
+ // Root of app's private writable storage
+ applicationStorageDirectory: null,
+ // Where to put app-specific data files.
+ dataDirectory: null,
+ // Cached files that should survive app restarts.
+ // Apps should not rely on the OS to delete files in here.
+ cacheDirectory: null,
+ // Android: the application space on external storage.
+ externalApplicationStorageDirectory: null,
+ // Android: Where to put app-specific data files on external storage.
+ externalDataDirectory: null,
+ // Android: the application cache on external storage.
+ externalCacheDirectory: null,
+ // Android: the external storage (SD card) root.
+ externalRootDirectory: null,
+ // iOS: Temp directory that the OS can clear at will.
+ tempDirectory: null,
+ // iOS: Holds app-specific files that should be synced (e.g. to iCloud).
+ syncedDataDirectory: null,
+ // iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
+ documentsDirectory: null,
+ // BlackBerry10: Files globally available to all apps
+ sharedDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function () {
+ function after (paths) {
+ for (var k in paths) {
+ exports.file[k] = paths[k];
+ }
+ channel.initializationComplete('onFileSystemPathsReady');
+ }
+ exec(after, null, 'File', 'requestAllPaths', []);
+});
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Map of fsName -> FileSystem.
+var fsMap = null;
+var FileSystem = require('./FileSystem');
+var exec = require('cordova/exec');
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+require('./fileSystems').getFs = function (name, callback) {
+ function success (response) {
+ fsMap = {};
+ for (var i = 0; i < response.length; ++i) {
+ var fsRoot = response[i];
+ if (fsRoot) {
+ var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
+ fsMap[fs.name] = fs;
+ }
+ }
+ callback(fsMap[name]);
+ }
+
+ if (fsMap) {
+ callback(fsMap[name]);
+ } else {
+ exec(success, null, 'File', 'requestAllFileSystems', []);
+ }
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+module.exports.getFs = function (name, callback) {
+ callback(null);
+};
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+ // For browser platform: not all browsers use this file.
+ function checkBrowser () {
+ if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+ module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
+ return true;
+ }
+ return false;
+ }
+ if (checkBrowser()) {
+ return;
+ }
+
+ var argscheck = require('cordova/argscheck');
+ var FileError = require('./FileError');
+ var FileSystem = require('./FileSystem');
+ var exec = require('cordova/exec');
+ var fileSystems = require('./fileSystems');
+
+ /**
+ * Request a file system in which to store application data.
+ * @param type local file system type
+ * @param size indicates how much storage space, in bytes, the application expects to need
+ * @param successCallback invoked with a FileSystem object
+ * @param errorCallback invoked if error occurs retrieving file system
+ */
+ var requestFileSystem = function (type, size, successCallback, errorCallback) {
+ argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
+ var fail = function (code) {
+ if (errorCallback) {
+ errorCallback(new FileError(code));
+ }
+ };
+
+ if (type < 0) {
+ fail(FileError.SYNTAX_ERR);
+ } else {
+ // if successful, return a FileSystem object
+ var success = function (file_system) {
+ if (file_system) {
+ if (successCallback) {
+ fileSystems.getFs(file_system.name, function (fs) {
+ // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+ if (!fs) {
+ fs = new FileSystem(file_system.name, file_system.root);
+ }
+ successCallback(fs);
+ });
+ }
+ } else {
+ // no FileSystem object returned
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ };
+ exec(success, fail, 'File', 'requestFileSystem', [type, size]);
+ }
+ };
+
+ module.exports = requestFileSystem;
+})();
+
+});
--- /dev/null
+cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+(function () {
+ // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
+ function checkBrowser () {
+ if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+ module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+ return true;
+ }
+ return false;
+ }
+ if (checkBrowser()) {
+ return;
+ }
+
+ var argscheck = require('cordova/argscheck');
+ var DirectoryEntry = require('./DirectoryEntry');
+ var FileEntry = require('./FileEntry');
+ var FileError = require('./FileError');
+ var exec = require('cordova/exec');
+ var fileSystems = require('./fileSystems');
+
+ /**
+ * Look up file system Entry referred to by local URI.
+ * @param {DOMString} uri URI referring to a local file or directory
+ * @param successCallback invoked with Entry object corresponding to URI
+ * @param errorCallback invoked if error occurs retrieving file system entry
+ */
+ module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function (uri, successCallback, errorCallback) {
+ argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
+ // error callback
+ var fail = function (error) {
+ if (errorCallback) {
+ errorCallback(new FileError(error));
+ }
+ };
+ // sanity check for 'not:valid:filename' or '/not:valid:filename'
+ // file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
+ if (!uri || uri.split(':').length > 2) {
+ setTimeout(function () {
+ fail(FileError.ENCODING_ERR);
+ }, 0);
+ return;
+ }
+ // if successful, return either a file or directory entry
+ var success = function (entry) {
+ if (entry) {
+ if (successCallback) {
+ // create appropriate Entry object
+ var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem === window.PERSISTENT ? 'persistent' : 'temporary'); // eslint-disable-line no-undef
+ fileSystems.getFs(fsName, function (fs) {
+ // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+ if (!fs) {
+ fs = new FileSystem(fsName, {name: '', fullPath: '/'}); // eslint-disable-line no-undef
+ }
+ var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
+ successCallback(result);
+ });
+ }
+ } else {
+ // no Entry object returned
+ fail(FileError.NOT_FOUND_ERR);
+ }
+ };
+
+ exec(success, fail, 'File', 'resolveLocalFileSystemURI', [uri]);
+ };
+
+ module.exports.resolveLocalFileSystemURI = function () {
+ console.log('resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.');
+ module.exports.resolveLocalFileSystemURL.apply(this, arguments);
+ };
+})();
+
+});
--- /dev/null
+cordova.define("cordova-plugin-screen-orientation.screenorientation", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+ */
+var screenOrientation = {};
+if (!window.OrientationType) {
+ window.OrientationType = {
+ 'portrait-primary': 0,
+ 'portrait-secondary': 180,
+ 'landscape-primary': 90,
+ 'landscape-secondary': -90
+ };
+}
+if (!window.OrientationLockType) {
+ window.OrientationLockType = {
+ 'portrait-primary': 1,
+ 'portrait-secondary': 2,
+ 'landscape-primary': 4,
+ 'landscape-secondary': 8,
+ 'portrait': 3, // either portrait-primary or portrait-secondary.
+ 'landscape': 12, // either landscape-primary or landscape-secondary.
+ 'any': 15 // All orientations are supported (unlocked orientation)
+ };
+}
+var orientationMask = 1;
+screenOrientation.setOrientation = function(orientation) {
+ orientationMask = window.OrientationLockType[orientation];
+ cordova.exec(null, null, "CDVOrientation", "screenOrientation", [orientationMask, orientation]);
+};
+
+if (!screen.orientation) {
+ screen.orientation = {};
+}
+
+setOrientationProperties();
+
+function addScreenOrientationApi(screenObject) {
+
+ if (screenObject.unlock || screenObject.lock) {
+ screenObject.nativeLock = screenObject.lock;
+ }
+
+ screenObject.lock = function(orientation) {
+ var promiseLock;
+ var p = new Promise(function(resolve, reject) {
+ if (screenObject.nativeLock) {
+ promiseLock = screenObject.nativeLock(orientation);
+ promiseLock.then(function success(res) {
+ resolve();
+ }, function error(err) {
+ screenObject.nativeLock = null;
+ resolveOrientation(orientation, resolve, reject);
+ });
+ } else {
+ resolveOrientation(orientation, resolve, reject);
+ }
+ });
+ return p;
+ };
+ screenObject.unlock = function() {
+ screenOrientation.setOrientation('any');
+ };
+}
+
+function resolveOrientation(orientation, resolve, reject) {
+ if (!OrientationLockType.hasOwnProperty(orientation)) {
+ var err = new Error();
+ err.name = "NotSupportedError";
+ reject(err); //"cannot change orientation");
+ } else {
+ screenOrientation.setOrientation(orientation);
+ resolve("Orientation set"); // orientation change successful
+ }
+
+}
+
+addScreenOrientationApi(screen.orientation);
+
+var onChangeListener = null;
+
+Object.defineProperty(screen.orientation, 'onchange', {
+ set: function(listener) {
+
+ if (onChangeListener) {
+ screen.orientation.removeEventListener('change', onChangeListener);
+ }
+ onChangeListener = listener;
+ if (onChangeListener) {
+ screen.orientation.addEventListener('change', onChangeListener);
+ }
+ },
+ get: function() {
+ return (onChangeListener ? onChangeListener : null);
+ },
+ enumerable: true,
+});
+
+
+var evtTarget = new XMLHttpRequest(); //document.createElement('div');
+var orientationchange = function() {
+ setOrientationProperties();
+ var event = document.createEvent('Events');
+ event.initEvent("change", false, false);
+ evtTarget.dispatchEvent(event);
+};
+
+screen.orientation.addEventListener = function(a,b,c) {
+ return evtTarget.addEventListener(a,b,c);
+};
+
+screen.orientation.removeEventListener = function(a,b,c) {
+ return evtTarget.removeEventListener(a,b,c);
+};
+
+function setOrientationProperties() {
+ switch (window.orientation) {
+ case 0:
+ screen.orientation.type = 'portrait-primary';
+ break;
+ case 90:
+ screen.orientation.type = 'landscape-primary';
+ break;
+ case 180:
+ screen.orientation.type = 'portrait-secondary';
+ break;
+ case -90:
+ screen.orientation.type = 'landscape-secondary';
+ break;
+ default:
+ screen.orientation.type = 'portrait-primary';
+ break;
+ }
+ screen.orientation.angle = window.orientation || 0;
+
+}
+window.addEventListener("orientationchange", orientationchange, true);
+
+module.exports = screenOrientation;
+
+});
--- /dev/null
+cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) {
+/*
+ *
+ * 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 cordova */
+
+var exec = require('cordova/exec');
+
+var namedColors = {
+ "black": "#000000",
+ "darkGray": "#A9A9A9",
+ "lightGray": "#D3D3D3",
+ "white": "#FFFFFF",
+ "gray": "#808080",
+ "red": "#FF0000",
+ "green": "#00FF00",
+ "blue": "#0000FF",
+ "cyan": "#00FFFF",
+ "yellow": "#FFFF00",
+ "magenta": "#FF00FF",
+ "orange": "#FFA500",
+ "purple": "#800080",
+ "brown": "#A52A2A"
+};
+
+var StatusBar = {
+
+ isVisible: true,
+
+ overlaysWebView: function (doOverlay) {
+ exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
+ },
+
+ styleDefault: function () {
+ // dark text ( to be used on a light background )
+ exec(null, null, "StatusBar", "styleDefault", []);
+ },
+
+ styleLightContent: function () {
+ // light text ( to be used on a dark background )
+ exec(null, null, "StatusBar", "styleLightContent", []);
+ },
+
+ styleBlackTranslucent: function () {
+ // #88000000 ? Apple says to use lightContent instead
+ exec(null, null, "StatusBar", "styleBlackTranslucent", []);
+ },
+
+ styleBlackOpaque: function () {
+ // #FF000000 ? Apple says to use lightContent instead
+ exec(null, null, "StatusBar", "styleBlackOpaque", []);
+ },
+
+ backgroundColorByName: function (colorname) {
+ return StatusBar.backgroundColorByHexString(namedColors[colorname]);
+ },
+
+ backgroundColorByHexString: function (hexString) {
+ if (hexString.charAt(0) !== "#") {
+ hexString = "#" + hexString;
+ }
+
+ if (hexString.length === 4) {
+ var split = hexString.split("");
+ hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3];
+ }
+
+ exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
+ },
+
+ hide: function () {
+ exec(null, null, "StatusBar", "hide", []);
+ StatusBar.isVisible = false;
+ },
+
+ show: function () {
+ exec(null, null, "StatusBar", "show", []);
+ StatusBar.isVisible = true;
+ }
+
+};
+
+// prime it. setTimeout so that proxy gets time to init
+window.setTimeout(function () {
+ exec(function (res) {
+ if (typeof res == 'object') {
+ if (res.type == 'tap') {
+ cordova.fireWindowEvent('statusTap');
+ }
+ } else {
+ StatusBar.isVisible = res;
+ }
+ }, null, "StatusBar", "_ready", []);
+}, 0);
+
+module.exports = StatusBar;
+
+});
--- /dev/null
+cordova.define("es6-promise-plugin.Promise", function(require, exports, module) {
+/*!
+ * @overview es6-promise - a tiny implementation of Promises/A+.
+ * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
+ * @license Licensed under MIT license
+ * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
+ * @version v4.2.2+97478eb6
+ */
+
+!function t(e,n,r){function o(u,s){if(!n[u]){if(!e[u]){var c="function"==typeof require&&require;if(!s&&c)return c(u,!0);if(i)return i(u,!0);var f=new Error("Cannot find module '"+u+"'");throw f.code="MODULE_NOT_FOUND",f}var a=n[u]={exports:{}};e[u][0].call(a.exports,function(t){var n=e[u][1][t];return o(n?n:t)},a,a.exports,t,e,n,r)}return n[u].exports}for(var i="function"==typeof require&&require,u=0;u<r.length;u++)o(r[u]);return o}({1:[function(t){void 0===window.Promise&&t("es6-promise").polyfill()},{"es6-promise":2}],2:[function(t,e,n){(function(r,o){!function(t,r){"object"==typeof n&&"undefined"!=typeof e?e.exports=r():"function"==typeof define&&define.amd?define(r):t.ES6Promise=r()}(this,function(){"use strict";function e(t){var e=typeof t;return null!==t&&("object"===e||"function"===e)}function n(t){return"function"==typeof t}function i(t){J=t}function u(t){Q=t}function s(){return function(){return r.nextTick(h)}}function c(){return"undefined"!=typeof I?function(){I(h)}:l()}function f(){var t=0,e=new X(h),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}function a(){var t=new MessageChannel;return t.port1.onmessage=h,function(){return t.port2.postMessage(0)}}function l(){var t=setTimeout;return function(){return t(h,1)}}function h(){for(var t=0;H>t;t+=2){var e=te[t],n=te[t+1];e(n),te[t]=void 0,te[t+1]=void 0}H=0}function p(){try{var e=t,n=e("vertx");return I=n.runOnLoop||n.runOnContext,c()}catch(r){return l()}}function d(t,e){var n=this,r=new this.constructor(y);void 0===r[ne]&&D(r);var o=n._state;if(o){var i=arguments[o-1];Q(function(){return L(o,r,i,n._result)})}else O(n,r,t,e);return r}function v(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(y);return E(n,t),n}function y(){}function m(){return new TypeError("You cannot resolve a promise with itself")}function _(){return new TypeError("A promises callback cannot return that same promise.")}function w(t){try{return t.then}catch(e){return ue.error=e,ue}}function g(t,e,n,r){try{t.call(e,n,r)}catch(o){return o}}function b(t,e,n){Q(function(t){var r=!1,o=g(n,e,function(n){r||(r=!0,e!==n?E(t,n):j(t,n))},function(e){r||(r=!0,x(t,e))},"Settle: "+(t._label||" unknown promise"));!r&&o&&(r=!0,x(t,o))},t)}function T(t,e){e._state===oe?j(t,e._result):e._state===ie?x(t,e._result):O(e,void 0,function(e){return E(t,e)},function(e){return x(t,e)})}function A(t,e,r){e.constructor===t.constructor&&r===d&&e.constructor.resolve===v?T(t,e):r===ue?(x(t,ue.error),ue.error=null):void 0===r?j(t,e):n(r)?b(t,e,r):j(t,e)}function E(t,n){t===n?x(t,m()):e(n)?A(t,n,w(n)):j(t,n)}function S(t){t._onerror&&t._onerror(t._result),M(t)}function j(t,e){t._state===re&&(t._result=e,t._state=oe,0!==t._subscribers.length&&Q(M,t))}function x(t,e){t._state===re&&(t._state=ie,t._result=e,Q(S,t))}function O(t,e,n,r){var o=t._subscribers,i=o.length;t._onerror=null,o[i]=e,o[i+oe]=n,o[i+ie]=r,0===i&&t._state&&Q(M,t)}function M(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r=void 0,o=void 0,i=t._result,u=0;u<e.length;u+=3)r=e[u],o=e[u+n],r?L(n,r,o,i):o(i);t._subscribers.length=0}}function P(){this.error=null}function C(t,e){try{return t(e)}catch(n){return se.error=n,se}}function L(t,e,r,o){var i=n(r),u=void 0,s=void 0,c=void 0,f=void 0;if(i){if(u=C(r,o),u===se?(f=!0,s=u.error,u.error=null):c=!0,e===u)return x(e,_()),void 0}else u=o,c=!0;e._state!==re||(i&&c?E(e,u):f?x(e,s):t===oe?j(e,u):t===ie&&x(e,u))}function k(t,e){try{e(function(e){E(t,e)},function(e){x(t,e)})}catch(n){x(t,n)}}function q(){return ce++}function D(t){t[ne]=ce++,t._state=void 0,t._result=void 0,t._subscribers=[]}function F(){return new Error("Array Methods must be provided an Array")}function F(){return new Error("Array Methods must be provided an Array")}function N(t){return new fe(this,t).promise}function U(t){var e=this;return G(t)?new e(function(n,r){for(var o=t.length,i=0;o>i;i++)e.resolve(t[i]).then(n,r)}):new e(function(t,e){return e(new TypeError("You must pass an array to race."))})}function Y(t){var e=this,n=new e(y);return x(n,t),n}function K(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function W(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function z(){var t=void 0;if("undefined"!=typeof o)t=o;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=t.Promise;if(n){var r=null;try{r=Object.prototype.toString.call(n.resolve())}catch(e){}if("[object Promise]"===r&&!n.cast)return}t.Promise=ae}var B=void 0;B=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var G=B,H=0,I=void 0,J=void 0,Q=function(t,e){te[H]=t,te[H+1]=e,H+=2,2===H&&(J?J(h):ee())},R="undefined"!=typeof window?window:void 0,V=R||{},X=V.MutationObserver||V.WebKitMutationObserver,Z="undefined"==typeof self&&"undefined"!=typeof r&&"[object process]"==={}.toString.call(r),$="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,te=new Array(1e3),ee=void 0;ee=Z?s():X?f():$?a():void 0===R&&"function"==typeof t?p():l();var ne=Math.random().toString(36).substring(16),re=void 0,oe=1,ie=2,ue=new P,se=new P,ce=0,fe=function(){function t(t,e){this._instanceConstructor=t,this.promise=new t(y),this.promise[ne]||D(this.promise),G(e)?(this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?j(this.promise,this._result):(this.length=this.length||0,this._enumerate(e),0===this._remaining&&j(this.promise,this._result))):x(this.promise,F())}return t.prototype._enumerate=function(t){for(var e=0;this._state===re&&e<t.length;e++)this._eachEntry(t[e],e)},t.prototype._eachEntry=function(t,e){var n=this._instanceConstructor,r=n.resolve;if(r===v){var o=w(t);if(o===d&&t._state!==re)this._settledAt(t._state,e,t._result);else if("function"!=typeof o)this._remaining--,this._result[e]=t;else if(n===ae){var i=new n(y);A(i,t,o),this._willSettleAt(i,e)}else this._willSettleAt(new n(function(e){return e(t)}),e)}else this._willSettleAt(r(t),e)},t.prototype._settledAt=function(t,e,n){var r=this.promise;r._state===re&&(this._remaining--,t===ie?x(r,n):this._result[e]=n),0===this._remaining&&j(r,this._result)},t.prototype._willSettleAt=function(t,e){var n=this;O(t,void 0,function(t){return n._settledAt(oe,e,t)},function(t){return n._settledAt(ie,e,t)})},t}(),ae=function(){function t(e){this[ne]=q(),this._result=this._state=void 0,this._subscribers=[],y!==e&&("function"!=typeof e&&K(),this instanceof t?k(this,e):W())}return t.prototype.catch=function(t){return this.then(null,t)},t.prototype.finally=function(t){var e=this,n=e.constructor;return e.then(function(e){return n.resolve(t()).then(function(){return e})},function(e){return n.resolve(t()).then(function(){throw e})})},t}();return ae.prototype.then=d,ae.all=N,ae.race=U,ae.resolve=v,ae.reject=Y,ae._setScheduler=i,ae._setAsap=u,ae._asap=Q,ae.polyfill=z,ae.Promise=ae,ae})}).call(this,t("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:3}],3:[function(t,e){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(t){if(a===setTimeout)return setTimeout(t,0);if((a===n||!a)&&setTimeout)return a=setTimeout,setTimeout(t,0);try{return a(t,0)}catch(e){try{return a.call(null,t,0)}catch(e){return a.call(this,t,0)}}}function i(t){if(l===clearTimeout)return clearTimeout(t);if((l===r||!l)&&clearTimeout)return l=clearTimeout,clearTimeout(t);try{return l(t)}catch(e){try{return l.call(null,t)}catch(e){return l.call(this,t)}}}function u(){v&&p&&(v=!1,p.length?d=p.concat(d):y=-1,d.length&&s())}function s(){if(!v){var t=o(u);v=!0;for(var e=d.length;e;){for(p=d,d=[];++y<e;)p&&p[y].run();y=-1,e=d.length}p=null,v=!1,i(t)}}function c(t,e){this.fun=t,this.array=e}function f(){}var a,l,h=e.exports={};!function(){try{a="function"==typeof setTimeout?setTimeout:n}catch(t){a=n}try{l="function"==typeof clearTimeout?clearTimeout:r}catch(t){l=r}}();var p,d=[],v=!1,y=-1;h.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];d.push(new c(t,e)),1!==d.length||v||o(s)},c.prototype.run=function(){this.fun.apply(null,this.array)},h.title="browser",h.browser=!0,h.env={},h.argv=[],h.version="",h.versions={},h.on=f,h.addListener=f,h.once=f,h.off=f,h.removeListener=f,h.removeAllListeners=f,h.emit=f,h.prependListener=f,h.prependOnceListener=f,h.listeners=function(){return[]},h.binding=function(){throw new Error("process.binding is not supported")},h.cwd=function(){return"/"},h.chdir=function(){throw new Error("process.chdir is not supported")},h.umask=function(){return 0}},{}]},{},[1]);
+
+
+});
--- /dev/null
+package com.darryncampbell.cordova.plugin.intent;
+
+public class CordovaPluginIntentFileProvider extends androidx.core.content.FileProvider {
+}
--- /dev/null
+package com.darryncampbell.cordova.plugin.intent;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ClipData;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.core.content.FileProvider;
+import android.text.Html;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.webkit.MimeTypeMap;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaActivity;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import static android.os.Environment.getExternalStorageDirectory;
+import static android.os.Environment.getExternalStorageState;
+
+public class IntentShim extends CordovaPlugin {
+
+ private static final String LOG_TAG = "Cordova Intents Shim";
+ private CallbackContext onNewIntentCallbackContext = null;
+ private CallbackContext onBroadcastCallbackContext = null;
+ private CallbackContext onActivityResultCallbackContext = null;
+
+ private Intent deferredIntent = null;
+
+ public IntentShim() {
+
+ }
+
+ public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException
+ {
+ Log.d(LOG_TAG, "Action: " + action);
+ if (action.equals("startActivity") || action.equals("startActivityForResult"))
+ {
+ // Credit: https://github.com/chrisekelley/cordova-webintent
+ if (args.length() != 1) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+
+ JSONObject obj = args.getJSONObject(0);
+ Intent intent = populateIntent(obj, callbackContext);
+ int requestCode = obj.has("requestCode") ? obj.getInt("requestCode") : 1;
+
+ boolean bExpectResult = false;
+ if (action.equals("startActivityForResult"))
+ {
+ bExpectResult = true;
+ this.onActivityResultCallbackContext = callbackContext;
+ }
+ startActivity(intent, bExpectResult, requestCode, callbackContext);
+
+ return true;
+ }
+ else if (action.equals("sendBroadcast"))
+ {
+ // Credit: https://github.com/chrisekelley/cordova-webintent
+ if (args.length() != 1) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+
+ // Parse the arguments
+ JSONObject obj = args.getJSONObject(0);
+ Intent intent = populateIntent(obj, callbackContext);
+
+ sendBroadcast(intent);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
+ return true;
+ }
+ else if (action.equals("startService"))
+ {
+ if (args.length() != 1) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+ JSONObject obj = args.getJSONObject(0);
+ Intent intent = populateIntent(obj, callbackContext);
+ startService(intent);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
+ return true;
+ }
+ else if (action.equals("registerBroadcastReceiver")) {
+ try
+ {
+ // Ensure we only have a single registered broadcast receiver
+ this.cordova.getActivity().unregisterReceiver(myBroadcastReceiver);
+ }
+ catch (IllegalArgumentException e) {}
+
+ // No error callback
+ if(args.length() != 1) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+
+ // Expect an array of filterActions
+ JSONObject obj = args.getJSONObject(0);
+ JSONArray filterActions = obj.has("filterActions") ? obj.getJSONArray("filterActions") : null;
+ if (filterActions == null || filterActions.length() == 0)
+ {
+ // The arguments are not correct
+ Log.w(LOG_TAG, "filterActions argument is not in the expected format");
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+
+ this.onBroadcastCallbackContext = callbackContext;
+
+ PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+ result.setKeepCallback(true);
+
+ IntentFilter filter = new IntentFilter();
+ for (int i = 0; i < filterActions.length(); i++) {
+ Log.d(LOG_TAG, "Registering broadcast receiver for filter: " + filterActions.getString(i));
+ filter.addAction(filterActions.getString(i));
+ }
+
+ // Allow an array of filterCategories
+ JSONArray filterCategories = obj.has("filterCategories") ? obj.getJSONArray("filterCategories") : null;
+ if (filterCategories != null) {
+ for (int i = 0; i < filterCategories.length(); i++) {
+ Log.d(LOG_TAG, "Registering broadcast receiver for category filter: " + filterCategories.getString(i));
+ filter.addCategory(filterCategories.getString(i));
+ }
+ }
+
+ // Add any specified Data Schemes
+ // https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/issues/24
+ JSONArray filterDataSchemes = obj.has("filterDataSchemes") ? obj.getJSONArray("filterDataSchemes") : null;
+ if (filterDataSchemes != null && filterDataSchemes.length() > 0)
+ {
+ for (int i = 0; i < filterDataSchemes.length(); i++)
+ {
+ Log.d(LOG_TAG, "Associating data scheme to filter: " + filterDataSchemes.getString(i));
+ filter.addDataScheme(filterDataSchemes.getString(i));
+ }
+ }
+
+ this.cordova.getActivity().registerReceiver(myBroadcastReceiver, filter);
+
+ callbackContext.sendPluginResult(result);
+ }
+ else if (action.equals("unregisterBroadcastReceiver"))
+ {
+ try
+ {
+ this.cordova.getActivity().unregisterReceiver(myBroadcastReceiver);
+ }
+ catch (IllegalArgumentException e) {}
+ }
+ else if (action.equals("onIntent"))
+ {
+ // Credit: https://github.com/napolitano/cordova-plugin-intent
+ if(args.length() != 1) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+
+ this.onNewIntentCallbackContext = callbackContext;
+
+ if (this.deferredIntent != null) {
+ fireOnNewIntent(this.deferredIntent);
+ this.deferredIntent = null;
+ }
+
+ PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+ result.setKeepCallback(true);
+ callbackContext.sendPluginResult(result);
+ return true;
+ }
+ else if (action.equals("onActivityResult"))
+ {
+ if(args.length() != 1) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+
+ this.onActivityResultCallbackContext = callbackContext;
+
+ PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+ result.setKeepCallback(true);
+ callbackContext.sendPluginResult(result);
+ return true;
+ }
+ else if (action.equals("getIntent"))
+ {
+ // Credit: https://github.com/napolitano/cordova-plugin-intent
+ if(args.length() != 0) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+
+ Intent intent;
+
+ if (this.deferredIntent != null) {
+ intent = this.deferredIntent;
+ this.deferredIntent = null;
+ }
+ else {
+ intent = cordova.getActivity().getIntent();
+ }
+
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, getIntentJson(intent)));
+ return true;
+ }
+ else if (action.equals("sendResult"))
+ {
+ // Assuming this application was started with startActivityForResult, send the result back
+ // https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/issues/3
+ Intent result = new Intent();
+ if (args.length() > 0)
+ {
+ JSONObject json = args.getJSONObject(0);
+ JSONObject extras = (json.has("extras"))?json.getJSONObject("extras"):null;
+
+ // Populate the extras if any exist
+ if (extras != null) {
+ JSONArray extraNames = extras.names();
+ for (int i = 0; i < extraNames.length(); i++) {
+ String key = extraNames.getString(i);
+ Object extrasObj = extras.get(key);
+ if (extrasObj instanceof JSONObject) {
+ // The extra is a bundle
+ Bundle bundle = toBundle((JSONObject) extras.get(key));
+ result.putExtra(key, bundle);
+ } else if (extrasObj instanceof Boolean) {
+ result.putExtra(key, extras.getBoolean(key));
+ } else if(extrasObj instanceof Integer) {
+ result.putExtra(key, extras.getInt(key));
+ } else if(extrasObj instanceof Long) {
+ result.putExtra(key, extras.getLong(key));
+ } else if(extrasObj instanceof Double) {
+ result.putExtra(key, extras.getDouble(key));
+ } else if (extrasObj instanceof Float) {
+ result.putExtra(key, extras.getDouble(key));
+ } else {
+ result.putExtra(key, extras.getString(key));
+ }
+ }
+ }
+ }
+
+ //set result
+ cordova.getActivity().setResult(Activity.RESULT_OK, result);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
+
+ //finish the activity
+ cordova.getActivity().finish();
+
+ }
+ else if (action.equals("realPathFromUri"))
+ {
+ if (args.length() != 1) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return false;
+ }
+
+ JSONObject obj = args.getJSONObject(0);
+ String realPath = getRealPathFromURI_API19(obj, callbackContext);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, realPath));
+ return true;
+
+ }
+
+ return true;
+ }
+
+ private Uri remapUriWithFileProvider(String uriAsString, final CallbackContext callbackContext)
+ {
+ // Create the URI via FileProvider Special case for N and above when installing apks
+ int permissionCheck = ContextCompat.checkSelfPermission(this.cordova.getActivity(),
+ Manifest.permission.READ_EXTERNAL_STORAGE);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED)
+ {
+ // Could do better here - if the app does not already have permission should
+ // only continue when we get the success callback from this.
+ ActivityCompat.requestPermissions(this.cordova.getActivity(),
+ new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
+ callbackContext.error("Please grant read external storage permission");
+ return null;
+ }
+
+ try
+ {
+ String externalStorageState = getExternalStorageState();
+ if (externalStorageState.equals(Environment.MEDIA_MOUNTED) || externalStorageState.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
+ String fileName = uriAsString.substring(uriAsString.indexOf('/') + 2, uriAsString.length());
+ File uriAsFile = new File(fileName);
+ boolean fileExists = uriAsFile.exists();
+ if (!fileExists)
+ {
+ Log.e(LOG_TAG, "File at path " + uriAsFile.getPath() + " with name " + uriAsFile.getName() + "does not exist");
+ callbackContext.error("File not found: " + uriAsFile.toString());
+ return null;
+ }
+ String PACKAGE_NAME = this.cordova.getActivity().getPackageName() + ".darryncampbell.cordova.plugin.intent.fileprovider";
+ Uri uri = FileProvider.getUriForFile(this.cordova.getActivity().getApplicationContext(), PACKAGE_NAME, uriAsFile);
+ return uri;
+ }
+ else
+ {
+ Log.e(LOG_TAG, "Storage directory is not mounted. Please ensure the device is not connected via USB for file transfer");
+ callbackContext.error("Storage directory is returning not mounted");
+ return null;
+ }
+ }
+ catch(StringIndexOutOfBoundsException e)
+ {
+ Log.e(LOG_TAG, "URL is not well formed");
+ callbackContext.error("URL is not well formed");
+ return null;
+ }
+ }
+
+ private String getRealPathFromURI_API19(JSONObject obj, CallbackContext callbackContext) throws JSONException
+ {
+ // Credit: https://stackoverflow.com/questions/2789276/android-get-real-path-by-uri-getpath/2790688
+ Uri uri = obj.has("uri") ? Uri.parse(obj.getString("uri")) : null;
+ if (uri == null)
+ {
+ Log.w(LOG_TAG, "URI is not a specified parameter");
+ throw new JSONException("URI is not a specified parameter");
+ }
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
+ String filePath = "";
+ if (uri.getHost().contains("com.android.providers.media")) {
+ int permissionCheck = ContextCompat.checkSelfPermission(this.cordova.getActivity(),
+ Manifest.permission.READ_EXTERNAL_STORAGE);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED)
+ {
+ // Could do better here - if the app does not already have permission should
+ // only continue when we get the success callback from this.
+ ActivityCompat.requestPermissions(this.cordova.getActivity(),
+ new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
+ callbackContext.error("Please grant read external storage permission");
+ return null;
+ }
+
+ // Image pick from recent
+ String wholeID = DocumentsContract.getDocumentId(uri);
+
+ // Split at colon, use second item in the array
+ String id = wholeID.split(":")[1];
+
+ String[] column = {MediaStore.Images.Media.DATA};
+
+ // where id is equal to
+ String sel = MediaStore.Images.Media._ID + "=?";
+
+ // This line requires read storage permission
+
+ Cursor cursor = this.cordova.getActivity().getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ column, sel, new String[]{id}, null);
+
+ int columnIndex = cursor.getColumnIndex(column[0]);
+
+ if (cursor.moveToFirst()) {
+ filePath = cursor.getString(columnIndex);
+ }
+ cursor.close();
+ return filePath;
+ } else {
+ // image pick from gallery
+ String[] proj = {MediaStore.Images.Media.DATA};
+ Cursor cursor = this.cordova.getActivity().getApplicationContext().getContentResolver().query(uri, proj, null, null, null);
+ int column_index
+ = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+ cursor.moveToFirst();
+ return cursor.getString(column_index);
+ }
+ }
+
+ return "Requires KK or higher";
+ }
+
+ private void startActivity(Intent i, boolean bExpectResult, int requestCode, CallbackContext callbackContext) {
+
+ if (i.resolveActivityInfo(this.cordova.getActivity().getPackageManager(), 0) != null)
+ {
+ if (bExpectResult)
+ {
+ cordova.setActivityResultCallback(this);
+ this.cordova.getActivity().startActivityForResult(i, requestCode);
+ }
+ else
+ {
+ this.cordova.getActivity().startActivity(i);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
+ }
+ }
+ else
+ {
+ // Return an error as there is no app to handle this intent
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR));
+ }
+ }
+
+ private void sendBroadcast(Intent intent) {
+ this.cordova.getActivity().sendBroadcast(intent);
+ }
+
+ private void startService(Intent intent)
+ {
+ this.cordova.getActivity().startService(intent);
+ }
+
+ private Intent populateIntent(JSONObject obj, CallbackContext callbackContext) throws JSONException
+ {
+ // Credit: https://github.com/chrisekelley/cordova-webintent
+ // Credit: https://github.com/chrisekelley/cordova-webintent
+ String type = obj.has("type") ? obj.getString("type") : null;
+ String packageAssociated = obj.has("package") ? obj.getString("package") : null;
+
+ //Uri uri = obj.has("url") ? resourceApi.remapUri(Uri.parse(obj.getString("url"))) : null;
+ Uri uri = null;
+ final CordovaResourceApi resourceApi = webView.getResourceApi();
+ if (obj.has("url"))
+ {
+ String uriAsString = obj.getString("url");
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && uriAsString.startsWith("file://"))
+ {
+ uri = remapUriWithFileProvider(uriAsString, callbackContext);
+ }
+ else
+ {
+ uri = resourceApi.remapUri(Uri.parse(obj.getString("url")));
+ }
+ }
+
+ JSONObject extras = obj.has("extras") ? obj.getJSONObject("extras") : null;
+ Map<String, Object> extrasMap = new HashMap<String, Object>();
+ Bundle bundle = null;
+ String bundleKey = "";
+ if (extras != null) {
+ JSONArray extraNames = extras.names();
+ for (int i = 0; i < extraNames.length(); i++) {
+ String key = extraNames.getString(i);
+ Object extrasObj = extras.get(key);
+ if (extrasObj instanceof JSONObject) {
+ // The extra is a bundle
+ bundleKey = key;
+ bundle = toBundle((JSONObject) extras.get(key));
+ } else {
+ extrasMap.put(key, extras.get(key));
+ }
+ }
+ }
+
+ String action = obj.has("action") ? obj.getString("action") : null;
+ Intent i = new Intent();
+ if (action != null)
+ i.setAction(action);
+
+ if (type != null && uri != null) {
+ i.setDataAndType(uri, type); //Fix the crash problem with android 2.3.6
+ } else {
+ if (type != null) {
+ i.setType(type);
+ }
+ if (uri != null)
+ {
+ i.setData(uri);
+ }
+ }
+
+ JSONObject component = obj.has("component") ? obj.getJSONObject("component") : null;
+ if (component != null)
+ {
+ // User has specified an explicit intent
+ String componentPackage = component.has("package") ? component.getString("package") : null;
+ String componentClass = component.has("class") ? component.getString("class") : null;
+ if (componentPackage == null || componentClass == null)
+ {
+ Log.w(LOG_TAG, "Component specified but missing corresponding package or class");
+ throw new JSONException("Component specified but missing corresponding package or class");
+ }
+
+ else
+ {
+ ComponentName componentName = new ComponentName(componentPackage, componentClass);
+ i.setComponent(componentName);
+ }
+ }
+
+ if (packageAssociated != null)
+ i.setPackage(packageAssociated);
+
+ JSONArray flags = obj.has("flags") ? obj.getJSONArray("flags") : null;
+ if (flags != null)
+ {
+ int length = flags.length();
+ for (int k = 0; k < length; k++)
+ {
+ i.addFlags(flags.getInt(k));
+ }
+ }
+
+ if (bundle != null)
+ i.putExtra(bundleKey, bundle);
+
+ for (String key : extrasMap.keySet()) {
+ Object value = extrasMap.get(key);
+ String valueStr = String.valueOf(value);
+ // If type is text html, the extra text must sent as HTML
+ if (key.equals(Intent.EXTRA_TEXT) && type.equals("text/html")) {
+ i.putExtra(key, Html.fromHtml(valueStr));
+ } else if (key.equals(Intent.EXTRA_STREAM)) {
+ // allows sharing of images as attachments.
+ // value in this case should be a URI of a file
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && valueStr.startsWith("file://"))
+ {
+ Uri uriOfStream = remapUriWithFileProvider(valueStr, callbackContext);
+ if (uriOfStream != null)
+ i.putExtra(key, uriOfStream);
+ }
+ else
+ {
+ //final CordovaResourceApi resourceApi = webView.getResourceApi();
+ i.putExtra(key, resourceApi.remapUri(Uri.parse(valueStr)));
+ }
+ } else if (key.equals(Intent.EXTRA_EMAIL)) {
+ // allows to add the email address of the receiver
+ i.putExtra(Intent.EXTRA_EMAIL, new String[] { valueStr });
+ } else if (key.equals(Intent.EXTRA_KEY_EVENT)) {
+ // allows to add a key event object
+ JSONObject keyEventJson = new JSONObject(valueStr);
+ int keyAction = keyEventJson.getInt("action");
+ int keyCode = keyEventJson.getInt("code");
+ KeyEvent keyEvent = new KeyEvent(keyAction, keyCode);
+ i.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+ } else {
+ if (value instanceof Boolean) {
+ i.putExtra(key, Boolean.valueOf(valueStr));
+ } else if(value instanceof Integer) {
+ i.putExtra(key, Integer.valueOf(valueStr));
+ } else if(value instanceof Long) {
+ i.putExtra(key, Long.valueOf(valueStr));
+ } else if(value instanceof Double) {
+ i.putExtra(key, Double.valueOf(valueStr));
+ } else {
+ i.putExtra(key, valueStr);
+ }
+ }
+ }
+
+ i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ if (obj.has("chooser")) {
+ i = Intent.createChooser(i, obj.getString("chooser"));
+ }
+
+ return i;
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ if (this.onNewIntentCallbackContext != null) {
+ fireOnNewIntent(intent);
+ }
+ else {
+ // save the intent for use when onIntent action is called in the execute method
+ this.deferredIntent = intent;
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent intent)
+ {
+ super.onActivityResult(requestCode, resultCode, intent);
+ if (onActivityResultCallbackContext != null && intent != null)
+ {
+ intent.putExtra("requestCode", requestCode);
+ intent.putExtra("resultCode", resultCode);
+ PluginResult result = new PluginResult(PluginResult.Status.OK, getIntentJson(intent));
+ result.setKeepCallback(true);
+ onActivityResultCallbackContext.sendPluginResult(result);
+ }
+ else if (onActivityResultCallbackContext != null)
+ {
+ Intent canceledIntent = new Intent();
+ canceledIntent.putExtra("requestCode", requestCode);
+ canceledIntent.putExtra("resultCode", resultCode);
+ PluginResult canceledResult = new PluginResult(PluginResult.Status.OK, getIntentJson(canceledIntent));
+ canceledResult.setKeepCallback(true);
+ onActivityResultCallbackContext.sendPluginResult(canceledResult);
+ }
+
+ }
+
+ private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (onBroadcastCallbackContext != null)
+ {
+ PluginResult result = new PluginResult(PluginResult.Status.OK, getIntentJson(intent));
+ result.setKeepCallback(true);
+ onBroadcastCallbackContext.sendPluginResult(result);
+ }
+ }
+ };
+
+ /**
+ * Sends the provided Intent to the onNewIntentCallbackContext.
+ *
+ * @param intent This is the intent to send to the JS layer.
+ */
+ private void fireOnNewIntent(Intent intent) {
+ PluginResult result = new PluginResult(PluginResult.Status.OK, getIntentJson(intent));
+ result.setKeepCallback(true);
+ this.onNewIntentCallbackContext.sendPluginResult(result);
+ }
+
+ /**
+ * Return JSON representation of intent attributes
+ *
+ * @param intent
+ * Credit: https://github.com/napolitano/cordova-plugin-intent
+ */
+ private JSONObject getIntentJson(Intent intent) {
+ JSONObject intentJSON = null;
+ ClipData clipData = null;
+ JSONObject[] items = null;
+ ContentResolver cR = this.cordova.getActivity().getApplicationContext().getContentResolver();
+ MimeTypeMap mime = MimeTypeMap.getSingleton();
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ clipData = intent.getClipData();
+ if(clipData != null) {
+ int clipItemCount = clipData.getItemCount();
+ items = new JSONObject[clipItemCount];
+
+ for (int i = 0; i < clipItemCount; i++) {
+
+ ClipData.Item item = clipData.getItemAt(i);
+
+ try {
+ items[i] = new JSONObject();
+ items[i].put("htmlText", item.getHtmlText());
+ items[i].put("intent", item.getIntent());
+ items[i].put("text", item.getText());
+ items[i].put("uri", item.getUri());
+
+ if (item.getUri() != null) {
+ String type = cR.getType(item.getUri());
+ String extension = mime.getExtensionFromMimeType(cR.getType(item.getUri()));
+
+ items[i].put("type", type);
+ items[i].put("extension", extension);
+ }
+
+ } catch (JSONException e) {
+ Log.d(LOG_TAG, " Error thrown during intent > JSON conversion");
+ Log.d(LOG_TAG, e.getMessage());
+ Log.d(LOG_TAG, Arrays.toString(e.getStackTrace()));
+ }
+
+ }
+ }
+ }
+
+ try {
+ intentJSON = new JSONObject();
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ if(items != null) {
+ intentJSON.put("clipItems", new JSONArray(items));
+ }
+ }
+
+ intentJSON.put("type", intent.getType());
+ intentJSON.put("extras", toJsonObject(intent.getExtras()));
+ intentJSON.put("action", intent.getAction());
+ intentJSON.put("categories", intent.getCategories());
+ intentJSON.put("flags", intent.getFlags());
+ intentJSON.put("component", intent.getComponent());
+ intentJSON.put("data", intent.getData());
+ intentJSON.put("package", intent.getPackage());
+
+ return intentJSON;
+ } catch (JSONException e) {
+ Log.d(LOG_TAG, " Error thrown during intent > JSON conversion");
+ Log.d(LOG_TAG, e.getMessage());
+ Log.d(LOG_TAG, Arrays.toString(e.getStackTrace()));
+
+ return null;
+ }
+ }
+
+ private static JSONObject toJsonObject(Bundle bundle) {
+ // Credit: https://github.com/napolitano/cordova-plugin-intent
+ try {
+ return (JSONObject) toJsonValue(bundle);
+ } catch (JSONException e) {
+ throw new IllegalArgumentException("Cannot convert bundle to JSON: " + e.getMessage(), e);
+ }
+ }
+
+ private static Object toJsonValue(final Object value) throws JSONException {
+ // Credit: https://github.com/napolitano/cordova-plugin-intent
+ if (value == null) {
+ return null;
+ } else if (value instanceof Bundle) {
+ final Bundle bundle = (Bundle) value;
+ final JSONObject result = new JSONObject();
+ for (final String key : bundle.keySet()) {
+ result.put(key, toJsonValue(bundle.get(key)));
+ }
+ return result;
+ } else if ((value.getClass().isArray())) {
+ final JSONArray result = new JSONArray();
+ int length = Array.getLength(value);
+ for (int i = 0; i < length; ++i) {
+ result.put(i, toJsonValue(Array.get(value, i)));
+ }
+ return result;
+ }
+ else if (value instanceof ArrayList<?>) {
+ final ArrayList arrayList = (ArrayList<?>)value;
+ final JSONArray result = new JSONArray();
+ for (int i = 0; i < arrayList.size(); i++)
+ result.put(toJsonValue(arrayList.get(i)));
+ return result;
+ }
+ else if (
+ value instanceof String
+ || value instanceof Boolean
+ || value instanceof Integer
+ || value instanceof Long
+ || value instanceof Double) {
+ return value;
+ } else {
+ return String.valueOf(value);
+ }
+ }
+
+ private Bundle toBundle(final JSONObject obj) {
+ Bundle returnBundle = new Bundle();
+ if (obj == null) {
+ return null;
+ }
+ try {
+ Iterator<?> keys = obj.keys();
+ while(keys.hasNext())
+ {
+ String key = (String)keys.next();
+ Object compare = obj.get(key);
+ if (obj.get(key) instanceof String)
+ returnBundle.putString(key, obj.getString(key));
+ else if (obj.get(key) instanceof Boolean)
+ returnBundle.putBoolean(key, obj.getBoolean(key));
+ else if (obj.get(key) instanceof Integer)
+ returnBundle.putInt(key, obj.getInt(key));
+ else if (obj.get(key) instanceof Long)
+ returnBundle.putLong(key, obj.getLong(key));
+ else if (obj.get(key) instanceof Double)
+ returnBundle.putDouble(key, obj.getDouble(key));
+ else if (obj.get(key).getClass().isArray() || obj.get(key) instanceof JSONArray)
+ {
+ JSONArray jsonArray = obj.getJSONArray(key);
+ int length = jsonArray.length();
+ if (jsonArray.get(0) instanceof String)
+ {
+ String[] stringArray = new String[length];
+ for (int j = 0; j < length; j++)
+ stringArray[j] = jsonArray.getString(j);
+ returnBundle.putStringArray(key, stringArray);
+ //returnBundle.putParcelableArray(key, obj.get);
+ }
+ else
+ {
+ if (key.equals("PLUGIN_CONFIG")) {
+ ArrayList<Bundle> bundleArray = new ArrayList<Bundle>();
+ for (int k = 0; k < length; k++) {
+ bundleArray.add(toBundle(jsonArray.getJSONObject(k)));
+ }
+ returnBundle.putParcelableArrayList(key, bundleArray);
+ } else {
+ Bundle[] bundleArray = new Bundle[length];
+ for (int k = 0; k < length; k++)
+ bundleArray[k] = toBundle(jsonArray.getJSONObject(k));
+ returnBundle.putParcelableArray(key, bundleArray);
+ }
+ }
+ }
+ else if (obj.get(key) instanceof JSONObject)
+ returnBundle.putBundle(key, toBundle((JSONObject)obj.get(key)));
+ }
+ }
+ catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+
+ return returnBundle;
+ }
+}
--- /dev/null
+/*
+ *
+ * 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 cordova.plugins.screenorientation;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.app.Activity;
+import android.content.pm.ActivityInfo;
+import android.util.Log;
+
+public class CDVOrientation extends CordovaPlugin {
+
+ private static final String TAG = "YoikScreenOrientation";
+
+ /**
+ * Screen Orientation Constants
+ */
+
+ private static final String ANY = "any";
+ private static final String PORTRAIT_PRIMARY = "portrait-primary";
+ private static final String PORTRAIT_SECONDARY = "portrait-secondary";
+ private static final String LANDSCAPE_PRIMARY = "landscape-primary";
+ private static final String LANDSCAPE_SECONDARY = "landscape-secondary";
+ private static final String PORTRAIT = "portrait";
+ private static final String LANDSCAPE = "landscape";
+
+ @Override
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
+
+ Log.d(TAG, "execute action: " + action);
+
+ // Route the Action
+ if (action.equals("screenOrientation")) {
+ return routeScreenOrientation(args, callbackContext);
+ }
+
+ // Action not found
+ callbackContext.error("action not recognised");
+ return false;
+ }
+
+ private boolean routeScreenOrientation(JSONArray args, CallbackContext callbackContext) {
+
+ String action = args.optString(0);
+
+
+
+ String orientation = args.optString(1);
+
+ Log.d(TAG, "Requested ScreenOrientation: " + orientation);
+
+ Activity activity = cordova.getActivity();
+
+ if (orientation.equals(ANY)) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ } else if (orientation.equals(LANDSCAPE_PRIMARY)) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ } else if (orientation.equals(PORTRAIT_PRIMARY)) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ } else if (orientation.equals(LANDSCAPE)) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+ } else if (orientation.equals(PORTRAIT)) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
+ } else if (orientation.equals(LANDSCAPE_SECONDARY)) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+ } else if (orientation.equals(PORTRAIT_SECONDARY)) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
+ }
+
+ callbackContext.success();
+ return true;
+
+
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ 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 fr.enhydra.tortuga.home;
+
+import android.os.Bundle;
+import org.apache.cordova.*;
+
+public class MainActivity extends CordovaActivity
+{
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // enable Cordova apps to be started in the background
+ Bundle extras = getIntent().getExtras();
+ if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
+ moveTaskToBack(true);
+ }
+
+ // Set by <content src="index.html" /> in config.xml
+ loadUrl(launchUrl);
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.device;
+
+import java.util.TimeZone;
+
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaInterface;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.provider.Settings;
+
+public class Device extends CordovaPlugin {
+ public static final String TAG = "Device";
+
+ public static String platform; // Device OS
+ public static String uuid; // Device UUID
+
+ private static final String ANDROID_PLATFORM = "Android";
+ private static final String AMAZON_PLATFORM = "amazon-fireos";
+ private static final String AMAZON_DEVICE = "Amazon";
+
+ /**
+ * Constructor.
+ */
+ public Device() {
+ }
+
+ /**
+ * Sets the context of the Command. This can then be used to do things like
+ * get file paths associated with the Activity.
+ *
+ * @param cordova The context of the main Activity.
+ * @param webView The CordovaWebView Cordova is running in.
+ */
+ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+ super.initialize(cordova, webView);
+ Device.uuid = getUuid();
+ }
+
+ /**
+ * Executes the request and returns PluginResult.
+ *
+ * @param action The action to execute.
+ * @param args JSONArry of arguments for the plugin.
+ * @param callbackContext The callback id used when calling back into JavaScript.
+ * @return True if the action was valid, false if not.
+ */
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+ if ("getDeviceInfo".equals(action)) {
+ JSONObject r = new JSONObject();
+ r.put("uuid", Device.uuid);
+ r.put("version", this.getOSVersion());
+ r.put("platform", this.getPlatform());
+ r.put("model", this.getModel());
+ r.put("manufacturer", this.getManufacturer());
+ r.put("isVirtual", this.isVirtual());
+ r.put("serial", this.getSerialNumber());
+ callbackContext.success(r);
+ }
+ else {
+ return false;
+ }
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ // LOCAL METHODS
+ //--------------------------------------------------------------------------
+
+ /**
+ * Get the OS name.
+ *
+ * @return
+ */
+ public String getPlatform() {
+ String platform;
+ if (isAmazonDevice()) {
+ platform = AMAZON_PLATFORM;
+ } else {
+ platform = ANDROID_PLATFORM;
+ }
+ return platform;
+ }
+
+ /**
+ * Get the device's Universally Unique Identifier (UUID).
+ *
+ * @return
+ */
+ public String getUuid() {
+ String uuid = Settings.Secure.getString(this.cordova.getActivity().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
+ return uuid;
+ }
+
+ public String getModel() {
+ String model = android.os.Build.MODEL;
+ return model;
+ }
+
+ public String getProductName() {
+ String productname = android.os.Build.PRODUCT;
+ return productname;
+ }
+
+ public String getManufacturer() {
+ String manufacturer = android.os.Build.MANUFACTURER;
+ return manufacturer;
+ }
+
+ public String getSerialNumber() {
+ String serial = android.os.Build.SERIAL;
+ return serial;
+ }
+
+ /**
+ * Get the OS version.
+ *
+ * @return
+ */
+ public String getOSVersion() {
+ String osversion = android.os.Build.VERSION.RELEASE;
+ return osversion;
+ }
+
+ public String getSDKVersion() {
+ @SuppressWarnings("deprecation")
+ String sdkversion = android.os.Build.VERSION.SDK;
+ return sdkversion;
+ }
+
+ public String getTimeZoneID() {
+ TimeZone tz = TimeZone.getDefault();
+ return (tz.getID());
+ }
+
+ /**
+ * Function to check if the device is manufactured by Amazon
+ *
+ * @return
+ */
+ public boolean isAmazonDevice() {
+ if (android.os.Build.MANUFACTURER.equals(AMAZON_DEVICE)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isVirtual() {
+ return android.os.Build.FINGERPRINT.contains("generic") ||
+ android.os.Build.PRODUCT.contains("sdk");
+ }
+
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+import android.content.res.AssetManager;
+import android.net.Uri;
+
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.LOG;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AssetFilesystem extends Filesystem {
+
+ private final AssetManager assetManager;
+
+ // A custom gradle hook creates the cdvasset.manifest file, which speeds up asset listing a tonne.
+ // See: http://stackoverflow.com/questions/16911558/android-assetmanager-list-incredibly-slow
+ private static Object listCacheLock = new Object();
+ private static boolean listCacheFromFile;
+ private static Map<String, String[]> listCache;
+ private static Map<String, Long> lengthCache;
+
+ private static final String LOG_TAG = "AssetFilesystem";
+
+ private void lazyInitCaches() {
+ synchronized (listCacheLock) {
+ if (listCache == null) {
+ ObjectInputStream ois = null;
+ try {
+ ois = new ObjectInputStream(assetManager.open("cdvasset.manifest"));
+ listCache = (Map<String, String[]>) ois.readObject();
+ lengthCache = (Map<String, Long>) ois.readObject();
+ listCacheFromFile = true;
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ // Asset manifest won't exist if the gradle hook isn't set up correctly.
+ } finally {
+ if (ois != null) {
+ try {
+ ois.close();
+ } catch (IOException e) {
+ LOG.d(LOG_TAG, e.getLocalizedMessage());
+ }
+ }
+ }
+ if (listCache == null) {
+ LOG.w("AssetFilesystem", "Asset manifest not found. Recursive copies and directory listing will be slow.");
+ listCache = new HashMap<String, String[]>();
+ }
+ }
+ }
+ }
+
+ private String[] listAssets(String assetPath) throws IOException {
+ if (assetPath.startsWith("/")) {
+ assetPath = assetPath.substring(1);
+ }
+ if (assetPath.endsWith("/")) {
+ assetPath = assetPath.substring(0, assetPath.length() - 1);
+ }
+ lazyInitCaches();
+ String[] ret = listCache.get(assetPath);
+ if (ret == null) {
+ if (listCacheFromFile) {
+ ret = new String[0];
+ } else {
+ ret = assetManager.list(assetPath);
+ listCache.put(assetPath, ret);
+ }
+ }
+ return ret;
+ }
+
+ private long getAssetSize(String assetPath) throws FileNotFoundException {
+ if (assetPath.startsWith("/")) {
+ assetPath = assetPath.substring(1);
+ }
+ lazyInitCaches();
+ if (lengthCache != null) {
+ Long ret = lengthCache.get(assetPath);
+ if (ret == null) {
+ throw new FileNotFoundException("Asset not found: " + assetPath);
+ }
+ return ret;
+ }
+ CordovaResourceApi.OpenForReadResult offr = null;
+ try {
+ offr = resourceApi.openForRead(nativeUriForFullPath(assetPath));
+ long length = offr.length;
+ if (length < 0) {
+ // available() doesn't always yield the file size, but for assets it does.
+ length = offr.inputStream.available();
+ }
+ return length;
+ } catch (IOException e) {
+ FileNotFoundException fnfe = new FileNotFoundException("File not found: " + assetPath);
+ fnfe.initCause(e);
+ throw fnfe;
+ } finally {
+ if (offr != null) {
+ try {
+ offr.inputStream.close();
+ } catch (IOException e) {
+ LOG.d(LOG_TAG, e.getLocalizedMessage());
+ }
+ }
+ }
+ }
+
+ public AssetFilesystem(AssetManager assetManager, CordovaResourceApi resourceApi) {
+ super(Uri.parse("file:///android_asset/"), "assets", resourceApi);
+ this.assetManager = assetManager;
+ }
+
+ @Override
+ public Uri toNativeUri(LocalFilesystemURL inputURL) {
+ return nativeUriForFullPath(inputURL.path);
+ }
+
+ @Override
+ public LocalFilesystemURL toLocalUri(Uri inputURL) {
+ if (!"file".equals(inputURL.getScheme())) {
+ return null;
+ }
+ File f = new File(inputURL.getPath());
+ // Removes and duplicate /s (e.g. file:///a//b/c)
+ Uri resolvedUri = Uri.fromFile(f);
+ String rootUriNoTrailingSlash = rootUri.getEncodedPath();
+ rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
+ if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
+ return null;
+ }
+ String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
+ // Strip leading slash
+ if (!subPath.isEmpty()) {
+ subPath = subPath.substring(1);
+ }
+ Uri.Builder b = new Uri.Builder()
+ .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
+ .authority("localhost")
+ .path(name);
+ if (!subPath.isEmpty()) {
+ b.appendEncodedPath(subPath);
+ }
+ if (isDirectory(subPath) || inputURL.getPath().endsWith("/")) {
+ // Add trailing / for directories.
+ b.appendEncodedPath("");
+ }
+ return LocalFilesystemURL.parse(b.build());
+ }
+
+ private boolean isDirectory(String assetPath) {
+ try {
+ return listAssets(assetPath).length != 0;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
+ String pathNoSlashes = inputURL.path.substring(1);
+ if (pathNoSlashes.endsWith("/")) {
+ pathNoSlashes = pathNoSlashes.substring(0, pathNoSlashes.length() - 1);
+ }
+
+ String[] files;
+ try {
+ files = listAssets(pathNoSlashes);
+ } catch (IOException e) {
+ FileNotFoundException fnfe = new FileNotFoundException();
+ fnfe.initCause(e);
+ throw fnfe;
+ }
+
+ LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
+ for (int i = 0; i < files.length; ++i) {
+ entries[i] = localUrlforFullPath(new File(inputURL.path, files[i]).getPath());
+ }
+ return entries;
+ }
+
+ @Override
+ public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
+ String path, JSONObject options, boolean directory)
+ throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+ if (options != null && options.optBoolean("create")) {
+ throw new UnsupportedOperationException("Assets are read-only");
+ }
+
+ // Check whether the supplied path is absolute or relative
+ if (directory && !path.endsWith("/")) {
+ path += "/";
+ }
+
+ LocalFilesystemURL requestedURL;
+ if (path.startsWith("/")) {
+ requestedURL = localUrlforFullPath(normalizePath(path));
+ } else {
+ requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
+ }
+
+ // Throws a FileNotFoundException if it doesn't exist.
+ getFileMetadataForLocalURL(requestedURL);
+
+ boolean isDir = isDirectory(requestedURL.path);
+ if (directory && !isDir) {
+ throw new TypeMismatchException("path doesn't exist or is file");
+ } else if (!directory && isDir) {
+ throw new TypeMismatchException("path doesn't exist or is directory");
+ }
+
+ // Return the directory
+ return makeEntryForURL(requestedURL);
+ }
+
+ @Override
+ public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+ JSONObject metadata = new JSONObject();
+ long size = inputURL.isDirectory ? 0 : getAssetSize(inputURL.path);
+ try {
+ metadata.put("size", size);
+ metadata.put("type", inputURL.isDirectory ? "text/directory" : resourceApi.getMimeType(toNativeUri(inputURL)));
+ metadata.put("name", new File(inputURL.path).getName());
+ metadata.put("fullPath", inputURL.path);
+ metadata.put("lastModifiedDate", 0);
+ } catch (JSONException e) {
+ return null;
+ }
+ return metadata;
+ }
+
+ @Override
+ public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
+ return false;
+ }
+
+ @Override
+ long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset, boolean isBinary) throws NoModificationAllowedException, IOException {
+ throw new NoModificationAllowedException("Assets are read-only");
+ }
+
+ @Override
+ long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException, NoModificationAllowedException {
+ throw new NoModificationAllowedException("Assets are read-only");
+ }
+
+ @Override
+ String filesystemPathForURL(LocalFilesystemURL url) {
+ return new File(rootUri.getPath(), url.path).toString();
+ }
+
+ @Override
+ LocalFilesystemURL URLforFilesystemPath(String path) {
+ return null;
+ }
+
+ @Override
+ boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException {
+ throw new NoModificationAllowedException("Assets are read-only");
+ }
+
+ @Override
+ boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws NoModificationAllowedException {
+ throw new NoModificationAllowedException("Assets are read-only");
+ }
+
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import org.apache.cordova.CordovaResourceApi;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class ContentFilesystem extends Filesystem {
+
+ private final Context context;
+
+ public ContentFilesystem(Context context, CordovaResourceApi resourceApi) {
+ super(Uri.parse("content://"), "content", resourceApi);
+ this.context = context;
+ }
+
+ @Override
+ public Uri toNativeUri(LocalFilesystemURL inputURL) {
+ String authorityAndPath = inputURL.uri.getEncodedPath().substring(this.name.length() + 2);
+ if (authorityAndPath.length() < 2) {
+ return null;
+ }
+ String ret = "content://" + authorityAndPath;
+ String query = inputURL.uri.getEncodedQuery();
+ if (query != null) {
+ ret += '?' + query;
+ }
+ String frag = inputURL.uri.getEncodedFragment();
+ if (frag != null) {
+ ret += '#' + frag;
+ }
+ return Uri.parse(ret);
+ }
+
+ @Override
+ public LocalFilesystemURL toLocalUri(Uri inputURL) {
+ if (!"content".equals(inputURL.getScheme())) {
+ return null;
+ }
+ String subPath = inputURL.getEncodedPath();
+ if (subPath.length() > 0) {
+ subPath = subPath.substring(1);
+ }
+ Uri.Builder b = new Uri.Builder()
+ .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
+ .authority("localhost")
+ .path(name)
+ .appendPath(inputURL.getAuthority());
+ if (subPath.length() > 0) {
+ b.appendEncodedPath(subPath);
+ }
+ Uri localUri = b.encodedQuery(inputURL.getEncodedQuery())
+ .encodedFragment(inputURL.getEncodedFragment())
+ .build();
+ return LocalFilesystemURL.parse(localUri);
+ }
+
+ @Override
+ public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
+ String fileName, JSONObject options, boolean directory) throws IOException, TypeMismatchException, JSONException {
+ throw new UnsupportedOperationException("getFile() not supported for content:. Use resolveLocalFileSystemURL instead.");
+ }
+
+ @Override
+ public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL)
+ throws NoModificationAllowedException {
+ Uri contentUri = toNativeUri(inputURL);
+ try {
+ context.getContentResolver().delete(contentUri, null, null);
+ } catch (UnsupportedOperationException t) {
+ // Was seeing this on the File mobile-spec tests on 4.0.3 x86 emulator.
+ // The ContentResolver applies only when the file was registered in the
+ // first case, which is generally only the case with images.
+ NoModificationAllowedException nmae = new NoModificationAllowedException("Deleting not supported for content uri: " + contentUri);
+ nmae.initCause(t);
+ throw nmae;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL)
+ throws NoModificationAllowedException {
+ throw new NoModificationAllowedException("Cannot remove content url");
+ }
+
+ @Override
+ public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
+ throw new UnsupportedOperationException("readEntriesAtLocalURL() not supported for content:. Use resolveLocalFileSystemURL instead.");
+ }
+
+ @Override
+ public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+ long size = -1;
+ long lastModified = 0;
+ Uri nativeUri = toNativeUri(inputURL);
+ String mimeType = resourceApi.getMimeType(nativeUri);
+ Cursor cursor = openCursorForURL(nativeUri);
+ try {
+ if (cursor != null && cursor.moveToFirst()) {
+ Long sizeForCursor = resourceSizeForCursor(cursor);
+ if (sizeForCursor != null) {
+ size = sizeForCursor.longValue();
+ }
+ Long modified = lastModifiedDateForCursor(cursor);
+ if (modified != null)
+ lastModified = modified.longValue();
+ } else {
+ // Some content providers don't support cursors at all!
+ CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(nativeUri);
+ size = offr.length;
+ }
+ } catch (IOException e) {
+ FileNotFoundException fnfe = new FileNotFoundException();
+ fnfe.initCause(e);
+ throw fnfe;
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+
+ JSONObject metadata = new JSONObject();
+ try {
+ metadata.put("size", size);
+ metadata.put("type", mimeType);
+ metadata.put("name", name);
+ metadata.put("fullPath", inputURL.path);
+ metadata.put("lastModifiedDate", lastModified);
+ } catch (JSONException e) {
+ return null;
+ }
+ return metadata;
+ }
+
+ @Override
+ public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
+ int offset, boolean isBinary) throws NoModificationAllowedException {
+ throw new NoModificationAllowedException("Couldn't write to file given its content URI");
+ }
+ @Override
+ public long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
+ throws NoModificationAllowedException {
+ throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
+ }
+
+ protected Cursor openCursorForURL(Uri nativeUri) {
+ ContentResolver contentResolver = context.getContentResolver();
+ try {
+ return contentResolver.query(nativeUri, null, null, null, null);
+ } catch (UnsupportedOperationException e) {
+ return null;
+ }
+ }
+
+ private Long resourceSizeForCursor(Cursor cursor) {
+ int columnIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
+ if (columnIndex != -1) {
+ String sizeStr = cursor.getString(columnIndex);
+ if (sizeStr != null) {
+ return Long.parseLong(sizeStr);
+ }
+ }
+ return null;
+ }
+
+ protected Long lastModifiedDateForCursor(Cursor cursor) {
+ int columnIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DATE_MODIFIED);
+ if (columnIndex == -1) {
+ columnIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
+ }
+ if (columnIndex != -1) {
+ String dateStr = cursor.getString(columnIndex);
+ if (dateStr != null) {
+ return Long.parseLong(dateStr);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String filesystemPathForURL(LocalFilesystemURL url) {
+ File f = resourceApi.mapUriToFile(toNativeUri(url));
+ return f == null ? null : f.getAbsolutePath();
+ }
+
+ @Override
+ public LocalFilesystemURL URLforFilesystemPath(String path) {
+ // Returns null as we don't support reverse mapping back to content:// URLs
+ return null;
+ }
+
+ @Override
+ public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
+ return true;
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+import android.os.Environment;
+import android.os.StatFs;
+
+import java.io.File;
+
+/**
+ * This class provides file directory utilities.
+ * All file operations are performed on the SD card.
+ *
+ * It is used by the FileUtils class.
+ */
+public class DirectoryManager {
+
+ @SuppressWarnings("unused")
+ private static final String LOG_TAG = "DirectoryManager";
+
+ /**
+ * Determine if a file or directory exists.
+ * @param name The name of the file to check.
+ * @return T=exists, F=not found
+ */
+ public static boolean testFileExists(String name) {
+ boolean status;
+
+ // If SD card exists
+ if ((testSaveLocationExists()) && (!name.equals(""))) {
+ File path = Environment.getExternalStorageDirectory();
+ File newPath = constructFilePaths(path.toString(), name);
+ status = newPath.exists();
+ }
+ // If no SD card
+ else {
+ status = false;
+ }
+ return status;
+ }
+
+ /**
+ * Get the free space in external storage
+ *
+ * @return Size in KB or -1 if not available
+ */
+ public static long getFreeExternalStorageSpace() {
+ String status = Environment.getExternalStorageState();
+ long freeSpaceInBytes = 0;
+
+ // Check if external storage exists
+ if (status.equals(Environment.MEDIA_MOUNTED)) {
+ freeSpaceInBytes = getFreeSpaceInBytes(Environment.getExternalStorageDirectory().getPath());
+ } else {
+ // If no external storage then return -1
+ return -1;
+ }
+
+ return freeSpaceInBytes / 1024;
+ }
+
+ /**
+ * Given a path return the number of free bytes in the filesystem containing the path.
+ *
+ * @param path to the file system
+ * @return free space in bytes
+ */
+ public static long getFreeSpaceInBytes(String path) {
+ try {
+ StatFs stat = new StatFs(path);
+ long blockSize = stat.getBlockSize();
+ long availableBlocks = stat.getAvailableBlocks();
+ return availableBlocks * blockSize;
+ } catch (IllegalArgumentException e) {
+ // The path was invalid. Just return 0 free bytes.
+ return 0;
+ }
+ }
+
+ /**
+ * Determine if SD card exists.
+ *
+ * @return T=exists, F=not found
+ */
+ public static boolean testSaveLocationExists() {
+ String sDCardStatus = Environment.getExternalStorageState();
+ boolean status;
+
+ // If SD card is mounted
+ if (sDCardStatus.equals(Environment.MEDIA_MOUNTED)) {
+ status = true;
+ }
+
+ // If no SD card
+ else {
+ status = false;
+ }
+ return status;
+ }
+
+ /**
+ * Create a new file object from two file paths.
+ *
+ * @param file1 Base file path
+ * @param file2 Remaining file path
+ * @return File object
+ */
+ private static File constructFilePaths (String file1, String file2) {
+ File newPath;
+ if (file2.startsWith(file1)) {
+ newPath = new File(file2);
+ }
+ else {
+ newPath = new File(file1 + "/" + file2);
+ }
+ return newPath;
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class EncodingException extends Exception {
+
+ public EncodingException(String message) {
+ super(message);
+ }
+
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class FileExistsException extends Exception {
+
+ public FileExistsException(String msg) {
+ super(msg);
+ }
+
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.util.Base64;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PermissionHelper;
+import org.apache.cordova.PluginResult;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+
+/**
+ * This class provides file and directory services to JavaScript.
+ */
+public class FileUtils extends CordovaPlugin {
+ private static final String LOG_TAG = "FileUtils";
+
+ public static int NOT_FOUND_ERR = 1;
+ public static int SECURITY_ERR = 2;
+ public static int ABORT_ERR = 3;
+
+ public static int NOT_READABLE_ERR = 4;
+ public static int ENCODING_ERR = 5;
+ public static int NO_MODIFICATION_ALLOWED_ERR = 6;
+ public static int INVALID_STATE_ERR = 7;
+ public static int SYNTAX_ERR = 8;
+ public static int INVALID_MODIFICATION_ERR = 9;
+ public static int QUOTA_EXCEEDED_ERR = 10;
+ public static int TYPE_MISMATCH_ERR = 11;
+ public static int PATH_EXISTS_ERR = 12;
+
+ /*
+ * Permission callback codes
+ */
+
+ public static final int ACTION_GET_FILE = 0;
+ public static final int ACTION_WRITE = 1;
+ public static final int ACTION_GET_DIRECTORY = 2;
+
+ public static final int WRITE = 3;
+ public static final int READ = 4;
+
+ public static int UNKNOWN_ERR = 1000;
+
+ private boolean configured = false;
+
+ private PendingRequests pendingRequests;
+
+
+
+ /*
+ * We need both read and write when accessing the storage, I think.
+ */
+
+ private String [] permissions = {
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE };
+
+ // This field exists only to support getEntry, below, which has been deprecated
+ private static FileUtils filePlugin;
+
+ private interface FileOp {
+ void run(JSONArray args) throws Exception;
+ }
+
+ private ArrayList<Filesystem> filesystems;
+
+ public void registerFilesystem(Filesystem fs) {
+ if (fs != null && filesystemForName(fs.name)== null) {
+ this.filesystems.add(fs);
+ }
+ }
+
+ private Filesystem filesystemForName(String name) {
+ for (Filesystem fs:filesystems) {
+ if (fs != null && fs.name != null && fs.name.equals(name)) {
+ return fs;
+ }
+ }
+ return null;
+ }
+
+ protected String[] getExtraFileSystemsPreference(Activity activity) {
+ String fileSystemsStr = preferences.getString("androidextrafilesystems", "files,files-external,documents,sdcard,cache,cache-external,assets,root");
+ return fileSystemsStr.split(",");
+ }
+
+ protected void registerExtraFileSystems(String[] filesystems, HashMap<String, String> availableFileSystems) {
+ HashSet<String> installedFileSystems = new HashSet<String>();
+
+ /* Register filesystems in order */
+ for (String fsName : filesystems) {
+ if (!installedFileSystems.contains(fsName)) {
+ String fsRoot = availableFileSystems.get(fsName);
+ if (fsRoot != null) {
+ File newRoot = new File(fsRoot);
+ if (newRoot.mkdirs() || newRoot.isDirectory()) {
+ registerFilesystem(new LocalFilesystem(fsName, webView.getContext(), webView.getResourceApi(), newRoot));
+ installedFileSystems.add(fsName);
+ } else {
+ LOG.d(LOG_TAG, "Unable to create root dir for filesystem \"" + fsName + "\", skipping");
+ }
+ } else {
+ LOG.d(LOG_TAG, "Unrecognized extra filesystem identifier: " + fsName);
+ }
+ }
+ }
+ }
+
+ protected HashMap<String, String> getAvailableFileSystems(Activity activity) {
+ Context context = activity.getApplicationContext();
+ HashMap<String, String> availableFileSystems = new HashMap<String,String>();
+
+ availableFileSystems.put("files", context.getFilesDir().getAbsolutePath());
+ availableFileSystems.put("documents", new File(context.getFilesDir(), "Documents").getAbsolutePath());
+ availableFileSystems.put("cache", context.getCacheDir().getAbsolutePath());
+ availableFileSystems.put("root", "/");
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ try {
+ availableFileSystems.put("files-external", context.getExternalFilesDir(null).getAbsolutePath());
+ availableFileSystems.put("sdcard", Environment.getExternalStorageDirectory().getAbsolutePath());
+ availableFileSystems.put("cache-external", context.getExternalCacheDir().getAbsolutePath());
+ }
+ catch(NullPointerException e) {
+ LOG.d(LOG_TAG, "External storage unavailable, check to see if USB Mass Storage Mode is on");
+ }
+ }
+
+ return availableFileSystems;
+ }
+
+ @Override
+ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+ super.initialize(cordova, webView);
+ this.filesystems = new ArrayList<Filesystem>();
+ this.pendingRequests = new PendingRequests();
+
+ String tempRoot = null;
+ String persistentRoot = null;
+
+ Activity activity = cordova.getActivity();
+ String packageName = activity.getPackageName();
+
+ String location = preferences.getString("androidpersistentfilelocation", "internal");
+
+ tempRoot = activity.getCacheDir().getAbsolutePath();
+ if ("internal".equalsIgnoreCase(location)) {
+ persistentRoot = activity.getFilesDir().getAbsolutePath() + "/files/";
+ this.configured = true;
+ } else if ("compatibility".equalsIgnoreCase(location)) {
+ /*
+ * Fall-back to compatibility mode -- this is the logic implemented in
+ * earlier versions of this plugin, and should be maintained here so
+ * that apps which were originally deployed with older versions of the
+ * plugin can continue to provide access to files stored under those
+ * versions.
+ */
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ persistentRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
+ tempRoot = Environment.getExternalStorageDirectory().getAbsolutePath() +
+ "/Android/data/" + packageName + "/cache/";
+ } else {
+ persistentRoot = "/data/data/" + packageName;
+ }
+ this.configured = true;
+ }
+
+ if (this.configured) {
+ // Create the directories if they don't exist.
+ File tmpRootFile = new File(tempRoot);
+ File persistentRootFile = new File(persistentRoot);
+ tmpRootFile.mkdirs();
+ persistentRootFile.mkdirs();
+
+ // Register initial filesystems
+ // Note: The temporary and persistent filesystems need to be the first two
+ // registered, so that they will match window.TEMPORARY and window.PERSISTENT,
+ // per spec.
+ this.registerFilesystem(new LocalFilesystem("temporary", webView.getContext(), webView.getResourceApi(), tmpRootFile));
+ this.registerFilesystem(new LocalFilesystem("persistent", webView.getContext(), webView.getResourceApi(), persistentRootFile));
+ this.registerFilesystem(new ContentFilesystem(webView.getContext(), webView.getResourceApi()));
+ this.registerFilesystem(new AssetFilesystem(webView.getContext().getAssets(), webView.getResourceApi()));
+
+ registerExtraFileSystems(getExtraFileSystemsPreference(activity), getAvailableFileSystems(activity));
+
+ // Initialize static plugin reference for deprecated getEntry method
+ if (filePlugin == null) {
+ FileUtils.filePlugin = this;
+ }
+ } else {
+ LOG.e(LOG_TAG, "File plugin configuration error: Please set AndroidPersistentFileLocation in config.xml to one of \"internal\" (for new applications) or \"compatibility\" (for compatibility with previous versions)");
+ activity.finish();
+ }
+ }
+
+ public static FileUtils getFilePlugin() {
+ return filePlugin;
+ }
+
+ private Filesystem filesystemForURL(LocalFilesystemURL localURL) {
+ if (localURL == null) return null;
+ return filesystemForName(localURL.fsName);
+ }
+
+ @Override
+ public Uri remapUri(Uri uri) {
+ // Remap only cdvfile: URLs (not content:).
+ if (!LocalFilesystemURL.FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
+ return null;
+ }
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ return null;
+ }
+ String path = fs.filesystemPathForURL(inputURL);
+ if (path != null) {
+ return Uri.parse("file://" + fs.filesystemPathForURL(inputURL));
+ }
+ return null;
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+ public boolean execute(String action, final String rawArgs, final CallbackContext callbackContext) {
+ if (!configured) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "File plugin is not configured. Please see the README.md file for details on how to update config.xml"));
+ return true;
+ }
+ if (action.equals("testSaveLocationExists")) {
+ threadhelper(new FileOp() {
+ public void run(JSONArray args) {
+ boolean b = DirectoryManager.testSaveLocationExists();
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("getFreeDiskSpace")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) {
+ // The getFreeDiskSpace plugin API is not documented, but some apps call it anyway via exec().
+ // For compatibility it always returns free space in the primary external storage, and
+ // does NOT fallback to internal store if external storage is unavailable.
+ long l = DirectoryManager.getFreeExternalStorageSpace();
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, l));
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("testFileExists")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException {
+ String fname=args.getString(0);
+ boolean b = DirectoryManager.testFileExists(fname);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("testDirectoryExists")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException {
+ String fname=args.getString(0);
+ boolean b = DirectoryManager.testFileExists(fname);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("readAsText")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, MalformedURLException {
+ String encoding = args.getString(1);
+ int start = args.getInt(2);
+ int end = args.getInt(3);
+ String fname=args.getString(0);
+ readFileAs(fname, start, end, callbackContext, encoding, PluginResult.MESSAGE_TYPE_STRING);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("readAsDataURL")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, MalformedURLException {
+ int start = args.getInt(1);
+ int end = args.getInt(2);
+ String fname=args.getString(0);
+ readFileAs(fname, start, end, callbackContext, null, -1);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("readAsArrayBuffer")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, MalformedURLException {
+ int start = args.getInt(1);
+ int end = args.getInt(2);
+ String fname=args.getString(0);
+ readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_ARRAYBUFFER);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("readAsBinaryString")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, MalformedURLException {
+ int start = args.getInt(1);
+ int end = args.getInt(2);
+ String fname=args.getString(0);
+ readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_BINARYSTRING);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("write")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
+ String fname=args.getString(0);
+ String nativeURL = resolveLocalFileSystemURI(fname).getString("nativeURL");
+ String data=args.getString(1);
+ int offset=args.getInt(2);
+ Boolean isBinary=args.getBoolean(3);
+
+ if(needPermission(nativeURL, WRITE)) {
+ getWritePermission(rawArgs, ACTION_WRITE, callbackContext);
+ }
+ else {
+ long fileSize = write(fname, data, offset, isBinary);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
+ }
+
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("truncate")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
+ String fname=args.getString(0);
+ int offset=args.getInt(1);
+ long fileSize = truncateFile(fname, offset);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("requestAllFileSystems")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws IOException, JSONException {
+ callbackContext.success(requestAllFileSystems());
+ }
+ }, rawArgs, callbackContext);
+ } else if (action.equals("requestAllPaths")) {
+ cordova.getThreadPool().execute(
+ new Runnable() {
+ public void run() {
+ try {
+ callbackContext.success(requestAllPaths());
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ );
+ } else if (action.equals("requestFileSystem")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException {
+ int fstype = args.getInt(0);
+ long requiredSize = args.optLong(1);
+ requestFileSystem(fstype, requiredSize, callbackContext);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("resolveLocalFileSystemURI")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws IOException, JSONException {
+ String fname=args.getString(0);
+ JSONObject obj = resolveLocalFileSystemURI(fname);
+ callbackContext.success(obj);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("getFileMetadata")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
+ String fname=args.getString(0);
+ JSONObject obj = getFileMetadata(fname);
+ callbackContext.success(obj);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("getParent")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, IOException {
+ String fname=args.getString(0);
+ JSONObject obj = getParent(fname);
+ callbackContext.success(obj);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("getDirectory")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+ String dirname = args.getString(0);
+ String path = args.getString(1);
+ String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
+ boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
+
+ if(containsCreate && needPermission(nativeURL, WRITE)) {
+ getWritePermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
+ }
+ else if(!containsCreate && needPermission(nativeURL, READ)) {
+ getReadPermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
+ }
+ else {
+ JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
+ callbackContext.success(obj);
+ }
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("getFile")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+ String dirname = args.getString(0);
+ String path = args.getString(1);
+ String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
+ boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
+
+ if(containsCreate && needPermission(nativeURL, WRITE)) {
+ getWritePermission(rawArgs, ACTION_GET_FILE, callbackContext);
+ }
+ else if(!containsCreate && needPermission(nativeURL, READ)) {
+ getReadPermission(rawArgs, ACTION_GET_FILE, callbackContext);
+ }
+ else {
+ JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
+ callbackContext.success(obj);
+ }
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("remove")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, NoModificationAllowedException, InvalidModificationException, MalformedURLException {
+ String fname=args.getString(0);
+ boolean success = remove(fname);
+ if (success) {
+ callbackContext.success();
+ } else {
+ callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+ }
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("removeRecursively")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, FileExistsException, MalformedURLException, NoModificationAllowedException {
+ String fname=args.getString(0);
+ boolean success = removeRecursively(fname);
+ if (success) {
+ callbackContext.success();
+ } else {
+ callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+ }
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("moveTo")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
+ String fname=args.getString(0);
+ String newParent=args.getString(1);
+ String newName=args.getString(2);
+ JSONObject entry = transferTo(fname, newParent, newName, true);
+ callbackContext.success(entry);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("copyTo")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
+ String fname=args.getString(0);
+ String newParent=args.getString(1);
+ String newName=args.getString(2);
+ JSONObject entry = transferTo(fname, newParent, newName, false);
+ callbackContext.success(entry);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("readEntries")) {
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
+ String fname=args.getString(0);
+ JSONArray entries = readEntries(fname);
+ callbackContext.success(entries);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else if (action.equals("_getLocalFilesystemPath")) {
+ // Internal method for testing: Get the on-disk location of a local filesystem url.
+ // [Currently used for testing file-transfer]
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
+ String localURLstr = args.getString(0);
+ String fname = filesystemPathForURL(localURLstr);
+ callbackContext.success(fname);
+ }
+ }, rawArgs, callbackContext);
+ }
+ else {
+ return false;
+ }
+ return true;
+ }
+
+ private void getReadPermission(String rawArgs, int action, CallbackContext callbackContext) {
+ int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
+ PermissionHelper.requestPermission(this, requestCode, Manifest.permission.READ_EXTERNAL_STORAGE);
+ }
+
+ private void getWritePermission(String rawArgs, int action, CallbackContext callbackContext) {
+ int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
+ PermissionHelper.requestPermission(this, requestCode, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ }
+
+ private boolean hasReadPermission() {
+ return PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
+ }
+
+ private boolean hasWritePermission() {
+ return PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ }
+
+ private boolean needPermission(String nativeURL, int permissionType) throws JSONException {
+ JSONObject j = requestAllPaths();
+ ArrayList<String> allowedStorageDirectories = new ArrayList<String>();
+ allowedStorageDirectories.add(j.getString("applicationDirectory"));
+ allowedStorageDirectories.add(j.getString("applicationStorageDirectory"));
+ if(j.has("externalApplicationStorageDirectory")) {
+ allowedStorageDirectories.add(j.getString("externalApplicationStorageDirectory"));
+ }
+
+ if(permissionType == READ && hasReadPermission()) {
+ return false;
+ }
+ else if(permissionType == WRITE && hasWritePermission()) {
+ return false;
+ }
+
+ // Permission required if the native url lies outside the allowed storage directories
+ for(String directory : allowedStorageDirectories) {
+ if(nativeURL.startsWith(directory)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ public LocalFilesystemURL resolveNativeUri(Uri nativeUri) {
+ LocalFilesystemURL localURL = null;
+
+ // Try all installed filesystems. Return the best matching URL
+ // (determined by the shortest resulting URL)
+ for (Filesystem fs : filesystems) {
+ LocalFilesystemURL url = fs.toLocalUri(nativeUri);
+ if (url != null) {
+ // A shorter fullPath implies that the filesystem is a better
+ // match for the local path than the previous best.
+ if (localURL == null || (url.uri.toString().length() < localURL.toString().length())) {
+ localURL = url;
+ }
+ }
+ }
+ return localURL;
+ }
+
+ /*
+ * These two native-only methods can be used by other plugins to translate between
+ * device file system paths and URLs. By design, there is no direct JavaScript
+ * interface to these methods.
+ */
+
+ public String filesystemPathForURL(String localURLstr) throws MalformedURLException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(localURLstr);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+ return fs.filesystemPathForURL(inputURL);
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+ }
+
+ public LocalFilesystemURL filesystemURLforLocalPath(String localPath) {
+ LocalFilesystemURL localURL = null;
+ int shortestFullPath = 0;
+
+ // Try all installed filesystems. Return the best matching URL
+ // (determined by the shortest resulting URL)
+ for (Filesystem fs: filesystems) {
+ LocalFilesystemURL url = fs.URLforFilesystemPath(localPath);
+ if (url != null) {
+ // A shorter fullPath implies that the filesystem is a better
+ // match for the local path than the previous best.
+ if (localURL == null || (url.path.length() < shortestFullPath)) {
+ localURL = url;
+ shortestFullPath = url.path.length();
+ }
+ }
+ }
+ return localURL;
+ }
+
+
+ /* helper to execute functions async and handle the result codes
+ *
+ */
+ private void threadhelper(final FileOp f, final String rawArgs, final CallbackContext callbackContext){
+ cordova.getThreadPool().execute(new Runnable() {
+ public void run() {
+ try {
+ JSONArray args = new JSONArray(rawArgs);
+ f.run(args);
+ } catch ( Exception e) {
+ if( e instanceof EncodingException){
+ callbackContext.error(FileUtils.ENCODING_ERR);
+ } else if(e instanceof FileNotFoundException) {
+ callbackContext.error(FileUtils.NOT_FOUND_ERR);
+ } else if(e instanceof FileExistsException) {
+ callbackContext.error(FileUtils.PATH_EXISTS_ERR);
+ } else if(e instanceof NoModificationAllowedException ) {
+ callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+ } else if(e instanceof InvalidModificationException ) {
+ callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
+ } else if(e instanceof MalformedURLException ) {
+ callbackContext.error(FileUtils.ENCODING_ERR);
+ } else if(e instanceof IOException ) {
+ callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
+ } else if(e instanceof EncodingException ) {
+ callbackContext.error(FileUtils.ENCODING_ERR);
+ } else if(e instanceof TypeMismatchException ) {
+ callbackContext.error(FileUtils.TYPE_MISMATCH_ERR);
+ } else if(e instanceof JSONException ) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+ } else if (e instanceof SecurityException) {
+ callbackContext.error(FileUtils.SECURITY_ERR);
+ } else {
+ e.printStackTrace();
+ callbackContext.error(FileUtils.UNKNOWN_ERR);
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Allows the user to look up the Entry for a file or directory referred to by a local URI.
+ *
+ * @param uriString of the file/directory to look up
+ * @return a JSONObject representing a Entry from the filesystem
+ * @throws MalformedURLException if the url is not valid
+ * @throws FileNotFoundException if the file does not exist
+ * @throws IOException if the user can't read the file
+ * @throws JSONException
+ */
+ private JSONObject resolveLocalFileSystemURI(String uriString) throws IOException, JSONException {
+ if (uriString == null) {
+ throw new MalformedURLException("Unrecognized filesystem URL");
+ }
+ Uri uri = Uri.parse(uriString);
+ boolean isNativeUri = false;
+
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
+ if (inputURL == null) {
+ /* Check for file://, content:// urls */
+ inputURL = resolveNativeUri(uri);
+ isNativeUri = true;
+ }
+
+ try {
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+ if (fs.exists(inputURL)) {
+ if (!isNativeUri) {
+ // If not already resolved as native URI, resolve to a native URI and back to
+ // fix the terminating slash based on whether the entry is a directory or file.
+ inputURL = fs.toLocalUri(fs.toNativeUri(inputURL));
+ }
+
+ return fs.getEntryForLocalURL(inputURL);
+ }
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+ throw new FileNotFoundException();
+ }
+
+ /**
+ * Read the list of files from this directory.
+ *
+ * @return a JSONArray containing JSONObjects that represent Entry objects.
+ * @throws FileNotFoundException if the directory is not found.
+ * @throws JSONException
+ * @throws MalformedURLException
+ */
+ private JSONArray readEntries(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+ return fs.readEntriesAtLocalURL(inputURL);
+
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+ }
+
+ /**
+ * A setup method that handles the move/copy of files/directories
+ *
+ * @param newName for the file directory to be called, if null use existing file name
+ * @param move if false do a copy, if true do a move
+ * @return a Entry object
+ * @throws NoModificationAllowedException
+ * @throws IOException
+ * @throws InvalidModificationException
+ * @throws EncodingException
+ * @throws JSONException
+ * @throws FileExistsException
+ */
+ private JSONObject transferTo(String srcURLstr, String destURLstr, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
+ if (srcURLstr == null || destURLstr == null) {
+ // either no source or no destination provided
+ throw new FileNotFoundException();
+ }
+
+ LocalFilesystemURL srcURL = LocalFilesystemURL.parse(srcURLstr);
+ LocalFilesystemURL destURL = LocalFilesystemURL.parse(destURLstr);
+
+ Filesystem srcFs = this.filesystemForURL(srcURL);
+ Filesystem destFs = this.filesystemForURL(destURL);
+
+ // Check for invalid file name
+ if (newName != null && newName.contains(":")) {
+ throw new EncodingException("Bad file name");
+ }
+
+ return destFs.copyFileToURL(destURL, newName, srcFs, srcURL, move);
+ }
+
+ /**
+ * Deletes a directory and all of its contents, if any. In the event of an error
+ * [e.g. trying to delete a directory that contains a file that cannot be removed],
+ * some of the contents of the directory may be deleted.
+ * It is an error to attempt to delete the root directory of a filesystem.
+ *
+ * @return a boolean representing success of failure
+ * @throws FileExistsException
+ * @throws NoModificationAllowedException
+ * @throws MalformedURLException
+ */
+ private boolean removeRecursively(String baseURLstr) throws FileExistsException, NoModificationAllowedException, MalformedURLException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+ // You can't delete the root directory.
+ if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
+ throw new NoModificationAllowedException("You can't delete the root directory");
+ }
+
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+ return fs.recursiveRemoveFileAtLocalURL(inputURL);
+
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+ }
+
+
+ /**
+ * Deletes a file or directory. It is an error to attempt to delete a directory that is not empty.
+ * It is an error to attempt to delete the root directory of a filesystem.
+ *
+ * @return a boolean representing success of failure
+ * @throws NoModificationAllowedException
+ * @throws InvalidModificationException
+ * @throws MalformedURLException
+ */
+ private boolean remove(String baseURLstr) throws NoModificationAllowedException, InvalidModificationException, MalformedURLException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+ // You can't delete the root directory.
+ if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
+
+ throw new NoModificationAllowedException("You can't delete the root directory");
+ }
+
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+ return fs.removeFileAtLocalURL(inputURL);
+
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+ }
+
+ /**
+ * Creates or looks up a file.
+ *
+ * @param baseURLstr base directory
+ * @param path file/directory to lookup or create
+ * @param options specify whether to create or not
+ * @param directory if true look up directory, if false look up file
+ * @return a Entry object
+ * @throws FileExistsException
+ * @throws IOException
+ * @throws TypeMismatchException
+ * @throws EncodingException
+ * @throws JSONException
+ */
+ private JSONObject getFile(String baseURLstr, String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+ return fs.getFileForLocalURL(inputURL, path, options, directory);
+
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+
+ }
+
+ /**
+ * Look up the parent DirectoryEntry containing this Entry.
+ * If this Entry is the root of its filesystem, its parent is itself.
+ */
+ private JSONObject getParent(String baseURLstr) throws JSONException, IOException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+ return fs.getParentForLocalURL(inputURL);
+
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+ }
+
+ /**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @return returns a JSONObject represent a W3C File object
+ */
+ private JSONObject getFileMetadata(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+ return fs.getFileMetadataForLocalURL(inputURL);
+
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+ }
+
+ /**
+ * Requests a filesystem in which to store application data.
+ *
+ * @param type of file system requested
+ * @param requiredSize required free space in the file system in bytes
+ * @param callbackContext context for returning the result or error
+ * @throws JSONException
+ */
+ private void requestFileSystem(int type, long requiredSize, final CallbackContext callbackContext) throws JSONException {
+ Filesystem rootFs = null;
+ try {
+ rootFs = this.filesystems.get(type);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // Pass null through
+ }
+ if (rootFs == null) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR));
+ } else {
+ // If a nonzero required size was specified, check that the retrieved filesystem has enough free space.
+ long availableSize = 0;
+ if (requiredSize > 0) {
+ availableSize = rootFs.getFreeSpaceInBytes();
+ }
+
+ if (availableSize < requiredSize) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.QUOTA_EXCEEDED_ERR));
+ } else {
+ JSONObject fs = new JSONObject();
+ fs.put("name", rootFs.name);
+ fs.put("root", rootFs.getRootEntry());
+ callbackContext.success(fs);
+ }
+ }
+ }
+
+ /**
+ * Requests a filesystem in which to store application data.
+ *
+ * @return a JSONObject representing the file system
+ */
+ private JSONArray requestAllFileSystems() throws IOException, JSONException {
+ JSONArray ret = new JSONArray();
+ for (Filesystem fs : filesystems) {
+ ret.put(fs.getRootEntry());
+ }
+ return ret;
+ }
+
+ private static String toDirUrl(File f) {
+ return Uri.fromFile(f).toString() + '/';
+ }
+
+ private JSONObject requestAllPaths() throws JSONException {
+ Context context = cordova.getActivity();
+ JSONObject ret = new JSONObject();
+ ret.put("applicationDirectory", "file:///android_asset/");
+ ret.put("applicationStorageDirectory", toDirUrl(context.getFilesDir().getParentFile()));
+ ret.put("dataDirectory", toDirUrl(context.getFilesDir()));
+ ret.put("cacheDirectory", toDirUrl(context.getCacheDir()));
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ try {
+ ret.put("externalApplicationStorageDirectory", toDirUrl(context.getExternalFilesDir(null).getParentFile()));
+ ret.put("externalDataDirectory", toDirUrl(context.getExternalFilesDir(null)));
+ ret.put("externalCacheDirectory", toDirUrl(context.getExternalCacheDir()));
+ ret.put("externalRootDirectory", toDirUrl(Environment.getExternalStorageDirectory()));
+ }
+ catch(NullPointerException e) {
+ /* If external storage is unavailable, context.getExternal* returns null */
+ LOG.d(LOG_TAG, "Unable to access these paths, most liklely due to USB storage");
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Returns a JSON object representing the given File. Internal APIs should be modified
+ * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
+ *
+ * @param file the File to convert
+ * @return a JSON representation of the given File
+ * @throws JSONException
+ */
+ public JSONObject getEntryForFile(File file) throws JSONException {
+ JSONObject entry;
+
+ for (Filesystem fs : filesystems) {
+ entry = fs.makeEntryForFile(file);
+ if (entry != null) {
+ return entry;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a JSON object representing the given File. Deprecated, as this is only used by
+ * FileTransfer, and because it is a static method that should really be an instance method,
+ * since it depends on the actual filesystem roots in use. Internal APIs should be modified
+ * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
+ *
+ * @param file the File to convert
+ * @return a JSON representation of the given File
+ * @throws JSONException
+ */
+ @Deprecated
+ public static JSONObject getEntry(File file) throws JSONException {
+ if (getFilePlugin() != null) {
+ return getFilePlugin().getEntryForFile(file);
+ }
+ return null;
+ }
+
+ /**
+ * Read the contents of a file.
+ * This is done in a background thread; the result is sent to the callback.
+ *
+ * @param start Start position in the file.
+ * @param end End position to stop at (exclusive).
+ * @param callbackContext The context through which to send the result.
+ * @param encoding The encoding to return contents as. Typical value is UTF-8. (see http://www.iana.org/assignments/character-sets)
+ * @param resultType The desired type of data to send to the callback.
+ * @return Contents of file.
+ */
+ public void readFileAs(final String srcURLstr, final int start, final int end, final CallbackContext callbackContext, final String encoding, final int resultType) throws MalformedURLException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+
+ fs.readFileAtURL(inputURL, start, end, new Filesystem.ReadFileCallback() {
+ public void handleData(InputStream inputStream, String contentType) {
+ try {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ final int BUFFER_SIZE = 8192;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ for (;;) {
+ int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
+
+ if (bytesRead <= 0) {
+ break;
+ }
+ os.write(buffer, 0, bytesRead);
+ }
+
+ PluginResult result;
+ switch (resultType) {
+ case PluginResult.MESSAGE_TYPE_STRING:
+ result = new PluginResult(PluginResult.Status.OK, os.toString(encoding));
+ break;
+ case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
+ result = new PluginResult(PluginResult.Status.OK, os.toByteArray());
+ break;
+ case PluginResult.MESSAGE_TYPE_BINARYSTRING:
+ result = new PluginResult(PluginResult.Status.OK, os.toByteArray(), true);
+ break;
+ default: // Base64.
+ byte[] base64 = Base64.encode(os.toByteArray(), Base64.NO_WRAP);
+ String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII");
+ result = new PluginResult(PluginResult.Status.OK, s);
+ }
+
+ callbackContext.sendPluginResult(result);
+ } catch (IOException e) {
+ LOG.d(LOG_TAG, e.getLocalizedMessage());
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
+ }
+ }
+ });
+
+
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ } catch (FileNotFoundException e) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_FOUND_ERR));
+ } catch (IOException e) {
+ LOG.d(LOG_TAG, e.getLocalizedMessage());
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
+ }
+ }
+
+
+ /**
+ * Write contents of file.
+ *
+ * @param data The contents of the file.
+ * @param offset The position to begin writing the file.
+ * @param isBinary True if the file contents are base64-encoded binary data
+ */
+ /**/
+ public long write(String srcURLstr, String data, int offset, boolean isBinary) throws FileNotFoundException, IOException, NoModificationAllowedException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+
+ long x = fs.writeToFileAtURL(inputURL, data, offset, isBinary); LOG.d("TEST",srcURLstr + ": "+x); return x;
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+
+ }
+
+ /**
+ * Truncate the file to size
+ */
+ private long truncateFile(String srcURLstr, long size) throws FileNotFoundException, IOException, NoModificationAllowedException {
+ try {
+ LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
+ Filesystem fs = this.filesystemForURL(inputURL);
+ if (fs == null) {
+ throw new MalformedURLException("No installed handlers for this URL");
+ }
+
+ return fs.truncateFileAtURL(inputURL, size);
+ } catch (IllegalArgumentException e) {
+ MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+ mue.initCause(e);
+ throw mue;
+ }
+ }
+
+
+ /*
+ * Handle the response
+ */
+
+ public void onRequestPermissionResult(int requestCode, String[] permissions,
+ int[] grantResults) throws JSONException {
+
+ final PendingRequests.Request req = pendingRequests.getAndRemove(requestCode);
+ if (req != null) {
+ for(int r:grantResults)
+ {
+ if(r == PackageManager.PERMISSION_DENIED)
+ {
+ req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+ return;
+ }
+ }
+ switch(req.getAction())
+ {
+ case ACTION_GET_FILE:
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+ String dirname = args.getString(0);
+
+ String path = args.getString(1);
+ JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
+ req.getCallbackContext().success(obj);
+ }
+ }, req.getRawArgs(), req.getCallbackContext());
+ break;
+ case ACTION_GET_DIRECTORY:
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+ String dirname = args.getString(0);
+
+ String path = args.getString(1);
+ JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
+ req.getCallbackContext().success(obj);
+ }
+ }, req.getRawArgs(), req.getCallbackContext());
+ break;
+ case ACTION_WRITE:
+ threadhelper( new FileOp( ){
+ public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
+ String fname=args.getString(0);
+ String data=args.getString(1);
+ int offset=args.getInt(2);
+ Boolean isBinary=args.getBoolean(3);
+ long fileSize = write(fname, data, offset, isBinary);
+ req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
+ }
+ }, req.getRawArgs(), req.getCallbackContext());
+ break;
+ }
+ } else {
+ LOG.d(LOG_TAG, "Received permission callback for unknown request code");
+ }
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+import android.net.Uri;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.cordova.CordovaResourceApi;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public abstract class Filesystem {
+
+ protected final Uri rootUri;
+ protected final CordovaResourceApi resourceApi;
+ public final String name;
+ private JSONObject rootEntry;
+
+ public Filesystem(Uri rootUri, String name, CordovaResourceApi resourceApi) {
+ this.rootUri = rootUri;
+ this.name = name;
+ this.resourceApi = resourceApi;
+ }
+
+ public interface ReadFileCallback {
+ public void handleData(InputStream inputStream, String contentType) throws IOException;
+ }
+
+ public static JSONObject makeEntryForURL(LocalFilesystemURL inputURL, Uri nativeURL) {
+ try {
+ String path = inputURL.path;
+ int end = path.endsWith("/") ? 1 : 0;
+ String[] parts = path.substring(0, path.length() - end).split("/+");
+ String fileName = parts[parts.length - 1];
+
+ JSONObject entry = new JSONObject();
+ entry.put("isFile", !inputURL.isDirectory);
+ entry.put("isDirectory", inputURL.isDirectory);
+ entry.put("name", fileName);
+ entry.put("fullPath", path);
+ // The file system can't be specified, as it would lead to an infinite loop,
+ // but the filesystem name can be.
+ entry.put("filesystemName", inputURL.fsName);
+ // Backwards compatibility
+ entry.put("filesystem", "temporary".equals(inputURL.fsName) ? 0 : 1);
+
+ String nativeUrlStr = nativeURL.toString();
+ if (inputURL.isDirectory && !nativeUrlStr.endsWith("/")) {
+ nativeUrlStr += "/";
+ }
+ entry.put("nativeURL", nativeUrlStr);
+ return entry;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public JSONObject makeEntryForURL(LocalFilesystemURL inputURL) {
+ Uri nativeUri = toNativeUri(inputURL);
+ return nativeUri == null ? null : makeEntryForURL(inputURL, nativeUri);
+ }
+
+ public JSONObject makeEntryForNativeUri(Uri nativeUri) {
+ LocalFilesystemURL inputUrl = toLocalUri(nativeUri);
+ return inputUrl == null ? null : makeEntryForURL(inputUrl, nativeUri);
+ }
+
+ public JSONObject getEntryForLocalURL(LocalFilesystemURL inputURL) throws IOException {
+ return makeEntryForURL(inputURL);
+ }
+
+ public JSONObject makeEntryForFile(File file) {
+ return makeEntryForNativeUri(Uri.fromFile(file));
+ }
+
+ abstract JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, String path,
+ JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException;
+
+ abstract boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException;
+
+ abstract boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException;
+
+ abstract LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException;
+
+ public final JSONArray readEntriesAtLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+ LocalFilesystemURL[] children = listChildren(inputURL);
+ JSONArray entries = new JSONArray();
+ if (children != null) {
+ for (LocalFilesystemURL url : children) {
+ entries.put(makeEntryForURL(url));
+ }
+ }
+ return entries;
+ }
+
+ abstract JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
+
+ public Uri getRootUri() {
+ return rootUri;
+ }
+
+ public boolean exists(LocalFilesystemURL inputURL) {
+ try {
+ getFileMetadataForLocalURL(inputURL);
+ } catch (FileNotFoundException e) {
+ return false;
+ }
+ return true;
+ }
+
+ public Uri nativeUriForFullPath(String fullPath) {
+ Uri ret = null;
+ if (fullPath != null) {
+ String encodedPath = Uri.fromFile(new File(fullPath)).getEncodedPath();
+ if (encodedPath.startsWith("/")) {
+ encodedPath = encodedPath.substring(1);
+ }
+ ret = rootUri.buildUpon().appendEncodedPath(encodedPath).build();
+ }
+ return ret;
+ }
+
+ public LocalFilesystemURL localUrlforFullPath(String fullPath) {
+ Uri nativeUri = nativeUriForFullPath(fullPath);
+ if (nativeUri != null) {
+ return toLocalUri(nativeUri);
+ }
+ return null;
+ }
+
+ /**
+ * Removes multiple repeated //s, and collapses processes ../s.
+ */
+ protected static String normalizePath(String rawPath) {
+ // If this is an absolute path, trim the leading "/" and replace it later
+ boolean isAbsolutePath = rawPath.startsWith("/");
+ if (isAbsolutePath) {
+ rawPath = rawPath.replaceFirst("/+", "");
+ }
+ ArrayList<String> components = new ArrayList<String>(Arrays.asList(rawPath.split("/+")));
+ for (int index = 0; index < components.size(); ++index) {
+ if (components.get(index).equals("..")) {
+ components.remove(index);
+ if (index > 0) {
+ components.remove(index-1);
+ --index;
+ }
+ }
+ }
+ StringBuilder normalizedPath = new StringBuilder();
+ for(String component: components) {
+ normalizedPath.append("/");
+ normalizedPath.append(component);
+ }
+ if (isAbsolutePath) {
+ return normalizedPath.toString();
+ } else {
+ return normalizedPath.toString().substring(1);
+ }
+ }
+
+ /**
+ * Gets the free space in bytes available on this filesystem.
+ * Subclasses may override this method to return nonzero free space.
+ */
+ public long getFreeSpaceInBytes() {
+ return 0;
+ }
+
+ public abstract Uri toNativeUri(LocalFilesystemURL inputURL);
+ public abstract LocalFilesystemURL toLocalUri(Uri inputURL);
+
+ public JSONObject getRootEntry() {
+ if (rootEntry == null) {
+ rootEntry = makeEntryForNativeUri(rootUri);
+ }
+ return rootEntry;
+ }
+
+ public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException {
+ Uri parentUri = inputURL.uri;
+ String parentPath = new File(inputURL.uri.getPath()).getParent();
+ if (!"/".equals(parentPath)) {
+ parentUri = inputURL.uri.buildUpon().path(parentPath + '/').build();
+ }
+ return getEntryForLocalURL(LocalFilesystemURL.parse(parentUri));
+ }
+
+ protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL, boolean isDirectory) {
+ // I know this looks weird but it is to work around a JSON bug.
+ if ("null".equals(newName) || "".equals(newName)) {
+ newName = srcURL.uri.getLastPathSegment();;
+ }
+
+ String newDest = destURL.uri.toString();
+ if (newDest.endsWith("/")) {
+ newDest = newDest + newName;
+ } else {
+ newDest = newDest + "/" + newName;
+ }
+ if (isDirectory) {
+ newDest += '/';
+ }
+ return LocalFilesystemURL.parse(newDest);
+ }
+
+ /* Read a source URL (possibly from a different filesystem, srcFs,) and copy it to
+ * the destination URL on this filesystem, optionally with a new filename.
+ * If move is true, then this method should either perform an atomic move operation
+ * or remove the source file when finished.
+ */
+ public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
+ Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
+ // First, check to see that we can do it
+ if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
+ throw new NoModificationAllowedException("Cannot move file at source URL");
+ }
+ final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
+
+ Uri srcNativeUri = srcFs.toNativeUri(srcURL);
+
+ CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(srcNativeUri);
+ OutputStream os = null;
+ try {
+ os = getOutputStreamForURL(destination);
+ } catch (IOException e) {
+ ofrr.inputStream.close();
+ throw e;
+ }
+ // Closes streams.
+ resourceApi.copyResource(ofrr, os);
+
+ if (move) {
+ srcFs.removeFileAtLocalURL(srcURL);
+ }
+ return getEntryForLocalURL(destination);
+ }
+
+ public OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL) throws IOException {
+ return resourceApi.openOutputStream(toNativeUri(inputURL));
+ }
+
+ public void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
+ ReadFileCallback readFileCallback) throws IOException {
+ CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(toNativeUri(inputURL));
+ if (end < 0) {
+ end = ofrr.length;
+ }
+ long numBytesToRead = end - start;
+ try {
+ if (start > 0) {
+ ofrr.inputStream.skip(start);
+ }
+ InputStream inputStream = ofrr.inputStream;
+ if (end < ofrr.length) {
+ inputStream = new LimitedInputStream(inputStream, numBytesToRead);
+ }
+ readFileCallback.handleData(inputStream, ofrr.mimeType);
+ } finally {
+ ofrr.inputStream.close();
+ }
+ }
+
+ abstract long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset,
+ boolean isBinary) throws NoModificationAllowedException, IOException;
+
+ abstract long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
+ throws IOException, NoModificationAllowedException;
+
+ // This method should return null if filesystem urls cannot be mapped to paths
+ abstract String filesystemPathForURL(LocalFilesystemURL url);
+
+ abstract LocalFilesystemURL URLforFilesystemPath(String path);
+
+ abstract boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL);
+
+ protected class LimitedInputStream extends FilterInputStream {
+ long numBytesToRead;
+ public LimitedInputStream(InputStream in, long numBytesToRead) {
+ super(in);
+ this.numBytesToRead = numBytesToRead;
+ }
+ @Override
+ public int read() throws IOException {
+ if (numBytesToRead <= 0) {
+ return -1;
+ }
+ numBytesToRead--;
+ return in.read();
+ }
+ @Override
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ if (numBytesToRead <= 0) {
+ return -1;
+ }
+ int bytesToRead = byteCount;
+ if (byteCount > numBytesToRead) {
+ bytesToRead = (int)numBytesToRead; // Cast okay; long is less than int here.
+ }
+ int numBytesRead = in.read(buffer, byteOffset, bytesToRead);
+ numBytesToRead -= numBytesRead;
+ return numBytesRead;
+ }
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class InvalidModificationException extends Exception {
+
+ public InvalidModificationException(String message) {
+ super(message);
+ }
+
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import org.apache.cordova.CordovaResourceApi;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.os.Build;
+import android.os.Environment;
+import android.util.Base64;
+import android.net.Uri;
+import android.content.Context;
+import android.content.Intent;
+
+import java.nio.charset.Charset;
+
+public class LocalFilesystem extends Filesystem {
+ private final Context context;
+
+ public LocalFilesystem(String name, Context context, CordovaResourceApi resourceApi, File fsRoot) {
+ super(Uri.fromFile(fsRoot).buildUpon().appendEncodedPath("").build(), name, resourceApi);
+ this.context = context;
+ }
+
+ public String filesystemPathForFullPath(String fullPath) {
+ return new File(rootUri.getPath(), fullPath).toString();
+ }
+
+ @Override
+ public String filesystemPathForURL(LocalFilesystemURL url) {
+ return filesystemPathForFullPath(url.path);
+ }
+
+ private String fullPathForFilesystemPath(String absolutePath) {
+ if (absolutePath != null && absolutePath.startsWith(rootUri.getPath())) {
+ return absolutePath.substring(rootUri.getPath().length() - 1);
+ }
+ return null;
+ }
+
+ @Override
+ public Uri toNativeUri(LocalFilesystemURL inputURL) {
+ return nativeUriForFullPath(inputURL.path);
+ }
+
+ @Override
+ public LocalFilesystemURL toLocalUri(Uri inputURL) {
+ if (!"file".equals(inputURL.getScheme())) {
+ return null;
+ }
+ File f = new File(inputURL.getPath());
+ // Removes and duplicate /s (e.g. file:///a//b/c)
+ Uri resolvedUri = Uri.fromFile(f);
+ String rootUriNoTrailingSlash = rootUri.getEncodedPath();
+ rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
+ if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
+ return null;
+ }
+ String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
+ // Strip leading slash
+ if (!subPath.isEmpty()) {
+ subPath = subPath.substring(1);
+ }
+ Uri.Builder b = new Uri.Builder()
+ .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
+ .authority("localhost")
+ .path(name);
+ if (!subPath.isEmpty()) {
+ b.appendEncodedPath(subPath);
+ }
+ if (f.isDirectory()) {
+ // Add trailing / for directories.
+ b.appendEncodedPath("");
+ }
+ return LocalFilesystemURL.parse(b.build());
+ }
+
+ @Override
+ public LocalFilesystemURL URLforFilesystemPath(String path) {
+ return localUrlforFullPath(fullPathForFilesystemPath(path));
+ }
+
+ @Override
+ public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
+ String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+ boolean create = false;
+ boolean exclusive = false;
+
+ if (options != null) {
+ create = options.optBoolean("create");
+ if (create) {
+ exclusive = options.optBoolean("exclusive");
+ }
+ }
+
+ // Check for a ":" character in the file to line up with BB and iOS
+ if (path.contains(":")) {
+ throw new EncodingException("This path has an invalid \":\" in it.");
+ }
+
+ LocalFilesystemURL requestedURL;
+
+ // Check whether the supplied path is absolute or relative
+ if (directory && !path.endsWith("/")) {
+ path += "/";
+ }
+ if (path.startsWith("/")) {
+ requestedURL = localUrlforFullPath(normalizePath(path));
+ } else {
+ requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
+ }
+
+ File fp = new File(this.filesystemPathForURL(requestedURL));
+
+ if (create) {
+ if (exclusive && fp.exists()) {
+ throw new FileExistsException("create/exclusive fails");
+ }
+ if (directory) {
+ fp.mkdir();
+ } else {
+ fp.createNewFile();
+ }
+ if (!fp.exists()) {
+ throw new FileExistsException("create fails");
+ }
+ }
+ else {
+ if (!fp.exists()) {
+ throw new FileNotFoundException("path does not exist");
+ }
+ if (directory) {
+ if (fp.isFile()) {
+ throw new TypeMismatchException("path doesn't exist or is file");
+ }
+ } else {
+ if (fp.isDirectory()) {
+ throw new TypeMismatchException("path doesn't exist or is directory");
+ }
+ }
+ }
+
+ // Return the directory
+ return makeEntryForURL(requestedURL);
+ }
+
+ @Override
+ public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException {
+
+ File fp = new File(filesystemPathForURL(inputURL));
+
+ // You can't delete a directory that is not empty
+ if (fp.isDirectory() && fp.list().length > 0) {
+ throw new InvalidModificationException("You can't delete a directory that is not empty.");
+ }
+
+ return fp.delete();
+ }
+
+ @Override
+ public boolean exists(LocalFilesystemURL inputURL) {
+ File fp = new File(filesystemPathForURL(inputURL));
+ return fp.exists();
+ }
+
+ @Override
+ public long getFreeSpaceInBytes() {
+ return DirectoryManager.getFreeSpaceInBytes(rootUri.getPath());
+ }
+
+ @Override
+ public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException {
+ File directory = new File(filesystemPathForURL(inputURL));
+ return removeDirRecursively(directory);
+ }
+
+ protected boolean removeDirRecursively(File directory) throws FileExistsException {
+ if (directory.isDirectory()) {
+ for (File file : directory.listFiles()) {
+ removeDirRecursively(file);
+ }
+ }
+
+ if (!directory.delete()) {
+ throw new FileExistsException("could not delete: " + directory.getName());
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
+ File fp = new File(filesystemPathForURL(inputURL));
+
+ if (!fp.exists()) {
+ // The directory we are listing doesn't exist so we should fail.
+ throw new FileNotFoundException();
+ }
+
+ File[] files = fp.listFiles();
+ if (files == null) {
+ // inputURL is a directory
+ return null;
+ }
+ LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
+ for (int i = 0; i < files.length; i++) {
+ entries[i] = URLforFilesystemPath(files[i].getPath());
+ }
+
+ return entries;
+ }
+
+ @Override
+ public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+ File file = new File(filesystemPathForURL(inputURL));
+
+ if (!file.exists()) {
+ throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
+ }
+
+ JSONObject metadata = new JSONObject();
+ try {
+ // Ensure that directories report a size of 0
+ metadata.put("size", file.isDirectory() ? 0 : file.length());
+ metadata.put("type", resourceApi.getMimeType(Uri.fromFile(file)));
+ metadata.put("name", file.getName());
+ metadata.put("fullPath", inputURL.path);
+ metadata.put("lastModifiedDate", file.lastModified());
+ } catch (JSONException e) {
+ return null;
+ }
+ return metadata;
+ }
+
+ private void copyFile(Filesystem srcFs, LocalFilesystemURL srcURL, File destFile, boolean move) throws IOException, InvalidModificationException, NoModificationAllowedException {
+ if (move) {
+ String realSrcPath = srcFs.filesystemPathForURL(srcURL);
+ if (realSrcPath != null) {
+ File srcFile = new File(realSrcPath);
+ if (srcFile.renameTo(destFile)) {
+ return;
+ }
+ // Trying to rename the file failed. Possibly because we moved across file system on the device.
+ }
+ }
+
+ CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(srcFs.toNativeUri(srcURL));
+ copyResource(offr, new FileOutputStream(destFile));
+
+ if (move) {
+ srcFs.removeFileAtLocalURL(srcURL);
+ }
+ }
+
+ private void copyDirectory(Filesystem srcFs, LocalFilesystemURL srcURL, File dstDir, boolean move) throws IOException, NoModificationAllowedException, InvalidModificationException, FileExistsException {
+ if (move) {
+ String realSrcPath = srcFs.filesystemPathForURL(srcURL);
+ if (realSrcPath != null) {
+ File srcDir = new File(realSrcPath);
+ // If the destination directory already exists and is empty then delete it. This is according to spec.
+ if (dstDir.exists()) {
+ if (dstDir.list().length > 0) {
+ throw new InvalidModificationException("directory is not empty");
+ }
+ dstDir.delete();
+ }
+ // Try to rename the directory
+ if (srcDir.renameTo(dstDir)) {
+ return;
+ }
+ // Trying to rename the file failed. Possibly because we moved across file system on the device.
+ }
+ }
+
+ if (dstDir.exists()) {
+ if (dstDir.list().length > 0) {
+ throw new InvalidModificationException("directory is not empty");
+ }
+ } else {
+ if (!dstDir.mkdir()) {
+ // If we can't create the directory then fail
+ throw new NoModificationAllowedException("Couldn't create the destination directory");
+ }
+ }
+
+ LocalFilesystemURL[] children = srcFs.listChildren(srcURL);
+ for (LocalFilesystemURL childLocalUrl : children) {
+ File target = new File(dstDir, new File(childLocalUrl.path).getName());
+ if (childLocalUrl.isDirectory) {
+ copyDirectory(srcFs, childLocalUrl, target, false);
+ } else {
+ copyFile(srcFs, childLocalUrl, target, false);
+ }
+ }
+
+ if (move) {
+ srcFs.recursiveRemoveFileAtLocalURL(srcURL);
+ }
+ }
+
+ @Override
+ public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
+ Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
+
+ // Check to see if the destination directory exists
+ String newParent = this.filesystemPathForURL(destURL);
+ File destinationDir = new File(newParent);
+ if (!destinationDir.exists()) {
+ // The destination does not exist so we should fail.
+ throw new FileNotFoundException("The source does not exist");
+ }
+
+ // Figure out where we should be copying to
+ final LocalFilesystemURL destinationURL = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
+
+ Uri dstNativeUri = toNativeUri(destinationURL);
+ Uri srcNativeUri = srcFs.toNativeUri(srcURL);
+ // Check to see if source and destination are the same file
+ if (dstNativeUri.equals(srcNativeUri)) {
+ throw new InvalidModificationException("Can't copy onto itself");
+ }
+
+ if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
+ throw new InvalidModificationException("Source URL is read-only (cannot move)");
+ }
+
+ File destFile = new File(dstNativeUri.getPath());
+ if (destFile.exists()) {
+ if (!srcURL.isDirectory && destFile.isDirectory()) {
+ throw new InvalidModificationException("Can't copy/move a file to an existing directory");
+ } else if (srcURL.isDirectory && destFile.isFile()) {
+ throw new InvalidModificationException("Can't copy/move a directory to an existing file");
+ }
+ }
+
+ if (srcURL.isDirectory) {
+ // E.g. Copy /sdcard/myDir to /sdcard/myDir/backup
+ if (dstNativeUri.toString().startsWith(srcNativeUri.toString() + '/')) {
+ throw new InvalidModificationException("Can't copy directory into itself");
+ }
+ copyDirectory(srcFs, srcURL, destFile, move);
+ } else {
+ copyFile(srcFs, srcURL, destFile, move);
+ }
+ return makeEntryForURL(destinationURL);
+ }
+
+ @Override
+ public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
+ int offset, boolean isBinary) throws IOException, NoModificationAllowedException {
+
+ boolean append = false;
+ if (offset > 0) {
+ this.truncateFileAtURL(inputURL, offset);
+ append = true;
+ }
+
+ byte[] rawData;
+ if (isBinary) {
+ rawData = Base64.decode(data, Base64.DEFAULT);
+ } else {
+ rawData = data.getBytes(Charset.defaultCharset());
+ }
+ ByteArrayInputStream in = new ByteArrayInputStream(rawData);
+ try
+ {
+ byte buff[] = new byte[rawData.length];
+ String absolutePath = filesystemPathForURL(inputURL);
+ FileOutputStream out = new FileOutputStream(absolutePath, append);
+ try {
+ in.read(buff, 0, buff.length);
+ out.write(buff, 0, rawData.length);
+ out.flush();
+ } finally {
+ // Always close the output
+ out.close();
+ }
+ if (isPublicDirectory(absolutePath)) {
+ broadcastNewFile(Uri.fromFile(new File(absolutePath)));
+ }
+ }
+ catch (NullPointerException e)
+ {
+ // This is a bug in the Android implementation of the Java Stack
+ NoModificationAllowedException realException = new NoModificationAllowedException(inputURL.toString());
+ realException.initCause(e);
+ throw realException;
+ }
+
+ return rawData.length;
+ }
+
+ private boolean isPublicDirectory(String absolutePath) {
+ // TODO: should expose a way to scan app's private files (maybe via a flag).
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ // Lollipop has a bug where SD cards are null.
+ for (File f : context.getExternalMediaDirs()) {
+ if(f != null && absolutePath.startsWith(f.getAbsolutePath())) {
+ return true;
+ }
+ }
+ }
+
+ String extPath = Environment.getExternalStorageDirectory().getAbsolutePath();
+ return absolutePath.startsWith(extPath);
+ }
+
+ /**
+ * Send broadcast of new file so files appear over MTP
+ */
+ private void broadcastNewFile(Uri nativeUri) {
+ Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, nativeUri);
+ context.sendBroadcast(intent);
+ }
+
+ @Override
+ public long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException {
+ File file = new File(filesystemPathForURL(inputURL));
+
+ if (!file.exists()) {
+ throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
+ }
+
+ RandomAccessFile raf = new RandomAccessFile(filesystemPathForURL(inputURL), "rw");
+ try {
+ if (raf.length() >= size) {
+ FileChannel channel = raf.getChannel();
+ channel.truncate(size);
+ return size;
+ }
+
+ return raf.length();
+ } finally {
+ raf.close();
+ }
+
+
+ }
+
+ @Override
+ public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
+ String path = filesystemPathForURL(inputURL);
+ File file = new File(path);
+ return file.exists();
+ }
+
+ // This is a copy & paste from CordovaResource API that is required since CordovaResourceApi
+ // has a bug pre-4.0.0.
+ // TODO: Once cordova-android@4.0.0 is released, delete this copy and make the plugin depend on
+ // 4.0.0 with an engine tag.
+ private static void copyResource(CordovaResourceApi.OpenForReadResult input, OutputStream outputStream) throws IOException {
+ try {
+ InputStream inputStream = input.inputStream;
+ if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
+ FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
+ FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
+ long offset = 0;
+ long length = input.length;
+ if (input.assetFd != null) {
+ offset = input.assetFd.getStartOffset();
+ }
+ // transferFrom()'s 2nd arg is a relative position. Need to set the absolute
+ // position first.
+ inChannel.position(offset);
+ outChannel.transferFrom(inChannel, 0, length);
+ } else {
+ final int BUFFER_SIZE = 8192;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ for (;;) {
+ int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
+
+ if (bytesRead <= 0) {
+ break;
+ }
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ }
+ } finally {
+ input.inputStream.close();
+ if (outputStream != null) {
+ outputStream.close();
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+import android.net.Uri;
+
+public class LocalFilesystemURL {
+
+ public static final String FILESYSTEM_PROTOCOL = "cdvfile";
+
+ public final Uri uri;
+ public final String fsName;
+ public final String path;
+ public final boolean isDirectory;
+
+ private LocalFilesystemURL(Uri uri, String fsName, String fsPath, boolean isDirectory) {
+ this.uri = uri;
+ this.fsName = fsName;
+ this.path = fsPath;
+ this.isDirectory = isDirectory;
+ }
+
+ public static LocalFilesystemURL parse(Uri uri) {
+ if (!FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
+ return null;
+ }
+ String path = uri.getPath();
+ if (path.length() < 1) {
+ return null;
+ }
+ int firstSlashIdx = path.indexOf('/', 1);
+ if (firstSlashIdx < 0) {
+ return null;
+ }
+ String fsName = path.substring(1, firstSlashIdx);
+ path = path.substring(firstSlashIdx);
+ boolean isDirectory = path.charAt(path.length() - 1) == '/';
+ return new LocalFilesystemURL(uri, fsName, path, isDirectory);
+ }
+
+ public static LocalFilesystemURL parse(String uri) {
+ return parse(Uri.parse(uri));
+ }
+
+ public String toString() {
+ return uri.toString();
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class NoModificationAllowedException extends Exception {
+
+ public NoModificationAllowedException(String message) {
+ super(message);
+ }
+
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+import android.util.SparseArray;
+
+import org.apache.cordova.CallbackContext;
+
+/**
+ * Holds pending runtime permission requests
+ */
+class PendingRequests {
+ private int currentReqId = 0;
+ private SparseArray<Request> requests = new SparseArray<Request>();
+
+ /**
+ * Creates a request and adds it to the array of pending requests. Each created request gets a
+ * unique result code for use with requestPermission()
+ * @param rawArgs The raw arguments passed to the plugin
+ * @param action The action this request corresponds to (get file, etc.)
+ * @param callbackContext The CallbackContext for this plugin call
+ * @return The request code that can be used to retrieve the Request object
+ */
+ public synchronized int createRequest(String rawArgs, int action, CallbackContext callbackContext) {
+ Request req = new Request(rawArgs, action, callbackContext);
+ requests.put(req.requestCode, req);
+ return req.requestCode;
+ }
+
+ /**
+ * Gets the request corresponding to this request code and removes it from the pending requests
+ * @param requestCode The request code for the desired request
+ * @return The request corresponding to the given request code or null if such a
+ * request is not found
+ */
+ public synchronized Request getAndRemove(int requestCode) {
+ Request result = requests.get(requestCode);
+ requests.remove(requestCode);
+ return result;
+ }
+
+ /**
+ * Holds the options and CallbackContext for a call made to the plugin.
+ */
+ public class Request {
+
+ // Unique int used to identify this request in any Android permission callback
+ private int requestCode;
+
+ // Action to be performed after permission request result
+ private int action;
+
+ // Raw arguments passed to plugin
+ private String rawArgs;
+
+ // The callback context for this plugin request
+ private CallbackContext callbackContext;
+
+ private Request(String rawArgs, int action, CallbackContext callbackContext) {
+ this.rawArgs = rawArgs;
+ this.action = action;
+ this.callbackContext = callbackContext;
+ this.requestCode = currentReqId ++;
+ }
+
+ public int getAction() {
+ return this.action;
+ }
+
+ public String getRawArgs() {
+ return rawArgs;
+ }
+
+ public CallbackContext getCallbackContext() {
+ return callbackContext;
+ }
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class TypeMismatchException extends Exception {
+
+ public TypeMismatchException(String message) {
+ super(message);
+ }
+
+}
--- /dev/null
+/*
+ * 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 org.apache.cordova.statusbar;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Build;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PluginResult;
+import org.json.JSONException;
+import java.util.Arrays;
+
+public class StatusBar extends CordovaPlugin {
+ private static final String TAG = "StatusBar";
+
+ /**
+ * Sets the context of the Command. This can then be used to do things like
+ * get file paths associated with the Activity.
+ *
+ * @param cordova The context of the main Activity.
+ * @param webView The CordovaWebView Cordova is running in.
+ */
+ @Override
+ public void initialize(final CordovaInterface cordova, CordovaWebView webView) {
+ LOG.v(TAG, "StatusBar: initialization");
+ super.initialize(cordova, webView);
+
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially
+ // by the Cordova.
+ Window window = cordova.getActivity().getWindow();
+ window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+
+ // Read 'StatusBarBackgroundColor' from config.xml, default is #000000.
+ setStatusBarBackgroundColor(preferences.getString("StatusBarBackgroundColor", "#000000"));
+
+ // Read 'StatusBarStyle' from config.xml, default is 'lightcontent'.
+ setStatusBarStyle(preferences.getString("StatusBarStyle", "lightcontent"));
+ }
+ });
+ }
+
+ /**
+ * Executes the request and returns PluginResult.
+ *
+ * @param action The action to execute.
+ * @param args JSONArry of arguments for the plugin.
+ * @param callbackContext The callback id used when calling back into JavaScript.
+ * @return True if the action was valid, false otherwise.
+ */
+ @Override
+ public boolean execute(final String action, final CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
+ LOG.v(TAG, "Executing action: " + action);
+ final Activity activity = this.cordova.getActivity();
+ final Window window = activity.getWindow();
+
+ if ("_ready".equals(action)) {
+ boolean statusBarVisible = (window.getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, statusBarVisible));
+ return true;
+ }
+
+ if ("show".equals(action)) {
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // SYSTEM_UI_FLAG_FULLSCREEN is available since JellyBean, but we
+ // use KitKat here to be aligned with "Fullscreen" preference
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ int uiOptions = window.getDecorView().getSystemUiVisibility();
+ uiOptions &= ~View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ uiOptions &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
+
+ window.getDecorView().setSystemUiVisibility(uiOptions);
+ }
+
+ // CB-11197 We still need to update LayoutParams to force status bar
+ // to be hidden when entering e.g. text fields
+ window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+ });
+ return true;
+ }
+
+ if ("hide".equals(action)) {
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // SYSTEM_UI_FLAG_FULLSCREEN is available since JellyBean, but we
+ // use KitKat here to be aligned with "Fullscreen" preference
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ int uiOptions = window.getDecorView().getSystemUiVisibility()
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_FULLSCREEN;
+
+ window.getDecorView().setSystemUiVisibility(uiOptions);
+ }
+
+ // CB-11197 We still need to update LayoutParams to force status bar
+ // to be hidden when entering e.g. text fields
+ window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+ });
+ return true;
+ }
+
+ if ("backgroundColorByHexString".equals(action)) {
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ setStatusBarBackgroundColor(args.getString(0));
+ } catch (JSONException ignore) {
+ LOG.e(TAG, "Invalid hexString argument, use f.i. '#777777'");
+ }
+ }
+ });
+ return true;
+ }
+
+ if ("overlaysWebView".equals(action)) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ setStatusBarTransparent(args.getBoolean(0));
+ } catch (JSONException ignore) {
+ LOG.e(TAG, "Invalid boolean argument");
+ }
+ }
+ });
+ return true;
+ }
+ else return args.getBoolean(0) == false;
+ }
+
+ if ("styleDefault".equals(action)) {
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setStatusBarStyle("default");
+ }
+ });
+ return true;
+ }
+
+ if ("styleLightContent".equals(action)) {
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setStatusBarStyle("lightcontent");
+ }
+ });
+ return true;
+ }
+
+ if ("styleBlackTranslucent".equals(action)) {
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setStatusBarStyle("blacktranslucent");
+ }
+ });
+ return true;
+ }
+
+ if ("styleBlackOpaque".equals(action)) {
+ this.cordova.getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setStatusBarStyle("blackopaque");
+ }
+ });
+ return true;
+ }
+
+ return false;
+ }
+
+ private void setStatusBarBackgroundColor(final String colorPref) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ if (colorPref != null && !colorPref.isEmpty()) {
+ final Window window = cordova.getActivity().getWindow();
+ // Method and constants not available on all SDKs but we want to be able to compile this code with any SDK
+ window.clearFlags(0x04000000); // SDK 19: WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ window.addFlags(0x80000000); // SDK 21: WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ try {
+ // Using reflection makes sure any 5.0+ device will work without having to compile with SDK level 21
+ window.getClass().getMethod("setStatusBarColor", int.class).invoke(window, Color.parseColor(colorPref));
+ } catch (IllegalArgumentException ignore) {
+ LOG.e(TAG, "Invalid hexString argument, use f.i. '#999999'");
+ } catch (Exception ignore) {
+ // this should not happen, only in case Android removes this method in a version > 21
+ LOG.w(TAG, "Method window.setStatusBarColor not found for SDK level " + Build.VERSION.SDK_INT);
+ }
+ }
+ }
+ }
+
+ private void setStatusBarTransparent(final boolean transparent) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ final Window window = cordova.getActivity().getWindow();
+ if (transparent) {
+ window.getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+ window.setStatusBarColor(Color.TRANSPARENT);
+ }
+ else {
+ window.getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_VISIBLE);
+ }
+ }
+ }
+
+ private void setStatusBarStyle(final String style) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (style != null && !style.isEmpty()) {
+ View decorView = cordova.getActivity().getWindow().getDecorView();
+ int uiOptions = decorView.getSystemUiVisibility();
+
+ String[] darkContentStyles = {
+ "default",
+ };
+
+ String[] lightContentStyles = {
+ "lightcontent",
+ "blacktranslucent",
+ "blackopaque",
+ };
+
+ if (Arrays.asList(darkContentStyles).contains(style.toLowerCase())) {
+ decorView.setSystemUiVisibility(uiOptions | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ return;
+ }
+
+ if (Arrays.asList(lightContentStyles).contains(style.toLowerCase())) {
+ decorView.setSystemUiVisibility(uiOptions & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ return;
+ }
+
+ LOG.e(TAG, "Invalid style, must be either 'default', 'lightcontent' or the deprecated 'blacktranslucent' and 'blackopaque'");
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ 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 org.apache.cordova.whitelist;
+
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.ConfigXmlParser;
+import org.apache.cordova.LOG;
+import org.apache.cordova.Whitelist;
+import org.xmlpull.v1.XmlPullParser;
+
+import android.content.Context;
+
+public class WhitelistPlugin extends CordovaPlugin {
+ private static final String LOG_TAG = "WhitelistPlugin";
+ private Whitelist allowedNavigations;
+ private Whitelist allowedIntents;
+ private Whitelist allowedRequests;
+
+ // Used when instantiated via reflection by PluginManager
+ public WhitelistPlugin() {
+ }
+ // These can be used by embedders to allow Java-configuration of whitelists.
+ public WhitelistPlugin(Context context) {
+ this(new Whitelist(), new Whitelist(), null);
+ new CustomConfigXmlParser().parse(context);
+ }
+ public WhitelistPlugin(XmlPullParser xmlParser) {
+ this(new Whitelist(), new Whitelist(), null);
+ new CustomConfigXmlParser().parse(xmlParser);
+ }
+ public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
+ if (allowedRequests == null) {
+ allowedRequests = new Whitelist();
+ allowedRequests.addWhiteListEntry("file:///*", false);
+ allowedRequests.addWhiteListEntry("data:*", false);
+ }
+ this.allowedNavigations = allowedNavigations;
+ this.allowedIntents = allowedIntents;
+ this.allowedRequests = allowedRequests;
+ }
+ @Override
+ public void pluginInitialize() {
+ if (allowedNavigations == null) {
+ allowedNavigations = new Whitelist();
+ allowedIntents = new Whitelist();
+ allowedRequests = new Whitelist();
+ new CustomConfigXmlParser().parse(webView.getContext());
+ }
+ }
+
+ private class CustomConfigXmlParser extends ConfigXmlParser {
+ @Override
+ public void handleStartTag(XmlPullParser xml) {
+ String strNode = xml.getName();
+ if (strNode.equals("content")) {
+ String startPage = xml.getAttributeValue(null, "src");
+ allowedNavigations.addWhiteListEntry(startPage, false);
+ } else if (strNode.equals("allow-navigation")) {
+ String origin = xml.getAttributeValue(null, "href");
+ if ("*".equals(origin)) {
+ allowedNavigations.addWhiteListEntry("http://*/*", false);
+ allowedNavigations.addWhiteListEntry("https://*/*", false);
+ allowedNavigations.addWhiteListEntry("data:*", false);
+ } else {
+ allowedNavigations.addWhiteListEntry(origin, false);
+ }
+ } else if (strNode.equals("allow-intent")) {
+ String origin = xml.getAttributeValue(null, "href");
+ allowedIntents.addWhiteListEntry(origin, false);
+ } else if (strNode.equals("access")) {
+ String origin = xml.getAttributeValue(null, "origin");
+ String subdomains = xml.getAttributeValue(null, "subdomains");
+ boolean external = (xml.getAttributeValue(null, "launch-external") != null);
+ if (origin != null) {
+ if (external) {
+ LOG.w(LOG_TAG, "Found <access launch-external> within config.xml. Please use <allow-intent> instead.");
+ allowedIntents.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
+ } else {
+ if ("*".equals(origin)) {
+ allowedRequests.addWhiteListEntry("http://*/*", false);
+ allowedRequests.addWhiteListEntry("https://*/*", false);
+ } else {
+ allowedRequests.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
+ }
+ }
+ }
+ }
+ }
+ @Override
+ public void handleEndTag(XmlPullParser xml) {
+ }
+ }
+
+ @Override
+ public Boolean shouldAllowNavigation(String url) {
+ if (allowedNavigations.isUrlWhiteListed(url)) {
+ return true;
+ }
+ return null; // Default policy
+ }
+
+ @Override
+ public Boolean shouldAllowRequest(String url) {
+ if (Boolean.TRUE == shouldAllowNavigation(url)) {
+ return true;
+ }
+ if (allowedRequests.isUrlWhiteListed(url)) {
+ return true;
+ }
+ return null; // Default policy
+ }
+
+ @Override
+ public Boolean shouldOpenExternalUrl(String url) {
+ if (allowedIntents.isUrlWhiteListed(url)) {
+ return true;
+ }
+ return null; // Default policy
+ }
+
+ public Whitelist getAllowedNavigations() {
+ return allowedNavigations;
+ }
+
+ public void setAllowedNavigations(Whitelist allowedNavigations) {
+ this.allowedNavigations = allowedNavigations;
+ }
+
+ public Whitelist getAllowedIntents() {
+ return allowedIntents;
+ }
+
+ public void setAllowedIntents(Whitelist allowedIntents) {
+ this.allowedIntents = allowedIntents;
+ }
+
+ public Whitelist getAllowedRequests() {
+ return allowedRequests;
+ }
+
+ public void setAllowedRequests(Whitelist allowedRequests) {
+ this.allowedRequests = allowedRequests;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/background" />
+ <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/background" />
+ <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/background" />
+ <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/background" />
+ <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/background" />
+ <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/background" />
+ <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="background">#0a4a9e</color>
+</resources>
--- /dev/null
+<?xml version='1.0' encoding='utf-8'?>
+<resources>
+ <string name="app_name">Tortuga</string>
+ <string name="launcher_name">@string/app_name</string>
+ <string name="activity_name">@string/launcher_name</string>
+</resources>
--- /dev/null
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="fr.enhydra.tortuga.home" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <feature name="Whitelist">
+ <param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
+ <param name="onload" value="true" />
+ </feature>
+ <feature name="Device">
+ <param name="android-package" value="org.apache.cordova.device.Device" />
+ </feature>
+ <feature name="File">
+ <param name="android-package" value="org.apache.cordova.file.FileUtils" />
+ <param name="onload" value="true" />
+ </feature>
+ <allow-navigation href="cdvfile:*" />
+ <feature name="CDVOrientation">
+ <param name="android-package" value="cordova.plugins.screenorientation.CDVOrientation" />
+ </feature>
+ <feature name="StatusBar">
+ <param name="android-package" value="org.apache.cordova.statusbar.StatusBar" />
+ <param name="onload" value="true" />
+ </feature>
+ <feature name="IntentShim">
+ <param name="android-package" value="com.darryncampbell.cordova.plugin.intent.IntentShim" />
+ <param name="onload" value="true" />
+ </feature>
+ <name>Tortuga</name>
+ <description>Tortuga home remote app</description>
+ <author email="vincent@enhydra.fr" href="https://enhydra.fr">Vincent Vanwaelscappel</author>
+ <content src="https://home.tortuga.enhydra.fr/" />
+ <access origin="*" />
+ <allow-intent href="http://*/*" />
+ <allow-intent href="https://*/*" />
+ <allow-intent href="tel:*" />
+ <allow-intent href="sms:*" />
+ <allow-intent href="mailto:*" />
+ <allow-intent href="geo:*" />
+ <icon src="res/icon.png" />
+ <allow-navigation href="https://*.home.tortuga.enhydra.fr/*" />
+ <allow-navigation href="https://home.tortuga.enhydra.fr/*" />
+ <allow-intent href="market:*" />
+ <resource-file src="res/values/colors.xml" target="/app/src/main/res/values/colors.xml" />
+ <icon background="@color/background" density="ldpi" foreground="res/icon/android/ldpi-foreground.png" />
+ <icon background="@color/background" density="mdpi" foreground="res/icon/android/mdpi-foreground.png" />
+ <icon background="@color/background" density="hdpi" foreground="res/icon/android/hdpi-foreground.png" />
+ <icon background="@color/background" density="xhdpi" foreground="res/icon/android/xhdpi-foreground.png" />
+ <icon background="@color/background" density="xxhdpi" foreground="res/icon/android/xxhdpi-foreground.png" />
+ <icon background="@color/background" density="xxxhdpi" foreground="res/icon/android/xxxhdpi-foreground.png" />
+ <preference name="loglevel" value="DEBUG" />
+ <preference name="AndroidLaunchMode" value="singleTask" />
+</widget>
--- /dev/null
+<paths xmlns:android='http://schemas.android.com/apk/res/android'>
+ <external-path name='external_files' path='.' />
+</paths>
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+adb connect 192.168.13.40:5555
+adb connect 192.168.13.41:5555
--- /dev/null
+#!/usr/bin/php
+<?php
+require_once __DIR__ . "/../scripts/import.php";
+$heartbeats = ['cron', /*'logcats', 'logcatb',*/
+ 'domoticz', 'hue', 'squeezebox'];
+
+$hasError = false;
+$mintime = INF;
+
+foreach ($heartbeats as $h) {
+ $hb = getState($h . '_heartbeat');
+ $mintime = min($mintime, $hb);
+ $d = time() - $hb;
+ echo 'Timeout of ' . $h . ' : ' . $d . "\n";
+}
+$diff = time() - $mintime;
+
+if ($diff > 120) {
+ if ($diff > 300) {
+ echo 'Need to restart container.';
+ exit(1);
+ } else {
+ `/application/bin/restarthome`;
+ echo 'Restarted some services';
+ exit(0);
+ }
+}
+
+echo "Everything is running fine :)";
+exit(0);
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+/application/bin/adb-connect
+/application/servers/stopdaemon logcats
+/application/servers/stopdaemon logcatb
+/application/servers/startdaemon logcats
+/application/servers/startdaemon logcatb
--- /dev/null
+#!/bin/sh
+sleep 1
+service atd restart
+sleep 3
+/application/servers/stopdaemon domoticz
+/application/servers/startdaemon domoticz
+/application/servers/stopdaemon cron
+/application/servers/startdaemon cron
+/application/servers/stopdaemon hue
+/application/servers/startdaemon hue
+/application/servers/stopdaemon squeezebox
+/application/servers/startdaemon squeezebox
+/application/bin/restart-logcat
+sleep 5
+/usr/bin/monit
+sleep 1
+/usr/bin/monit reload
--- /dev/null
+#!/bin/sh
+/application/bin/restarthome
+/usr/sbin/php-fpm7.4 -O
\ No newline at end of file
--- /dev/null
+server=1.1.1.1
+server=1.0.0.1
+server=95.217.229.211
+server=151.80.222.79
+server=192.168.13.1
+server=8.8.8.8
+address=/nas.home.tortuga.enhydra.fr/192.168.13.1
+address=/home.tortuga.enhydra.fr/192.168.13.66
+address=/kodidb.home.tortuga.enhydra.fr/192.168.13.66
+address=/squeezebox.home.tortuga.enhydra.fr/192.168.13.67
+address=/mafreebox.freebox.fr/192.168.13.1
+address=/tvheadend.home.tortuga.enhydra.fr/192.168.13.60
+address=/domoticz.home.tortuga.enhydra.fr/192.168.13.67
+address=/nextcloud.home.tortuga.enhydra.fr/192.168.13.7
+address=/harmonyapi.home.tortuga.enhydra.fr/192.168.13.67
+address=/servarr.home.tortuga.enhydra.fr/192.168.13.70
+address=/potainersalon.home.tortuga.enhydra.fr/192.168.13.66
+address=/transmission.home.tortuga.enhydra.fr/192.168.13.7
+address=/paperless.home.tortuga.enhydra.fr/192.168.13.7
+address=/piwigo.home.tortuga.enhydra.fr/192.168.13.7
+address=/dockerbackup.home.tortuga.enhydra.fr/192.168.13.70
\ No newline at end of file
//'Salon' => 'dc:a6:32:02:47:c1',
//'Salon' => 'cc:cc:2d:15:82:0e',
//'Salon' => '5a:a1:4c:5c:e7:5e',
- 'Salon' => 'bb:bb:78:49:8f:a4',
+ 'Salon' => 'bb:bb:b1:c8:92:09',
//'Salon' => '00:04:20:17:82:8b',
'Chambre' => 'b8:27:eb:31:e1:44',
//'WC' => '00:04:20:2a:05:2e',
$shortcuts['lights'] = $c['all'];
$favoriteslights = $c['favorites'];
- $nav = ['home', 'lights', 'music', 'media', 'coffee', 'switch', 'fan', 'settings', 'alert', 'off'];
+ $nav = ['home', 'lights', 'music', /*'media', */'coffee', 'switch'/*, 'fan'*/, 'settings', 'alert', 'off'];
- include "media.php";
+// include "media.php";
include "default.php";
}
\ No newline at end of file
config('SCREENSAVER_BRIGHTNESS', 'auto');
config('SLEEPTYPE', 'screensaver');
config('SCREENSAVER', 'weatherstation');
-config('VOLUME_DEVICE', 'RaspberryPi');
+config('VOLUME_DEVICE', 'SqueezeboxPlayer');
config('VOLUME_STEP',5);
config('HIDEMASK_TIMEOUT', 250);
config('THEME','#086d89');
config('ROOM_NAME', 'Lit Vincent');
config('SQUEEZEBOX_PLAYER', 'Lit Vincent');
config('SQUEEZEBOX_AMBIANCE_PLAYER', 'Chambre');
-config('VOLUME_DEVICE', 'RaspberryPi');
-config('VOLUME_STEP',5);
+config('VOLUME_DEVICE', 'SqueezeboxPlayer');
+config('VOLUME_STEP', 5);
config('SCREENSAVER_BRIGHTNESS', 'auto');
config('SLEEPTYPE', 'screensaver');
config('SCREENSAVER', 'weatherstation');
config('HIDEMASK_TIMEOUT', 250);
config('SLEEPSCREEN', 8);
-config('THEME','#a62634');
+config('THEME', '#a62634');
if (DISPLAYINTERFACE) {
$shortcuts['media'][] = ['label' => 'Films', 'type' => 'sub', 'sub' => 'movies'];
if ($device == 'salon' || $device == 'bureau' || $device == 'bureausun') {
$shortcuts['media'][] = array('type' => 'netflix', 'url' => 'scripts/netflix.php?id=home', 'label' => '<img src="images/netflix.png">');
+ $shortcuts['media'][] = array('type' => 'amazonprime', 'url' => 'scripts/shield.php?amazonprime=home', 'label' => '<img src="images/amazonprime.png">');
+ $shortcuts['media'][] = array('type' => 'nintendoswitch', 'url' => 'scripts/switch.php', 'label' => '<img src="images/switch.png">');
$shortcuts['media'][] = ['label' => 'Vidéo web', 'type' => 'raspberrycast'];
}
if ($device == 'bureau' || $device == 'bureausun') {
function home()
{
$favorites = [
- ['type' => 'light', 'scene' => 'home/welcome/eco', 'label' => 'Bienvenue 🌿'],
+ ['type' => 'light', 'scene' => 'home/welcome/eco', 'label' => 'Bienvenue 🌿', 'confirm' => ['message' => 'Quelqu\'un dort peut-être. Veuillez confirmer votre action.', 'conditions' => ['night' => '1']]],
['type' => 'light', 'scene' => 'home/off', 'label' => 'éteindre'],
['type' => 'light', 'scene' => 'home/welcome', 'label' => 'Bienvenue ★', 'confirm' => ['message' => 'Quelqu\'un dort peut-être. Veuillez confirmer votre action.', 'conditions' => ['night' => '1']]],
];
function salon()
{
$favorites = [
- ['type' => 'light', 'scene' => 'salon/on', 'label' => 'Allumer'],
+ ['type' => 'light', 'scene' => 'salon/auto', 'label' => 'Allumer'],
['type' => 'light', 'scene' => 'salon/off', 'label' => 'éteindre'],
['type' => 'light', 'scene' => 'salon/lumineux', 'label' => 'lumineux'],
['type' => 'light', 'scene' => 'salon/cinema', 'label' => 'cinéma'],
['type' => 'light', 'scene' => 'salon/tamise', 'label' => 'Tamisé'],
['type' => 'light', 'scene' => 'salon/lecturenocture', 'label' => 'Lecture nocturne'],
['type' => 'light', 'scene' => 'salon/cheminee', 'label' => 'Cheminée'],
+ ['type' => 'light', 'scene' => 'salon/bar/toggle', 'label' => 'Bar'],
];
$all = array_merge($favorites, [['type' => 'separator', 'label' => 'Projecteur'],
['type' => 'light', 'scene' => 'salon/projector/on', 'label' => 'Allumer'],
'Connexion MyCanal' => array('freebox' => 'replay', 'shield' => 'mycanal:connect:home'),
'Replay' => array('freebox' => 'replay', 'shield' => 'mycanal:replay:home'),
'Netflix' => array('freebox' => 'netflix', 'shield' => 'netflix:home'),
+ 'Amazon Prime' => array('shield' => 'amazonprime:home'),
'Infos',
'France Info' => array('stream' => 'tvheadend:franceinfo:', 'channel' => 27, 'shield' => 'mycanal:live:670', 'logo' => '41072782'),
'Cnews' => array('stream' => 'tvheadend:CNEWS', 'channel' => 16, 'shield' => 'mycanal:live:480', 'logo' => '64698936'),
$name = '<img class="logo" style="margin-top:12%;" alt="' . $name . '" src="' . cacheMedia('http://thumb.canalplus.pro/bddpe/unsafe/' . $service['logo'], 'webp') . '">';
} elseif ($name === 'Netflix') {
$name = '<img class="logo" alt="' . $name . '" src="/images/netflix.png">';
+ }else if($name==='Amazon Prime'){
+ $name = '<img class="logo" alt="' . $name . '" src="/images/amazonprime.png">';
}
if (is_numeric($name)) {
$e = explode(':', $service['shield'], 2);
if ($name === 'netflix') {
$name = '<img src="images/netflix.png">';
+ } else if($name==='amazonprime'){
+ $name = '<img src="images/amazonprime.png">';
}
$shortcuts['sub-tv'][] = array('type' => 'shield', 'url' => 'scripts/shield.php?' . $e[0] . '=' . $e[1], 'label' => $name);
}
<?php
$shortcuts['water'] = [
+ ['type' => 'light', 'scene' => 'sdb/hotwater/auto', 'label' => 'Auto'],
['type' => 'light', 'scene' => 'sdb/hotwater/eco', 'label' => 'Eco'],
['type' => 'light', 'scene' => 'sdb/hotwater/max', 'label' => 'Max'],
['type' => 'light', 'scene' => 'sdb/hotwater/off', 'label' => 'Off'],
ini_set('memory_limit', '1G');
define('TIMELIMIT', 10);
define('DISPLAYINTERFACE', true);
+
require_once "scripts/import.php";
init();
profile('init index', __FILE__, __LINE__);
return $p . '?j=' . filemtime($p);
}
+
?><!DOCTYPE html>
<html lang="fr">
<head>
</main>
</div>
<?php
+
if (false) {
echo '<script src="' . relativePath('js/webapp.js') . '"></script>' . "\n";
} ?>
<?php
+echo ':)';
phpinfo();
\ No newline at end of file
}, 10000);
}
- if (true || raspberry) {
+ if (true || raspberry || androidApp) {
console.log('define check ecomode');
setInterval(function () {
+ console.log('check ecomode');
checkEcoMode(false);
- }, 60000);
+ }, 30000);
checkEcoMode(true);
} else {
console.log('no raspberry, ecomode false');
}
console.log('menu init');
- menu = new MmenuLight(
- document.querySelector("#mainnav")
- );
+ menu = new MmenuLight(document.querySelector("#mainnav"));
menunav = menu.navigation({theme: 'dark', title: ''});
menudrawer = menu.offcanvas();
}
$.ajax({
- url: '/scripts/accordionstate.php',
- method: 'post',
- data: {close: close, open: open}
+ url: '/scripts/accordionstate.php', method: 'post', data: {close: close, open: open}
});
$('#scrollholder').scrollTo(0);
console.log('init hammer');
// Long click
var mc = new Hammer.Manager(document, {
- recognizers: [
- // RecognizerClass, [options], [recognizeWith, ...], [requireFailure, ...]
- [Hammer.Press, {time: 551}],
- ]
+ recognizers: [// RecognizerClass, [options], [recognizeWith, ...], [requireFailure, ...]
+ [Hammer.Press, {time: 551}],]
});
mc.on('press', function (e) {
}
function checkEcoMode(init) {
- $.get('/scripts/ecomode.php?j=' + Date.now(), function (data) {
+ $.get('/scripts/ecomode.php?j=' + Date.now() + '&heartbeat=1', function (data) {
var formerEcoMode = ecomode;
ecomode = (parseInt(data) > 0);
$('body').attr('data-ecomode', ecomode);
if (CONFIG.SCREENSAVER === 'weatherstation') {
$.ajax('scripts/weatherstation.php', {
- dataType: 'html',
- data: {update: 1},
- cache: false,
- success: function (data) {
+ dataType: 'html', data: {update: 1}, cache: false, success: function (data) {
$("#weatherstation").html($(data).find("#weatherstation").html());
updateTime();
}
}).fail(function () {
hideLoader();
});
- ;
}
function updateVelib(force) {
}
var url = 'cache/velib.json?j=';
if (force) {
- url = 'scripts/cron/velib.php?force=1&';
+ url = 'scripts/velib.php?j=';
}
$.get(url + new Date().getTime(), function (data) {
+ console.log(data);
var list = [];
$.each(data.stations, function (k, v) {
- list.push('<li><span class="l">' + v.station.name + '</span><span class="n blue">' + v.nbEbike + '</span><span class="n green">' + v.nbBike + '</span></li>');
+ list.push('<li data-enabled="' + v.enabled + '"><span class="l">' + v.name + '</span><span class="n blue">' + v.nbe + '</span><span class="n green">' + v.nb + '</span></li>');
});
v.find('ul').html(list.join(''));
v.find('.dtime').text(data.time);
minWidth = ww;
}
$("main").css({
- height: hh,
- minWidth: minWidth
+ height: hh, minWidth: minWidth
});
$("#iframeHolder").css({left: fz * 1.3, width: ww - fz * 1.3});
$(".fit").each(function () {
$(this).css({
- width: $(this).find('img').attr('width'),
- height: $(this).find('imgw').attr('height'),
- overflow: ''
+ width: $(this).find('img').attr('width'), height: $(this).find('imgw').attr('height'), overflow: ''
});
var w = $(this).outerWidth();
var h = $(this).outerHeight();
var s = Math.min((scrollWidth - margin) / w, (hh - margin) / h);
$(this).css({
- transform: 'scale(' + s + ')',
- left: (scrollWidth - w * s) / 2,
- top: (hh - h * s) / 2,
- overflow: 'visible'
+ transform: 'scale(' + s + ')', left: (scrollWidth - w * s) / 2, top: (hh - h * s) / 2, overflow: 'visible'
});
$(this).closest('section').css({
- width: scrollWidth,
- height: hh,
- overflow: 'hidden'
+ width: scrollWidth, height: hh, overflow: 'hidden'
})
});
}
paddingSide = 0.5;
}
var css = {
- paddingTop: '0.5em',
- paddingBottom: '0.5em',
- paddingLeft: paddingSide + 'em',
- paddingRight: paddingSide + 'em'
+ paddingTop: '0.5em', paddingBottom: '0.5em', paddingLeft: paddingSide + 'em', paddingRight: paddingSide + 'em'
};
$(a).css(css);
echo '------------------------------------' . "\n";
_logSection('One Loop // ' . $cronmin);
+ cronHeartbeat($cronmin, false);
+ cronHotWater($cronmin);
cronRooms($cronmin);
- //cronInsteon($cronmin);
cronWeather($cronmin);
cronMagnet($cronmin);
if ($cronmin % 5 == 0) {
- cronHotWater($cronmin);
+
cronTraffic($cronmin, false);
cronVelib($cronmin);
cronGuest($cronmin);
if ($cronmin % 5 == 0) {
cronTranscode($cronmin);
}
- cronHeartbeat($cronmin);
if ($cronmin % 15 == 0) {
cronKodi($cronmin);
}
+ cronHeartbeat($cronmin, true);
_logSection('End Loop (min:' . $cronmin . ')');
}
function cronMagnet($cronmin)
{
- _logSection('Magnet links');
- file_get_contents("https://entree.home.tortuga.enhydra.fr/scripts/freeboxapi.php?action=magnets");
+ //_logSection('Magnet links');
+ //file_get_contents("https://entree.home.tortuga.enhydra.fr/scripts/freeboxapi.php?action=magnets");
}
function cronXPlanet($cronmin)
function cronBackyard($cronmin)
{
_logSection('Backyard');
- $device = 679;
+ $device = 6898;
domoticzSwitch($device, getDomoticzDeviceStatus($device) === 'On');
}
sshCommand('pwd', $device['host'], false, true);
}
}
- echo 'vincenthere : ' . getState('vincenthere') . "\n";
}
function cronSqueezeFavorites($cronmin)
function cronVelib($cronmin)
{
_logSection('Velib');
- $cache = ROOT . '/cache/velib.json';
-
- $hour = date('G');
- $day = date('w');
- $limit = 180;
-
- if ($day > 0 && $day < 6 && $hour > 7 && $hour < 11) {
- $limit = 60;
- }
- if (isset($_GET['force']) || !file_exists($cache) || filemtime($cache) < time() - $limit) {
- $velib = array('time' => date('H:i', time()), 'stations' => velibStations());
- $json = json_encode($velib);
- file_put_contents($cache, $json);
- if (isset($_GET['force'])) {
- ob_end_clean();
- header('Content-type: application/json');
- echo $json;
- exit;
- }
- }
+ velibStations(false);
}
function cronTraffic($cronmin, $force = false)
// }
}
-function cronHeartbeat($cronmin)
+function cronHeartbeat($cronmin, $devices = false)
{
_logSection('Heartbeat');
- if ($cronmin % 5 != 0) {
+ setState('cron_heartbeat', time());
+ domoticzCmd(null);
+ squeezeRequest(null);
+ hueCommand(null);
+
+ if (!$devices || $cronmin % 5 != 0) {
return;
}
- $devices = ['entree', 'sdb', 'litvincent', 'litjerome', 'bureausun', 'chambre'];
- foreach ($devices as $device) {
- if (isAlive($device) === 0) {
- sshCommand('/bin/echo "/usr/local/bin/tortugahome" | /usr/bin/at now', $device, false);
- } else if (isAlive($device) === -1) {
- sshCommand('/bin/echo "/sbin/reboot now" | /usr/bin/at now', $device, false);
- }
- }
+ restartDeadDevices();
}
function cronKodi($cronmin)
<?php
require_once "import.php";
-if(isset($_GET['avrcmd'])){
+if (isset($_GET['avrcmd'])) {
echo _denonTelnet($_GET['avrcmd']);
-}elseif (isset($_GET['avrvolume'])) {
+} elseif (isset($_GET['avrvolume'])) {
echo denonAVRGetVolume();
} else if (isset($_GET['avrinput'])) {
echo denonAVRGetInput();
denonAVROn();
} else if (isset($_GET['avrpower'])) {
echo denonAVRGetPowerState();
+} else if (isset($_GET['chambre'])) {
+ denon(!!$_GET['chambre']);
} else {
setState('denon', '0');
}
\ No newline at end of file
$_GET['im'] = '5';
$wcswitch = 6448;
-$cubesalon = ['6844', '6846', '6848'];
+$cubesalon = [6844, 6846, 6848];
+$bar = 6890;
+$device = (int)$_GET['device'];
-if (in_array($_GET['device'], $cubesalon)) {
+if (in_array($device, $cubesalon)) {
$forceConfig = 'salon';
-} elseif ($_GET['device'] == $wcswitch) {
+} elseif ($device == $wcswitch) {
$forceConfig = 'wc';
-} elseif ($_GET['device'] == 4600) {
+} elseif ($device == 4600) {
$forceConfig = 'bureau';
-} elseif ($_GET['device'] == 4711) {
+} elseif ($device == 4711) {
$forceConfig = 'sdb';
+} else if ($device == $bar) {
+ $forceConfig = 'salon';
+} else if ($device == 6894) {
+ $forceConfig = 'cour';
+} else if ($device == 6895) {
+ $forceConfig = 'cour';
}
require_once "import.php";
-if (gloria()) {
- die('0');
-}
-if ($_GET['device'] == 480) {
+if ($device === 6894) {
+ domoticzCmd(6898, 'Toggle');
+} elseif ($device == 6895) {
+ domoticzCmd(6899, 'Toggle');
+} elseif ($device == $bar) {
+ execScene('salon/bar/' . mb_strtolower($_GET['state']));
+} elseif ($device == 480) {
chambreToggle(true);
-} else if (in_array($_GET['device'], $cubesalon)) {
+} else if (in_array($device, $cubesalon)) {
// Cube
+ if (gloria()) {
+ die('0');
+ }
switch ($_GET['state']) {
case 'Shake':
- execScene('home/alert',true);
+ execScene('home/alert', true);
break;
case 'Flip_90':
- execScene('salon/cinema',true);
+ execScene('salon/cinema', true);
break;
case 'Flip_180':
- execScene('salon/auto',true);
+ execScene('salon/auto', true);
break;
case 'Free_Fall':
off('salon');
default:
break;
}
-} else if ($_GET['device'] == 1451) {
+} else if ($device == 1451) {
domoticzSwitch(1450);
-} else if ($_GET['device'] == $wcswitch) {
+} else if ($device == $wcswitch) {
$forceConfig = 'wc';
switch ($_GET['state']) {
case 'Double_Click':
- execScene('wc/spa',true);
+ execScene('wc/spa', true);
setState('wc', 1);
break;
case 'Long_Click':
- execScene('home/alert',true);
+ execScene('home/alert', true);
break;
case 'Click':
default:
wcToggle();
break;
}
-} else if ($_GET['device'] == 4600) {
+} else if ($device == 4600) {
+ if (gloria()) {
+ die('0');
+ }
// Cube bureau
switch ($_GET['state']) {
case 'Shake':
- execScene('home/alert',true);
+ execScene('home/alert', true);
break;
case 'Flip_90':
- execScene('bureau/rideaux/toggle',true);
+ execScene('bureau/rideaux/toggle', true);
break;
case 'Flip_180':
- execScene('bureau/auto',true);
+ execScene('bureau/auto', true);
break;
case 'Free_Fall':
- execScene('bureau/off',true);
+ execScene('bureau/off', true);
off('bureau');
break;
case 'Move':
default:
break;
}
-} else if ($_GET['device'] == 4711) {
+} else if ($device == 4711) {
+ if (gloria()) {
+ die('0');
+ }
// Cube SDB
switch ($_GET['state']) {
case 'Shake':
- execScene('home/alert',true);
+ execScene('home/alert', true);
break;
case 'Flip_90':
- execScene('sdb/off',true);
+ execScene('sdb/off', true);
break;
case 'Flip_180':
- execScene('sdb/on',true);
+ execScene('sdb/on', true);
break;
case 'Free_Fall':
off('sdb');
header('Location: /');
exit;
}
-} else {
+}
+
+if (isset($_GET['heartbeat']) && $_GET['heartbeat'] == 1) {
heartbeat();
}
-ob_end_clean();
$res = getEcoMode();
-
-
-
+ob_end_clean();
die($res);
<?php
require_once "import.php";
-
+header('Content-Type: text/plain');
+if (isset($_GET['action']) && $_GET['action'] === 'restart') {
+ restartDeadDevices();
+ exit;
+}
heartbeat(isset($_GET['device']) ? $_GET['device'] : null);
-checkDevicesAlive();
\ No newline at end of file
+//checkDevicesAlive();
\ No newline at end of file
<?php
require_once "import.php";
+echo "\n\n";
+hotwaterCheckMode();
+echo "\n\n";
echo getState('hotwater');
if (isset($_GET['on'])) {
echo hotwater($_GET['on']);
<?php
-require_once __DIR__.'/environment.php';
+
+session_set_cookie_params(3600 * 24 * 365, '/', '.enhydra.fr', true);
+session_start();
+
+require_once __DIR__ . '/environment.php';
require_once ROOT . "/vendor/autoload.php";
require_once ROOT . "/scripts/lib/lib.php";
-if(defined('TIMELIMIT')){
- set_time_limit(TIMELIMIT);
+if (defined('TIMELIMIT')) {
+ set_time_limit(TIMELIMIT);
}
if (isset($_GET['delay'])) {
+ $delay = round($_GET['delay']);
ignore_user_abort(true);
- set_time_limit($_GET['delay'] + 30);
- sleep($_GET['delay']);
+ set_time_limit($delay + 30);
+ sleep($delay);
}
if (!defined('DISPLAYINTERFACE')) {
- define('DISPLAYINTERFACE', false);
+ define('DISPLAYINTERFACE', false);
}
$include = ROOT . "/config/" . getCurrentConfig() . '.php';
if (file_exists($include)) {
- require_once $include;
+ require_once $include;
}
if (isset($_GET['im'])) {
- returnHttpResponse();
+ returnHttpResponse();
}
profile('END import', __FILE__, __LINE__);
\ No newline at end of file
if ($state === $on) {
return;
}
- sshCommand('/usr/local/bin/denon-toggle', 'lit', true, true);
+ print_r(sshCommand('/usr/local/bin/denon-toggle', 'lit', true, true));
setState('denon', $on ? '1' : '0');
}
function denonAVROn($input = 'Media Player', $force = false)
{
- $setvolume = !denonAVRGetPowerState();
if ($force || !denonAVRGetPowerState()) {
_denonTelnet('ZMON');
}
- denonAVRInput($input, $setvolume);
+ denonAVRInput($input, true);
}
function denonAVRInput($input, $setvolume = false)
{
- $map = ['Media Player' => 'MPLAY', 'CBL/SAT' => 'SAT/CBL', 'Blu-Ray' => 'BD', 'AUX' => 'AUX1', 'HEOS Music' => 'NET', 'TV Audio' => 'TV'];
+ $map = ['Media Player' => 'MPLAY', 'CBL/SAT' => 'SAT/CBL', 'Blu-Ray' => 'BD', 'AUX' => 'AUX1', 'HEOS Music' => 'NET', 'TV Audio' => 'TV', 'Game' => 'GAME'];
if (isset($map[$input])) {
$cmd = $map[$input];
} else {
sleep(1);
}
- if ($changedInput || $setvolume) {
- $volumes = ['Media Player' => 60, 'HEOS Music' => 40, 'CD' => 30, 'AUX' => 26];
+ if ($setvolume) {
+ $volumes = ['Media Player' => 60, 'Game' => 50, 'HEOS Music' => 40, 'CD' => 30, 'AUX' => 26];
if (isset($volumes[$input])) {
- denonAVRVolume($volumes[$input], '');
- sleep(1);
+ for ($i = 0; $i <= 2; $i++) {
+ denonAVRVolume($volumes[$input], '');
+ usleep(1000000 * 0.5);
+ }
}
}
- $audioMode = ['Media Player' => 'DOLBY DIGITAL', 'AUX' => 'DOLBY DIGITAL', 'CD' => 'DOLBY DIGITAL', 'HEOS Music' => 'MULTI CH IN 7.1'];
+ $audioMode = ['Media Player' => 'DOLBY DIGITAL', 'AUX' => 'DOLBY DIGITAL', 'CD' => 'DOLBY DIGITAL', 'Game' => 'DOLBY DIGITAL', 'HEOS Music' => 'MULTI CH IN 7.1'];
if (isset($audioMode[$input])) {
- denonAVRSetAudioMode($audioMode[$input]);
- usleep(1000000 * 1);
+ for ($i = 0; $i <= 2; $i++) {
+ denonAVRSetAudioMode($audioMode[$input]);
+ usleep(1000000 * 0.5);
+ }
}
return _denonTelnet('ZM?') === 'ZMON';
}
-function _denonTelnet($cmd)
+function _denonTelnet($cmd, $repair = true)
{
$client = getDenonTelnetClient();
profile('got denon telnet client for ' . $cmd);
- for ($i = 0; $i <= 5; $i++) {
+ for ($i = 0; $i <= 2; $i++) {
try {
$res = $client->execute($cmd);
if ($res->isError()) {
sleep(5);
}
}
+ if (null === $res) {
+ if ($repair) {
+ if ($cmd === 'ZMON') {
+ _denonTelnet('ZMOFF');
+ return _denonTelnet($cmd, false);
+ }
+ }
+ return '';
+ }
profile('Denon telnet ' . $cmd);
return trim($res->getResponseText());
}
}
$cmd = $on ? 'PowerOn' : 'PowerOff';
echo 'Epson ' . $cmd . "\n";
- sshCommand('/usr/local/bin/ir Epson ' . $cmd, 'salon', false, true);
+ print_r(irsend('salon', 'Epson', $cmd));
+ //sshCommand('/usr/local/bin/ir Epson ' . $cmd, 'salon', false, true);
setState('EpsonPowerState', $on ? '1' : '0');
if ($currentState !== $on && $on) {
sleep(30);
if (!is_array($queue)) {
$queue = [];
}
- if ($priority) {
- array_unshift($queue, $command);
- } else {
- array_push($queue, $command);
+ if (null !== $command) {
+ if ($priority) {
+ array_unshift($queue, $command);
+ } else {
+ array_push($queue, $command);
+ }
}
$redis->igbset($queue_name, $queue);
$redis->publish('domoticz_event', 'handle_queue');
//echo ':)';
$res = runDomoticzCommand(['type' => 'devices', 'rid' => $device]);
$res = json_decode($res->getBody(), true);
- if(null===$res || !isset($res['result']) || !count($res['result'])){
- echo 'Error getting status of device '.$device."\n".print_r($res,true);
+ if (null === $res || !isset($res['result']) || !count($res['result'])) {
+ echo 'Error getting status of device ' . $device . "\n" . print_r($res, true);
return null;
}
setState('night', (!!$mode) ? '1' : '0');
}
-function getNightMode()
+function getNightMode($device = null)
{
- $device = config('DEVICE');
+ $device = $device === null ?: config('DEVICE');
if ($device === 'sdb') {
$h = date('H');
if ($h >= 6 && $h <= 8) {
<?php
function updateFlowerPower()
{
- $devices = getState('device_salon_awake') ? ['bureausun', 'salon'] : ['bureausun'];
+ $devices = ['bureausun'];
shuffle($devices);
$device = array_pop($devices);
- $res = sshRunCommand('timeout -k 10 1m /usr/local/bin/flowerpower', $device, true, true);
+ $res = sshRunCommand('/docker/flowerpower/run', $device, true, true);
$fp = explode("\n", $res['output']);
$map = [1 => 1467, 0 => 1468];
foreach ($map as $k => $v) {
function freeboxWatchMagnets()
{
- $dir = '/nas/Téléchargements/Watch';
- $dr = opendir($dir);
- while ($f = readdir($dr)) {
- if ($f == '.' || $f == '..' || !stristr($f, '.magnet')) {
- continue;
- }
- try {
- $file = $dir . '/' . $f;
- freeboxAddMagnet(file_get_contents($file));
- unlink($file);
- } catch (Exception $e) {
- if (stristr($e->getMessage(), '(exists)')) {
- unlink($file);
- }
- echo $e->getMessage();
- }
- }
+// $dir = '/nas/Téléchargements/Watch';
+// $dr = opendir($dir);
+// while ($f = readdir($dr)) {
+// if ($f == '.' || $f == '..' || !stristr($f, '.magnet')) {
+// continue;
+// }
+// try {
+// $file = $dir . '/' . $f;
+// freeboxAddMagnet(file_get_contents($file));
+// unlink($file);
+// } catch (Exception $e) {
+// if (stristr($e->getMessage(), '(exists)')) {
+// unlink($file);
+// }
+// echo $e->getMessage();
+// }
+// }
}
\ No newline at end of file
function isAlive($device)
{
- if ($device === 'squeezebox') {
- $device = 'cuisine';
- }
-
$lastbeat = getState('heartbeat_' . $device, 0);
- $diff = $lastbeat - time();
- if ($diff < -1800) {
+ $diff = time() - $lastbeat;
+ if ($diff === 0) {
+ // Don't return 0, it means down
+ return 1;
+ }
+ if ($diff > 1800) {
return -1;
- } else if ($diff < -300) {
+ } else if ($diff > 300) {
return 0;
}
- return 1;
+ return $diff;
}
function checkDevicesAlive()
{
- $devices = ['litvincent', 'litjerome', 'bureausun', 'entree', 'sdb', 'cuisine'];
+ $devices = ['litvincent', 'litjerome', 'bureausun', 'entree', 'sdb', 'cuisine', 'chambre'];
header('Content-Type: text/plain');
foreach ($devices as $device) {
echo $device . ':' . isAlive($device) . '(' . getState('heartbeat_' . $device) . ')' . "\n";
}
+}
+
+function restartDeadDevices()
+{
+ $devices = [
+ 'litvincent' => ['room' => 'chambre', 'type' => 'rpi', 'eco' => false],
+ 'litjerome' => ['room' => 'chambre', 'type' => 'rpi', 'eco' => false],
+ 'chambre' => ['room' => 'chambre', 'type' => 'rpi', 'eco' => false],
+ 'bureausun' => ['room' => 'bureau', 'type' => 'rpi', 'eco' => false],
+ 'entree' => ['room' => 'entree', 'type' => 'rpi', 'eco' => true],
+ 'cuisine' => ['room' => 'cuisine', 'type' => 'android', 'eco' => true],
+ 'salon' => ['room' => 'salon', 'type' => 'android', 'eco' => true],
+ 'sdb' => ['room' => 'sdb', 'type' => 'android', 'eco' => true],
+ ];
+
+ foreach ($devices as $device => $infos) {
+ $alive = isAlive($device);
+ echo '---' . "\n";
+ echo $device . ':' . $alive . '(' . getState('heartbeat_' . $device) . ')' . "\n";
+ if ($alive > 0) {
+ echo 'Device ' . $device . ' is ok' . "\n";
+ continue;
+ }
+ if (!$infos['eco'] && getState('ecomode', '0') > 0) {
+ echo 'Ignore device ' . $device . " because of eco mode\n";
+ continue;
+ }
+ if ($infos['type'] === 'android') {
+ phoneTask('Tortuga', $device);
+ echo 'Restart android app on ' . $device . "\n";
+ } else {
+ if ($alive === 0 || getNightMode($device)) {
+ sshCommand('/usr/local/bin/tortugahome', $device, false, true);
+ echo 'Restart kiosk chrome on ' . $device . "\n";
+ } else if ($alive === -1) {
+ sshCommand('/sbin/reboot now', $device, false, true);
+ echo 'Reboot rpi ' . $device . "\n";
+ }
+ }
+ }
}
\ No newline at end of file
* @param array $headers
* @return mixed|\Psr\Http\Message\ResponseInterface
*/
-function httpRequest($url, $method = 'get', $data = [], $auth = null, $timeout = 10, $allowRedirections = true, $headers = [])
+function httpRequest($url, $method = 'get', $data = [], $auth = null, $timeout = 10, $allowRedirections = true, $headers = [], $sync = true)
{
$method = mb_strtoupper($method);
$client = getHttpClient();
$options['query'] = $data;
}
if ($method === 'PUT') {
- $options['json']=$data;
+ $options['json'] = $data;
} else {
if (is_string($data)) {
}
}
$options['headers'] = $headers;
- $res= $client->request($method, $url, $options);
+ if ($sync) {
+ $res = $client->request($method, $url, $options);
+ } else {
+ $res = $client->requestAsync($method, $url, $options);
+ }
return $res;
}
\ No newline at end of file
{
global $hue;
if (!isset($hue)) {
- $hue = new \Phue\Client(HUE_BRIDGE, HUE_USER);
+ try {
+ $hue = new \Phue\Client(HUE_BRIDGE, HUE_USER);
+ }catch (Exception $e){
+ return null;
+ }
}
return $hue;
}
function getHueState()
{
$hue = getHueInstance();
+ if(null===$hue){
+ return;
+ }
return array('groups' => $hue->getGroups(), 'scenes' => $hue->getScenes(), 'lights' => $hue->getLights());
}
if (!is_array($queue)) {
$queue = [];
}
- $command = $action;
- $command['transitionTime'] = $transitionTime;
- $queue[] = $command;
+ if (null !== $action) {
+ $command = $action;
+ $command['transitionTime'] = $transitionTime;
+ $queue[] = $command;
+ }
$redis->igbset('hue_queue', $queue);
$redis->publish('hue_event', 'handle_queue');
}
{
$hue = getHueInstance();
+ if($hue===null){
+ return;
+ }
$groups = $hue->getGroups();
$group = $groups[$groupId];
echo "Group : ";
function hueApplySceneLight($lightId, $sceneId, $transitionTime = null)
{
$hue = getHueInstance();
+ if(null===$hue){
+ return;
+ }
$lights = $hue->getLights();
$light = $lights[$lightId];
function irsend($room, $device, $command)
{
- sshCommand('/usr/local/bin/ir ' . $device . ' ' . $command, $room);
+ return sshCommand('/docker/lirc/ir ' . $device . ' ' . $command, $room, true, true);
}
\ No newline at end of file
function getKodiDBConnection()
{
- return mysqli_connect('kodidb.home.tortuga.enhydra.fr', "kodi", "4xNkxCDAyWrp5VVthtgS", "MyVideos119");
+ return mysqli_connect('kodidb.home.tortuga.enhydra.fr', "root", "4xNkxCDAyWrp5VVthtgS", "MyVideos119",3307);
}
function kodiGetAllKodiToTmdb($force = false)
$expires = time() + 60 * 60 * 24 * 30;
if (isset($_GET['c'])) {
- if (!headers_sent()) {
- setcookie('homeconfig', $_GET['c'], $expires, '/', 'enhydra.fr');
- }
- $_COOKIE['homeconfig'] = $_GET['c'];
+ $_SESSION['homeconfig'] = $_GET['c'];
}
- if (!isset($_COOKIE['homeconfig'])) {
- if (isset($_SERVER['REMOTE_ADDR']) && isset($ips[$_SERVER['REMOTE_ADDR']])) {
- $c = $ips[$_SERVER['REMOTE_ADDR']];
+
+ if (!isset($_SESSION['homeconfig'])) {
+ if (isset($_SERVER['HTTP_X_REAL_IP']) && isset($ips[$_SERVER['HTTP_X_REAL_IP']])) {
+ $c = $ips[$_SERVER['HTTP_X_REAL_IP']];
} else {
$c = 'salon';
}
- if (!headers_sent()) {
- setcookie('homeconfig', $c, $expires, '/', 'enhydra.fr');
- }
- $_COOKIE['homeconfig'] = $c;
+ $_SESSION['homeconfig'] = $c;
}
- return $_COOKIE['homeconfig'];
+ return $_SESSION['homeconfig'];
}
function config($key = null, $value = null)
} elseif ($s['type'] == 'media') {
$attrs['href'] = isset($s['path']) ? $s['path'] : $s['url'];
$attrs['class'] = 'media';
- } elseif ($s['type'] == 'freebox' || $s['type'] === 'shield' || $s['type'] === 'netflix') {
+ } elseif ($s['type'] == 'freebox' || $s['type'] === 'shield' || $s['type'] === 'netflix' || $s['type']==='amazonprime' || $s['type']==='nintendoswitch') {
$attrs['href'] = $s['url'];
- $attrs['class'] = 'ajax play';
+ $attrs['class'] = 'ajax play '.$s['type'];
$attrs['data-remote'] = "1";
} else if ($s['type'] == 'map') {
$rand = rand(1, 1000000);
}
}
+function triggerErrorNotif($title, $message = '')
+{
+ phoneTask('TortugaMessage|||' . $title . '|||' . $message, 'vincent', true);
+}
+
function phoneTask($task, $phone, $encode = true)
{
global $phones;
$url = "http://$p[ip]:1817/?message=$task&password=" . $password;
$res = getUrlContent($url);
- echo $url . ' : ' . $res . "\n--\n";
+ //echo $url . ' : ' . $res . "\n--\n";
if (!$res) {
$url = "https://autoremotejoaomgcd.appspot.com/sendmessage?key=$p[key]&message=$task&target=TORTUGA&password=$password";
$res = getUrlContent($url);
- echo $url . ' : ' . $res . "\n--\n";
+ //echo $url . ' : ' . $res . "\n--\n";
}
return $res;
}
function gloria()
{
$j = intval(date('N'));
- if ($j !== 4) {
+ if ($j !== 1) {
return false;
}
$h = intval(date('H'));
- return $h >= 11 && $h <= 16;
+ return $h >= 12 && $h <= 17;
}
return true;
}
- if ((($p === 'netflix' || $p === 'tv') && config('TVPLAYER') === 'shield') || config('VIDEOPLAYER') === 'shield') {
+ if ((($p === 'netflix' || $p === 'tv' || $p==='amazonprime') && config('TVPLAYER') === 'shield') || config('VIDEOPLAYER') === 'shield') {
return shieldRemoteCommand($cmd, $device);
} else if ($device == 'bureau') {
switch (getCurrentHarmonyActivity()) {
function offSdb()
{
execScene('sdb/ampli/off');
- offOMX('sdb');
+ sleep(10);
hotwaterAutoMode('1');
}
{
denon(false);
}
-
-function offAllOMX()
-{
- $devices = ['litvincent', 'litjerome', 'entree', 'sdb', 'bureausun'];
- foreach ($devices as $device) {
- offOMX($device);
- }
-}
-
-function offOMX($device)
-{
- sshCommand("kill $(ps aux | grep '[o]mxplayer' | awk '{print $2}')", $device);
-}
\ No newline at end of file
$n = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '-';
$n = str_replace('.php', '', $n);
$n = str_replace('/home/tortugahome/www/', '', $n);
+$n = str_replace('/application/', '', $n);
$n = str_replace('/', '-', $n);
$n = trim($n, '/ ');
*/
function getRedisClient()
{
- $redis = new Client('tcp://127.0.0.1:6379?read_write_timeout=0');
+ $redis = new Client('tcp://tortugahome-redis:6379?read_write_timeout=0');
$profile = $redis->getProfile();
// If you want, you can override SET or GET just like any other command, but I
}
} else {
- if (($p === 'netflix' || $p === 'tv') && config('TVPLAYER') === 'shield') {
+ if (($p === 'netflix' || $p === 'tv' || $p==='amazonprime') && config('TVPLAYER') === 'shield') {
$res = ['type' => 'shield', 'can_seek' => false];
} else {
if ($p == 'mediarasp' || $p === 'shieldmedia') {
['type' => 'function', 'function' => 'stopAllSqueezebox'],
['type' => 'nightmode', 'mode' => '1'],
['type' => 'ecomode', 'mode' => '1'],
- ['type' => 'function', 'key' => 'hotwaterAutoMode', 'args' => ['1']],
+ ['type' => 'scene', 'scene' => 'sdb/hotwater/auto'],
],
'home/music/synchro/soiree' => [
['type' => 'function', 'function' => 'syncMusic', 'args' => [['Salon', 'Cuisine', 'Bureau', 'WC']]],
'salon/projector/off' => [
['type' => 'function', 'function' => 'epson', 'args' => [false, true]],
],
-
'salon/auto' => [
['type' => 'function', 'function' => 'salonAuto', 'args' => [true]],
],
-
+ 'salon/bar/on' => [
+ ['type' => 'domoticz', 'device' => 6887, 'command' => true, 'priority' => true],
+ ],
+ 'salon/bar/off' => [
+ ['type' => 'domoticz', 'device' => 6887, 'command' => false, 'priority' => true],
+ ],
+ 'salon/bar/toggle' => [
+ ['type' => 'domoticz', 'device' => 6887, 'command' => 'Toggle', 'priority' => true],
+ ],
'salon/day' => [
['type' => 'domoticz', 'scene' => 45, 'command' => true, 'priority' => true],
- ['type' => 'hue', 'group' => $salon, 'scene' => 'Gte8sl76rzAD1wO', 'repeat' => 2],
+ ['type' => 'hue', 'group' => $salon, 'scene' => '9ay5VtNcjvUZIFF', 'repeat' => 2],
['type' => 'state', 'key' => 'salon', 'value' => 'on'],
['type' => 'scene', 'scene' => 'cuisine/on', 'delay' => 1],
['type' => 'scene', 'scene' => 'salon/cheminee', 'delay' => 1],
],
'salon/lumineux' => [
['type' => 'domoticz', 'scene' => 51, 'command' => true, 'priority' => true],
- ['type' => 'hue', 'group' => $salon, 'scene' => 'Gte8sl76rzAD1wO', 'repeat' => 2],
+ ['type' => 'hue', 'group' => $salon, 'scene' => '9ay5VtNcjvUZIFF', 'repeat' => 2],
['type' => 'state', 'key' => 'salon', 'value' => 'on'],
['type' => 'scene', 'scene' => 'cuisine/on', 'delay' => 1],
['type' => 'scene', 'scene' => 'salon/cheminee', 'delay' => 1],
['type' => 'function', 'function' => 'chemineeOff', 'args' => ['salon']],
['type' => 'hue', 'group' => $salon, 'scene' => array('on' => false)],
['type' => 'scene', 'scene' => 'salon/fan/off'],
+ ['type' => 'scene', 'scene' => 'salon/bar/off'],
],
'salon/cinemabase' => [
// ['type' => 'insteon', 'command' => '0?1111=I=0=0'],
],
'salon/cineclub' => [
+ ['type' => 'scene', 'scene' => 'salon/bar/off'],
['type' => 'function', 'function' => 'salonAuto', 'args' => [false]],
['type' => 'domoticz', 'scene' => 46, 'command' => true, 'priority' => true],
['type' => 'hue', 'group' => $salon, 'scene' => 'xpCjXtV3u7O1kYu', 'repeat' => 2],
['type' => 'scene', 'scene' => 'cuisine/tamise', 'repeat' => 2],
],
'salon/cinema' => [
+ ['type' => 'scene', 'scene' => 'salon/bar/off'],
['type' => 'function', 'function' => 'salonAuto', 'args' => [false]],
['type' => 'domoticz', 'scene' => 47, 'command' => true, 'priority' => true],
['type' => 'hue', 'group' => $salon, 'scene' => 'AsU9eOyGsjEyz35', 'repeat' => 2],
['type' => 'scene', 'scene' => 'cuisine/tamise', 'repeat' => 2],
],
'salon/tamise' => [
-
['type' => 'ecomode', 'mode' => '0'],
['type' => 'domoticz', 'scene' => 48, 'command' => true, 'priority' => true],
['type' => 'hue', 'group' => $salon, 'scene' => 'RbjnIcLtcDuHbfU', 'repeat' => 2],
// ['type' => 'insteon', 'command' => '0?1113=I=0=0'],
['type' => 'function', 'function' => 'chemineeOn', 'args' => ['salon', 'fire', 0.25]],
['type' => 'scene', 'scene' => 'cuisine/on', 'repeat' => 2],
+ ['type' => 'scene', 'scene' => 'salon/bar/off'],
],
'salon/cheminee' => [
['type' => 'function', 'function' => 'chemineeOn', 'args' => ['salon', 'fire', 1]],
['type' => 'domoticz', 'device' => '1', 'command' => false, 'priority' => true],
],
'bureau/rideaux/close' => [
- ['type' => 'domoticz', 'device' => '391', 'command' => false, 'priority' => true],
+ ['type' => 'domoticz', 'device' => '391', 'command' => true, 'priority' => true],
],
'bureau/rideaux/open' => [
- ['type' => 'domoticz', 'device' => '391', 'command' => true, 'priority' => true],
+ ['type' => 'domoticz', 'device' => '391', 'command' => false, 'priority' => true],
],
'bureau/rideaux/toggle' => [
['type' => 'domoticz', 'device' => '391', 'command' => 'Toggle', 'priority' => true],
['type' => 'scene', 'scene' => 'wc/off'],
['type' => 'function', 'function' => 'stopHarmony'],
['type' => 'function', 'function' => 'stopAllSqueezebox'],
- ['type' => 'function', 'function' => 'offAllOMX'],
['type' => 'scene', 'scene' => 'chambre/deshumidificateur/on'],
['type' => 'scene', 'scene' => 'chambre/planetarium/off'],
['type' => 'scene', 'scene' => 'cuisine/coffee/off'],
['type' => 'scene', 'scene' => 'home/hueoff'],
['type' => 'scene', 'scene' => 'salon/media/off'],
['type' => 'scene', 'scene' => 'salon/off', 'delay' => 2],
- ['type' => 'function', 'key' => 'hotwaterAutoMode', 'args' => ['1']],
+ ['type' => 'scene', 'scene' => 'sdb/hotwater/auto'],
],
'home/welcome/eco' => [
['type' => 'scene', 'scene' => 'cuisine/on'],
['type' => 'scene', 'scene' => 'salon/auto'],
['type' => 'ecomode', 'mode' => '0'],
+ ['type' => 'scene', 'scene' => 'sdb/hotwater/auto'],
],
'home/welcome' => [
'sdb/ampli/off' => [
['type' => 'domoticz', 'device' => '476', 'command' => false, 'priority' => true],
],
+ 'sdb/hotwater/auto' => [
+ ['type' => 'function', 'function' => 'hotwaterAutoMode', 'args' => ['1']],
+ ],
'sdb/hotwater/eco' => [
- ['type' => 'function', 'key' => 'hotwaterAutoMode', 'args' => ['0']],
+ ['type' => 'function', 'function' => 'hotwaterAutoMode', 'args' => ['0']],
['type' => 'function', 'function' => 'hotwater', 'args' => ['1']],
],
'sdb/hotwater/max' => [
- ['type' => 'function', 'key' => 'hotwaterAutoMode', 'args' => ['0']],
+ ['type' => 'function', 'function' => 'hotwaterAutoMode', 'args' => ['0']],
['type' => 'function', 'function' => 'hotwater', 'args' => ['2']],
],
'sdb/hotwater/off' => [
- ['type' => 'function', 'key' => 'hotwaterAutoMode', 'args' => ['0']],
+ ['type' => 'function', 'function' => 'hotwaterAutoMode', 'args' => ['0']],
['type' => 'function', 'function' => 'hotwater', 'args' => ['0']],
],
'sdb/off' => [
['type' => 'function', 'function' => 'coffee_off'],
],
'cour/auto' => [
- ['type' => 'domoticz', 'device' => '678', 'command' => true],
+ ['type' => 'domoticz', 'device' => '6899', 'command' => true],
['type' => 'function', 'function' => 'courAuto', 'args' => [true]],
],
'cour/daylight' => [
- ['type' => 'domoticz', 'device' => '678', 'command' => true],
+ ['type' => 'domoticz', 'device' => '6899', 'command' => true],
['type' => 'hue', 'group' => $cour, 'scene' => '8RyJJ3Dn7ayPQ8t'],
],
'cour/lumineux' => [
- ['type' => 'domoticz', 'device' => '678', 'command' => true],
+ ['type' => 'domoticz', 'device' => '6899', 'command' => true],
['type' => 'hue', 'group' => $cour, 'scene' => 'XzV1CuYIdHXPKoJ'],
],
'cour/tropical' => [
- ['type' => 'domoticz', 'device' => '678', 'command' => true],
+ ['type' => 'domoticz', 'device' => '6899', 'command' => true],
['type' => 'hue', 'group' => $cour, 'scene' => 'wBdbymg1w5ZZvtS'],
],
'cour/grow' => [
- ['type' => 'domoticz', 'device' => '678', 'command' => true],
+ ['type' => 'domoticz', 'device' => '6899', 'command' => true],
['type' => 'hue', 'group' => $cour, 'scene' => 'WVanIpWUWjkBjsS'],
],
'cour/off' => [
['type' => 'hue', 'group' => $cour, 'scene' => ['on' => false]],
['type' => 'function', 'function' => 'courAuto', 'args' => [false]],
- ['type' => 'domoticz', 'device' => '678', 'command' => false],
+ ['type' => 'domoticz', 'device' => '6899', 'command' => false],
],
'cour/projecteurs/on' => [
- ['type' => 'domoticz', 'device' => '679', 'command' => true],
+ ['type' => 'domoticz', 'device' => '6898', 'command' => true],
],
'cour/projecteurs/off' => [
- ['type' => 'domoticz', 'device' => '679', 'command' => false],
+ ['type' => 'domoticz', 'device' => '6898', 'command' => false],
],
'ecomode/basic' => [
- ['type' => 'scene', 'scene' => 'sdb/ampli/off'],
['type' => 'domoticz', 'device' => '1', 'switchtype' => 'scene', 'command' => false],
],
'ecomode/super' => [
}
}
- $killurl = WEB_ROOT . 'scripts/light.php?[r]=2';
- $kill = "/bin/kill $(ps aux | grep '$killurl' | awk '{print $2}')";
- $res = `$kill`;
+// $killurl = WEB_ROOT . 'scripts/light.php?r=2';
+// $kill = "/usr/bin/pkill -f $killurl";
+// $res = `$kill`;
foreach ($scene as $action) {
if (isset($action['when'])) {
execScene($action['scene'], $fromUserAction, $transitionTime);
}
} else if ($action['type'] == 'function') {
- $f = $action['function'];
if (!isset($action['args'])) {
$action['args'] = array();
}
function killCheminee($room)
{
// Kill current animation
- $kill = 'id -u -n;/bin/kill $(ps aux | grep \'[c]heminee_running/' . $room . '\' | awk \'{print $2}\') 2>&1';
+ $kill = '/usr/bin/pkill -f cheminee_running/' . $room;
$res = `$kill`;
echo 'Kill cheminée ' . $room . ' :: ' . $res;
return $res;
function salonAuto($on = true)
{
if ($on) {
+ setState('salonOff', '0');
setState('salonAutoMode', '1');
updateSalonAuto();
} else if (getState('salonAutoMode') === '1') {
function updateCuisine()
{
$salon = getState('salon', 'off');
- if ($salon === 'on' || $salon === 'off' || $salon === 'tamise') {
+ if ($salon === 'day' || $salon === 'on' || $salon === 'off' || $salon === 'tamise') {
execScene('cuisine/base/on');
} else if ($salon == 'cinema') {
execScene('cuisine/tamise');
function updateCourAuto()
{
+ $h = date('H');
+ if ($h >= 7) {
+ execScene('cour/projecteurs/off');
+ } else {
+ execScene('cour/projecteurs/on');
+ }
if (getState('courOff') == '1') {
execScene('cour/off');
return;
execScene('wc/vmc/off');
}
-function delayHttpCall($url, $delay)
+function delayHttpCall($url, $params, $delay)
{
- $lynx = "lynx -connect_timeout=$delay -dump \"$url\"";
- $cmd = "echo '$lynx' | at now 2>&1";
- return `$cmd`;
+ try {
+ $params['delay'] = $delay;
+ $res = httpRequest($url, 'get', $params, null, 1);
+ echo $url;
+ echo $res->getBody()->getContents();
+ } catch (Exception $e) {
+ print_r($e);
+ }
}
function delayScene($scene, $delay)
{
- $timeout = $delay + 30;
- $url = WEB_ROOT . 'scripts/light.php?delay=' . $delay . '&scene=' . $scene . '&sid=' . session_id();
- return delayHttpCall($url, $timeout);
+ $host = $_SERVER['HTTP_HOST'] ?? 'entree.home.tortuga.enhydra.fr';
+ $url = 'https://' . $host . '/scripts/light.php';
+ delayHttpCall($url, ['scene' => $scene], $delay);
}
function alert()
function shieldNetflix($id = null, $device = null)
{
- shieldRunActivity($device, true);
+ shieldRunActivity($device);
shieldHome($device);
sleep(1);
}
}
+function shieldAmazonPrime($id = null, $device = null)
+{
+ shieldRunActivity($device);
+ shieldHome($device);
+ sleep(1);
+ setPlaying('amazonprime', $device);
+ shieldLaunchApp('com.amazon.amazonvideo.livingroom/com.amazon.ignition.IgnitionActivity', $device);
+}
+
function shieldRemoteCommand($cmd, $device = null)
{
shieldKey([$cmd], $device);
{
$d = getDevice($device);
$state = 'mycanallastconnect_' . $d['id'];
- $limit = time() - 3600 * 24 * 8;
+ $limit = time() - 3600 * 24 * 16;
if (!$force && getState($state, 0) > $limit) {
return;
}
sleep(4);
shieldKey(['down', 'down', 'ok', 'down', 'ok'], $device);
sleep(3);
- shieldText('fbx18439571', $device);
+ shieldText('fbx16909099', $device);
shieldKey(['back', 'down'], $device);
- shieldText('paogaiho', $device);
+ shieldText('f06cyqae3aj1asyo', $device);
shieldKey(['back', 'ok']);
sleep(11);
shieldKey(['down', 'ok', 'up', 'ok']);
'steamlink' => 'com.valvesoftware.steamlink',
'squeezeplayer' => 'de.bluegaspode.squeezeplayer',
'tortuga' => 'fr.enhydra.tortuga.home',
+ 'amazonprime' => 'com.amazon.amazonvideo.livingroom',
];
}
function shieldPlayingVideo($device = null)
{
- $videoApps = ['kodi', 'vlc', 'mycanal', 'netflix', 'arte', 'francetv', 'gamecast', 'twitch', 'youtube', 'dailymotion', 'vimeo', 'steamlink'];
+ $videoApps = ['kodi', 'vlc', 'mycanal', 'amazonprime', 'netflix', 'arte', 'francetv', 'gamecast', 'twitch', 'youtube', 'dailymotion', 'vimeo', 'steamlink'];
return in_array(shieldGetCurrentApp($device), $videoApps);
}
function shieldLogcat($cases = [], $device = null)
{
$cmd = _adbcmd('logcat', '', $device);
-
- `pkill -f "$cmd"`;
- shieldConnect(true, $device);
+ shieldConnect(false, $device);
$proc = new proc();
echo $cmd . "\n";
return;
}
-
squeezeRequest('sync -', $player);
squeezeRequest('stop', $player);
squeezeRequest('power 0', $player);
if (!is_array($queue)) {
$queue = [];
}
- array_push($queue, [$params, $player]);
+ if (null !== $params) {
+ array_push($queue, [$params, $player]);
+ }
$redis->igbset($queue_name, $queue);
$redis->publish('squeezebox_event', 'handle_queue');
function squeezePlayByName($musicName, $player, $volume = null, $playIfSync = true)
{
-
+ global $squeezeboxPlayers;
if (!$playIfSync && isSynced($player)) {
echo 'sync enabled';
return;
global $allmusics;
$m = $allmusics[$musicName];
+ $player = _player($player);
$player = _squeezePlay($player, $volume);
squeezeRequest('pause', $player);
squeezeRequest($command, $player);
}
- if ($player === 'Salle de bains') {
+ if ($player === 'Salle de bains' || $player == $squeezeboxPlayers['Salle de bains']) {
+ hotwaterCheckMode();
+ sleep(3);
hotwaterCheckMode();
}
}
global $squeezeboxPlayers;
$player = _player($player);
if ($player == $squeezeboxPlayers['Salon']) {
-// $state=denonAVRGetPowerState();
-// denonAVROn('HEOS Music', false);
-// sleep(4);
-// if(!$state){
-// denonAVROff();
-// denonAVROn('HEOS Music', true);
-// }
+ $state = denonAVRGetPowerState();
+ denonAVROn('HEOS Music', false);
+ sleep(4);
+ if (!$state) {
+ denonAVROff();
+ denonAVROn('HEOS Music', true);
+ }
} else if ($player == $squeezeboxPlayers['Salle de bains']) {
execScene('sdb/ampli/on');
-
+ hotwaterCheckMode();
if (getSqueezePlayerStatus($player) < 0) {
phoneTask('Tortuga', 'sdb');
}
-
} else if ($player == $squeezeboxPlayers['Bureau']) {
harmonyActivity('musique');
} else if ($player == $squeezeboxPlayers['Chambre']) {
}
$user = $sudo ? 'root' : $d['user'];
//if (getState('device_' . $device . '_awake') == '1') {
- print_r($d);
$ssh[$instance_key] = ssh2_connect($d['host'], 22);
if ($ssh[$instance_key]) {
if (!ssh2_auth_password($ssh[$instance_key], $user, $d['password'])) {
<?php
-function switchbot($device, $command = 'press', $rpi = 'bureausun')
+function switchbot($device, $command = 'press', $rpi = 'sdb')
{
- return;
- for ($i = 0; $i <= 2; $i++) {
- $res = sshCommand('/usr/bin/python3 /usr/local/python-host/switchbot_py3.py -d ' . $device . ' -c ' . $command, $rpi, true, true);
+ for ($i = 0; $i <= 5; $i++) {
+ $res = sshCommand('/docker/switchbot/run ' . $device . ' ' . $command, $rpi, true, true);
if (stristr($res['output'], 'Command execution successful')) {
break;
}
- sleep(1);
+ sleep(5);
}
-
return $res;
}
function hotwaterAutoMode($mode)
{
- return;
$mode = $mode ? '1' : '0';
setState('hotwater_auto_mode', $mode);
if ($mode) {
function hotwaterCheckMode()
{
- return;
if (getState('hotwater_auto_mode', '1') == '0') {
return;
}
if (getSqueezePlayerStatus('Salle de bains')) {
$hot = '2';
} else {
- $ecomode = getState('ecomode', '0');
- if ($ecomode == '0') {
- $hot = '1';
- } else if ($ecomode == '2') {
+ $h = date('G');
+ $d = date('N');
+ $isWeek = $d < 6;
+
+ $ecomode = (int)getState('ecomode', '0');
+ if ($ecomode == 0) {
+ $hot = ($isWeek && $h > 8 && $h < 21) ? '0' : '1';
+ } else if ($ecomode == 1) {
+ $hot = ($isWeek && $h >= 6 && $h <= 7) ? '1' : '0';
+ } else if ($ecomode == 2) {
$hot = '0';
- } else if ($ecomode == '1') {
- $h = date('G');
- $hot = ($h >= 6 && $h <= 9) ? '1' : '0';
}
+
+ echo "\n\n".'H:' . $h . '/D:' . $d . '/W:' . $hot."\n\n";
}
hotwater($hot);
}
function hotwater($newState)
{
- return;
+ set_time_limit(300);
// 0 : OFF
// 1 : ECO
// 2 : MAX
+ echo getState('hotwater_auto_mode', '1') . '::' . getState('hotwater_change', '0') . '::' . getState('hotwater', '1');
$changing = getState('hotwater_change', '0');
-// if ($changing == '1') {
-// return 'changing';
-// }
- setState('hotwater_change', '1');
+ $limit = time() - 300;
+ if ($changing > $limit) {
+ return 'changing';
+ }
$device = 'C1:F7:66:5E:A2:CF';
$state = getState('hotwater', '1');
- if ($newState === $state) {
+ if ($newState == $state) {
+ setState('hotwater_change', '0');
return 'no state change';
}
-
$clicks = (3 + $newState - $state) % 3;
+ setState('hotwater_change', time());
+
$res = '';
for ($i = 0; $i < $clicks; $i++) {
$res .= ' one click - ';
if ($directory['context'] != 'tvshow') {
continue;
}
- $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/volume1/Share/Videos/' . $directory['dir']));
+ $d = '/volume1/Share/Videos/' . $directory['dir'];
+ if (!file_exists($d) || !is_dir($d)) {
+ continue;
+ }
+ $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($d));
foreach ($it as $f) {
/** @var $f SplFileInfo */
if ($f->getFilename() == '.tmbd.id') {
if ($directory['context'] != 'movie') {
continue;
}
- $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/volume1/Share/Videos/' . $directory['dir']));
+ $d = '/volume1/Share/Videos/' . $directory['dir'];
+ if (!file_exists($d) || !is_dir($d)) {
+ continue;
+ }
+ $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($d));
foreach ($it as $f) {
/** @var $f SplFileInfo */
if ($f->isDir() || !stristr($f->getFilename(), '.tmdb.id')) {
function parseMoviesLibrary()
{
global $directories, $videoExt;
- $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/volume1/Share/Videos/' . $directories['Films']['dir']));
+ $d='/volume1/Share/Videos/' . $directories['Films']['dir'];
+ if(!file_exists($d) || !is_dir($d)){
+ return;
+ }
+ $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($d));
$moviesExtensions = $videoExt;
$tmdbclient = getTmbdClient();
$search = $tmdbclient->getSearchApi();
<?php
-function velibStations()
+function velibStations($force = false)
{
- $cache = __DIR__ . '/../../cache/velib.all.json';
- `curl 'https://www.velib-metropole.fr/webapi/map/details?gpsTopLatitude=51&gpsTopLongitude=4&gpsBotLatitude=48&gpsBotLongitude=1&zoomLevel=11' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0' --output $cache`;
- $alldata = json_decode(file_get_contents($cache), true);
+ $cache = ROOT . '/cache/velib.json';
- $stations = ['Cadet' => '9101', 'Bleue' => '9113', 'Folies bergères' => '9011', '9009', 'Le Pelletier' => '9014'];
- $res = array();
- foreach ($alldata as $n => $s) {
- if (!in_array($s['station']['code'], $stations)) {
- continue;
- }
- $res[$s['station']['code']] = $s;
+ $hour = date('G');
+ $day = date('w');
+ $limit = 180;
+
+ if ($day > 0 && $day < 6 && $hour > 7 && $hour < 11) {
+ $limit = 60;
}
- $ordered = [];
- foreach ($stations as $name => $s) {
- if (isset($res[$s])) {
- if (is_string($name)) {
- $res[$s]['station']['name'] = $name;
+ if ($force || !file_exists($cache) || filemtime($cache) < time() - $limit) {
+ $allcache = __DIR__ . '/../../cache/velib.all.json';
+ $ffversion = rand('96', '105');
+ $thversion = rand('1', '100');
+
+ `curl 'https://velib-metropole-opendata.smoove.pro/opendata/Velib_Metropole/station_status.json' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv$ffversion.0) Gecko/20100101 Firefox/$ffversion.0 TortugaHome/$thversion.0' --output $cache`;
+ $alldata = json_decode(file_get_contents($allcache), true);
+
+ $stations = ['Cadet' => '9101', 'Bleue' => '9113', 'Folies bergères' => '9011', 'Square Montholon' => '9009', 'Le Pelletier' => '9014'];
+ $res = array();
+ foreach ($alldata['data']['stations'] as $n => $s) {
+ if (!in_array($s['stationCode'], $stations)) {
+ continue;
}
- $ordered['s' . $s] = $res[$s];
+ $res[$s['stationCode']] = $s;
}
- }
- return $ordered;
+ $ordered = [];
+ foreach ($stations as $name => $s) {
+ if (isset($res[$s])) {
+ $data = $res[$s];
+ $o = ['name' => $name, 'enabled' => $data['is_returning'] && $data['is_renting'], 'nb' => 0, 'nbe' => 0];
+ if($o['enabled']) {
+ foreach ($data['num_bikes_available_types'] as $k => $v) {
+ foreach ($v as $type => $nb) {
+ if ($type === 'mechanical') {
+ $o['nbe'] = $nb;
+ } else {
+ $o['nb'] = $nb;
+ }
+ }
+ }
+ }
+ $ordered['s' . $s] = $o;
+ }
+ }
+ $res = ['time' => date('H:i'), 'stations' => $ordered];
+ $json = json_encode($res);
+ file_put_contents($cache, $json);
+ } else {
+ $json = file_get_contents($cache);
+ }
+ return $json;
}
\ No newline at end of file
$res['temp'] = round(($weather['Temperature']['Metric']['Value']/* + getState('airtemperature')*/));
$res['outdoor_temp'] = toNumber(getDomoticzDeviceStatus(1467), 1);
$res['outdoor_humidity'] = toNumber($weather['RelativeHumidity'], true);
- $res['outdoor_pressure'] = toNumber(getDomoticzDeviceStatus(1358), true);
- $res['backyard_temp'] = toNumber(getDomoticzDeviceStatus(1354), 1);
- $res['backyard_humidity'] = toNumber(getDomoticzDeviceStatus(1357), true);
- $res['backyard_pressure'] = toNumber(getDomoticzDeviceStatus(1358), true);
+ $res['outdoor_pressure'] = toNumber(getDomoticzDeviceStatus(6886), true);
+ $res['backyard_temp'] = toNumber(getDomoticzDeviceStatus(6884), 1);
+ $res['backyard_humidity'] = toNumber(getDomoticzDeviceStatus(6885), true);
+ $res['backyard_pressure'] = toNumber(getDomoticzDeviceStatus(6886), true);
$res['bathroom_temp'] = toNumber(getDomoticzDeviceStatus(1346), 1);
$res['bathroom_humidity'] = toNumber(getDomoticzDeviceStatus(1347), true);
$res['bedroom_temp'] = toNumber(getDomoticzDeviceStatus(6851), 1);
$res['livingroom_humidity'] = toNumber(getDomoticzDeviceStatus(6454), true);
$res['kitchen_temp'] = toNumber(getDomoticzDeviceStatus(1506), 1);
$res['kitchen_humidity'] = toNumber(getDomoticzDeviceStatus(1507), true);
- $res['wc_temp'] = toNumber(getDomoticzDeviceStatus(1501), 1);
- $res['wc_humidity'] = toNumber(getDomoticzDeviceStatus(1502), true);
- $res['office_temp'] = toNumber(getDomoticzDeviceStatus(1496), 1);
- $res['office_humidity'] = toNumber(getDomoticzDeviceStatus(1497), true);
+ $res['wc_temp'] = toNumber(getDomoticzDeviceStatus(6868), 1);
+ $res['wc_humidity'] = toNumber(getDomoticzDeviceStatus(6869), true);
+ $res['office_temp'] = toNumber(getDomoticzDeviceStatus(6876), 1);
+ $res['office_humidity'] = toNumber(getDomoticzDeviceStatus(6877), true);
$res['cellar_humidity'] = toNumber(getDomoticzDeviceStatus(4818), true);
$res['cellar_temp'] = toNumber(getDomoticzDeviceStatus(4817), 1);
$res['pressure'] = round($weather['Pressure']['Metric']['Value']);
$ip = $devices[$device]['host'];
$mac = $devices[$device]['mac'];
- `wakeonlan -i $ip $mac`;
+ $cmd = "/usr/bin/wakeonlan -i $ip $mac";
+ $res = `$cmd`;
+ //echo $cmd . ':' . $res;
+ $cmd = "/usr/bin/wakeonlan $mac";
+ $res = `$cmd`;
+ //echo $cmd . ':' .$res;
try {
freeboxWOL($mac);
--- /dev/null
+<?php
+require_once "import.php";
+triggerErrorNotif($_GET['title'],$_GET['message']);
\ No newline at end of file
shieldRunAppAndBackHome($_GET['runappback'], $device);
} else if (isset($_GET['clear'])) {
echo shieldClearAppData($_GET['clear'], $device);
+} else if (isset($_GET['amazonprime'])) {
+ shieldAmazonPrime($_GET['amazonprime'], $device);
}
echo '</pre>';
\ No newline at end of file
include "import.php";
header('Content-Type: text/plain');
ob_end_clean();
-echo getState($_GET['key'], $_GET['default'] ?? null);
\ No newline at end of file
+if (isset($_GET['value'])) {
+ setState($_GET['key'], $_GET['value']);
+} else {
+ echo getState($_GET['key'], $_GET['default'] ?? null);
+}
\ No newline at end of file
if ($device == 'bureau' || $device === 'bureausun') {
execScene('bureau/media/play');
harmonyActivity('switch');
+}else if($device==='salon'){
+ stopPlayersIn('salon', true, false);
+ denonAVROn('Game');
+ execScene('salon/cinema');
+ epson(true);
}
\ No newline at end of file
$task = rawurlencode($task) . "=:=task";
if (getState('vincenthere') == '1') {
- $tortuga = 'http://192.168.13.31:1817/?message=' . $task . '&password=4pyA?Rnyeyc1$44M';
+ $tortuga = 'http://192.168.13.20:1817/?message=' . $task . '&password=4pyA?Rnyeyc1$44M';
} else {
$tortuga = "https://autoremotejoaomgcd.appspot.com/sendmessage?key=APA91bEnQyiR8RE7HcPCcm3mhb6ALojD9PQjHAAHM7y0ih8jYrt1c5q8r_zT_WJacMh8jpvI-bIdstHRQLe6Cx3PTxigQo2H-jsazHOisbFIW9JLvmKNs0O7Mt6kQDPLBvRhBESVTAXa&message=$task&target=TORTUGA&password=4pyA?Rnyeyc1$44M";
}
--- /dev/null
+<?php
+
+include "import.php";
+header('Content-Type: application/json');
+echo velibStations(true);
\ No newline at end of file
<?php
$n = $argv[1];
$path = realpath(__DIR__ . '/../servers/' . $n . '.php');
-`$path >> /var/log/tortugahome/$n.log`;
\ No newline at end of file
+$cmd="$path >> /var/log/tortugahome/$n.log 2>&1";
+echo $cmd;
+`$cmd`;
\ No newline at end of file
$redis = connectRedis();
redisEventListener('domoticz_event', 'handleDomoticzQueue');
+handleDomoticzQueue();
function handleDomoticzQueue()
{
global $redis;
while (true) {
+ setState('domoticz_heartbeat', time());
$q = 'domoticz_queue';
$queue = $redis->igbget($q);
if (!is_array($queue)) {
global $redis;
while (true) {
+ setState('hue_heartbeat', time());
$queue = $redis->igbget('hue_queue');
if (!is_array($queue)) {
$queue = [];
--- /dev/null
+#!/usr/bin/php
+
+<?php
+require_once __DIR__ . "/../scripts/import.php";
+
+// Set time limit to indefinite execution
+set_time_limit(0);
+ignore_user_abort(true);
+
+echo 'Run home server insteon' . "\n";
+
+$redis = connectRedis();
+handleInsteonQueue();
+
+redisEventListener('insteon_event', 'handleInsteonQueue');
+
+function handleInsteonQueue()
+{
+ global $redis;
+
+ while (true) {
+ $queue = $redis->igbget('insteon_queue');
+ if (!is_array($queue)) {
+ $queue = [];
+ $redis->igbset('insteon_queue', $queue);
+ }
+
+
+ if (!count($queue)) {
+ echo 'Queue empty ' . "\n";
+ break;
+ }
+
+ $queue = array_unique($queue);
+
+ echo 'Handle Queue : current state ' . json_encode($queue) . "\n";
+
+ $command = array_shift($queue);
+ $redis->igbset('insteon_queue', $queue);
+ echo 'Run command ' . $command . "\n";
+ if ($command == 'knock') {
+ insteonKnock();
+ continue;
+ }
+ runInsteonCommand($command);
+ usleep(1000000 * 0.5);
+ }
+ echo 'End of handling queue' . "\n";
+}
\ No newline at end of file
}
];
+ setState('logcat'.$l.'_heartbeat', time());
echo 'Run home server logcat ' . $device . "\n";
shieldLogcat($cases, $device);
echo 'Logcat ended' . "\n----\n";
#!/usr/bin/php
<?php
$forceConfig = $device = 'bureau';
+$l='b';
include_once "logcat.php";
\ No newline at end of file
#!/usr/bin/php
<?php
$forceConfig = $device = 'salon';
+$l='s';
include_once "logcat.php";
\ No newline at end of file
echo 'Begin ' . $processingSqueezeboxQueue . "\n";
while (true) {
+ setState('squeezebox_heartbeat', time());
$q = 'squeezebox_queue';
$queue = $redis->igbget($q);
if (!is_array($queue)) {
#!/bin/sh
-/sbin/start-stop-daemon --start --quiet --user tortugahome --chuid tortugahome --name home-$1 --make-pidfile --pidfile /var/run/home-$1.pid --background --startas /bin/bash -- -c "exec /home/tortugahome/www/servers/_startdaemon.php $1"
\ No newline at end of file
+/sbin/start-stop-daemon --start --quiet --user www-data --chuid www-data --name home-$1 --make-pidfile --pidfile /var/run/home-$1.pid --background --startas /bin/bash -- -c "exec /application/servers/_startdaemon.php $1"
\ No newline at end of file
top: 0.2em;
font-size: 0.6em;
}
+section .col > *.nintendoswitch {
+ background-color: #e60012;
+}
section .col > *.missing {
color: #aaa;
opacity: 0.5;
margin-top: 0.3em;
clear: both;
}
+section .col > *.velib li[data-enabled=false] .n.blue,
+section .col > *.velib li[data-enabled=false] .n.green {
+ background-color: #cc0000;
+ color: #cc0000;
+}
section .col > *.velib li .l {
max-width: 7.2em;
display: inline-block;
top: 0.2em;
font-size: 0.6em;
}
+section accordion > a.nintendoswitch {
+ background-color: #e60012;
+}
section accordion > a.missing {
color: #aaa;
opacity: 0.5;
margin-top: 0.3em;
clear: both;
}
+section accordion > a.velib li[data-enabled=false] .n.blue,
+section accordion > a.velib li[data-enabled=false] .n.green {
+ background-color: #cc0000;
+ color: #cc0000;
+}
section accordion > a.velib li .l {
max-width: 7.2em;
display: inline-block;
}
}
+ &.nintendoswitch{
+ background-color:#e60012;
+ }
+
&.missing {
color: #aaa;
opacity: 0.5;
margin-top: 0.3em;
clear: both;
+ &[data-enabled=false] {
+ .n {
+ &.blue, &.green {
+ background-color: #cc0000;
+ color: #cc0000;
+ }
+ }
+ }
+
.l {
max-width: 7.2em;
display: inline-block;
[earth]
"Earth"
grid=no
-map=/home/tortugahome/www/tools/xplanet/earth.png
-night_map=/home/tortugahome/www/tools/xplanet/earth_lights_4800.tif
+map=/application/tools/xplanet/earth.png
+night_map=/application/tools/xplanet/earth_lights_4800.tif
#!/bin/sh
month=$(date +%m)
-ln -sf "/home/tortugahome/www/tools/xplanet/world.topo.bathy.2004$month.3x5400x2700.png" "/home/tortugahome/www/tools/xplanet/earth.png"
-xplanet -config /home/tortugahome/www/tools/xplanet/config -longitude 2.3343236 -latitude 36 -geometry 300x300 -num_times 1 -output /home/tortugahome/www/images/earth.png
\ No newline at end of file
+ln -sf "/application/tools/xplanet/world.topo.bathy.2004$month.3x5400x2700.png" "/application/tools/xplanet/earth.png"
+xplanet -config /application/tools/xplanet/config -longitude 2.3343236 -latitude 36 -geometry 300x300 -num_times 1 -output /application/images/earth.png
\ No newline at end of file
#!/bin/sh
month=$(date +%m)
-ln -sf "/home/tortugahome/www/tools/xplanet/world.topo.bathy.2004$month.3x5400x2700.png" "/home/tortugahome/www/tools/xplanet/earth.png"
-xplanet -config /home/tortugahome/www/tools/xplanet/config -longitude 2.3343236 -geometry 1600x1200 -projection rectangular -num_times 1 -output /home/tortugahome/www/images/suncurve.png
\ No newline at end of file
+ln -sf "/application/tools/xplanet/world.topo.bathy.2004$month.3x5400x2700.png" "/application/tools/xplanet/earth.png"
+xplanet -config /application/tools/xplanet/config -longitude 2.3343236 -geometry 1600x1200 -projection rectangular -num_times 1 -output /application/images/suncurve.png
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+composer update
\ No newline at end of file