Lazy load theme switcher thumbnails
This commit is contained in:
@@ -19,7 +19,8 @@ Usage:
|
|||||||
|
|
||||||
Measure the non-interactive parts of the theme switcher:
|
Measure the non-interactive parts of the theme switcher:
|
||||||
- theme preview index build (omarchy-theme-switcher before UI handoff)
|
- theme preview index build (omarchy-theme-switcher before UI handoff)
|
||||||
- image selector row/thumbnail cache prep (omarchy-menu-images --cache-only)
|
- lazy selector row prep used by the interactive theme switcher
|
||||||
|
- full thumbnail cache warmup cost (omarchy-menu-images --cache-only)
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--repeat=<count> Number of warm runs to measure for each case (default: 5)
|
--repeat=<count> Number of warm runs to measure for each case (default: 5)
|
||||||
@@ -100,6 +101,7 @@ if [[ ! $REPEAT =~ ^[0-9]+$ ]] || (( REPEAT < 1 )); then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
benchmark_cache=$(mktemp -d)
|
benchmark_cache=$(mktemp -d)
|
||||||
|
thumbnail_cache=$(mktemp -d)
|
||||||
stub_bin=$(mktemp -d)
|
stub_bin=$(mktemp -d)
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
@@ -107,8 +109,9 @@ cleanup() {
|
|||||||
|
|
||||||
if [[ $KEEP_CACHE == "true" ]]; then
|
if [[ $KEEP_CACHE == "true" ]]; then
|
||||||
printf 'Benchmark cache: %s\n' "$benchmark_cache"
|
printf 'Benchmark cache: %s\n' "$benchmark_cache"
|
||||||
|
printf 'Thumbnail cache: %s\n' "$thumbnail_cache"
|
||||||
else
|
else
|
||||||
rm -rf "$benchmark_cache"
|
rm -rf "$benchmark_cache" "$thumbnail_cache"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
@@ -126,20 +129,35 @@ benchmark_env=(
|
|||||||
"PATH=$stub_bin:$OMARCHY_BIN_DIR:$PATH"
|
"PATH=$stub_bin:$OMARCHY_BIN_DIR:$PATH"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
thumbnail_env=(
|
||||||
|
env
|
||||||
|
"OMARCHY_PATH=$OMARCHY_PATH"
|
||||||
|
"XDG_CACHE_HOME=$thumbnail_cache"
|
||||||
|
"PATH=$stub_bin:$OMARCHY_BIN_DIR:$PATH"
|
||||||
|
)
|
||||||
|
|
||||||
preview_dir="$benchmark_cache/omarchy/theme-selector/previews"
|
preview_dir="$benchmark_cache/omarchy/theme-selector/previews"
|
||||||
|
thumbnail_preview_dir="$thumbnail_cache/omarchy/theme-selector/previews"
|
||||||
|
|
||||||
build_theme_index() {
|
build_theme_index() {
|
||||||
"${benchmark_env[@]}" "$OMARCHY_BIN_DIR/omarchy-theme-switcher"
|
"${benchmark_env[@]}" "$OMARCHY_BIN_DIR/omarchy-theme-switcher"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepare_selector_lazy() {
|
||||||
|
"${benchmark_env[@]}" "$OMARCHY_BIN_DIR/omarchy-menu-images" --prepare-only --lazy-thumbnails --show-labels --filterable "$preview_dir"
|
||||||
|
}
|
||||||
|
|
||||||
prepare_image_cache() {
|
prepare_image_cache() {
|
||||||
"${benchmark_env[@]}" "$OMARCHY_BIN_DIR/omarchy-menu-images" --cache-only "$preview_dir"
|
"${thumbnail_env[@]}" "$OMARCHY_BIN_DIR/omarchy-menu-images" --cache-only "$thumbnail_preview_dir"
|
||||||
}
|
}
|
||||||
|
|
||||||
printf 'Theme switcher benchmark (%d warm runs each)\n\n' "$REPEAT"
|
printf 'Theme switcher benchmark (%d warm runs each)\n\n' "$REPEAT"
|
||||||
printf '%-34s %s ms\n' "theme index cold" "$(format_ms "$(measure_once build_theme_index)")"
|
printf '%-34s %s ms\n' "theme index cold" "$(format_ms "$(measure_once build_theme_index)")"
|
||||||
run_case "theme index warm" build_theme_index
|
run_case "theme index warm" build_theme_index
|
||||||
printf '%-34s %s ms\n' "selector cache cold" "$(format_ms "$(measure_once prepare_image_cache)")"
|
printf '%-34s %s ms\n' "selector prep cold (lazy)" "$(format_ms "$(measure_once prepare_selector_lazy)")"
|
||||||
run_case "selector cache warm" prepare_image_cache
|
run_case "selector prep warm (lazy)" prepare_selector_lazy
|
||||||
|
"${thumbnail_env[@]}" "$OMARCHY_BIN_DIR/omarchy-theme-switcher" >/dev/null
|
||||||
|
printf '%-34s %s ms\n' "thumbnail cache cold" "$(format_ms "$(measure_once prepare_image_cache)")"
|
||||||
|
run_case "thumbnail cache warm" prepare_image_cache
|
||||||
|
|
||||||
printf '\nTheme previews: %d\n' "$(find -L "$preview_dir" -maxdepth 1 -type f 2>/dev/null | wc -l)"
|
printf '\nTheme previews: %d\n' "$(find -L "$preview_dir" -maxdepth 1 -type f 2>/dev/null | wc -l)"
|
||||||
|
|||||||
+60
-8
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# omarchy:summary=Open a generic image selector menu
|
# omarchy:summary=Open a generic image selector menu
|
||||||
# omarchy:args=[--selected <image>] [--colors-file <path>] [--print-name] [--show-labels] [--filterable] [--cache-only] <image-dir>...
|
# omarchy:args=[--selected <image>] [--colors-file <path>] [--print-name] [--show-labels] [--filterable] [--lazy-thumbnails] [--cache-only] <image-dir>...
|
||||||
|
|
||||||
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
|
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
|
||||||
|
|
||||||
@@ -10,11 +10,13 @@ colors_file=""
|
|||||||
print_name=false
|
print_name=false
|
||||||
show_labels=false
|
show_labels=false
|
||||||
filterable=false
|
filterable=false
|
||||||
|
lazy_thumbnails=false
|
||||||
|
prepare_only=false
|
||||||
cache_only=false
|
cache_only=false
|
||||||
image_dirs=()
|
image_dirs=()
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo "Usage: omarchy-menu-images [--selected <image>] [--colors-file <path>] [--print-name] [--show-labels] [--filterable] [--cache-only] <image-dir>..."
|
echo "Usage: omarchy-menu-images [--selected <image>] [--colors-file <path>] [--print-name] [--show-labels] [--filterable] [--lazy-thumbnails] [--cache-only] <image-dir>..."
|
||||||
}
|
}
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
@@ -49,6 +51,14 @@ while [[ $# -gt 0 ]]; do
|
|||||||
filterable=true
|
filterable=true
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--lazy-thumbnails)
|
||||||
|
lazy_thumbnails=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--prepare-only)
|
||||||
|
prepare_only=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--cache-only)
|
--cache-only)
|
||||||
cache_only=true
|
cache_only=true
|
||||||
shift
|
shift
|
||||||
@@ -108,7 +118,8 @@ mkdir -p "$cache_dir"
|
|||||||
cache_key=$(printf '%s' "$image_dirs_env" | md5sum | cut -d ' ' -f 1)
|
cache_key=$(printf '%s' "$image_dirs_env" | md5sum | cut -d ' ' -f 1)
|
||||||
rows_cache_file="$cache_dir/$cache_key.rows"
|
rows_cache_file="$cache_dir/$cache_key.rows"
|
||||||
rows_signature_file="$cache_dir/$cache_key.signature"
|
rows_signature_file="$cache_dir/$cache_key.signature"
|
||||||
rows_signature=""
|
rows_signature="v2"$'\n'
|
||||||
|
rows_cacheable=true
|
||||||
image_files=()
|
image_files=()
|
||||||
|
|
||||||
for dir in "${image_dirs[@]}"; do
|
for dir in "${image_dirs[@]}"; do
|
||||||
@@ -123,6 +134,29 @@ for dir in "${image_dirs[@]}"; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
generate_thumbnail() {
|
||||||
|
local image="$1"
|
||||||
|
local thumbnail="$2"
|
||||||
|
local lock="$thumbnail.lock"
|
||||||
|
local tmp="$thumbnail.$$.jpg"
|
||||||
|
|
||||||
|
if mkdir "$lock" 2>/dev/null; then
|
||||||
|
if magick "${image}[0]" -auto-orient -resize '1536x864^' -gravity center -extent '1536x864' -strip -quality 82 "$tmp"; then
|
||||||
|
mv -f "$tmp" "$thumbnail"
|
||||||
|
else
|
||||||
|
rm -f "$tmp" "$thumbnail"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rmdir "$lock" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
for ((i = 0; i < 3000; i++)); do
|
||||||
|
[[ -f $thumbnail ]] && return
|
||||||
|
[[ -d $lock ]] || break
|
||||||
|
sleep 0.01
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
thumbnail_for() {
|
thumbnail_for() {
|
||||||
local image="$1"
|
local image="$1"
|
||||||
local signature hash thumbnail
|
local signature hash thumbnail
|
||||||
@@ -131,14 +165,25 @@ thumbnail_for() {
|
|||||||
hash=$(awk -F '\t' -v path="$image" -v sig="$signature" '$1 == path && $2 == sig { print $3; exit }' "$index_file" 2>/dev/null)
|
hash=$(awk -F '\t' -v path="$image" -v sig="$signature" '$1 == path && $2 == sig { print $3; exit }' "$index_file" 2>/dev/null)
|
||||||
|
|
||||||
if [[ -z $hash ]]; then
|
if [[ -z $hash ]]; then
|
||||||
hash=$(md5sum "$image" | cut -d ' ' -f 1)
|
hash=$(printf '%s\t%s' "$image" "$signature" | md5sum | cut -d ' ' -f 1)
|
||||||
printf '%s\t%s\t%s\n' "$image" "$signature" "$hash" >>"$index_file"
|
printf '%s\t%s\t%s\n' "$image" "$signature" "$hash" >>"$index_file"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
thumbnail="$cache_dir/$hash.jpg"
|
thumbnail="$cache_dir/$hash.jpg"
|
||||||
|
|
||||||
if [[ ! -f $thumbnail ]]; then
|
if [[ ! -f $thumbnail ]]; then
|
||||||
magick "${image}[0]" -auto-orient -resize '1536x864^' -gravity center -extent '1536x864' -strip -quality 82 "$thumbnail"
|
if [[ $lazy_thumbnails == true && $cache_only != true ]]; then
|
||||||
|
rows_cacheable=false
|
||||||
|
|
||||||
|
if [[ $prepare_only != true ]]; then
|
||||||
|
generate_thumbnail "$image" "$thumbnail" >/dev/null 2>&1 &
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s' "$image"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
generate_thumbnail "$image" "$thumbnail"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ -f $thumbnail ]] && printf '%s' "$thumbnail"
|
[[ -f $thumbnail ]] && printf '%s' "$thumbnail"
|
||||||
@@ -150,6 +195,9 @@ else
|
|||||||
for image in "${image_files[@]}"; do
|
for image in "${image_files[@]}"; do
|
||||||
thumbnail=$(thumbnail_for "$image")
|
thumbnail=$(thumbnail_for "$image")
|
||||||
[[ -n $thumbnail ]] || continue
|
[[ -n $thumbnail ]] || continue
|
||||||
|
if [[ $lazy_thumbnails == true && $cache_only != true && $thumbnail == "$image" ]]; then
|
||||||
|
rows_cacheable=false
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -z $rows ]]; then
|
if [[ -z $rows ]]; then
|
||||||
rows="$image"$'\t'"$thumbnail"
|
rows="$image"$'\t'"$thumbnail"
|
||||||
@@ -158,8 +206,12 @@ else
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
printf '%s' "$rows" >"$rows_cache_file"
|
if [[ $rows_cacheable == true ]]; then
|
||||||
printf '%s' "$rows_signature" >"$rows_signature_file"
|
printf '%s' "$rows" >"$rows_cache_file"
|
||||||
|
printf '%s' "$rows_signature" >"$rows_signature_file"
|
||||||
|
else
|
||||||
|
rm -f "$rows_cache_file" "$rows_signature_file"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rows_payload=${rows//$'\t'/$'\f'}
|
rows_payload=${rows//$'\t'/$'\f'}
|
||||||
@@ -173,7 +225,7 @@ if [[ -f $colors_file ]]; then
|
|||||||
colors_payload=${colors_payload//$'\n'/$'\v'}
|
colors_payload=${colors_payload//$'\n'/$'\v'}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $cache_only == true ]]; then
|
if [[ $cache_only == true || $prepare_only == true ]]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -93,5 +93,6 @@ exec omarchy-menu-images \
|
|||||||
--print-name \
|
--print-name \
|
||||||
--show-labels \
|
--show-labels \
|
||||||
--filterable \
|
--filterable \
|
||||||
|
--lazy-thumbnails \
|
||||||
--selected "$selected_preview" \
|
--selected "$selected_preview" \
|
||||||
"$preview_dir"
|
"$preview_dir"
|
||||||
|
|||||||
Reference in New Issue
Block a user