PublicFiles/Artian-Apps/gui

650 lines
26 KiB
Bash

#!/bin/bash
error() { #red text and exit 1
echo -e "\e[91m$1\e[0m" 1>&2
exit 1
}
if ! command -v yad &>/dev/null; then
error "YAD needs to be installed to run Artian-Apps."
fi
if [[ $(id -u) == 0 ]]; then
echo "Artian-Apps is not designed to be run as root! Please try again as a regular user." | yad --center --window-icon="${DIRECTORY}/icons/logo.png" \
--width=700 --height=300 --text-info --title="Error" \
--image="${DIRECTORY}/icons/error.png" --image-on-top --fontname=12 \
--button='OK'
error "Artian-Apps is not designed to be run as root! Please try again as a regular user."
fi
# set GUI format versioning
export GUI_FORMAT_VERSION=2
#display first 4 arguments this script receives (for debugging)
if false;then
echo "1 $1" 1>&2
echo "2 $2" 1>&2
echo "3 $3" 1>&2
echo "4 $4" 1>&2
fi
#if this script runs itself with a 3rd argument, then yad used it.
if [ ! -z "$3" ];then
input="$3" #the 3rd argument is the "sysname" column - invisible and used internally for scripts.
echo "Selection: $input" 1>&2
refresh_list() { #Refresh the current list of apps in the event of a change
if [ ! -z "$pipe" ];then
echo -e "\f" > "$pipe"
"${DIRECTORY}/preload" yad "$prefix" > "$pipe" 2>/dev/null
fi
}
if [[ "$input" == *'Updates/' ]];then
#updater window
get_positions
"${DIRECTORY}/updater" gui fast $geometry2 --skip-taskbar --close-on-unfocus
exitcode=$? #0 if update successful, 1 if list of updates was closed
#figure out which prefix we are on and refresh the app list
prefix="$(echo "$input" | sed 's+Updates/$++g')"
if [ $exitcode == 0 ];then
refresh_list
fi
elif [ "$input" == 'Search/' ];then
#search window
get_positions
source "${DIRECTORY}/api" #to set the yadflags array variable
app="$(yadflags+=("$geometry2") ; app_search_gui)"
if [ ! -z "$app" ];then
"${DIRECTORY}/gui" '' "$app" "/$app" "$app"
fi
elif [[ "$input" == */ ]];then
#app folder selected
echo -e '\f' > $pipe #clear the yad list
"${DIRECTORY}/preload" yad "${input::-1}" >> $pipe #send yad the app-list - derived from folder name but dropping the final slash character
else #app details window
# make sure terminal_manage function is available
# the old updater did not source the new api script
typeset -f terminal_manage &>/dev/null || { set -a; source "${DIRECTORY}/api"; }
#app is in format $prefix/$app, so split them out
app="$(basename "$input")"
prefix="$(dirname "$input")"
#add status heading
app_status="$(app_status "${app}")"
#text to the right of the app icon
abovetext="<b>$app</b> ($(sed 's/corrupted/corrupted - installation failed/g' <<<"$app_status" | sed 's/disabled/disabled - installation is prevented on your system/g'))"
#If package-app, show what packages it installs
if [ -f "${DIRECTORY}/apps/${app}/packages" ];then
packages="$(cat "${DIRECTORY}/apps/${app}/packages")"
if [ "$(wc -w <<<"$packages")" == 1 ];then
#if package-app uses only 1 package, use singular case
abovetext+=$'\n'"- This app installs the <b>${packages}</b> package."
else
#if package-app uses multiple packages, use plural case
abovetext+=$'\n'"- This app installs these packages: <b>$(sed 's/ /, /g' <<<"$packages")</b>"
fi
fi
#show app's website if available
if [ -f "${DIRECTORY}/apps/${app}/website" ];then
website="$(head -n1 "${DIRECTORY}/apps/${app}/website")"
abovetext+=$'\n'"- Website: <a href="\""$website"\"">$website</a>"
#show credits link if available - on same line as website link
if [ -f "${DIRECTORY}/apps/${app}/credits" ];then
abovetext+=" | <a href="\""file://${DIRECTORY}/apps/${app}/credits"\"">Credits</a>"
fi
else #website unavailable
#show credits link standalone, if available
if [ -f "${DIRECTORY}/apps/${app}/credits" ];then
abovetext+=$'\n'"- <a href="\""file://${DIRECTORY}/apps/${app}/credits"\"">Credits</a>"
fi
fi
num_users="$(usercount "$app")"
if [ ! -z "$num_users" ] && [ "$num_users" -gt 20 ];then
#list the number of users, using this printf command to add commas (,) for every thousand number
abovetext+=$'\n'"- <b>$(printf "%'d" "$num_users")</b> users"
if [ "$num_users" -ge 10000 ];then
#if this app has over 10,000 users, add two exclamation points!!
abovetext+="!!"
elif [ "$num_users" -ge 1500 ];then
#if this app has over 1500 users, add an exclamation point!
abovetext+="!"
fi
fi
#array holding various buttons that may be passed to yad
whichbutton=()
if [ -f "${DIRECTORY}/apps/$app/uninstall" ] || [ -f "${DIRECTORY}/apps/$app/install" ] || [ -f "${DIRECTORY}/apps/$app/install-$arch" ];then
whichbutton+=("--button=Scripts!${DIRECTORY}/icons/shellscript.png!Feel free to see how an app is installed!"$'\n'"Perfect for learning or troubleshooting.:6")
fi
if [ "$(cat "${DIRECTORY}/data/settings/Show Edit button")" == 'Yes' ];then
#if edit button enabled, show it
whichbutton+=("--button=Edit!${DIRECTORY}/icons/edit.png!Make changes to the app:8")
fi
#display buttons based on app's installation status
if [ "$app_status" == 'installed' ];then
#if installed, display uninstall button
whichbutton+=("--button=Uninstall!${DIRECTORY}/icons/uninstall.png:2")
elif [ "$app_status" == 'uninstalled' ];then
#if uninstalled, display install button
whichbutton+=("--button=Install!${DIRECTORY}/icons/install.png:4")
elif [ "$app_status" == 'disabled' ];then
#if disabled, display only an 'enable' button
whichbutton+=("--button=<b>Enable</b>!!Force this app to install on your system."$'\n'"This app was disabled for a reason so if you enable it..."$'\n'"YOU HAVE BEEN WARNED.:12")
else
#if app status is 'corrupted', and a log file exists for this app, then display a button to view the log file
if [ "$app_status" == 'corrupted' ];then
logfile="$(ls "$DIRECTORY/logs"/* -t | grep "fail-${app}" | head -n1)"
if [ ! -z "$logfile" ];then
whichbutton+=("--button=Errors!${DIRECTORY}/icons/log-file.png!$app failed to $(echo "$(basename "$logfile")" | awk -F'-' '{print $1}'). Click this button to view the error output saved in the log file.:14")
fi
fi
#if status is corrupted or unknown, then show both buttons
whichbutton+=("--button=Uninstall!${DIRECTORY}/icons/uninstall.png:2" "--button=Install!${DIRECTORY}/icons/install.png:4")
fi
#only display app icon if it exists
if [ -f "${DIRECTORY}/apps/${app}/icon-64.png" ];then
imageline=(--image="${DIRECTORY}/apps/${app}/icon-64.png" --image-on-top)
fi
#Make sure app details window is focused (necessary for openbox window manager)
(i=0
while [ "$(xdotool getactivewindow getwindowname)" != "Details of ${app}" ] && [ $i -lt 20 ]; do
wmctrl -a "Details of ${app}" #Raise the window named "Details of ${app}"
sleep 0.2
i=$((i+1))
done) &
#display app details window
get_positions
(cat "${DIRECTORY}/apps/$app/description" || echo "Description unavailable") | yad --class Artian-Apps --name "Artian-Apps" --text-info --fontname=12 --wrap --show-uri \
--text="$(sed 's/&/&amp;/g' <<<"$abovetext")" \
"${imageline[@]}" \
--title="Details of ${app}" --window-icon="${DIRECTORY}/icons/logo.png" \
$geometry2 --close-on-unfocus --skip-taskbar \
"${whichbutton[@]}"
button=$?
case $button in
4)
#install
terminal_manage install "$app" &
;;
2)
#uninstall
terminal_manage uninstall "$app" &
;;
6)
#scripts
install_script="${DIRECTORY}/apps/${app}/$(script_name_cpu "$app")"
uninstall_script="${DIRECTORY}/apps/${app}/uninstall"
text_editor "$uninstall_script" &
sleep 0.1
text_editor "$install_script" &
"${DIRECTORY}/gui" "$@" #open details window again
;;
8)
#edit
"${DIRECTORY}/createapp" "$app"
refresh_list
;;
12)
#enable
#remove status file containing 'disabled'
rm -f "${DIRECTORY}/data/status/${app}"
refresh_list &
"${DIRECTORY}/gui" "$@" #open details window again
;;
14)
#viewlog
echo "Viewing error log of $app..."
echo "Log filepath: $logfile"
"${DIRECTORY}/etc/viewlog" "$logfile"
"${DIRECTORY}/gui" "$@" #open details window again
;;
*)
#unknown button
exit 0
;;
esac
fi
exit 0
fi
DIRECTORY="$(readlink -f "$(dirname "$0")")"
#check mission-critical scripts and re-download them if they contain a syntax error
(
sleep 10
command -v shellcheck >/dev/null || exit 0
if shellcheck "${DIRECTORY}/updater" --color=always | grep '\[31m' --before 1 ;then
echo "Downloading updater script to repair syntax error"
errors="$(wget -O "${DIRECTORY}/updater" 'https://git.fdc.abrish.ir/a.kamyar/PublicFiles/Artian-Apps/updater' 2>&1)" || echo "$errors"
fi | sed 's/]31m//g'
if shellcheck "${DIRECTORY}/api" --color=always | grep '\[31m' --before 1 ;then
echo "Downloading api script to repair syntax error"
errors="$(wget -O "${DIRECTORY}/api" 'https://git.fdc.abrish.ir/a.kamyar/PublicFiles/Artian-Apps/api' 2>&1)" || echo "$errors"
fi | sed 's/]31m//g'
) &
set -a #make all functions in the api available to subprocesses
source "${DIRECTORY}/api" || error "failed to source ${DIRECTORY}/api"
#For systems with older versions of yad, the text color column cannot be left blank. This python script determines the default text color from GTK bindings.
if [ -z "${text_color+x}" ];then
#0400 is the latest version
yad_version="$(zcat /usr/share/doc/yad/NEWS.gz | head -n 1 | tr -cd '0123456789\n')"
if [ $yad_version -lt 0400 ]; then
if command -v python3 &>/dev/null; then
python_version="python3"
else
python_version="python2"
fi
export text_color=$(echo "import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
tv = Gtk.TextView()
style = tv.get_style_context()
textcolor = style.get_color(Gtk.StateType.NORMAL)
print(Gdk.RGBA.to_string(textcolor))
" | $python_version -)
else
export text_color=""
fi
fi
#display the Artian-Apps logo in the terminal
generate_logo &
#install dependencies
runonce <<"EOF"
dependencies='yad curl wget aria2 lsb-release software-properties-common apt-utils apt-transport-https gnupg imagemagick bc librsvg2-bin locales shellcheck git wmctrl xdotool x11-utils rsync'
# Install dependencies if necessary
if ! dpkg -s $dependencies >/dev/null 2>&1; then
sudo_popup apt install $dependencies -y -f --no-install-recommends
fi
EOF
#Various stuff to run in background (enclosed in brackets so Geany IDE can collapse the code)
{
mkdir -p "${DIRECTORY}/data/status" "${DIRECTORY}/data/update-status" \
"${DIRECTORY}/data/preload" "${DIRECTORY}/data/settings" \
"${DIRECTORY}/data/status" "${DIRECTORY}/data/update-status" \
"${DIRECTORY}/data/categories"
#check for updates
"${DIRECTORY}/updater" set-status &
trap "kill $! &>/dev/null" EXIT #kill the above subprocess on exit
#Click Artian-Apps usage link every time the GUI is run only if the 'Enable Analytics' setting is enabled
if [ "$(cat "${DIRECTORY}/data/settings/Enable analytics")" == 'Yes' ];then
#click it
curl -s -X 'GET' "https://git.fdc.abrish.ir/a.kamyar/PublicFiles/Artian-Apps" -H 'accept: image/gif' -A "Artian-Apps software manager for Artian company" >/dev/null &
fi
}
#Determine the app list mode. Allowed values: 'yad-*', 'xlunch-*'
guimode="$(cat "${DIRECTORY}/data/settings/App List Style")"
[ -z "$guimode" ] && guimode=yad-default
#In YAD mode, two windows are handled in a side-by-side configuration. As a group, they must be centered on the the screen.
#In Xlunch mode, the window must be centered, but xlunch only handles absolute offsets.
get_positions() {
#determine screen_width and screen_height
screen_dimensions="$(xrandr --nograb --current | awk -F 'connected |\\+|\\(' '/ connected.*[0-9]+x[0-9]+\+/ && $2 {printf $2 ", "}' | sed -n -e 's/^.*primary //p' | tr 'x+' ' ' | tr ',+' ' ')"
if [ -z "$screen_dimensions" ];then
# if screen_dimensions is empty, this could be a single monitor wayland display which does not have the word "primary" in the output
# workaround is to get the first output returned for the connected display
screen_dimensions="$(xrandr --nograb --current | awk -F 'connected |\\+|\\(' '/ connected.*[0-9]+x[0-9]+\+/ && $2 {printf $2 ", "}' | tr 'x+' ' ' | tr ',+' ' ')"
fi
screen_width="$(awk '{print $1}' <<<"$screen_dimensions")"
screen_height="$(awk '{print $2}' <<<"$screen_dimensions")"
unset screen_dimensions
if [[ "$guimode" == yad* ]];then
# if this is being run by yad, there should be a yad window id
# store in arrary of x and y
# this allows for windows to be moved by the user and the second window to still show up where expected
main_yad_window=$YAD_XID
if [ -n "${main_yad_window}" ]; then
window_info=$(xwininfo -id $main_yad_window)
# for speed of execution, we are assuming the order of matches from xwininfo
# this is safe as the output order has been standardized for over a decade
# this is the location of where the window content starts inside the title bar and window borders (pos x then pos y)
main_yad_window_pos=($(echo "$window_info" | sed -n 's/Absolute upper-left.*://p'))
# these are the dimensions of where the window content starts inside the title bar and window borders (dim x then dim y)
main_yad_window_dim=($(echo "$window_info" | sed -n 's/Width://p;s/Height://p'))
# again, for speed, all border widths are saved to one array
# left, right, title, bottom [0, 1, 2, 3]
# this is the size of the window borders (including title bar)
border_widths=($(xprop _NET_FRAME_EXTENTS -id "$main_yad_window" | sed -n 's/_NET_FRAME_EXTENTS.*=//p' | tr ',' '\n'))
#total dimensions for both yad windows side by side
if [ $screen_width -le 1000 ] || [ $screen_height -le 600 ];then
#gui size for small screens
height=${main_yad_window_dim[1]}
width=600
#width of first window
width1=${main_yad_window_dim[0]}
#width of second window
width2=350
else
#gui size for large screens
height=${main_yad_window_dim[1]}
width=800
#width of first window
width1=${main_yad_window_dim[0]}
#width of second window
width2=480
fi
#how far down the top of the title bar of yad window is from the top of the screen
yoffset=$((main_yad_window_pos[1]-border_widths[2]))
#screen offsets for window 1
#use current position of the left side of the main window border
xoffset1=$((main_yad_window_pos[0]-border_widths[0]))
#screen offsets for window 2
#use current position of the right side of the main window border
xoffset2=$((xoffset1+border_widths[0]+width1+border_widths[1]))
#set completed location arguments for both yad windows
geometry1="--geometry=${width1}x${height}+${xoffset1}+${yoffset}"
geometry2="--geometry=${width2}x${height}+${xoffset2}+${yoffset}"
else
# default positions when the main window does not exist yet
#total dimensions for both yad windows side by side
if [ $screen_width -le 1000 ] || [ $screen_height -le 600 ];then
#gui size for small screens
height=400
width=600
#width of first window
width1=250
#width of second window
width2=$((width - width1))
else
#gui size for large screens
height=600
width=800
#width of first window
width1=320
#width of second window
width2=$((width - width1))
fi
#how far down the top of the title bar of yad window is from the top of the screen
yoffset=$(((screen_height/2)-(height/2)))
#screen offsets for window 1
xoffset1=$(((screen_width/2)-(width/2)))
#screen offsets for window 2
xoffset2=$(((screen_width/2)-(width/2)+width1))
#set completed location arguments for both yad windows
geometry1="--geometry=${width1}x${height}+${xoffset1}+${yoffset}"
geometry2="--geometry=${width2}x${height}+${xoffset2}+${yoffset}"
fi
elif [[ "$guimode" == xlunch* ]];then
#desired dimensions for xlunch window
height=700
width=800
#determine
xoffset=$(((screen_width/2)-(width/2)))
yoffset=$(((screen_height/2)-(height/2)))
else
error "Unrecognized app list style '$guimode'!"
fi
}
# run get_positions once incase sometime requires the position value immediatly
get_positions
#Compile xlunch if required
if [[ "$guimode" == xlunch* ]] && ([ ! -d "${DIRECTORY}/xlunch" ] || [ ! -f /usr/bin/xlunch ]);then
#signal files
rm -f /tmp/xlunchfailed /tmp/xlunchfinished /tmp/terminalexit
echo '' > /tmp/terminalexit
"${DIRECTORY}/etc/terminal-run" "
function error {
echo -e "\""\e[91m$1\e[39m"\""
echo 'Close this terminal to exit.'
echo '' > /tmp/xlunchfailed
sleep infinity
}
trap 'echo "\"""\"" > /tmp/terminalexit' EXIT
#uninstall xlunch first
sudo rm -rf /etc/xlunch /usr/share/xlunch /usr/bin/xlunch /usr/bin/genentries /usr/bin/updateentries /usr/bin/genentries.desktop.sh /usr/share/icons/hicolor/48x48/apps/xlunch_ghost.png /usr/share/icons/hicolor/48x48/apps/xlunch.png /usr/share/applications/genentries.desktop
rm -f /tmp/terminalexit
sudo rm -rf /usr/bin/xlunch "\""$DIRECTORY/xlunch"\"" 2>/dev/null
sudo apt install -y libimlib2-dev libx11-dev || error 'APT failed to install libimlib2-dev and libx11-dev packages!'
cd "\""$DIRECTORY"\""
git clone https://github.com/Tomas-M/xlunch.git || error 'Failed to clone xlunch repository!'
cd "\""$DIRECTORY/xlunch"\""
echo 'Running make...'
echo "\"""\$"(cat '${DIRECTORY}/xlunch/Makefile' | grep -v 'genentries \|cp -r svgicons/')"\"" > '${DIRECTORY}/xlunch/Makefile'
make -j8 || error 'make command failed!'
echo 'Running sudo make install...'
sudo make install || error 'sudo make install failed!'
sudo rm -f /usr/share/applications/genentries.desktop
cd $HOME
if [ ! -f /usr/bin/xlunch ];then
error 'xlunch should be installed now, but /usr/bin/xlunch does not exist!'
fi
echo '' > /tmp/xlunchfinished
" 'Compiling xlunch...'
#if terminal doesn't start in 3 seconds, then /tmp/terminalexit will exist.
sleep 3
#check for an exit status code from the running terminal
while true; do
if [ -f /tmp/xlunchfinished ];then
echo "xlunch finished installing."
break
elif [ -f /tmp/xlunchfailed ];then
#revert back to yad
echo 'yad-default' > "{DIRECTORY}/data/settings/App List Style"
error "xlunch failed to compile!"
elif [ -f /tmp/terminalexit ];then #if terminal doesn't start in 3 seconds, then /tmp/terminalexit will exist.
#revert back to yad
echo 'yad-default' > "{DIRECTORY}/data/settings/App List Style"
error "The xlunch compilation terminal exited prematurely."
else
sleep 1
fi
done
fi
#Determine message of the day. If announcements file missing or over a day old, download it.
if [ ! -f "${DIRECTORY}/data/announcements" ] || [ ! -z "$(find "${DIRECTORY}/data/announcements" -mtime +1 -print)" ]; then
announcements="$(wget -qO- https://git.fdc.abrish.ir/a.kamyar/PublicFiles/Artian-Apps)"
echo "$announcements" > "${DIRECTORY}/data/announcements"
fi & #use $announcements and & here to avoid delaying launch or emptying the file before download completes
if [[ "$guimode" == yad* ]];then
#create a named pipe to send app list through to yad
pipe="$(mktemp -u)" #get a random filename to work with
mkfifo $pipe #make the named pipe
trap "rm -f $pipe" EXIT #remove this named pipe on exit
echo pipe is $pipe
while true;do #main operating loop for yad window
#in background process, send initial app list to yad; first echo line waits until yad is accepting input, then use small delay to prevent items from being missed
(echo -e '\f' > $pipe
sleep 0.5
"${DIRECTORY}/preload" yad '' >> $pipe) &
#retrieve a random line from the announcements file for this session
motd="$(shuf -n 1 "${DIRECTORY}/data/announcements")"
#constantly read from the pipe and send all output to yad
#if an item is selected, this script will be run with the row's contents
{ yad --class Artian-Apps --name "Artian-Apps" --center --title='Artian-Apps' \
--image="${DIRECTORY}/icons/logo-64.png" --image-on-top --text "$motd" \
--list --no-headers --column=:IMG --column=Name --column=Sysname:HD --column=tip:HD --column=@fore@:HD \
--separator='\n' --window-icon="${DIRECTORY}/icons/logo.png" \
--tooltip-column=4 \
--dclick-action "env pipe=$pipe '${DIRECTORY}/gui'" --select-action "env pipe=$pipe '${DIRECTORY}/gui'" \
--button="!${DIRECTORY}/icons/search.png"!'Search':"env pipe=$pipe '${DIRECTORY}/gui' '' '' Search/ Search/" \
--button="!${DIRECTORY}/icons/options.png"!'Settings':2 \
"$geometry1"; button=$?; kill "$!"; } < <(exec tail -f --retry $pipe)
case $button in
2) #settings
# remove pipe early so that nothing attempts to write to it
rm -f "$pipe"
"${DIRECTORY}/settings"
"${DIRECTORY}/gui" "$@" #run new instance of this script
exit 0
;;
3) #search
app="$(yadflags+=("$geometry2") ; app_search_gui)"
if [ ! -z "$app" ];then
"${DIRECTORY}/gui" '' "$app" "/$app" "$app"
fi
;;
*) #unknown button
exit 0
;;
esac
done
#END of yad main window loop
elif [[ "$guimode" == xlunch* ]];then
#create a named pipe to send app list through to yad
pipe="$(mktemp -u)" #get a random filename to work with
mkfifo $pipe #make the named pipe
trap "rm $pipe" EXIT #remove this named pipe on exit
echo pipe is $pipe
#disabled, but too cool to remove: this can make the transparent background of xlunch blurry - like Windows 7
if false;then
scrot -a "$((xoffset+1)),$((yoffset+33)),${width},${height}" blur.png #blur_init.png
convert -blur 10x5 ~/blur.png ~/blur.png
fi
#Depending on the xlunch theme, different arguments will be used.
if [ "$guimode" == xlunch-light-3d ];then
#light mode
xlunchflags=(--multiple --dontquit -WoCS -s 64 --bc e0e0e000 --tc 000000 --pc 6060ffff --hc ffffff50 \
-p "Search: " -a -c $([ $width -lt 550 ] && echo 1 || echo 2) --title "Artian-Apps: Artian app store" \
--icon "${DIRECTORY}/icons/logo.png" --scrollbarcolor ffffff40 --scrollindicatorcolor 0000ff80 \
--width $width --height $height --xposition $xoffset --yposition $yoffset \
--button "${DIRECTORY}/icons/logo-3d.png;;$((($width/2)-(300/2))),0;:exec echo Artian-apps-homepage" \
--button "${DIRECTORY}/icons/settings-dark.png;;$(($width-140)),30;:exec echo Artian-apps-settings" \
-g "${DIRECTORY}/icons/background-3d.png")
elif [ "$guimode" == xlunch-dark-3d ];then
#dark mode, 3d opaque version
xlunchflags=(--multiple --dontquit -WoCS -s 64 --bc ffffff00 --tc DCDDDE --pc ffffffa0 --hc ffffff30 \
-p "Search: " -a -c $([ $width -lt 550 ] && echo 1 || echo 2) --title "Artian-Apps: Artian app store" \
--icon "${DIRECTORY}/icons/logo.png" --scrollbarcolor ffffff20 --scrollindicatorcolor ffffff40 \
--width $width --height $height --xposition $xoffset --yposition $yoffset \
--button "${DIRECTORY}/icons/logo-3d-dark.png;;$((($width/2)-(300/2))),0;:exec echo Artian-apps-homepage" \
--button "${DIRECTORY}/icons/settings-light.png;;$(($width-140)),30;:exec echo Artian-apps-settings" \
-g "${DIRECTORY}/icons/background-3d-dark.png")
else
#dark mode, transparent version
xlunchflags=(--multiple --dontquit -WoCS -s 64 --bc 000000A0 --tc ffffffff --pc 6060ffff --hc ffffff30 \
-p "Search: " -a -c $([ $width -lt 550 ] && echo 1 || echo 2) --title "Artian-Apps: Artian app store" \
--icon "${DIRECTORY}/icons/logo.png" --scrollbarcolor ffffff40 --scrollindicatorcolor 0000ff80 \
--width $width --height $height --xposition $xoffset --yposition $yoffset \
--button "${DIRECTORY}/icons/logo-128.png;;$((($width/2)-(128/2))),0;:exec echo Artian-apps-homepage" \
--button "${DIRECTORY}/icons/logo-text.png;;$([ -z "$prefix" ] && echo '45' || echo '65'),$([ -z "$prefix" ] && echo '10' || echo '0');:exec echo Artian-apps-homepage" \
--button "${DIRECTORY}/icons/settings-light.png;;$(($width-140)),30;:exec echo Artian-apps-settings")
fi
#in background process, send initial app list to xlunch; first echo line waits until xlunch is accepting input
(
#set initial value to make xlunch keep listening
echo 'botspot is cool' > $pipe
echo "$("${DIRECTORY}/preload" xlunch '')" > $pipe) &
#read pipe pipe to xlunch read output of xlunch
tail -f --retry $pipe | xlunch "${xlunchflags[@]}" | while read -r line; do
echo "Received '$line'"
if [ "$line" == 'Updates/' ];then
echo > $pipe #clear list
#in subprocess, open details window for app
geometry2="--center --height=$((height/2)) --width=$width" pipe='' "${DIRECTORY}/gui" '' '' "$line" "$line"
#back to main level
"${DIRECTORY}/preload" xlunch '' > $pipe
#category selected
elif [[ "$line" == */ ]];then
echo > $pipe #clear list
"${DIRECTORY}/preload" xlunch "$(echo "$line" | sed 's+/$++g')" > $pipe
#Artian-apps logo button clicked
elif [ "$line" == 'Artian-apps-homepage' ];then
x-www-browser "$(cat "https://artianhpc.ir/")" &
# x-www-browser "$(cat "${DIRECTORY}/etc/git_url")" &
#Settings button clicked
elif [ "$line" == 'Artian-apps-settings' ];then
#close xlunch
echo ':quit' > $pipe
#run settings, then run Artian-apps gui
"${DIRECTORY}/settings"
"${DIRECTORY}/gui" "$@"
#exit this script
exit 0
#app selected
else
echo > $pipe #clear list
#in subprocess, open details window for app
geometry2="--center --height=$((height/2)) --width=$width" pipe='' "${DIRECTORY}/gui" '' '' "$line" "$line"
#show app list again
"${DIRECTORY}/preload" xlunch "$(dirname "$line" | sed 's/^.$//g')" > $pipe
fi
done
fi