ruflet_core 0.0.21 → 0.0.22
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/version.rb +1 -1
- data/lib/ruflet_ui/ruflet/dsl.rb +76 -0
- data/lib/ruflet_ui/ruflet/event.rb +3 -2
- data/lib/ruflet_ui/ruflet/events/gesture_events.rb +2 -1
- data/lib/ruflet_ui/ruflet/page.rb +242 -4
- data/lib/ruflet_ui/ruflet/ui/control_factory.rb +2 -0
- data/lib/ruflet_ui/ruflet/ui/control_methods.rb +4 -0
- data/lib/ruflet_ui/ruflet/ui/control_registry.rb +20 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheet_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheetaction_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactivityindicator_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoalertdialog_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoappbar_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobottomsheet_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocheckbox_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenu_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenuaction_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodatepicker_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodialogaction_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinofilledbutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinolisttile_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinonavigationbar_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinopicker_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoradio_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinosegmentedbutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslider_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslidingsegmentedbutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoswitch_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotextfield_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotimerpicker_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotintedbutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/materials/ad_controls.rb +45 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/animation_extension_controls.rb +29 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/chart_controls.rb +56 -279
- data/lib/ruflet_ui/ruflet/ui/controls/materials/code_editor_control.rb +42 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/color_picker_controls.rb +34 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/datatable2_controls.rb +41 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdownm2_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/materials/map_control.rb +80 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/ruflet_controls.rb +62 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/video_control.rb +1 -2
- data/lib/ruflet_ui/ruflet/ui/controls/materials/webview_control.rb +5 -30
- data/lib/ruflet_ui/ruflet/ui/controls/ruflet_controls.rb +60 -0
- data/lib/ruflet_ui/ruflet/ui/controls/shared/browsercontextmenu_control.rb +17 -0
- data/lib/ruflet_ui/ruflet/ui/controls/shared/ruflet_app_control.rb +3 -3
- data/lib/ruflet_ui/ruflet/ui/controls/shared/serviceregistry_control.rb +5 -1
- data/lib/ruflet_ui/ruflet/ui/cupertino_control_methods.rb +2 -0
- data/lib/ruflet_ui/ruflet/ui/material_control_methods.rb +110 -6
- data/lib/ruflet_ui/ruflet/ui/material_control_registry.rb +23 -8
- data/lib/ruflet_ui/ruflet/ui/platform_control_contracts.rb +392 -0
- data/lib/ruflet_ui/ruflet/ui/platform_control_methods.rb +35 -0
- data/lib/ruflet_ui/ruflet/ui/services/current_service_methods.rb +220 -0
- data/lib/ruflet_ui/ruflet/ui/services/ruflet/camera_control.rb +88 -0
- data/lib/ruflet_ui/ruflet/ui/services/ruflet_services.rb +4 -0
- data/lib/ruflet_ui/ruflet/ui/shared_control_forwarders.rb +75 -0
- metadata +9 -1
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "controls/ruflet_controls"
|
|
4
|
+
|
|
5
|
+
module Ruflet
|
|
6
|
+
module UI
|
|
7
|
+
# One Ruby protocol contract for controls whose visual implementation is
|
|
8
|
+
# selected by the Flet client. These schemas deliberately accept the union
|
|
9
|
+
# of the Material and Cupertino properties: Ruby describes intent and the
|
|
10
|
+
# platform renderer decides how that intent looks.
|
|
11
|
+
module PlatformControlContracts
|
|
12
|
+
module Components
|
|
13
|
+
class PlatformControl < Ruflet::Control
|
|
14
|
+
def initialize(id: nil, **props)
|
|
15
|
+
props = platform_defaults.merge(props)
|
|
16
|
+
validate_platform_props!(props)
|
|
17
|
+
compact = {}
|
|
18
|
+
props.each do |key, value|
|
|
19
|
+
raise ArgumentError, "unknown keyword: :#{key}" unless self.class::KEYWORDS.include?(key)
|
|
20
|
+
|
|
21
|
+
value = normalize_platform_prop(key, value)
|
|
22
|
+
compact[key] = value unless value.nil?
|
|
23
|
+
end
|
|
24
|
+
super(type: self.class::TYPE, id: id, **compact)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def platform_defaults = {}
|
|
30
|
+
def validate_platform_props!(_props); end
|
|
31
|
+
def normalize_platform_prop(_key, value) = value
|
|
32
|
+
|
|
33
|
+
def require_control_prop!(props, name)
|
|
34
|
+
value = props[name]
|
|
35
|
+
raise ArgumentError, "#{self.class::TYPE} requires #{name}" if value.nil?
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class ButtonControl < PlatformControl
|
|
40
|
+
TYPE = "button".freeze
|
|
41
|
+
WIRE = "Button".freeze
|
|
42
|
+
KEYWORDS = (
|
|
43
|
+
Controls::RufletComponents::ButtonControl::KEYWORDS +
|
|
44
|
+
Controls::RufletComponents::CupertinoButtonControl::KEYWORDS +
|
|
45
|
+
%i[default destructive]
|
|
46
|
+
).uniq.freeze
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class FilledButtonControl < PlatformControl
|
|
51
|
+
TYPE = "filledbutton".freeze
|
|
52
|
+
WIRE = "FilledButton".freeze
|
|
53
|
+
KEYWORDS = (
|
|
54
|
+
Controls::RufletComponents::FilledButtonControl::KEYWORDS +
|
|
55
|
+
Controls::RufletComponents::CupertinoFilledButtonControl::KEYWORDS
|
|
56
|
+
).uniq.freeze
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def platform_defaults = { autofocus: false, clip_behavior: "none" }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class FilledTonalButtonControl < PlatformControl
|
|
64
|
+
TYPE = "filledtonalbutton".freeze
|
|
65
|
+
WIRE = "FilledTonalButton".freeze
|
|
66
|
+
KEYWORDS = (
|
|
67
|
+
Controls::RufletComponents::FilledTonalButtonControl::KEYWORDS +
|
|
68
|
+
Controls::RufletComponents::CupertinoTintedButtonControl::KEYWORDS
|
|
69
|
+
).uniq.freeze
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def platform_defaults = { autofocus: false, clip_behavior: "none" }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class OutlinedButtonControl < PlatformControl
|
|
77
|
+
TYPE = "outlinedbutton".freeze
|
|
78
|
+
WIRE = "OutlinedButton".freeze
|
|
79
|
+
KEYWORDS = (
|
|
80
|
+
Controls::RufletComponents::OutlinedButtonControl::KEYWORDS +
|
|
81
|
+
Controls::RufletComponents::CupertinoButtonControl::KEYWORDS
|
|
82
|
+
).uniq.freeze
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def platform_defaults = { autofocus: false, clip_behavior: "none" }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class TextButtonControl < PlatformControl
|
|
90
|
+
TYPE = "textbutton".freeze
|
|
91
|
+
WIRE = "TextButton".freeze
|
|
92
|
+
KEYWORDS = (
|
|
93
|
+
Controls::RufletComponents::TextButtonControl::KEYWORDS +
|
|
94
|
+
Controls::RufletComponents::CupertinoButtonControl::KEYWORDS
|
|
95
|
+
).uniq.freeze
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
def platform_defaults = { autofocus: false, clip_behavior: "none" }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class TextFieldControl < PlatformControl
|
|
103
|
+
TYPE = "textfield".freeze
|
|
104
|
+
WIRE = "TextField".freeze
|
|
105
|
+
KEYWORDS = (
|
|
106
|
+
Controls::RufletComponents::TextFieldControl::KEYWORDS +
|
|
107
|
+
Controls::RufletComponents::CupertinoTextFieldControl::KEYWORDS
|
|
108
|
+
).uniq.freeze
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class CheckboxControl < PlatformControl
|
|
112
|
+
TYPE = "checkbox".freeze
|
|
113
|
+
WIRE = "Checkbox".freeze
|
|
114
|
+
KEYWORDS = (
|
|
115
|
+
Controls::RufletComponents::CheckboxControl::KEYWORDS +
|
|
116
|
+
Controls::RufletComponents::CupertinoCheckboxControl::KEYWORDS
|
|
117
|
+
).uniq.freeze
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
class RadioControl < PlatformControl
|
|
121
|
+
TYPE = "radio".freeze
|
|
122
|
+
WIRE = "Radio".freeze
|
|
123
|
+
KEYWORDS = (
|
|
124
|
+
Controls::RufletComponents::RadioControl::KEYWORDS +
|
|
125
|
+
Controls::RufletComponents::CupertinoRadioControl::KEYWORDS
|
|
126
|
+
).uniq.freeze
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class SliderControl < PlatformControl
|
|
130
|
+
TYPE = "slider".freeze
|
|
131
|
+
WIRE = "Slider".freeze
|
|
132
|
+
KEYWORDS = (
|
|
133
|
+
Controls::RufletComponents::SliderControl::KEYWORDS +
|
|
134
|
+
Controls::RufletComponents::CupertinoSliderControl::KEYWORDS
|
|
135
|
+
).uniq.freeze
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
class SwitchControl < PlatformControl
|
|
139
|
+
TYPE = "switch".freeze
|
|
140
|
+
WIRE = "Switch".freeze
|
|
141
|
+
KEYWORDS = (
|
|
142
|
+
Controls::RufletComponents::SwitchControl::KEYWORDS +
|
|
143
|
+
Controls::RufletComponents::CupertinoSwitchControl::KEYWORDS
|
|
144
|
+
).uniq.freeze
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
class AlertDialogControl < PlatformControl
|
|
148
|
+
TYPE = "alertdialog".freeze
|
|
149
|
+
WIRE = "AlertDialog".freeze
|
|
150
|
+
KEYWORDS = (
|
|
151
|
+
Controls::RufletComponents::AlertDialogControl::KEYWORDS +
|
|
152
|
+
%i[inset_animation]
|
|
153
|
+
).uniq.freeze
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
class BottomSheetControl < PlatformControl
|
|
157
|
+
TYPE = "bottomsheet".freeze
|
|
158
|
+
WIRE = "BottomSheet".freeze
|
|
159
|
+
KEYWORDS = %i[
|
|
160
|
+
adaptive animation_style badge barrier_color bgcolor clip_behavior col content data
|
|
161
|
+
disabled dismissible draggable elevation expand expand_loose fullscreen height key
|
|
162
|
+
maintain_bottom_view_insets_padding modal opacity open padding rtl scrollable shape
|
|
163
|
+
show_drag_handle size_constraints tooltip use_safe_area visible on_dismiss
|
|
164
|
+
].freeze
|
|
165
|
+
|
|
166
|
+
private
|
|
167
|
+
|
|
168
|
+
def validate_platform_props!(props) = require_control_prop!(props, :content)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
class AppBarControl < PlatformControl
|
|
172
|
+
TYPE = "appbar".freeze
|
|
173
|
+
WIRE = "AppBar".freeze
|
|
174
|
+
KEYWORDS = (
|
|
175
|
+
Controls::RufletComponents::AppBarControl::KEYWORDS + %i[
|
|
176
|
+
automatic_background_visibility automatically_imply_title border brightness
|
|
177
|
+
enable_background_filter_blur large padding previous_page_title trailing
|
|
178
|
+
transition_between_routes
|
|
179
|
+
]
|
|
180
|
+
).uniq.freeze
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
class ListTileControl < PlatformControl
|
|
184
|
+
TYPE = "listtile".freeze
|
|
185
|
+
WIRE = "ListTile".freeze
|
|
186
|
+
KEYWORDS = (
|
|
187
|
+
Controls::RufletComponents::ListTileControl::KEYWORDS +
|
|
188
|
+
Controls::RufletComponents::CupertinoListTileControl::KEYWORDS
|
|
189
|
+
).uniq.freeze
|
|
190
|
+
|
|
191
|
+
private
|
|
192
|
+
|
|
193
|
+
def validate_platform_props!(props) = require_control_prop!(props, :title)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
class NavigationBarControl < PlatformControl
|
|
197
|
+
TYPE = "navigationbar".freeze
|
|
198
|
+
WIRE = "NavigationBar".freeze
|
|
199
|
+
KEYWORDS = (
|
|
200
|
+
Controls::RufletComponents::NavigationBarControl::KEYWORDS +
|
|
201
|
+
Controls::RufletComponents::CupertinoNavigationBarControl::KEYWORDS
|
|
202
|
+
).uniq.freeze
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
class ProgressRingControl < PlatformControl
|
|
206
|
+
TYPE = "progressring".freeze
|
|
207
|
+
WIRE = "ProgressRing".freeze
|
|
208
|
+
KEYWORDS = (
|
|
209
|
+
Controls::RufletComponents::ProgressRingControl::KEYWORDS +
|
|
210
|
+
Controls::RufletComponents::CupertinoActivityIndicatorControl::KEYWORDS
|
|
211
|
+
).uniq.freeze
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
class SegmentedButtonControl < PlatformControl
|
|
215
|
+
TYPE = "segmentedbutton".freeze
|
|
216
|
+
WIRE = "SegmentedButton".freeze
|
|
217
|
+
KEYWORDS = (
|
|
218
|
+
Controls::RufletComponents::SegmentedButtonControl::KEYWORDS +
|
|
219
|
+
Controls::RufletComponents::CupertinoSegmentedButtonControl::KEYWORDS +
|
|
220
|
+
Controls::RufletComponents::CupertinoSlidingSegmentedButtonControl::KEYWORDS
|
|
221
|
+
).uniq.freeze
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
class ContextMenuControl < PlatformControl
|
|
225
|
+
TYPE = "contextmenu".freeze
|
|
226
|
+
WIRE = "ContextMenu".freeze
|
|
227
|
+
KEYWORDS = (
|
|
228
|
+
Controls::RufletComponents::ContextMenuControl::KEYWORDS +
|
|
229
|
+
%i[actions adaptive enable_haptic_feedback]
|
|
230
|
+
).uniq.freeze
|
|
231
|
+
|
|
232
|
+
def open(position: nil, timeout: 10, on_result: nil)
|
|
233
|
+
args = {}
|
|
234
|
+
args["position"] = stringify_hash_keys(position) unless position.nil?
|
|
235
|
+
runtime_page&.invoke(self, "open", args: args, timeout: timeout, on_result: on_result)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
private
|
|
239
|
+
|
|
240
|
+
def validate_platform_props!(props) = require_control_prop!(props, :content)
|
|
241
|
+
|
|
242
|
+
def stringify_hash_keys(value)
|
|
243
|
+
return value.map { |item| stringify_hash_keys(item) } if value.is_a?(Array)
|
|
244
|
+
if value.is_a?(Hash)
|
|
245
|
+
return value.each_with_object({}) do |(key, child), result|
|
|
246
|
+
result[key.to_s] = stringify_hash_keys(child)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
value
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
class ContextMenuActionControl < PlatformControl
|
|
255
|
+
TYPE = "contextmenuaction".freeze
|
|
256
|
+
WIRE = "ContextMenuAction".freeze
|
|
257
|
+
KEYWORDS = %i[
|
|
258
|
+
adaptive align animate_align animate_margin animate_offset animate_opacity
|
|
259
|
+
animate_position animate_rotation animate_scale animate_size aspect_ratio badge bottom
|
|
260
|
+
checked col content data default destructive disabled expand expand_loose height icon key
|
|
261
|
+
left margin mouse_cursor offset opacity right rotate rtl scale size_change_interval
|
|
262
|
+
tooltip top trailing_icon value visible width on_animation_end on_click on_size_change
|
|
263
|
+
].freeze
|
|
264
|
+
|
|
265
|
+
private
|
|
266
|
+
|
|
267
|
+
def validate_platform_props!(props) = require_control_prop!(props, :content)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
class ActionSheetControl < PlatformControl
|
|
271
|
+
TYPE = "actionsheet".freeze
|
|
272
|
+
WIRE = "ActionSheet".freeze
|
|
273
|
+
KEYWORDS = Controls::RufletComponents::CupertinoActionSheetControl::KEYWORDS
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
class ActionSheetActionControl < PlatformControl
|
|
277
|
+
TYPE = "actionsheetaction".freeze
|
|
278
|
+
WIRE = "ActionSheetAction".freeze
|
|
279
|
+
KEYWORDS = Controls::RufletComponents::CupertinoActionSheetActionControl::KEYWORDS
|
|
280
|
+
|
|
281
|
+
private
|
|
282
|
+
|
|
283
|
+
def validate_platform_props!(props) = require_control_prop!(props, :content)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
class DatePickerControl < PlatformControl
|
|
287
|
+
TYPE = "datepicker".freeze
|
|
288
|
+
WIRE = "DatePicker".freeze
|
|
289
|
+
KEYWORDS = (
|
|
290
|
+
Controls::RufletComponents::DatePickerControl::KEYWORDS +
|
|
291
|
+
Controls::RufletComponents::CupertinoDatePickerControl::KEYWORDS
|
|
292
|
+
).uniq.freeze
|
|
293
|
+
|
|
294
|
+
private
|
|
295
|
+
|
|
296
|
+
def normalize_platform_prop(key, value)
|
|
297
|
+
return value unless %i[value first_date last_date current_date].include?(key)
|
|
298
|
+
|
|
299
|
+
Ruflet::Protocol.date_time(value)
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
class PickerControl < PlatformControl
|
|
304
|
+
TYPE = "picker".freeze
|
|
305
|
+
WIRE = "Picker".freeze
|
|
306
|
+
KEYWORDS = Controls::RufletComponents::CupertinoPickerControl::KEYWORDS
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
class TimerPickerControl < PlatformControl
|
|
310
|
+
TYPE = "timerpicker".freeze
|
|
311
|
+
WIRE = "TimerPicker".freeze
|
|
312
|
+
KEYWORDS = Controls::RufletComponents::CupertinoTimerPickerControl::KEYWORDS
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
class DropdownControl < PlatformControl
|
|
316
|
+
TYPE = "dropdown".freeze
|
|
317
|
+
WIRE = "Dropdown".freeze
|
|
318
|
+
KEYWORDS = (
|
|
319
|
+
Controls::RufletComponents::DropdownControl::KEYWORDS +
|
|
320
|
+
Controls::RufletComponents::Dropdown2Control::KEYWORDS
|
|
321
|
+
).uniq.freeze
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
CANONICAL_CLASS_MAP = {
|
|
326
|
+
%w[button elevated_button elevatedbutton] => Components::ButtonControl,
|
|
327
|
+
%w[filled_button filledbutton] => Components::FilledButtonControl,
|
|
328
|
+
%w[filled_tonal_button filledtonalbutton] => Components::FilledTonalButtonControl,
|
|
329
|
+
%w[outlined_button outlinedbutton] => Components::OutlinedButtonControl,
|
|
330
|
+
%w[text_button textbutton] => Components::TextButtonControl,
|
|
331
|
+
%w[text_field textfield] => Components::TextFieldControl,
|
|
332
|
+
%w[checkbox] => Components::CheckboxControl,
|
|
333
|
+
%w[radio] => Components::RadioControl,
|
|
334
|
+
%w[slider] => Components::SliderControl,
|
|
335
|
+
%w[switch] => Components::SwitchControl,
|
|
336
|
+
%w[alert_dialog alertdialog] => Components::AlertDialogControl,
|
|
337
|
+
%w[bottom_sheet bottomsheet] => Components::BottomSheetControl,
|
|
338
|
+
%w[app_bar appbar] => Components::AppBarControl,
|
|
339
|
+
%w[list_tile listtile] => Components::ListTileControl,
|
|
340
|
+
%w[navigation_bar navigationbar] => Components::NavigationBarControl,
|
|
341
|
+
%w[progress_ring progressring] => Components::ProgressRingControl,
|
|
342
|
+
%w[segmented_button segmentedbutton] => Components::SegmentedButtonControl,
|
|
343
|
+
%w[context_menu contextmenu] => Components::ContextMenuControl,
|
|
344
|
+
%w[context_menu_action contextmenuaction] => Components::ContextMenuActionControl,
|
|
345
|
+
%w[action_sheet actionsheet] => Components::ActionSheetControl,
|
|
346
|
+
%w[action_sheet_action actionsheetaction] => Components::ActionSheetActionControl,
|
|
347
|
+
%w[date_picker datepicker] => Components::DatePickerControl,
|
|
348
|
+
%w[picker] => Components::PickerControl,
|
|
349
|
+
%w[timer_picker timerpicker] => Components::TimerPickerControl,
|
|
350
|
+
%w[dropdown dropdown_m2 dropdownm2] => Components::DropdownControl,
|
|
351
|
+
}.each_with_object({}) do |(names, klass), map|
|
|
352
|
+
names.each { |name| map[name] = klass }
|
|
353
|
+
end.freeze
|
|
354
|
+
|
|
355
|
+
LEGACY_CLASS_MAP = {
|
|
356
|
+
%w[cupertino_button cupertinobutton] => Controls::RufletComponents::CupertinoButtonControl,
|
|
357
|
+
%w[cupertino_filled_button cupertinofilledbutton] => Controls::RufletComponents::CupertinoFilledButtonControl,
|
|
358
|
+
%w[cupertino_tinted_button cupertinotintedbutton] => Controls::RufletComponents::CupertinoTintedButtonControl,
|
|
359
|
+
%w[cupertino_text_field cupertinotextfield] => Controls::RufletComponents::CupertinoTextFieldControl,
|
|
360
|
+
%w[cupertino_checkbox cupertinocheckbox] => Controls::RufletComponents::CupertinoCheckboxControl,
|
|
361
|
+
%w[cupertino_radio cupertinoradio] => Controls::RufletComponents::CupertinoRadioControl,
|
|
362
|
+
%w[cupertino_slider cupertinoslider] => Controls::RufletComponents::CupertinoSliderControl,
|
|
363
|
+
%w[cupertino_switch cupertinoswitch] => Controls::RufletComponents::CupertinoSwitchControl,
|
|
364
|
+
%w[cupertino_alert_dialog cupertinoalertdialog] => Controls::RufletComponents::CupertinoAlertDialogControl,
|
|
365
|
+
%w[cupertino_bottom_sheet cupertinobottomsheet] => Controls::RufletComponents::CupertinoBottomSheetControl,
|
|
366
|
+
%w[cupertino_app_bar cupertinoappbar] => Controls::RufletComponents::CupertinoAppBarControl,
|
|
367
|
+
%w[cupertino_list_tile cupertinolisttile] => Controls::RufletComponents::CupertinoListTileControl,
|
|
368
|
+
%w[cupertino_navigation_bar cupertinonavigationbar] => Controls::RufletComponents::CupertinoNavigationBarControl,
|
|
369
|
+
%w[cupertino_activity_indicator cupertinoactivityindicator] => Controls::RufletComponents::CupertinoActivityIndicatorControl,
|
|
370
|
+
%w[cupertino_segmented_button cupertinosegmentedbutton] => Controls::RufletComponents::CupertinoSegmentedButtonControl,
|
|
371
|
+
%w[cupertino_sliding_segmented_button cupertinoslidingsegmentedbutton] => Controls::RufletComponents::CupertinoSlidingSegmentedButtonControl,
|
|
372
|
+
%w[cupertino_context_menu cupertinocontextmenu] => Controls::RufletComponents::CupertinoContextMenuControl,
|
|
373
|
+
%w[cupertino_context_menu_action cupertinocontextmenuaction] => Controls::RufletComponents::CupertinoContextMenuActionControl,
|
|
374
|
+
%w[cupertino_action_sheet cupertinoactionsheet] => Controls::RufletComponents::CupertinoActionSheetControl,
|
|
375
|
+
%w[cupertino_action_sheet_action cupertinoactionsheetaction] => Controls::RufletComponents::CupertinoActionSheetActionControl,
|
|
376
|
+
%w[cupertino_date_picker cupertinodatepicker] => Controls::RufletComponents::CupertinoDatePickerControl,
|
|
377
|
+
%w[cupertino_picker cupertinopicker] => Controls::RufletComponents::CupertinoPickerControl,
|
|
378
|
+
%w[cupertino_timer_picker cupertinotimerpicker] => Controls::RufletComponents::CupertinoTimerPickerControl,
|
|
379
|
+
%w[cupertino_dialog_action cupertinodialogaction] => Controls::RufletComponents::CupertinoDialogActionControl,
|
|
380
|
+
%w[popup_menu_item popupmenuitem] => Controls::RufletComponents::PopupMenuItemControl
|
|
381
|
+
}.each_with_object({}) do |(names, klass), map|
|
|
382
|
+
names.each { |name| map[name] = klass }
|
|
383
|
+
end.freeze
|
|
384
|
+
|
|
385
|
+
CLASS_MAP = CANONICAL_CLASS_MAP.merge(LEGACY_CLASS_MAP).freeze
|
|
386
|
+
|
|
387
|
+
TYPE_MAP = CLASS_MAP.each_with_object({}) do |(name, klass), map|
|
|
388
|
+
map[name] = klass::WIRE
|
|
389
|
+
end.freeze
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ruflet
|
|
4
|
+
module UI
|
|
5
|
+
# Canonical DSL entry points for controls whose renderer is selected by
|
|
6
|
+
# the Flet client. There is no design-system choice in this API.
|
|
7
|
+
module PlatformControlMethods
|
|
8
|
+
def context_menu_action(content = nil, **props)
|
|
9
|
+
mapped = props.dup
|
|
10
|
+
mapped[:content] = content unless content.nil?
|
|
11
|
+
build_widget(:contextmenuaction, **mapped)
|
|
12
|
+
end
|
|
13
|
+
def contextmenuaction(content = nil, **props) = context_menu_action(content, **props)
|
|
14
|
+
|
|
15
|
+
def action_sheet(**props) = build_widget(:actionsheet, **props)
|
|
16
|
+
def actionsheet(**props) = action_sheet(**props)
|
|
17
|
+
|
|
18
|
+
def action_sheet_action(content = nil, **props)
|
|
19
|
+
mapped = props.dup
|
|
20
|
+
mapped[:content] = content unless content.nil?
|
|
21
|
+
build_widget(:actionsheetaction, **mapped)
|
|
22
|
+
end
|
|
23
|
+
def actionsheetaction(content = nil, **props) = action_sheet_action(content, **props)
|
|
24
|
+
|
|
25
|
+
def picker(children = nil, **props)
|
|
26
|
+
mapped = props.dup
|
|
27
|
+
mapped[:controls] = children unless children.nil?
|
|
28
|
+
build_widget(:picker, **mapped)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def timer_picker(**props) = build_widget(:timerpicker, **props)
|
|
32
|
+
def timerpicker(**props) = timer_picker(**props)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ruflet
|
|
4
|
+
module UI
|
|
5
|
+
module Services
|
|
6
|
+
module CurrentServiceMethods
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def invoke_service_method(method_name, args: nil, timeout: 10, on_result: nil)
|
|
10
|
+
runtime_page&.invoke(self, method_name, args: args, timeout: timeout, on_result: on_result)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def service_args(values)
|
|
14
|
+
values.each_with_object({}) do |(key, value), result|
|
|
15
|
+
result[key.to_s] = service_value(value, key.to_s) unless value.nil?
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def service_value(value, parent_key = nil)
|
|
20
|
+
if parent_key == "data" && byte_array?(value)
|
|
21
|
+
return value.pack("C*").b
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
case value
|
|
25
|
+
when Array
|
|
26
|
+
value.map { |item| service_value(item) }
|
|
27
|
+
when Hash
|
|
28
|
+
value.each_with_object({}) do |(key, item), result|
|
|
29
|
+
result[key.to_s] = service_value(item, key.to_s) unless item.nil?
|
|
30
|
+
end
|
|
31
|
+
when Symbol
|
|
32
|
+
value.to_s
|
|
33
|
+
else
|
|
34
|
+
value.respond_to?(:to_h) ? service_value(value.to_h) : value
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def byte_array?(value)
|
|
39
|
+
value.is_a?(Array) && value.all? { |item| item.is_a?(Integer) && item.between?(0, 255) }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module NoArgumentServiceMethods
|
|
44
|
+
def define_no_argument_service_methods(*method_names)
|
|
45
|
+
method_names.each do |method_name|
|
|
46
|
+
define_method(method_name) do |timeout: 10, on_result: nil|
|
|
47
|
+
invoke_service_method(method_name, timeout: timeout, on_result: on_result)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
components = RufletServicesComponents
|
|
54
|
+
|
|
55
|
+
[
|
|
56
|
+
[components::BatteryControl, %w[get_battery_level get_battery_state is_in_battery_save_mode]],
|
|
57
|
+
[components::ConnectivityControl, %w[get_connectivity]],
|
|
58
|
+
[components::FlashlightControl, %w[on off is_available]],
|
|
59
|
+
[components::HapticFeedbackControl, %w[heavy_impact light_impact medium_impact vibrate selection_click]],
|
|
60
|
+
[components::StoragePathsControl, %w[
|
|
61
|
+
get_application_cache_directory get_application_documents_directory
|
|
62
|
+
get_application_support_directory get_downloads_directory
|
|
63
|
+
get_external_cache_directories get_external_storage_directories
|
|
64
|
+
get_library_directory get_external_storage_directory
|
|
65
|
+
get_temporary_directory get_console_log_filename
|
|
66
|
+
]],
|
|
67
|
+
[components::WakelockControl, %w[enable disable is_enabled]]
|
|
68
|
+
].each do |klass, method_names|
|
|
69
|
+
klass.include(CurrentServiceMethods)
|
|
70
|
+
klass.extend(NoArgumentServiceMethods)
|
|
71
|
+
klass.define_no_argument_service_methods(*method_names)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class RufletServicesComponents::FilePickerControl
|
|
75
|
+
include CurrentServiceMethods
|
|
76
|
+
|
|
77
|
+
def upload(files, timeout: 10, on_result: nil)
|
|
78
|
+
invoke_service_method("upload", args: { "files" => service_value(files) }, timeout: timeout, on_result: on_result)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def get_directory_path(dialog_title: nil, initial_directory: nil, timeout: 10, on_result: nil)
|
|
82
|
+
invoke_service_method("get_directory_path", args: service_args(dialog_title: dialog_title, initial_directory: initial_directory), timeout: timeout, on_result: on_result)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def save_file(dialog_title: nil, file_name: nil, initial_directory: nil, file_type: :any,
|
|
86
|
+
allowed_extensions: nil, src_bytes: nil, timeout: 10, on_result: nil)
|
|
87
|
+
args = service_args(
|
|
88
|
+
dialog_title: dialog_title,
|
|
89
|
+
file_name: file_name,
|
|
90
|
+
initial_directory: initial_directory,
|
|
91
|
+
file_type: file_type,
|
|
92
|
+
allowed_extensions: allowed_extensions
|
|
93
|
+
)
|
|
94
|
+
args["src_bytes"] = src_bytes.pack("C*").b if byte_array?(src_bytes)
|
|
95
|
+
args["src_bytes"] = src_bytes unless src_bytes.nil? || byte_array?(src_bytes)
|
|
96
|
+
invoke_service_method("save_file", args: args, timeout: timeout, on_result: on_result)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def pick_files(dialog_title: nil, initial_directory: nil, file_type: :any,
|
|
100
|
+
allowed_extensions: nil, allow_multiple: false, with_data: false,
|
|
101
|
+
timeout: 10, on_result: nil)
|
|
102
|
+
invoke_service_method(
|
|
103
|
+
"pick_files",
|
|
104
|
+
args: service_args(
|
|
105
|
+
dialog_title: dialog_title,
|
|
106
|
+
initial_directory: initial_directory,
|
|
107
|
+
file_type: file_type,
|
|
108
|
+
allowed_extensions: allowed_extensions,
|
|
109
|
+
allow_multiple: allow_multiple,
|
|
110
|
+
with_data: with_data
|
|
111
|
+
),
|
|
112
|
+
timeout: timeout,
|
|
113
|
+
on_result: on_result
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class RufletServicesComponents::ScreenBrightnessControl
|
|
119
|
+
include CurrentServiceMethods
|
|
120
|
+
|
|
121
|
+
%w[
|
|
122
|
+
get_system_screen_brightness can_change_system_screen_brightness
|
|
123
|
+
get_application_screen_brightness reset_application_screen_brightness
|
|
124
|
+
is_animate is_auto_reset
|
|
125
|
+
].each do |method_name|
|
|
126
|
+
define_method(method_name) do |timeout: 10, on_result: nil|
|
|
127
|
+
invoke_service_method(method_name, timeout: timeout, on_result: on_result)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def set_system_screen_brightness(brightness, timeout: 10, on_result: nil)
|
|
132
|
+
invoke_service_method("set_system_screen_brightness", args: { "brightness" => brightness }, timeout: timeout, on_result: on_result)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def set_application_screen_brightness(brightness, timeout: 10, on_result: nil)
|
|
136
|
+
invoke_service_method("set_application_screen_brightness", args: { "brightness" => brightness }, timeout: timeout, on_result: on_result)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def set_animate(animate, timeout: 10, on_result: nil)
|
|
140
|
+
invoke_service_method("set_animate", args: { "animate" => animate }, timeout: timeout, on_result: on_result)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def set_auto_reset(auto_reset, timeout: 10, on_result: nil)
|
|
144
|
+
invoke_service_method("set_auto_reset", args: { "auto_reset" => auto_reset }, timeout: timeout, on_result: on_result)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
class RufletServicesComponents::ShareControl
|
|
149
|
+
include CurrentServiceMethods
|
|
150
|
+
|
|
151
|
+
def share_text(text, title: nil, subject: nil, preview_thumbnail: nil,
|
|
152
|
+
share_position_origin: nil, download_fallback_enabled: true,
|
|
153
|
+
mail_to_fallback_enabled: true, excluded_cupertino_activities: nil,
|
|
154
|
+
timeout: 10, on_result: nil)
|
|
155
|
+
invoke_service_method(
|
|
156
|
+
"share_text",
|
|
157
|
+
args: service_args(
|
|
158
|
+
text: text, title: title, subject: subject, preview_thumbnail: preview_thumbnail,
|
|
159
|
+
share_position_origin: share_position_origin,
|
|
160
|
+
download_fallback_enabled: download_fallback_enabled,
|
|
161
|
+
mail_to_fallback_enabled: mail_to_fallback_enabled,
|
|
162
|
+
excluded_cupertino_activities: excluded_cupertino_activities
|
|
163
|
+
),
|
|
164
|
+
timeout: timeout,
|
|
165
|
+
on_result: on_result
|
|
166
|
+
)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def share_uri(uri, share_position_origin: nil, excluded_cupertino_activities: nil, timeout: 10, on_result: nil)
|
|
170
|
+
invoke_service_method("share_uri", args: service_args(uri: uri, share_position_origin: share_position_origin, excluded_cupertino_activities: excluded_cupertino_activities), timeout: timeout, on_result: on_result)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def share_files(files, title: nil, text: nil, subject: nil, preview_thumbnail: nil,
|
|
174
|
+
share_position_origin: nil, download_fallback_enabled: true,
|
|
175
|
+
mail_to_fallback_enabled: true, excluded_cupertino_activities: nil,
|
|
176
|
+
timeout: 10, on_result: nil)
|
|
177
|
+
invoke_service_method(
|
|
178
|
+
"share_files",
|
|
179
|
+
args: service_args(
|
|
180
|
+
files: files, title: title, text: text, subject: subject,
|
|
181
|
+
preview_thumbnail: preview_thumbnail, share_position_origin: share_position_origin,
|
|
182
|
+
download_fallback_enabled: download_fallback_enabled,
|
|
183
|
+
mail_to_fallback_enabled: mail_to_fallback_enabled,
|
|
184
|
+
excluded_cupertino_activities: excluded_cupertino_activities
|
|
185
|
+
),
|
|
186
|
+
timeout: timeout,
|
|
187
|
+
on_result: on_result
|
|
188
|
+
)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
class RufletServicesComponents::SharedPreferencesControl
|
|
193
|
+
include CurrentServiceMethods
|
|
194
|
+
|
|
195
|
+
def set(key, value, timeout: 10, on_result: nil) = invoke_service_method("set", args: { "key" => key, "value" => service_value(value) }, timeout: timeout, on_result: on_result)
|
|
196
|
+
def get(key, timeout: 10, on_result: nil) = invoke_service_method("get", args: { "key" => key }, timeout: timeout, on_result: on_result)
|
|
197
|
+
def contains_key(key, timeout: 10, on_result: nil) = invoke_service_method("contains_key", args: { "key" => key }, timeout: timeout, on_result: on_result)
|
|
198
|
+
def remove(key, timeout: 10, on_result: nil) = invoke_service_method("remove", args: { "key" => key }, timeout: timeout, on_result: on_result)
|
|
199
|
+
def get_keys(key_prefix, timeout: 10, on_result: nil) = invoke_service_method("get_keys", args: { "key_prefix" => key_prefix }, timeout: timeout, on_result: on_result)
|
|
200
|
+
def clear(timeout: 10, on_result: nil) = invoke_service_method("clear", timeout: timeout, on_result: on_result)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
class RufletServicesComponents::UrlLauncherControl
|
|
204
|
+
include CurrentServiceMethods
|
|
205
|
+
|
|
206
|
+
def launch_url(url, mode: :platform_default, web_view_configuration: nil,
|
|
207
|
+
browser_configuration: nil, web_only_window_name: nil,
|
|
208
|
+
timeout: 10, on_result: nil)
|
|
209
|
+
invoke_service_method("launch_url", args: service_args(url: url, mode: mode, web_view_configuration: web_view_configuration, browser_configuration: browser_configuration, web_only_window_name: web_only_window_name), timeout: timeout, on_result: on_result)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def can_launch_url(url, timeout: 10, on_result: nil) = invoke_service_method("can_launch_url", args: { "url" => url.to_s }, timeout: timeout, on_result: on_result)
|
|
213
|
+
def close_in_app_web_view(timeout: 10, on_result: nil) = invoke_service_method("close_in_app_web_view", timeout: timeout, on_result: on_result)
|
|
214
|
+
def open_window(url, title: nil, width: nil, height: nil, timeout: 10, on_result: nil) = invoke_service_method("open_window", args: service_args(url: url, title: title, width: width, height: height), timeout: timeout, on_result: on_result)
|
|
215
|
+
def supports_launch_mode(mode, timeout: 10, on_result: nil) = invoke_service_method("supports_launch_mode", args: { "mode" => service_value(mode) }, timeout: timeout, on_result: on_result)
|
|
216
|
+
def supports_close_for_launch_mode(mode, timeout: 10, on_result: nil) = invoke_service_method("supports_close_for_launch_mode", args: { "mode" => service_value(mode) }, timeout: timeout, on_result: on_result)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|