Add CLAUDE.md with topic-specific context docs
Split project context into .claude/context/ (architecture, server, styling, standards) instead of one large file, referenced from a minimal root CLAUDE.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# Server integration
|
||||
|
||||
## Auth: Login Flow v2
|
||||
|
||||
The app **never** collects a Nextcloud password directly. It implements
|
||||
[Login Flow v2](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#login-flow-v2)
|
||||
via [`LoginFlowService`](../../lib/services/login_flow_service.dart):
|
||||
|
||||
1. `LoginFlowService.initiate(serverUrl)` POSTs to
|
||||
`{server}/index.php/login/v2`, gets back a browser login URL + a poll
|
||||
endpoint/token.
|
||||
2. The app opens the login URL in the system browser (`url_launcher`); the
|
||||
user authenticates and authorizes there.
|
||||
3. `ServerProvider` polls `LoginFlowService.poll(pollEndpoint, token)` every
|
||||
2 seconds (`Timer.periodic`, see `_pollTimer`/`_pollTimeoutTimer` in
|
||||
`server_provider.dart`) until it gets a 200 with `server`/`loginName`/
|
||||
`appPassword`, a non-404 error, or a 10-minute timeout.
|
||||
4. The returned **app password** (scoped, revocable) is what gets stored and
|
||||
used for every subsequent request — real user passwords are never in
|
||||
memory or on disk.
|
||||
|
||||
`LoginFlowStatus` (`idle` → `initiating` → `awaitingBrowser` → `error`)
|
||||
drives `LoginView`'s UI; see `LoginFlowService`'s doc comment for the full
|
||||
flow rationale before changing it.
|
||||
|
||||
## Talking to the server
|
||||
|
||||
[`NextcloudService`](../../lib/services/nextcloud_service.dart) is the
|
||||
client for an authenticated session — constructed with `serverUrl` +
|
||||
`username` + the app password, one instance per login (held as
|
||||
`ServerProvider.service`, recreated on login/logout).
|
||||
|
||||
- **Files**: WebDAV (`PROPFIND`/`MKCOL`/`DELETE`/`MOVE` etc. against
|
||||
`/remote.php/dav/files/{username}/...`) via raw `http`/`dio` calls with a
|
||||
hand-rolled XML request body and `package:xml` for parsing responses —
|
||||
there is no WebDAV client dependency. `_parseDavDate`/`_davPath` in this
|
||||
file exist because WebDAV responses use RFC 1123 dates and either bare
|
||||
paths or full URLs for `href`; reuse them rather than re-deriving.
|
||||
- **Everything else** (shares, activity, trash, favorites, quota, user info)
|
||||
goes through Nextcloud's OCS APIs (`/ocs/v2.php/...`), JSON in, with the
|
||||
`OCS-APIRequest: true` header required on every OCS call.
|
||||
- Auth header is HTTP Basic (`username:appPassword`, base64), built in
|
||||
`_headers`/exposed as `authHeaders` for widgets that need to hit URLs
|
||||
directly (e.g. `Image.network(url, headers: service.authHeaders)` for
|
||||
thumbnails/previews).
|
||||
- Downloads stream through `Dio` (`downloadToFile`) for progress callbacks;
|
||||
small in-app previews (text/PDF) use `fetchBytes` via `package:http`.
|
||||
|
||||
## Session persistence
|
||||
|
||||
- **Credentials** (`server`, `loginName`, `appPassword`) live in
|
||||
`flutter_secure_storage` — OS keychain/keystore-backed, never
|
||||
`shared_preferences`.
|
||||
- **UI/app preferences** (theme mode, seed color, dynamic-color toggle,
|
||||
bottom-bar opacity/blur, grid vs. list, sort field, hidden-files toggle,
|
||||
etc.) live in `shared_preferences` — see the `_pref*` key constants at the
|
||||
top of `server_provider.dart`.
|
||||
- On startup, `ServerProvider._restoreSession()` reads the secure-storage
|
||||
keys and, if all three are present, rebuilds a `NextcloudService` without
|
||||
re-hitting the login flow (`_applyCredentials(..., persist: false)`).
|
||||
`isRestoringSession` gates the splash screen until this resolves — see
|
||||
`standards.md` for why widget tests must mock both storage channels
|
||||
rather than relying on this async path throwing naturally.
|
||||
Reference in New Issue
Block a user