local cache

This commit is contained in:
2026-02-02 07:43:17 +01:00
parent 18c47b6ff7
commit 795b9c03ef
2 changed files with 271 additions and 57 deletions
+69 -5
View File
@@ -1019,6 +1019,11 @@ data:
text: str
done: bool = False
class TodoSyncRequest(BaseModel):
"""Request body for syncing todos."""
todos: list
modified: str # Client's last modified timestamp
class MotivationItem(BaseModel):
text: str
@@ -1038,6 +1043,7 @@ data:
default = {
"notes": "",
"todos": [],
"todos_modified": None, # ISO timestamp of last todos modification
"motivation": [
"Believe in yourself!",
"Every day is a new opportunity.",
@@ -1100,18 +1106,73 @@ data:
)
# ========== TODOS ==========
def _update_todos_modified(data: dict) -> str:
"""Update the todos_modified timestamp and return it."""
ts = datetime.now(timezone.utc).isoformat()
data["todos_modified"] = ts
return ts
@APP.get("/userdata/{user}/todos")
def get_todos(user: str):
"""Get user todos."""
"""Get user todos with modification timestamp for sync."""
data = _load_userdata(user)
return Response(
content=json.dumps({
"todos": data.get("todos", []),
"count": len(data.get("todos", []))
"count": len(data.get("todos", [])),
"modified": data.get("todos_modified")
}, ensure_ascii=False),
media_type="application/json; charset=utf-8"
)
@APP.post("/userdata/{user}/todos/sync")
def sync_todos(user: str, body: TodoSyncRequest, key: str = Query(default="")):
"""
Sync todos between client and server.
- If client's modified > server's modified: update server with client data
- If server's modified > client's modified: return server data (client should update)
- Returns current server state either way
"""
_verify_key(key)
data = _load_userdata(user)
server_modified = data.get("todos_modified")
client_modified = body.modified
# Determine who has newer data
# If server has no timestamp, client data is newer
# If client timestamp > server timestamp, client is newer
client_is_newer = False
if not server_modified:
client_is_newer = True
elif client_modified and client_modified > server_modified:
client_is_newer = True
if client_is_newer:
# Update server with client data
data["todos"] = body.todos
new_ts = _update_todos_modified(data)
_save_userdata(user, data)
return Response(
content=json.dumps({
"action": "uploaded",
"todos": data["todos"],
"modified": new_ts,
"count": len(data["todos"])
}, ensure_ascii=False),
media_type="application/json; charset=utf-8"
)
else:
# Server has newer or same data, client should download
return Response(
content=json.dumps({
"action": "downloaded",
"todos": data.get("todos", []),
"modified": server_modified,
"count": len(data.get("todos", []))
}, ensure_ascii=False),
media_type="application/json; charset=utf-8"
)
@APP.post("/userdata/{user}/todos")
def add_todo(user: str, body: TodoItem, key: str = Query(default="")):
"""Add a new todo item."""
@@ -1128,10 +1189,11 @@ data:
if not data.get("todos"):
data["todos"] = []
data["todos"].append(new_todo)
new_ts = _update_todos_modified(data)
_save_userdata(user, data)
return Response(
content=json.dumps({"success": True, "todo": new_todo}, ensure_ascii=False),
content=json.dumps({"success": True, "todo": new_todo, "modified": new_ts}, ensure_ascii=False),
media_type="application/json; charset=utf-8"
)
@@ -1145,9 +1207,10 @@ data:
if todo.get("id") == todo_id:
todo["text"] = body.text.strip()
todo["done"] = body.done
new_ts = _update_todos_modified(data)
_save_userdata(user, data)
return Response(
content=json.dumps({"success": True, "todo": todo}, ensure_ascii=False),
content=json.dumps({"success": True, "todo": todo, "modified": new_ts}, ensure_ascii=False),
media_type="application/json; charset=utf-8"
)
@@ -1165,9 +1228,10 @@ data:
if len(data["todos"]) == original_count:
raise HTTPException(status_code=404, detail="Todo not found")
new_ts = _update_todos_modified(data)
_save_userdata(user, data)
return Response(
content=json.dumps({"success": True, "deleted": todo_id}, ensure_ascii=False),
content=json.dumps({"success": True, "deleted": todo_id, "modified": new_ts}, ensure_ascii=False),
media_type="application/json; charset=utf-8"
)