Class: Ruflet::Page

Inherits:
Object
  • Object
show all
Defined in:
lib/ruflet_ui/ruflet/page.rb

Defined Under Namespace

Classes: FlashlightService, ScreenBrightnessService, SharedPreferencesService, WakelockService

Constant Summary collapse

PAGE_PROP_KEYS =
%w[dark_theme fonts route rtl show_semantics_debugger theme theme_mode title vertical_alignment horizontal_alignment scroll].freeze
DIALOG_PROP_KEYS =
%w[dialog snack_bar bottom_sheet].freeze
WIDGET_HELPER_METHODS =
(
  Ruflet::UI::MaterialControlMethods.instance_methods(false) +
  Ruflet::UI::CupertinoControlMethods.instance_methods(false) +
  %i[control widget]
).map(&:to_s).to_set.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(session_id:, client_details:, sender:) ⇒ Page

Returns a new instance of Page.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/ruflet_ui/ruflet/page.rb', line 152

def initialize(session_id:, client_details:, sender:)
  @session_id = session_id
  @client_details = client_details
  @sender = sender
  @control_index = {}
  @wire_index = {}
  @next_wire_id = 100
  @view_id = 20
  @root_controls = []
  @views = []
  @dialogs = []
  @overlay_container_mounted = false
  @dialogs_container_mounted = false
  @services_container_mounted = false
  @visual_service_controls = {}
  @page_event_handlers = {}
  @view_props = {}
  @page_props = { "route" => (client_details["route"] || "/") }
  @overlay_container = Ruflet::Control.new(
    type: "overlay",
    id: "_overlay",
    controls: []
  )
  @services_container = Ruflet::Control.new(
    type: "service_registry",
    id: "_services",
    "_services": [],
    "_internals": { "uid" => Ruflet::Control.generate_id }
  )
  @dialogs_container = Ruflet::Control.new(
    type: "dialogs",
    id: "_dialogs",
    controls: []
  )
  @invoke_waiters = {}
  @invoke_callbacks = {}
  @invoke_waiters_mutex = Mutex.new
  @shared_preferences_proxy = SharedPreferencesService.new(self)
  @wakelock_proxy = WakelockService.new(self)
  @flashlight_proxy = FlashlightService.new(self)
  @screen_brightness_proxy = ScreenBrightnessService.new(self)
  refresh_overlay_container!
  refresh_services_container!
  refresh_dialogs_container!
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
# File 'lib/ruflet_ui/ruflet/page.rb', line 1253

def method_missing(name, *args, &block)
  method_name = name.to_s
  prop_name = method_name.delete_suffix("=")

  if method_name.end_with?("=")
    if widget_helper_method?(prop_name)
      raise NoMethodError, "Use `#{prop_name}(...)` as a free widget helper, then attach with `page.add(...)`."
    end
    assign_split_prop(prop_name, normalize_value(prop_name, args.first))
    return args.first
  end

  if args.empty? && !block
    return @page_props[method_name] if @page_props.key?(method_name)
    return @view_props[method_name] if @view_props.key?(method_name)
    return instance_variable_get("@#{method_name}") if DIALOG_PROP_KEYS.include?(method_name)
  end

  if widget_helper_method?(name)
    raise NoMethodError, "Use `#{name}(...)` as a free widget helper, then attach with `page.add(...)`."
  end

  super
end

Instance Attribute Details

#client_detailsObject (readonly)

Returns the value of attribute client_details.



150
151
152
# File 'lib/ruflet_ui/ruflet/page.rb', line 150

def client_details
  @client_details
end

#session_idObject (readonly)

Returns the value of attribute session_id.



150
151
152
# File 'lib/ruflet_ui/ruflet/page.rb', line 150

def session_id
  @session_id
end

#viewsObject

Returns the value of attribute views.



150
151
152
# File 'lib/ruflet_ui/ruflet/page.rb', line 150

def views
  @views
end

Instance Method Details

#accelerometer(**props) ⇒ Object



925
926
927
# File 'lib/ruflet_ui/ruflet/page.rb', line 925

def accelerometer(**props)
  service(:accelerometer, **props)
end

#add(*controls, appbar: nil, bottom_appbar: nil, floating_action_button: nil, navigation_bar: nil, dialog: nil, snack_bar: nil, bottom_sheet: nil) ⇒ Object



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/ruflet_ui/ruflet/page.rb', line 247

def add(*controls, appbar: nil, bottom_appbar: nil, floating_action_button: nil, navigation_bar: nil, dialog: nil, snack_bar: nil, bottom_sheet: nil)
  controls = controls.flatten
  visited = Set.new
  controls.each { |c| register_control_tree(c, visited) }
  @root_controls = controls

  update_view_slot("appbar", appbar)
  update_view_slot("bottom_appbar", bottom_appbar)
  update_view_slot("floating_action_button", floating_action_button)
  update_view_slot("navigation_bar", navigation_bar)
  @dialog = dialog if dialog
  @snack_bar = snack_bar if snack_bar
  @bottom_sheet = bottom_sheet if bottom_sheet

  refresh_dialogs_container!
  @view_props.each_value { |value| register_embedded_value(value, visited) }

  send_view_patch

  self
end

#add_service(*value) ⇒ Object



329
330
331
332
333
334
# File 'lib/ruflet_ui/ruflet/page.rb', line 329

def add_service(*value)
  @services_container.props["_services"] = services + value.flatten.compact
  refresh_services_container!
  push_services_update!
  self
end

#appbar=(value) ⇒ Object



426
427
428
# File 'lib/ruflet_ui/ruflet/page.rb', line 426

def appbar=(value)
  @view_props["appbar"] = value
end

#apply_client_update(control_or_id, props) ⇒ Object



1220
1221
1222
1223
1224
1225
1226
1227
1228
# File 'lib/ruflet_ui/ruflet/page.rb', line 1220

def apply_client_update(control_or_id, props)
  control = resolve_control(control_or_id)
  return self unless control

  patch = normalize_props(props || {})
  patch.each { |k, v| control.props[k] = v }

  self
end

#audio(**props) ⇒ Object



309
310
311
# File 'lib/ruflet_ui/ruflet/page.rb', line 309

def audio(**props)
  service(:audio, **props)
end

#audio_recorder(**props) ⇒ Object



313
314
315
# File 'lib/ruflet_ui/ruflet/page.rb', line 313

def audio_recorder(**props)
  service(:audio_recorder, **props)
end

#barometer(**props) ⇒ Object



941
942
943
# File 'lib/ruflet_ui/ruflet/page.rb', line 941

def barometer(**props)
  service(:barometer, **props)
end

#battery(**props) ⇒ Object



957
958
959
# File 'lib/ruflet_ui/ruflet/page.rb', line 957

def battery(**props)
  service(:battery, **props)
end

#battery_save_mode?(timeout: nil, on_result: nil) ⇒ Boolean

Returns:

  • (Boolean)


921
922
923
# File 'lib/ruflet_ui/ruflet/page.rb', line 921

def battery_save_mode?(timeout: nil, on_result: nil)
  is_in_battery_save_mode(timeout: timeout, on_result: on_result)
end

#bgcolorObject



239
240
241
# File 'lib/ruflet_ui/ruflet/page.rb', line 239

def bgcolor
  @view_props["bgcolor"]
end

#bgcolor=(value) ⇒ Object



243
244
245
# File 'lib/ruflet_ui/ruflet/page.rb', line 243

def bgcolor=(value)
  @view_props["bgcolor"] = normalize_value("bgcolor", value)
end

#bottom_appbar=(value) ⇒ Object



430
431
432
# File 'lib/ruflet_ui/ruflet/page.rb', line 430

def bottom_appbar=(value)
  @view_props["bottom_appbar"] = value
end

#bottom_sheet=(value) ⇒ Object



500
501
502
503
# File 'lib/ruflet_ui/ruflet/page.rb', line 500

def bottom_sheet=(value)
  @bottom_sheet = value
  refresh_dialogs_container!
end

#bottomappbar=(value) ⇒ Object



434
435
436
# File 'lib/ruflet_ui/ruflet/page.rb', line 434

def bottomappbar=(value)
  self.bottom_appbar = value
end

#bottomsheet=(value) ⇒ Object



505
506
507
# File 'lib/ruflet_ui/ruflet/page.rb', line 505

def bottomsheet=(value)
  self.bottom_sheet = value
end

#browser_context_menu(**props) ⇒ Object



317
318
319
# File 'lib/ruflet_ui/ruflet/page.rb', line 317

def browser_context_menu(**props)
  service(:browser_context_menu, **props)
end

#camera(**props) ⇒ Object



985
986
987
# File 'lib/ruflet_ui/ruflet/page.rb', line 985

def camera(**props)
  service(:camera, **props)
end

#can_launch_url(url, timeout: 10) ⇒ Object



580
581
582
583
# File 'lib/ruflet_ui/ruflet/page.rb', line 580

def can_launch_url(url, timeout: 10)
  url_launcher = ensure_url_launcher_service
  invoke(url_launcher, "can_launch_url", args: { "url" => url }, timeout: timeout)
end

#center_window(timeout: 10, on_result: nil) ⇒ Object



701
702
703
# File 'lib/ruflet_ui/ruflet/page.rb', line 701

def center_window(timeout: 10, on_result: nil)
  invoke_window("center", timeout: timeout, on_result: on_result)
end

#clipboard(**props) ⇒ Object



965
966
967
# File 'lib/ruflet_ui/ruflet/page.rb', line 965

def clipboard(**props)
  service(:clipboard, **props)
end

#close_dialog(dialog_control) ⇒ Object



1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
# File 'lib/ruflet_ui/ruflet/page.rb', line 1157

def close_dialog(dialog_control)
  return self unless dialog_control

  before_dialog_count = @dialogs_container.props["controls"].length
  dialog_control.props["open"] = false
  @dialog = nil if @dialog.equal?(dialog_control)
  remove_dialog_tracking(dialog_control)
  refresh_dialogs_container!
  push_dialogs_update!(force_view: @dialogs_container.props["controls"].length < before_dialog_count)
  self
end

#close_drawer(timeout: 10, on_result: nil) ⇒ Object



465
466
467
468
# File 'lib/ruflet_ui/ruflet/page.rb', line 465

def close_drawer(timeout: 10, on_result: nil)
  invoke_current_view("close_drawer", timeout: timeout, on_result: on_result)
  self
end

#close_end_drawer(timeout: 10, on_result: nil) ⇒ Object



477
478
479
480
# File 'lib/ruflet_ui/ruflet/page.rb', line 477

def close_end_drawer(timeout: 10, on_result: nil)
  invoke_current_view("close_end_drawer", timeout: timeout, on_result: on_result)
  self
end

#close_in_app_web_view(timeout: 10, on_result: nil) ⇒ Object



585
586
587
588
# File 'lib/ruflet_ui/ruflet/page.rb', line 585

def close_in_app_web_view(timeout: 10, on_result: nil)
  url_launcher = ensure_url_launcher_service
  invoke(url_launcher, "close_in_app_web_view", timeout: timeout, on_result: on_result)
end

#close_window(timeout: 10, on_result: nil) ⇒ Object



705
706
707
# File 'lib/ruflet_ui/ruflet/page.rb', line 705

def close_window(timeout: 10, on_result: nil)
  invoke_window("close", timeout: timeout, on_result: on_result)
end

#connectivity(**props) ⇒ Object



961
962
963
# File 'lib/ruflet_ui/ruflet/page.rb', line 961

def connectivity(**props)
  service(:connectivity, **props)
end

#destroy_window(timeout: 10, on_result: nil) ⇒ Object



709
710
711
# File 'lib/ruflet_ui/ruflet/page.rb', line 709

def destroy_window(timeout: 10, on_result: nil)
  invoke_window("destroy", timeout: timeout, on_result: on_result)
end

#dialogObject



482
# File 'lib/ruflet_ui/ruflet/page.rb', line 482

def dialog = @dialog

#dialog=(value) ⇒ Object



484
485
486
487
488
# File 'lib/ruflet_ui/ruflet/page.rb', line 484

def dialog=(value)
  @dialog = value
  refresh_dialogs_container!
  push_dialogs_update! if @dialogs_container_mounted
end

#disable_browser_context_menu(timeout: 10, on_result: nil) ⇒ Object



685
686
687
# File 'lib/ruflet_ui/ruflet/page.rb', line 685

def disable_browser_context_menu(timeout: 10, on_result: nil)
  invoke_browser_context_menu("disable_menu", timeout: timeout, on_result: on_result)
end

#dispatch_event(target:, name:, data:) ⇒ Object



1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
# File 'lib/ruflet_ui/ruflet/page.rb', line 1230

def dispatch_event(target:, name:, data:)
  if page_control_target?(target)
    if name.to_s == "route_change"
      route_from_event = extract_route(data)
      @page_props["route"] = route_from_event if route_from_event
    end
    dispatch_page_event(name: name, data: data)
    return
  end

  control = @wire_index[target.to_i] || @control_index[target.to_s]
  return unless control

  event = Event.new(name: name, target: target, raw_data: data, page: self, control: control)
  apply_event_value_to_control(control, event) if %w[change select select_change].include?(name.to_s)
  before_dialog_count = @dialogs_container.props["controls"].length
  if dialog_close_event?(control, name) && remove_dialog_tracking(control)
    push_dialogs_update!(force_view: @dialogs_container.props["controls"].length < before_dialog_count)
  end

  control.emit(name, event)
end

#drag(finder_id, offset, finder_index: nil, timeout: 10, on_result: nil) ⇒ Object



796
797
798
799
800
801
802
803
804
805
806
807
# File 'lib/ruflet_ui/ruflet/page.rb', line 796

def drag(finder_id, offset, finder_index: nil, timeout: 10, on_result: nil)
  invoke_tester(
    "drag",
    args: compact_service_args(
      "finder_id" => finder_id,
      "finder_index" => finder_index,
      "offset" => offset
    ),
    timeout: timeout,
    on_result: on_result
  )
end

#drag_from(start, offset, timeout: 10, on_result: nil) ⇒ Object



809
810
811
812
813
814
815
816
# File 'lib/ruflet_ui/ruflet/page.rb', line 809

def drag_from(start, offset, timeout: 10, on_result: nil)
  invoke_tester(
    "drag_from",
    args: compact_service_args("start" => start, "offset" => offset),
    timeout: timeout,
    on_result: on_result
  )
end

#drawerObject



442
443
444
# File 'lib/ruflet_ui/ruflet/page.rb', line 442

def drawer
  @view_props["drawer"]
end

#drawer=(value) ⇒ Object



446
447
448
# File 'lib/ruflet_ui/ruflet/page.rb', line 446

def drawer=(value)
  @view_props["drawer"] = value
end

#enable_browser_context_menu(timeout: 10, on_result: nil) ⇒ Object



689
690
691
# File 'lib/ruflet_ui/ruflet/page.rb', line 689

def enable_browser_context_menu(timeout: 10, on_result: nil)
  invoke_browser_context_menu("enable_menu", timeout: timeout, on_result: on_result)
end

#end_drawerObject



450
451
452
# File 'lib/ruflet_ui/ruflet/page.rb', line 450

def end_drawer
  @view_props["end_drawer"]
end

#end_drawer=(value) ⇒ Object



454
455
456
# File 'lib/ruflet_ui/ruflet/page.rb', line 454

def end_drawer=(value)
  @view_props["end_drawer"] = value
end

#enter_text(finder_id, text, options = nil, finder_index: nil, timeout: 10, on_result: nil) ⇒ Object



823
824
825
826
827
828
829
830
831
832
833
834
835
# File 'lib/ruflet_ui/ruflet/page.rb', line 823

def enter_text(finder_id, text, options = nil, finder_index: nil, timeout: 10, on_result: nil)
  finder_index = options[:finder_index] || options["finder_index"] if options.is_a?(Hash) && finder_index.nil?
  invoke_tester(
    "enter_text",
    args: compact_service_args(
      "finder_id" => finder_id,
      "finder_index" => finder_index,
      "text" => text
    ),
    timeout: timeout,
    on_result: on_result
  )
end

#file_picker(**props) ⇒ Object



969
970
971
# File 'lib/ruflet_ui/ruflet/page.rb', line 969

def file_picker(**props)
  service(:file_picker, **props)
end

#find_by_icon(icon, timeout: 10, on_result: nil) ⇒ Object



752
753
754
# File 'lib/ruflet_ui/ruflet/page.rb', line 752

def find_by_icon(icon, timeout: 10, on_result: nil)
  invoke_tester("find_by_icon", args: { "icon" => normalize_service_value(icon) }, timeout: timeout, on_result: on_result)
end

#find_by_key(key, timeout: 10, on_result: nil) ⇒ Object



744
745
746
# File 'lib/ruflet_ui/ruflet/page.rb', line 744

def find_by_key(key, timeout: 10, on_result: nil)
  invoke_tester("find_by_key", args: { "key" => key }, timeout: timeout, on_result: on_result)
end

#find_by_text(text, timeout: 10, on_result: nil) ⇒ Object



736
737
738
# File 'lib/ruflet_ui/ruflet/page.rb', line 736

def find_by_text(text, timeout: 10, on_result: nil)
  invoke_tester("find_by_text", args: { "text" => text }, timeout: timeout, on_result: on_result)
end

#find_by_text_containing(pattern, timeout: 10, on_result: nil) ⇒ Object



740
741
742
# File 'lib/ruflet_ui/ruflet/page.rb', line 740

def find_by_text_containing(pattern, timeout: 10, on_result: nil)
  invoke_tester("find_by_text_containing", args: { "pattern" => pattern }, timeout: timeout, on_result: on_result)
end

#find_by_tooltip(value, timeout: 10, on_result: nil) ⇒ Object



748
749
750
# File 'lib/ruflet_ui/ruflet/page.rb', line 748

def find_by_tooltip(value, timeout: 10, on_result: nil)
  invoke_tester("find_by_tooltip", args: { "value" => value }, timeout: timeout, on_result: on_result)
end

#flashlight(**props) ⇒ Object



297
298
299
300
301
# File 'lib/ruflet_ui/ruflet/page.rb', line 297

def flashlight(**props)
  return service(:flashlight, **props) unless props.empty?

  @flashlight_proxy
end

#floating_action_button=(value) ⇒ Object



438
439
440
# File 'lib/ruflet_ui/ruflet/page.rb', line 438

def floating_action_button=(value)
  @view_props["floating_action_button"] = value
end

#geolocator(**props) ⇒ Object



993
994
995
# File 'lib/ruflet_ui/ruflet/page.rb', line 993

def geolocator(**props)
  service(:geolocator, **props)
end

#get_application_cache_directory(timeout: nil, on_result: nil) ⇒ Object



1005
1006
1007
# File 'lib/ruflet_ui/ruflet/page.rb', line 1005

def get_application_cache_directory(timeout: nil, on_result: nil)
  invoke_storage_paths("get_application_cache_directory", timeout: timeout, on_result: on_result)
end

#get_application_documents_directory(timeout: nil, on_result: nil) ⇒ Object



1009
1010
1011
# File 'lib/ruflet_ui/ruflet/page.rb', line 1009

def get_application_documents_directory(timeout: nil, on_result: nil)
  invoke_storage_paths("get_application_documents_directory", timeout: timeout, on_result: on_result)
end

#get_application_support_directory(timeout: nil, on_result: nil) ⇒ Object



1013
1014
1015
# File 'lib/ruflet_ui/ruflet/page.rb', line 1013

def get_application_support_directory(timeout: nil, on_result: nil)
  invoke_storage_paths("get_application_support_directory", timeout: timeout, on_result: on_result)
end

#get_battery_level(timeout: nil, on_result: nil) ⇒ Object



909
910
911
# File 'lib/ruflet_ui/ruflet/page.rb', line 909

def get_battery_level(timeout: nil, on_result: nil)
  invoke_battery_method("get_battery_level", timeout: timeout, on_result: on_result)
end

#get_battery_state(timeout: nil, on_result: nil) ⇒ Object



913
914
915
# File 'lib/ruflet_ui/ruflet/page.rb', line 913

def get_battery_state(timeout: nil, on_result: nil)
  invoke_battery_method("get_battery_state", timeout: timeout, on_result: on_result)
end

#get_clipboard(timeout: nil, on_result: nil) ⇒ Object



875
876
877
# File 'lib/ruflet_ui/ruflet/page.rb', line 875

def get_clipboard(timeout: nil, on_result: nil)
  invoke_clipboard_method("get", timeout: timeout, on_result: on_result)
end

#get_clipboard_files(timeout: nil, on_result: nil) ⇒ Object



888
889
890
# File 'lib/ruflet_ui/ruflet/page.rb', line 888

def get_clipboard_files(timeout: nil, on_result: nil)
  invoke_clipboard_method("get_files", timeout: timeout, on_result: on_result)
end

#get_clipboard_image(timeout: nil, on_result: nil) ⇒ Object



901
902
903
# File 'lib/ruflet_ui/ruflet/page.rb', line 901

def get_clipboard_image(timeout: nil, on_result: nil)
  invoke_clipboard_method("get_image", timeout: timeout, on_result: on_result)
end

#get_connectivity(timeout: nil, on_result: nil) ⇒ Object



905
906
907
# File 'lib/ruflet_ui/ruflet/page.rb', line 905

def get_connectivity(timeout: nil, on_result: nil)
  invoke_connectivity_method("get_connectivity", timeout: timeout, on_result: on_result)
end

#get_console_log_filename(timeout: nil, on_result: nil) ⇒ Object



1041
1042
1043
# File 'lib/ruflet_ui/ruflet/page.rb', line 1041

def get_console_log_filename(timeout: nil, on_result: nil)
  invoke_storage_paths("get_console_log_filename", timeout: timeout, on_result: on_result)
end

#get_directory_path(dialog_title: nil, initial_directory: nil, timeout: nil, on_result: nil) ⇒ Object



660
661
662
663
664
665
666
667
668
669
670
# File 'lib/ruflet_ui/ruflet/page.rb', line 660

def get_directory_path(dialog_title: nil, initial_directory: nil, timeout: nil, on_result: nil)
  invoke_file_picker(
    "get_directory_path",
    compact_service_args(
      "dialog_title" => dialog_title,
      "initial_directory" => initial_directory
    ),
    timeout: timeout,
    on_result: on_result
  )
end

#get_downloads_directory(timeout: nil, on_result: nil) ⇒ Object



1017
1018
1019
# File 'lib/ruflet_ui/ruflet/page.rb', line 1017

def get_downloads_directory(timeout: nil, on_result: nil)
  invoke_storage_paths("get_downloads_directory", timeout: timeout, on_result: on_result)
end

#get_external_cache_directories(timeout: nil, on_result: nil) ⇒ Object



1021
1022
1023
# File 'lib/ruflet_ui/ruflet/page.rb', line 1021

def get_external_cache_directories(timeout: nil, on_result: nil)
  invoke_storage_paths("get_external_cache_directories", timeout: timeout, on_result: on_result)
end

#get_external_storage_directories(timeout: nil, on_result: nil) ⇒ Object



1025
1026
1027
# File 'lib/ruflet_ui/ruflet/page.rb', line 1025

def get_external_storage_directories(timeout: nil, on_result: nil)
  invoke_storage_paths("get_external_storage_directories", timeout: timeout, on_result: on_result)
end

#get_external_storage_directory(timeout: nil, on_result: nil) ⇒ Object



1033
1034
1035
# File 'lib/ruflet_ui/ruflet/page.rb', line 1033

def get_external_storage_directory(timeout: nil, on_result: nil)
  invoke_storage_paths("get_external_storage_directory", timeout: timeout, on_result: on_result)
end

#get_library_directory(timeout: nil, on_result: nil) ⇒ Object



1029
1030
1031
# File 'lib/ruflet_ui/ruflet/page.rb', line 1029

def get_library_directory(timeout: nil, on_result: nil)
  invoke_storage_paths("get_library_directory", timeout: timeout, on_result: on_result)
end

#get_temporary_directory(timeout: nil, on_result: nil) ⇒ Object



1037
1038
1039
# File 'lib/ruflet_ui/ruflet/page.rb', line 1037

def get_temporary_directory(timeout: nil, on_result: nil)
  invoke_storage_paths("get_temporary_directory", timeout: timeout, on_result: on_result)
end

#go(route, **query_params) ⇒ Object



388
389
390
391
392
393
# File 'lib/ruflet_ui/ruflet/page.rb', line 388

def go(route, **query_params)
  @page_props["route"] = build_route(route, query_params)
  dispatch_page_event(name: "route_change", data: @page_props["route"])
  send_view_patch
  self
end

#gyroscope(**props) ⇒ Object



929
930
931
# File 'lib/ruflet_ui/ruflet/page.rb', line 929

def gyroscope(**props)
  service(:gyroscope, **props)
end

#handle_invoke_method_result(payload) ⇒ Object



1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
# File 'lib/ruflet_ui/ruflet/page.rb', line 1130

def handle_invoke_method_result(payload)
  call_id = payload["call_id"].to_s
  waiter = @invoke_waiters_mutex.synchronize { @invoke_waiters[call_id] }
  if waiter
    waiter << payload
    return true
  end

  callback = @invoke_waiters_mutex.synchronize { @invoke_callbacks.delete(call_id) }
  return false unless callback

  callback.call(payload["result"], payload["error"])
  true
rescue StandardError => e
  Kernel.warn("invoke callback error: #{e.class}: #{e.message}")
  false
end

#haptic_feedback(**props) ⇒ Object



989
990
991
# File 'lib/ruflet_ui/ruflet/page.rb', line 989

def haptic_feedback(**props)
  service(:haptic_feedback, **props)
end

#heavy_impact(timeout: 10, on_result: nil) ⇒ Object



846
847
848
# File 'lib/ruflet_ui/ruflet/page.rb', line 846

def heavy_impact(timeout: 10, on_result: nil)
  invoke_haptic_feedback("heavy_impact", timeout: timeout, on_result: on_result)
end

#horizontal_alignmentObject



229
230
231
# File 'lib/ruflet_ui/ruflet/page.rb', line 229

def horizontal_alignment
  @page_props["horizontal_alignment"] || @view_props["horizontal_alignment"]
end

#horizontal_alignment=(value) ⇒ Object



233
234
235
236
237
# File 'lib/ruflet_ui/ruflet/page.rb', line 233

def horizontal_alignment=(value)
  v = normalize_value("horizontal_alignment", value)
  @page_props["horizontal_alignment"] = v
  @view_props["horizontal_alignment"] = v
end

#invoke(control_or_id, method_name, args: nil, timeout: 10, on_result: nil) ⇒ Object



523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'lib/ruflet_ui/ruflet/page.rb', line 523

def invoke(control_or_id, method_name, args: nil, timeout: 10, on_result: nil)
  control_id =
    if page_control_target?(control_or_id)
      1
    else
      control = resolve_control(control_or_id)
      return nil unless control
      control.wire_id
    end

  call_id = "call_#{Ruflet::Control.generate_id}"
  if on_result.respond_to?(:call)
    @invoke_waiters_mutex.synchronize { @invoke_callbacks[call_id] = on_result }
    unless timeout.nil?
      Thread.new(call_id, timeout.to_f) do |pending_call_id, invoke_timeout|
        sleep([invoke_timeout, 0.0].max + 0.1)
        callback = @invoke_waiters_mutex.synchronize { @invoke_callbacks.delete(pending_call_id) }
        callback&.call(nil, "execution expired")
      rescue StandardError => e
        Kernel.warn("invoke timeout callback error: #{e.class}: #{e.message}")
      end
    end
  end
  payload = {
    "control_id" => control_id,
    "call_id" => call_id,
    "name" => method_name.to_s,
    "args" => args
  }
  payload["timeout"] = timeout unless timeout.nil?
  send_message(Protocol::ACTIONS[:invoke_control_method], payload)

  call_id
end

#invoke_sync(control_or_id, method_name, args: nil, timeout: 10) ⇒ Object

Synchronous invoke for controls/services that must return a value before continuing (e.g. picker selection, camera discovery/init).



560
561
562
# File 'lib/ruflet_ui/ruflet/page.rb', line 560

def invoke_sync(control_or_id, method_name, args: nil, timeout: 10)
  invoke_and_wait(control_or_id, method_name, args: args, timeout: timeout)
end

#is_in_battery_save_mode(timeout: nil, on_result: nil) ⇒ Object



917
918
919
# File 'lib/ruflet_ui/ruflet/page.rb', line 917

def is_in_battery_save_mode(timeout: nil, on_result: nil)
  invoke_battery_method("is_in_battery_save_mode", timeout: timeout, on_result: on_result)
end

#launch_url(url, mode: nil, web_view_configuration: nil, browser_configuration: nil, web_only_window_name: nil, timeout: 10, on_result: nil) ⇒ Object



564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
# File 'lib/ruflet_ui/ruflet/page.rb', line 564

def launch_url(url, mode: nil, web_view_configuration: nil, browser_configuration: nil, web_only_window_name: nil, timeout: 10, on_result: nil)
  url_launcher = ensure_url_launcher_service
  args = { "url" => url }
  args["mode"] = mode unless mode.nil?
  args["web_view_configuration"] = web_view_configuration unless web_view_configuration.nil?
  args["browser_configuration"] = browser_configuration unless browser_configuration.nil?
  args["web_only_window_name"] = web_only_window_name unless web_only_window_name.nil?
  invoke(
    url_launcher,
    "launch_url",
    args: args,
    timeout: timeout,
    on_result: on_result
  )
end

#light_impact(timeout: 10, on_result: nil) ⇒ Object



854
855
856
# File 'lib/ruflet_ui/ruflet/page.rb', line 854

def light_impact(timeout: 10, on_result: nil)
  invoke_haptic_feedback("light_impact", timeout: timeout, on_result: on_result)
end

#long_press(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil) ⇒ Object



818
819
820
821
# File 'lib/ruflet_ui/ruflet/page.rb', line 818

def long_press(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil)
  finder_index = options[:finder_index] || options["finder_index"] if options.is_a?(Hash) && finder_index.nil?
  invoke_tester_finder("long_press", finder_id, finder_index: finder_index, timeout: timeout, on_result: on_result)
end

#magnetometer(**props) ⇒ Object



937
938
939
# File 'lib/ruflet_ui/ruflet/page.rb', line 937

def magnetometer(**props)
  service(:magnetometer, **props)
end

#medium_impact(timeout: 10, on_result: nil) ⇒ Object



850
851
852
# File 'lib/ruflet_ui/ruflet/page.rb', line 850

def medium_impact(timeout: 10, on_result: nil)
  invoke_haptic_feedback("medium_impact", timeout: timeout, on_result: on_result)
end

#mount(&block) ⇒ Object



420
421
422
423
424
# File 'lib/ruflet_ui/ruflet/page.rb', line 420

def mount(&block)
  builder = WidgetBuilder.new
  builder.instance_eval(&block)
  add(*builder.children)
end

#mouse_click(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil) ⇒ Object



765
766
767
768
# File 'lib/ruflet_ui/ruflet/page.rb', line 765

def mouse_click(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil)
  finder_index = options[:finder_index] || options["finder_index"] if options.is_a?(Hash) && finder_index.nil?
  invoke_tester_finder("mouse_click", finder_id, finder_index: finder_index, timeout: timeout, on_result: on_result)
end

#mouse_click_at(offset = nil, timeout: 10, on_result: nil) ⇒ Object



784
785
786
# File 'lib/ruflet_ui/ruflet/page.rb', line 784

def mouse_click_at(offset = nil, timeout: 10, on_result: nil)
  invoke_tester_at("mouse_click_at", offset, timeout: timeout, on_result: on_result)
end

#mouse_double_click(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil) ⇒ Object



770
771
772
773
# File 'lib/ruflet_ui/ruflet/page.rb', line 770

def mouse_double_click(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil)
  finder_index = options[:finder_index] || options["finder_index"] if options.is_a?(Hash) && finder_index.nil?
  invoke_tester_finder("mouse_double_click", finder_id, finder_index: finder_index, timeout: timeout, on_result: on_result)
end

#mouse_double_click_at(offset = nil, timeout: 10, on_result: nil) ⇒ Object



788
789
790
# File 'lib/ruflet_ui/ruflet/page.rb', line 788

def mouse_double_click_at(offset = nil, timeout: 10, on_result: nil)
  invoke_tester_at("mouse_double_click_at", offset, timeout: timeout, on_result: on_result)
end

#mouse_hover(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil) ⇒ Object



837
838
839
840
# File 'lib/ruflet_ui/ruflet/page.rb', line 837

def mouse_hover(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil)
  finder_index = options[:finder_index] || options["finder_index"] if options.is_a?(Hash) && finder_index.nil?
  invoke_tester_finder("mouse_hover", finder_id, finder_index: finder_index, timeout: timeout, on_result: on_result)
end


395
396
397
# File 'lib/ruflet_ui/ruflet/page.rb', line 395

def navigate(route, **query_params)
  go(route, **query_params)
end

#on(event_name, &block) ⇒ Object



415
416
417
418
# File 'lib/ruflet_ui/ruflet/page.rb', line 415

def on(event_name, &block)
  @page_event_handlers[event_name.to_s.sub(/\Aon_/, "")] = block
  self
end

#on_route_change=(handler) ⇒ Object



407
408
409
# File 'lib/ruflet_ui/ruflet/page.rb', line 407

def on_route_change=(handler)
  @page_event_handlers["route_change"] = handler
end

#on_view_pop=(handler) ⇒ Object



411
412
413
# File 'lib/ruflet_ui/ruflet/page.rb', line 411

def on_view_pop=(handler)
  @page_event_handlers["view_pop"] = handler
end

#open_window(url, title: nil, width: nil, height: nil, timeout: 10, on_result: nil) ⇒ Object



590
591
592
593
594
595
596
597
# File 'lib/ruflet_ui/ruflet/page.rb', line 590

def open_window(url, title: nil, width: nil, height: nil, timeout: 10, on_result: nil)
  url_launcher = ensure_url_launcher_service
  args = { "url" => url }
  args["title"] = title unless title.nil?
  args["width"] = width unless width.nil?
  args["height"] = height unless height.nil?
  invoke(url_launcher, "open_window", args: args, timeout: timeout, on_result: on_result)
end

#patch_page(control_id, **props) ⇒ Object



1216
1217
1218
# File 'lib/ruflet_ui/ruflet/page.rb', line 1216

def patch_page(control_id, **props)
  update(control_id, **props)
end

#permission_handler(**props) ⇒ Object



997
998
999
# File 'lib/ruflet_ui/ruflet/page.rb', line 997

def permission_handler(**props)
  service(:permission_handler, **props)
end

#pick_files(dialog_title: nil, initial_directory: nil, file_type: "any", allowed_extensions: nil, allow_multiple: false, with_data: false, timeout: nil, on_result: nil) ⇒ Object

File picker helpers: create an ephemeral service, invoke method, and dispose it.



610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
# File 'lib/ruflet_ui/ruflet/page.rb', line 610

def pick_files(
  dialog_title: nil,
  initial_directory: nil,
  file_type: "any",
  allowed_extensions: nil,
  allow_multiple: false,
  with_data: false,
  timeout: nil,
  on_result: nil
)
  invoke_file_picker(
    "pick_files",
    compact_service_args(
      "dialog_title" => dialog_title,
      "initial_directory" => initial_directory,
      "file_type" => file_type,
      "allowed_extensions" => allowed_extensions,
      "allow_multiple" => allow_multiple,
      "with_data" => with_data
    ),
    timeout: timeout,
    on_result: on_result
  )
end

#pop_dialogObject



1148
1149
1150
1151
1152
1153
1154
1155
# File 'lib/ruflet_ui/ruflet/page.rb', line 1148

def pop_dialog
  dialog_control = latest_open_dialog
  return nil unless dialog_control

  dialog_control.props["open"] = false
  update(dialog_control, open: false)
  dialog_control
end

#push_route(route, **query_params) ⇒ Object



399
400
401
# File 'lib/ruflet_ui/ruflet/page.rb', line 399

def push_route(route, **query_params)
  go(route, **query_params)
end

#queryObject



403
404
405
# File 'lib/ruflet_ui/ruflet/page.rb', line 403

def query
  parse_query(route)
end

#remove_service(*value) ⇒ Object



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/ruflet_ui/ruflet/page.rb', line 336

def remove_service(*value)
  targets = value.flatten.compact
  return self if targets.empty?

  @services_container.props["_services"] = services.reject do |service|
    targets.any? do |target|
      case target
      when Control
        service.equal?(target) || (!target.id.nil? && service.id.to_s == target.id.to_s)
      else
        needle = target.to_s
        service.id.to_s == needle || service.type.to_s.downcase == needle.downcase
      end
    end
  end

  refresh_services_container!
  push_services_update!
  self
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
# File 'lib/ruflet_ui/ruflet/page.rb', line 1278

def respond_to_missing?(name, include_private = false)
  method_name = name.to_s
  prop_name = method_name.delete_suffix("=")
  widget_helper_method?(name) ||
    widget_helper_method?(prop_name) ||
    method_name.end_with?("=") ||
    @page_props.key?(method_name) ||
    @view_props.key?(method_name) ||
    DIALOG_PROP_KEYS.include?(method_name) ||
    super
end

#right_mouse_click(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil) ⇒ Object



775
776
777
778
# File 'lib/ruflet_ui/ruflet/page.rb', line 775

def right_mouse_click(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil)
  finder_index = options[:finder_index] || options["finder_index"] if options.is_a?(Hash) && finder_index.nil?
  invoke_tester_finder("right_mouse_click", finder_id, finder_index: finder_index, timeout: timeout, on_result: on_result)
end

#right_mouse_click_at(offset = nil, timeout: 10, on_result: nil) ⇒ Object



792
793
794
# File 'lib/ruflet_ui/ruflet/page.rb', line 792

def right_mouse_click_at(offset = nil, timeout: 10, on_result: nil)
  invoke_tester_at("right_mouse_click_at", offset, timeout: timeout, on_result: on_result)
end

#routeObject



211
212
213
# File 'lib/ruflet_ui/ruflet/page.rb', line 211

def route
  @page_props["route"]
end

#route=(value) ⇒ Object



215
216
217
# File 'lib/ruflet_ui/ruflet/page.rb', line 215

def route=(value)
  @page_props["route"] = value
end

#save_file(dialog_title: nil, file_name: nil, initial_directory: nil, file_type: "any", allowed_extensions: nil, src_bytes: nil, timeout: nil, on_result: nil) ⇒ Object



635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
# File 'lib/ruflet_ui/ruflet/page.rb', line 635

def save_file(
  dialog_title: nil,
  file_name: nil,
  initial_directory: nil,
  file_type: "any",
  allowed_extensions: nil,
  src_bytes: nil,
  timeout: nil,
  on_result: nil
)
  invoke_file_picker(
    "save_file",
    compact_service_args(
      "dialog_title" => dialog_title,
      "file_name" => file_name,
      "initial_directory" => initial_directory,
      "file_type" => file_type,
      "allowed_extensions" => allowed_extensions,
      "src_bytes" => src_bytes
    ),
    timeout: timeout,
    on_result: on_result
  )
end

#screen_brightness(**props) ⇒ Object



303
304
305
306
307
# File 'lib/ruflet_ui/ruflet/page.rb', line 303

def screen_brightness(**props)
  return service(:screen_brightness, **props) unless props.empty?

  @screen_brightness_proxy
end

#screenshot(**props) ⇒ Object



953
954
955
# File 'lib/ruflet_ui/ruflet/page.rb', line 953

def screenshot(**props)
  service(:screenshot, **props)
end

#secure_storage(**props) ⇒ Object



1001
1002
1003
# File 'lib/ruflet_ui/ruflet/page.rb', line 1001

def secure_storage(**props)
  service(:secure_storage, **props)
end

#selection_click(timeout: 10, on_result: nil) ⇒ Object



858
859
860
# File 'lib/ruflet_ui/ruflet/page.rb', line 858

def selection_click(timeout: 10, on_result: nil)
  invoke_haptic_feedback("selection_click", timeout: timeout, on_result: on_result)
end

#semantics_service(**props) ⇒ Object



949
950
951
# File 'lib/ruflet_ui/ruflet/page.rb', line 949

def semantics_service(**props)
  service(:semantics_service, **props)
end

#service(type, **props) ⇒ Object



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/ruflet_ui/ruflet/page.rb', line 357

def service(type, **props)
  mapped_props = normalize_props(props || {})
  id = mapped_props.delete("id")
  normalized_type = type.to_s.downcase
  compact_type = normalized_type.delete("_")

  if visual_service_type?(normalized_type)
    key = id ? "id:#{id}" : normalized_type
    existing = @visual_service_controls[key]
    return existing if existing

    svc = Ruflet::UI::ControlFactory.build(type.to_s, id: id&.to_s, **mapped_props)
    @visual_service_controls[key] = svc
    return svc
  end

  existing =
    if id
      services.find { |s| s.is_a?(Control) && s.id.to_s == id.to_s }
    else
      services.find do |s|
        s.is_a?(Control) && s.type.to_s.downcase.delete("_") == compact_type
      end
    end
  return existing if existing

  svc = Ruflet::UI::ControlFactory.build(type.to_s, id: id&.to_s, **mapped_props)
  add_service(svc) unless services.include?(svc)
  svc
end

#servicesObject



274
275
276
# File 'lib/ruflet_ui/ruflet/page.rb', line 274

def services
  @services_container.props["_services"] ||= []
end

#services=(value) ⇒ Object



278
279
280
281
282
283
# File 'lib/ruflet_ui/ruflet/page.rb', line 278

def services=(value)
  @services_container.props["_services"] = Array(value).compact
  refresh_services_container!
  push_services_update!
  self
end

#set_clipboard(value, timeout: nil, on_result: nil) ⇒ Object



866
867
868
869
870
871
872
873
# File 'lib/ruflet_ui/ruflet/page.rb', line 866

def set_clipboard(value, timeout: nil, on_result: nil)
  invoke_clipboard_method(
    "set",
    args: { "data" => value.to_s },
    timeout: timeout,
    on_result: on_result
  )
end

#set_clipboard_files(files, timeout: nil, on_result: nil) ⇒ Object



879
880
881
882
883
884
885
886
# File 'lib/ruflet_ui/ruflet/page.rb', line 879

def set_clipboard_files(files, timeout: nil, on_result: nil)
  invoke_clipboard_method(
    "set_files",
    args: { "files" => Array(files).map(&:to_s) },
    timeout: timeout,
    on_result: on_result
  )
end

#set_clipboard_image(value, timeout: nil, on_result: nil) ⇒ Object



892
893
894
895
896
897
898
899
# File 'lib/ruflet_ui/ruflet/page.rb', line 892

def set_clipboard_image(value, timeout: nil, on_result: nil)
  invoke_clipboard_method(
    "set_image",
    args: { "data" => value },
    timeout: timeout,
    on_result: on_result
  )
end

#set_view_props(props) ⇒ Object



198
199
200
201
# File 'lib/ruflet_ui/ruflet/page.rb', line 198

def set_view_props(props)
  split_props(normalize_props(props || {}))
  self
end

#shake_detector(**props) ⇒ Object



945
946
947
# File 'lib/ruflet_ui/ruflet/page.rb', line 945

def shake_detector(**props)
  service(:shake_detector, **props)
end

#share(**props) ⇒ Object



981
982
983
# File 'lib/ruflet_ui/ruflet/page.rb', line 981

def share(**props)
  service(:share, **props)
end

#share_files(files = nil, text: nil, title: nil, subject: nil, preview_thumbnail: nil, share_position_origin: nil, download_fallback_enabled: true, mail_to_fallback_enabled: true, excluded_cupertino_activities: nil, timeout: nil, on_result: nil) ⇒ Object



1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
# File 'lib/ruflet_ui/ruflet/page.rb', line 1097

def share_files(
  files = nil,
  text: nil,
  title: nil,
  subject: nil,
  preview_thumbnail: nil,
  share_position_origin: nil,
  download_fallback_enabled: true,
  mail_to_fallback_enabled: true,
  excluded_cupertino_activities: nil,
  timeout: nil,
  on_result: nil
)
  share = ensure_share_service
  invoke(
    share,
    "share_files",
    args: compact_service_args(
      "files" => normalize_share_files(files),
      "text" => text,
      "title" => title,
      "subject" => subject,
      "preview_thumbnail" => normalize_share_file(preview_thumbnail),
      "share_position_origin" => share_position_origin,
      "download_fallback_enabled" => download_fallback_enabled,
      "mail_to_fallback_enabled" => mail_to_fallback_enabled,
      "excluded_cupertino_activities" => excluded_cupertino_activities
    ),
    timeout: timeout,
    on_result: on_result
  )
end

#share_text(text = nil, title: nil, subject: nil, preview_thumbnail: nil, share_position_origin: nil, download_fallback_enabled: true, mail_to_fallback_enabled: true, excluded_cupertino_activities: nil, timeout: nil, on_result: nil) ⇒ Object



1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
# File 'lib/ruflet_ui/ruflet/page.rb', line 1045

def share_text(
  text = nil,
  title: nil,
  subject: nil,
  preview_thumbnail: nil,
  share_position_origin: nil,
  download_fallback_enabled: true,
  mail_to_fallback_enabled: true,
  excluded_cupertino_activities: nil,
  timeout: nil,
  on_result: nil
)
  share = ensure_share_service
  invoke(
    share,
    "share_text",
    args: compact_service_args(
      "text" => text,
      "title" => title,
      "subject" => subject,
      "preview_thumbnail" => preview_thumbnail,
      "share_position_origin" => share_position_origin,
      "download_fallback_enabled" => download_fallback_enabled,
      "mail_to_fallback_enabled" => mail_to_fallback_enabled,
      "excluded_cupertino_activities" => excluded_cupertino_activities
    ),
    timeout: timeout,
    on_result: on_result
  )
end

#share_uri(uri = nil, share_position_origin: nil, excluded_cupertino_activities: nil, timeout: nil, on_result: nil) ⇒ Object



1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
# File 'lib/ruflet_ui/ruflet/page.rb', line 1076

def share_uri(
  uri = nil,
  share_position_origin: nil,
  excluded_cupertino_activities: nil,
  timeout: nil,
  on_result: nil
)
  share = ensure_share_service
  invoke(
    share,
    "share_uri",
    args: compact_service_args(
      "uri" => uri,
      "share_position_origin" => share_position_origin,
      "excluded_cupertino_activities" => excluded_cupertino_activities
    ),
    timeout: timeout,
    on_result: on_result
  )
end

#shared_preferences(**props) ⇒ Object



285
286
287
288
289
# File 'lib/ruflet_ui/ruflet/page.rb', line 285

def shared_preferences(**props)
  return service(:shared_preferences, **props) unless props.empty?

  @shared_preferences_proxy
end

#show_dialog(dialog_control) ⇒ Object



509
510
511
512
513
514
515
516
517
518
519
520
521
# File 'lib/ruflet_ui/ruflet/page.rb', line 509

def show_dialog(dialog_control)
  return self unless dialog_control

  return self if dialog_open?(dialog_control)

  dialog_control.props["open"] = true
  remove_existing_singleton_dialogs(dialog_control)
  @dialogs << dialog_control unless @dialogs.include?(dialog_control)
  refresh_dialogs_container!
  send_view_patch unless @dialogs_container.wire_id
  push_dialogs_update!
  self
end

#show_drawer(timeout: 10, on_result: nil) ⇒ Object

Raises:

  • (ArgumentError)


458
459
460
461
462
463
# File 'lib/ruflet_ui/ruflet/page.rb', line 458

def show_drawer(timeout: 10, on_result: nil)
  raise ArgumentError, "show_drawer requires drawer" unless drawer

  invoke_current_view("show_drawer", timeout: timeout, on_result: on_result)
  self
end

#show_end_drawer(timeout: 10, on_result: nil) ⇒ Object

Raises:

  • (ArgumentError)


470
471
472
473
474
475
# File 'lib/ruflet_ui/ruflet/page.rb', line 470

def show_end_drawer(timeout: 10, on_result: nil)
  raise ArgumentError, "show_end_drawer requires end_drawer" unless end_drawer

  invoke_current_view("show_end_drawer", timeout: timeout, on_result: on_result)
  self
end

#snack_bar=(value) ⇒ Object



490
491
492
493
494
# File 'lib/ruflet_ui/ruflet/page.rb', line 490

def snack_bar=(value)
  @snack_bar = value
  refresh_dialogs_container!
  push_dialogs_update! if @dialogs_container_mounted
end

#snackbar=(value) ⇒ Object



496
497
498
# File 'lib/ruflet_ui/ruflet/page.rb', line 496

def snackbar=(value)
  self.snack_bar = value
end

#start_window_dragging(timeout: 10, on_result: nil) ⇒ Object



713
714
715
# File 'lib/ruflet_ui/ruflet/page.rb', line 713

def start_window_dragging(timeout: 10, on_result: nil)
  invoke_window("start_dragging", timeout: timeout, on_result: on_result)
end

#start_window_resizing(edge, timeout: 10, on_result: nil) ⇒ Object



717
718
719
720
721
722
723
724
# File 'lib/ruflet_ui/ruflet/page.rb', line 717

def start_window_resizing(edge, timeout: 10, on_result: nil)
  invoke_window(
    "start_resizing",
    args: { "edge" => normalize_service_value(edge) },
    timeout: timeout,
    on_result: on_result
  )
end

#storage_paths(**props) ⇒ Object



977
978
979
# File 'lib/ruflet_ui/ruflet/page.rb', line 977

def storage_paths(**props)
  service(:storage_paths, **props)
end

#supports_close_for_launch_mode(mode, timeout: 10, on_result: nil) ⇒ Object



604
605
606
607
# File 'lib/ruflet_ui/ruflet/page.rb', line 604

def supports_close_for_launch_mode(mode, timeout: 10, on_result: nil)
  url_launcher = ensure_url_launcher_service
  invoke(url_launcher, "supports_close_for_launch_mode", args: { "mode" => mode }, timeout: timeout, on_result: on_result)
end

#supports_launch_mode(mode, timeout: 10, on_result: nil) ⇒ Object



599
600
601
602
# File 'lib/ruflet_ui/ruflet/page.rb', line 599

def supports_launch_mode(mode, timeout: 10, on_result: nil)
  url_launcher = ensure_url_launcher_service
  invoke(url_launcher, "supports_launch_mode", args: { "mode" => mode }, timeout: timeout, on_result: on_result)
end

#take_screenshot(name, timeout: 10, on_result: nil) ⇒ Object



756
757
758
# File 'lib/ruflet_ui/ruflet/page.rb', line 756

def take_screenshot(name, timeout: 10, on_result: nil)
  invoke_tester("take_screenshot", args: { "name" => name }, timeout: timeout, on_result: on_result)
end

#tap(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil) ⇒ Object



760
761
762
763
# File 'lib/ruflet_ui/ruflet/page.rb', line 760

def tap(finder_id = nil, options = nil, finder_index: nil, timeout: 10, on_result: nil)
  finder_index = options[:finder_index] || options["finder_index"] if options.is_a?(Hash) && finder_index.nil?
  invoke_tester_finder("tap", finder_id, finder_index: finder_index, timeout: timeout, on_result: on_result)
end

#tap_at(offset = nil, timeout: 10, on_result: nil) ⇒ Object



780
781
782
# File 'lib/ruflet_ui/ruflet/page.rb', line 780

def tap_at(offset = nil, timeout: 10, on_result: nil)
  invoke_tester_at("tap_at", offset, timeout: timeout, on_result: on_result)
end

#tester(**props) ⇒ Object



325
326
327
# File 'lib/ruflet_ui/ruflet/page.rb', line 325

def tester(**props)
  service(:tester, **props)
end

#tester_pump(options = nil, duration: nil, timeout: 10, on_result: nil) ⇒ Object



726
727
728
729
# File 'lib/ruflet_ui/ruflet/page.rb', line 726

def tester_pump(options = nil, duration: nil, timeout: 10, on_result: nil)
  duration = options[:duration] || options["duration"] if options.is_a?(Hash) && duration.nil?
  invoke_tester("pump", args: compact_service_args("duration" => duration), timeout: timeout, on_result: on_result)
end

#tester_pump_and_settle(options = nil, duration: nil, timeout: 10, on_result: nil) ⇒ Object



731
732
733
734
# File 'lib/ruflet_ui/ruflet/page.rb', line 731

def tester_pump_and_settle(options = nil, duration: nil, timeout: 10, on_result: nil)
  duration = options[:duration] || options["duration"] if options.is_a?(Hash) && duration.nil?
  invoke_tester("pump_and_settle", args: compact_service_args("duration" => duration), timeout: timeout, on_result: on_result)
end

#tester_teardown(timeout: 10, on_result: nil) ⇒ Object



842
843
844
# File 'lib/ruflet_ui/ruflet/page.rb', line 842

def tester_teardown(timeout: 10, on_result: nil)
  invoke_tester("teardown", timeout: timeout, on_result: on_result)
end

#titleObject



203
204
205
# File 'lib/ruflet_ui/ruflet/page.rb', line 203

def title
  @page_props["title"]
end

#title=(value) ⇒ Object



207
208
209
# File 'lib/ruflet_ui/ruflet/page.rb', line 207

def title=(value)
  @page_props["title"] = value
end

#update(control_or_id = nil, **props) ⇒ Object



1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
# File 'lib/ruflet_ui/ruflet/page.rb', line 1169

def update(control_or_id = nil, **props)
  if control_or_id.nil? && props.empty?
    send_view_patch
    return self
  end

  if page_control_target?(control_or_id)
    split_props(normalize_props(props))
    send_view_patch
    return self
  end

  control = resolve_control(control_or_id)
  return self unless control
  wire_id = control.wire_id
  if wire_id.nil?
    # Events can race with navigation/disposal; never emit patch_control with nil id.
    refresh_control_indexes!
    wire_id = control.wire_id
  end
  return self if wire_id.nil?

  patch = normalize_props(props)
  if text_maps_to_content?(control, patch)
    patch["content"] = patch.delete("text")
  end

  # Keep runtime control tree aligned with incremental patches.
  if patch.key?("controls")
    control.children.clear
    Array(patch["controls"]).each { |child| control.children << child if child.is_a?(Control) }
  end

  visited = Set.new
  patch.each_value { |value| register_embedded_value(value, visited) }
  patch.each { |k, v| control.props[k] = v }

  patch_ops = patch.map { |k, v| [0, 0, k, serialize_patch_value(v)] }

  send_message(Protocol::ACTIONS[:patch_control], {
    "id" => wire_id,
    "patch" => [[0], *patch_ops]
  })

  self
end

#upload(files, timeout: nil, on_result: nil) ⇒ Object



672
673
674
675
676
677
678
679
# File 'lib/ruflet_ui/ruflet/page.rb', line 672

def upload(files, timeout: nil, on_result: nil)
  invoke_file_picker(
    "upload",
    { "files" => Array(files).map { |file| normalize_service_value(file) } },
    timeout: timeout,
    on_result: on_result
  )
end

#upload_files(files, timeout: nil, on_result: nil) ⇒ Object



681
682
683
# File 'lib/ruflet_ui/ruflet/page.rb', line 681

def upload_files(files, timeout: nil, on_result: nil)
  upload(files, timeout: timeout, on_result: on_result)
end

#url_launcher(**props) ⇒ Object



973
974
975
# File 'lib/ruflet_ui/ruflet/page.rb', line 973

def url_launcher(**props)
  service(:url_launcher, **props)
end

#user_accelerometer(**props) ⇒ Object



933
934
935
# File 'lib/ruflet_ui/ruflet/page.rb', line 933

def user_accelerometer(**props)
  service(:user_accelerometer, **props)
end

#vertical_alignmentObject



219
220
221
# File 'lib/ruflet_ui/ruflet/page.rb', line 219

def vertical_alignment
  @page_props["vertical_alignment"] || @view_props["vertical_alignment"]
end

#vertical_alignment=(value) ⇒ Object



223
224
225
226
227
# File 'lib/ruflet_ui/ruflet/page.rb', line 223

def vertical_alignment=(value)
  v = normalize_value("vertical_alignment", value)
  @page_props["vertical_alignment"] = v
  @view_props["vertical_alignment"] = v
end

#vibrate(timeout: 10, on_result: nil) ⇒ Object



862
863
864
# File 'lib/ruflet_ui/ruflet/page.rb', line 862

def vibrate(timeout: 10, on_result: nil)
  invoke_haptic_feedback("vibrate", timeout: timeout, on_result: on_result)
end

#wait_until_ready_to_show(timeout: 10, on_result: nil) ⇒ Object



693
694
695
# File 'lib/ruflet_ui/ruflet/page.rb', line 693

def wait_until_ready_to_show(timeout: 10, on_result: nil)
  invoke_window("wait_until_ready_to_show", timeout: timeout, on_result: on_result)
end

#wakelock(**props) ⇒ Object



291
292
293
294
295
# File 'lib/ruflet_ui/ruflet/page.rb', line 291

def wakelock(**props)
  return service(:wakelock, **props) unless props.empty?

  @wakelock_proxy
end

#window(**props) ⇒ Object



321
322
323
# File 'lib/ruflet_ui/ruflet/page.rb', line 321

def window(**props)
  service(:window, **props)
end

#window_to_front(timeout: 10, on_result: nil) ⇒ Object



697
698
699
# File 'lib/ruflet_ui/ruflet/page.rb', line 697

def window_to_front(timeout: 10, on_result: nil)
  invoke_window("to_front", timeout: timeout, on_result: on_result)
end