Make sure expected directories exist in home.

This commit is contained in:
Storm Dragon
2026-04-21 18:57:00 -04:00
parent 038d2f4b62
commit c6a182a47a
3 changed files with 134 additions and 6 deletions

View File

@@ -0,0 +1,13 @@
[Unit]
Description=Create Stormux user directories
RequiresMountsFor=/home/stormux
After=local-fs.target user@1000.service
[Service]
Type=oneshot
User=stormux
Environment=HOME=/home/stormux
ExecStart=/usr/bin/xdg-user-dirs-update
[Install]
WantedBy=multi-user.target

View File

@@ -5,31 +5,47 @@ download_with_fallback() {
local outputPath="$1"
local sourceUrl="$2"
local errorFile=""
local curlArgs=(
--fail
--show-error
--location
--connect-timeout 20
--speed-limit 1024
--speed-time 30
--retry 3
--retry-connrefused
--retry-delay 2
)
local curlExitCode=0
local retryExitCode=0
local fallbackExitCode=0
local wgetExitCode=0
local totalBytes=0
downloadAttemptExitCodes=""
downloadErrorLog=""
errorFile="$(mktemp)" || return 1
totalBytes="$(get_remote_file_size "${sourceUrl}")"
if curl -L4 -C - --retry 10 --output "${outputPath}" "${sourceUrl}" 2> "${errorFile}"; then
printf 'Trying curl with resume support: %s\n' "${sourceUrl}" >&2
if run_download_command "${outputPath}" "${totalBytes}" "${errorFile}" curl -4 -C - "${curlArgs[@]}" --output "${outputPath}" "${sourceUrl}"; then
rm -f "${errorFile}"
return 0
fi
curlExitCode=$?
rm -f "${outputPath}"
if curl -L4 --retry 10 --output "${outputPath}" "${sourceUrl}" 2>> "${errorFile}"; then
printf 'Trying fresh IPv4 curl download: %s\n' "${sourceUrl}" >&2
if run_download_command "${outputPath}" "${totalBytes}" "${errorFile}" curl -4 "${curlArgs[@]}" --output "${outputPath}" "${sourceUrl}"; then
rm -f "${errorFile}"
return 0
fi
retryExitCode=$?
rm -f "${outputPath}"
if curl -L --retry 10 --output "${outputPath}" "${sourceUrl}" 2>> "${errorFile}"; then
printf 'Trying fresh curl download with any address family: %s\n' "${sourceUrl}" >&2
if run_download_command "${outputPath}" "${totalBytes}" "${errorFile}" curl "${curlArgs[@]}" --output "${outputPath}" "${sourceUrl}"; then
rm -f "${errorFile}"
return 0
fi
@@ -37,7 +53,8 @@ download_with_fallback() {
if command -v wget > /dev/null 2>&1; then
rm -f "${outputPath}"
if wget --tries=10 --output-document="${outputPath}" "${sourceUrl}" 2>> "${errorFile}"; then
printf 'Trying wget fallback: %s\n' "${sourceUrl}" >&2
if run_download_command "${outputPath}" "${totalBytes}" "${errorFile}" wget --tries=3 --timeout=20 --read-timeout=30 --output-document="${outputPath}" "${sourceUrl}"; then
rm -f "${errorFile}"
return 0
fi
@@ -58,6 +75,102 @@ download_with_fallback() {
return 1
}
get_remote_file_size() {
local sourceUrl="$1"
local headerOutput
headerOutput="$(curl --fail --silent --show-error --location --head --max-redirs 10 --max-time 20 "${sourceUrl}" 2> /dev/null || true)"
awk '
BEGIN { IGNORECASE = 1 }
/^content-length:/ {
gsub("\r", "", $2)
if ($2 ~ /^[0-9]+$/) {
contentLength = $2
}
}
END {
if (contentLength != "") {
print contentLength
} else {
print 0
}
}
' <<< "${headerOutput}"
}
beep_download_progress() {
local percent="$1"
local frequency
[[ "${STORMUX_DOWNLOAD_BEEPS:-1}" == "1" ]] || return 0
command -v play > /dev/null 2>&1 || return 0
frequency="$((220 + (percent * 7)))"
play -q -n synth 0.06 sine "${frequency}" vol 0.12 > /dev/null 2>&1 || true
}
monitor_download_progress() {
local outputPath="$1"
local totalBytes="$2"
local doneFile="$3"
local currentBytes=0
local percent=0
local lastAnnouncedPercent=-10
local tickCount=0
while [[ ! -e "$doneFile" ]]; do
if [[ -f "$outputPath" ]]; then
currentBytes="$(stat -c '%s' "$outputPath" 2> /dev/null || printf '0')"
else
currentBytes=0
fi
if [[ "$totalBytes" -gt 0 ]]; then
percent="$(((currentBytes * 100) / totalBytes))"
if [[ "$percent" -gt 100 ]]; then
percent=100
fi
if [[ "$percent" -ge $((lastAnnouncedPercent + 10)) ]]; then
printf 'Downloaded %s%% (%s/%s bytes)\n' "$percent" "$currentBytes" "$totalBytes" >&2
beep_download_progress "$percent"
lastAnnouncedPercent="$percent"
fi
else
tickCount="$((tickCount + 1))"
if [[ "$tickCount" -ge 5 ]]; then
printf 'Downloaded %s bytes\n' "$currentBytes" >&2
beep_download_progress 50
tickCount=0
fi
fi
sleep 2
done
}
run_download_command() {
local outputPath="$1"
local totalBytes="$2"
local errorFile="$3"
local doneFile
local monitorPid
local commandStatus=0
shift 3
doneFile="$(mktemp)" || return 1
rm -f "$doneFile"
monitor_download_progress "$outputPath" "$totalBytes" "$doneFile" &
monitorPid="$!"
"$@" 2> >(tee -a "$errorFile" >&2)
commandStatus="$?"
touch "$doneFile"
wait "$monitorPid" 2> /dev/null || true
rm -f "$doneFile"
return "$commandStatus"
}
validate_downloaded_cache_file() {
local dest="$1"
local downloadError=0

View File

@@ -583,11 +583,13 @@ class VoicedMenu:
# Add the appropriate items based on current status for each service
for friendlyName, serviceName in self.systemMenuServices.items():
isActive = self.check_service_status(serviceName)
startLabel = "Start" if friendlyName == "Fenrir Screen Reader" else "Enable"
stopLabel = "Stop" if friendlyName == "Fenrir Screen Reader" else "Disable"
if isActive:
self.add_item("System", f"Disable {friendlyName}",
self.add_item("System", f"{stopLabel} {friendlyName}",
lambda fn=friendlyName: self.toggle_service(fn))
else:
self.add_item("System", f"Enable {friendlyName}",
self.add_item("System", f"{startLabel} {friendlyName}",
lambda fn=friendlyName: self.toggle_service(fn))
def install_and_launch(self, executable_name, launch_mode="gui"):