"""OphthalmoCapture — Image Gallery Component Renders a thumbnail strip of all uploaded images with labeling-status badges and click-to-select behaviour. """ import streamlit as st from i18n import t from services import session_manager as sm def _label_badge(label): """Return a coloured status indicator for the label value.""" if label is None: return "🔴" # unlabeled return "🟢" # labeled (any value) def render_gallery(): """Draw the horizontal thumbnail gallery with status badges. Returns True if the user clicked on a thumbnail (triggers rerun). """ images = st.session_state.images order = st.session_state.image_order current_id = st.session_state.current_image_id if not order: return False # ── Progress bar ───────────────────────────────────────────────────── labeled, total = sm.get_labeling_progress() progress_text = f"{t('progress')}: **{labeled}** / **{total}** {t('labeled_suffix')}" st.markdown(progress_text) st.progress(labeled / total if total > 0 else 0) # ── Thumbnail strip ────────────────────────────────────────────────── # Show up to 8 thumbnails per row; wrap if there are more. COLS_PER_ROW = 6 THUMB_HEIGHT = 120 # fixed thumbnail height in pixels num_images = len(order) # Paginate the gallery if many images if "gallery_page" not in st.session_state: st.session_state.gallery_page = 0 total_pages = max(1, -(-num_images // COLS_PER_ROW)) # ceil division page = st.session_state.gallery_page start = page * COLS_PER_ROW end = min(start + COLS_PER_ROW, num_images) visible_ids = order[start:end] # Always use fixed number of columns so thumbnails keep consistent size cols = st.columns(COLS_PER_ROW) clicked = False for i, img_id in enumerate(visible_ids): img = images[img_id] badge = _label_badge(img["label"]) is_selected = (img_id == current_id) with cols[i]: # Visual border to highlight the selected thumbnail border_color = "#4CAF50" if is_selected else "transparent" st.markdown( f"