ruby_native 0.0.6 → 0.1.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 +78 -6
- data/app/assets/stylesheets/ruby_native.css +11 -0
- data/app/javascript/ruby_native/back.js +3 -0
- data/app/javascript/ruby_native/bridge/button_controller.js +30 -0
- data/app/javascript/ruby_native/bridge/form_controller.js +27 -0
- data/app/javascript/ruby_native/bridge/index.js +14 -0
- data/app/javascript/ruby_native/bridge/menu_controller.js +22 -0
- data/app/javascript/ruby_native/bridge/push_controller.js +10 -0
- data/app/javascript/ruby_native/bridge/search_controller.js +16 -0
- data/app/javascript/ruby_native/bridge/tabs_controller.js +11 -0
- data/config/importmap.rb +2 -0
- data/lib/generators/ruby_native/templates/CLAUDE.md +10 -8
- data/lib/ruby_native/cli/preview.rb +3 -0
- data/lib/ruby_native/engine.rb +10 -1
- data/lib/ruby_native/helper.rb +70 -3
- data/lib/ruby_native/version.rb +1 -1
- metadata +10 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c9cc3f159d5a1cdb53f843060574ad40fa6023854633df6ab08c23628246f926
|
|
4
|
+
data.tar.gz: bfc390268391502cc285da1011e2b17263829d1a92daf33bf40256ebe90f57a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7638386535366c20bb57eac4b339d1c6df136d172efbebbda30acf5a1de8d12fdf4b5bb1bb8c8cb0b3a0a8fdd8f43792dfa9fbee6831450efe4aa67f50e7fc52
|
|
7
|
+
data.tar.gz: 4bbd9674f45483760079c09476650c8bec90f693bdca2632d59fd8a2865a154c9fd26174110ad7a248d36cd20320e7cffbd73dcab71f07b278c3468a6353c32b
|
data/README.md
CHANGED
|
@@ -32,8 +32,6 @@ Using Claude Code? Open it in your project and ask "what do I need to do next?"
|
|
|
32
32
|
Edit `config/ruby_native.yml`:
|
|
33
33
|
|
|
34
34
|
```yaml
|
|
35
|
-
app:
|
|
36
|
-
name: My App
|
|
37
35
|
appearance:
|
|
38
36
|
tint_color: "#4F46E5"
|
|
39
37
|
background_color: "#FFFFFF"
|
|
@@ -80,14 +78,88 @@ The companion app persists the scanned URL across launches. Long-press the app i
|
|
|
80
78
|
- `GET /native/config` - returns the YAML config as JSON
|
|
81
79
|
- `POST /native/push/devices` - registers a push notification token (requires `current_user` from host app)
|
|
82
80
|
|
|
81
|
+
## Normal and Advanced Modes
|
|
82
|
+
|
|
83
|
+
Normal Mode works with any frontend framework and requires no JavaScript. You get tabs, form page marking, push notifications, and history management.
|
|
84
|
+
|
|
85
|
+
Advanced Mode adds native navigation bar buttons, submit buttons, action menus, and search bars. It requires Stimulus and a small JavaScript setup step (see [Advanced Mode setup](#advanced-mode-setup) below). Migration is additive. Start with Normal and add Advanced helpers one page at a time.
|
|
86
|
+
|
|
83
87
|
## View helpers
|
|
84
88
|
|
|
89
|
+
Place helpers in the `<body>`, not the `<head>`.
|
|
90
|
+
|
|
91
|
+
### Any mode
|
|
92
|
+
|
|
85
93
|
- `native_app?` - true when the request comes from a Ruby Native app (checks user agent)
|
|
86
|
-
- `native_tabs_tag` -
|
|
87
|
-
- `
|
|
88
|
-
- `
|
|
94
|
+
- `native_tabs_tag(enabled: true)` - shows the native tab bar.
|
|
95
|
+
- `native_push_tag` - requests push notification permission.
|
|
96
|
+
- `native_back_button_tag(text = nil, **options)` - renders a back button for Normal Mode. Hidden by default, shown when the native app sets `body.can-go-back`. Not needed in [Advanced Mode](https://rubynative.dev/docs/advanced-mode) where the system provides a native back button.
|
|
97
|
+
|
|
98
|
+
### Normal Mode
|
|
99
|
+
|
|
100
|
+
- `native_form_tag` - marks the page as a form. The app skips form pages when navigating back.
|
|
101
|
+
|
|
102
|
+
### Advanced Mode
|
|
103
|
+
|
|
104
|
+
These require the JavaScript setup described in [Advanced Mode setup](#advanced-mode-setup).
|
|
105
|
+
|
|
106
|
+
- `native_form_data` - returns the data hash for the native form submit button. Pass to `form_with`'s `data:` option.
|
|
107
|
+
- `native_submit_data` - returns the data hash for the native submit target. Pass to `form.submit`'s `data:` option.
|
|
108
|
+
- `native_button_tag(title, url, ios_image:, side: :right, **options)` - adds a native navigation bar button.
|
|
109
|
+
- `native_menu_tag(title:, side: :right, &block)` - displays a native action sheet menu.
|
|
110
|
+
- `native_search_tag` - adds a native search bar.
|
|
111
|
+
|
|
112
|
+
## Advanced Mode setup
|
|
113
|
+
|
|
114
|
+
1. Install the JavaScript dependency:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
yarn add @hotwired/hotwire-native-bridge
|
|
118
|
+
# or
|
|
119
|
+
bin/importmap pin @hotwired/hotwire-native-bridge
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
2. Import the controllers in your JavaScript entrypoint:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
import "ruby_native/bridge"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `native_form_data` / `native_submit_data`
|
|
129
|
+
|
|
130
|
+
```erb
|
|
131
|
+
<%= form_with model: @link, data: native_form_data do |f| %>
|
|
132
|
+
<%= f.text_field :url %>
|
|
133
|
+
<%= f.submit "Save", data: native_submit_data %>
|
|
134
|
+
<% end %>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### `native_button_tag`
|
|
138
|
+
|
|
139
|
+
```erb
|
|
140
|
+
<%= native_button_tag "Add a link", new_link_path, ios_image: "plus", class: "btn btn-primary" %>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Options:
|
|
144
|
+
- `ios_image:` - SF Symbol icon name (falls back to the title text)
|
|
145
|
+
- `side:` - `:left` or `:right` (default). Left supplements the back button.
|
|
146
|
+
|
|
147
|
+
### `native_menu_tag`
|
|
148
|
+
|
|
149
|
+
```erb
|
|
150
|
+
<%= native_menu_tag(title: "Actions") do |menu| %>
|
|
151
|
+
<%= menu.item "Edit", edit_link_path(@link) %>
|
|
152
|
+
<%= menu.item "Delete", link_path(@link), method: :delete, destructive: true %>
|
|
153
|
+
<% end %>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Options on `native_menu_tag`:
|
|
157
|
+
- `title:` - action sheet title
|
|
158
|
+
- `side:` - `:left` or `:right` (default)
|
|
89
159
|
|
|
90
|
-
|
|
160
|
+
Options on `menu.item`:
|
|
161
|
+
- `method:` - Turbo method (e.g., `:delete`)
|
|
162
|
+
- `destructive: true` - red styling
|
|
91
163
|
|
|
92
164
|
## Stylesheet
|
|
93
165
|
|
|
@@ -5,3 +5,14 @@
|
|
|
5
5
|
body.can-go-back .native-back-button {
|
|
6
6
|
display: inline;
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
[data-bridge-components~="form"]
|
|
10
|
+
[data-controller~="bridge--form"]
|
|
11
|
+
[type="submit"] {
|
|
12
|
+
display: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
[data-bridge-components~="button"]
|
|
16
|
+
[data-controller~="bridge--button"] {
|
|
17
|
+
display: none;
|
|
18
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
|
2
|
+
|
|
3
|
+
export default class extends BridgeComponent {
|
|
4
|
+
static component = "button"
|
|
5
|
+
|
|
6
|
+
connect() {
|
|
7
|
+
super.connect()
|
|
8
|
+
this.#addButton()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
disconnect() {
|
|
12
|
+
super.disconnect()
|
|
13
|
+
this.#removeButton()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#addButton() {
|
|
17
|
+
const element = this.bridgeElement
|
|
18
|
+
const side = element.bridgeAttribute("side") || "right"
|
|
19
|
+
const image = element.bridgeAttribute("ios-image")
|
|
20
|
+
const data = { title: element.title, image }
|
|
21
|
+
|
|
22
|
+
this.send(side, data, () => {
|
|
23
|
+
this.element.click()
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#removeButton() {
|
|
28
|
+
this.send("disconnect")
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BridgeComponent, BridgeElement } from "@hotwired/hotwire-native-bridge"
|
|
2
|
+
|
|
3
|
+
export default class extends BridgeComponent {
|
|
4
|
+
static component = "form"
|
|
5
|
+
static targets = ["submit"]
|
|
6
|
+
|
|
7
|
+
connect() {
|
|
8
|
+
super.connect()
|
|
9
|
+
|
|
10
|
+
const title = new BridgeElement(this.submitTarget).title
|
|
11
|
+
this.send("connect", { submitTitle: title.trim() }, () => {
|
|
12
|
+
this.submitTarget.click()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
this.element.addEventListener("turbo:submit-start", this.submitStarted)
|
|
16
|
+
this.element.addEventListener("turbo:submit-end", this.submitEnded)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
disconnect() {
|
|
20
|
+
super.disconnect()
|
|
21
|
+
this.element.removeEventListener("turbo:submit-start", this.submitStarted)
|
|
22
|
+
this.element.removeEventListener("turbo:submit-end", this.submitEnded)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
submitStarted = () => this.send("submitDisabled")
|
|
26
|
+
submitEnded = () => this.send("submitEnabled")
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { application } from "controllers/application"
|
|
2
|
+
import TabsController from "ruby_native/bridge/tabs_controller"
|
|
3
|
+
import FormController from "ruby_native/bridge/form_controller"
|
|
4
|
+
import PushController from "ruby_native/bridge/push_controller"
|
|
5
|
+
import MenuController from "ruby_native/bridge/menu_controller"
|
|
6
|
+
import SearchController from "ruby_native/bridge/search_controller"
|
|
7
|
+
import ButtonController from "ruby_native/bridge/button_controller"
|
|
8
|
+
|
|
9
|
+
application.register("bridge--tabs", TabsController)
|
|
10
|
+
application.register("bridge--form", FormController)
|
|
11
|
+
application.register("bridge--push", PushController)
|
|
12
|
+
application.register("bridge--menu", MenuController)
|
|
13
|
+
application.register("bridge--search", SearchController)
|
|
14
|
+
application.register("bridge--button", ButtonController)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BridgeComponent, BridgeElement } from "@hotwired/hotwire-native-bridge"
|
|
2
|
+
|
|
3
|
+
export default class extends BridgeComponent {
|
|
4
|
+
static component = "menu"
|
|
5
|
+
static targets = ["item"]
|
|
6
|
+
static values = { title: String, side: { type: String, default: "right" } }
|
|
7
|
+
|
|
8
|
+
connect() {
|
|
9
|
+
super.connect()
|
|
10
|
+
|
|
11
|
+
const items = this.itemTargets.map((el, index) => ({
|
|
12
|
+
title: new BridgeElement(el).title,
|
|
13
|
+
index,
|
|
14
|
+
destructive: el.hasAttribute("data-destructive")
|
|
15
|
+
}))
|
|
16
|
+
|
|
17
|
+
this.send("connect", { title: this.titleValue, items, side: this.sideValue }, (message) => {
|
|
18
|
+
const { selectedIndex } = message.data
|
|
19
|
+
this.itemTargets[selectedIndex]?.click()
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
|
2
|
+
|
|
3
|
+
export default class extends BridgeComponent {
|
|
4
|
+
static component = "search"
|
|
5
|
+
|
|
6
|
+
connect() {
|
|
7
|
+
super.connect()
|
|
8
|
+
|
|
9
|
+
this.send("connect", {}, (message) => {
|
|
10
|
+
const query = message.data.query
|
|
11
|
+
const detail = {query}
|
|
12
|
+
|
|
13
|
+
this.dispatch("queried", {detail})
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
|
2
|
+
|
|
3
|
+
export default class extends BridgeComponent {
|
|
4
|
+
static component = "tabs"
|
|
5
|
+
static values = { enabled: Boolean }
|
|
6
|
+
|
|
7
|
+
connect() {
|
|
8
|
+
super.connect()
|
|
9
|
+
this.send("connect", { enabled: this.enabledValue })
|
|
10
|
+
}
|
|
11
|
+
}
|
data/config/importmap.rb
ADDED
|
@@ -30,13 +30,17 @@ rails generate ruby_native:install
|
|
|
30
30
|
<%= native_tabs_tag %>
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
6.
|
|
33
|
+
6. Start your Rails server and the preview tunnel in separate terminals:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bin/rails server
|
|
37
|
+
```
|
|
34
38
|
|
|
35
39
|
```bash
|
|
36
40
|
bundle exec ruby_native preview
|
|
37
41
|
```
|
|
38
42
|
|
|
39
|
-
Scan the QR code with the Ruby Native Preview app from the App Store.
|
|
43
|
+
Scan the QR code with the Ruby Native Preview app from the App Store. Keep both the server and tunnel running.
|
|
40
44
|
|
|
41
45
|
## Configuration
|
|
42
46
|
|
|
@@ -100,7 +104,7 @@ Signal elements are hidden `<div>` tags. Place them in the `<body>`, not the `<h
|
|
|
100
104
|
|
|
101
105
|
## Preview
|
|
102
106
|
|
|
103
|
-
`bundle exec ruby_native preview` starts a Cloudflare tunnel and displays a QR code. Requires `cloudflared`:
|
|
107
|
+
`bundle exec ruby_native preview` starts a Cloudflare tunnel and displays a QR code. Your Rails server must be running separately (e.g., `bin/rails server` in another terminal). Requires `cloudflared`:
|
|
104
108
|
|
|
105
109
|
```bash
|
|
106
110
|
brew install cloudflare/cloudflare/cloudflared
|
|
@@ -139,16 +143,14 @@ The gem auto-mounts at `/native`. No route configuration needed.
|
|
|
139
143
|
<%= native_tabs_tag if user_signed_in? %>
|
|
140
144
|
```
|
|
141
145
|
|
|
142
|
-
### Add a native back button
|
|
146
|
+
### Add a native back button (Normal Mode only)
|
|
143
147
|
|
|
144
|
-
|
|
148
|
+
Use the `native_back_button_tag` helper. The gem's stylesheet handles showing it only when there's history to go back to. Not needed in Advanced Mode where the system provides a native back button.
|
|
145
149
|
|
|
146
150
|
```erb
|
|
147
151
|
<%= stylesheet_link_tag :ruby_native %>
|
|
148
152
|
```
|
|
149
153
|
|
|
150
154
|
```erb
|
|
151
|
-
|
|
152
|
-
Back
|
|
153
|
-
</button>
|
|
155
|
+
<%= native_back_button_tag %>
|
|
154
156
|
```
|
|
@@ -45,6 +45,8 @@ module RubyNative
|
|
|
45
45
|
|
|
46
46
|
def start_tunnel
|
|
47
47
|
puts "Starting tunnel to http://localhost:#{@port}..."
|
|
48
|
+
puts "Make sure your Rails server is running on port #{@port} in another terminal."
|
|
49
|
+
puts ""
|
|
48
50
|
|
|
49
51
|
stdin, stdout_err, wait_thread = Open3.popen2e(
|
|
50
52
|
"cloudflared", "tunnel", "--url", "http://localhost:#{@port}"
|
|
@@ -108,6 +110,7 @@ module RubyNative
|
|
|
108
110
|
puts url
|
|
109
111
|
puts ""
|
|
110
112
|
puts "Scan with the Ruby Native preview app."
|
|
113
|
+
puts "Keep this running and your Rails server on port #{@port} in another terminal."
|
|
111
114
|
puts "Press Ctrl+C to stop."
|
|
112
115
|
end
|
|
113
116
|
|
data/lib/ruby_native/engine.rb
CHANGED
|
@@ -10,7 +10,16 @@ module RubyNative
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
initializer "ruby_native.assets" do |app|
|
|
13
|
-
|
|
13
|
+
if app.config.respond_to?(:assets)
|
|
14
|
+
app.config.assets.paths << root.join("app/assets/stylesheets")
|
|
15
|
+
app.config.assets.paths << root.join("app/javascript")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
initializer "ruby_native.importmap", before: "importmap" do |app|
|
|
20
|
+
if app.config.respond_to?(:importmap)
|
|
21
|
+
app.config.importmap.paths << root.join("config/importmap.rb")
|
|
22
|
+
end
|
|
14
23
|
end
|
|
15
24
|
|
|
16
25
|
initializer "ruby_native.config" do
|
data/lib/ruby_native/helper.rb
CHANGED
|
@@ -4,16 +4,83 @@ module RubyNative
|
|
|
4
4
|
request.user_agent.to_s.include?("Ruby Native")
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
def native_tabs_tag
|
|
8
|
-
|
|
7
|
+
def native_tabs_tag(enabled: true)
|
|
8
|
+
safe_join([
|
|
9
|
+
(tag.div(data: { native_tabs: true }, hidden: true) if enabled),
|
|
10
|
+
tag.div(data: { controller: "bridge--tabs", bridge__tabs_enabled_value: enabled })
|
|
11
|
+
].compact)
|
|
9
12
|
end
|
|
10
13
|
|
|
11
14
|
def native_form_tag
|
|
12
15
|
tag.div(data: { native_form: true }, hidden: true)
|
|
13
16
|
end
|
|
14
17
|
|
|
18
|
+
def native_form_data
|
|
19
|
+
{ controller: "bridge--form" }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def native_submit_data
|
|
23
|
+
{ bridge__form_target: "submit" }
|
|
24
|
+
end
|
|
25
|
+
|
|
15
26
|
def native_push_tag
|
|
16
|
-
|
|
27
|
+
safe_join([
|
|
28
|
+
tag.div(data: { native_push: true }, hidden: true),
|
|
29
|
+
tag.div(data: { controller: "bridge--push" })
|
|
30
|
+
])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def native_back_button_tag(text = nil, **options)
|
|
34
|
+
options[:class] = [options[:class], "native-back-button"].compact.join(" ")
|
|
35
|
+
default_content = tag.svg(
|
|
36
|
+
tag.path(d: "M15.75 19.5L8.25 12l7.5-7.5", stroke_linecap: "round", stroke_linejoin: "round"),
|
|
37
|
+
width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", stroke_width: 2.5
|
|
38
|
+
)
|
|
39
|
+
tag.button(text || default_content, onclick: "webkit.messageHandlers.rubyNative.postMessage({action: 'back'})", **options)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def native_search_tag
|
|
43
|
+
tag.div(data: { controller: "bridge--search" })
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def native_button_tag(title, url, ios_image: nil, side: :right, **options)
|
|
47
|
+
data = options.delete(:data) || {}
|
|
48
|
+
data[:controller] = "bridge--button"
|
|
49
|
+
data[:bridge_side] = side.to_s
|
|
50
|
+
data[:bridge_ios_image] = ios_image if ios_image
|
|
51
|
+
|
|
52
|
+
link_to title, url, **options, data: data
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def native_menu_tag(title:, side: :right, &block)
|
|
56
|
+
builder = MenuBuilder.new(self)
|
|
57
|
+
capture(builder, &block)
|
|
58
|
+
|
|
59
|
+
tag.div(style: "display:none", data: {
|
|
60
|
+
controller: "bridge--menu",
|
|
61
|
+
bridge__menu_title_value: title,
|
|
62
|
+
bridge__menu_side_value: side.to_s
|
|
63
|
+
}) { builder.to_html }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class MenuBuilder
|
|
67
|
+
def initialize(context)
|
|
68
|
+
@context = context
|
|
69
|
+
@items = []
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def item(title, url, method: nil, destructive: false, **options)
|
|
73
|
+
data = options.delete(:data) || {}
|
|
74
|
+
data[:bridge__menu_target] = "item"
|
|
75
|
+
data[:turbo_method] = method if method
|
|
76
|
+
data[:destructive] = "" if destructive
|
|
77
|
+
|
|
78
|
+
@items << @context.link_to(title, url, **options, data: data, hidden: true)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def to_html
|
|
82
|
+
@context.safe_join(@items)
|
|
83
|
+
end
|
|
17
84
|
end
|
|
18
85
|
end
|
|
19
86
|
end
|
data/lib/ruby_native/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joe Masilotti
|
|
@@ -51,6 +51,15 @@ files:
|
|
|
51
51
|
- app/assets/stylesheets/ruby_native.css
|
|
52
52
|
- app/controllers/ruby_native/config_controller.rb
|
|
53
53
|
- app/controllers/ruby_native/push/devices_controller.rb
|
|
54
|
+
- app/javascript/ruby_native/back.js
|
|
55
|
+
- app/javascript/ruby_native/bridge/button_controller.js
|
|
56
|
+
- app/javascript/ruby_native/bridge/form_controller.js
|
|
57
|
+
- app/javascript/ruby_native/bridge/index.js
|
|
58
|
+
- app/javascript/ruby_native/bridge/menu_controller.js
|
|
59
|
+
- app/javascript/ruby_native/bridge/push_controller.js
|
|
60
|
+
- app/javascript/ruby_native/bridge/search_controller.js
|
|
61
|
+
- app/javascript/ruby_native/bridge/tabs_controller.js
|
|
62
|
+
- config/importmap.rb
|
|
54
63
|
- config/routes.rb
|
|
55
64
|
- exe/ruby_native
|
|
56
65
|
- lib/generators/ruby_native/install_generator.rb
|