diff --git a/app_builder/examples/wx_demo/mix.exs b/app_builder/examples/wx_demo/mix.exs
index 88ec9fea7..d12373993 100644
--- a/app_builder/examples/wx_demo/mix.exs
+++ b/app_builder/examples/wx_demo/mix.exs
@@ -38,16 +38,22 @@ defmodule WxDemo.MixProject do
name: "WxDemo",
url_schemes: ["wxdemo"],
document_types: [
- %{
+ [
name: "WxDemo",
extensions: ["wxdemo"],
- macos_role: "Editor"
- }
+ macos: [
+ role: "Editor"
+ ]
+ ]
],
- server: WxDemo,
- macos_build_dmg: macos_notarization != nil,
- macos_notarization: macos_notarization,
- windows_build_installer: true
+ macos: [
+ build_dmg: macos_notarization != nil,
+ notarization: macos_notarization
+ ],
+ windows: [
+ server: WxDemo,
+ build_installer: true
+ ]
]
]
]
diff --git a/app_builder/lib/app_builder.ex b/app_builder/lib/app_builder.ex
index 16bc14663..b4aa840f0 100644
--- a/app_builder/lib/app_builder.ex
+++ b/app_builder/lib/app_builder.ex
@@ -1,25 +1,8 @@
defmodule AppBuilder do
def bundle(release) do
- os = os()
+ options = validate_options(release.options[:app])
- allowed_options = [
- :name,
- :server,
- icon_path: [
- macos: Application.app_dir(:wx, "examples/demo/erlang.png")
- ],
- url_schemes: [],
- document_types: [],
- additional_paths: [],
- macos_is_agent_app: false,
- macos_build_dmg: false,
- macos_notarization: nil,
- windows_build_installer: true
- ]
-
- options = Keyword.validate!(release.options[:app], allowed_options)
-
- case os do
+ case os() do
:macos ->
AppBuilder.MacOS.bundle(release, options)
@@ -34,4 +17,72 @@ defmodule AppBuilder do
{:win32, _} -> :windows
end
end
+
+ defp validate_options(options) do
+ os = os()
+
+ root_allowed_options = %{
+ all: [
+ :name,
+ :icon_path,
+ url_schemes: [],
+ document_types: [],
+ additional_paths: []
+ ],
+ macos: [
+ app_type: :regular,
+ build_dmg: false,
+ notarization: nil
+ ],
+ windows: [
+ :server,
+ build_installer: false
+ ]
+ }
+
+ document_type_allowed_options = %{
+ all: [
+ :name,
+ :extensions,
+ :icon_path
+ ],
+ macos: [
+ :role
+ ],
+ windows: []
+ }
+
+ options = validate_options(options, root_allowed_options, os)
+
+ Keyword.update!(options, :document_types, fn document_types ->
+ Enum.map(document_types, fn options ->
+ validate_options(options, document_type_allowed_options, os)
+ end)
+ end)
+ end
+
+ defp validate_options(options, allowed, os) do
+ {macos_options, options} = Keyword.pop(options, :macos, [])
+ {windows_options, options} = Keyword.pop(options, :windows, [])
+
+ options_per_os = %{
+ macos: macos_options,
+ windows: windows_options
+ }
+
+ options = Keyword.validate!(options, allowed.all)
+ options_for_os = Map.fetch!(options_per_os, os)
+
+ allowed_without_defaults =
+ for option <- allowed.all do
+ case option do
+ atom when is_atom(atom) -> atom
+ {atom, _default} when is_atom(atom) -> atom
+ end
+ end
+
+ allowed_for_os = allowed_without_defaults ++ Map.fetch!(allowed, os)
+ os_options = Keyword.validate!(options_for_os, allowed_for_os)
+ Keyword.merge(options, os_options)
+ end
end
diff --git a/app_builder/lib/app_builder/macos.ex b/app_builder/lib/app_builder/macos.ex
index 666396fdd..dd87df419 100644
--- a/app_builder/lib/app_builder/macos.ex
+++ b/app_builder/lib/app_builder/macos.ex
@@ -33,13 +33,15 @@ defmodule AppBuilder.MacOS do
launcher_src_path
])
- icon_path = Keyword.fetch!(options, :icon_path)
+ icon_path =
+ Keyword.get(options, :icon_path, Application.app_dir(:wx, "examples/demo/erlang.png"))
+
dest_path = "#{resources_path}/AppIcon.icns"
create_icon(icon_path, dest_path)
for type <- Keyword.fetch!(options, :document_types) do
- if src_path = type[:icon_path] do
- dest_path = "#{resources_path}/#{type.name}Icon.icns"
+ if src_path = Keyword.get(type, :icon_path, icon_path) do
+ dest_path = "#{resources_path}/#{type[:name]}Icon.icns"
create_icon(src_path, dest_path)
end
end
diff --git a/app_builder/lib/app_builder/windows.ex b/app_builder/lib/app_builder/windows.ex
index db3396c61..34571faaa 100644
--- a/app_builder/lib/app_builder/windows.ex
+++ b/app_builder/lib/app_builder/windows.ex
@@ -30,11 +30,15 @@ defmodule AppBuilder.Windows do
vcredist_path = ensure_vcredistx64()
copy_file(vcredist_path, "#{app_path}/vcredist_x64.exe")
- create_icon(options[:icon_path], "#{app_path}/AppIcon.ico")
+ icon_path = options[:icon_path]
+
+ if icon_path do
+ create_icon(icon_path, "#{app_path}/AppIcon.ico")
+ end
for type <- Keyword.fetch!(options, :document_types) do
- if src_path = type[:icon_path] do
- dest_path = "#{app_path}/#{type.name}Icon.ico"
+ if src_path = Keyword.get(type, :icon_path, icon_path) do
+ dest_path = "#{app_path}/#{type[:name]}Icon.ico"
create_icon(src_path, dest_path)
end
end
diff --git a/app_builder/lib/templates/macos/Info.plist.eex b/app_builder/lib/templates/macos/Info.plist.eex
index 7d7d40c1a..c2009f0d3 100644
--- a/app_builder/lib/templates/macos/Info.plist.eex
+++ b/app_builder/lib/templates/macos/Info.plist.eex
@@ -41,25 +41,25 @@
<%= for type <- types do %>
CFBundleTypeName
- <%= type.name %>
+ <%= type[:name] %>
CFBundleTypeRole
- <%= type.macos_role %>
+ <%= type[:role] %>
CFBundleTypeExtensions
- <%= for ext <- type.extensions do %>
+ <%= for ext <- type[:extensions] do %>
<%= ext %>
<% end %>
<%= if type[:icon_path] do %>
CFBundleTypeIconFile
- <%= type.name %>Icon
+ <%= type[:name] %>Icon
<% end %>
<% end %>
<% end %>
-<%= if @app_options[:macos_is_agent_app] do %>
+<%= if @app_options[:app_type] == :agent do %>
LSUIElement
<% end %>
diff --git a/app_builder/lib/templates/windows/Installer.nsi.eex b/app_builder/lib/templates/windows/Installer.nsi.eex
index 6452d6658..30375a471 100644
--- a/app_builder/lib/templates/windows/Installer.nsi.eex
+++ b/app_builder/lib/templates/windows/Installer.nsi.eex
@@ -23,7 +23,9 @@ RequestExecutionLevel admin
;Pages
;!insertmacro MUI_PAGE_COMPONENTS
+<%= if @app_options[:icon_path] do %>
!define MUI_ICON "AppIcon.ico"
+<% end %>
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
@@ -46,18 +48,22 @@ Section "Install"
File /r rel rel
File "<%= app_name %>Launcher.vbs"
+<%= if @app_options[:icon_path] do %>
File "AppIcon.ico"
+<% end %>
CreateDirectory "$INSTDIR\Logs"
WriteUninstaller "$INSTDIR\<%= app_name %>Uninstall.exe"
<%= for type <- Keyword.fetch!(@app_options, :document_types) do %>
-<%= for ext <- type.extensions do %>
- WriteRegStr HKCR ".<%= ext %>" "" "<%= app_name %>.<%= type.name %>"
+<%= for ext <- type[:extensions] do %>
+ WriteRegStr HKCR ".<%= ext %>" "" "<%= app_name %>.<%= type[:name] %>"
<% end %>
- WriteRegStr HKCR "<%= app_name %>.<%= type.name %>" "" "<%= type.name %>"
- WriteRegStr HKCR "<%= app_name %>.<%= type.name %>\DefaultIcon" "" "$INSTDIR\<%= type.name %>Icon.ico"
- WriteRegStr HKCR "<%= app_name %>.<%= type.name %>\shell\open\command" "" '$WINDIR\system32\wscript.exe "$INSTDIR\<%= app_name %>Launcher.vbs" "open_file:%1"'
+ WriteRegStr HKCR "<%= app_name %>.<%= type[:name] %>" "" "<%= type[:name] %>"
+<%= if type[:icon_path] || @app_options[:icon_path] do %>
+ WriteRegStr HKCR "<%= app_name %>.<%= type[:name] %>\DefaultIcon" "" "$INSTDIR\<%= type[:name] %>Icon.ico"
+<% end %>
+ WriteRegStr HKCR "<%= app_name %>.<%= type[:name] %>\shell\open\command" "" '$WINDIR\system32\wscript.exe "$INSTDIR\<%= app_name %>Launcher.vbs" "open_file:%1"'
<% end %>
<%= for url_scheme <- Keyword.fetch!(@app_options, :url_schemes) do %>
@@ -72,7 +78,7 @@ Section "Install"
SectionEnd
Section "Desktop Shortcut"
- CreateShortCut "$DESKTOP\<%= app_name %>.lnk" "$INSTDIR\<%= app_name %>Launcher.vbs" "" "$INSTDIR\AppIcon.ico"
+ CreateShortCut "$DESKTOP\<%= app_name %>.lnk" "$INSTDIR\<%= app_name %>Launcher.vbs" "" <%= if @app_options[:icon_path] do %> "$INSTDIR\AppIcon.ico" <% end %>
SectionEnd
Section "Uninstall"
diff --git a/mix.exs b/mix.exs
index f37c42c97..07d538c31 100644
--- a/mix.exs
+++ b/mix.exs
@@ -146,31 +146,34 @@ defmodule Livebook.MixProject do
],
app: [
name: "Livebook",
- icon_path: [
- macos: "rel/app/icon-macos.png",
- windows: "rel/app/icon.ico"
- ],
url_schemes: ["livebook"],
document_types: [
- %{
+ [
name: "LiveMarkdown",
extensions: ["livemd"],
- icon_path: [
- macos: "rel/app/icon.png",
- windows: "rel/app/icon.ico"
+ macos: [
+ icon_path: "rel/app/icon.png",
+ role: "Editor"
],
- macos_role: "Editor"
- }
+ windows: [
+ icon_path: "rel/app/icon.ico"
+ ]
+ ]
],
additional_paths: [
"rel/erts-#{:erlang.system_info(:version)}/bin",
"rel/vendor/elixir/bin"
],
- server: LivebookApp,
- macos_is_agent_app: true,
- macos_build_dmg: macos_notarization != nil,
- macos_notarization: macos_notarization,
- windows_build_installer: true
+ macos: [
+ icon_path: "rel/app/icon-macos.png",
+ build_dmg: macos_notarization != nil,
+ notarization: macos_notarization
+ ],
+ windows: [
+ server: LivebookApp,
+ icon_path: "rel/app/icon.ico",
+ build_installer: true
+ ]
]
]
]