diff --git a/apps/readest-app/.claude/memory/epub-review-editor-migration.md b/apps/readest-app/.claude/memory/epub-review-editor-migration.md index 0ad0c1c9..daa52dcd 100644 --- a/apps/readest-app/.claude/memory/epub-review-editor-migration.md +++ b/apps/readest-app/.claude/memory/epub-review-editor-migration.md @@ -28,3 +28,6 @@ Next recommended steps: 1. Package the Python sidecar/runtime or replace it with native Tauri commands so desktop users do not need a system Python installation. 2. Add a launch token / origin guard for the loopback sidecar API before wider distribution. 3. Gradually port long-tail review-editor surfaces into React: glossary editing, full bookshelf classification UI, richer chapter navigation, and reading-position restore. + +Desktop latest-version entrypoint: +- `scripts/open-readest-latest.ps1` and `scripts/open-readest-latest.cmd` are the stable desktop shortcut targets. They fetch `akai-tools/codex/desktop-review-editor-blocks`, fast-forward only on a clean worktree, update submodules/dependencies when needed, then start `pnpm --filter @readest/readest-app tauri dev`. Do not point the user shortcut directly at `target/debug/Readest.exe`, because that can launch stale code or miss the Next/Tauri dev server. diff --git a/scripts/open-readest-latest.cmd b/scripts/open-readest-latest.cmd new file mode 100644 index 00000000..de444c58 --- /dev/null +++ b/scripts/open-readest-latest.cmd @@ -0,0 +1,2 @@ +@echo off +powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%~dp0open-readest-latest.ps1" %* diff --git a/scripts/open-readest-latest.ps1 b/scripts/open-readest-latest.ps1 new file mode 100644 index 00000000..3ccfce58 --- /dev/null +++ b/scripts/open-readest-latest.ps1 @@ -0,0 +1,162 @@ +param( + [string]$Remote = "akai-tools", + [string]$Branch = "codex/desktop-review-editor-blocks", + [switch]$SkipPull, + [switch]$CheckOnly, + [switch]$KeepRunning +) + +$ErrorActionPreference = "Stop" +[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 + +$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path + +function Write-Step { + param([string]$Message) + Write-Host "" + Write-Host "==> $Message" -ForegroundColor Cyan +} + +function Invoke-Checked { + param( + [string]$Command, + [string[]]$Arguments, + [string]$WorkingDirectory = $RepoRoot + ) + + Push-Location $WorkingDirectory + try { + & $Command @Arguments + if ($LASTEXITCODE -ne 0) { + throw "$Command $($Arguments -join ' ') failed with exit code $LASTEXITCODE." + } + } finally { + Pop-Location + } +} + +function Add-PathIfExists { + param([string]$PathToAdd) + if ($PathToAdd -and (Test-Path -LiteralPath $PathToAdd)) { + $script:PathParts += $PathToAdd + } +} + +function Stop-OldReadestDev { + if ($KeepRunning) { + return + } + + Write-Step "Stopping old Readest desktop/dev processes" + Get-Process -Name "Readest" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue + + $repoLower = $RepoRoot.ToLowerInvariant() + $currentPid = $PID + Get-CimInstance Win32_Process | + Where-Object { + $_.ProcessId -ne $currentPid -and + $_.CommandLine -and + $_.CommandLine.ToLowerInvariant().Contains($repoLower) -and + ($_.CommandLine -match "tauri\s+dev|next\s+dev|@readest/readest-app|epub-reviewer:dev") + } | + ForEach-Object { + Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue + } +} + +function Assert-CleanWorktree { + $status = (& git -C $RepoRoot status --porcelain) + if ($status) { + Write-Host "" + Write-Host "Local changes were found. The launcher will not pull or overwrite them:" -ForegroundColor Yellow + & git -C $RepoRoot status --short + throw "Commit, stash, or discard local changes before launching the latest organization version." + } +} + +try { + $PathParts = @() + $runtimeRoot = Join-Path $env:USERPROFILE ".cache\codex-runtimes\codex-primary-runtime\dependencies" + Add-PathIfExists "C:\w64devkit\bin" + Add-PathIfExists (Join-Path $runtimeRoot "bin") + Add-PathIfExists (Join-Path $runtimeRoot "node\bin") + Add-PathIfExists (Join-Path $env:USERPROFILE ".cargo\bin") + $env:Path = (($PathParts + ($env:Path -split ";" | Where-Object { $_ })) -join ";") + $env:RUSTUP_TOOLCHAIN = "stable-x86_64-pc-windows-gnu" + + foreach ($command in @("git", "pnpm", "cargo")) { + if (-not (Get-Command $command -ErrorAction SilentlyContinue)) { + throw "Required command not found: $command" + } + } + + Write-Step "Readest latest launcher" + Write-Host "Repository: $RepoRoot" + Write-Host "Remote: $Remote" + Write-Host "Branch: $Branch" + + $beforeHead = (& git -C $RepoRoot rev-parse HEAD).Trim() + + if (-not $SkipPull) { + Assert-CleanWorktree + + Write-Step "Fetching latest code from organization remote" + Invoke-Checked "git" @("-C", $RepoRoot, "fetch", "--prune", $Remote) + + $currentBranch = (& git -C $RepoRoot branch --show-current).Trim() + if ($currentBranch -ne $Branch) { + Write-Step "Switching to $Branch" + & git -C $RepoRoot show-ref --verify --quiet "refs/heads/$Branch" + if ($LASTEXITCODE -eq 0) { + Invoke-Checked "git" @("-C", $RepoRoot, "switch", $Branch) + } else { + Invoke-Checked "git" @("-C", $RepoRoot, "switch", "--track", "-c", $Branch, "$Remote/$Branch") + } + } + + Write-Step "Fast-forwarding local branch" + Invoke-Checked "git" @("-C", $RepoRoot, "pull", "--ff-only", $Remote, $Branch) + } else { + Write-Step "Skipping git pull by request" + } + + $afterHead = (& git -C $RepoRoot rev-parse HEAD).Trim() + + Write-Step "Updating submodules" + Invoke-Checked "git" @("-C", $RepoRoot, "submodule", "update", "--init", "--recursive") + + $changedFiles = @() + if ($beforeHead -ne $afterHead) { + $changedFiles = (& git -C $RepoRoot diff --name-only $beforeHead $afterHead) + } + + $needsInstall = + -not (Test-Path -LiteralPath (Join-Path $RepoRoot "node_modules")) -or + ($changedFiles -contains "pnpm-lock.yaml") -or + ($changedFiles -contains "package.json") -or + ($changedFiles -contains "apps/readest-app/package.json") + + if ($needsInstall) { + Write-Step "Installing/updating dependencies" + Invoke-Checked "pnpm" @("install", "--frozen-lockfile") + } + + if ($CheckOnly) { + Write-Step "Launcher check complete" + exit 0 + } + + Stop-OldReadestDev + + Write-Step "Starting Readest desktop with the latest code" + Write-Host "Close the Readest window or press Ctrl+C here to stop the dev server." + Invoke-Checked "pnpm" @("--filter", "@readest/readest-app", "tauri", "dev") +} catch { + Write-Host "" + Write-Host "Readest launcher failed:" -ForegroundColor Red + Write-Host $_.Exception.Message -ForegroundColor Red + Write-Host "" + Write-Host "Press Enter to close this window." + [void][Console]::ReadLine() + exit 1 +}