Module: RubyNative
- Defined in:
- lib/ruby_native.rb,
lib/ruby_native/cli.rb,
lib/ruby_native/engine.rb,
lib/ruby_native/helper.rb,
lib/ruby_native/version.rb,
lib/ruby_native/cli/login.rb,
lib/ruby_native/iap/event.rb,
lib/ruby_native/cli/deploy.rb,
lib/ruby_native/cli/preview.rb,
lib/ruby_native/iap/decodable.rb,
lib/ruby_native/iap/verifiable.rb,
lib/ruby_native/native_version.rb,
lib/ruby_native/cli/credentials.rb,
lib/ruby_native/inertia_support.rb,
lib/ruby_native/iap/normalizable.rb,
lib/ruby_native/native_detection.rb,
lib/ruby_native/oauth_middleware.rb,
lib/generators/ruby_native/iap_generator.rb,
lib/ruby_native/tunnel_cookie_middleware.rb,
app/models/ruby_native/iap/purchase_intent.rb,
lib/ruby_native/screenshots/sign_in_helper.rb,
app/controllers/ruby_native/aasa_controller.rb,
lib/ruby_native/iap/apple_webhook_processor.rb,
lib/generators/ruby_native/install_generator.rb,
app/controllers/ruby_native/config_controller.rb,
app/controllers/ruby_native/auth/start_controller.rb,
app/controllers/ruby_native/iap/restores_controller.rb,
app/controllers/ruby_native/push/devices_controller.rb,
app/controllers/ruby_native/auth/sessions_controller.rb,
app/controllers/ruby_native/iap/purchases_controller.rb,
app/controllers/ruby_native/webhooks/apple_controller.rb,
app/controllers/ruby_native/iap/completions_controller.rb,
app/controllers/ruby_native/screenshots/sessions_controller.rb
Defined Under Namespace
Modules: Auth, Generators, Helper, IAP, InertiaSupport, NativeDetection, Push, Screenshots, Webhooks Classes: AasaController, CLI, ConfigController, Engine, NativeVersion, OAuthMiddleware, TunnelCookieMiddleware
Constant Summary collapse
- ERROR_SCREEN_STATES =
The native fallback screen has two states: ‘offline` (no connectivity) and `generic` (any other load failure). Each can carry a per-platform icon and localized copy.
%i[offline generic].freeze
- ERROR_SCREEN_COPY_KEYS =
%i[title message].freeze
- VERSION =
"0.10.8"
Class Method Summary collapse
-
.backfill_error_icons ⇒ Object
Mirrors ‘backfill_tab_icons` for the error screen: fills a state’s flat ‘icon` from its per-platform `icons` (ios first, then android), so the iOS app, which reads only the flat `icon`, still renders one.
-
.backfill_tab_icons ⇒ Object
Mirrors per-platform ‘icons:` into the legacy flat `icon:` field so native binaries that only read `tab.icon` keep rendering an icon.
-
.config_as_json ⇒ Object
The JSON served at GET /native/config.
- .configure {|_self| ... } ⇒ Object
-
.error_screen_config(yaml_errors) ⇒ Object
Merges per-state error-screen icons (from YAML) with localized copy (from I18n) into the shape the native apps decode.
-
.error_screen_translations(subkey) ⇒ Object
Reads ‘ruby_native.errors.<subkey>` for every available locale, keeping only the locales the developer actually translated.
- .fire_subscription_callbacks(event) ⇒ Object
- .load_config ⇒ Object
-
.normalize_oauth_paths ⇒ Object
‘auth.oauth_paths` must list only OAuth authorize paths, never their callbacks.
- .on_subscription_change(&block) ⇒ Object
Class Method Details
.backfill_error_icons ⇒ Object
Mirrors ‘backfill_tab_icons` for the error screen: fills a state’s flat ‘icon` from its per-platform `icons` (ios first, then android), so the iOS app, which reads only the flat `icon`, still renders one. An explicit `icon:` wins.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/ruby_native.rb', line 67 def self.backfill_error_icons errors = self.config[:errors] return unless errors.is_a?(Hash) ERROR_SCREEN_STATES.each do |state| state_config = errors[state] next unless state_config.is_a?(Hash) icons = state_config[:icons] next unless icons.is_a?(Hash) state_config[:icon] ||= icons[:ios] || icons[:android] end end |
.backfill_tab_icons ⇒ Object
Mirrors per-platform ‘icons:` into the legacy flat `icon:` field so native binaries that only read `tab.icon` keep rendering an icon. Explicit `icon:` wins; otherwise falls back to `icons.ios`, then `icons.android`.
52 53 54 55 56 57 58 59 60 61 |
# File 'lib/ruby_native.rb', line 52 def self.backfill_tab_icons Array(self.config[:tabs]).each do |tab| next unless tab.is_a?(Hash) icons = tab[:icons] next unless icons.is_a?(Hash) tab[:icon] ||= icons[:ios] || icons[:android] end end |
.config_as_json ⇒ Object
The JSON served at GET /native/config. Identical to ‘config`, except the `errors` block is enriched: per-state icons from config/ruby_native.yml are merged with localized title/message pulled from the host app’s I18n (‘ruby_native.errors.<state>.<key>`), one entry per available locale. Only values the developer actually provided are emitted; the native apps fall back to bundled English copy for anything missing. Built on a deep copy so the in-memory `config` the server reads for view helpers is never mutated.
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/ruby_native.rb', line 95 def self.config_as_json return config if config.nil? payload = config.deep_dup errors = error_screen_config(payload[:errors]) if errors.empty? payload.delete(:errors) else payload[:errors] = errors end payload end |
.configure {|_self| ... } ⇒ Object
24 25 26 |
# File 'lib/ruby_native.rb', line 24 def self.configure yield self end |
.error_screen_config(yaml_errors) ⇒ Object
Merges per-state error-screen icons (from YAML) with localized copy (from I18n) into the shape the native apps decode. Omits any state with neither an icon nor copy, so an untouched app sends no ‘errors` block at all.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/ruby_native.rb', line 111 def self.error_screen_config(yaml_errors) config = ERROR_SCREEN_STATES.each_with_object({}) do |state, result| entry = {} state_config = yaml_errors[state] if yaml_errors.is_a?(Hash) if state_config.is_a?(Hash) entry[:icon] = state_config[:icon] if state_config[:icon] entry[:icons] = state_config[:icons] if state_config[:icons] end ERROR_SCREEN_COPY_KEYS.each do |key| translations = error_screen_translations("#{state}.#{key}") entry[key] = translations unless translations.empty? end result[state] = entry unless entry.empty? end # The Retry button label is shared by both states, so it sits at the top of # the block rather than under a state. retry_label = error_screen_translations("retry") config[:retry] = retry_label unless retry_label.empty? config end |
.error_screen_translations(subkey) ⇒ Object
Reads ‘ruby_native.errors.<subkey>` for every available locale, keeping only the locales the developer actually translated. Copy lives in the host app’s own locale files; the gem ships none.
136 137 138 139 140 141 |
# File 'lib/ruby_native.rb', line 136 def self.error_screen_translations(subkey) I18n.available_locales.each_with_object({}) do |locale, result| value = I18n.t("ruby_native.errors.#{subkey}", locale: locale, default: nil) result[locale] = value unless value.nil? end end |
.fire_subscription_callbacks(event) ⇒ Object
32 33 34 |
# File 'lib/ruby_native.rb', line 32 def self.fire_subscription_callbacks(event) subscription_callbacks.each { |cb| cb.call(event) } end |
.load_config ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ruby_native.rb', line 36 def self.load_config path = Rails.root.join("config", "ruby_native.yml") return unless path.exist? self.config = YAML.load_file(path).deep_symbolize_keys self.config[:app] ||= {} self.config[:app][:entry_path] ||= self.config.dig(:tabs, 0, :path) || "/" self.config[:auth] ||= {} normalize_oauth_paths backfill_tab_icons backfill_error_icons end |
.normalize_oauth_paths ⇒ Object
‘auth.oauth_paths` must list only OAuth authorize paths, never their callbacks. The native app treats every listed path as a sign-in trigger and derives the provider from the last path segment, so a callback entry like “/auth/google/callback” would launch a bogus flow for a provider named “callback” and send sign-in into a loop. The callback round-trip is handled automatically by OAuthMiddleware’s tracking cookie, so it never needs listing. Drop any entry that is the “/callback” child of another listed path and warn, so a copied-in callback can’t break native sign-in.
151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/ruby_native.rb', line 151 def self.normalize_oauth_paths paths = Array(self.config.dig(:auth, :oauth_paths)) callbacks = paths.select { |path| paths.any? { |start| path == "#{start}/callback" } } return if callbacks.empty? Rails.logger.warn( "[RubyNative] Ignoring OAuth callback path(s) in config/ruby_native.yml " \ "(#{callbacks.join(", ")}). List only the authorize path; callbacks are handled automatically." ) self.config[:auth][:oauth_paths] = paths - callbacks end |
.on_subscription_change(&block) ⇒ Object
28 29 30 |
# File 'lib/ruby_native.rb', line 28 def self.on_subscription_change(&block) subscription_callbacks << block end |