ruflet_core 0.0.21 → 0.0.23

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ruflet/version.rb +1 -1
  3. data/lib/ruflet_ui/ruflet/dsl.rb +76 -0
  4. data/lib/ruflet_ui/ruflet/event.rb +3 -2
  5. data/lib/ruflet_ui/ruflet/events/gesture_events.rb +2 -1
  6. data/lib/ruflet_ui/ruflet/icons/cupertino/cupertino_icons.rb +46 -26
  7. data/lib/ruflet_ui/ruflet/icons/material/material_icons.rb +61 -26
  8. data/lib/ruflet_ui/ruflet/page.rb +242 -4
  9. data/lib/ruflet_ui/ruflet/ui/control_factory.rb +2 -0
  10. data/lib/ruflet_ui/ruflet/ui/control_methods.rb +4 -0
  11. data/lib/ruflet_ui/ruflet/ui/control_registry.rb +20 -1
  12. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheet_control.rb +1 -1
  13. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheetaction_control.rb +1 -1
  14. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactivityindicator_control.rb +1 -1
  15. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoalertdialog_control.rb +1 -1
  16. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoappbar_control.rb +1 -1
  17. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobottomsheet_control.rb +1 -1
  18. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobutton_control.rb +1 -1
  19. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocheckbox_control.rb +1 -1
  20. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenu_control.rb +1 -1
  21. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenuaction_control.rb +1 -1
  22. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodatepicker_control.rb +1 -1
  23. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodialogaction_control.rb +1 -1
  24. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinofilledbutton_control.rb +1 -1
  25. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinolisttile_control.rb +1 -1
  26. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinonavigationbar_control.rb +1 -1
  27. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinopicker_control.rb +1 -1
  28. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoradio_control.rb +1 -1
  29. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinosegmentedbutton_control.rb +1 -1
  30. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslider_control.rb +1 -1
  31. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslidingsegmentedbutton_control.rb +1 -1
  32. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoswitch_control.rb +1 -1
  33. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotextfield_control.rb +1 -1
  34. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotimerpicker_control.rb +1 -1
  35. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotintedbutton_control.rb +1 -1
  36. data/lib/ruflet_ui/ruflet/ui/controls/materials/ad_controls.rb +45 -0
  37. data/lib/ruflet_ui/ruflet/ui/controls/materials/animation_extension_controls.rb +29 -0
  38. data/lib/ruflet_ui/ruflet/ui/controls/materials/chart_controls.rb +56 -279
  39. data/lib/ruflet_ui/ruflet/ui/controls/materials/code_editor_control.rb +42 -0
  40. data/lib/ruflet_ui/ruflet/ui/controls/materials/color_picker_controls.rb +34 -0
  41. data/lib/ruflet_ui/ruflet/ui/controls/materials/datatable2_controls.rb +41 -0
  42. data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdownm2_control.rb +1 -1
  43. data/lib/ruflet_ui/ruflet/ui/controls/materials/map_control.rb +80 -0
  44. data/lib/ruflet_ui/ruflet/ui/controls/materials/ruflet_controls.rb +62 -0
  45. data/lib/ruflet_ui/ruflet/ui/controls/materials/video_control.rb +1 -2
  46. data/lib/ruflet_ui/ruflet/ui/controls/materials/webview_control.rb +5 -30
  47. data/lib/ruflet_ui/ruflet/ui/controls/ruflet_controls.rb +60 -0
  48. data/lib/ruflet_ui/ruflet/ui/controls/shared/browsercontextmenu_control.rb +17 -0
  49. data/lib/ruflet_ui/ruflet/ui/controls/shared/ruflet_app_control.rb +3 -3
  50. data/lib/ruflet_ui/ruflet/ui/controls/shared/serviceregistry_control.rb +5 -1
  51. data/lib/ruflet_ui/ruflet/ui/cupertino_control_methods.rb +2 -0
  52. data/lib/ruflet_ui/ruflet/ui/material_control_methods.rb +110 -6
  53. data/lib/ruflet_ui/ruflet/ui/material_control_registry.rb +23 -8
  54. data/lib/ruflet_ui/ruflet/ui/platform_control_contracts.rb +392 -0
  55. data/lib/ruflet_ui/ruflet/ui/platform_control_methods.rb +35 -0
  56. data/lib/ruflet_ui/ruflet/ui/services/current_service_methods.rb +220 -0
  57. data/lib/ruflet_ui/ruflet/ui/services/ruflet/camera_control.rb +88 -0
  58. data/lib/ruflet_ui/ruflet/ui/services/ruflet_services.rb +4 -0
  59. data/lib/ruflet_ui/ruflet/ui/shared_control_forwarders.rb +75 -0
  60. data/lib/ruflet_ui.rb +6 -9
  61. metadata +9 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96131a85e131d05e9d2bbe07eb2bb3ceba97aeb2112301d4d6137d7067e81c3c
4
- data.tar.gz: 21245edeb2dc44b0cfe457c34678a552929ef813b2309494453582b717558209
3
+ metadata.gz: b7c6e921c44aa57801c14bb2bce64088b8b92b3759d6476a76db284cc74f5e00
4
+ data.tar.gz: 92970e55579384280481a14a37d76724a0f820be79281f668b462321bb4eb005
5
5
  SHA512:
6
- metadata.gz: 1889c987529cb0915da64b09e534d8d132c34c1ec1553d099f3a81340744d57a5a48a8325ae77f6a4b19f7537440dae1a6c77a5dc7d632548b7dfe297de857f7
7
- data.tar.gz: ce99b6ffcae8ccc7c6837df5f53fe936bd1df521c73642a60957a3552a53500b5626a2d0611d571cc069efca0c597194ff4ec627916b73d07081e6046cf96611
6
+ metadata.gz: 733714ee9e1c916d6c5b4f402163bd7caaa34df1fd4c4f07e0e49dbcb4e324b8287c70fe753d35b376039e02d227810a7856bc5a02cb8920ee51069862533462
7
+ data.tar.gz: fbf901236bac15ec93b15175e93bc2b49bfb3c17ac26dd0fd453085900d7e180fec4b76fc7b54fca265823f3e1b618cdfc91e1ed12b09e3b59bb5ad21a921c79
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ruflet
4
- VERSION = "0.0.21" unless const_defined?(:VERSION)
4
+ VERSION = "0.0.23" unless const_defined?(:VERSION)
5
5
  end
@@ -51,6 +51,16 @@ module Ruflet
51
51
  def control(type, **props, &block) = _pending_app.control(type, **props, &block)
52
52
  def widget(type, **props, &block) = _pending_app.widget(type, **props, &block)
53
53
  def service(type, **props, &block) = _pending_app.service(type, **props, &block)
54
+ def view(children = nil, **props, &block) = _pending_app.view(children, **props, &block)
55
+ def base_page(**props, &block) = _pending_app.base_page(**props, &block)
56
+ def basepage(**props, &block) = _pending_app.basepage(**props, &block)
57
+ def dialogs(controls = nil, **props) = _pending_app.dialogs(controls, **props)
58
+ def pagelet(content = nil, **props, &block) = _pending_app.pagelet(content, **props, &block)
59
+ def ruflet_app(**props) = _pending_app.ruflet_app(**props)
60
+ def rufletapp(**props) = _pending_app.rufletapp(**props)
61
+ def service_registry(services = nil, **props) = _pending_app.service_registry(services, **props)
62
+ def serviceregistry(services = nil, **props) = _pending_app.serviceregistry(services, **props)
63
+ def window(**props) = _pending_app.window(**props)
54
64
  def column(children = nil, **props, &block) = _pending_app.column(children, **props, &block)
55
65
  def center(**props, &block) = _pending_app.center(**props, &block)
56
66
  def row(children = nil, **props, &block) = _pending_app.row(children, **props, &block)
@@ -62,7 +72,31 @@ module Ruflet
62
72
  def animatedswitcher(content = nil, **props) = _pending_app.animatedswitcher(content, **props)
63
73
  def animation(duration = nil, **props) = _pending_app.animation(duration, **props)
64
74
  def animation_style(**props) = _pending_app.animation_style(**props)
75
+ def accelerometer(**props) = _pending_app.accelerometer(**props)
65
76
  def audio(**props) = _pending_app.audio(**props)
77
+ def audio_recorder(**props) = _pending_app.audio_recorder(**props)
78
+ def barometer(**props) = _pending_app.barometer(**props)
79
+ def battery(**props) = _pending_app.battery(**props)
80
+ def browser_context_menu(**props) = _pending_app.browser_context_menu(**props)
81
+ def camera(**props) = _pending_app.camera(**props)
82
+ def connectivity(**props) = _pending_app.connectivity(**props)
83
+ def file_picker(**props) = _pending_app.file_picker(**props)
84
+ def flashlight(**props) = _pending_app.flashlight(**props)
85
+ def geolocator(**props) = _pending_app.geolocator(**props)
86
+ def gyroscope(**props) = _pending_app.gyroscope(**props)
87
+ def haptic_feedback(**props) = _pending_app.haptic_feedback(**props)
88
+ def magnetometer(**props) = _pending_app.magnetometer(**props)
89
+ def permission_handler(**props) = _pending_app.permission_handler(**props)
90
+ def screen_brightness(**props) = _pending_app.screen_brightness(**props)
91
+ def secure_storage(**props) = _pending_app.secure_storage(**props)
92
+ def semantics_service(**props) = _pending_app.semantics_service(**props)
93
+ def shake_detector(**props) = _pending_app.shake_detector(**props)
94
+ def share(**props) = _pending_app.share(**props)
95
+ def shared_preferences(**props) = _pending_app.shared_preferences(**props)
96
+ def storage_paths(**props) = _pending_app.storage_paths(**props)
97
+ def url_launcher(**props) = _pending_app.url_launcher(**props)
98
+ def user_accelerometer(**props) = _pending_app.user_accelerometer(**props)
99
+ def wakelock(**props) = _pending_app.wakelock(**props)
66
100
  def auto_complete(suggestions = nil, **props) = _pending_app.auto_complete(suggestions, **props)
67
101
  def autocomplete(suggestions = nil, **props) = _pending_app.autocomplete(suggestions, **props)
68
102
  def auto_complete_suggestion(key = nil, **props) = _pending_app.auto_complete_suggestion(key, **props)
@@ -70,6 +104,8 @@ module Ruflet
70
104
  def autocompletesuggestion(key = nil, **props) = _pending_app.autocompletesuggestion(key, **props)
71
105
  def context_menu(content = nil, **props) = _pending_app.context_menu(content, **props)
72
106
  def contextmenu(content = nil, **props) = _pending_app.contextmenu(content, **props)
107
+ def context_menu_action(content = nil, **props) = _pending_app.context_menu_action(content, **props)
108
+ def contextmenuaction(content = nil, **props) = _pending_app.contextmenuaction(content, **props)
73
109
  def autofill_group(content = nil, **props) = _pending_app.autofill_group(content, **props)
74
110
  def autofillgroup(content = nil, **props) = _pending_app.autofillgroup(content, **props)
75
111
  def hero(content = nil, **props) = _pending_app.hero(content, **props)
@@ -133,6 +169,14 @@ module Ruflet
133
169
  def polygonmarker(**props) = _pending_app.polygonmarker(**props)
134
170
  def simple_attribution(**props) = _pending_app.simple_attribution(**props)
135
171
  def simpleattribution(**props) = _pending_app.simpleattribution(**props)
172
+ def map_layer(**props) = _pending_app.map_layer(**props)
173
+ def maplayer(**props) = _pending_app.maplayer(**props)
174
+ def rich_attribution(attributions = nil, **props) = _pending_app.rich_attribution(attributions, **props)
175
+ def richattribution(attributions = nil, **props) = _pending_app.richattribution(attributions, **props)
176
+ def image_source_attribution(image = nil, **props) = _pending_app.image_source_attribution(image, **props)
177
+ def imagesourceattribution(image = nil, **props) = _pending_app.imagesourceattribution(image, **props)
178
+ def text_source_attribution(text = nil, **props) = _pending_app.text_source_attribution(text, **props)
179
+ def textsourceattribution(text = nil, **props) = _pending_app.textsourceattribution(text, **props)
136
180
  def list_view(children = nil, **props) = _pending_app.list_view(children, **props)
137
181
  def listview(children = nil, **props) = _pending_app.listview(children, **props)
138
182
  def menu_bar(children = nil, **props) = _pending_app.menu_bar(children, **props)
@@ -160,6 +204,13 @@ module Ruflet
160
204
  def datarow(cells = nil, **props) = _pending_app.datarow(cells, **props)
161
205
  def data_cell(content = nil, **props) = _pending_app.data_cell(content, **props)
162
206
  def datacell(content = nil, **props) = _pending_app.datacell(content, **props)
207
+ def option(key = nil, **props) = _pending_app.option(key, **props)
208
+ def data_table2(columns = nil, **props) = _pending_app.data_table2(columns, **props)
209
+ def datatable2(columns = nil, **props) = _pending_app.datatable2(columns, **props)
210
+ def data_column2(label = nil, **props) = _pending_app.data_column2(label, **props)
211
+ def datacolumn2(label = nil, **props) = _pending_app.datacolumn2(label, **props)
212
+ def data_row2(cells = nil, **props) = _pending_app.data_row2(cells, **props)
213
+ def datarow2(cells = nil, **props) = _pending_app.datarow2(cells, **props)
163
214
  def expansion_tile(children = nil, **props) = _pending_app.expansion_tile(children, **props)
164
215
  def expansiontile(children = nil, **props) = _pending_app.expansiontile(children, **props)
165
216
  def expansion_panel(**props) = _pending_app.expansion_panel(**props)
@@ -178,6 +229,9 @@ module Ruflet
178
229
  def pageview(children = nil, **props) = _pending_app.pageview(children, **props)
179
230
  def progress_ring(**props) = _pending_app.progress_ring(**props)
180
231
  def progressring(**props) = _pending_app.progressring(**props)
232
+ def picker(children = nil, **props) = _pending_app.picker(children, **props)
233
+ def timer_picker(**props) = _pending_app.timer_picker(**props)
234
+ def timerpicker(**props) = _pending_app.timerpicker(**props)
181
235
  def spinkit(**props) = _pending_app.spinkit(**props)
182
236
  def range_slider(**props) = _pending_app.range_slider(**props)
183
237
  def rangeslider(**props) = _pending_app.rangeslider(**props)
@@ -257,6 +311,10 @@ module Ruflet
257
311
  def snackbaraction(label = nil, **props) = _pending_app.snackbaraction(label, **props)
258
312
  def bottom_sheet(content = nil, **props) = _pending_app.bottom_sheet(content, **props)
259
313
  def bottomsheet(content = nil, **props) = _pending_app.bottomsheet(content, **props)
314
+ def action_sheet(**props) = _pending_app.action_sheet(**props)
315
+ def actionsheet(**props) = _pending_app.actionsheet(**props)
316
+ def action_sheet_action(content = nil, **props) = _pending_app.action_sheet_action(content, **props)
317
+ def actionsheetaction(content = nil, **props) = _pending_app.actionsheetaction(content, **props)
260
318
  def markdown(value = nil, **props) = _pending_app.markdown(value, **props)
261
319
  def floating_action_button(**props) = _pending_app.floating_action_button(**props)
262
320
  def floatingactionbutton(**props) = _pending_app.floatingactionbutton(**props)
@@ -319,6 +377,24 @@ module Ruflet
319
377
  def web_view(**props) = _pending_app.web_view(**props)
320
378
  def webview(**props) = _pending_app.webview(**props)
321
379
  def video(**props) = _pending_app.video(**props)
380
+ def block_picker(**props) = _pending_app.block_picker(**props)
381
+ def blockpicker(**props) = _pending_app.blockpicker(**props)
382
+ def color_picker(**props) = _pending_app.color_picker(**props)
383
+ def colorpicker(**props) = _pending_app.colorpicker(**props)
384
+ def hue_ring_picker(**props) = _pending_app.hue_ring_picker(**props)
385
+ def hueringpicker(**props) = _pending_app.hueringpicker(**props)
386
+ def material_picker(**props) = _pending_app.material_picker(**props)
387
+ def materialpicker(**props) = _pending_app.materialpicker(**props)
388
+ def multiple_choice_block_picker(**props) = _pending_app.multiple_choice_block_picker(**props)
389
+ def multiplechoiceblockpicker(**props) = _pending_app.multiplechoiceblockpicker(**props)
390
+ def slide_picker(**props) = _pending_app.slide_picker(**props)
391
+ def slidepicker(**props) = _pending_app.slidepicker(**props)
392
+ def banner_ad(**props) = _pending_app.banner_ad(**props)
393
+ def bannerad(**props) = _pending_app.bannerad(**props)
394
+ def interstitial_ad(**props) = _pending_app.interstitial_ad(**props)
395
+ def interstitialad(**props) = _pending_app.interstitialad(**props)
396
+ def native_ad(**props) = _pending_app.native_ad(**props)
397
+ def nativead(**props) = _pending_app.nativead(**props)
322
398
  def code_editor(value = nil, **props) = _pending_app.code_editor(value, **props)
323
399
  def codeeditor(value = nil, **props) = _pending_app.codeeditor(value, **props)
324
400
  def lottie(src = nil, **props) = _pending_app.lottie(src, **props)
@@ -30,9 +30,10 @@ module Ruflet
30
30
 
31
31
  def parse_data(raw)
32
32
  return raw unless raw.is_a?(String)
33
+ return raw unless Object.const_defined?(:JSON)
33
34
 
34
- JSON.parse(raw)
35
- rescue JSON::ParserError
35
+ Object.const_get(:JSON).parse(raw)
36
+ rescue StandardError
36
37
  raw
37
38
  end
38
39
 
@@ -48,7 +48,8 @@ module Ruflet
48
48
  raw = data.is_a?(Hash) ? stringify_keys(data) : data
49
49
  value =
50
50
  if raw.is_a?(Hash)
51
- raw["value"] || raw["v"] || raw["data"] || raw["state"] || raw["route"]
51
+ key = %w[value v data state route].find { |candidate| raw.key?(candidate) }
52
+ key.nil? ? nil : raw[key]
52
53
  else
53
54
  raw
54
55
  end
@@ -5,46 +5,46 @@ require_relative "../icon_constant_names"
5
5
  require_relative "../cupertino_icon_lookup"
6
6
 
7
7
  module Ruflet
8
+ # Cupertino icon names, exposed as constants. Materialized on demand for the
9
+ # same reason as Ruflet::MaterialIcons -- see the note there.
8
10
  module CupertinoIcons
9
11
  module_function
10
12
 
11
- ICONS = begin
12
- source = Ruflet::CupertinoIconLookup.icon_map
13
- if source.empty?
14
- {
15
- HOME: "house",
16
- SEARCH: "search",
17
- SETTINGS: "gear",
18
- ADD: "add",
19
- CLOSE: "clear"
20
- }
21
- else
22
- source.keys.each_with_object({}) do |name, result|
23
- text = Ruflet::IconNames.constant_for(name)
24
- result[text.upcase.to_sym] = name
25
- end
26
- end.freeze
27
- end
28
-
29
- ICONS.each do |const_name, icon_name|
30
- next if const_defined?(const_name, false)
13
+ FALLBACK_ICONS = {
14
+ HOME: "house",
15
+ SEARCH: "search",
16
+ SETTINGS: "gear",
17
+ ADD: "add",
18
+ CLOSE: "clear"
19
+ }.freeze
31
20
 
32
- const_set(const_name, icon_name.to_s.downcase)
21
+ def icons
22
+ @icons ||= begin
23
+ source = Ruflet::CupertinoIconLookup.icon_map
24
+ if source.empty?
25
+ FALLBACK_ICONS
26
+ else
27
+ source.keys.each_with_object({}) do |name, result|
28
+ text = Ruflet::IconNames.constant_for(name)
29
+ result[text.upcase.to_sym] = name
30
+ end
31
+ end.freeze
32
+ end
33
33
  end
34
34
 
35
35
  def [](name)
36
- key = name.to_s.upcase.to_sym
37
- return const_get(key) if const_defined?(key, false)
36
+ icon = icons[name.to_s.upcase.to_sym]
37
+ return icon.to_s.downcase unless icon.nil?
38
38
 
39
39
  Ruflet::CupertinoIconLookup.canonical_name_for(name) || name.to_s
40
40
  end
41
41
 
42
42
  def constants(_inherit = true)
43
- ICONS.keys
43
+ icons.keys
44
44
  end
45
45
 
46
46
  def all
47
- ICONS.keys.map { |k| const_get(k) }
47
+ icons.values.map { |name| name.to_s.downcase }
48
48
  end
49
49
 
50
50
  def random
@@ -52,7 +52,27 @@ module Ruflet
52
52
  end
53
53
 
54
54
  def names
55
- ICONS.values
55
+ icons.values
56
+ end
57
+
58
+ class << self
59
+ # See Ruflet::MaterialIcons.resolve_constant.
60
+ def resolve_constant(name)
61
+ return const_get(name) if const_defined?(name, false)
62
+ return const_set(:ICONS, icons) if name == :ICONS
63
+
64
+ key = name.to_s
65
+ source = Ruflet::CupertinoIconLookup.icon_map
66
+ return const_set(name, key.downcase) if source.key?(key)
67
+
68
+ icon = icons[name]
69
+ icon.nil? ? nil : const_set(name, icon.to_s.downcase)
70
+ end
71
+
72
+ def const_missing(name)
73
+ resolved = resolve_constant(name)
74
+ resolved.nil? ? super : resolved
75
+ end
56
76
  end
57
77
  end
58
78
  end
@@ -5,46 +5,55 @@ require_relative "../icon_constant_names"
5
5
  require_relative "../material_icon_lookup"
6
6
 
7
7
  module Ruflet
8
+ # Material icon names, exposed as constants: Ruflet::MaterialIcons::HOME.
9
+ #
10
+ # The constants are materialized on demand rather than at load. Building all
11
+ # of them eagerly meant interning ~8,800 symbols, filling a hash with them and
12
+ # calling const_set ~8,800 times every time the VM opened -- on the embedded
13
+ # mruby runtime that was the single largest item in application cold start,
14
+ # and an app typically names a handful of icons. const_missing keeps the
15
+ # constant syntax working, so nothing at the call site changes.
8
16
  module MaterialIcons
9
17
  module_function
10
18
 
11
- ICONS = begin
12
- source = Ruflet::MaterialIconLookup.icon_map
13
- if source.empty?
14
- {
15
- HOME: "home",
16
- SETTINGS: "settings",
17
- SEARCH: "search",
18
- ADD: "add",
19
- CLOSE: "close"
20
- }
21
- else
22
- source.keys.each_with_object({}) do |name, result|
23
- text = Ruflet::IconNames.constant_for(name)
24
- result[text.upcase.to_sym] = name
25
- end
26
- end.freeze
27
- end
28
-
29
- ICONS.each do |const_name, icon_name|
30
- next if const_defined?(const_name, false)
19
+ FALLBACK_ICONS = {
20
+ HOME: "home",
21
+ SETTINGS: "settings",
22
+ SEARCH: "search",
23
+ ADD: "add",
24
+ CLOSE: "close"
25
+ }.freeze
31
26
 
32
- const_set(const_name, icon_name.to_s.downcase)
27
+ # Constant name -> icon name, e.g. :ACCESS_ALARM => "ACCESS_ALARM". Built on
28
+ # first use by anything that needs the whole table; single constant lookups
29
+ # do not need it at all (see const_missing).
30
+ def icons
31
+ @icons ||= begin
32
+ source = Ruflet::MaterialIconLookup.icon_map
33
+ if source.empty?
34
+ FALLBACK_ICONS
35
+ else
36
+ source.keys.each_with_object({}) do |name, result|
37
+ text = Ruflet::IconNames.constant_for(name)
38
+ result[text.upcase.to_sym] = name
39
+ end
40
+ end.freeze
41
+ end
33
42
  end
34
43
 
35
44
  def [](name)
36
- key = name.to_s.upcase.to_sym
37
- return const_get(key) if const_defined?(key, false)
45
+ icon = icons[name.to_s.upcase.to_sym]
46
+ return icon.to_s.downcase unless icon.nil?
38
47
 
39
48
  Ruflet::MaterialIconLookup.canonical_name_for(name) || name.to_s
40
49
  end
41
50
 
42
51
  def constants(_inherit = true)
43
- ICONS.keys
52
+ icons.keys
44
53
  end
45
54
 
46
55
  def all
47
- ICONS.keys.map { |k| const_get(k) }
56
+ icons.values.map { |name| name.to_s.downcase }
48
57
  end
49
58
 
50
59
  def random
@@ -52,8 +61,34 @@ module Ruflet
52
61
  end
53
62
 
54
63
  def names
55
- ICONS.values
64
+ icons.values
56
65
  end
57
66
 
67
+ class << self
68
+ # Materializes one icon constant, or returns nil when the name is not an
69
+ # icon. Callers that used to probe with const_defined?(name, false) must
70
+ # come through here instead: with deferred constants, const_defined? is
71
+ # false for every icon nobody has referenced yet.
72
+ def resolve_constant(name)
73
+ return const_get(name) if const_defined?(name, false)
74
+
75
+ # ICONS stayed a public constant for callers that want the whole table.
76
+ return const_set(:ICONS, icons) if name == :ICONS
77
+
78
+ # Most constant names are already a key of the compiled map, so the
79
+ # common case is one hash hit and never builds the reverse table.
80
+ key = name.to_s
81
+ source = Ruflet::MaterialIconLookup.icon_map
82
+ return const_set(name, key.downcase) if source.key?(key)
83
+
84
+ icon = icons[name]
85
+ icon.nil? ? nil : const_set(name, icon.to_s.downcase)
86
+ end
87
+
88
+ def const_missing(name)
89
+ resolved = resolve_constant(name)
90
+ resolved.nil? ? super : resolved
91
+ end
92
+ end
58
93
  end
59
94
  end