local cache
This commit is contained in:
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user