"""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"
", unsafe_allow_html=True, ) st.image(img["bytes"], width=THUMB_HEIGHT) st.markdown("
", unsafe_allow_html=True) # Label + filename short_name = img["filename"] if len(short_name) > 18: short_name = short_name[:15] + "…" if st.button( f"{badge} {short_name}", key=f"thumb_{img_id}", use_container_width=True, ): sm.set_current_image(img_id) clicked = True # ── Gallery pagination ─────────────────────────────────────────────── if total_pages > 1: gc1, gc2, gc3 = st.columns([1, 3, 1]) with gc1: if page > 0: if st.button(t("gallery_prev"), key="gal_prev"): st.session_state.gallery_page -= 1 clicked = True with gc2: st.markdown( f"
" f"{t('page')} {page + 1} / {total_pages}
", unsafe_allow_html=True, ) with gc3: if page < total_pages - 1: if st.button(t("gallery_next"), key="gal_next"): st.session_state.gallery_page += 1 clicked = True return clicked