ruby_native 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +20 -0
- data/app/controllers/ruby_native/screenshots/sessions_controller.rb +1 -1
- data/lib/generators/ruby_native/templates/CLAUDE.md +20 -0
- data/lib/ruby_native/cli/deploy.rb +53 -8
- data/lib/ruby_native/cli.rb +1 -1
- data/lib/ruby_native/helper.rb +24 -6
- data/lib/ruby_native/native_detection.rb +10 -1
- data/lib/ruby_native/screenshots/sign_in_helper.rb +26 -0
- data/lib/ruby_native/version.rb +1 -1
- data/lib/ruby_native.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f882623a2d70e309c284e7a67a9dd4119579024f5c8da2afbb8cefbf5185127
|
|
4
|
+
data.tar.gz: e05abee9a75d6f830fa0e575517746bfa0e4bc728aeff5d2da75f893de09289e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a598a22166379ba712b9b0fb9417434cb94786937085055363bac1eb676c06a684addaecd4537e5b45098a9ed0ca810d0569d4c1af12c5adbe170cad1d0de6b2
|
|
7
|
+
data.tar.gz: 3fd6fe2454af67d3ea515862dc3161b2a2695dbf1534774baa3afa03e72e8ae564cb147a24d6ff7ad53feebaf1d41520025bdd849a2bb5dc139e583874d2ae0e
|
data/README.md
CHANGED
|
@@ -79,6 +79,26 @@ The companion app persists the scanned URL across launches. Long-press the app i
|
|
|
79
79
|
- `GET /native/config` - returns the YAML config as JSON
|
|
80
80
|
- `POST /native/push/devices` - registers a push notification token (requires `current_user` from host app)
|
|
81
81
|
|
|
82
|
+
## Push notifications
|
|
83
|
+
|
|
84
|
+
Delivery uses the companion `action_push_native` gem. Ruby Native owns the registration handshake (the `native_push_tag` helper prompts for permission, `/native/push/devices` stores the token) and the tap-handling conventions on the native side.
|
|
85
|
+
|
|
86
|
+
When sending a push, two destination keys are supported via `with_data`:
|
|
87
|
+
|
|
88
|
+
- `path` — internal route appended to your base URL and loaded in the in-app WebView (e.g. `/sources/42`).
|
|
89
|
+
- `url` — full external URL opened in `SFSafariViewController`, leaving the WebView in place behind it (e.g. `https://dashboard.stripe.com/payments/pi_abc`).
|
|
90
|
+
|
|
91
|
+
If both are present, `url` wins. `http` and `https` URLs open in `SFSafariViewController`; other valid schemes (`mailto:`, `tel:`, `maps:`, third-party app schemes, etc.) hand off to the appropriate app via `UIApplication.open`. Malformed `url` strings are dropped (the tap does not fall back to `path`).
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
ApplicationPushNotification
|
|
95
|
+
.with_data(path: source_path(source), url: notification.external_url)
|
|
96
|
+
.new(title: "New payment", body: "$49.99 from joe@example.com")
|
|
97
|
+
.deliver_later_to(user.push_devices)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
For model/migration setup, see [action_push_native](https://github.com/basecamp/action_push_native).
|
|
101
|
+
|
|
82
102
|
## Normal and Advanced Modes
|
|
83
103
|
|
|
84
104
|
Normal Mode works with any frontend framework and requires no JavaScript. You get tabs, form page marking, push notifications, and history management.
|
|
@@ -129,6 +129,26 @@ The gem auto-mounts at `/native`. No route configuration needed.
|
|
|
129
129
|
- `GET /native/config` returns the YAML config as JSON
|
|
130
130
|
- `POST /native/push/devices` registers a push notification device token
|
|
131
131
|
|
|
132
|
+
## Push notifications
|
|
133
|
+
|
|
134
|
+
Delivery uses the companion `action_push_native` gem. Ruby Native owns the registration (the `native_push_tag` helper prompts for permission, `/native/push/devices` stores the token) and defines the tap conventions on the native side.
|
|
135
|
+
|
|
136
|
+
Two destination keys are supported via `with_data`:
|
|
137
|
+
|
|
138
|
+
- `path` — internal route appended to your base URL, loaded in the WebView.
|
|
139
|
+
- `url` — full external URL, opened in `SFSafariViewController`.
|
|
140
|
+
|
|
141
|
+
If both are present, `url` wins. `http` and `https` open in `SFSafariViewController`; other valid schemes (`mailto:`, `tel:`, `maps:`, third-party app schemes) open via `UIApplication.open`. Malformed `url` does not fall back to `path`.
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
ApplicationPushNotification
|
|
145
|
+
.with_data(path: source_path(source), url: notification.external_url)
|
|
146
|
+
.new(title: "New payment", body: "$49.99 from joe@example.com")
|
|
147
|
+
.deliver_later_to(user.push_devices)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
For model/migration setup, see the [action_push_native](https://github.com/basecamp/action_push_native) README.
|
|
151
|
+
|
|
132
152
|
## CLI
|
|
133
153
|
|
|
134
154
|
### Deploy from CI
|
|
@@ -16,6 +16,7 @@ module RubyNative
|
|
|
16
16
|
|
|
17
17
|
def initialize(argv)
|
|
18
18
|
@if_needed = argv.include?("--if-needed")
|
|
19
|
+
@platform = parse_platform(argv)
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
def run
|
|
@@ -105,7 +106,7 @@ module RubyNative
|
|
|
105
106
|
req = Net::HTTP::Post.new(uri)
|
|
106
107
|
req["Authorization"] = "Token #{Credentials.token}"
|
|
107
108
|
req["Content-Type"] = "application/json"
|
|
108
|
-
req.body = JSON.generate(
|
|
109
|
+
req.body = JSON.generate(build_payload)
|
|
109
110
|
|
|
110
111
|
response = make_request(uri, req)
|
|
111
112
|
|
|
@@ -174,7 +175,7 @@ module RubyNative
|
|
|
174
175
|
puts " Version: v#{data["version"]} (#{data["number"]})"
|
|
175
176
|
puts " Ruby Native: #{data["native_version"]}" if data["native_version"]
|
|
176
177
|
puts ""
|
|
177
|
-
puts
|
|
178
|
+
puts success_destination_message(data)
|
|
178
179
|
break
|
|
179
180
|
when "failure", "failed", "cancelled"
|
|
180
181
|
puts ""
|
|
@@ -208,15 +209,59 @@ module RubyNative
|
|
|
208
209
|
end
|
|
209
210
|
|
|
210
211
|
def print_status(status)
|
|
211
|
-
|
|
212
|
-
"queued" => "Queued",
|
|
213
|
-
"building" => "Building",
|
|
214
|
-
"processing" => "Submitting to App Store Connect"
|
|
215
|
-
}
|
|
216
|
-
label = labels[status]
|
|
212
|
+
label = status_labels[status]
|
|
217
213
|
puts " #{label}..." if label
|
|
218
214
|
end
|
|
219
215
|
|
|
216
|
+
def status_labels
|
|
217
|
+
if android?
|
|
218
|
+
{
|
|
219
|
+
"queued" => "Queued",
|
|
220
|
+
"building" => "Building Android AAB",
|
|
221
|
+
"processing" => "Uploading to Play Internal Testing"
|
|
222
|
+
}
|
|
223
|
+
else
|
|
224
|
+
{
|
|
225
|
+
"queued" => "Queued",
|
|
226
|
+
"building" => "Building",
|
|
227
|
+
"processing" => "Submitting to App Store Connect"
|
|
228
|
+
}
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def success_destination_message(data)
|
|
233
|
+
platform = data["platform"] || requested_platform
|
|
234
|
+
case platform
|
|
235
|
+
when "android"
|
|
236
|
+
"Your build is being uploaded to Play Internal Testing."
|
|
237
|
+
else
|
|
238
|
+
"Your build is being submitted to TestFlight."
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def parse_platform(argv)
|
|
243
|
+
return "android" if argv.include?("--android")
|
|
244
|
+
|
|
245
|
+
flag = argv.find { |a| a.start_with?("--platform=") }
|
|
246
|
+
return flag.split("=", 2).last if flag
|
|
247
|
+
|
|
248
|
+
"ios"
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def requested_platform
|
|
252
|
+
@platform
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def android?
|
|
256
|
+
@platform == "android"
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def build_payload
|
|
260
|
+
payload = { gem_version: RubyNative::VERSION }
|
|
261
|
+
payload[:platform] = @platform unless @platform == "ios"
|
|
262
|
+
payload
|
|
263
|
+
end
|
|
264
|
+
|
|
220
265
|
# --- App linking ---
|
|
221
266
|
|
|
222
267
|
def link_app
|
data/lib/ruby_native/cli.rb
CHANGED
|
@@ -26,7 +26,7 @@ module RubyNative
|
|
|
26
26
|
puts "Usage: ruby_native <command>"
|
|
27
27
|
puts ""
|
|
28
28
|
puts "Commands:"
|
|
29
|
-
puts " deploy Trigger an iOS build"
|
|
29
|
+
puts " deploy Trigger an iOS build (use --android for Android)"
|
|
30
30
|
puts " login Authenticate with Ruby Native"
|
|
31
31
|
puts " logout Remove stored credentials"
|
|
32
32
|
puts " preview Start a tunnel and display a QR code"
|
data/lib/ruby_native/helper.rb
CHANGED
|
@@ -53,8 +53,10 @@ module RubyNative
|
|
|
53
53
|
tag.div(data: { native_navbar: title.to_s }, hidden: true) { builder.to_html }
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
def native_fab_tag(icon
|
|
57
|
-
|
|
56
|
+
def native_fab_tag(icon: nil, icons: nil, href: nil, click: nil)
|
|
57
|
+
resolved = RubyNative::Helper.resolve_icon(icon: icon, icons: icons, platform: try(:native_platform))
|
|
58
|
+
raise ArgumentError, "native_fab_tag requires an icon" if resolved.nil?
|
|
59
|
+
data = { native_fab: true, native_icon: resolved }
|
|
58
60
|
data[:native_href] = href if href
|
|
59
61
|
data[:native_click] = click if click
|
|
60
62
|
tag.div(data: data, hidden: true)
|
|
@@ -71,16 +73,31 @@ module RubyNative
|
|
|
71
73
|
data
|
|
72
74
|
end
|
|
73
75
|
|
|
76
|
+
# Picks the right icon name for the current native platform. Accepts the
|
|
77
|
+
# single `icon:` form (applied to every platform) and/or the `icons:` hash
|
|
78
|
+
# form (`{ ios: "...", android: "..." }`). When both are given, a matching
|
|
79
|
+
# `icons[platform]` wins; otherwise falls back to `icon`. Returns nil when
|
|
80
|
+
# nothing resolves.
|
|
81
|
+
def self.resolve_icon(icon: nil, icons: nil, platform: nil)
|
|
82
|
+
if icons.is_a?(Hash) && platform
|
|
83
|
+
key = platform.to_sym
|
|
84
|
+
per_platform = icons[key] || icons[key.to_s]
|
|
85
|
+
return per_platform if per_platform
|
|
86
|
+
end
|
|
87
|
+
icon
|
|
88
|
+
end
|
|
89
|
+
|
|
74
90
|
class NavbarBuilder
|
|
75
91
|
def initialize(context)
|
|
76
92
|
@context = context
|
|
77
93
|
@items = []
|
|
78
94
|
end
|
|
79
95
|
|
|
80
|
-
def button(title = nil, icon: nil, href: nil, click: nil, position: :trailing, selected: false, &block)
|
|
96
|
+
def button(title = nil, icon: nil, icons: nil, href: nil, click: nil, position: :trailing, selected: false, &block)
|
|
97
|
+
resolved = RubyNative::Helper.resolve_icon(icon: icon, icons: icons, platform: @context.try(:native_platform))
|
|
81
98
|
data = { native_button: "" }
|
|
82
99
|
data[:native_title] = title if title
|
|
83
|
-
data[:native_icon] =
|
|
100
|
+
data[:native_icon] = resolved if resolved
|
|
84
101
|
data[:native_href] = href if href
|
|
85
102
|
data[:native_click] = click if click
|
|
86
103
|
data[:native_position] = position.to_s
|
|
@@ -114,11 +131,12 @@ module RubyNative
|
|
|
114
131
|
@items = []
|
|
115
132
|
end
|
|
116
133
|
|
|
117
|
-
def item(title, href: nil, click: nil, icon: nil, selected: false)
|
|
134
|
+
def item(title, href: nil, click: nil, icon: nil, icons: nil, selected: false)
|
|
135
|
+
resolved = RubyNative::Helper.resolve_icon(icon: icon, icons: icons, platform: @context.try(:native_platform))
|
|
118
136
|
data = { native_menu_item: "", native_title: title }
|
|
119
137
|
data[:native_href] = href if href
|
|
120
138
|
data[:native_click] = click if click
|
|
121
|
-
data[:native_icon] =
|
|
139
|
+
data[:native_icon] = resolved if resolved
|
|
122
140
|
data[:native_selected] = "" if selected
|
|
123
141
|
@items << @context.tag.div(data: data)
|
|
124
142
|
end
|
|
@@ -3,7 +3,7 @@ module RubyNative
|
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
5
|
included do
|
|
6
|
-
helper_method :native_app?, :native_version if respond_to?(:helper_method)
|
|
6
|
+
helper_method :native_app?, :native_version, :native_platform if respond_to?(:helper_method)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def native_app?
|
|
@@ -14,5 +14,14 @@ module RubyNative
|
|
|
14
14
|
match = request.user_agent.to_s.match(/RubyNative\/([\d.]+)/)
|
|
15
15
|
NativeVersion.new(match ? match[1] : "0")
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
# Returns "ios" or "android" for native requests, nil for web browsers.
|
|
19
|
+
# Used by view helpers to pick the right icon from `icons: { ios:, android: }`.
|
|
20
|
+
def native_platform
|
|
21
|
+
ua = request.user_agent.to_s
|
|
22
|
+
return "ios" if ua.include?("Ruby Native iOS")
|
|
23
|
+
return "android" if ua.include?("Ruby Native Android")
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
17
26
|
end
|
|
18
27
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module RubyNative
|
|
2
|
+
module Screenshots
|
|
3
|
+
# Yielded to the customer's `screenshot_sign_in` lambda. Exposes the
|
|
4
|
+
# request, session, and cookies as public accessors so the lambda never
|
|
5
|
+
# touches `ActionController` internals directly. `cookies` in particular
|
|
6
|
+
# is private on `ActionController::Base` in Rails 8.1+, so customers
|
|
7
|
+
# would otherwise have to fall back to `controller.send(:cookies)`.
|
|
8
|
+
class SignInHelper
|
|
9
|
+
def initialize(controller)
|
|
10
|
+
@controller = controller
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def cookies
|
|
14
|
+
@controller.send(:cookies)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def request
|
|
18
|
+
@controller.request
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def session
|
|
22
|
+
@controller.session
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/ruby_native/version.rb
CHANGED
data/lib/ruby_native.rb
CHANGED
|
@@ -10,6 +10,7 @@ require "ruby_native/iap/verifiable"
|
|
|
10
10
|
require "ruby_native/iap/decodable"
|
|
11
11
|
require "ruby_native/iap/normalizable"
|
|
12
12
|
require "ruby_native/iap/apple_webhook_processor"
|
|
13
|
+
require "ruby_native/screenshots/sign_in_helper"
|
|
13
14
|
require "ruby_native/engine"
|
|
14
15
|
|
|
15
16
|
module RubyNative
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_native
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joe Masilotti
|
|
@@ -101,6 +101,7 @@ files:
|
|
|
101
101
|
- lib/ruby_native/native_detection.rb
|
|
102
102
|
- lib/ruby_native/native_version.rb
|
|
103
103
|
- lib/ruby_native/oauth_middleware.rb
|
|
104
|
+
- lib/ruby_native/screenshots/sign_in_helper.rb
|
|
104
105
|
- lib/ruby_native/tunnel_cookie_middleware.rb
|
|
105
106
|
- lib/ruby_native/version.rb
|
|
106
107
|
homepage: https://github.com/ruby-native/gem
|