From 9499d1095e294b03f0eac011402db9028a9fb4aa Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Sat, 23 Aug 2025 20:57:58 -0500 Subject: [PATCH] hopefully done --- .github/workflows/ci_cd.yml | 2 - .github/workflows/release.yml | 366 +++++++++++++++++++++++++++++++--- .gitignore | 3 - APPIMAGE_TROUBLESHOOTING.md | 49 ----- scripts/build_AppImage.py | 0 scripts/build_AppImage.sh | 243 ---------------------- src/adb_manager.py | 10 +- src/gui/file_browser.py | 2 +- 8 files changed, 335 insertions(+), 340 deletions(-) delete mode 100644 APPIMAGE_TROUBLESHOOTING.md delete mode 100644 scripts/build_AppImage.py delete mode 100755 scripts/build_AppImage.sh diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 116bac6..bf8e643 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -3,8 +3,6 @@ name: CI/CD Pipeline on: workflow_dispatch: - pull_request: - branches: [ main ] jobs: test: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0449ca0..c6401be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,61 +1,361 @@ -# .github/workflows/release.yml -name: Release +name: Build and Publish Multi-Platform on: workflow_dispatch: + inputs: + version: + description: 'Release version (e.g., 1.0.0)' + required: true + type: string + +env: + APP_NAME: yourapp + PYTHON_VERSION: "3.12" jobs: - release: - runs-on: ${{ matrix.os }} + build: strategy: matrix: + os: [ubuntu-latest, windows-latest, ubuntu-20.04] include: - os: ubuntu-latest - asset_name: android-file-handler-linux - - os: windows-latest - asset_name: android-file-handler-windows.exe + platform: linux-deb + binary_name: yourapp + - os: windows-latest + platform: windows + binary_name: yourapp.exe + - os: ubuntu-20.04 + platform: linux-rpm + binary_name: yourapp + - os: ubuntu-latest + platform: linux-arch + binary_name: yourapp + container: archlinux:latest + runs-on: ${{ matrix.os }} + container: ${{ matrix.container }} + steps: - uses: actions/checkout@v4 - - name: Install AppImage dependencies (Linux) - if: matrix.os == 'ubuntu-latest' + - name: Setup Arch Linux environment + if: matrix.platform == 'linux-arch' run: | - sudo apt update - sudo apt install -y fuse libfuse2 curl imagemagick - - - name: Set up Python + pacman -Sy --noconfirm + pacman -S --noconfirm python python-pip base-devel git + pip install poetry + + - name: Set up Python ${{ env.PYTHON_VERSION }} + if: matrix.platform != 'linux-arch' uses: actions/setup-python@v4 with: - python-version: '3.12' + python-version: ${{ env.PYTHON_VERSION }} - name: Install Poetry + if: matrix.platform != 'linux-arch' uses: snok/install-poetry@v1 with: version: latest virtualenvs-create: true virtualenvs-in-project: true - - - name: Install dependencies - run: poetry install - - - name: Build AppImage (Linux) - if: matrix.os == 'ubuntu-latest' - env: - CI_CD: true - run: | - chmod +x scripts/build_AppImage.sh - ./scripts/build_AppImage.sh - - - name: Build executable (Windows) - if: matrix.os == 'windows-latest' + + - name: Lock and install dependencies run: | poetry lock poetry install - poetry run pyinstaller --onefile src/main.py --distpath dist --name android-file-handler-windows - - - name: Create Release + + - name: Build binary with PyInstaller + run: | + poetry run pip install pyinstaller + poetry run pyinstaller --onefile --name ${{ matrix.binary_name }} main.py + + - name: Install fpm (Ubuntu/Debian) + if: matrix.platform == 'linux-deb' || matrix.platform == 'linux-rpm' + run: | + sudo apt-get update + sudo apt-get install -y ruby ruby-dev rubygems build-essential rpm + sudo gem install --no-document fpm + + - name: Install package tools (Arch) + if: matrix.platform == 'linux-arch' + run: | + pacman -S --noconfirm base-devel + + - name: Create .deb package + if: matrix.platform == 'linux-deb' + run: | + mkdir -p package/usr/bin + cp dist/${{ matrix.binary_name }} package/usr/bin/ + fpm -s dir -t deb -n ${{ env.APP_NAME }} -v ${{ github.event.inputs.version }} \ + --description "Your Python desktop application" \ + --depends "python3.12" \ + --maintainer "Your Name " \ + --url "https://github.com/${{ github.repository }}" \ + -C package \ + usr/bin/${{ matrix.binary_name }}=/usr/bin/${{ env.APP_NAME }} + + - name: Create .rpm package + if: matrix.platform == 'linux-rpm' + run: | + mkdir -p package/usr/bin + cp dist/${{ matrix.binary_name }} package/usr/bin/ + fpm -s dir -t rpm -n ${{ env.APP_NAME }} -v ${{ github.event.inputs.version }} \ + --description "Your Python desktop application" \ + --depends "python3.12" \ + --maintainer "Your Name " \ + --url "https://github.com/${{ github.repository }}" \ + -C package \ + usr/bin/${{ matrix.binary_name }}=/usr/bin/${{ env.APP_NAME }} + + - name: Create Arch PKGBUILD + if: matrix.platform == 'linux-arch' + run: | + # Create PKGBUILD file for AUR submission + cat > PKGBUILD << EOF + # Maintainer: Your Name + pkgname=${{ env.APP_NAME }} + pkgver=${{ github.event.inputs.version }} + pkgrel=1 + pkgdesc="Your Python desktop application" + arch=('x86_64') + url="https://github.com/${{ github.repository }}" + license=('MIT') + depends=('python') + source=("\$pkgname-\$pkgver::https://github.com/${{ github.repository }}/releases/download/v\$pkgver/${{ env.APP_NAME }}-\$pkgver-linux") + sha256sums=('SKIP') # Will be updated with actual checksums + + package() { + install -Dm755 "\$srcdir/\$pkgname-\$pkgver" "\$pkgdir/usr/bin/\$pkgname" + } + EOF + + # Create .SRCINFO file + makepkg --printsrcinfo > .SRCINFO + + - name: Create PKGBUILD for AUR + if: matrix.platform == 'linux-deb' + run: | + cat > PKGBUILD << 'EOF' + pkgname=${{ env.APP_NAME }} + pkgver=${{ github.event.inputs.version }} + pkgrel=1 + pkgdesc="Your Python desktop application" + arch=('x86_64') + url="https://github.com/${{ github.repository }}" + depends=('python312') + source=("$pkgname-$pkgver::https://github.com/${{ github.repository }}/releases/download/v$pkgver/${{ env.APP_NAME }}-${{ github.event.inputs.version }}-linux") + sha256sums=('SKIP') # You should replace this with actual checksums + + package() { + install -Dm755 "$srcdir/$pkgname-$pkgver" "$pkgdir/usr/bin/$pkgname" + } + EOF + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.platform }}-artifacts + path: | + dist/${{ matrix.binary_name }} + *.deb + *.rpm + PKGBUILD + .SRCINFO + + release: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v3 + with: + path: artifacts + + - name: Prepare release assets + run: | + mkdir -p release-assets + + # Rename binaries for release + cp artifacts/linux-deb-artifacts/dist/yourapp release-assets/${{ env.APP_NAME }}-${{ github.event.inputs.version }}-linux + cp artifacts/windows-artifacts/dist/yourapp.exe release-assets/${{ env.APP_NAME }}-${{ github.event.inputs.version }}-windows.exe + + # Copy packages + find artifacts -name "*.deb" -exec cp {} release-assets/ \; + find artifacts -name "*.rpm" -exec cp {} release-assets/ \; + find artifacts -name "PKGBUILD" -exec cp {} release-assets/ \; + find artifacts -name ".SRCINFO" -exec cp {} release-assets/ \; + + chmod +x release-assets/${{ env.APP_NAME }}-${{ github.event.inputs.version }}-linux + + - name: Create GitHub Release uses: softprops/action-gh-release@v1 with: - files: dist/${{ matrix.asset_name }} - generate_release_notes: true \ No newline at end of file + tag_name: v${{ github.event.inputs.version }} + name: Release ${{ github.event.inputs.version }} + draft: false + prerelease: false + files: release-assets/* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + publish-aur: + needs: release + runs-on: ubuntu-latest + steps: + - name: Download PKGBUILD artifact + uses: actions/download-artifact@v3 + with: + name: linux-arch-artifacts + path: aur-files + + - name: Set up SSH for AUR + run: | + mkdir -p ~/.ssh + echo "${{ secrets.AUR_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts + + # Configure git + git config --global user.name "${{ secrets.AUR_USER_NAME }}" + git config --global user.email "${{ secrets.AUR_USER_EMAIL }}" + + - name: Clone AUR repository + run: | + git clone ssh://aur@aur.archlinux.org/${{ env.APP_NAME }}.git aur-repo || { + echo "Package doesn't exist in AUR yet, creating new repository" + mkdir aur-repo + cd aur-repo + git init + git remote add origin ssh://aur@aur.archlinux.org/${{ env.APP_NAME }}.git + } + + - name: Prepare AUR files + run: | + cd aur-repo + cp ../aur-files/PKGBUILD . + cp ../aur-files/.SRCINFO . + + - name: Commit and push to AUR + run: | + cd aur-repo + git add PKGBUILD .SRCINFO + git commit -m "Update to version ${{ github.event.inputs.version }}" || echo "No changes to commit" + git push origin master + + publish-repos: + needs: [release, publish-aur] + runs-on: ubuntu-latest + steps: + - name: Checkout repository pages + uses: actions/checkout@v4 + with: + repository: ${{ github.repository_owner }}/${{ github.repository_owner }}.github.io + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + path: pages-repo + + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + path: artifacts + + - name: Set up repository structure + run: | + cd pages-repo + mkdir -p apt/dists/stable/main/binary-amd64 + mkdir -p dnf/x86_64 + + - name: Install repository tools + run: | + sudo apt-get update + sudo apt-get install -y dpkg-dev createrepo-c + + - name: Update APT repository + run: | + cd pages-repo/apt + + # Copy .deb files + find ../../artifacts -name "*.deb" -exec cp {} dists/stable/main/binary-amd64/ \; + + # Create Packages file + cd dists/stable/main/binary-amd64 + dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz + dpkg-scanpackages . /dev/null > Packages + + # Create Release file + cd ../../../ + cat > dists/stable/Release << EOF + Origin: ${{ github.repository_owner }} + Label: ${{ github.repository_owner }} APT Repository + Suite: stable + Codename: stable + Architectures: amd64 + Components: main + Description: Personal APT repository for ${{ env.APP_NAME }} + EOF + + - name: Update DNF repository + run: | + cd pages-repo/dnf/x86_64 + + # Copy .rpm files + find ../../../artifacts -name "*.rpm" -exec cp {} . \; + + # Create repository metadata + createrepo_c . + + - name: Create repository index page + run: | + cd pages-repo + cat > index.html << 'EOF' + + + + ${{ env.APP_NAME }} Repositories + + +

${{ env.APP_NAME }} Package Repositories

+ +

APT (Ubuntu/Debian)

+
+        echo "deb https://${{ github.repository_owner }}.github.io/apt stable main" | sudo tee /etc/apt/sources.list.d/${{ env.APP_NAME }}.list
+        sudo apt update
+        sudo apt install ${{ env.APP_NAME }}
+            
+ +

DNF (Fedora/RHEL)

+
+        sudo tee /etc/yum.repos.d/${{ env.APP_NAME }}.repo << EOF
+        [${{ env.APP_NAME }}]
+        name=${{ env.APP_NAME }} Repository
+        baseurl=https://${{ github.repository_owner }}.github.io/dnf/\$basearch
+        enabled=1
+        gpgcheck=0
+        EOF
+        sudo dnf install ${{ env.APP_NAME }}
+            
+ +

AUR (Arch Linux)

+
+        yay -S ${{ env.APP_NAME }}
+        # or
+        git clone https://aur.archlinux.org/${{ env.APP_NAME }}.git
+        cd ${{ env.APP_NAME }}
+        makepkg -si
+            
+ +

Direct Downloads

+

Check the releases page for direct binary downloads.

+ + + EOF + + - name: Commit and push repository updates + run: | + cd pages-repo + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git add . + git commit -m "Update repositories for ${{ env.APP_NAME }} v${{ github.event.inputs.version }}" || echo "No changes to commit" + git push \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5910875..b57b245 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,8 @@ platform-tools** dist/ build_temp/ -AppDir/ build *.ini -squashfs-root - # Python cache files __pycache__/ diff --git a/APPIMAGE_TROUBLESHOOTING.md b/APPIMAGE_TROUBLESHOOTING.md deleted file mode 100644 index 3ebcb6a..0000000 --- a/APPIMAGE_TROUBLESHOOTING.md +++ /dev/null @@ -1,49 +0,0 @@ -# AppImage Troubleshooting - -## XCB Threading Error - -If you encounter this error when running the AppImage: - -``` -[xcb] Unknown sequence number while appending request -[xcb] You called XInitThreads, this is not your fault -[xcb] Aborting, sorry about that. -python3.12: ../../src/xcb_io.c:157: append_pending_request: Assertion `!xcb_xlib_unknown_seq_number' failed. -``` - -This is a known issue with certain Linux distributions and X11/XCB configurations. - -### Solutions: - -1. **Try different display server settings:** - ```bash - export LIBXCB_ALLOW_SLOPPY_LOCK=1 - ./android-file-handler-linux - ``` - -2. **Use virtual framebuffer (if available):** - ```bash - xvfb-run -a ./android-file-handler-linux - ``` - -3. **Try on different Linux distribution:** - - This issue is more common on certain Ubuntu/Debian configurations - - The AppImage should work fine on most other distributions - -4. **Alternative: Run from source:** - ```bash - git clone - cd android_file_handler_adb - poetry install - poetry run python src/main.py - ``` - -## Verification that AppImage is Correct - -Despite the XCB error, the AppImage is properly built: -- ✅ All dependencies included (requests, urllib3, etc.) -- ✅ Python 3.12 runtime embedded -- ✅ All source code packaged -- ✅ 72MB self-contained executable - -The issue is environment-specific, not a packaging problem. diff --git a/scripts/build_AppImage.py b/scripts/build_AppImage.py deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/build_AppImage.sh b/scripts/build_AppImage.sh deleted file mode 100755 index 9e16b7d..0000000 --- a/scripts/build_AppImage.sh +++ /dev/null @@ -1,243 +0,0 @@ -#!/bin/bash - -# Check if an old AppImage exists and remove it -if [ -f "dist/android-file-handler-linux.AppImage" ]; then - echo "Removing old AppImage..." - rm -f dist/android-file-handler-linux.AppImage -fi - -# Check if required packages are installed -missing_packages=() -for package in fuse libfuse2 curl imagemagick; do - if ! dpkg -l | grep -q "^ii $package "; then - missing_packages+=("$package") - fi -done - -# Only run apt commands if there are missing packages -if [ ${#missing_packages[@]} -gt 0 ]; then - echo "Installing missing packages: ${missing_packages[*]}" - sudo apt update - sudo apt install -y "${missing_packages[@]}" -else - echo "All required packages are already installed" -fi - -mkdir build_temp -cd build_temp || exit 1 - -# Download portable Python 3.12 -echo "Downloading portable Python 3.12..." -PYTHON_VERSION="3.12.5" -PYTHON_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz" - -if ! curl -L "$PYTHON_URL" -o "python-${PYTHON_VERSION}.tgz"; then - echo "Error: Failed to download Python source" - exit 1 -fi - -# For simplicity, let's use a pre-built Python binary instead -echo "Downloading pre-built Python 3.12 for Linux..." -if ! curl -L "https://github.com/indygreg/python-build-standalone/releases/download/20240713/cpython-3.12.4+20240713-x86_64-unknown-linux-gnu-install_only.tar.gz" -o "python-standalone.tar.gz"; then - echo "Error: Failed to download Python standalone" - exit 1 -fi - -# Extract Python -echo "Extracting Python..." -tar -xzf python-standalone.tar.gz - -# Rename the extracted directory for consistency -if [ -d "python" ]; then - mv python python3.12 -fi - -# Check if extraction was successful -if [ ! -d "python3.12" ]; then - echo "Error: Python extraction failed" - exit 1 -fi - -# 2. Create AppDir structure -mkdir -p AppDir/opt/python3.12 -mkdir -p AppDir/usr/share/{applications,icons/hicolor/256x256/apps} -mkdir -p AppDir/opt/android-file-handler - -# 3. Copy Python runtime to AppDir -echo "Copying Python runtime..." -if [ -d "python3.12" ]; then - cp -r python3.12/* AppDir/opt/python3.12/ 2>/dev/null || echo "Failed to copy Python runtime" -else - echo "Error: Python directory not found" - exit 1 -fi - -# Make sure Python binary is executable -chmod +x AppDir/opt/python3.12/bin/python3* 2>/dev/null || true - -# 4. Install dependencies using the portable Python -echo "Installing dependencies..." -cd .. - -cd build_temp -echo "Installing packages..." -# Install specific packages we need directly -AppDir/opt/python3.12/bin/python3.12 -m pip install requests urllib3 certifi charset-normalizer idna --target AppDir/opt/python3.12/lib/python3.12/site-packages/ --no-deps --force-reinstall - -# 5. Copy application source -echo "Copying application source..." -cp -r ../src/* AppDir/opt/android-file-handler/ - -# Create a launcher script to handle XCB issues -cat > AppDir/opt/android-file-handler/launcher.py << 'EOF' -#!/usr/bin/env python3 -""" -Launcher script to handle threading and import issues in AppImage -""" -import os -import sys -import threading - -# Critical: Set single-threaded mode BEFORE any imports -os.environ['OMP_NUM_THREADS'] = '1' -os.environ['MKL_NUM_THREADS'] = '1' -os.environ['NUMEXPR_NUM_THREADS'] = '1' - -# XCB environment fixes -os.environ['QT_X11_NO_MITSHM'] = '1' -os.environ['_X11_NO_MITSHM'] = '1' -os.environ['_MITSHM'] = '0' -os.environ['LIBXCB_ALLOW_SLOPPY_LOCK'] = '1' -os.environ['TK_SILENCE_DEPRECATION'] = '1' - -def main(): - """Main launcher function with proper thread handling""" - try: - # Force single-threaded mode - threading.current_thread().name = "MainThread" - - # Add the application directory to Python path - app_dir = os.path.dirname(os.path.abspath(__file__)) - if app_dir not in sys.path: - sys.path.insert(0, app_dir) - - # Also ensure packages directory is in path - packages_dir = os.path.join(os.path.dirname(app_dir), 'python3.12', 'lib', 'python3.12', 'site-packages') - if os.path.exists(packages_dir) and packages_dir not in sys.path: - sys.path.insert(0, packages_dir) - - # Import tkinter early and set up single-threaded mode - import tkinter as tk - - # Allow default root but ensure single-threaded operation - # Don't call NoDefaultRoot() - let the app create its own root - - try: - # Import the main application - import main - main.main() - - except ImportError: - try: - # Fallback import path - from gui.main_window import main as app_main - app_main() - except Exception as e: - print(f"Failed to import application: {e}") - sys.exit(1) - - except Exception as e: - print(f"Application startup error: {e}") - sys.exit(1) - -if __name__ == "__main__": - main() -EOF - -# 6. Create .desktop file -cat > AppDir/android-file-handler.desktop << 'EOF' -[Desktop Entry] -Type=Application -Name=Android File Handler -Exec=AppRun -Icon=android-file-handler -Categories=Utility; -EOF - -# 7. Create AppRun script -cat > AppDir/AppRun << 'EOF' -#!/bin/bash -HERE="$(dirname "$(readlink -f "${0}")")" -export APPDIR="$HERE" - -# Force single-threaded execution -export OMP_NUM_THREADS=1 -export MKL_NUM_THREADS=1 -export NUMEXPR_NUM_THREADS=1 - -# Set up Python paths -export PYTHONPATH="$HERE/opt/python3.12/lib/python3.12/site-packages:$HERE/opt/android-file-handler:$PYTHONPATH" -export PATH="$HERE/opt/python3.12/bin:$PATH" - -# Python runtime settings -export PYTHONDONTWRITEBYTECODE=1 -export PYTHONUNBUFFERED=1 - -# XCB and GUI fixes -export QT_X11_NO_MITSHM=1 -export _X11_NO_MITSHM=1 -export _MITSHM=0 -export LIBXCB_ALLOW_SLOPPY_LOCK=1 -export TK_SILENCE_DEPRECATION=1 - -# Additional GUI stability settings -export GDK_BACKEND=x11 -export XDG_SESSION_TYPE=x11 - -# Disable CI mode to prevent threading issues -export CI_MODE=false - -# Find Python executable -PYTHON="$HERE/opt/python3.12/bin/python3.12" -if [ ! -f "$PYTHON" ]; then - PYTHON="$HERE/opt/python3.12/bin/python3" -fi - -if [ ! -f "$PYTHON" ]; then - echo "Error: Python not found in AppImage" - exit 1 -fi - -# Change to application directory to ensure proper imports -cd "$HERE/opt/android-file-handler" - -# Run with explicit single-threaded mode and ensure Python path is set -PYTHONPATH="$HERE/opt/python3.12/lib/python3.12/site-packages:$HERE/opt/android-file-handler:$PYTHONPATH" exec "$PYTHON" -u launcher.py "$@" -EOF - -chmod +x AppDir/AppRun - -# 9. Create icon in the correct location for appimagetool -convert -size 256x256 xc:lightblue -pointsize 48 -fill black -gravity center -annotate +0+0 "AFH" AppDir/usr/share/icons/hicolor/256x256/apps/android-file-handler.png 2>/dev/null || true -# Also create icon in AppDir root as appimagetool expects -cp AppDir/usr/share/icons/hicolor/256x256/apps/android-file-handler.png AppDir/android-file-handler.png 2>/dev/null || true - -# 10. Download and setup appimagetool -for attempt in 1 2 3; do - curl -L -o appimagetool https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage && break - sleep 5 -done -chmod +x appimagetool - -# 11. Create AppImage directly in parent dist folder -mkdir -p ../dist -if ! ./appimagetool AppDir ../dist/android-file-handler-linux; then - echo "AppImage creation failed" - exit 1 -fi - -# 12. Clean up (only in local development, not CI/CD) -cd .. -if [ "${CI_CD:-false}" != "true" ]; then - rm -rf build_temp -fi \ No newline at end of file diff --git a/src/adb_manager.py b/src/adb_manager.py index 992f355..76c61ad 100644 --- a/src/adb_manager.py +++ b/src/adb_manager.py @@ -25,17 +25,9 @@ def get_executable_directory() -> str: return os.path.dirname(os.path.abspath(__file__)) def get_platform_tools_directory() -> str: - """Get platform-tools directory with executable and AppImage support.""" + """Get platform-tools directory.""" base_dir = get_executable_directory() - # For AppImages running from temporary mounts, use persistent storage - if sys.platform.startswith('linux') and ('tmp' in base_dir and '.mount_' in base_dir): - # AppImage temporary mount - use persistent user directory - home_dir = os.path.expanduser("~") - persistent_dir = os.path.join(home_dir, ".android-file-handler", "platform-tools") - os.makedirs(os.path.dirname(persistent_dir), exist_ok=True) - return persistent_dir - # Check if we're in development mode (running from src/ directory) if not getattr(sys, 'frozen', False): # Running as script - check if we're in src/ directory or subdirectory diff --git a/src/gui/file_browser.py b/src/gui/file_browser.py index c6b65d2..2406ce6 100644 --- a/src/gui/file_browser.py +++ b/src/gui/file_browser.py @@ -1,6 +1,6 @@ """ Windows Android Browser Module -Provides Android filesystem browsing capabilities for Windows using ADB. +Provides Android filesystem browsing capabilities for Windows and Linux using ADB. """ import threading