inplace-demo-streamlit / edit_history.py
Chae
feat: add chat history, edit panel
fec7628
# edit_history.py
import difflib
from datetime import datetime
import streamlit as st
def init_edit_history():
"""Ensure edit history list exists in session_state."""
if "edit_history" not in st.session_state:
st.session_state.edit_history = []
def add_edit(old_text: str, new_text: str, source: str | None = None):
"""
Append an edit event to history.
- old_text: text before edit
- new_text: text after edit
- source: where this edit came from (e.g., "In-place Chat", "System")
"""
init_edit_history()
st.session_state.edit_history.append(
{
"old": old_text,
"new": new_text,
"source": source,
"ts": datetime.now().strftime("%H:%M:%S"),
}
)
def _render_diff_html(old: str, new: str) -> str:
"""
Return HTML for a git-style diff:
- removed tokens: red, strikethrough
- added tokens: green
- unchanged: normal
"""
# word-level diff
diff = difflib.ndiff(old.split(), new.split())
parts: list[str] = []
for token in diff:
code = token[:2] # "+ ", "- ", or " "
word = token[2:]
if code == "+ ":
# Added text in green
parts.append(
f"<span style='color:#22c55e;'>{word}</span>"
)
elif code == "- ":
# Removed text in red with strikethrough
parts.append(
f"<span style='color:#ef4444;text-decoration:line-through;'>{word}</span>"
)
else:
parts.append(word)
return " ".join(parts)
def render_edit_history_sidebar(max_items: int = 20):
"""
Render the edit history inside the sidebar.
Call this inside a sidebar container.
"""
init_edit_history()
with st.expander("Edit history", expanded=True):
history = st.session_state.edit_history
if not history:
st.caption("No edits yet. Edits will appear here.")
return
# Show most recent first
for idx, item in enumerate(reversed(history[-max_items:]), start=1):
header_html = "<div style='margin-bottom:0.15rem;'>"
# Title + meta info
meta_bits = []
if "ts" in item:
meta_bits.append(item["ts"])
if item.get("source"):
meta_bits.append(item["source"])
meta_html = " · ".join(meta_bits)
header_html += f"<strong>Edit {len(history) - idx + 1}</strong>"
if meta_html:
header_html += (
f" <span style='font-size:0.75rem;color:#9ca3af;'>"
f"{meta_html}</span>"
)
header_html += "</div>"
st.markdown(header_html, unsafe_allow_html=True)
diff_html = _render_diff_html(item["old"], item["new"])
st.markdown(
f"<div style='font-size:0.85rem;'>{diff_html}</div>",
unsafe_allow_html=True,
)
st.markdown(
"<hr style='margin:0.35rem 0;border:none;border-top:1px solid #e5e7eb;'/>",
unsafe_allow_html=True,
)