I have a GitHub Action that automates downloading and injecting YouTube tweaks into an IPA file. I would like to convert this functionality into a native macOS app using SwiftUI.

The app should allow the user to:

	•	Provide a direct URL to a decrypted IPA file and select the version of the tweak to use.
	•	Enable/disable specific tweaks via checkboxes (enabled by default).
	•	Add custom GitHub repositories dynamically using a “+” button.
	•	Download YouTube and tweak files, clone various submodules, build them, and inject the tweaks into the IPA.
	•	Display the status of each step (e.g., downloading, building, injecting) and the final results of successful and failed builds.

Requirements:

	1.	SwiftUI-based Interface:
	•	Two text fields for the IPA URL and tweak version.
	•	A list of checkboxes for each tweak (enabled by default) that the user can toggle on or off.
	•	A “+” button to allow the user to manually add custom GitHub repositories (with a URL input).
	•	A “Start Process” button to begin the automation.
	•	A log view that displays the progress and results of the task.
	2.	Functional Conversion:
	•	Replicate the core functionality of the GitHub Action:
	•	Clone repositories (either predefined or user-added), check for cached files, and run the build commands.
	•	Build only the tweaks selected by the user.
	•	Inject the selected tweaks into the IPA file.
	•	Implement logic to allow the user to add new repositories, which should be cloned and built similarly to the predefined ones.
	3.	Asynchronous Execution:
	•	Ensure that all tasks (downloads, builds, injections) are done asynchronously to keep the UI responsive.
	•	Update the log view with real-time progress.
	4.	Architecture:
	•	Use MVVM (Model-View-ViewModel) for clean separation of concerns.
	5.	macOS Compatibility:
	•	Ensure compatibility with macOS 12.0+ and Swift 5.

Here is the full GitHub Action YAML file for reference:

name: YouTube Plus + YTLitePlus Tweaks

on:
  workflow_dispatch:
    inputs:
      ipa_url:
        description: "The direct URL to the decrypted IPA file"
        default: ""
        required: true
        type: string
      tweak_version:
        description: "The version of the tweak to use. Enter the version manually from dayanch96/YTLite/releases or leave default"
        default: "5.0.2"
        required: true
        type: string

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build:
    name: Build Tweaks
    runs-on: macos-12
    permissions:
      contents: write

    steps:
      - name: Checkout Main
        uses: actions/checkout@v4.1.1

      - name: Install Dependencies
        run: brew install make

      - name: Set PATH environment variable
        run: echo "$(brew --prefix make)/libexec/gnubin" >> $GITHUB_PATH

      - name: Cache Theos
        id: theos
        uses: actions/cache@v4.0.1
        env:
          cache-name: theos_cache
        with:
          path: theos/
          key: ${{ env.cache-name }}
          restore-keys: ${{ env.cache-name }}

      - name: Setup Theos
        if: steps.theos.outputs.cache-hit != 'true'
        uses: actions/checkout@v4.1.7
        with:
          repository: theos/theos
          ref: 3da31488281ecf4394d10302d2629607f4a1aa07
          path: ${{ github.workspace }}/theos
          submodules: recursive

      - name: Download iOS SDKs
        if: steps.theos.outputs.cache-hit != 'true'
        run: |
          git clone --quiet -n --depth=1 --filter=tree:0 https://github.com/theos/sdks/
          cd sdks
          git sparse-checkout set --no-cone iPhoneOS13.7.sdk iPhoneOS16.5.sdk
          git checkout
          mkdir -p $THEOS/sdks
          mv iPhoneOS13.7.sdk iPhoneOS16.5.sdk $THEOS/sdks/
          echo "SDK contents:"
          ls -R $THEOS/sdks
        env:
          THEOS: ${{ github.workspace }}/theos


      - name: Install Pyzule
        run: bash -c "$(curl https://raw.githubusercontent.com/asdfzxcvbn/pyzule/main/install-pyzule.sh)"

      - name: Download YouTube
        run: wget "${{ inputs.ipa_url }}" --no-verbose -O ${{ github.workspace }}/youtube.ipa

      - name: Download YouTube Plus
        run: |
          deb_url="https://github.com/dayanch96/YTLite/releases/download/v${{ inputs.tweak_version }}/com.dvntm.ytlite_${{ inputs.tweak_version }}_iphoneos-arm.deb"
          wget "$deb_url" --no-verbose -O ${{ github.workspace }}/ytplus.deb

      - name: Clone and Build Submodules
        id: build_submodules
        run: |
          mkdir -p ${{ github.workspace }}/Tweaks
          cd ${{ github.workspace }}/Tweaks
          
          submodules=(
            "https://github.com/therealFoxster/DontEatMyContent.git"
            "https://github.com/Balackburn/YTLitePlus"
            "https://github.com/arichornloverALT/YTVideoOverlay.git"
            "https://github.com/PoomSmart/YouPiP"
            "https://github.com/PoomSmart/YTABConfig"
            "https://github.com/PoomSmart/YTUHD"
            "https://github.com/PoomSmart/YouGroupSettings"
            "https://github.com/PoomSmart/YouMute"
            "https://github.com/PoomSmart/YouQuality"
            "https://github.com/arichornloverALT/Return-YouTube-Dislikes.git"
            "https://github.com/arichornloverALT/YouTimeStamp.git"
            "https://github.com/bhackel/YouLoop"
          )

          successful_builds=()
          failed_builds=()

          # Clone YouTubeHeader repository once in the parent directory
          git clone --recursive --depth=1 https://github.com/PoomSmart/YouTubeHeader.git

          # Clone and build each submodule
          for submodule in "${submodules[@]}"; do
            repo_name=$(basename $submodule .git)
            if git clone --recursive --depth=1 $submodule $repo_name; then
              cd $repo_name
              
              # Create a symbolic link to YouTubeHeader in the tweak directory
              ln -s ../YouTubeHeader YouTubeHeader
              
              # Also create a symbolic link in the parent directory if it doesn't exist
              if [ ! -e "../YouTubeHeader" ]; then
                ln -s YouTubeHeader ../YouTubeHeader
              fi
              
              if [ -f "Makefile" ]; then
                echo "Building $repo_name"
                if make clean package DEBUG=0 FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless; then
                  if mv packages/*.deb ${{ github.workspace }}/"${repo_name}.deb"; then
                    successful_builds+=("$repo_name")
                  else
                    failed_builds+=("$repo_name (No .deb file produced)")
                  fi
                else
                  failed_builds+=("$repo_name (Build failed)")
                fi
              else
                failed_builds+=("$repo_name (No Makefile)")
              fi
              cd ..
            else
              failed_builds+=("$repo_name (Clone failed)")
            fi
          done

          echo "successful_builds=${successful_builds[*]}" >> $GITHUB_OUTPUT
          echo "failed_builds=${failed_builds[*]}" >> $GITHUB_OUTPUT
        env:
          THEOS: ${{ github.workspace }}/theos
        continue-on-error: true
        
      - name: Clone Open in YouTube (Safari extension)
        run: |
          git clone --quiet -n --depth=1 --filter=tree:0 https://github.com/CokePokes/YoutubeExtensions/
          cd YoutubeExtensions
          git sparse-checkout set --no-cone OpenYoutubeSafariExtension.appex
          git checkout
          mv *.appex ${{ github.workspace }}

      - name: Inject tweaks into IPA
        id: inject_tweaks
        run: |
          tweaks=""
          for deb in ${{ github.workspace }}/*.deb; do
            tweaks="$tweaks $deb"
          done
          pyzule -i ${{ github.workspace }}/youtube.ipa -o ${{ github.workspace }}/YouTubePlus_${{ inputs.tweak_version }}_AllTweaks.ipa -w -u -f $tweaks ${{ github.workspace }}/OpenYoutubeSafariExtension.appex
          echo "ipa_size=$(ls -lh ${{ github.workspace }}/YouTubePlus_${{ inputs.tweak_version }}_AllTweaks.ipa | awk '{print $5}')" >> $GITHUB_OUTPUT

      - name: Upload to GitHub Releases
        uses: softprops/action-gh-release@v2.0.1
        with:
          tag_name: v${{ github.run_number }}
          name: YouTubePlus v${{ inputs.tweak_version }} + All Tweaks (${{ github.run_number }})
          files: YouTubePlus_${{ inputs.tweak_version }}_AllTweaks.ipa
          draft: true

      - name: Generate Job Summary
        run: |
          echo "# YouTube Plus Build Summary" >> $GITHUB_STEP_SUMMARY
          echo "## Build Information" >> $GITHUB_STEP_SUMMARY
          echo "- YouTube Plus Version: ${{ inputs.tweak_version }}" >> $GITHUB_STEP_SUMMARY
          echo "- Build Number: ${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY
          echo "- Final IPA Size: ${{ steps.inject_tweaks.outputs.ipa_size }}" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          
          echo "## Build Results" >> $GITHUB_STEP_SUMMARY
          
          # Process successful builds
          echo "### Successfully Built and Injected Tweaks" >> $GITHUB_STEP_SUMMARY
          if [ -n "${{ steps.build_submodules.outputs.successful_builds }}" ]; then
            echo "${{ steps.build_submodules.outputs.successful_builds }}" | tr ' ' '\n' | sed 's/^/- /' >> $GITHUB_STEP_SUMMARY
          else
            echo "No successful builds" >> $GITHUB_STEP_SUMMARY
          fi
          echo "" >> $GITHUB_STEP_SUMMARY
          
          # Process failed builds
          echo "### Failed Builds or Injections" >> $GITHUB_STEP_SUMMARY
          if [ -n "${{ steps.build_submodules.outputs.failed_builds }}" ]; then
            echo "${{ steps.build_submodules.outputs.failed_builds }}" | tr ' ' '\n' | sed 's/^/- /' >> $GITHUB_STEP_SUMMARY
          else
            echo "No failed builds" >> $GITHUB_STEP_SUMMARY
          fi
          echo "" >> $GITHUB_STEP_SUMMARY
          
          # Calculate statistics
          echo "## Build Statistics" >> $GITHUB_STEP_SUMMARY
          successful_count=$(echo "${{ steps.build_submodules.outputs.successful_builds }}" | wc -w)
          failed_count=$(echo "${{ steps.build_submodules.outputs.failed_builds }}" | wc -w)
          total_count=$((successful_count + failed_count))
          
          echo "- Total attempted builds: $total_count" >> $GITHUB_STEP_SUMMARY
          
          if [ $total_count -gt 0 ]; then
            success_rate=$(awk "BEGIN {printf \"%.2f\", ($successful_count / $total_count) * 100}")
            echo "- Success rate: ${success_rate}%" >> $GITHUB_STEP_SUMMARY
          else
            echo "- Success rate: N/A (no builds attempted)" >> $GITHUB_STEP_SUMMARY
          fi