yusenthebot
commited on
Commit
·
81fd60c
1
Parent(s):
aa3fdef
Fix Flashcards tab: replace deprecated st.experimental_rerun with st.rerun, fix dataframe display
Browse files
requirements.txt
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
########################################
|
| 2 |
# Streamlit Core
|
| 3 |
########################################
|
| 4 |
-
streamlit
|
| 5 |
-
tornado
|
| 6 |
|
| 7 |
########################################
|
| 8 |
# Audio Input / Output
|
|
|
|
| 1 |
########################################
|
| 2 |
# Streamlit Core
|
| 3 |
########################################
|
| 4 |
+
streamlit>=1.28.0
|
| 5 |
+
tornado>=6.3.3
|
| 6 |
|
| 7 |
########################################
|
| 8 |
# Audio Input / Output
|
src/app/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (467 Bytes). View file
|
|
|
src/app/__pycache__/main_app.cpython-311.pyc
ADDED
|
Binary file (59.9 kB). View file
|
|
|
src/app/main_app.py
CHANGED
|
@@ -257,7 +257,7 @@ def login_view():
|
|
| 257 |
if authenticate_user(u, p):
|
| 258 |
st.session_state["user"] = u
|
| 259 |
st.session_state["prefs"] = get_user_prefs(u)
|
| 260 |
-
st.
|
| 261 |
else:
|
| 262 |
st.error("Invalid login.")
|
| 263 |
|
|
@@ -527,7 +527,7 @@ def conversation_tab(username: str):
|
|
| 527 |
st.session_state["pending_transcript"] = ""
|
| 528 |
st.session_state["speech_state"] = "idle"
|
| 529 |
st.session_state["recorder_key"] += 1
|
| 530 |
-
st.
|
| 531 |
|
| 532 |
# ------------------------------------------
|
| 533 |
# FIRST MESSAGE GREETING
|
|
@@ -637,7 +637,7 @@ def conversation_tab(username: str):
|
|
| 637 |
st.session_state["pending_transcript"] = txt.strip()
|
| 638 |
st.session_state["speech_state"] = "pending_speech"
|
| 639 |
st.session_state["recorder_key"] += 1
|
| 640 |
-
st.
|
| 641 |
except Exception as e:
|
| 642 |
st.error(f"Audio decode/transcription error: {e}")
|
| 643 |
|
|
@@ -661,14 +661,14 @@ def conversation_tab(username: str):
|
|
| 661 |
st.session_state["speech_state"] = "idle"
|
| 662 |
st.session_state["pending_transcript"] = ""
|
| 663 |
st.session_state["recorder_key"] += 1
|
| 664 |
-
st.
|
| 665 |
|
| 666 |
with c2:
|
| 667 |
if st.button("Discard", key="discard_pending"):
|
| 668 |
st.session_state["speech_state"] = "idle"
|
| 669 |
st.session_state["pending_transcript"] = ""
|
| 670 |
st.session_state["recorder_key"] += 1
|
| 671 |
-
st.
|
| 672 |
|
| 673 |
# -------------------------------
|
| 674 |
# TYPED TEXT INPUT
|
|
@@ -677,7 +677,7 @@ def conversation_tab(username: str):
|
|
| 677 |
if typed.strip() and st.button("Send typed message"):
|
| 678 |
handle_user_message(username, typed.strip())
|
| 679 |
st.session_state["typed_input"] = ""
|
| 680 |
-
st.
|
| 681 |
|
| 682 |
st.markdown("</div>", unsafe_allow_html=True)
|
| 683 |
|
|
@@ -728,7 +728,7 @@ def conversation_tab(username: str):
|
|
| 728 |
|
| 729 |
if st.button(f"Delete {f.stem}", key=f"delete_{f.stem}"):
|
| 730 |
f.unlink()
|
| 731 |
-
st.
|
| 732 |
|
| 733 |
|
| 734 |
###############################################################
|
|
@@ -855,7 +855,7 @@ def flashcards_tab(username: str):
|
|
| 855 |
# Delete deck button
|
| 856 |
if st.button("Delete deck"):
|
| 857 |
deck_path.unlink()
|
| 858 |
-
st.
|
| 859 |
|
| 860 |
# ---------------------------------------------------------
|
| 861 |
# Session state setup
|
|
@@ -919,7 +919,7 @@ def flashcards_tab(username: str):
|
|
| 919 |
with c1:
|
| 920 |
if st.button("Flip", key=key + "flip"):
|
| 921 |
ss[key + "show_back"] = not show_back
|
| 922 |
-
st.
|
| 923 |
with c2:
|
| 924 |
if st.button("Shuffle deck", key=key + "shuf"):
|
| 925 |
random.shuffle(cards)
|
|
@@ -927,12 +927,12 @@ def flashcards_tab(username: str):
|
|
| 927 |
save_deck(deck_path, deck)
|
| 928 |
ss[key + "idx"] = 0
|
| 929 |
ss[key + "show_back"] = False
|
| 930 |
-
st.
|
| 931 |
with c3:
|
| 932 |
if st.button("Next →", key=key + "next"):
|
| 933 |
ss[key + "idx"] = (idx + 1) % len(cards)
|
| 934 |
ss[key + "show_back"] = False
|
| 935 |
-
st.
|
| 936 |
|
| 937 |
# DIFFICULTY GRADING (centered)
|
| 938 |
st.markdown("### Rate this card")
|
|
@@ -955,7 +955,7 @@ def flashcards_tab(username: str):
|
|
| 955 |
save_deck(deck_path, deck)
|
| 956 |
ss[key + "idx"] = _choose_next_card_index(cards)
|
| 957 |
ss[key + "show_back"] = False
|
| 958 |
-
st.
|
| 959 |
|
| 960 |
with cA:
|
| 961 |
if st.button("🔥 Very Difficult", key=key+"g_vd"):
|
|
@@ -991,7 +991,7 @@ def flashcards_tab(username: str):
|
|
| 991 |
ss[key + "test_order"] = order
|
| 992 |
ss[key + "test_pos"] = 0
|
| 993 |
ss[key + "test_results"] = []
|
| 994 |
-
st.
|
| 995 |
|
| 996 |
else:
|
| 997 |
order = ss[key + "test_order"]
|
|
@@ -1013,7 +1013,7 @@ def flashcards_tab(username: str):
|
|
| 1013 |
ss[key + "test_pos"] = 0
|
| 1014 |
ss[key + "test_results"] = []
|
| 1015 |
ss[key + "test_order"] = []
|
| 1016 |
-
st.
|
| 1017 |
return
|
| 1018 |
|
| 1019 |
# Current question
|
|
@@ -1051,7 +1051,7 @@ def flashcards_tab(username: str):
|
|
| 1051 |
})
|
| 1052 |
ss[key + "test_results"] = results
|
| 1053 |
ss[key + "test_pos"] = pos + 1
|
| 1054 |
-
st.
|
| 1055 |
|
| 1056 |
# =======================================================
|
| 1057 |
# DECK AT A GLANCE (FULL WIDTH)
|
|
@@ -1059,17 +1059,21 @@ def flashcards_tab(username: str):
|
|
| 1059 |
st.markdown("---")
|
| 1060 |
st.subheader("Deck at a glance")
|
| 1061 |
|
| 1062 |
-
|
| 1063 |
-
|
| 1064 |
-
|
| 1065 |
-
|
| 1066 |
-
|
| 1067 |
-
|
| 1068 |
-
|
| 1069 |
-
|
| 1070 |
-
|
| 1071 |
-
|
| 1072 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1073 |
|
| 1074 |
|
| 1075 |
###############################################################
|
|
@@ -1153,7 +1157,7 @@ def quiz_tab(username: str):
|
|
| 1153 |
"correct": choice == q["answer"],
|
| 1154 |
}
|
| 1155 |
st.session_state["quiz_idx"] += 1
|
| 1156 |
-
st.
|
| 1157 |
else:
|
| 1158 |
ans = st.text_input("Your answer", key=f"fill_{idx}")
|
| 1159 |
if st.button("Submit", key=f"sub_{idx}"):
|
|
@@ -1162,7 +1166,7 @@ def quiz_tab(username: str):
|
|
| 1162 |
"correct": ans.strip().lower() == q["answer"].lower(),
|
| 1163 |
}
|
| 1164 |
st.session_state["quiz_idx"] += 1
|
| 1165 |
-
st.
|
| 1166 |
|
| 1167 |
|
| 1168 |
###############################################################
|
|
@@ -1180,47 +1184,35 @@ def main():
|
|
| 1180 |
|
| 1181 |
if st.sidebar.button("Log out"):
|
| 1182 |
st.session_state.clear()
|
| 1183 |
-
st.
|
| 1184 |
|
| 1185 |
# ---------- LOAD MODELS + PREFS ----------
|
| 1186 |
preload_models()
|
| 1187 |
sidebar_settings(username)
|
| 1188 |
ensure_default_decks(username)
|
| 1189 |
|
| 1190 |
-
# ----------
|
| 1191 |
-
if "active_tab" not in st.session_state:
|
| 1192 |
-
st.session_state["active_tab"] = 0
|
| 1193 |
-
|
| 1194 |
tab_labels = ["Dashboard", "Conversation", "OCR", "Flashcards", "Quiz", "Settings"]
|
| 1195 |
tabs = st.tabs(tab_labels)
|
| 1196 |
|
| 1197 |
tab_dash, tab_conv, tab_ocr, tab_flash, tab_quiz, tab_settings = tabs
|
| 1198 |
|
| 1199 |
-
# restore active tab (required so Streamlit shows correct tab on rerun)
|
| 1200 |
-
_ = tabs[st.session_state["active_tab"]]
|
| 1201 |
-
|
| 1202 |
with tab_dash:
|
| 1203 |
-
st.session_state["active_tab"] = 0
|
| 1204 |
dashboard_tab(username)
|
| 1205 |
|
| 1206 |
with tab_conv:
|
| 1207 |
-
st.session_state["active_tab"] = 1
|
| 1208 |
conversation_tab(username)
|
| 1209 |
|
| 1210 |
with tab_ocr:
|
| 1211 |
-
st.session_state["active_tab"] = 2
|
| 1212 |
ocr_tab(username)
|
| 1213 |
|
| 1214 |
with tab_flash:
|
| 1215 |
-
st.session_state["active_tab"] = 3
|
| 1216 |
flashcards_tab(username)
|
| 1217 |
|
| 1218 |
with tab_quiz:
|
| 1219 |
-
st.session_state["active_tab"] = 4
|
| 1220 |
quiz_tab(username)
|
| 1221 |
|
| 1222 |
with tab_settings:
|
| 1223 |
-
st.session_state["active_tab"] = 5
|
| 1224 |
settings_tab(username)
|
| 1225 |
|
| 1226 |
|
|
|
|
| 257 |
if authenticate_user(u, p):
|
| 258 |
st.session_state["user"] = u
|
| 259 |
st.session_state["prefs"] = get_user_prefs(u)
|
| 260 |
+
st.rerun()
|
| 261 |
else:
|
| 262 |
st.error("Invalid login.")
|
| 263 |
|
|
|
|
| 527 |
st.session_state["pending_transcript"] = ""
|
| 528 |
st.session_state["speech_state"] = "idle"
|
| 529 |
st.session_state["recorder_key"] += 1
|
| 530 |
+
st.rerun()
|
| 531 |
|
| 532 |
# ------------------------------------------
|
| 533 |
# FIRST MESSAGE GREETING
|
|
|
|
| 637 |
st.session_state["pending_transcript"] = txt.strip()
|
| 638 |
st.session_state["speech_state"] = "pending_speech"
|
| 639 |
st.session_state["recorder_key"] += 1
|
| 640 |
+
st.rerun()
|
| 641 |
except Exception as e:
|
| 642 |
st.error(f"Audio decode/transcription error: {e}")
|
| 643 |
|
|
|
|
| 661 |
st.session_state["speech_state"] = "idle"
|
| 662 |
st.session_state["pending_transcript"] = ""
|
| 663 |
st.session_state["recorder_key"] += 1
|
| 664 |
+
st.rerun()
|
| 665 |
|
| 666 |
with c2:
|
| 667 |
if st.button("Discard", key="discard_pending"):
|
| 668 |
st.session_state["speech_state"] = "idle"
|
| 669 |
st.session_state["pending_transcript"] = ""
|
| 670 |
st.session_state["recorder_key"] += 1
|
| 671 |
+
st.rerun()
|
| 672 |
|
| 673 |
# -------------------------------
|
| 674 |
# TYPED TEXT INPUT
|
|
|
|
| 677 |
if typed.strip() and st.button("Send typed message"):
|
| 678 |
handle_user_message(username, typed.strip())
|
| 679 |
st.session_state["typed_input"] = ""
|
| 680 |
+
st.rerun()
|
| 681 |
|
| 682 |
st.markdown("</div>", unsafe_allow_html=True)
|
| 683 |
|
|
|
|
| 728 |
|
| 729 |
if st.button(f"Delete {f.stem}", key=f"delete_{f.stem}"):
|
| 730 |
f.unlink()
|
| 731 |
+
st.rerun()
|
| 732 |
|
| 733 |
|
| 734 |
###############################################################
|
|
|
|
| 855 |
# Delete deck button
|
| 856 |
if st.button("Delete deck"):
|
| 857 |
deck_path.unlink()
|
| 858 |
+
st.rerun()
|
| 859 |
|
| 860 |
# ---------------------------------------------------------
|
| 861 |
# Session state setup
|
|
|
|
| 919 |
with c1:
|
| 920 |
if st.button("Flip", key=key + "flip"):
|
| 921 |
ss[key + "show_back"] = not show_back
|
| 922 |
+
st.rerun()
|
| 923 |
with c2:
|
| 924 |
if st.button("Shuffle deck", key=key + "shuf"):
|
| 925 |
random.shuffle(cards)
|
|
|
|
| 927 |
save_deck(deck_path, deck)
|
| 928 |
ss[key + "idx"] = 0
|
| 929 |
ss[key + "show_back"] = False
|
| 930 |
+
st.rerun()
|
| 931 |
with c3:
|
| 932 |
if st.button("Next →", key=key + "next"):
|
| 933 |
ss[key + "idx"] = (idx + 1) % len(cards)
|
| 934 |
ss[key + "show_back"] = False
|
| 935 |
+
st.rerun()
|
| 936 |
|
| 937 |
# DIFFICULTY GRADING (centered)
|
| 938 |
st.markdown("### Rate this card")
|
|
|
|
| 955 |
save_deck(deck_path, deck)
|
| 956 |
ss[key + "idx"] = _choose_next_card_index(cards)
|
| 957 |
ss[key + "show_back"] = False
|
| 958 |
+
st.rerun()
|
| 959 |
|
| 960 |
with cA:
|
| 961 |
if st.button("🔥 Very Difficult", key=key+"g_vd"):
|
|
|
|
| 991 |
ss[key + "test_order"] = order
|
| 992 |
ss[key + "test_pos"] = 0
|
| 993 |
ss[key + "test_results"] = []
|
| 994 |
+
st.rerun()
|
| 995 |
|
| 996 |
else:
|
| 997 |
order = ss[key + "test_order"]
|
|
|
|
| 1013 |
ss[key + "test_pos"] = 0
|
| 1014 |
ss[key + "test_results"] = []
|
| 1015 |
ss[key + "test_order"] = []
|
| 1016 |
+
st.rerun()
|
| 1017 |
return
|
| 1018 |
|
| 1019 |
# Current question
|
|
|
|
| 1051 |
})
|
| 1052 |
ss[key + "test_results"] = results
|
| 1053 |
ss[key + "test_pos"] = pos + 1
|
| 1054 |
+
st.rerun()
|
| 1055 |
|
| 1056 |
# =======================================================
|
| 1057 |
# DECK AT A GLANCE (FULL WIDTH)
|
|
|
|
| 1059 |
st.markdown("---")
|
| 1060 |
st.subheader("Deck at a glance")
|
| 1061 |
|
| 1062 |
+
if cards:
|
| 1063 |
+
df_rows = []
|
| 1064 |
+
for i, c in enumerate(cards, start=1):
|
| 1065 |
+
df_rows.append({
|
| 1066 |
+
"#": i,
|
| 1067 |
+
"Front": c.get("front", ""),
|
| 1068 |
+
"Back": c.get("back", ""),
|
| 1069 |
+
"Score": c.get("score", 0),
|
| 1070 |
+
"Reviews": c.get("reviews", 0),
|
| 1071 |
+
})
|
| 1072 |
+
|
| 1073 |
+
df = pd.DataFrame(df_rows)
|
| 1074 |
+
st.dataframe(df, height=min(500, len(cards) * 40 + 50), use_container_width=True, hide_index=True)
|
| 1075 |
+
else:
|
| 1076 |
+
st.info("No cards in this deck.")
|
| 1077 |
|
| 1078 |
|
| 1079 |
###############################################################
|
|
|
|
| 1157 |
"correct": choice == q["answer"],
|
| 1158 |
}
|
| 1159 |
st.session_state["quiz_idx"] += 1
|
| 1160 |
+
st.rerun()
|
| 1161 |
else:
|
| 1162 |
ans = st.text_input("Your answer", key=f"fill_{idx}")
|
| 1163 |
if st.button("Submit", key=f"sub_{idx}"):
|
|
|
|
| 1166 |
"correct": ans.strip().lower() == q["answer"].lower(),
|
| 1167 |
}
|
| 1168 |
st.session_state["quiz_idx"] += 1
|
| 1169 |
+
st.rerun()
|
| 1170 |
|
| 1171 |
|
| 1172 |
###############################################################
|
|
|
|
| 1184 |
|
| 1185 |
if st.sidebar.button("Log out"):
|
| 1186 |
st.session_state.clear()
|
| 1187 |
+
st.rerun()
|
| 1188 |
|
| 1189 |
# ---------- LOAD MODELS + PREFS ----------
|
| 1190 |
preload_models()
|
| 1191 |
sidebar_settings(username)
|
| 1192 |
ensure_default_decks(username)
|
| 1193 |
|
| 1194 |
+
# ---------- TABS ----------
|
|
|
|
|
|
|
|
|
|
| 1195 |
tab_labels = ["Dashboard", "Conversation", "OCR", "Flashcards", "Quiz", "Settings"]
|
| 1196 |
tabs = st.tabs(tab_labels)
|
| 1197 |
|
| 1198 |
tab_dash, tab_conv, tab_ocr, tab_flash, tab_quiz, tab_settings = tabs
|
| 1199 |
|
|
|
|
|
|
|
|
|
|
| 1200 |
with tab_dash:
|
|
|
|
| 1201 |
dashboard_tab(username)
|
| 1202 |
|
| 1203 |
with tab_conv:
|
|
|
|
| 1204 |
conversation_tab(username)
|
| 1205 |
|
| 1206 |
with tab_ocr:
|
|
|
|
| 1207 |
ocr_tab(username)
|
| 1208 |
|
| 1209 |
with tab_flash:
|
|
|
|
| 1210 |
flashcards_tab(username)
|
| 1211 |
|
| 1212 |
with tab_quiz:
|
|
|
|
| 1213 |
quiz_tab(username)
|
| 1214 |
|
| 1215 |
with tab_settings:
|
|
|
|
| 1216 |
settings_tab(username)
|
| 1217 |
|
| 1218 |
|