diff --git a/scripts/install_deps.ps1 b/scripts/install_deps.ps1 index 6b94c01..5d37940 100644 --- a/scripts/install_deps.ps1 +++ b/scripts/install_deps.ps1 @@ -46,8 +46,10 @@ function Update-EnvironmentPath { "${env:ProgramFiles(x86)}\nodejs", "$env:APPDATA\npm", "$env:LOCALAPPDATA\Programs\platform-tools", + "$env:LOCALAPPDATA\Programs\scrcpy", "$env:LOCALAPPDATA\Programs\node", "$env:USERPROFILE\.local\share\platform-tools", + "$env:USERPROFILE\.local\share\scrcpy", "$env:USERPROFILE\.local\share\node", "$env:LOCALAPPDATA\nvm", "$env:ProgramData\nvm", @@ -107,6 +109,39 @@ function Install-PortablePlatformTools { return $false } +function Install-PortableScrcpy { + $scrcpyDir = "$env:LOCALAPPDATA\Programs\scrcpy" + if (Test-Path "$scrcpyDir\scrcpy.exe") { + $env:PATH = "$scrcpyDir;$env:PATH" + return $true + } + Write-Host " [INFO] Installing portable scrcpy in user space..." -ForegroundColor Cyan + try { + $zipPath = "$env:TEMP\scrcpy-win64.zip" + Invoke-WebRequest -Uri "https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-win64-v4.1.zip" -OutFile $zipPath -UseBasicParsing + $extractDir = "$env:TEMP\scrcpy_extract" + if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue } + New-Item -ItemType Directory -Path $extractDir -Force | Out-Null + Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force + $extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1 + if ($extractedFolder) { + New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null + if (Test-Path $scrcpyDir) { Remove-Item $scrcpyDir -Recurse -Force -ErrorAction SilentlyContinue } + Move-Item -Path $extractedFolder.FullName -Destination $scrcpyDir -Force + } + Remove-Item $zipPath -Force -ErrorAction SilentlyContinue + Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue + if (Test-Path "$scrcpyDir\scrcpy.exe") { + $env:PATH = "$scrcpyDir;$env:PATH" + Write-Host " ✔ Portable scrcpy installed in user space." -ForegroundColor Green + return $true + } + } catch { + Write-Host " ⚠ Failed to install portable scrcpy: $_" -ForegroundColor DarkYellow + } + return $false +} + function Test-NodeCompatible { if (-not (Test-CommandExists "node") -or -not (Test-CommandExists "npm")) { return $false } try { @@ -219,10 +254,13 @@ if ($missingTools.Count -eq 0) { Update-EnvironmentPath } - # Zero-admin user-space fallback for adb if still missing + # Zero-admin user-space fallback for adb and scrcpy if still missing if (-not (Test-CommandExists "adb")) { Install-PortablePlatformTools } + if (-not (Test-CommandExists "scrcpy")) { + Install-PortableScrcpy + } # Ensure local ADB daemon is warm & listening Start-LocalAdbServer diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 97ae0e2..1f4847d 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -52,6 +52,7 @@ STANDARD_PATHS=( "${HOME}/.local/bin" "${HOME}/.local/share/node/bin" "${HOME}/.local/share/platform-tools" + "${HOME}/.local/share/scrcpy" "${HOME}/.cargo/bin" "${HOME}/Library/Android/sdk/platform-tools" "${HOME}/Android/Sdk/platform-tools" @@ -231,7 +232,8 @@ install_system_packages() { if has_cmd apt-get; then echo -e " ${CYAN}Detected Debian/Ubuntu (apt-get). Synchronizing and installing...${NC}" - ${SUDO_PREFIX} apt-get update -qq && ${SUDO_PREFIX} apt-get install -y "${PKGS[@]}" || true + ${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=60 update -qq 2>/dev/null || true + ${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=60 install -y "${PKGS[@]}" 2>/dev/null || true elif has_cmd dnf; then echo -e " ${CYAN}Detected Fedora/RHEL (dnf). Installing packages...${NC}" local DNF_PKGS=() @@ -249,6 +251,38 @@ install_system_packages() { fi fi + # Fallback: if scrcpy is still missing, try snap or install portable scrcpy in user space + if ! has_cmd scrcpy; then + if has_cmd snap && request_sudo "install scrcpy via snap"; then + local SUDO_PREFIX="" + if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi + ${SUDO_PREFIX} snap install scrcpy 2>/dev/null || true + fi + fi + if ! has_cmd scrcpy; then + local SCRCPY_ARCH="" + case "${ARCH_TYPE}" in + x86_64|amd64) SCRCPY_ARCH="x86_64" ;; + aarch64|arm64) SCRCPY_ARCH="aarch64" ;; + esac + if [ -n "${SCRCPY_ARCH}" ]; then + local SCRCPY_DIR="${HOME}/.local/share/scrcpy" + if [ ! -x "${SCRCPY_DIR}/scrcpy" ]; then + echo -e " ${CYAN}📦 Installing portable scrcpy in user space (~/.local)...${NC}" + mkdir -p "${SCRCPY_DIR}" "${HOME}/.local/bin" + local SCRCPY_URL="https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-linux-${SCRCPY_ARCH}-v4.1.tar.gz" + if curl -fsSL "${SCRCPY_URL}" | tar -xz -C "${SCRCPY_DIR}" --strip-components=1 2>/dev/null; then + ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy" + export PATH="${SCRCPY_DIR}:${PATH}" + echo -e " ${GREEN}✓ scrcpy installed in user space.${NC}" + fi + else + ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy" + export PATH="${SCRCPY_DIR}:${PATH}" + fi + fi + fi + # User-space fallback for adb if missing and no root privileges if ! has_cmd adb; then if [[ "${ARCH_TYPE}" = "x86_64" || "${ARCH_TYPE}" = "amd64" ]]; then diff --git a/scripts/start.ps1 b/scripts/start.ps1 index fd20d3d..930748b 100644 --- a/scripts/start.ps1 +++ b/scripts/start.ps1 @@ -41,8 +41,10 @@ function Update-EnvironmentPath { "${env:ProgramFiles(x86)}\nodejs", "$env:APPDATA\npm", "$env:LOCALAPPDATA\Programs\platform-tools", + "$env:LOCALAPPDATA\Programs\scrcpy", "$env:LOCALAPPDATA\Programs\node", "$env:USERPROFILE\.local\share\platform-tools", + "$env:USERPROFILE\.local\share\scrcpy", "$env:USERPROFILE\.local\share\node", "$env:LOCALAPPDATA\nvm", "$env:ProgramData\nvm", @@ -102,6 +104,39 @@ function Install-PortablePlatformTools { return $false } +function Install-PortableScrcpy { + $scrcpyDir = "$env:LOCALAPPDATA\Programs\scrcpy" + if (Test-Path "$scrcpyDir\scrcpy.exe") { + $env:PATH = "$scrcpyDir;$env:PATH" + return $true + } + Write-Host " [INFO] Installing portable scrcpy in user space..." -ForegroundColor Cyan + try { + $zipPath = "$env:TEMP\scrcpy-win64.zip" + Invoke-WebRequest -Uri "https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-win64-v4.1.zip" -OutFile $zipPath -UseBasicParsing + $extractDir = "$env:TEMP\scrcpy_extract" + if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue } + New-Item -ItemType Directory -Path $extractDir -Force | Out-Null + Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force + $extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1 + if ($extractedFolder) { + New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null + if (Test-Path $scrcpyDir) { Remove-Item $scrcpyDir -Recurse -Force -ErrorAction SilentlyContinue } + Move-Item -Path $extractedFolder.FullName -Destination $scrcpyDir -Force + } + Remove-Item $zipPath -Force -ErrorAction SilentlyContinue + Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue + if (Test-Path "$scrcpyDir\scrcpy.exe") { + $env:PATH = "$scrcpyDir;$env:PATH" + Write-Host " ✔ Portable scrcpy installed in user space." -ForegroundColor Green + return $true + } + } catch { + Write-Host " ⚠ Failed to install portable scrcpy: $_" -ForegroundColor DarkYellow + } + return $false +} + function Test-NodeCompatible { if (-not (Test-CommandExists "node") -or -not (Test-CommandExists "npm")) { return $false } try { @@ -205,10 +240,13 @@ if ($missingCore.Count -gt 0) { Update-EnvironmentPath } - # Zero-admin user-space fallback for adb if still missing + # Zero-admin user-space fallback for adb and scrcpy if still missing if (-not (Test-CommandExists "adb")) { Install-PortablePlatformTools } + if (-not (Test-CommandExists "scrcpy")) { + Install-PortableScrcpy + } } # Ensure local ADB daemon is warm & listening so probes do not hit 'Connection refused' diff --git a/start.sh b/start.sh index e45a935..0e97dd9 100755 --- a/start.sh +++ b/start.sh @@ -39,6 +39,7 @@ STANDARD_PATHS=( "${HOME}/.local/bin" "${HOME}/.local/share/node/bin" "${HOME}/.local/share/platform-tools" + "${HOME}/.local/share/scrcpy" "${HOME}/.cargo/bin" "${HOME}/Library/Android/sdk/platform-tools" "${HOME}/Android/Sdk/platform-tools" @@ -177,7 +178,8 @@ if [ ${#MISSING_CORE[@]} -gt 0 ]; then SUDO_PREFIX="" if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi if command -v apt-get >/dev/null 2>&1; then - ${SUDO_PREFIX} apt-get update -qq && ${SUDO_PREFIX} apt-get install -y -qq "${MISSING_CORE[@]}" || true + ${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=60 update -qq 2>/dev/null || true + ${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=60 install -y -qq "${MISSING_CORE[@]}" 2>/dev/null || true elif command -v dnf >/dev/null 2>&1; then ${SUDO_PREFIX} dnf install -y "${MISSING_CORE[@]}" || true elif command -v pacman >/dev/null 2>&1; then @@ -185,6 +187,39 @@ if [ ${#MISSING_CORE[@]} -gt 0 ]; then fi fi + # Fallback: if scrcpy is still missing, try snap or install portable scrcpy in user space + if ! command -v scrcpy >/dev/null 2>&1; then + if command -v snap >/dev/null 2>&1 && request_sudo "install scrcpy via snap"; then + local SUDO_PREFIX="" + if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi + ${SUDO_PREFIX} snap install scrcpy 2>/dev/null || true + fi + fi + if ! command -v scrcpy >/dev/null 2>&1; then + ARCH="$(uname -m)" + SCRCPY_ARCH="" + case "${ARCH}" in + x86_64|amd64) SCRCPY_ARCH="x86_64" ;; + aarch64|arm64) SCRCPY_ARCH="aarch64" ;; + esac + if [ -n "${SCRCPY_ARCH}" ]; then + SCRCPY_DIR="${HOME}/.local/share/scrcpy" + if [ ! -x "${SCRCPY_DIR}/scrcpy" ]; then + echo -e " ${CYAN}📦 Installing portable scrcpy in user space (~/.local)...${NC}" + mkdir -p "${SCRCPY_DIR}" "${HOME}/.local/bin" + SCRCPY_URL="https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-linux-${SCRCPY_ARCH}-v4.1.tar.gz" + if curl -fsSL "${SCRCPY_URL}" | tar -xz -C "${SCRCPY_DIR}" --strip-components=1 2>/dev/null; then + ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy" + export PATH="${SCRCPY_DIR}:${PATH}" + echo -e " ${GREEN}✓ scrcpy installed in user space.${NC}" + fi + else + ln -sf "${SCRCPY_DIR}/scrcpy" "${HOME}/.local/bin/scrcpy" + export PATH="${SCRCPY_DIR}:${PATH}" + fi + fi + fi + # Fallback: if adb is missing on Linux without root/sudo, install platform-tools in user space if ! command -v adb >/dev/null 2>&1; then ARCH="$(uname -m)"