@iamsamuelrodda/dictate 2026.5.18-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/assets/dictate-listening.ico +0 -0
- package/assets/dictate-listening.png +0 -0
- package/assets/dictate.ico +0 -0
- package/assets/dictate.png +0 -0
- package/config/default-config.yaml +17 -0
- package/install-windows-wizard.ps1 +392 -0
- package/install-windows.ps1 +330 -0
- package/install.ps1 +87 -0
- package/install.sh +233 -0
- package/npm/dictate-lifecycle.mjs +49 -0
- package/package.json +50 -0
- package/uninstall-windows.ps1 +83 -0
- package/uninstall.ps1 +51 -0
- package/uninstall.sh +92 -0
- package/update-windows.ps1 +70 -0
- package/update.ps1 +115 -0
- package/update.sh +34 -0
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@iamsamuelrodda/dictate",
|
|
3
|
+
"version": "2026.5.18-1",
|
|
4
|
+
"description": "Installer shim for Dictate desktop dictation.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"homepage": "https://github.com/arcforgelabs/dictate#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/arcforgelabs/dictate.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/arcforgelabs/dictate/issues"
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"dictate-install": "npm/dictate-lifecycle.mjs",
|
|
17
|
+
"dictate-update": "npm/dictate-lifecycle.mjs",
|
|
18
|
+
"dictate-uninstall": "npm/dictate-lifecycle.mjs"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"install.ps1",
|
|
22
|
+
"update.ps1",
|
|
23
|
+
"install-windows.ps1",
|
|
24
|
+
"install-windows-wizard.ps1",
|
|
25
|
+
"update-windows.ps1",
|
|
26
|
+
"uninstall.ps1",
|
|
27
|
+
"uninstall-windows.ps1",
|
|
28
|
+
"install.sh",
|
|
29
|
+
"update.sh",
|
|
30
|
+
"uninstall.sh",
|
|
31
|
+
"config/default-config.yaml",
|
|
32
|
+
"assets/dictate.ico",
|
|
33
|
+
"assets/dictate.png",
|
|
34
|
+
"assets/dictate-listening.ico",
|
|
35
|
+
"assets/dictate-listening.png",
|
|
36
|
+
"npm/",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public",
|
|
42
|
+
"provenance": true
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"pack:check": "npm pack --dry-run"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[switch]$Quiet,
|
|
3
|
+
[switch]$RemoveUserData
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference = "Stop"
|
|
7
|
+
|
|
8
|
+
function Remove-IfExists {
|
|
9
|
+
param([string]$Path)
|
|
10
|
+
if (Test-Path $Path) {
|
|
11
|
+
Remove-Item -Force -Path $Path
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function Stop-DictateProcesses {
|
|
16
|
+
$currentPid = $PID
|
|
17
|
+
$matches = Get-CimInstance Win32_Process |
|
|
18
|
+
Where-Object {
|
|
19
|
+
$_.ProcessId -ne $currentPid -and (
|
|
20
|
+
$_.Name -in @("dictate.exe", "dictate-controls.exe") -or
|
|
21
|
+
$_.CommandLine -like '*dictate.exe* --type-backend pynput*' -or
|
|
22
|
+
$_.CommandLine -like '*pythonw.exe* -m dictate --type-backend pynput*' -or
|
|
23
|
+
$_.CommandLine -like '*dictate-daemon.cmd*' -or
|
|
24
|
+
$_.CommandLine -like '*dictate-controls*'
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
foreach ($match in $matches) {
|
|
28
|
+
Stop-Process -Id $match.ProcessId -Force -ErrorAction SilentlyContinue
|
|
29
|
+
}
|
|
30
|
+
Start-Sleep -Milliseconds 500
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
$programsDir = Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs"
|
|
34
|
+
if (-not $env:APPDATA) {
|
|
35
|
+
$programsDir = Join-Path $HOME "AppData\Roaming\Microsoft\Windows\Start Menu\Programs"
|
|
36
|
+
}
|
|
37
|
+
$startupDir = Join-Path $programsDir "Startup"
|
|
38
|
+
|
|
39
|
+
Remove-IfExists -Path (Join-Path $programsDir "Dictate.lnk")
|
|
40
|
+
Remove-IfExists -Path (Join-Path $programsDir "Dictate Controls.lnk")
|
|
41
|
+
Remove-IfExists -Path (Join-Path $startupDir "Dictate.lnk")
|
|
42
|
+
|
|
43
|
+
$uninstallKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Dictate"
|
|
44
|
+
if (Test-Path $uninstallKey) {
|
|
45
|
+
Remove-Item -Recurse -Force -Path $uninstallKey
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Stop-DictateProcesses
|
|
49
|
+
|
|
50
|
+
$venvDir = Join-Path $PSScriptRoot ".venv"
|
|
51
|
+
if (Test-Path $venvDir) {
|
|
52
|
+
Remove-Item -Recurse -Force -Path $venvDir
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
$localAppData = $env:LOCALAPPDATA
|
|
56
|
+
if (-not $localAppData) {
|
|
57
|
+
$localAppData = Join-Path $HOME "AppData\Local"
|
|
58
|
+
}
|
|
59
|
+
$appData = $env:APPDATA
|
|
60
|
+
if (-not $appData) {
|
|
61
|
+
$appData = Join-Path $HOME "AppData\Roaming"
|
|
62
|
+
}
|
|
63
|
+
$dataDir = Join-Path $localAppData "dictate"
|
|
64
|
+
$configDir = Join-Path $appData "dictate"
|
|
65
|
+
|
|
66
|
+
if ($RemoveUserData) {
|
|
67
|
+
if (Test-Path $dataDir) {
|
|
68
|
+
Remove-Item -Recurse -Force -Path $dataDir
|
|
69
|
+
}
|
|
70
|
+
if (Test-Path $configDir) {
|
|
71
|
+
Remove-Item -Recurse -Force -Path $configDir
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (-not $Quiet) {
|
|
76
|
+
Write-Host "Dictate shortcuts, startup entry, app registration, and runtime venv removed."
|
|
77
|
+
if ($RemoveUserData) {
|
|
78
|
+
Write-Host "User config/data removed."
|
|
79
|
+
} else {
|
|
80
|
+
Write-Host "User config/data preserved. Re-run with -RemoveUserData to remove it."
|
|
81
|
+
}
|
|
82
|
+
Write-Host "Install source files were left in place: $PSScriptRoot"
|
|
83
|
+
}
|
package/uninstall.ps1
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$InstallRoot,
|
|
3
|
+
[switch]$Quiet,
|
|
4
|
+
[switch]$RemoveUserData
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = "Stop"
|
|
8
|
+
|
|
9
|
+
if (-not $InstallRoot) {
|
|
10
|
+
$base = $env:LOCALAPPDATA
|
|
11
|
+
if (-not $base) {
|
|
12
|
+
$base = Join-Path $HOME "AppData\Local"
|
|
13
|
+
}
|
|
14
|
+
$InstallRoot = Join-Path $base "Dictate"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
$installRootPath = [System.IO.Path]::GetFullPath($InstallRoot)
|
|
18
|
+
$sourceDir = Join-Path $installRootPath "source"
|
|
19
|
+
$uninstaller = Join-Path $sourceDir "uninstall-windows.ps1"
|
|
20
|
+
|
|
21
|
+
if (Test-Path $uninstaller) {
|
|
22
|
+
$args = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $uninstaller)
|
|
23
|
+
if ($Quiet) { $args += "-Quiet" }
|
|
24
|
+
if ($RemoveUserData) { $args += "-RemoveUserData" }
|
|
25
|
+
& powershell @args
|
|
26
|
+
if ($LASTEXITCODE -ne 0) {
|
|
27
|
+
throw "Dictate Windows uninstaller failed with exit code $LASTEXITCODE."
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
if (-not $Quiet) {
|
|
31
|
+
Write-Host "Dictate source uninstaller not found: $uninstaller"
|
|
32
|
+
Write-Host "Removing known Start Menu, startup, and Installed Apps entries."
|
|
33
|
+
}
|
|
34
|
+
$programsDir = Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs"
|
|
35
|
+
if (-not $env:APPDATA) {
|
|
36
|
+
$programsDir = Join-Path $HOME "AppData\Roaming\Microsoft\Windows\Start Menu\Programs"
|
|
37
|
+
}
|
|
38
|
+
Remove-Item -Force -ErrorAction SilentlyContinue -Path `
|
|
39
|
+
(Join-Path $programsDir "Dictate.lnk"), `
|
|
40
|
+
(Join-Path $programsDir "Dictate Controls.lnk"), `
|
|
41
|
+
(Join-Path $programsDir "Startup\Dictate.lnk")
|
|
42
|
+
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Dictate"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (Test-Path $installRootPath) {
|
|
46
|
+
Remove-Item -Recurse -Force -Path $installRootPath
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (-not $Quiet) {
|
|
50
|
+
Write-Host "Dictate removed from: $installRootPath"
|
|
51
|
+
}
|
package/uninstall.sh
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Remove Dictate launchers/autostart and installed runtime files.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
INSTALL_DIR="$HOME/.local/share/dictate"
|
|
6
|
+
BIN_PATH="$HOME/.local/bin/dictate"
|
|
7
|
+
DESKTOP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
|
|
8
|
+
AUTOSTART_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/autostart"
|
|
9
|
+
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/dictate"
|
|
10
|
+
REMOVE_USER_DATA=0
|
|
11
|
+
QUIET=0
|
|
12
|
+
|
|
13
|
+
usage() {
|
|
14
|
+
cat <<EOF
|
|
15
|
+
Usage: $0 [--remove-user-data] [--quiet]
|
|
16
|
+
|
|
17
|
+
Removes Dictate launcher/autostart entries, ~/.local/bin/dictate, and the
|
|
18
|
+
installed runtime venv/icons. User config, logs, history, and downloaded models
|
|
19
|
+
are preserved unless --remove-user-data is passed.
|
|
20
|
+
EOF
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
while [ "$#" -gt 0 ]; do
|
|
24
|
+
case "$1" in
|
|
25
|
+
--remove-user-data)
|
|
26
|
+
REMOVE_USER_DATA=1
|
|
27
|
+
;;
|
|
28
|
+
--quiet)
|
|
29
|
+
QUIET=1
|
|
30
|
+
;;
|
|
31
|
+
-h|--help)
|
|
32
|
+
usage
|
|
33
|
+
exit 0
|
|
34
|
+
;;
|
|
35
|
+
*)
|
|
36
|
+
usage
|
|
37
|
+
exit 1
|
|
38
|
+
;;
|
|
39
|
+
esac
|
|
40
|
+
shift
|
|
41
|
+
done
|
|
42
|
+
|
|
43
|
+
say() {
|
|
44
|
+
if [ "$QUIET" -eq 0 ]; then
|
|
45
|
+
printf '%s\n' "$1"
|
|
46
|
+
fi
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
remove_file() {
|
|
50
|
+
local path="$1"
|
|
51
|
+
if [ -e "$path" ] || [ -L "$path" ]; then
|
|
52
|
+
rm -f "$path"
|
|
53
|
+
say "Removed $path"
|
|
54
|
+
fi
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
remove_dir_if_empty() {
|
|
58
|
+
local path="$1"
|
|
59
|
+
if [ -d "$path" ]; then
|
|
60
|
+
rmdir "$path" 2>/dev/null || true
|
|
61
|
+
fi
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
remove_file "$DESKTOP_DIR/dictate.desktop"
|
|
65
|
+
remove_file "$DESKTOP_DIR/dictate-settings.desktop"
|
|
66
|
+
remove_file "$AUTOSTART_DIR/dictate.desktop"
|
|
67
|
+
|
|
68
|
+
if [ -L "$BIN_PATH" ]; then
|
|
69
|
+
target="$(readlink "$BIN_PATH" || true)"
|
|
70
|
+
if [ "$target" = "$INSTALL_DIR/venv/bin/dictate" ]; then
|
|
71
|
+
remove_file "$BIN_PATH"
|
|
72
|
+
else
|
|
73
|
+
say "Leaving $BIN_PATH because it points to $target"
|
|
74
|
+
fi
|
|
75
|
+
elif [ -e "$BIN_PATH" ]; then
|
|
76
|
+
say "Leaving $BIN_PATH because it is not a Dictate-managed symlink"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
rm -rf "$INSTALL_DIR/venv" "$INSTALL_DIR/share/icons"
|
|
80
|
+
remove_dir_if_empty "$INSTALL_DIR/share"
|
|
81
|
+
say "Removed installed runtime files from $INSTALL_DIR"
|
|
82
|
+
|
|
83
|
+
if [ "$REMOVE_USER_DATA" -eq 1 ]; then
|
|
84
|
+
rm -rf "$CONFIG_DIR" "$INSTALL_DIR"
|
|
85
|
+
say "Removed user config/data: $CONFIG_DIR and $INSTALL_DIR"
|
|
86
|
+
else
|
|
87
|
+
say "Preserved user config/data: $CONFIG_DIR and $INSTALL_DIR"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
update-desktop-database "$DESKTOP_DIR" 2>/dev/null || true
|
|
91
|
+
|
|
92
|
+
say "Dictate uninstall complete."
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[switch]$NoVerify,
|
|
3
|
+
[switch]$NoPrepareTurbo,
|
|
4
|
+
[switch]$NoShortcut,
|
|
5
|
+
[switch]$NoStartup,
|
|
6
|
+
[switch]$ForceStartup,
|
|
7
|
+
[switch]$RecreateVenv,
|
|
8
|
+
[switch]$SkipGitPull
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
$ErrorActionPreference = "Stop"
|
|
12
|
+
|
|
13
|
+
function Get-StartMenuProgramsDir {
|
|
14
|
+
$programsDir = Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs"
|
|
15
|
+
if (-not $env:APPDATA) {
|
|
16
|
+
$programsDir = Join-Path $HOME "AppData\Roaming\Microsoft\Windows\Start Menu\Programs"
|
|
17
|
+
}
|
|
18
|
+
return $programsDir
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function Remove-LegacyEntries {
|
|
22
|
+
$programsDir = Get-StartMenuProgramsDir
|
|
23
|
+
Remove-Item -Force -ErrorAction SilentlyContinue -Path (Join-Path $programsDir "Dictate Controls.lnk")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function Get-StartupShortcutPath {
|
|
27
|
+
$programsDir = Get-StartMenuProgramsDir
|
|
28
|
+
return (Join-Path (Join-Path $programsDir "Startup") "Dictate.lnk")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function Stop-DictateProcesses {
|
|
32
|
+
$currentPid = $PID
|
|
33
|
+
$matches = Get-CimInstance Win32_Process |
|
|
34
|
+
Where-Object {
|
|
35
|
+
$_.ProcessId -ne $currentPid -and (
|
|
36
|
+
$_.Name -in @("dictate.exe", "dictate-controls.exe") -or
|
|
37
|
+
$_.CommandLine -like '*dictate.exe* --type-backend pynput*' -or
|
|
38
|
+
$_.CommandLine -like '*pythonw.exe* -m dictate --type-backend pynput*' -or
|
|
39
|
+
$_.CommandLine -like '*dictate-daemon.cmd*' -or
|
|
40
|
+
$_.CommandLine -like '*dictate-controls*'
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
foreach ($match in $matches) {
|
|
44
|
+
Stop-Process -Id $match.ProcessId -Force -ErrorAction SilentlyContinue
|
|
45
|
+
}
|
|
46
|
+
Start-Sleep -Milliseconds 500
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if ((-not $SkipGitPull) -and (Test-Path (Join-Path $PSScriptRoot ".git"))) {
|
|
50
|
+
Write-Host "==> Updating source checkout"
|
|
51
|
+
& git -C $PSScriptRoot pull --ff-only
|
|
52
|
+
if ($LASTEXITCODE -ne 0) {
|
|
53
|
+
throw "git pull failed with exit code $LASTEXITCODE."
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Remove-LegacyEntries
|
|
58
|
+
Stop-DictateProcesses
|
|
59
|
+
|
|
60
|
+
$installerArgs = @("-ExecutionPolicy", "Bypass", "-File", (Join-Path $PSScriptRoot "install-windows.ps1"))
|
|
61
|
+
if ($NoVerify) { $installerArgs += "-NoVerify" }
|
|
62
|
+
if ($NoPrepareTurbo) { $installerArgs += "-NoPrepareTurbo" }
|
|
63
|
+
if ($NoShortcut) { $installerArgs += "-NoShortcut" }
|
|
64
|
+
if ($NoStartup -or ((-not $ForceStartup) -and (-not (Test-Path (Get-StartupShortcutPath))))) { $installerArgs += "-NoStartup" }
|
|
65
|
+
if ($RecreateVenv) { $installerArgs += "-RecreateVenv" }
|
|
66
|
+
|
|
67
|
+
& powershell @installerArgs
|
|
68
|
+
if ($LASTEXITCODE -ne 0) {
|
|
69
|
+
throw "Dictate Windows update failed with exit code $LASTEXITCODE."
|
|
70
|
+
}
|
package/update.ps1
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$InstallRoot,
|
|
3
|
+
[string]$ArchiveUrl,
|
|
4
|
+
[switch]$NoVerify,
|
|
5
|
+
[switch]$NoPrepareTurbo,
|
|
6
|
+
[switch]$NoShortcut,
|
|
7
|
+
[switch]$NoStartup,
|
|
8
|
+
[switch]$ForceStartup,
|
|
9
|
+
[switch]$RecreateVenv
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
$ErrorActionPreference = "Stop"
|
|
13
|
+
$DictateVersion = "2026.5.18-1"
|
|
14
|
+
|
|
15
|
+
if (-not $ArchiveUrl) {
|
|
16
|
+
$ArchiveUrl = "https://github.com/arcforgelabs/dictate/archive/refs/tags/v$DictateVersion.zip"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (-not $InstallRoot) {
|
|
20
|
+
$currentDirectory = [System.IO.Directory]::GetCurrentDirectory()
|
|
21
|
+
$candidateSource = Join-Path $currentDirectory "source"
|
|
22
|
+
if (
|
|
23
|
+
(Test-Path (Join-Path $candidateSource "update-windows.ps1")) -and
|
|
24
|
+
(Test-Path (Join-Path $candidateSource "pyproject.toml")) -and
|
|
25
|
+
(Test-Path (Join-Path $candidateSource "src\dictate"))
|
|
26
|
+
) {
|
|
27
|
+
$InstallRoot = $currentDirectory
|
|
28
|
+
} else {
|
|
29
|
+
$base = $env:LOCALAPPDATA
|
|
30
|
+
if (-not $base) {
|
|
31
|
+
$base = Join-Path $HOME "AppData\Local"
|
|
32
|
+
}
|
|
33
|
+
$InstallRoot = Join-Path $base "Dictate"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
$installRootPath = [System.IO.Path]::GetFullPath($InstallRoot)
|
|
38
|
+
$sourceDir = Join-Path $installRootPath "source"
|
|
39
|
+
$stagingRoot = Join-Path $env:TEMP ("dictate-update-" + [guid]::NewGuid().ToString("N"))
|
|
40
|
+
$archivePath = Join-Path $stagingRoot "dictate.zip"
|
|
41
|
+
|
|
42
|
+
function Stop-DictateProcesses {
|
|
43
|
+
$currentPid = $PID
|
|
44
|
+
$matches = Get-CimInstance Win32_Process |
|
|
45
|
+
Where-Object {
|
|
46
|
+
$_.ProcessId -ne $currentPid -and (
|
|
47
|
+
$_.Name -in @("dictate.exe", "dictate-controls.exe") -or
|
|
48
|
+
$_.CommandLine -like '*dictate.exe* --type-backend pynput*' -or
|
|
49
|
+
$_.CommandLine -like '*pythonw.exe* -m dictate --type-backend pynput*' -or
|
|
50
|
+
$_.CommandLine -like '*dictate-daemon.cmd*' -or
|
|
51
|
+
$_.CommandLine -like '*dictate-controls*'
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
foreach ($match in $matches) {
|
|
55
|
+
Stop-Process -Id $match.ProcessId -Force -ErrorAction SilentlyContinue
|
|
56
|
+
}
|
|
57
|
+
Start-Sleep -Milliseconds 500
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
Write-Host "==> Updating Dictate in $installRootPath"
|
|
61
|
+
New-Item -ItemType Directory -Force -Path $stagingRoot | Out-Null
|
|
62
|
+
New-Item -ItemType Directory -Force -Path $installRootPath | Out-Null
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
if (Test-Path -LiteralPath $ArchiveUrl) {
|
|
66
|
+
Write-Host "==> Copying local archive $ArchiveUrl"
|
|
67
|
+
Copy-Item -Force -LiteralPath $ArchiveUrl -Destination $archivePath
|
|
68
|
+
} else {
|
|
69
|
+
Write-Host "==> Downloading $ArchiveUrl"
|
|
70
|
+
Invoke-WebRequest -UseBasicParsing -Uri $ArchiveUrl -OutFile $archivePath
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
Write-Host "==> Expanding source archive"
|
|
74
|
+
Expand-Archive -Force -Path $archivePath -DestinationPath $stagingRoot
|
|
75
|
+
$expanded = Get-ChildItem -Path $stagingRoot -Directory |
|
|
76
|
+
Where-Object { Test-Path (Join-Path $_.FullName "update-windows.ps1") } |
|
|
77
|
+
Select-Object -First 1
|
|
78
|
+
if (-not $expanded) {
|
|
79
|
+
throw "Downloaded archive did not contain update-windows.ps1."
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (Test-Path $sourceDir) {
|
|
83
|
+
Stop-DictateProcesses
|
|
84
|
+
Write-Host "==> Replacing existing managed source: $sourceDir"
|
|
85
|
+
Remove-Item -Recurse -Force $sourceDir
|
|
86
|
+
}
|
|
87
|
+
Move-Item -Path $expanded.FullName -Destination $sourceDir
|
|
88
|
+
|
|
89
|
+
$updaterArgs = @(
|
|
90
|
+
"-ExecutionPolicy",
|
|
91
|
+
"Bypass",
|
|
92
|
+
"-File",
|
|
93
|
+
(Join-Path $sourceDir "update-windows.ps1"),
|
|
94
|
+
"-SkipGitPull"
|
|
95
|
+
)
|
|
96
|
+
if ($NoVerify) { $updaterArgs += "-NoVerify" }
|
|
97
|
+
if ($NoPrepareTurbo) { $updaterArgs += "-NoPrepareTurbo" }
|
|
98
|
+
if ($NoShortcut) { $updaterArgs += "-NoShortcut" }
|
|
99
|
+
if ($NoStartup) { $updaterArgs += "-NoStartup" }
|
|
100
|
+
if ($ForceStartup) { $updaterArgs += "-ForceStartup" }
|
|
101
|
+
if ($RecreateVenv) { $updaterArgs += "-RecreateVenv" }
|
|
102
|
+
|
|
103
|
+
Write-Host "==> Running Dictate Windows updater"
|
|
104
|
+
& powershell @updaterArgs
|
|
105
|
+
if ($LASTEXITCODE -ne 0) {
|
|
106
|
+
throw "Dictate Windows updater failed with exit code $LASTEXITCODE."
|
|
107
|
+
}
|
|
108
|
+
} finally {
|
|
109
|
+
if (Test-Path $stagingRoot) {
|
|
110
|
+
Remove-Item -Recurse -Force $stagingRoot
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Write-Host ""
|
|
115
|
+
Write-Host "Dictate updated from: $sourceDir"
|
package/update.sh
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Update Dictate and migrate old launcher/icon names from previous installs.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
INSTALL_DIR="$HOME/.local/share/dictate"
|
|
7
|
+
DESKTOP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
|
|
8
|
+
AUTOSTART_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/autostart"
|
|
9
|
+
ICON_DIR="$INSTALL_DIR/share/icons"
|
|
10
|
+
AUTOSTART_PATH="$AUTOSTART_DIR/dictate.desktop"
|
|
11
|
+
|
|
12
|
+
cleanup_legacy_entries() {
|
|
13
|
+
rm -f "$DESKTOP_DIR/dictate-settings.desktop"
|
|
14
|
+
rm -f "$ICON_DIR/dictate-controls.png" "$ICON_DIR/dictate.png"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if [ -d "$SCRIPT_DIR/.git" ]; then
|
|
18
|
+
git -C "$SCRIPT_DIR" pull --ff-only
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
cleanup_legacy_entries
|
|
22
|
+
|
|
23
|
+
args=("$@")
|
|
24
|
+
startup_option_seen=0
|
|
25
|
+
for arg in "${args[@]}"; do
|
|
26
|
+
if [ "$arg" = "--no-startup" ]; then
|
|
27
|
+
startup_option_seen=1
|
|
28
|
+
fi
|
|
29
|
+
done
|
|
30
|
+
if [ "$startup_option_seen" -eq 0 ] && [ ! -e "$AUTOSTART_PATH" ]; then
|
|
31
|
+
args+=("--no-startup")
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
"$SCRIPT_DIR/install.sh" "${args[@]}"
|