ruflet 0.0.3 → 0.0.5
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/lib/ruflet/manifest_compiler.rb +62 -0
- data/lib/ruflet/version.rb +1 -1
- data/lib/ruflet.rb +6 -6
- data/lib/ruflet_ui/ruflet/app.rb +11 -0
- data/lib/ruflet_ui/ruflet/colors.rb +50 -16
- data/lib/ruflet_ui/ruflet/control.rb +16 -2
- data/lib/ruflet_ui/ruflet/dsl.rb +35 -0
- data/lib/ruflet_ui/ruflet/icon_data.rb +8 -3
- data/lib/ruflet_ui/ruflet/page.rb +139 -36
- data/lib/ruflet_ui/ruflet/ui/control_factory.rb +3 -2
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_dialog_action_control.rb +11 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/snack_bar_control.rb +55 -0
- data/lib/ruflet_ui/ruflet/ui/cupertino_control_registry.rb +14 -0
- data/lib/ruflet_ui/ruflet/ui/material_control_methods.rb +11 -2
- data/lib/ruflet_ui/ruflet/ui/material_control_registry.rb +64 -1
- data/lib/ruflet_ui/ruflet/ui/shared_control_forwarders.rb +1 -0
- data/lib/ruflet_ui.rb +3 -1
- 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: 8f114a59fe4013e5313b51fc7b8b3373dfa7120e57422bc33abb2e224f9724d6
|
|
4
|
+
data.tar.gz: fe0b491c3eff667a72c31521209953a2f7ba8249c1d16f6ec9ac08243099f850
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cbf26f1c4752d3fdd13600ff8b0bd305e3e669165c9cda9d094d4e4687f801adcb1df015230a509c016f8305f195c32459af74eeacdc8829475f62ac8c7af591
|
|
7
|
+
data.tar.gz: a59f249b3b71255a4b499e8e87c69216c3e61d50c974a786cc1d926b7d502b500effe4161b5c2d8c3c384078ead1cfe1194106c872ca4a17bdafb05f180e36f7
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "time"
|
|
5
|
+
|
|
6
|
+
module Ruflet
|
|
7
|
+
module ManifestCompiler
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def compile_app(app, route: "/")
|
|
11
|
+
messages = []
|
|
12
|
+
sender = lambda do |action, payload|
|
|
13
|
+
messages << { "action" => action, "payload" => payload }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
page = Ruflet::Page.new(
|
|
17
|
+
session_id: "manifest",
|
|
18
|
+
client_details: { "route" => route.to_s.empty? ? "/" : route.to_s },
|
|
19
|
+
sender: sender
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
app.view(page)
|
|
23
|
+
page.update
|
|
24
|
+
|
|
25
|
+
compacted = compact_messages(messages)
|
|
26
|
+
|
|
27
|
+
{
|
|
28
|
+
"schema" => "ruflet_manifest/v1",
|
|
29
|
+
"generated_at" => Time.now.utc.iso8601,
|
|
30
|
+
"route" => page.route || "/",
|
|
31
|
+
"messages" => compacted
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def write_file(path, manifest)
|
|
36
|
+
File.write(path, JSON.pretty_generate(manifest))
|
|
37
|
+
path
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def read_file(path)
|
|
41
|
+
JSON.parse(File.read(path.to_s))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def compact_messages(messages)
|
|
45
|
+
full_patch_index = nil
|
|
46
|
+
messages.each_with_index do |message, idx|
|
|
47
|
+
next unless message["action"] == Ruflet::Protocol::ACTIONS[:patch_control]
|
|
48
|
+
|
|
49
|
+
payload = message["payload"] || {}
|
|
50
|
+
next unless payload["id"] == 1
|
|
51
|
+
|
|
52
|
+
patch = payload["patch"]
|
|
53
|
+
next unless patch.is_a?(Array) && patch.any? { |op| op.is_a?(Array) && op[2] == "views" }
|
|
54
|
+
|
|
55
|
+
full_patch_index = idx
|
|
56
|
+
end
|
|
57
|
+
return messages if full_patch_index.nil?
|
|
58
|
+
|
|
59
|
+
[messages[full_patch_index]]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/ruflet/version.rb
CHANGED
data/lib/ruflet.rb
CHANGED
|
@@ -11,12 +11,6 @@ module Ruflet
|
|
|
11
11
|
module_function
|
|
12
12
|
|
|
13
13
|
def run(entrypoint = nil, host: "0.0.0.0", port: 8550, &block)
|
|
14
|
-
begin
|
|
15
|
-
require "ruflet_server"
|
|
16
|
-
rescue LoadError => e
|
|
17
|
-
raise LoadError, "Ruflet.run requires the 'ruflet_server' gem. Add it to your Gemfile.", e.backtrace
|
|
18
|
-
end
|
|
19
|
-
|
|
20
14
|
callback = entrypoint || block
|
|
21
15
|
raise ArgumentError, "Ruflet.run requires a callable entrypoint or block" unless callback.respond_to?(:call)
|
|
22
16
|
|
|
@@ -26,6 +20,12 @@ module Ruflet
|
|
|
26
20
|
return result unless result == :pass
|
|
27
21
|
end
|
|
28
22
|
|
|
23
|
+
begin
|
|
24
|
+
require "ruflet_server"
|
|
25
|
+
rescue LoadError => e
|
|
26
|
+
raise LoadError, "Ruflet.run requires the 'ruflet_server' gem unless a run interceptor handles execution.", e.backtrace
|
|
27
|
+
end
|
|
28
|
+
|
|
29
29
|
Server.new(host: host, port: port) do |page|
|
|
30
30
|
callback.call(page)
|
|
31
31
|
end.start
|
data/lib/ruflet_ui/ruflet/app.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
require_relative "../../ruflet/manifest_compiler"
|
|
2
3
|
|
|
3
4
|
module Ruflet
|
|
4
5
|
class App
|
|
@@ -8,6 +9,16 @@ module Ruflet
|
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def run
|
|
12
|
+
manifest_out = ENV["RUFLET_MANIFEST_OUT"].to_s
|
|
13
|
+
unless manifest_out.empty?
|
|
14
|
+
route = ENV["RUFLET_MANIFEST_ROUTE"].to_s
|
|
15
|
+
route = "/" if route.empty?
|
|
16
|
+
manifest = Ruflet::ManifestCompiler.compile_app(self, route: route)
|
|
17
|
+
Ruflet::ManifestCompiler.write_file(manifest_out, manifest)
|
|
18
|
+
puts manifest_out
|
|
19
|
+
return manifest_out
|
|
20
|
+
end
|
|
21
|
+
|
|
11
22
|
Ruflet.run(host: @host, port: @port) do |page|
|
|
12
23
|
view(page)
|
|
13
24
|
end
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Ruflet
|
|
4
4
|
module Colors
|
|
5
|
-
module_function
|
|
6
|
-
|
|
7
5
|
SEMANTIC_COLORS = {
|
|
8
6
|
PRIMARY: "primary",
|
|
9
7
|
ON_PRIMARY: "onprimary",
|
|
@@ -127,14 +125,32 @@ module Ruflet
|
|
|
127
125
|
end
|
|
128
126
|
|
|
129
127
|
def all_values
|
|
130
|
-
@all_values
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
128
|
+
return @all_values if @all_values
|
|
129
|
+
|
|
130
|
+
values = []
|
|
131
|
+
SEMANTIC_COLORS.each_value { |v| values << v }
|
|
132
|
+
FIXED_COLORS.each_value { |v| values << v }
|
|
133
|
+
|
|
134
|
+
BASE_PRIMARY.each do |base|
|
|
135
|
+
values << base
|
|
136
|
+
PRIMARY_SHADES.each do |shade|
|
|
137
|
+
values << "#{base}#{shade}"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
BASE_ACCENT.each do |base|
|
|
142
|
+
values << "#{base}accent"
|
|
143
|
+
ACCENT_SHADES.each do |shade|
|
|
144
|
+
values << "#{base}accent#{shade}"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
uniq_map = {}
|
|
149
|
+
values.each { |v| uniq_map[v] = true }
|
|
150
|
+
@all_values = uniq_map.keys.freeze
|
|
135
151
|
end
|
|
136
152
|
|
|
137
|
-
def normalize_color(color)
|
|
153
|
+
def self.normalize_color(color)
|
|
138
154
|
return color.to_s if color.is_a?(Symbol)
|
|
139
155
|
return color if color.is_a?(String)
|
|
140
156
|
return color.to_s unless color.respond_to?(:to_s)
|
|
@@ -164,15 +180,17 @@ module Ruflet
|
|
|
164
180
|
"yellow" => "YELLOW"
|
|
165
181
|
}.freeze
|
|
166
182
|
|
|
167
|
-
def constant_prefix_for(base_name)
|
|
168
|
-
|
|
183
|
+
def self.constant_prefix_for(base_name)
|
|
184
|
+
key = base_name.to_s
|
|
185
|
+
return BASE_PREFIX[key] if BASE_PREFIX.key?(key)
|
|
186
|
+
key.upcase
|
|
169
187
|
end
|
|
170
188
|
|
|
171
189
|
SEMANTIC_COLORS.each { |k, v| const_set(k, v) }
|
|
172
190
|
FIXED_COLORS.each { |k, v| const_set(k, v) }
|
|
173
191
|
|
|
174
192
|
BASE_PRIMARY.each do |base|
|
|
175
|
-
prefix = constant_prefix_for(base)
|
|
193
|
+
prefix = self.constant_prefix_for(base)
|
|
176
194
|
const_set(prefix, base)
|
|
177
195
|
PRIMARY_SHADES.each do |shade|
|
|
178
196
|
const_set("#{prefix}_#{shade}", "#{base}#{shade}")
|
|
@@ -180,7 +198,7 @@ module Ruflet
|
|
|
180
198
|
end
|
|
181
199
|
|
|
182
200
|
BASE_ACCENT.each do |base|
|
|
183
|
-
prefix = "#{constant_prefix_for(base)}_ACCENT"
|
|
201
|
+
prefix = "#{self.constant_prefix_for(base)}_ACCENT"
|
|
184
202
|
const_set(prefix, "#{base}accent")
|
|
185
203
|
ACCENT_SHADES.each do |shade|
|
|
186
204
|
const_set("#{prefix}_#{shade}", "#{base}accent#{shade}")
|
|
@@ -191,10 +209,26 @@ module Ruflet
|
|
|
191
209
|
const_set(alias_name, const_get(target))
|
|
192
210
|
end
|
|
193
211
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
212
|
+
constant_names = []
|
|
213
|
+
SEMANTIC_COLORS.each_key { |k| constant_names << k }
|
|
214
|
+
FIXED_COLORS.each_key { |k| constant_names << k }
|
|
215
|
+
BASE_PRIMARY.each do |base|
|
|
216
|
+
constant_names << constant_prefix_for(base).to_sym
|
|
217
|
+
PRIMARY_SHADES.each { |shade| constant_names << "#{constant_prefix_for(base)}_#{shade}".to_sym }
|
|
218
|
+
end
|
|
219
|
+
BASE_ACCENT.each do |base|
|
|
220
|
+
constant_names << "#{constant_prefix_for(base)}_ACCENT".to_sym
|
|
221
|
+
ACCENT_SHADES.each { |shade| constant_names << "#{constant_prefix_for(base)}_ACCENT_#{shade}".to_sym }
|
|
222
|
+
end
|
|
223
|
+
DEPRECATED_ALIASES.each_key { |k| constant_names << k }
|
|
224
|
+
|
|
225
|
+
uniq_constants = {}
|
|
226
|
+
constant_names.each { |n| uniq_constants[n] = true }
|
|
227
|
+
if respond_to?(:define_singleton_method)
|
|
228
|
+
uniq_constants.keys.each do |name|
|
|
229
|
+
next if respond_to?(name)
|
|
230
|
+
define_singleton_method(name) { const_get(name) }
|
|
231
|
+
end
|
|
198
232
|
end
|
|
199
233
|
end
|
|
200
234
|
end
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
begin
|
|
4
|
+
require "securerandom"
|
|
5
|
+
rescue LoadError
|
|
6
|
+
nil
|
|
7
|
+
end
|
|
4
8
|
require_relative "ui/control_registry"
|
|
5
9
|
require_relative "icon_data"
|
|
6
10
|
require_relative "icons/material_icon_lookup"
|
|
@@ -17,7 +21,7 @@ module Ruflet
|
|
|
17
21
|
|
|
18
22
|
def initialize(type:, id: nil, **props)
|
|
19
23
|
@type = type.to_s.downcase
|
|
20
|
-
@id = (id || props.delete(:id) || "ctrl_#{
|
|
24
|
+
@id = (id || props.delete(:id) || "ctrl_#{self.class.generate_id}").to_s
|
|
21
25
|
@children = []
|
|
22
26
|
@handlers = {}
|
|
23
27
|
@wire_id = nil
|
|
@@ -62,6 +66,16 @@ module Ruflet
|
|
|
62
66
|
|
|
63
67
|
private
|
|
64
68
|
|
|
69
|
+
class << self
|
|
70
|
+
def generate_id
|
|
71
|
+
if defined?(SecureRandom) && SecureRandom.respond_to?(:hex)
|
|
72
|
+
SecureRandom.hex(4)
|
|
73
|
+
else
|
|
74
|
+
format("%08x", rand(0..0xffff_ffff))
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
65
79
|
def serialize_value(value)
|
|
66
80
|
case value
|
|
67
81
|
when Control
|
data/lib/ruflet_ui/ruflet/dsl.rb
CHANGED
|
@@ -5,6 +5,15 @@ require_relative "ui/control_factory"
|
|
|
5
5
|
|
|
6
6
|
module Ruflet
|
|
7
7
|
module DSL
|
|
8
|
+
DURATION_FACTORS_MS = {
|
|
9
|
+
days: 86_400_000.0,
|
|
10
|
+
hours: 3_600_000.0,
|
|
11
|
+
minutes: 60_000.0,
|
|
12
|
+
seconds: 1_000.0,
|
|
13
|
+
milliseconds: 1.0,
|
|
14
|
+
microseconds: 0.001
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
8
17
|
module_function
|
|
9
18
|
|
|
10
19
|
def _pending_app
|
|
@@ -95,6 +104,7 @@ module Ruflet
|
|
|
95
104
|
def cupertinodialogaction(**props) = _pending_app.cupertinodialogaction(**props)
|
|
96
105
|
def cupertino_navigation_bar(**props) = _pending_app.cupertino_navigation_bar(**props)
|
|
97
106
|
def cupertinonavigationbar(**props) = _pending_app.cupertinonavigationbar(**props)
|
|
107
|
+
def duration(**parts) = duration_in_milliseconds(parts)
|
|
98
108
|
|
|
99
109
|
class App
|
|
100
110
|
include UI::ControlMethods
|
|
@@ -146,6 +156,10 @@ module Ruflet
|
|
|
146
156
|
c
|
|
147
157
|
end
|
|
148
158
|
|
|
159
|
+
def duration(**parts)
|
|
160
|
+
DSL.duration(**parts)
|
|
161
|
+
end
|
|
162
|
+
|
|
149
163
|
def run
|
|
150
164
|
app_roots = @roots
|
|
151
165
|
page_props = @page_props.dup
|
|
@@ -177,6 +191,27 @@ module Ruflet
|
|
|
177
191
|
"#{type}_#{@seq}"
|
|
178
192
|
end
|
|
179
193
|
|
|
194
|
+
def duration_in_milliseconds(parts)
|
|
195
|
+
DSL.send(:duration_in_milliseconds, parts)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def duration_in_milliseconds(parts)
|
|
201
|
+
return 0 if parts.nil? || parts.empty?
|
|
202
|
+
|
|
203
|
+
DURATION_FACTORS_MS.reduce(0.0) do |sum, (key, factor)|
|
|
204
|
+
sum + read_duration_part(parts, key) * factor
|
|
205
|
+
end.round
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def read_duration_part(parts, key)
|
|
209
|
+
raw = parts[key] || parts[key.to_s]
|
|
210
|
+
return 0.0 if raw.nil?
|
|
211
|
+
return raw.to_f if raw.is_a?(Numeric)
|
|
212
|
+
return raw.to_f if raw.is_a?(String) && raw.match?(/\A-?\d+(\.\d+)?\z/)
|
|
213
|
+
|
|
214
|
+
0.0
|
|
180
215
|
end
|
|
181
216
|
end
|
|
182
217
|
end
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
require_relative "icons/
|
|
3
|
+
begin
|
|
4
|
+
require_relative "icons/material_icon_lookup"
|
|
5
|
+
require_relative "icons/cupertino_icon_lookup"
|
|
6
|
+
rescue StandardError
|
|
7
|
+
nil
|
|
8
|
+
end
|
|
5
9
|
|
|
6
10
|
module Ruflet
|
|
7
11
|
class IconData
|
|
@@ -44,7 +48,8 @@ module Ruflet
|
|
|
44
48
|
return codepoint
|
|
45
49
|
end
|
|
46
50
|
|
|
47
|
-
raw = input.to_s
|
|
51
|
+
raw = input.to_s
|
|
52
|
+
raw = raw.strip if raw.respond_to?(:strip)
|
|
48
53
|
return raw if raw.empty?
|
|
49
54
|
|
|
50
55
|
codepoint = Ruflet::MaterialIconLookup.codepoint_for(raw)
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
require_relative "event"
|
|
4
4
|
require "ruflet_protocol"
|
|
5
5
|
require_relative "control"
|
|
6
|
-
require_relative "ui/control_methods"
|
|
7
6
|
require_relative "ui/widget_builder"
|
|
8
7
|
require_relative "icons/material_icon_lookup"
|
|
9
8
|
require_relative "icons/cupertino_icon_lookup"
|
|
@@ -12,11 +11,21 @@ require "cgi"
|
|
|
12
11
|
|
|
13
12
|
module Ruflet
|
|
14
13
|
class Page
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
PAGE_PROP_KEYS = %w[route title vertical_alignment horizontal_alignment].freeze
|
|
14
|
+
PAGE_PROP_KEYS = %w[route title vertical_alignment horizontal_alignment scroll].freeze
|
|
18
15
|
DIALOG_PROP_KEYS = %w[dialog snack_bar bottom_sheet].freeze
|
|
19
16
|
BUTTON_TEXT_TYPES = %w[button elevatedbutton textbutton filledbutton].freeze
|
|
17
|
+
DEPRECATED_PAGE_WIDGET_METHODS = %i[
|
|
18
|
+
control widget view column center row stack container gesture_detector gesturedetector draggable
|
|
19
|
+
drag_target dragtarget text button elevated_button elevatedbutton text_button textbutton filled_button
|
|
20
|
+
filledbutton icon_button iconbutton text_field textfield checkbox radio radio_group radiogroup
|
|
21
|
+
alert_dialog alertdialog markdown icon image app_bar appbar floating_action_button snack_bar snackbar
|
|
22
|
+
bottom_sheet bottomsheet tabs tab tab_bar tabbar tab_bar_view tabbarview navigation_bar navigationbar
|
|
23
|
+
navigation_bar_destination navigationbardestination fab cupertino_button
|
|
24
|
+
cupertinobutton cupertino_filled_button cupertinofilledbutton cupertino_text_field cupertinotextfield
|
|
25
|
+
cupertino_switch cupertinoswitch cupertino_slider cupertinoslider cupertino_alert_dialog
|
|
26
|
+
cupertinoalertdialog cupertino_action_sheet cupertinoactionsheet cupertino_dialog_action
|
|
27
|
+
cupertinodialogaction cupertino_navigation_bar cupertinonavigationbar
|
|
28
|
+
].freeze
|
|
20
29
|
|
|
21
30
|
attr_reader :session_id, :client_details, :views
|
|
22
31
|
|
|
@@ -39,12 +48,18 @@ module Ruflet
|
|
|
39
48
|
id: "_overlay",
|
|
40
49
|
controls: []
|
|
41
50
|
)
|
|
51
|
+
@services_container = Ruflet::Control.new(
|
|
52
|
+
type: "service_registry",
|
|
53
|
+
id: "_services",
|
|
54
|
+
"_services": []
|
|
55
|
+
)
|
|
42
56
|
@dialogs_container = Ruflet::Control.new(
|
|
43
57
|
type: "dialogs",
|
|
44
58
|
id: "_dialogs",
|
|
45
59
|
controls: []
|
|
46
60
|
)
|
|
47
61
|
refresh_overlay_container!
|
|
62
|
+
refresh_services_container!
|
|
48
63
|
refresh_dialogs_container!
|
|
49
64
|
end
|
|
50
65
|
|
|
@@ -123,6 +138,24 @@ module Ruflet
|
|
|
123
138
|
self
|
|
124
139
|
end
|
|
125
140
|
|
|
141
|
+
def services
|
|
142
|
+
@services_container.props["_services"] ||= []
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def services=(value)
|
|
146
|
+
@services_container.props["_services"] = Array(value).compact
|
|
147
|
+
refresh_services_container!
|
|
148
|
+
push_services_update!
|
|
149
|
+
self
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def add_service(*value)
|
|
153
|
+
@services_container.props["_services"] = services + value.flatten.compact
|
|
154
|
+
refresh_services_container!
|
|
155
|
+
push_services_update!
|
|
156
|
+
self
|
|
157
|
+
end
|
|
158
|
+
|
|
126
159
|
def go(route, **query_params)
|
|
127
160
|
@page_props["route"] = build_route(route, query_params)
|
|
128
161
|
dispatch_page_event(name: "route_change", data: @page_props["route"])
|
|
@@ -149,22 +182,10 @@ module Ruflet
|
|
|
149
182
|
add(*builder.children)
|
|
150
183
|
end
|
|
151
184
|
|
|
152
|
-
def appbar(**props, &block)
|
|
153
|
-
return @view_props["appbar"] if props.empty? && !block
|
|
154
|
-
|
|
155
|
-
WidgetBuilder.new.appbar(**props, &block)
|
|
156
|
-
end
|
|
157
|
-
|
|
158
185
|
def appbar=(value)
|
|
159
186
|
@view_props["appbar"] = value
|
|
160
187
|
end
|
|
161
188
|
|
|
162
|
-
def floating_action_button(**props, &block)
|
|
163
|
-
return @view_props["floating_action_button"] if props.empty? && !block
|
|
164
|
-
|
|
165
|
-
WidgetBuilder.new.floating_action_button(**props, &block)
|
|
166
|
-
end
|
|
167
|
-
|
|
168
189
|
def floating_action_button=(value)
|
|
169
190
|
@view_props["floating_action_button"] = value
|
|
170
191
|
end
|
|
@@ -176,40 +197,20 @@ module Ruflet
|
|
|
176
197
|
refresh_dialogs_container!
|
|
177
198
|
end
|
|
178
199
|
|
|
179
|
-
def snack_bar(**props, &block)
|
|
180
|
-
return @snack_bar if props.empty? && !block
|
|
181
|
-
|
|
182
|
-
super
|
|
183
|
-
end
|
|
184
|
-
|
|
185
200
|
def snack_bar=(value)
|
|
186
201
|
@snack_bar = value
|
|
187
202
|
refresh_dialogs_container!
|
|
188
203
|
end
|
|
189
204
|
|
|
190
|
-
def snackbar(**props, &block)
|
|
191
|
-
snack_bar(**props, &block)
|
|
192
|
-
end
|
|
193
|
-
|
|
194
205
|
def snackbar=(value)
|
|
195
206
|
self.snack_bar = value
|
|
196
207
|
end
|
|
197
208
|
|
|
198
|
-
def bottom_sheet(**props, &block)
|
|
199
|
-
return @bottom_sheet if props.empty? && !block
|
|
200
|
-
|
|
201
|
-
super
|
|
202
|
-
end
|
|
203
|
-
|
|
204
209
|
def bottom_sheet=(value)
|
|
205
210
|
@bottom_sheet = value
|
|
206
211
|
refresh_dialogs_container!
|
|
207
212
|
end
|
|
208
213
|
|
|
209
|
-
def bottomsheet(**props, &block)
|
|
210
|
-
bottom_sheet(**props, &block)
|
|
211
|
-
end
|
|
212
|
-
|
|
213
214
|
def bottomsheet=(value)
|
|
214
215
|
self.bottom_sheet = value
|
|
215
216
|
end
|
|
@@ -227,6 +228,43 @@ module Ruflet
|
|
|
227
228
|
self
|
|
228
229
|
end
|
|
229
230
|
|
|
231
|
+
def invoke(control_or_id, method_name, args: nil, timeout: 10)
|
|
232
|
+
control = resolve_control(control_or_id)
|
|
233
|
+
return nil unless control
|
|
234
|
+
|
|
235
|
+
call_id = "call_#{Ruflet::Control.generate_id}"
|
|
236
|
+
send_message(Protocol::ACTIONS[:invoke_control_method], {
|
|
237
|
+
"control_id" => control.wire_id,
|
|
238
|
+
"call_id" => call_id,
|
|
239
|
+
"name" => method_name.to_s,
|
|
240
|
+
"args" => args,
|
|
241
|
+
"timeout" => timeout
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
call_id
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def launch_url(url, mode: "external_application", web_view_configuration: nil, browser_configuration: nil, web_only_window_name: nil, timeout: 10)
|
|
248
|
+
launcher = ensure_url_launcher_service
|
|
249
|
+
invoke(
|
|
250
|
+
launcher,
|
|
251
|
+
"launch_url",
|
|
252
|
+
args: {
|
|
253
|
+
"url" => url,
|
|
254
|
+
"mode" => mode,
|
|
255
|
+
"web_view_configuration" => web_view_configuration,
|
|
256
|
+
"browser_configuration" => browser_configuration,
|
|
257
|
+
"web_only_window_name" => web_only_window_name
|
|
258
|
+
}.compact,
|
|
259
|
+
timeout: timeout
|
|
260
|
+
)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def can_launch_url(url, timeout: 10)
|
|
264
|
+
launcher = ensure_url_launcher_service
|
|
265
|
+
invoke(launcher, "can_launch_url", args: { "url" => url }, timeout: timeout)
|
|
266
|
+
end
|
|
267
|
+
|
|
230
268
|
def pop_dialog
|
|
231
269
|
dialog_control = latest_open_dialog
|
|
232
270
|
return nil unless dialog_control
|
|
@@ -304,6 +342,45 @@ module Ruflet
|
|
|
304
342
|
end
|
|
305
343
|
end
|
|
306
344
|
|
|
345
|
+
def method_missing(name, *args, &block)
|
|
346
|
+
method_name = name.to_s
|
|
347
|
+
prop_name = method_name.delete_suffix("=")
|
|
348
|
+
|
|
349
|
+
if method_name.end_with?("=")
|
|
350
|
+
if DEPRECATED_PAGE_WIDGET_METHODS.include?(prop_name.to_sym)
|
|
351
|
+
Kernel.warn("[DEPRECATION] `page.#{prop_name}(...)` is no longer supported.")
|
|
352
|
+
raise NoMethodError, "Use `#{prop_name}(...)` as a free widget helper, then attach with `page.add(...)`."
|
|
353
|
+
end
|
|
354
|
+
assign_split_prop(prop_name, normalize_value(prop_name, args.first))
|
|
355
|
+
return args.first
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
if args.empty? && !block
|
|
359
|
+
return @page_props[method_name] if @page_props.key?(method_name)
|
|
360
|
+
return @view_props[method_name] if @view_props.key?(method_name)
|
|
361
|
+
return instance_variable_get("@#{method_name}") if DIALOG_PROP_KEYS.include?(method_name)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
if DEPRECATED_PAGE_WIDGET_METHODS.include?(name.to_sym)
|
|
365
|
+
Kernel.warn("[DEPRECATION] `page.#{name}(...)` is no longer supported.")
|
|
366
|
+
raise NoMethodError, "Use `#{name}(...)` as a free widget helper, then attach with `page.add(...)`."
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
super
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def respond_to_missing?(name, include_private = false)
|
|
373
|
+
method_name = name.to_s
|
|
374
|
+
prop_name = method_name.delete_suffix("=")
|
|
375
|
+
DEPRECATED_PAGE_WIDGET_METHODS.include?(name.to_sym) ||
|
|
376
|
+
DEPRECATED_PAGE_WIDGET_METHODS.include?(prop_name.to_sym) ||
|
|
377
|
+
method_name.end_with?("=") ||
|
|
378
|
+
@page_props.key?(method_name) ||
|
|
379
|
+
@view_props.key?(method_name) ||
|
|
380
|
+
DIALOG_PROP_KEYS.include?(method_name) ||
|
|
381
|
+
super
|
|
382
|
+
end
|
|
383
|
+
|
|
307
384
|
private
|
|
308
385
|
|
|
309
386
|
def build_widget(type, **props, &block) = WidgetBuilder.new.control(type, **props, &block)
|
|
@@ -480,6 +557,23 @@ module Ruflet
|
|
|
480
557
|
@page_props["_overlay"] = @overlay_container
|
|
481
558
|
end
|
|
482
559
|
|
|
560
|
+
def refresh_services_container!
|
|
561
|
+
@page_props["_services"] = @services_container
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def push_services_update!
|
|
565
|
+
refresh_control_indexes!
|
|
566
|
+
|
|
567
|
+
if @services_container.wire_id
|
|
568
|
+
send_message(Protocol::ACTIONS[:patch_control], {
|
|
569
|
+
"id" => @services_container.wire_id,
|
|
570
|
+
"patch" => [[0], [0, 0, "_services", serialize_patch_value(@services_container.props["_services"])]]
|
|
571
|
+
})
|
|
572
|
+
else
|
|
573
|
+
send_view_patch
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
|
|
483
577
|
def push_dialogs_update!
|
|
484
578
|
refresh_control_indexes!
|
|
485
579
|
|
|
@@ -546,5 +640,14 @@ module Ruflet
|
|
|
546
640
|
end
|
|
547
641
|
codepoint
|
|
548
642
|
end
|
|
643
|
+
|
|
644
|
+
def ensure_url_launcher_service
|
|
645
|
+
launcher = services.find { |service| service.is_a?(Control) && service.type == "url_launcher" }
|
|
646
|
+
return launcher if launcher
|
|
647
|
+
|
|
648
|
+
launcher = build_widget(:url_launcher)
|
|
649
|
+
add_service(launcher)
|
|
650
|
+
launcher
|
|
651
|
+
end
|
|
549
652
|
end
|
|
550
653
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "material_control_factory"
|
|
4
4
|
require_relative "cupertino_control_factory"
|
|
5
|
+
require_relative "../control"
|
|
5
6
|
|
|
6
7
|
module Ruflet
|
|
7
8
|
module UI
|
|
@@ -13,9 +14,9 @@ module Ruflet
|
|
|
13
14
|
def build(type, id: nil, **props)
|
|
14
15
|
normalized_type = type.to_s.downcase
|
|
15
16
|
klass = CLASS_MAP[normalized_type]
|
|
16
|
-
|
|
17
|
+
return klass.new(id: id, **props) if klass
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
Ruflet::Control.new(type: normalized_type, id: id, **props)
|
|
19
20
|
end
|
|
20
21
|
end
|
|
21
22
|
end
|
|
@@ -7,6 +7,17 @@ module Ruflet
|
|
|
7
7
|
def initialize(id: nil, **props)
|
|
8
8
|
super(type: "cupertino_dialog_action", id: id, **props)
|
|
9
9
|
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def preprocess_props(props)
|
|
14
|
+
mapped = props.dup
|
|
15
|
+
if mapped.key?(:text) || mapped.key?("text")
|
|
16
|
+
value = mapped.key?(:text) ? mapped.delete(:text) : mapped.delete("text")
|
|
17
|
+
mapped[:content] = value unless mapped.key?(:content) || mapped.key?("content")
|
|
18
|
+
end
|
|
19
|
+
mapped
|
|
20
|
+
end
|
|
10
21
|
end
|
|
11
22
|
end
|
|
12
23
|
end
|
|
@@ -7,6 +7,61 @@ module Ruflet
|
|
|
7
7
|
def initialize(id: nil, **props)
|
|
8
8
|
super(type: "snackbar", id: id, **props)
|
|
9
9
|
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def preprocess_props(props)
|
|
14
|
+
mapped = props.dup
|
|
15
|
+
key = if mapped.key?(:duration)
|
|
16
|
+
:duration
|
|
17
|
+
elsif mapped.key?("duration")
|
|
18
|
+
"duration"
|
|
19
|
+
end
|
|
20
|
+
return mapped unless key
|
|
21
|
+
|
|
22
|
+
mapped[key] = normalize_duration_ms(mapped[key])
|
|
23
|
+
mapped
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def normalize_duration_ms(value)
|
|
27
|
+
return value.to_i if value.is_a?(Numeric)
|
|
28
|
+
return value.to_i if value.is_a?(String) && value.match?(/\A\d+(\.\d+)?\z/)
|
|
29
|
+
|
|
30
|
+
parts =
|
|
31
|
+
if value.is_a?(Hash)
|
|
32
|
+
value
|
|
33
|
+
elsif value.respond_to?(:to_h)
|
|
34
|
+
value.to_h
|
|
35
|
+
else
|
|
36
|
+
nil
|
|
37
|
+
end
|
|
38
|
+
return value unless parts.is_a?(Hash)
|
|
39
|
+
|
|
40
|
+
days = read_number(parts, "days")
|
|
41
|
+
hours = read_number(parts, "hours")
|
|
42
|
+
minutes = read_number(parts, "minutes")
|
|
43
|
+
seconds = read_number(parts, "seconds")
|
|
44
|
+
milliseconds = read_number(parts, "milliseconds")
|
|
45
|
+
microseconds = read_number(parts, "microseconds")
|
|
46
|
+
|
|
47
|
+
total_ms = 0.0
|
|
48
|
+
total_ms += days * 86_400_000.0
|
|
49
|
+
total_ms += hours * 3_600_000.0
|
|
50
|
+
total_ms += minutes * 60_000.0
|
|
51
|
+
total_ms += seconds * 1_000.0
|
|
52
|
+
total_ms += milliseconds
|
|
53
|
+
total_ms += microseconds / 1000.0
|
|
54
|
+
total_ms.round
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def read_number(parts, key)
|
|
58
|
+
raw = parts[key] || parts[key.to_sym]
|
|
59
|
+
return 0.0 if raw.nil?
|
|
60
|
+
return raw.to_f if raw.is_a?(Numeric)
|
|
61
|
+
return raw.to_f if raw.is_a?(String) && raw.match?(/\A-?\d+(\.\d+)?\z/)
|
|
62
|
+
|
|
63
|
+
0.0
|
|
64
|
+
end
|
|
10
65
|
end
|
|
11
66
|
end
|
|
12
67
|
end
|
|
@@ -8,18 +8,32 @@ module Ruflet
|
|
|
8
8
|
"cupertinobutton" => "CupertinoButton",
|
|
9
9
|
"cupertino_filled_button" => "CupertinoFilledButton",
|
|
10
10
|
"cupertinofilledbutton" => "CupertinoFilledButton",
|
|
11
|
+
"cupertino_tinted_button" => "CupertinoTintedButton",
|
|
12
|
+
"cupertinotintedbutton" => "CupertinoTintedButton",
|
|
11
13
|
"cupertino_text_field" => "CupertinoTextField",
|
|
12
14
|
"cupertinotextfield" => "CupertinoTextField",
|
|
15
|
+
"cupertino_checkbox" => "CupertinoCheckbox",
|
|
16
|
+
"cupertinocheckbox" => "CupertinoCheckbox",
|
|
13
17
|
"cupertino_switch" => "CupertinoSwitch",
|
|
14
18
|
"cupertinoswitch" => "CupertinoSwitch",
|
|
15
19
|
"cupertino_slider" => "CupertinoSlider",
|
|
16
20
|
"cupertinoslider" => "CupertinoSlider",
|
|
21
|
+
"cupertino_radio" => "CupertinoRadio",
|
|
22
|
+
"cupertinoradio" => "CupertinoRadio",
|
|
17
23
|
"cupertino_alert_dialog" => "CupertinoAlertDialog",
|
|
18
24
|
"cupertinoalertdialog" => "CupertinoAlertDialog",
|
|
19
25
|
"cupertino_action_sheet" => "CupertinoActionSheet",
|
|
20
26
|
"cupertinoactionsheet" => "CupertinoActionSheet",
|
|
21
27
|
"cupertino_dialog_action" => "CupertinoDialogAction",
|
|
22
28
|
"cupertinodialogaction" => "CupertinoDialogAction",
|
|
29
|
+
"cupertino_bottom_sheet" => "CupertinoBottomSheet",
|
|
30
|
+
"cupertinobottomsheet" => "CupertinoBottomSheet",
|
|
31
|
+
"cupertino_picker" => "CupertinoPicker",
|
|
32
|
+
"cupertinopicker" => "CupertinoPicker",
|
|
33
|
+
"cupertino_date_picker" => "CupertinoDatePicker",
|
|
34
|
+
"cupertinodatepicker" => "CupertinoDatePicker",
|
|
35
|
+
"cupertino_timer_picker" => "CupertinoTimerPicker",
|
|
36
|
+
"cupertinotimerpicker" => "CupertinoTimerPicker",
|
|
23
37
|
"cupertino_navigation_bar" => "CupertinoNavigationBar",
|
|
24
38
|
"cupertinonavigationbar" => "CupertinoNavigationBar"
|
|
25
39
|
}.freeze
|
|
@@ -71,14 +71,17 @@ module Ruflet
|
|
|
71
71
|
|
|
72
72
|
def icon(**props) = build_widget(:icon, **props)
|
|
73
73
|
|
|
74
|
-
def image(src = nil, **props)
|
|
74
|
+
def image(src = nil, src_base64: nil, placeholder_src: nil, **props)
|
|
75
75
|
mapped = props.dup
|
|
76
|
-
mapped[:src] = src unless src.nil?
|
|
76
|
+
mapped[:src] = normalize_image_source(src) unless src.nil?
|
|
77
|
+
mapped[:src] = normalize_image_source(src_base64) if mapped[:src].nil? && !src_base64.nil?
|
|
78
|
+
mapped[:placeholder_src] = normalize_image_source(placeholder_src) unless placeholder_src.nil?
|
|
77
79
|
build_widget(:image, **mapped)
|
|
78
80
|
end
|
|
79
81
|
|
|
80
82
|
def app_bar(**props) = build_widget(:appbar, **props)
|
|
81
83
|
def appbar(**props) = app_bar(**props)
|
|
84
|
+
def url_launcher(**props) = build_widget(:url_launcher, **props)
|
|
82
85
|
def floating_action_button(**props) = build_widget(:floatingactionbutton, **props)
|
|
83
86
|
def floatingactionbutton(**props) = floating_action_button(**props)
|
|
84
87
|
def tabs(**props, &block) = build_widget(:tabs, **props, &block)
|
|
@@ -100,6 +103,12 @@ module Ruflet
|
|
|
100
103
|
|
|
101
104
|
private
|
|
102
105
|
|
|
106
|
+
def normalize_image_source(value)
|
|
107
|
+
return value unless value.is_a?(Array)
|
|
108
|
+
return value.pack("C*") if value.all? { |v| v.is_a?(Integer) }
|
|
109
|
+
value
|
|
110
|
+
end
|
|
111
|
+
|
|
103
112
|
# Flet container alignment expects a vector-like object ({x:, y:}),
|
|
104
113
|
# not a plain string. Keep common shorthand compatible.
|
|
105
114
|
def normalize_container_props(props)
|
|
@@ -52,7 +52,55 @@ module Ruflet
|
|
|
52
52
|
"navigationbar" => "NavigationBar",
|
|
53
53
|
"navigation_bar" => "NavigationBar",
|
|
54
54
|
"navigationbardestination" => "NavigationBarDestination",
|
|
55
|
-
"navigation_bar_destination" => "NavigationBarDestination"
|
|
55
|
+
"navigation_bar_destination" => "NavigationBarDestination",
|
|
56
|
+
"switch" => "Switch",
|
|
57
|
+
"slider" => "Slider",
|
|
58
|
+
"dropdown" => "DropdownM2",
|
|
59
|
+
"dropdownm2" => "DropdownM2",
|
|
60
|
+
"dropdown_m2" => "DropdownM2",
|
|
61
|
+
"option" => "Option",
|
|
62
|
+
"card" => "Card",
|
|
63
|
+
"banner" => "Banner",
|
|
64
|
+
"datepicker" => "DatePicker",
|
|
65
|
+
"date_picker" => "DatePicker",
|
|
66
|
+
"timepicker" => "TimePicker",
|
|
67
|
+
"time_picker" => "TimePicker",
|
|
68
|
+
"filledtonalbutton" => "FilledTonalButton",
|
|
69
|
+
"filled_tonal_button" => "FilledTonalButton",
|
|
70
|
+
"outlinedbutton" => "OutlinedButton",
|
|
71
|
+
"outlined_button" => "OutlinedButton",
|
|
72
|
+
"listtile" => "ListTile",
|
|
73
|
+
"list_tile" => "ListTile",
|
|
74
|
+
"progressbar" => "ProgressBar",
|
|
75
|
+
"progress_bar" => "ProgressBar",
|
|
76
|
+
"safearea" => "SafeArea",
|
|
77
|
+
"safe_area" => "SafeArea",
|
|
78
|
+
"canvas" => "Canvas",
|
|
79
|
+
"line" => "Line",
|
|
80
|
+
"service_registry" => "ServiceRegistry",
|
|
81
|
+
"url_launcher" => "UrlLauncher",
|
|
82
|
+
"audio" => "Audio",
|
|
83
|
+
"video" => "Video",
|
|
84
|
+
"flashlight" => "Flashlight",
|
|
85
|
+
"barchart" => "BarChart",
|
|
86
|
+
"barchartgroup" => "BarChartGroup",
|
|
87
|
+
"barchartrod" => "BarChartRod",
|
|
88
|
+
"barchartrodstackitem" => "BarChartRodStackItem",
|
|
89
|
+
"linechart" => "LineChart",
|
|
90
|
+
"linechartdata" => "LineChartData",
|
|
91
|
+
"linechartdatapoint" => "LineChartDataPoint",
|
|
92
|
+
"piechart" => "PieChart",
|
|
93
|
+
"piechartsection" => "PieChartSection",
|
|
94
|
+
"candlestickchart" => "CandlestickChart",
|
|
95
|
+
"candlestickchartspot" => "CandlestickChartSpot",
|
|
96
|
+
"radarchart" => "RadarChart",
|
|
97
|
+
"radarcharttitle" => "RadarChartTitle",
|
|
98
|
+
"radardataset" => "RadarDataSet",
|
|
99
|
+
"radardatasetentry" => "RadarDataSetEntry",
|
|
100
|
+
"scatterchart" => "ScatterChart",
|
|
101
|
+
"scatterchartspot" => "ScatterChartSpot",
|
|
102
|
+
"chartaxis" => "ChartAxis",
|
|
103
|
+
"chartaxislabel" => "ChartAxisLabel"
|
|
56
104
|
}.freeze
|
|
57
105
|
|
|
58
106
|
EVENT_PROPS = {
|
|
@@ -77,6 +125,21 @@ module Ruflet
|
|
|
77
125
|
on_horizontal_drag_start: "horizontal_drag_start",
|
|
78
126
|
on_horizontal_drag_update: "horizontal_drag_update",
|
|
79
127
|
on_horizontal_drag_end: "horizontal_drag_end",
|
|
128
|
+
on_tap_down: "tap_down",
|
|
129
|
+
on_long_press_start: "long_press_start",
|
|
130
|
+
on_right_pan_start: "right_pan_start",
|
|
131
|
+
on_event: "event",
|
|
132
|
+
on_load: "load",
|
|
133
|
+
on_loaded: "loaded",
|
|
134
|
+
on_enter_fullscreen: "enter_fullscreen",
|
|
135
|
+
on_exit_fullscreen: "exit_fullscreen",
|
|
136
|
+
on_duration_change: "duration_change",
|
|
137
|
+
on_position_change: "position_change",
|
|
138
|
+
on_state_change: "state_change",
|
|
139
|
+
on_seek_complete: "seek_complete",
|
|
140
|
+
on_complete: "complete",
|
|
141
|
+
on_track_change: "track_change",
|
|
142
|
+
on_error: "error",
|
|
80
143
|
on_accept: "accept",
|
|
81
144
|
on_will_accept: "will_accept",
|
|
82
145
|
on_accept_with_details: "accept_with_details",
|
|
@@ -74,6 +74,7 @@ module Ruflet
|
|
|
74
74
|
def cupertinodialogaction(**props) = control_delegate.cupertinodialogaction(**props)
|
|
75
75
|
def cupertino_navigation_bar(**props) = control_delegate.cupertino_navigation_bar(**props)
|
|
76
76
|
def cupertinonavigationbar(**props) = control_delegate.cupertinonavigationbar(**props)
|
|
77
|
+
def duration(**parts) = control_delegate.duration(**parts)
|
|
77
78
|
|
|
78
79
|
private
|
|
79
80
|
|
data/lib/ruflet_ui.rb
CHANGED
|
@@ -105,5 +105,7 @@ module Kernel
|
|
|
105
105
|
Ruflet::DSL
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
if Ruflet::UI::SharedControlForwarders.respond_to?(:instance_methods)
|
|
109
|
+
private(*Ruflet::UI::SharedControlForwarders.instance_methods(false))
|
|
110
|
+
end
|
|
109
111
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruflet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- AdamMusa
|
|
@@ -19,6 +19,7 @@ extra_rdoc_files: []
|
|
|
19
19
|
files:
|
|
20
20
|
- README.md
|
|
21
21
|
- lib/ruflet.rb
|
|
22
|
+
- lib/ruflet/manifest_compiler.rb
|
|
22
23
|
- lib/ruflet/version.rb
|
|
23
24
|
- lib/ruflet_protocol.rb
|
|
24
25
|
- lib/ruflet_protocol/ruflet/protocol.rb
|