# streamlit_app.py import streamlit as st import pandas as pd import numpy as np from pathlib import Path import uuid from cards import ( chat_card, inplace_chat_card ) # ---------- Global state init ---------- if "init" not in st.session_state: st.session_state.init = True st.session_state.conversations = {} # {chat_id: {"title": str, "messages": [...]}} st.session_state.current_chat_id = None # which conversation is open def create_new_conversation(): chat_id = str(uuid.uuid4()) st.session_state.conversations[chat_id] = { "title": "New chat", "messages": [], "editable": False, "prev_text": "", "edited_text": "", "original_user_prompt": "", "edit_history": [] } st.session_state.current_chat_id = chat_id # ensure at least one conversation exists if not st.session_state.conversations: create_new_conversation() # Fix code block font rendering - force monospace st.markdown(""" """, unsafe_allow_html=True) pages = [ st.Page( "inplace_chat.py", title="In-place Feedback Chat", icon=":material/edit_document:" ), st.Page( "chat.py", title="Chat", icon=":material/chat:" ) ] page = st.navigation(pages) # ---------- Sidebar: ChatGPT-style history ---------- with st.sidebar: # new chat button st.write("This is a simple demo for CSED499 Inplace feedback.") st.button( "+ New chat", use_container_width=True, on_click=create_new_conversation, ) st.markdown("---") st.markdown("### Chat History") # Add custom CSS for hover effect on chat history items st.markdown(""" """, unsafe_allow_html=True) # list existing conversations as clickable text for chat_id, conv in st.session_state.conversations.items(): # truncate title like ChatGPT label = conv["title"] if len(label) > 35: label = label[:35] + "…" # Create columns for chat item and delete button col_chat, col_delete = st.columns([0.85, 0.15]) with col_chat: # highlight current chat with a marker if chat_id == st.session_state.current_chat_id: st.markdown(f"**▶ {label}**") else: # Make entire text clickable with hover effect if st.button(label, key=f"chat-{chat_id}", type="secondary", use_container_width=True): st.session_state.current_chat_id = chat_id st.rerun() with col_delete: # Delete button - only show for non-active chats or show for all if st.button("✕", key=f"delete-{chat_id}", type="secondary", help="Delete chat"): # If deleting current chat, switch to another one first if chat_id == st.session_state.current_chat_id: remaining = [cid for cid in st.session_state.conversations.keys() if cid != chat_id] if remaining: st.session_state.current_chat_id = remaining[0] else: st.session_state.current_chat_id = None # Delete the conversation del st.session_state.conversations[chat_id] st.rerun() # run selected page (after sidebar is defined) page.run() # === Edit History Panel === st.sidebar.markdown("### Edit History") if st.session_state.current_chat_id: current_conv = st.session_state.conversations.get(st.session_state.current_chat_id, {}) edit_history = current_conv.get("edit_history", []) if edit_history: st.sidebar.markdown(""" """, unsafe_allow_html=True) for idx, edit in enumerate(reversed(edit_history)): edit_num = len(edit_history) - idx # Each edit as a collapsible expander with st.sidebar.expander(f"Edit #{edit_num} at {edit['timestamp']}", expanded=False): # Build the diff HTML diff_html = "