Module: Everywhere::Config::DesktopUi

Included in:
Everywhere::Config
Defined in:
lib/everywhere/config/desktop_ui.rb

Constant Summary collapse

WINDOW_TITLE_BARS =

Desktop window chrome. Desktop-only: on mobile the OS owns the frame, so mobile builds ignore this section entirely.

window:
title_bar: overlay   # decorated (default) | overlay | frameless
title: false         # draw the title text (default true)
size: [1100, 750]    # initial inner size
min_size: [600, 400]
resizable: true
drag_height: 28      # top strip that drags the window; 0 turns it off

Every reader returns nil when the key is absent so to_shell_hash drops it and the shell keeps its own default — there is exactly one place each default lives, and it's the Rust side.

overlay is the macOS "traffic lights floating over your content" look (TitleBarStyle::Overlay + hidden title). Windows and Linux have no such style, so the shell falls back to frameless there and the page draws its own controls via Everywhere.window.

%w[decorated overlay frameless].freeze

Instance Method Summary collapse

Instance Method Details

Custom native menu items (macOS app menu). Each entry: label + path (+ optional accelerator), or "separator". Clicks arrive in the page as "everywhere:menu" events and navigate via Turbo.



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/everywhere/config/desktop_ui.rb', line 9

def menu
  entries = @data["menu"]
  return [] unless entries.is_a?(Array)

  entries.filter_map do |item|
    if item == "separator" || (item.is_a?(Hash) && item["separator"])
      { "separator" => true }
    elsif item.is_a?(Hash) && item["label"] && item["path"]
      { "label" => item["label"], "path" => item["path"],
        "accelerator" => item["accelerator"] }.compact
    end
  end
end

#trayObject

System tray: same entry shape as menu: plus action: quit | show.

tray:
- label: "Open My App"
  action: show
- label: "New Note"
  path: /notes/new
- separator
- label: Quit
  action: quit


33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/everywhere/config/desktop_ui.rb', line 33

def tray
  entries = @data["tray"]
  return [] unless entries.is_a?(Array)

  entries.filter_map do |item|
    if item == "separator" || (item.is_a?(Hash) && item["separator"])
      { "separator" => true }
    elsif item.is_a?(Hash) && item["label"] && (item["path"] || item["action"])
      { "label" => item["label"], "path" => item["path"],
        "action" => item["action"] }.compact
    end
  end
end

#windowObject



68
69
70
71
# File 'lib/everywhere/config/desktop_ui.rb', line 68

def window
  section = @data["window"]
  section.is_a?(Hash) ? section : {}
end

#window_drag_heightObject

How much of the top of the page drags the window, in CSS pixels. Only meaningful for overlay/frameless, where there's no system title bar left to grab. nil leaves the shell's 28px default (the height of the macOS traffic-light band); 0 turns dragging off for an app that wants to place its own drag regions.



91
92
93
94
# File 'lib/everywhere/config/desktop_ui.rb', line 91

def window_drag_height
  value = window["drag_height"]
  value.to_f if value.is_a?(Numeric) && !value.negative?
end

#window_errorsObject



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/everywhere/config/desktop_ui.rb', line 110

def window_errors
  raw = @data["window"]
  return [] if raw.nil?
  return ["window: must be a mapping"] unless raw.is_a?(Hash)

  errors = []
  bar = raw["title_bar"]
  if bar && !WINDOW_TITLE_BARS.include?(bar.to_s)
    errors << "window.title_bar #{bar.to_s.inspect} must be one of " \
              "#{WINDOW_TITLE_BARS.join(" / ")}"
  end

  errors += %w[size min_size].filter_map do |key|
    next if raw[key].nil? || window_dimensions(key)

    "window.#{key} must be two positive numbers, like [1100, 750]"
  end

  drag = raw["drag_height"]
  unless drag.nil? || (drag.is_a?(Numeric) && !drag.negative?)
    errors << "window.drag_height must be a number of pixels (0 turns dragging off)"
  end

  errors + %w[title resizable].filter_map do |key|
    next if raw[key].nil? || boolean_or_nil(raw[key]) == raw[key]

    "window.#{key} must be true or false"
  end
end

#window_min_sizeObject



84
# File 'lib/everywhere/config/desktop_ui.rb', line 84

def window_min_size = window_dimensions("min_size")

#window_resizableObject



81
# File 'lib/everywhere/config/desktop_ui.rb', line 81

def window_resizable = boolean_or_nil(window["resizable"])

#window_shell_hashObject

The window subset the shell needs. nil (absent from everywhere.json) when the app declares nothing, so the shell's own defaults stand untouched.



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/everywhere/config/desktop_ui.rb', line 98

def window_shell_hash
  hash = {
    "title_bar" => window_title_bar,
    "title" => window_title,
    "resizable" => window_resizable,
    "size" => window_size,
    "min_size" => window_min_size,
    "drag_height" => window_drag_height
  }.compact
  hash unless hash.empty?
end

#window_sizeObject



83
# File 'lib/everywhere/config/desktop_ui.rb', line 83

def window_size = window_dimensions("size")

#window_titleObject

Tri-state, like native_ios_lazy_load_tabs: an absent key leaves the shell on its default rather than forcing one.



80
# File 'lib/everywhere/config/desktop_ui.rb', line 80

def window_title = boolean_or_nil(window["title"])

#window_title_barObject



73
74
75
76
# File 'lib/everywhere/config/desktop_ui.rb', line 73

def window_title_bar
  value = window["title_bar"].to_s
  value if WINDOW_TITLE_BARS.include?(value)
end