Files
bvandeusen 89d8b4b5a0 feat(flutter): send timezone on login + app-start + weekly
Flutter client posts FlutterTimezone.getLocalTimezone() to
PUT /api/me/timezone on every setSession (login / register success)
and on every AuthController.build (app cold-start with valid
session), when the locally-stored tz_last_sent_at is >7 days old.
Cadence tracked in flutter_secure_storage so it survives app
restarts.

Failures swallowed: the server's UTC default + last-known value
keep the scheduler functioning until the next attempt.

Completes the client side of #392 Half B (per-user timezone
scheduling).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:16:52 -04:00

50 lines
1.8 KiB
Dart

import 'package:dio/dio.dart';
import '../../models/history_event.dart';
import '../../models/quarantine_mine.dart';
import '../../models/system_playlists_status.dart';
/// /api/me/* endpoints — caller-scoped data (history, profile, etc.).
class MeApi {
MeApi(this._dio);
final Dio _dio;
/// GET /api/me/history. Paginated via offset/limit; server emits
/// `{events, has_more}` rather than the standard `Page<T>` envelope.
Future<HistoryPage> history({int limit = 50, int offset = 0}) async {
final r = await _dio.get<Map<String, dynamic>>(
'/api/me/history',
queryParameters: {'limit': limit, 'offset': offset},
);
return HistoryPage.fromJson(r.data ?? const {});
}
/// GET /api/quarantine/mine — flat list (no envelope).
Future<List<QuarantineMineRow>> quarantineMine() async {
final r = await _dio.get<List<dynamic>>('/api/quarantine/mine');
final raw = r.data ?? const [];
return raw
.map((e) =>
QuarantineMineRow.fromJson((e as Map).cast<String, dynamic>()))
.toList(growable: false);
}
/// GET /api/me/system-playlists-status. Returns the caller's most
/// recent system-playlist build state. Used by the home Playlists
/// row to choose between real and placeholder cards.
Future<SystemPlaylistsStatus> systemPlaylistsStatus() async {
final r = await _dio.get<Map<String, dynamic>>(
'/api/me/system-playlists-status',
);
return SystemPlaylistsStatus.fromJson(r.data ?? const {});
}
/// PUT /api/me/timezone — submit the device's IANA timezone. The
/// scheduler uses this to fire the user's daily playlist build at
/// 03:00 in their local time. See AuthController._sendTimezoneIfStale
/// for the weekly cadence trigger.
Future<void> putTimezone(String timezone) async {
await _dio.put<void>('/api/me/timezone', data: {'timezone': timezone});
}
}