refactor: share low-risk UI and tracker helpers
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import '../oauth_proxy_client.dart';
|
||||
import '../tracker_session_utils.dart';
|
||||
|
||||
/// Immutable AniList OAuth session.
|
||||
///
|
||||
@@ -14,7 +13,7 @@ class AnilistSession {
|
||||
|
||||
const AnilistSession({required this.accessToken, required this.expiresAt, required this.createdAt, this.username});
|
||||
|
||||
bool get isExpired => DateTime.now().millisecondsSinceEpoch ~/ 1000 >= expiresAt;
|
||||
bool get isExpired => isTrackerTokenExpired(expiresAt);
|
||||
|
||||
AnilistSession copyWith({String? accessToken, int? expiresAt, String? username, int? createdAt}) {
|
||||
return AnilistSession(
|
||||
@@ -43,11 +42,11 @@ class AnilistSession {
|
||||
/// and have no refresh; when the proxy doesn't echo an explicit expiry we
|
||||
/// default to the documented year.
|
||||
factory AnilistSession.fromProxyResult(OAuthProxyResult r) {
|
||||
final createdAt = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
final createdAt = trackerSessionNowEpochSeconds();
|
||||
final expiresIn = r.expiresIn ?? 365 * 24 * 60 * 60;
|
||||
return AnilistSession(accessToken: r.accessToken, expiresAt: createdAt + expiresIn, createdAt: createdAt);
|
||||
}
|
||||
|
||||
String encode() => json.encode(toJson());
|
||||
static AnilistSession decode(String raw) => AnilistSession.fromJson(json.decode(raw) as Map<String, dynamic>);
|
||||
String encode() => encodeTrackerSessionJson(toJson());
|
||||
static AnilistSession decode(String raw) => decodeTrackerSessionJson(raw, AnilistSession.fromJson);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import '../oauth_proxy_client.dart';
|
||||
import '../tracker_session_utils.dart';
|
||||
|
||||
/// Immutable MyAnimeList OAuth session.
|
||||
///
|
||||
@@ -21,8 +20,8 @@ class MalSession {
|
||||
this.username,
|
||||
});
|
||||
|
||||
bool get isExpired => DateTime.now().millisecondsSinceEpoch ~/ 1000 >= expiresAt;
|
||||
bool get needsRefresh => DateTime.now().millisecondsSinceEpoch ~/ 1000 >= expiresAt - 300;
|
||||
bool get isExpired => isTrackerTokenExpired(expiresAt);
|
||||
bool get needsRefresh => trackerTokenNeedsRefresh(expiresAt);
|
||||
|
||||
MalSession copyWith({String? accessToken, String? refreshToken, int? expiresAt, String? username, int? createdAt}) {
|
||||
return MalSession(
|
||||
@@ -52,7 +51,7 @@ class MalSession {
|
||||
|
||||
/// Build a session from MAL's `/oauth2/token` response.
|
||||
factory MalSession.fromTokenResponse(Map<String, dynamic> json) {
|
||||
final createdAt = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
final createdAt = trackerSessionNowEpochSeconds();
|
||||
final expiresIn = (json['expires_in'] as num).toInt();
|
||||
return MalSession(
|
||||
accessToken: json['access_token'] as String,
|
||||
@@ -65,7 +64,7 @@ class MalSession {
|
||||
/// Build a session from an OAuth-proxy result. MAL's refresh_token is
|
||||
/// required for the 31-day refresh loop.
|
||||
factory MalSession.fromProxyResult(OAuthProxyResult r) {
|
||||
final createdAt = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
final createdAt = trackerSessionNowEpochSeconds();
|
||||
final expiresIn = r.expiresIn ?? 31 * 24 * 60 * 60;
|
||||
return MalSession(
|
||||
accessToken: r.accessToken,
|
||||
@@ -75,6 +74,6 @@ class MalSession {
|
||||
);
|
||||
}
|
||||
|
||||
String encode() => json.encode(toJson());
|
||||
static MalSession decode(String raw) => MalSession.fromJson(json.decode(raw) as Map<String, dynamic>);
|
||||
String encode() => encodeTrackerSessionJson(toJson());
|
||||
static MalSession decode(String raw) => decodeTrackerSessionJson(raw, MalSession.fromJson);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'dart:convert';
|
||||
import '../tracker_session_utils.dart';
|
||||
|
||||
/// Immutable Simkl OAuth session.
|
||||
///
|
||||
@@ -27,11 +27,9 @@ class SimklSession {
|
||||
|
||||
/// Build a session from Simkl's device-code `/oauth/pin/<code>` response.
|
||||
/// Simkl doesn't expose a creation timestamp so we stamp "now".
|
||||
factory SimklSession.fromTokenResponse(Map<String, dynamic> json) => SimklSession(
|
||||
accessToken: json['access_token'] as String,
|
||||
createdAt: DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||
);
|
||||
factory SimklSession.fromTokenResponse(Map<String, dynamic> json) =>
|
||||
SimklSession(accessToken: json['access_token'] as String, createdAt: trackerSessionNowEpochSeconds());
|
||||
|
||||
String encode() => json.encode(toJson());
|
||||
static SimklSession decode(String raw) => SimklSession.fromJson(json.decode(raw) as Map<String, dynamic>);
|
||||
String encode() => encodeTrackerSessionJson(toJson());
|
||||
static SimklSession decode(String raw) => decodeTrackerSessionJson(raw, SimklSession.fromJson);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'dart:convert' as convert;
|
||||
|
||||
/// Current epoch time in seconds, matching tracker OAuth expiry fields.
|
||||
int trackerSessionNowEpochSeconds() => DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
|
||||
bool isTrackerTokenExpired(int expiresAt, {int? nowSeconds}) =>
|
||||
(nowSeconds ?? trackerSessionNowEpochSeconds()) >= expiresAt;
|
||||
|
||||
bool trackerTokenNeedsRefresh(int expiresAt, {int refreshWindowSeconds = 300, int? nowSeconds}) =>
|
||||
(nowSeconds ?? trackerSessionNowEpochSeconds()) >= expiresAt - refreshWindowSeconds;
|
||||
|
||||
String encodeTrackerSessionJson(Map<String, dynamic> value) => convert.json.encode(value);
|
||||
|
||||
T decodeTrackerSessionJson<T>(String raw, T Function(Map<String, dynamic> json) fromJson) {
|
||||
return fromJson(convert.json.decode(raw) as Map<String, dynamic>);
|
||||
}
|
||||
Reference in New Issue
Block a user