ruflet 0.0.5 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f114a59fe4013e5313b51fc7b8b3373dfa7120e57422bc33abb2e224f9724d6
4
- data.tar.gz: fe0b491c3eff667a72c31521209953a2f7ba8249c1d16f6ec9ac08243099f850
3
+ metadata.gz: 50d9722e6751b03441e1b205a2c52c7dd2e24d3a20c9b65aa75bd18e0b07b99d
4
+ data.tar.gz: b4cf12770851ef43aee2331aabb1a57f0bf521ed6fbc769fe61d6beb0378eaef
5
5
  SHA512:
6
- metadata.gz: cbf26f1c4752d3fdd13600ff8b0bd305e3e669165c9cda9d094d4e4687f801adcb1df015230a509c016f8305f195c32459af74eeacdc8829475f62ac8c7af591
7
- data.tar.gz: a59f249b3b71255a4b499e8e87c69216c3e61d50c974a786cc1d926b7d502b500effe4161b5c2d8c3c384078ead1cfe1194106c872ca4a17bdafb05f180e36f7
6
+ metadata.gz: d35da0d4a41493d8a6dced4aac0a6ab8491aef7588c2ef69dd42e12255921fbf9d62008a9c31f717a1eac7e4b44ce73b6e4d01769a07775803a60c58f6b96530
7
+ data.tar.gz: dbaff1a82f3dcdb9a4d5fbb1a06e9620282560a52ec3032b08ef8008809592656dcae0fa0dede4fc0f7a37b8b9e742066304b7713df85cbb2dfc41be856696e1
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ruflet
4
- VERSION = "0.0.5" unless const_defined?(:VERSION)
4
+ VERSION = "0.0.7" unless const_defined?(:VERSION)
5
5
  end
@@ -40,6 +40,8 @@ module Ruflet
40
40
  def center(**props, &block) = _pending_app.center(**props, &block)
41
41
  def row(**props, &block) = _pending_app.row(**props, &block)
42
42
  def stack(**props, &block) = _pending_app.stack(**props, &block)
43
+ def grid_view(**props, &block) = _pending_app.grid_view(**props, &block)
44
+ def gridview(**props, &block) = _pending_app.gridview(**props, &block)
43
45
  def container(**props, &block) = _pending_app.container(**props, &block)
44
46
  def gesture_detector(**props, &block) = _pending_app.gesture_detector(**props, &block)
45
47
  def gesturedetector(**props, &block) = _pending_app.gesturedetector(**props, &block)
@@ -58,6 +60,7 @@ module Ruflet
58
60
  def iconbutton(**props) = _pending_app.iconbutton(**props)
59
61
  def app_bar(**props) = _pending_app.app_bar(**props)
60
62
  def appbar(**props) = _pending_app.appbar(**props)
63
+ def clipboard(**props) = _pending_app.clipboard(**props)
61
64
  def text_button(**props) = _pending_app.text_button(**props)
62
65
  def textbutton(**props) = _pending_app.textbutton(**props)
63
66
  def filled_button(**props) = _pending_app.filled_button(**props)
@@ -137,7 +140,7 @@ module Ruflet
137
140
 
138
141
  def control(type, **props, &block)
139
142
  mapped_props = props.dup
140
- prop_children = mapped_props.delete(:controls) || mapped_props.delete("controls")
143
+ prop_children = extract_children_prop(mapped_props)
141
144
 
142
145
  id = mapped_props.delete(:id)&.to_s || next_id(type)
143
146
  c = Ruflet::UI::ControlFactory.build(type.to_s, id: id, **normalize_props(mapped_props))
@@ -186,6 +189,13 @@ module Ruflet
186
189
  hash.transform_keys(&:to_s).transform_values { |v| v.is_a?(Symbol) ? v.to_s : v }
187
190
  end
188
191
 
192
+ def extract_children_prop(props)
193
+ props.delete(:children) ||
194
+ props.delete("children") ||
195
+ props.delete(:controls) ||
196
+ props.delete("controls")
197
+ end
198
+
189
199
  def next_id(type)
190
200
  @seq += 1
191
201
  "#{type}_#{@seq}"
@@ -8,6 +8,8 @@ require_relative "icons/material_icon_lookup"
8
8
  require_relative "icons/cupertino_icon_lookup"
9
9
  require "set"
10
10
  require "cgi"
11
+ require "thread"
12
+ require "timeout"
11
13
 
12
14
  module Ruflet
13
15
  class Page
@@ -51,13 +53,16 @@ module Ruflet
51
53
  @services_container = Ruflet::Control.new(
52
54
  type: "service_registry",
53
55
  id: "_services",
54
- "_services": []
56
+ "_services": [],
57
+ "_internals": { "uid" => Ruflet::Control.generate_id }
55
58
  )
56
59
  @dialogs_container = Ruflet::Control.new(
57
60
  type: "dialogs",
58
61
  id: "_dialogs",
59
62
  controls: []
60
63
  )
64
+ @invoke_waiters = {}
65
+ @invoke_waiters_mutex = Mutex.new
61
66
  refresh_overlay_container!
62
67
  refresh_services_container!
63
68
  refresh_dialogs_container!
@@ -265,6 +270,45 @@ module Ruflet
265
270
  invoke(launcher, "can_launch_url", args: { "url" => url }, timeout: timeout)
266
271
  end
267
272
 
273
+ def set_clipboard(value, timeout: 10)
274
+ clipboard = ensure_clipboard_service
275
+ invoke(clipboard, "set", args: { "data" => value.to_s }, timeout: timeout)
276
+ end
277
+
278
+ def get_clipboard(timeout: 10)
279
+ clipboard = ensure_clipboard_service
280
+ invoke(clipboard, "get", timeout: timeout)
281
+ end
282
+
283
+ def set_clipboard_files(files, timeout: 10)
284
+ clipboard = ensure_clipboard_service
285
+ invoke(clipboard, "set_files", args: { "files" => Array(files).map(&:to_s) }, timeout: timeout)
286
+ end
287
+
288
+ def get_clipboard_files(timeout: 10)
289
+ clipboard = ensure_clipboard_service
290
+ invoke(clipboard, "get_files", timeout: timeout)
291
+ end
292
+
293
+ def set_clipboard_image(value, timeout: 10)
294
+ clipboard = ensure_clipboard_service
295
+ invoke(clipboard, "set_image", args: { "data" => value }, timeout: timeout)
296
+ end
297
+
298
+ def get_clipboard_image(timeout: 10)
299
+ clipboard = ensure_clipboard_service
300
+ invoke(clipboard, "get_image", timeout: timeout)
301
+ end
302
+
303
+ def handle_invoke_method_result(payload)
304
+ call_id = payload["call_id"].to_s
305
+ waiter = @invoke_waiters_mutex.synchronize { @invoke_waiters[call_id] }
306
+ return false unless waiter
307
+
308
+ waiter << payload
309
+ true
310
+ end
311
+
268
312
  def pop_dialog
269
313
  dialog_control = latest_open_dialog
270
314
  return nil unless dialog_control
@@ -295,7 +339,16 @@ module Ruflet
295
339
  patch["content"] = patch.delete("text")
296
340
  end
297
341
 
298
- patch_ops = patch.map { |k, v| [0, 0, k, v] }
342
+ # Keep runtime control tree aligned with incremental patches.
343
+ if patch.key?("controls")
344
+ control.children.clear
345
+ Array(patch["controls"]).each { |child| control.children << child if child.is_a?(Control) }
346
+ end
347
+
348
+ visited = Set.new
349
+ patch.each_value { |value| register_embedded_value(value, visited) }
350
+
351
+ patch_ops = patch.map { |k, v| [0, 0, k, serialize_patch_value(v)] }
299
352
 
300
353
  send_message(Protocol::ACTIONS[:patch_control], {
301
354
  "id" => control.wire_id,
@@ -383,6 +436,31 @@ module Ruflet
383
436
 
384
437
  private
385
438
 
439
+ def invoke_and_wait(control_or_id, method_name, args: nil, timeout: 10)
440
+ control = resolve_control(control_or_id)
441
+ return nil unless control
442
+
443
+ call_id = "call_#{Ruflet::Control.generate_id}"
444
+ waiter = Queue.new
445
+ @invoke_waiters_mutex.synchronize { @invoke_waiters[call_id] = waiter }
446
+
447
+ send_message(Protocol::ACTIONS[:invoke_control_method], {
448
+ "control_id" => control.wire_id,
449
+ "call_id" => call_id,
450
+ "name" => method_name.to_s,
451
+ "args" => args,
452
+ "timeout" => timeout
453
+ })
454
+
455
+ response = Timeout.timeout(timeout.to_f) { waiter.pop }
456
+ error = response["error"]
457
+ raise RuntimeError, error if error && !error.to_s.empty?
458
+
459
+ response["result"]
460
+ ensure
461
+ @invoke_waiters_mutex.synchronize { @invoke_waiters.delete(call_id) } if call_id
462
+ end
463
+
386
464
  def build_widget(type, **props, &block) = WidgetBuilder.new.control(type, **props, &block)
387
465
 
388
466
  def split_props(props)
@@ -482,6 +560,7 @@ module Ruflet
482
560
  def normalize_props(hash)
483
561
  hash.each_with_object({}) do |(k, v), result|
484
562
  key = k.to_s
563
+ key = "controls" if key == "children"
485
564
  result[key] = normalize_value(key, v)
486
565
  end
487
566
  end
@@ -649,5 +728,14 @@ module Ruflet
649
728
  add_service(launcher)
650
729
  launcher
651
730
  end
731
+
732
+ def ensure_clipboard_service
733
+ clipboard = services.find { |service| service.is_a?(Control) && service.type == "clipboard" }
734
+ return clipboard if clipboard
735
+
736
+ clipboard = build_widget(:clipboard)
737
+ add_service(clipboard)
738
+ clipboard
739
+ end
652
740
  end
653
741
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruflet
4
+ module UI
5
+ module Controls
6
+ class GridViewControl < Ruflet::Control
7
+ def initialize(id: nil, **props)
8
+ super(type: "gridview", id: id, **props)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -6,6 +6,7 @@ require_relative "controls/material/container_control"
6
6
  require_relative "controls/material/column_control"
7
7
  require_relative "controls/material/row_control"
8
8
  require_relative "controls/material/stack_control"
9
+ require_relative "controls/material/grid_view_control"
9
10
  require_relative "controls/material/gesture_detector_control"
10
11
  require_relative "controls/material/draggable_control"
11
12
  require_relative "controls/material/drag_target_control"
@@ -44,6 +45,8 @@ module Ruflet
44
45
  "column" => Controls::ColumnControl,
45
46
  "row" => Controls::RowControl,
46
47
  "stack" => Controls::StackControl,
48
+ "gridview" => Controls::GridViewControl,
49
+ "grid_view" => Controls::GridViewControl,
47
50
  "container" => Controls::ContainerControl,
48
51
  "gesturedetector" => Controls::GestureDetectorControl,
49
52
  "gesture_detector" => Controls::GestureDetectorControl,
@@ -27,6 +27,8 @@ module Ruflet
27
27
 
28
28
  def row(**props, &block) = build_widget(:row, **props, &block)
29
29
  def stack(**props, &block) = build_widget(:stack, **props, &block)
30
+ def grid_view(**props, &block) = build_widget(:gridview, **props, &block)
31
+ def gridview(**props, &block) = grid_view(**props, &block)
30
32
  def container(**props, &block) = build_widget(:container, **normalize_container_props(props), &block)
31
33
  def gesture_detector(**props, &block) = build_widget(:gesturedetector, **props, &block)
32
34
  def gesturedetector(**props, &block) = gesture_detector(**props, &block)
@@ -82,6 +84,7 @@ module Ruflet
82
84
  def app_bar(**props) = build_widget(:appbar, **props)
83
85
  def appbar(**props) = app_bar(**props)
84
86
  def url_launcher(**props) = build_widget(:url_launcher, **props)
87
+ def clipboard(**props) = build_widget(:clipboard, **props)
85
88
  def floating_action_button(**props) = build_widget(:floatingactionbutton, **props)
86
89
  def floatingactionbutton(**props) = floating_action_button(**props)
87
90
  def tabs(**props, &block) = build_widget(:tabs, **props, &block)
@@ -8,6 +8,8 @@ module Ruflet
8
8
  "column" => "Column",
9
9
  "row" => "Row",
10
10
  "stack" => "Stack",
11
+ "gridview" => "GridView",
12
+ "grid_view" => "GridView",
11
13
  "view" => "View",
12
14
  "container" => "Container",
13
15
  "checkbox" => "Checkbox",
@@ -79,6 +81,7 @@ module Ruflet
79
81
  "line" => "Line",
80
82
  "service_registry" => "ServiceRegistry",
81
83
  "url_launcher" => "UrlLauncher",
84
+ "clipboard" => "Clipboard",
82
85
  "audio" => "Audio",
83
86
  "video" => "Video",
84
87
  "flashlight" => "Flashlight",
@@ -10,6 +10,8 @@ module Ruflet
10
10
  def center(**props, &block) = control_delegate.center(**props, &block)
11
11
  def row(**props, &block) = control_delegate.row(**props, &block)
12
12
  def stack(**props, &block) = control_delegate.stack(**props, &block)
13
+ def grid_view(**props, &block) = control_delegate.grid_view(**props, &block)
14
+ def gridview(**props, &block) = control_delegate.gridview(**props, &block)
13
15
  def container(**props, &block) = control_delegate.container(**props, &block)
14
16
  def gesture_detector(**props, &block) = control_delegate.gesture_detector(**props, &block)
15
17
  def gesturedetector(**props, &block) = control_delegate.gesturedetector(**props, &block)
@@ -44,6 +46,7 @@ module Ruflet
44
46
  def fab(content = nil, **props) = control_delegate.fab(content, **props)
45
47
  def app_bar(**props) = control_delegate.app_bar(**props)
46
48
  def appbar(**props) = control_delegate.appbar(**props)
49
+ def clipboard(**props) = control_delegate.clipboard(**props)
47
50
  def floating_action_button(**props) = control_delegate.floating_action_button(**props)
48
51
  def floatingactionbutton(**props) = control_delegate.floatingactionbutton(**props)
49
52
  def tabs(**props, &block) = control_delegate.tabs(**props, &block)
@@ -19,7 +19,7 @@ module Ruflet
19
19
 
20
20
  def control(type, **props, &block)
21
21
  mapped_props = props.dup
22
- prop_children = mapped_props.delete(:controls) || mapped_props.delete("controls")
22
+ prop_children = extract_children_prop(mapped_props)
23
23
 
24
24
  node = UI::ControlFactory.build(type, **mapped_props)
25
25
  if block
@@ -44,5 +44,12 @@ module Ruflet
44
44
  def build_widget(type, **props, &block) = control(type, **props, &block)
45
45
 
46
46
  private
47
+
48
+ def extract_children_prop(props)
49
+ props.delete(:children) ||
50
+ props.delete("children") ||
51
+ props.delete(:controls) ||
52
+ props.delete("controls")
53
+ end
47
54
  end
48
55
  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.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - AdamMusa
@@ -60,6 +60,7 @@ files:
60
60
  - lib/ruflet_ui/ruflet/ui/controls/material/filled_button_control.rb
61
61
  - lib/ruflet_ui/ruflet/ui/controls/material/floating_action_button_control.rb
62
62
  - lib/ruflet_ui/ruflet/ui/controls/material/gesture_detector_control.rb
63
+ - lib/ruflet_ui/ruflet/ui/controls/material/grid_view_control.rb
63
64
  - lib/ruflet_ui/ruflet/ui/controls/material/icon_button_control.rb
64
65
  - lib/ruflet_ui/ruflet/ui/controls/material/icon_control.rb
65
66
  - lib/ruflet_ui/ruflet/ui/controls/material/image_control.rb