#!/bin/bash #this generates a yad-friendly app list. This is run every time the gui script is executed. #if this script detects nothing has changed since last run, then it will echo back the app list that was generated last time. DIRECTORY="$(readlink -f "$(dirname "$0")")" function error { echo -e "\e[91m$1\e[39m" 1>&2 exit 1 } source "${DIRECTORY}/api" || error "failed to source ${DIRECTORY}/api" #yad or xlunch format format="$1" if [ -z "$format" ];then format=yad elif [[ "$format" = xlunch* ]];then format=xlunch elif [ "$format" != 'yad' ] && [ "$format" != 'xlunch' ];then error "Unknown list format '$format'!" fi #specifies an app folder(s) prefix="$2" timestampfile="${DIRECTORY}/data/preload/timestamps-$(echo "$prefix" | tr -d '/')" listfile="${DIRECTORY}/data/preload/LIST-$(echo "$prefix" | tr -d '/')" mkdir -p "${DIRECTORY}/data/preload" { #compile the genapplist-yad.c program if [ ! -f "${DIRECTORY}/etc/genapplist-yad" ] && [ -f "${DIRECTORY}/etc/genapplist-yad.c" ];then echo "Compiling genapplist-yad program..." 1>&2 command -v gcc >/dev/null || sudo apt install -y gcc 1>&2 gcc "${DIRECTORY}/etc/genapplist-yad.c" -o "${DIRECTORY}/etc/genapplist-yad" 1>&2 || failed=1 #Test the program and make sure it outputs 5 lines if [ "$(APPS=Arduino DIRECTORY="$DIRECTORY" "${DIRECTORY}/etc/genapplist-yad" | wc -l)" != 5 ];then failed=1 fi if [ "$failed" == 1 ];then rm -f "${DIRECTORY}/etc/genapplist-yad" echo "The genapplist-yad program failed to compile." 1>&2 else echo "Success! The genapplist-yad program has been compiled." 1>&2 fi fi } mktimestamps() { #these directories are checked for changes checkdirs="${DIRECTORY}/apps ${DIRECTORY}/data/settings ${DIRECTORY}/data/status ${DIRECTORY}/data/update-status ${DIRECTORY}/etc" timestamps='' local IFS=$'\n' for dir in $checkdirs do timestamps="$timestamps dir $dir $(stat -c %Y "${dir}/$(ls -t "$dir" | head -n1)")" done #remove first empty newline and check a few other things for changes too timestamps="prefix: $prefix format: $format number of files: $(ls -1q "${DIRECTORY}/apps"/* | wc -l) preload shasum: $(sha256sum "${DIRECTORY}/preload" | awk '{print $1}') api shasum: $(sha256sum "${DIRECTORY}/api" | awk '{print $1}') structure shasum: $(shasum "${DIRECTORY}/data/categories/structure" | awk '{print $1}') ${timestamps:1}" } reloadlist=0 if [ -f "$timestampfile" ];then #get modified timestamps for directories mktimestamps if [ "$timestamps" == "$(cat "$timestampfile")" ];then #if current timestamps and saved timestamps match, then don't reload the list reloadlist=0 echo "Timestamps match." 1>&2 else #timestamps don't match, so reload the list reloadlist=1 echo "Timestamps don't match" 1>&2 echo -e "original file: $(cat "$timestampfile")\nnew timestamp: $timestamps" 1>&2 fi else #timestamp file not found reloadlist=1 fi if [ ! -f "$listfile" ] || [ -z "$(cat "$listfile")" ];then echo "list file for $prefix does not exist." 1>&2 reloadlist=1 fi if [ $reloadlist == 1 ];then echo "Generating list..." 1>&2 #for app_categories() and app_status() functions source "${DIRECTORY}/api" vfiles="$(app_categories | grep . | sort | uniq)" #generate a virtual file system with apps in folders represented as subdirectories if [ ! -z "$prefix" ];then echo "Showing apps within $prefix/" 1>&2 vfiles="$(echo "$vfiles" | grep "^$prefix/" | sed "s+$prefix/++g")" fi #remove apps within categories - show this layer of stuff only. vfiles="$(echo "$vfiles" | sed 's+/.*+/+g' | sort | uniq)" #get list of apps - excluding folders APPS="$(echo "$vfiles" | grep -v '/')" #get list of folders - excluding apps - and hide the hidden folder. DIRS="$(echo "$vfiles" | grep '/' | tr -d '/' | grep -vx "hidden")" #If updates available, show special Updates category if "${DIRECTORY}/updater" get-status &>/dev/null;then DIRS="Updates $DIRS" fi #shuffle the list if enabled if [ "$(cat "${DIRECTORY}/data/settings/Shuffle App list")" == 'Yes' ];then APPS="$(echo "$APPS" | shuf)" DIRS="$(echo "$DIRS" | shuf)" fi #remove apps that are not compatible with OS architecture PREIFS="$IFS" IFS=$'\n' for i in $APPS do #if install script doesn't exist -------------------- and if os-specific install script doesn't exist, then... if [ ! -f "${DIRECTORY}/apps/${i}/install" ] && [ ! -f "${DIRECTORY}/apps/${i}/install-${arch}" ];then #...remove the app from the list echo "Removing $i from the list because it is not compatible with your ${arch}-bit OS." 1>&2 APPS="$(echo "$APPS" | grep -vx "$i")" fi done IFS="$PREIFS" if [ "$format" == yad ];then PREIFS="$IFS" IFS=$'\n' LIST='' for i in $DIRS do if [ -f "${DIRECTORY}/icons/categories/${i}.png" ];then diricon="${DIRECTORY}/icons/categories/${i}.png" else diricon="${DIRECTORY}/icons/categories/default.png" fi LIST="${LIST}$diricon ${DIRECTORY}/icons/none-24.png $i $i/ App folder " done #finished preloading categories #set to false to disable genapplist-yad program - use the original bash version if true && [ -f "${DIRECTORY}/etc/genapplist-yad" ];then LIST="$LIST$(DIRECTORY="$DIRECTORY" APPS="$APPS" "${DIRECTORY}/etc/genapplist-yad") " else for i in $APPS do status1="$(cat "${DIRECTORY}/data/status/${i}" 2>/dev/null || echo "none")" status2="$(echo "$status1" | sed 's/none/uninstalled/g')" LIST="$LIST$(echo "${DIRECTORY}/icons/$status1.png") ${DIRECTORY}/apps/${i}/icon-24.png $i $i "\("$status2"\)" $(head -n1 "${DIRECTORY}/apps/${i}/description" || echo "Description unavailable") " done fi #finished preloading apps IFS="$PREIFS" elif [ "$format" == xlunch ];then #XUNCH list format PREIFS="$IFS" IFS=$'\n' LIST='' for i in $DIRS do if [ -f "${DIRECTORY}/icons/categories/${i}-64.png" ];then diricon="${DIRECTORY}/icons/categories/${i}-64.png" else diricon="${DIRECTORY}/icons/categories/default-64.png" fi LIST="$LIST ${i};$diricon;${i}/" done for i in $APPS do LIST="$LIST ${i} ($(app_status "${i}"));${DIRECTORY}/apps/${i}/icon-64.png;${i}" done IFS="$PREIFS" fi LIST="$(echo -e "$LIST")" #save entire list string to file for future use echo "$LIST" > "$listfile" #save timestamps to file too mktimestamps echo "$timestamps" > "$timestampfile" else echo "Reading list file..." 1>&2 LIST="$(cat "$listfile")" fi (#put icons in cache PREIFS="$IFS" IFS=$'\n' for icon in $(echo "$LIST" | grep icon-24) do cat "$icon" &>/dev/null #echo "Putting $icon in cache..." 1>&2 done IFS="$PREIFS" ) & echo "$LIST" #preload all categories in background "${DIRECTORY}/etc/preload-daemon" "$format" &>/dev/null &