Desktop: always-visible work indication — indeterminate bars while running w/o pct, summarize job row, upload phase on library rows; dev-loop watcher fixes
This commit is contained in:
parent
a5201c1f2f
commit
7b3436837a
3 changed files with 65 additions and 22 deletions
|
|
@ -840,6 +840,10 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
|
||||||
val ref = runCatching {
|
val ref = runCatching {
|
||||||
provider.upload(draft) { p ->
|
provider.upload(draft) { p ->
|
||||||
d.uploadProgress = p
|
d.uploadProgress = p
|
||||||
|
// Row shows the upload too — pressing Transcribe must
|
||||||
|
// always change something on screen, immediately.
|
||||||
|
setLive(d.file.name, LiveProgress("uploading…", p))
|
||||||
|
rescanStatuses()
|
||||||
_detail.value = d.copy()
|
_detail.value = d.copy()
|
||||||
}
|
}
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
|
|
|
||||||
|
|
@ -196,12 +196,19 @@ fun LibraryScreen(state: DesktopState) {
|
||||||
else -> MaterialTheme.colorScheme.onSurfaceVariant
|
else -> MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if (e.progress != null) {
|
if (e.status == FileStatus.RUNNING) {
|
||||||
Spacer(Modifier.height(6.dp))
|
Spacer(Modifier.height(6.dp))
|
||||||
LinearProgressIndicator(
|
val frac = e.progress
|
||||||
progress = { e.progress },
|
if (frac != null) {
|
||||||
modifier = Modifier.fillMaxWidth().height(4.dp),
|
LinearProgressIndicator(
|
||||||
)
|
progress = { frac },
|
||||||
|
modifier = Modifier.fillMaxWidth().height(4.dp),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.fillMaxWidth().height(4.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e.status == FileStatus.NEW || e.status == FileStatus.FAILED) {
|
if (e.status == FileStatus.NEW || e.status == FileStatus.FAILED) {
|
||||||
|
|
@ -318,14 +325,30 @@ fun DetailScreen(state: DesktopState) {
|
||||||
Text(label, style = MaterialTheme.typography.bodyMedium,
|
Text(label, style = MaterialTheme.typography.bodyMedium,
|
||||||
color = if (it.status == "failed") MaterialTheme.colorScheme.error
|
color = if (it.status == "failed") MaterialTheme.colorScheme.error
|
||||||
else MaterialTheme.colorScheme.primary)
|
else MaterialTheme.colorScheme.primary)
|
||||||
if (running && it.progress != null) {
|
if (running) {
|
||||||
Spacer(Modifier.height(4.dp))
|
Spacer(Modifier.height(4.dp))
|
||||||
LinearProgressIndicator(
|
if (it.progress != null) {
|
||||||
progress = { it.progress / 100f },
|
LinearProgressIndicator(
|
||||||
modifier = Modifier.fillMaxWidth().height(4.dp),
|
progress = { it.progress / 100f },
|
||||||
)
|
modifier = Modifier.fillMaxWidth().height(4.dp),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.fillMaxWidth().height(4.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val sJob = detail.jobs.firstOrNull { it.jobType == "summarize" }
|
||||||
|
sJob?.takeIf { it.status == "running" || it.status == "queued" }?.let {
|
||||||
|
val label = if (it.status == "running") "Summarizing…" else "Summary queued"
|
||||||
|
Text(label, style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = MaterialTheme.colorScheme.primary)
|
||||||
|
Spacer(Modifier.height(4.dp))
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.fillMaxWidth().height(4.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
detail.error?.let {
|
detail.error?.let {
|
||||||
Text(it, color = MaterialTheme.colorScheme.error)
|
Text(it, color = MaterialTheme.colorScheme.error)
|
||||||
if (tJob?.status == "failed") {
|
if (tJob?.status == "failed") {
|
||||||
|
|
|
||||||
|
|
@ -4,28 +4,43 @@
|
||||||
# (SHONAR_DEV=1 -> uvicorn --reload), so backend edits apply live too.
|
# (SHONAR_DEV=1 -> uvicorn --reload), so backend edits apply live too.
|
||||||
#
|
#
|
||||||
# Stop with Ctrl-C (or pkill -f desktop-dev.sh).
|
# Stop with Ctrl-C (or pkill -f desktop-dev.sh).
|
||||||
set -euo pipefail
|
set -uo pipefail
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
export SHONAR_DEV=1
|
export SHONAR_DEV=1
|
||||||
export DISPLAY="${DISPLAY:-:0}"
|
export DISPLAY="${DISPLAY:-:0}"
|
||||||
|
|
||||||
WATCH_DIRS=(
|
|
||||||
"app/src/main/kotlin"
|
|
||||||
"../../android/app/src/main/java/com/shonar"
|
|
||||||
)
|
|
||||||
FLAG="$(pwd)/.dev-restart-flag"
|
FLAG="$(pwd)/.dev-restart-flag"
|
||||||
|
|
||||||
|
# Watch targets resolved to absolute paths, non-existent dirs skipped at
|
||||||
|
# start but retried each cycle (inotifywait -r tolerates a dir appearing).
|
||||||
|
watch_targets() {
|
||||||
|
local t=()
|
||||||
|
for d in "$PWD/app/src/main/kotlin" \
|
||||||
|
"$PWD/../android/app/src/main/java/com/shonar" \
|
||||||
|
"$PWD/../backend/shonar"; do
|
||||||
|
[ -d "$d" ] && t+=("$d")
|
||||||
|
done
|
||||||
|
printf '%s\n' "${t[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
pkill -f "com.shonar.desktop.MainKt" 2>/dev/null || true
|
pkill -f "com.shonar.desktop.MainKt" 2>/dev/null || true
|
||||||
rm -f "$FLAG"
|
rm -f "$FLAG"
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
(
|
(
|
||||||
while inotifywait -qq -e close_write,move \
|
while true; do
|
||||||
--include '\.kt$|\.kts$' "${WATCH_DIRS[@]}" 2>/dev/null; do
|
mapfile -t TARGETS < <(watch_targets)
|
||||||
echo "[dev] source change -> restarting app…"
|
[ ${#TARGETS[@]} -eq 0 ] && { sleep 5; continue; }
|
||||||
touch "$FLAG"
|
if inotifywait -qq -e close_write,move --include '\.kt$|\.kts$' \
|
||||||
pkill -f "com.shonar.desktop.MainKt" 2>/dev/null || true
|
-r "${TARGETS[@]}"; then
|
||||||
|
echo "[dev] source change -> restarting app…"
|
||||||
|
touch "$FLAG"
|
||||||
|
pkill -f "com.shonar.desktop.MainKt" 2>/dev/null || true
|
||||||
|
sleep 2 # debounce bursts (editor writes can fire several events)
|
||||||
|
else
|
||||||
|
sleep 5 # targets vanished; retry with a fresh list
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
) &
|
) &
|
||||||
WATCHER=$!
|
WATCHER=$!
|
||||||
|
|
@ -39,6 +54,7 @@ while true; do
|
||||||
fi
|
fi
|
||||||
rm -f "$FLAG"
|
rm -f "$FLAG"
|
||||||
# App closed cleanly or build failed — wait for the next edit.
|
# App closed cleanly or build failed — wait for the next edit.
|
||||||
# (Build failure: gradlew prints the error; the loop idles until you fix it.)
|
mapfile -t TARGETS < <(watch_targets)
|
||||||
inotifywait -qq -e close_write,move --include '\.kt$|\.kts$' "${WATCH_DIRS[@]}"
|
[ ${#TARGETS[@]} -eq 0 ] && { sleep 5; continue; }
|
||||||
|
inotifywait -qq -e close_write,move --include '\.kt$|\.kts$' -r "${TARGETS[@]}" || sleep 5
|
||||||
done
|
done
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue