Module: Everywhere::Config::DeepLinking
- Included in:
- Everywhere::Config
- Defined in:
- lib/everywhere/config/deep_linking.rb
Instance Method Summary collapse
-
#apple_app_site_association ⇒ Object
The apple-app-site-association document (a Hash), or nil when no Apple app ids are configured.
- #apple_app_site_association_json ⇒ Object
-
#asset_links ⇒ Object
The Digital Asset Links document (an Array), or nil without an Android app.
- #asset_links_json ⇒ Object
-
#deep_linking ⇒ Object
Deep linking / universal links.
- #deep_linking? ⇒ Boolean
- #deep_linking_android ⇒ Object
- #deep_linking_android? ⇒ Boolean
- #deep_linking_android_fingerprints ⇒ Object
- #deep_linking_android_package ⇒ Object
- #deep_linking_apple? ⇒ Boolean
-
#deep_linking_apple_app_ids ⇒ Object
The iOS/tvOS/...
-
#deep_linking_domains ⇒ Object
Domains for the iOS Associated Domains entitlement (applinks:
) and the shell's universal-link host allowlist: the remote host plus any extra domains:. -
#deep_linking_paths ⇒ Object
URL path patterns that open the app.
Instance Method Details
#apple_app_site_association ⇒ Object
The apple-app-site-association document (a Hash), or nil when no Apple app
ids are configured. applinks for universal links; webcredentials so
associated-domains password autofill / Face ID credentials work too.
74 75 76 77 78 79 80 81 82 |
# File 'lib/everywhere/config/deep_linking.rb', line 74 def apple_app_site_association ids = deep_linking_apple_app_ids return nil if ids.empty? { "applinks" => { "details" => [{ "appIDs" => ids, "components" => deep_linking_paths.map { |p| { "/" => p } } }] }, "webcredentials" => { "apps" => ids } } end |
#apple_app_site_association_json ⇒ Object
84 85 86 87 88 |
# File 'lib/everywhere/config/deep_linking.rb', line 84 def apple_app_site_association_json require "json" doc = apple_app_site_association or return nil JSON.generate(doc) end |
#asset_links ⇒ Object
The Digital Asset Links document (an Array), or nil without an Android app.
91 92 93 94 95 96 97 98 |
# File 'lib/everywhere/config/deep_linking.rb', line 91 def asset_links return nil unless deep_linking_android? [{ "relation" => ["delegate_permission/common.handle_all_urls"], "target" => { "namespace" => "android_app", "package_name" => deep_linking_android_package, "sha256_cert_fingerprints" => deep_linking_android_fingerprints } }] end |
#asset_links_json ⇒ Object
100 101 102 103 104 |
# File 'lib/everywhere/config/deep_linking.rb', line 100 def asset_links_json require "json" doc = asset_links or return nil JSON.generate(doc) end |
#deep_linking ⇒ Object
Deep linking / universal links. Declares the app's association with its web domains so the OS can hand matching URLs to the app instead of the browser. The gem serves the two well-known association files this needs — /.well-known/apple-app-site-association and /.well-known/assetlinks.json — generated from this config (Everywhere::Engine in Rails; MobileConfigEndpoint for Sinatra/Hanami). The iOS builder stamps the matching Associated Domains entitlement, and the shell routes an incoming link to its path.
deep_linking:
team_id: ABCDE12345 # derives the iOS app id from bundle_id
# or set app ids explicitly:
# apple_app_id: ABCDE12345.com.example.app
# apple_app_ids: ["ABCDE12345.com.example.app"]
paths: ["/*"] # which paths open the app (default: all)
domains: ["www.example.com"] # extra applinks: domains (remote host is implicit)
android:
package: com.example.app
sha256_cert_fingerprints: ["AB:CD:EF:..."]
24 |
# File 'lib/everywhere/config/deep_linking.rb', line 24 def deep_linking = @data.fetch("deep_linking", nil) || {} |
#deep_linking? ⇒ Boolean
54 |
# File 'lib/everywhere/config/deep_linking.rb', line 54 def deep_linking? = deep_linking_apple? || deep_linking_android? |
#deep_linking_android ⇒ Object
43 |
# File 'lib/everywhere/config/deep_linking.rb', line 43 def deep_linking_android = deep_linking["android"].is_a?(Hash) ? deep_linking["android"] : {} |
#deep_linking_android? ⇒ Boolean
50 |
# File 'lib/everywhere/config/deep_linking.rb', line 50 def deep_linking_android? = !deep_linking_android_package.to_s.empty? && !deep_linking_android_fingerprints.empty? |
#deep_linking_android_fingerprints ⇒ Object
46 47 48 |
# File 'lib/everywhere/config/deep_linking.rb', line 46 def deep_linking_android_fingerprints Array(deep_linking_android["sha256_cert_fingerprints"]).map { |f| f.to_s.strip }.reject(&:empty?) end |
#deep_linking_android_package ⇒ Object
44 |
# File 'lib/everywhere/config/deep_linking.rb', line 44 def deep_linking_android_package = deep_linking_android["package"]&.to_s |
#deep_linking_apple? ⇒ Boolean
52 |
# File 'lib/everywhere/config/deep_linking.rb', line 52 def deep_linking_apple? = !deep_linking_apple_app_ids.empty? |
#deep_linking_apple_app_ids ⇒ Object
The iOS/tvOS/... app identifiers (TeamID.bundleID) the association file advertises. Explicit ids win; otherwise team_id + the app's iOS bundle id.
28 29 30 31 32 33 34 |
# File 'lib/everywhere/config/deep_linking.rb', line 28 def deep_linking_apple_app_ids explicit = Array(deep_linking["apple_app_ids"]) + [deep_linking["apple_app_id"]].compact return explicit.map(&:to_s).uniq unless explicit.empty? team = deep_linking["team_id"].to_s.strip team.empty? ? [] : ["#{team}.#{bundle_id(target: "ios")}"] end |
#deep_linking_domains ⇒ Object
Domains for the iOS Associated Domains entitlement (applinks:domains:. Bare hostnames (no scheme, no path).
59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/everywhere/config/deep_linking.rb', line 59 def deep_linking_domains hosts = [] if remote_url require "uri" hosts << URI(remote_url).host end hosts += Array(deep_linking["domains"]).map { |d| d.to_s.sub(%r{\Ahttps?://}, "").sub(%r{/.*\z}, "") } hosts.compact.reject(&:empty?).uniq rescue URI::InvalidURIError Array(deep_linking["domains"]).map(&:to_s).reject(&:empty?).uniq end |
#deep_linking_paths ⇒ Object
URL path patterns that open the app. Modern (iOS 14+) component form; defaults to every path.
38 39 40 41 |
# File 'lib/everywhere/config/deep_linking.rb', line 38 def deep_linking_paths paths = Array(deep_linking["paths"]).map(&:to_s).reject(&:empty?) paths.empty? ? ["*"] : paths end |