3232 "generate" : PROJECT_DIR / "note_generation.py" ,
3333}
3434
35+ # User data directory: persistent across app restarts.
36+ # When running as a PyInstaller bundle (AppImage / .exe), __file__ resolves to
37+ # a temporary extraction folder that is deleted on exit — any files written
38+ # there are lost. Use ~/.auto_note/ instead so credentials and config survive.
39+ if getattr (sys , "frozen" , False ):
40+ DATA_DIR = Path .home () / ".auto_note"
41+ else :
42+ DATA_DIR = PROJECT_DIR
43+ DATA_DIR .mkdir (parents = True , exist_ok = True )
44+
3545COURSES : dict [int , str ] = {} # populated from Canvas API after token is entered
3646
3747_SKIP_KEYWORDS = [
@@ -44,8 +54,8 @@ def _load_courses_from_canvas() -> str:
4454 """Fetch active courses from Canvas and update the global COURSES dict.
4555 Returns "" on success, or a human-readable error string on failure."""
4656 COURSES .clear ()
47- token_file = PROJECT_DIR / "canvas_token.txt"
48- config_file = PROJECT_DIR / "config.json"
57+ token_file = DATA_DIR / "canvas_token.txt"
58+ config_file = DATA_DIR / "config.json"
4959 token = token_file .read_text ().strip () if token_file .exists () else ""
5060 if not token :
5161 return "Canvas token not saved — enter it in Settings → API Keys."
@@ -91,7 +101,7 @@ def _load_courses_from_canvas() -> str:
91101# ── Pipeline state helpers ────────────────────────────────────────────────────
92102
93103def _manifest () -> dict :
94- p = PROJECT_DIR / "manifest.json"
104+ p = DATA_DIR / "manifest.json"
95105 return json .loads (p .read_text ()) if p .exists () else {}
96106
97107def _video_status (course_id : int ) -> tuple [int , int ]:
@@ -101,16 +111,16 @@ def _video_status(course_id: int) -> tuple[int, int]:
101111 return done , len (items )
102112
103113def _caption_count (course_id : int ) -> int :
104- d = PROJECT_DIR / str (course_id ) / "captions"
114+ d = DATA_DIR / str (course_id ) / "captions"
105115 return len (list (d .glob ("*.json" ))) if d .exists () else 0
106116
107117def _alignment_count (course_id : int ) -> int :
108- d = PROJECT_DIR / str (course_id ) / "alignment"
118+ d = DATA_DIR / str (course_id ) / "alignment"
109119 return len ([f for f in d .glob ("*.json" )
110120 if "compact" not in f .name ]) if d .exists () else 0
111121
112122def _notes_path (course_id : int ) -> Path | None :
113- d = PROJECT_DIR / str (course_id ) / "notes"
123+ d = DATA_DIR / str (course_id ) / "notes"
114124 if d .exists ():
115125 mds = list (d .glob ("*.md" ))
116126 return mds [0 ] if mds else None
@@ -1059,7 +1069,7 @@ def _field_row(label: str, tf: ft.TextField) -> ft.Row:
10591069
10601070 # ── Connection settings (config.json) ────────────────────────────────────
10611071
1062- config_file = PROJECT_DIR / "config.json"
1072+ config_file = DATA_DIR / "config.json"
10631073
10641074 def _load_config () -> dict :
10651075 return json .load (open (config_file )) if config_file .exists () else {}
@@ -1073,10 +1083,10 @@ def _save_config_all(data: dict) -> None:
10731083 # _v holds the live text for every field; on_change keeps it in sync.
10741084 # Reading tf.value without on_change returns the *initial* value only.
10751085 _cfg = _load_config ()
1076- canvas_file = PROJECT_DIR / "canvas_token.txt"
1077- openai_file = PROJECT_DIR / "openai_api.txt"
1078- anthropic_file = PROJECT_DIR / "anthropic_key.txt"
1079- gemini_file = PROJECT_DIR / "gemini_api.txt"
1086+ canvas_file = DATA_DIR / "canvas_token.txt"
1087+ openai_file = DATA_DIR / "openai_api.txt"
1088+ anthropic_file = DATA_DIR / "anthropic_key.txt"
1089+ gemini_file = DATA_DIR / "gemini_api.txt"
10801090
10811091 _v = {
10821092 "canvas_url" : _cfg .get ("CANVAS_URL" , "" ),
@@ -1162,7 +1172,7 @@ def _do_refresh():
11621172 ft .Row (controls = [
11631173 ft .Text ("Project dir" , size = 11 ,
11641174 color = ft .Colors .with_opacity (0.5 , ft .Colors .WHITE )),
1165- ft .Text (str (PROJECT_DIR ), size = 11 , selectable = True ,
1175+ ft .Text (str (DATA_DIR ), size = 11 , selectable = True ,
11661176 color = ft .Colors .with_opacity (0.7 , ft .Colors .WHITE )),
11671177 ], spacing = 8 ),
11681178 ], spacing = 10 ))
0 commit comments