Skip to content

Commit eeff943

Browse files
committed
chore(build): add Windows NSIS installer configuration files
- Add project.nsi with installer configuration for Windows builds - Add wails_tools.nsh with auto-generated Wails build tools and macros - Update Titlebar component with improved styling - Update useTabs hook with enhanced tab management - Enable proper Windows installer generation with WebView2 runtime support and file associations
1 parent 7b85d23 commit eeff943

4 files changed

Lines changed: 393 additions & 29 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
Unicode true
2+
3+
####
4+
## Please note: Template replacements don't work in this file. They are provided with default defines like
5+
## mentioned underneath.
6+
## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
7+
## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
8+
## from outside of Wails for debugging and development of the installer.
9+
##
10+
## For development first make a wails nsis build to populate the "wails_tools.nsh":
11+
## > wails build --target windows/amd64 --nsis
12+
## Then you can call makensis on this file with specifying the path to your binary:
13+
## For a AMD64 only installer:
14+
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe
15+
## For a ARM64 only installer:
16+
## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe
17+
## For a installer with both architectures:
18+
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe
19+
####
20+
## The following information is taken from the ProjectInfo file, but they can be overwritten here.
21+
####
22+
## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}"
23+
## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}"
24+
## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}"
25+
## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}"
26+
## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}"
27+
###
28+
## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe"
29+
## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
30+
####
31+
## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html
32+
####
33+
## Include the wails tools
34+
####
35+
!include "wails_tools.nsh"
36+
37+
# The version information for this two must consist of 4 parts
38+
VIProductVersion "${INFO_PRODUCTVERSION}.0"
39+
VIFileVersion "${INFO_PRODUCTVERSION}.0"
40+
41+
VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}"
42+
VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer"
43+
VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}"
44+
VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
45+
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
46+
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
47+
48+
# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
49+
ManifestDPIAware true
50+
51+
!include "MUI.nsh"
52+
53+
!define MUI_ICON "..\icon.ico"
54+
!define MUI_UNICON "..\icon.ico"
55+
# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314
56+
!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps
57+
!define MUI_ABORTWARNING # This will warn the user if they exit from the installer.
58+
59+
!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page.
60+
# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer
61+
!insertmacro MUI_PAGE_DIRECTORY # In which folder install page.
62+
!insertmacro MUI_PAGE_INSTFILES # Installing page.
63+
!insertmacro MUI_PAGE_FINISH # Finished installation page.
64+
65+
!insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page
66+
67+
!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer
68+
69+
## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1
70+
#!uninstfinalize 'signtool --file "%1"'
71+
#!finalize 'signtool --file "%1"'
72+
73+
Name "${INFO_PRODUCTNAME}"
74+
OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file.
75+
InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder).
76+
ShowInstDetails show # This will always show the installation details.
77+
78+
Function .onInit
79+
!insertmacro wails.checkArchitecture
80+
FunctionEnd
81+
82+
Section
83+
!insertmacro wails.setShellContext
84+
85+
!insertmacro wails.webview2runtime
86+
87+
SetOutPath $INSTDIR
88+
89+
!insertmacro wails.files
90+
91+
CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
92+
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
93+
94+
!insertmacro wails.associateFiles
95+
!insertmacro wails.associateCustomProtocols
96+
97+
!insertmacro wails.writeUninstaller
98+
SectionEnd
99+
100+
Section "uninstall"
101+
!insertmacro wails.setShellContext
102+
103+
RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath
104+
105+
RMDir /r $INSTDIR
106+
107+
Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
108+
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
109+
110+
!insertmacro wails.unassociateFiles
111+
!insertmacro wails.unassociateCustomProtocols
112+
113+
!insertmacro wails.deleteUninstaller
114+
SectionEnd
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
# DO NOT EDIT - Generated automatically by `wails build`
2+
3+
!include "x64.nsh"
4+
!include "WinVer.nsh"
5+
!include "FileFunc.nsh"
6+
7+
!ifndef INFO_PROJECTNAME
8+
!define INFO_PROJECTNAME "MarkViewPro"
9+
!endif
10+
!ifndef INFO_COMPANYNAME
11+
!define INFO_COMPANYNAME "MarkViewPro"
12+
!endif
13+
!ifndef INFO_PRODUCTNAME
14+
!define INFO_PRODUCTNAME "MarkViewPro"
15+
!endif
16+
!ifndef INFO_PRODUCTVERSION
17+
!define INFO_PRODUCTVERSION "1.4.5"
18+
!endif
19+
!ifndef INFO_COPYRIGHT
20+
!define INFO_COPYRIGHT "Copyright © 2024 MarkViewPro Contributors"
21+
!endif
22+
!ifndef PRODUCT_EXECUTABLE
23+
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
24+
!endif
25+
!ifndef UNINST_KEY_NAME
26+
!define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
27+
!endif
28+
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}"
29+
30+
!ifndef REQUEST_EXECUTION_LEVEL
31+
!define REQUEST_EXECUTION_LEVEL "admin"
32+
!endif
33+
34+
RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
35+
36+
!ifdef ARG_WAILS_AMD64_BINARY
37+
!define SUPPORTS_AMD64
38+
!endif
39+
40+
!ifdef ARG_WAILS_ARM64_BINARY
41+
!define SUPPORTS_ARM64
42+
!endif
43+
44+
!ifdef SUPPORTS_AMD64
45+
!ifdef SUPPORTS_ARM64
46+
!define ARCH "amd64_arm64"
47+
!else
48+
!define ARCH "amd64"
49+
!endif
50+
!else
51+
!ifdef SUPPORTS_ARM64
52+
!define ARCH "arm64"
53+
!else
54+
!error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY"
55+
!endif
56+
!endif
57+
58+
!macro wails.checkArchitecture
59+
!ifndef WAILS_WIN10_REQUIRED
60+
!define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later."
61+
!endif
62+
63+
!ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED
64+
!define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}"
65+
!endif
66+
67+
${If} ${AtLeastWin10}
68+
!ifdef SUPPORTS_AMD64
69+
${if} ${IsNativeAMD64}
70+
Goto ok
71+
${EndIf}
72+
!endif
73+
74+
!ifdef SUPPORTS_ARM64
75+
${if} ${IsNativeARM64}
76+
Goto ok
77+
${EndIf}
78+
!endif
79+
80+
IfSilent silentArch notSilentArch
81+
silentArch:
82+
SetErrorLevel 65
83+
Abort
84+
notSilentArch:
85+
MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}"
86+
Quit
87+
${else}
88+
IfSilent silentWin notSilentWin
89+
silentWin:
90+
SetErrorLevel 64
91+
Abort
92+
notSilentWin:
93+
MessageBox MB_OK "${WAILS_WIN10_REQUIRED}"
94+
Quit
95+
${EndIf}
96+
97+
ok:
98+
!macroend
99+
100+
!macro wails.files
101+
!ifdef SUPPORTS_AMD64
102+
${if} ${IsNativeAMD64}
103+
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}"
104+
${EndIf}
105+
!endif
106+
107+
!ifdef SUPPORTS_ARM64
108+
${if} ${IsNativeARM64}
109+
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}"
110+
${EndIf}
111+
!endif
112+
!macroend
113+
114+
!macro wails.writeUninstaller
115+
WriteUninstaller "$INSTDIR\uninstall.exe"
116+
117+
SetRegView 64
118+
WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
119+
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
120+
WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
121+
WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
122+
WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
123+
WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
124+
125+
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
126+
IntFmt $0 "0x%08X" $0
127+
WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0"
128+
!macroend
129+
130+
!macro wails.deleteUninstaller
131+
Delete "$INSTDIR\uninstall.exe"
132+
133+
SetRegView 64
134+
DeleteRegKey HKLM "${UNINST_KEY}"
135+
!macroend
136+
137+
!macro wails.setShellContext
138+
${If} ${REQUEST_EXECUTION_LEVEL} == "admin"
139+
SetShellVarContext all
140+
${else}
141+
SetShellVarContext current
142+
${EndIf}
143+
!macroend
144+
145+
# Install webview2 by launching the bootstrapper
146+
# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment
147+
!macro wails.webview2runtime
148+
!ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT
149+
!define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime"
150+
!endif
151+
152+
SetRegView 64
153+
# If the admin key exists and is not empty then webview2 is already installed
154+
ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
155+
${If} $0 != ""
156+
Goto ok
157+
${EndIf}
158+
159+
${If} ${REQUEST_EXECUTION_LEVEL} == "user"
160+
# If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed
161+
ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
162+
${If} $0 != ""
163+
Goto ok
164+
${EndIf}
165+
${EndIf}
166+
167+
SetDetailsPrint both
168+
DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}"
169+
SetDetailsPrint listonly
170+
171+
InitPluginsDir
172+
CreateDirectory "$pluginsdir\webview2bootstrapper"
173+
SetOutPath "$pluginsdir\webview2bootstrapper"
174+
File "tmp\MicrosoftEdgeWebview2Setup.exe"
175+
ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install'
176+
177+
SetDetailsPrint both
178+
ok:
179+
!macroend
180+
181+
# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b
182+
!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
183+
; Backup the previously associated file class
184+
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
185+
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
186+
187+
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
188+
189+
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
190+
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
191+
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open"
192+
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
193+
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}`
194+
!macroend
195+
196+
!macro APP_UNASSOCIATE EXT FILECLASS
197+
; Backup the previously associated file class
198+
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
199+
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
200+
201+
DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
202+
!macroend
203+
204+
!macro wails.associateFiles
205+
; Create file associations
206+
207+
!macroend
208+
209+
!macro wails.unassociateFiles
210+
; Delete app associations
211+
212+
!macroend
213+
214+
!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND
215+
DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
216+
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}"
217+
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" ""
218+
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}"
219+
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" ""
220+
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" ""
221+
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}"
222+
!macroend
223+
224+
!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL
225+
DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
226+
!macroend
227+
228+
!macro wails.associateCustomProtocols
229+
; Create custom protocols associations
230+
231+
!macroend
232+
233+
!macro wails.unassociateCustomProtocols
234+
; Delete app custom protocol associations
235+
236+
!macroend

frontend/src/components/Titlebar/Titlebar.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ export function Titlebar({
158158
key={tab.id}
159159
onClick={() => onTabClick(tab.id)}
160160
className={`
161-
flex items-center gap-2 px-3 py-1.5 min-w-[100px] max-w-[180px] cursor-pointer rounded-t
161+
flex items-center gap-2 px-3 py-1.5 min-w-[100px] max-w-[180px] cursor-pointer rounded
162162
transition-all group relative
163163
${tab.id === activeTabId
164-
? 'bg-zinc-800 text-zinc-100 border-t-2 border-t-cyan-500 border-x border-x-zinc-700'
165-
: 'bg-zinc-900/30 text-zinc-500 hover:bg-zinc-800/50 hover:text-zinc-300 border-t-2 border-t-transparent'
164+
? 'bg-zinc-700 text-zinc-100 shadow-[inset_0_2px_0_0_#06b6d4]'
165+
: 'bg-zinc-900/30 text-zinc-500 hover:bg-zinc-800/50 hover:text-zinc-300'
166166
}
167167
`}
168168
>

0 commit comments

Comments
 (0)