-
Notifications
You must be signed in to change notification settings - Fork 14
fix: add Windows desktop shortcut installer option #503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
158d6bc
fix: wire windows shortcut installer hook
Astro-Han 6a40e11
fix: add windows shortcut installer choice
Astro-Han 7b93fe9
docs: add windows shortcut release checks
Astro-Han 3249945
fix: compile windows shortcut installer script
Astro-Han 051babc
fix: respect windows shortcut install scope
Astro-Han 99935eb
fix: address windows shortcut review notes
Astro-Han 6342435
fix: clean shortcut scope switch leftovers
Astro-Han 5d08f68
fix: elevate public shortcut cleanup
Astro-Han File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
packages/desktop-electron/electron-builder-nsis-shortcut.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| import { describe, expect, test } from "bun:test" | ||
| import { readFileSync } from "node:fs" | ||
| import { join } from "node:path" | ||
|
|
||
| const script = readFileSync(join(import.meta.dir, "resources", "installer.nsh"), "utf8") | ||
|
|
||
| describe("windows nsis desktop shortcut customization", () => { | ||
| test("adds an assisted installer checkbox with English and Chinese labels", () => { | ||
| expect(script).toContain("AddDesktopShortcut") | ||
| expect(script).toContain("添加桌面快捷方式") | ||
| expect(script).toContain("Add desktop shortcut") | ||
| expect(script).toContain("Shortcut Options") | ||
| expect(script).toContain("快捷方式选项") | ||
| expect(script).toContain('LangString PawWorkAddDesktopShortcut 1033 "Add desktop shortcut"') | ||
| expect(script).toContain('LangString PawWorkAddDesktopShortcut 2052 "添加桌面快捷方式"') | ||
| expect(script).toContain('LangString PawWorkShortcutOptions 1033 "Shortcut Options"') | ||
| expect(script).toContain('LangString PawWorkShortcutOptions 2052 "快捷方式选项"') | ||
| expect(script).not.toContain("LANG_ENGLISH") | ||
| expect(script).not.toContain("LANG_SIMPCHINESE") | ||
| expect(script).toContain("BST_CHECKED") | ||
| }) | ||
|
|
||
| test("uses language-aware standard shortcut names", () => { | ||
| expect(script).toContain("PawWork") | ||
| expect(script).toContain("爪印") | ||
| expect(script).toContain("爪印 Beta") | ||
| expect(script).toContain("爪印 Dev") | ||
| expect(script).toContain("$LANGUAGE") | ||
| }) | ||
|
|
||
| test("does not mutate desktop shortcuts during auto-update", () => { | ||
| expect(script).toContain("!include FileFunc.nsh") | ||
| expect(script).toContain('"--updated"') | ||
| expect(script).not.toContain("${isUpdated}") | ||
| expect(script).not.toContain("!insertmacro skipPageIfUpdated") | ||
| expect(script).toContain("PAWWORK_SKIP_DESKTOP_SHORTCUT") | ||
| }) | ||
|
|
||
| test("keeps custom renamed shortcuts out of scope", () => { | ||
| expect(script).toContain("PAWWORK_STANDARD_SHORTCUT") | ||
| expect(script).not.toContain("我的 AI 工具") | ||
| }) | ||
|
|
||
| test("declares a real custom page instead of running page commands inline", () => { | ||
| expect(script).toContain("!ifndef BUILD_UNINSTALLER") | ||
| expect(script).toContain("!ifndef BUILD_UNINSTALLER\n Var AddDesktopShortcutCheckbox") | ||
| expect(script).toContain("PageEx custom") | ||
| expect(script).toContain('Caption "$(PawWorkShortcutOptions)"') | ||
| expect(script).toContain("PageCallbacks PawWorkDesktopShortcutPageCreate PawWorkDesktopShortcutPageLeave") | ||
| expect(script).toContain('Function "PawWorkDesktopShortcutPageCreate"') | ||
| expect(script).toContain('Function "PawWorkDesktopShortcutPageLeave"') | ||
| }) | ||
|
|
||
| test("uses channel-specific shortcut names instead of hard-coded prod names", () => { | ||
| expect(script).toContain("${SHORTCUT_NAME}") | ||
| expect(script).toContain('${AndIf} "${SHORTCUT_NAME}" == "PawWork"') | ||
| expect(script).toContain('${AndIf} "${SHORTCUT_NAME}" == "PawWork Beta"') | ||
| expect(script).toContain('${AndIf} "${SHORTCUT_NAME}" == "PawWork Dev"') | ||
| expect(script).toContain('Delete "$DESKTOP\\${SHORTCUT_NAME}.lnk"') | ||
| expect(script).toContain('Delete "$DESKTOP\\爪印.lnk"') | ||
| expect(script).toContain('Delete "$DESKTOP\\爪印 Beta.lnk"') | ||
| expect(script).toContain('Delete "$DESKTOP\\爪印 Dev.lnk"') | ||
| }) | ||
|
|
||
| test("cleans standard shortcuts across scopes only for checked installs", () => { | ||
| expect(script).toContain("PAWWORK_REMOVE_STANDARD_SHORTCUTS_IN_ALL_INSTALL_SCOPES") | ||
| expect(script).toMatch( | ||
| /\$AddDesktopShortcut == \$\{BST_CHECKED\}[\s\S]*PAWWORK_REMOVE_STANDARD_SHORTCUTS_IN_ALL_INSTALL_SCOPES[\s\S]*PAWWORK_RESTORE_INSTALL_SCOPE[\s\S]*CreateShortCut/, | ||
| ) | ||
| }) | ||
|
|
||
| test("uses an elevated public desktop cleanup when switching from all-users to just-me", () => { | ||
| expect(script).toContain("PAWWORK_REMOVE_PUBLIC_STANDARD_SHORTCUTS_ELEVATED") | ||
| expect(script).toContain('${IfNot} ${UAC_IsAdmin}') | ||
| expect(script).toContain('$installMode != "all"') | ||
| expect(script).toContain('$hasPerMachineInstallation == "1"') | ||
| expect(script).toContain('${StdUtils.ExecShellWaitEx} $0 $1 "$SYSDIR\\cmd.exe" "runas"') | ||
| }) | ||
|
|
||
| test("owns uninstall cleanup for standard shortcuts in the selected install scope", () => { | ||
| expect(script).toContain("customUnInstall") | ||
| expect(script).toContain("PAWWORK_REMOVE_STANDARD_SHORTCUTS") | ||
| expect(script).not.toContain("PAWWORK_REMOVE_STANDARD_SHORTCUTS_IN_BOTH_SCOPES") | ||
| expect(script).toContain("SetShellVarContext current") | ||
| expect(script).toContain("SetShellVarContext all") | ||
| expect(script).toContain("PAWWORK_RESTORE_INSTALL_SCOPE") | ||
| expect(script).toMatch(/PAWWORK_RESTORE_INSTALL_SCOPE\s+!insertmacro PAWWORK_REMOVE_STANDARD_SHORTCUTS/) | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| !include nsDialogs.nsh | ||
| !include LogicLib.nsh | ||
| !include FileFunc.nsh | ||
| !include StdUtils.nsh | ||
| !include UAC.nsh | ||
|
|
||
| Var PawWorkStandardShortcutName | ||
|
|
||
| LangString PawWorkAddDesktopShortcut 1033 "Add desktop shortcut" | ||
| LangString PawWorkAddDesktopShortcut 2052 "添加桌面快捷方式" | ||
| LangString PawWorkShortcutOptions 1033 "Shortcut Options" | ||
| LangString PawWorkShortcutOptions 2052 "快捷方式选项" | ||
|
|
||
| !macro PAWWORK_STANDARD_SHORTCUT | ||
| StrCpy $PawWorkStandardShortcutName "${SHORTCUT_NAME}" | ||
| ${If} $LANGUAGE == 2052 | ||
| ${AndIf} "${SHORTCUT_NAME}" == "PawWork" | ||
| StrCpy $PawWorkStandardShortcutName "爪印" | ||
| ${ElseIf} $LANGUAGE == 2052 | ||
| ${AndIf} "${SHORTCUT_NAME}" == "PawWork Beta" | ||
| StrCpy $PawWorkStandardShortcutName "爪印 Beta" | ||
| ${ElseIf} $LANGUAGE == 2052 | ||
| ${AndIf} "${SHORTCUT_NAME}" == "PawWork Dev" | ||
| StrCpy $PawWorkStandardShortcutName "爪印 Dev" | ||
| ${EndIf} | ||
| !macroend | ||
|
|
||
| !macro PAWWORK_REMOVE_STANDARD_SHORTCUTS | ||
| !insertmacro PAWWORK_STANDARD_SHORTCUT | ||
| Delete "$DESKTOP\$PawWorkStandardShortcutName.lnk" | ||
| Delete "$DESKTOP\${SHORTCUT_NAME}.lnk" | ||
| ${If} "${SHORTCUT_NAME}" == "PawWork" | ||
| Delete "$DESKTOP\PawWork.lnk" | ||
| Delete "$DESKTOP\爪印.lnk" | ||
| ${ElseIf} "${SHORTCUT_NAME}" == "PawWork Beta" | ||
| Delete "$DESKTOP\PawWork Beta.lnk" | ||
| Delete "$DESKTOP\爪印 Beta.lnk" | ||
| ${ElseIf} "${SHORTCUT_NAME}" == "PawWork Dev" | ||
| Delete "$DESKTOP\PawWork Dev.lnk" | ||
| Delete "$DESKTOP\爪印 Dev.lnk" | ||
| ${EndIf} | ||
|
Astro-Han marked this conversation as resolved.
|
||
| !macroend | ||
|
|
||
| !macro PAWWORK_REMOVE_PUBLIC_STANDARD_SHORTCUTS_ELEVATED | ||
| # A per-user reinstall cannot remove Public Desktop shortcuts without elevation. | ||
| ${IfNot} ${UAC_IsAdmin} | ||
| ${AndIf} $installMode != "all" | ||
| ${AndIf} $hasPerMachineInstallation == "1" | ||
| SetShellVarContext all | ||
| ${If} "${SHORTCUT_NAME}" == "PawWork" | ||
| ${StdUtils.ExecShellWaitEx} $0 $1 "$SYSDIR\cmd.exe" "runas" '/C del /F /Q "$DESKTOP\PawWork.lnk" "$DESKTOP\爪印.lnk"' | ||
| ${ElseIf} "${SHORTCUT_NAME}" == "PawWork Beta" | ||
| ${StdUtils.ExecShellWaitEx} $0 $1 "$SYSDIR\cmd.exe" "runas" '/C del /F /Q "$DESKTOP\PawWork Beta.lnk" "$DESKTOP\爪印 Beta.lnk"' | ||
| ${ElseIf} "${SHORTCUT_NAME}" == "PawWork Dev" | ||
| ${StdUtils.ExecShellWaitEx} $0 $1 "$SYSDIR\cmd.exe" "runas" '/C del /F /Q "$DESKTOP\PawWork Dev.lnk" "$DESKTOP\爪印 Dev.lnk"' | ||
| ${EndIf} | ||
| ${EndIf} | ||
| !macroend | ||
|
|
||
| !macro PAWWORK_REMOVE_STANDARD_SHORTCUTS_IN_ALL_INSTALL_SCOPES | ||
| SetShellVarContext current | ||
| !insertmacro PAWWORK_REMOVE_STANDARD_SHORTCUTS | ||
| SetShellVarContext all | ||
| !insertmacro PAWWORK_REMOVE_STANDARD_SHORTCUTS | ||
| !insertmacro PAWWORK_REMOVE_PUBLIC_STANDARD_SHORTCUTS_ELEVATED | ||
| !macroend | ||
|
|
||
| !macro PAWWORK_RESTORE_INSTALL_SCOPE | ||
| ${If} $installMode == "all" | ||
| SetShellVarContext all | ||
| ${Else} | ||
| SetShellVarContext current | ||
| ${EndIf} | ||
| !macroend | ||
|
|
||
| !ifndef BUILD_UNINSTALLER | ||
| Var AddDesktopShortcutCheckbox | ||
| Var AddDesktopShortcut | ||
|
|
||
| !macro customPageAfterChangeDir | ||
| PageEx custom | ||
| PageCallbacks PawWorkDesktopShortcutPageCreate PawWorkDesktopShortcutPageLeave | ||
| Caption "$(PawWorkShortcutOptions)" | ||
| PageExEnd | ||
| !macroend | ||
|
|
||
| Function "PawWorkDesktopShortcutPageCreate" | ||
| ClearErrors | ||
| ${GetParameters} $0 | ||
| ${GetOptions} $0 "--updated" $1 | ||
| ${IfNot} ${Errors} | ||
| Abort | ||
| ${EndIf} | ||
|
|
||
| nsDialogs::Create 1018 | ||
| Pop $0 | ||
| ${If} $0 == error | ||
| Abort | ||
| ${EndIf} | ||
|
|
||
| ${NSD_CreateCheckbox} 0 0 100% 12u "$(PawWorkAddDesktopShortcut)" | ||
| Pop $AddDesktopShortcutCheckbox | ||
| ${NSD_Check} $AddDesktopShortcutCheckbox | ||
| nsDialogs::Show | ||
| FunctionEnd | ||
|
|
||
| Function "PawWorkDesktopShortcutPageLeave" | ||
| StrCpy $AddDesktopShortcut "0" | ||
| ${NSD_GetState} $AddDesktopShortcutCheckbox $AddDesktopShortcut | ||
| FunctionEnd | ||
|
|
||
| !macro customInstall | ||
| ClearErrors | ||
| ${GetParameters} $0 | ||
| ${GetOptions} $0 "--updated" $1 | ||
| ${IfNot} ${Errors} | ||
| StrCpy $AddDesktopShortcut "PAWWORK_SKIP_DESKTOP_SHORTCUT" | ||
| ${EndIf} | ||
|
|
||
| ${If} $AddDesktopShortcut == ${BST_CHECKED} | ||
| !insertmacro PAWWORK_STANDARD_SHORTCUT | ||
| !insertmacro PAWWORK_REMOVE_STANDARD_SHORTCUTS_IN_ALL_INSTALL_SCOPES | ||
| !insertmacro PAWWORK_RESTORE_INSTALL_SCOPE | ||
| CreateShortCut "$DESKTOP\$PawWorkStandardShortcutName.lnk" "$appExe" "" "$appExe" 0 "" "" "${APP_DESCRIPTION}" | ||
| ClearErrors | ||
| WinShell::SetLnkAUMI "$DESKTOP\$PawWorkStandardShortcutName.lnk" "${APP_ID}" | ||
| ${EndIf} | ||
| !macroend | ||
| !endif | ||
|
|
||
| !ifdef BUILD_UNINSTALLER | ||
| !macro customUnInstall | ||
| ClearErrors | ||
| ${GetParameters} $0 | ||
| ${GetOptions} $0 "--updated" $1 | ||
| ${If} ${Errors} | ||
| !insertmacro PAWWORK_RESTORE_INSTALL_SCOPE | ||
| !insertmacro PAWWORK_REMOVE_STANDARD_SHORTCUTS | ||
| ${EndIf} | ||
| !macroend | ||
| !endif | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.