-
Notifications
You must be signed in to change notification settings - Fork 1
/
UrlHandler2.lua
146 lines (126 loc) · 4.29 KB
/
UrlHandler2.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
139
140
141
142
143
144
145
146
local obj = {}
obj.__index = obj
-- Metadata
obj.name = "UrlHandler"
obj.version = "0.1"
obj.author = "Andriy Kulynyak <[email protected]>"
obj.license = "MIT - https://opensource.org/licenses/MIT"
obj.logger = hs.logger.new("UrlHandler")
obj.customBrowsers = {}
obj.widgetWidth = 20
obj._predefinedBrowsers = {
{id = "com.apple.Safari", name = "Safari", label = "safari"},
{id = "com.google.Chrome", name = "Chrome", label = "chrome"},
{id = "com.operasoftware.Opera", name = "Opera", label = "opera"},
{id = "com.vivaldi.Vivaldi", name = "Vivaldi", label = "vivaldi"},
{id = "com.brave.Browser", name = "Brave", label = "brave"},
{id = "org.mozilla.firefox", name = "Firefox", label = "firefox"}, {
id = "org.mozilla.firefoxdeveloperedition",
name = "Firefox Dev",
label = "firefox_dev"
}
}
obj._label2BundleMap = {}
local function mapByFn(keyFn, valFn, base, override)
local mix = hs.fnutils.concat(base, override);
local tmp = {}
for _, item in ipairs(mix) do tmp[keyFn(item)] = valFn(item) end
local result = {}
for _, item in pairs(tmp) do table.insert(result, item) end
return result
end
local function sortByName(left, right) return left.name < right.name end
local function installedBrowsers(base, overrides)
local keyFn = function(x) return x.id end
local valFn = function(x) return x end
local mixed = mapByFn(keyFn, valFn, base, overrides)
local result = hs.fnutils.filter(mixed, function(x)
return hs.application.pathForBundleID(x.id)
end)
table.sort(result, sortByName)
for _, item in pairs(result) do
item.icon = hs.image.imageFromAppBundle(item.id)
end
return result
end
local function mkLabel2BundleMap(browsers)
local result = {}
for _, item in ipairs(browsers) do
if (item.label == nil) then
obj.logger.ef("Key 'label' have to be defined for item: %s",
hs.inspect(item))
else
result[item.label] = item
end
end
return result
end
local function browsersByLabels(map, labels)
local result = {}
if (labels == nil) then
for _, item in pairs(map) do table.insert(result, item) end
else
for _, label in ipairs(labels) do
table.insert(result, map[label])
end
end
table.sort(result, sortByName)
return result
end
local function mkMenuData(browsers, url)
menuData = {}
for _, item in ipairs(browsers) do
table.insert(menuData, {
text = item.name,
image = item.icon,
id = item.id,
label = item.label,
url = url
})
end
table.insert(menuData, {text = "Cancel", id = "cancel"})
return menuData
end
local function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
-- TODO add an althernative chooser widget (like an application List?)
-- actionFn(action)
local function showChooser(map, labels, url, actionFn, widgetWidth)
local menuData = mkMenuData(browsersByLabels(map, labels), url)
local selectorobj = hs.chooser.new(actionFn)
selectorobj:width(widgetWidth)
selectorobj:choices(menuData)
selectorobj:refreshChoicesCallback()
local len = tablelength(menuData) + 1
if len > 10 then len = 10 end
selectorobj:rows(len)
selectorobj:show()
end
function handleSelectBrowserAction(action)
if (action == nil or action.id == 'cancel' or action.url == nil) then
return
end
hs.application.launchOrFocusByBundleID(action.id)
hs.timer.doAfter(1, function()
-- ! TODO reschedule if application still starting
-- ! or window is not yet shown
hs.urlevent.openURLWithBundle(action.url, action.id);
end)
end
function obj:_showChooser(labels, url)
showChooser(self._label2BundleMap, labels, url, handleSelectBrowserAction,
self.widgetWidth)
end
function obj:start()
local browsers = installedBrowsers(self._predefinedBrowsers,
self.customBrowsers)
self._label2BundleMap = mkLabel2BundleMap(browsers)
self:_showChooser({'opera', 'chrome', 'firefox'},
"https://github.com/kulynyak")
-- obj.logger.df("menuData = %s", hs.inspect(menuData))
return self
end
return obj