1#!/bin/bash
2set -e
3
4gum style --foreground 212 --border double --border-foreground 212 --padding "1 2" --align center "
5╻ ╻┏━┓┏━┓╻╺┳╸╻ ╻ ┏━╸┏━┓┏━┓┏━╸╺┳╸
6┃╻┃┣┳┛┣━┫┃ ┃ ┣━┫ ┃ ┣┳┛┣━┫┣╸ ┃
7┗┻┛╹┗╸╹ ╹╹ ╹ ╹ ╹ ┗━╸╹┗╸╹ ╹╹ ╹
8
9Install Web Apps, TUI Apps, or AppImages
10"
11
12if [ "$#" -lt 3 ]; then
13 APP_TYPE=$(gum choose "Web App" "TUI App" "AppImage")
14 APP_NAME=$(gum input --prompt "Name> " --placeholder "GitHub Desktop")
15 ICON_REF=$(gum input --prompt "Icon URL/Path (optional)> " --placeholder "https://example.com/icon.png")
16 SINGLETON=$(gum confirm "Singleton app (focus existing instance)?" && echo "yes" || echo "no")
17else
18 APP_NAME="$1"
19 APP_LOCATION="$2"
20 ICON_REF="$3"
21 CUSTOM_EXEC="$4"
22 MIME_TYPES="$5"
23fi
24
25[[ -z "$APP_NAME" ]] && { echo "App name required"; sleep 3; exit 1; }
26
27APP_ID=$(echo "$APP_NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed 's/[^a-z0-9-]//g')
28
29# ------------------ APP TYPE HANDLING ------------------
30case "$APP_TYPE" in
31 "Web App")
32 APP_LOCATION=$(gum input --prompt "URL> " --placeholder "https://github.com")
33 DOMAIN=$(echo "$APP_LOCATION" | awk -F[/:] '{print $4}' | sed 's/^www\.//')
34 APP_ID="chrome-$DOMAIN"
35 [[ "$SINGLETON" == "yes" ]] \
36 && CUSTOM_EXEC="smart-launch --web \"$APP_ID\" \"$APP_LOCATION\"" \
37 || CUSTOM_EXEC="smart-launch --web -n \"$APP_ID\" \"$APP_LOCATION\""
38 ;;
39
40 "TUI App")
41 APP_LOCATION=$(gum input --prompt "Path> " --placeholder "/usr/bin/htop")
42 [[ "$SINGLETON" == "yes" ]] \
43 && CUSTOM_EXEC="smart-launch --tui \"$APP_ID\" \"$APP_LOCATION\"" \
44 || CUSTOM_EXEC="smart-launch --tui -n \"$APP_ID\" \"$APP_LOCATION\""
45 ;;
46
47 "AppImage")
48 APPIMAGE_SRC=$(gum input --prompt "AppImage URL or Path> " --placeholder "https://example.com/app.AppImage")
49 [[ -z "$APPIMAGE_SRC" ]] && { echo "AppImage not found"; sleep 2; exit 1; }
50
51 APPIMAGE_DIR="$HOME/.local/appimages"
52 mkdir -p "$APPIMAGE_DIR"
53
54 if [[ "$APPIMAGE_SRC" =~ ^https?:// ]]; then
55 TMP_APPIMAGE="/tmp/$APP_ID.AppImage"
56 gum spin --spinner dot --title "Downloading AppImage…" -- \
57 curl -fL "$APPIMAGE_SRC" -o "$TMP_APPIMAGE"
58 APPIMAGE_PATH="$TMP_APPIMAGE"
59 else
60 APPIMAGE_PATH="$(realpath "$APPIMAGE_SRC")"
61 fi
62
63 [[ ! -f "$APPIMAGE_PATH" ]] && { echo "AppImage not found"; sleep 2; exit 1; }
64
65 INSTALL_PATH="$APPIMAGE_DIR/$APP_ID.AppImage"
66 cp "$APPIMAGE_PATH" "$INSTALL_PATH"
67 chmod +x "$INSTALL_PATH"
68
69 CUSTOM_EXEC="$INSTALL_PATH"
70
71 # Auto icon extraction (if user didn't provide one)
72 if [[ -z "$ICON_REF" ]]; then
73 TMPDIR="$(mktemp -d)"
74 pushd "$TMPDIR" >/dev/null
75 if "$INSTALL_PATH" --appimage-extract >/dev/null 2>&1; then
76 ICON_FOUND=$(find squashfs-root -type f \( -name '*.png' -o -name '*.svg' \) | head -n 1)
77 if [[ -n "$ICON_FOUND" ]]; then
78 ICON_DIR="$HOME/.assets/icons"
79 mkdir -p "$ICON_DIR"
80 ICON_REF="$ICON_DIR/$APP_ID.${ICON_FOUND##*.}"
81 cp "$ICON_FOUND" "$ICON_REF"
82 fi
83 fi
84 popd >/dev/null
85 rm -rf "$TMPDIR"
86 fi
87 ;;
88esac
89
90# ------------------ ICON MANAGEMENT ------------------
91ICON_LINE=""
92if [[ -n "$ICON_REF" ]]; then
93 ICON_DIR="$HOME/.assets/icons"
94 mkdir -p "$ICON_DIR"
95
96 if [[ "$ICON_REF" =~ ^https?:// ]]; then
97 ICON_PATH="$ICON_DIR/${APP_NAME,,}.png"
98 curl -sL -o "$ICON_PATH" "$ICON_REF" || { echo "Icon download failed"; exit 1; }
99 else
100 ICON_PATH="$ICON_REF"
101 fi
102
103 ICON_LINE="Icon=$ICON_PATH"
104fi
105
106# ------------------ DESKTOP FILE ------------------
107DESKTOP_DIR="$HOME/.local/share/applications"
108mkdir -p "$DESKTOP_DIR"
109
110DESKTOP_FILE="$DESKTOP_DIR/${APP_NAME,,}.desktop"
111
112cat >"$DESKTOP_FILE" <<EOF
113[Desktop Entry]
114Version=1.0
115Name=$APP_NAME
116Exec=$CUSTOM_EXEC
117Terminal=false
118Type=Application
119StartupNotify=true
120$ICON_LINE
121$( [[ -n "$MIME_TYPES" ]] && echo "MimeType=$MIME_TYPES" )
122EOF
123
124chmod +x "$DESKTOP_FILE"
125
126gum spin --spinner dot --title "Installed '$APP_NAME' successfully" -- sleep 2