Release Lunaris 2.0 customization update

This commit is contained in:
2026-05-26 12:45:46 +03:00
parent 9cff9e5307
commit f65efe7cf7
21 changed files with 514 additions and 189 deletions
+1 -1
View File
@@ -168,7 +168,7 @@ final updateServiceProvider = Provider<UpdateService>((ref) {
connectTimeout: const Duration(seconds: 12),
receiveTimeout: const Duration(seconds: 12),
headers: const {
'User-Agent': 'Lunaris/1.1 Flutter local booru browser',
'User-Agent': 'Lunaris/2.0 Flutter local booru browser',
'Accept': 'application/json',
},
),
+4 -6
View File
@@ -26,7 +26,7 @@ class KemonoProvider
receiveTimeout: const Duration(seconds: 20),
headers: const {
'Accept': 'application/json',
'User-Agent': 'Lunaris/1.1 Flutter local booru browser',
'User-Agent': 'Lunaris/2.0 Flutter local booru browser',
},
),
);
@@ -99,11 +99,9 @@ class KemonoProvider
if (searchText.isNotEmpty) {
try {
final response = await _creatorDio.get<dynamic>(
'/search',
_creatorPath(),
queryParameters: {
'q': searchText,
'query': searchText,
'site': _isCoomer ? 'coomer' : 'kemono',
'keyword': searchText,
'page': page,
'itemsPerPage': limit.clamp(1, 100),
},
@@ -460,7 +458,7 @@ class KemonoProvider
receiveTimeout: const Duration(seconds: 25),
headers: const {
'Accept': 'application/json',
'User-Agent': 'Lunaris/1.1 Flutter local booru browser',
'User-Agent': 'Lunaris/2.0 Flutter local booru browser',
},
),
);
+13 -12
View File
@@ -210,23 +210,24 @@ class ProviderManager {
Set<String> seen,
) {
final posts = <Post>[];
var index = 0;
while (true) {
var added = false;
for (final providerPosts in results) {
if (index >= providerPosts.length) continue;
final post = providerPosts[index];
if (seen.add(post.cacheKey)) {
posts.add(post);
added = true;
}
for (final providerPosts in results) {
for (final post in providerPosts) {
if (seen.add(post.cacheKey)) posts.add(post);
}
if (!added && results.every((items) => index >= items.length)) break;
index++;
}
posts.sort((a, b) => _mixKey(a).compareTo(_mixKey(b)));
return posts;
}
int _mixKey(Post post) {
var hash = 0x811c9dc5;
for (final code in post.cacheKey.codeUnits) {
hash ^= code;
hash = (hash * 0x01000193) & 0x7fffffff;
}
return hash;
}
Future<Result<List<PostComment>>> getComments(
String providerId,
String postId,
@@ -88,7 +88,7 @@ class ProviderRepository {
priority: 5,
timeoutSeconds: 20,
customHeaders: const {
'User-Agent': 'Lunaris/1.1 Flutter local booru browser',
'User-Agent': 'Lunaris/2.0 Flutter local booru browser',
},
createdAt: now,
updatedAt: now,
@@ -102,7 +102,7 @@ class ProviderRepository {
priority: 6,
timeoutSeconds: 20,
customHeaders: const {
'User-Agent': 'Lunaris/1.1 Flutter local booru browser',
'User-Agent': 'Lunaris/2.0 Flutter local booru browser',
},
createdAt: now,
updatedAt: now,
@@ -18,6 +18,10 @@ class AppSettings {
required this.cacheMaxItems,
required this.providerPriority,
required this.themeMode,
required this.languageCode,
required this.appSeedColor,
required this.hiddenTabs,
required this.allowExperimentalUpdates,
required this.desktopColumns,
required this.mobileColumns,
required this.blurExplicitContent,
@@ -54,6 +58,10 @@ class AppSettings {
final int cacheMaxItems;
final Map<String, int> providerPriority;
final String themeMode;
final String languageCode;
final int appSeedColor;
final List<String> hiddenTabs;
final bool allowExperimentalUpdates;
final int desktopColumns;
final int mobileColumns;
final bool blurExplicitContent;
@@ -90,6 +98,10 @@ class AppSettings {
cacheMaxItems: 2000,
providerPriority: {'gelbooru': 0, 'rule34': 1, 'safebooru': 2},
themeMode: 'dark',
languageCode: 'ru',
appSeedColor: 0xFFE84D8A,
hiddenTabs: [],
allowExperimentalUpdates: false,
desktopColumns: 5,
mobileColumns: 2,
blurExplicitContent: true,
@@ -127,6 +139,10 @@ class AppSettings {
int? cacheMaxItems,
Map<String, int>? providerPriority,
String? themeMode,
String? languageCode,
int? appSeedColor,
List<String>? hiddenTabs,
bool? allowExperimentalUpdates,
int? desktopColumns,
int? mobileColumns,
bool? blurExplicitContent,
@@ -164,6 +180,11 @@ class AppSettings {
cacheMaxItems: cacheMaxItems ?? this.cacheMaxItems,
providerPriority: providerPriority ?? this.providerPriority,
themeMode: themeMode ?? this.themeMode,
languageCode: languageCode ?? this.languageCode,
appSeedColor: appSeedColor ?? this.appSeedColor,
hiddenTabs: hiddenTabs ?? this.hiddenTabs,
allowExperimentalUpdates:
allowExperimentalUpdates ?? this.allowExperimentalUpdates,
desktopColumns: desktopColumns ?? this.desktopColumns,
mobileColumns: mobileColumns ?? this.mobileColumns,
blurExplicitContent: blurExplicitContent ?? this.blurExplicitContent,
@@ -206,6 +227,10 @@ class AppSettings {
'cacheMaxItems': cacheMaxItems,
'providerPriority': providerPriority,
'themeMode': themeMode,
'languageCode': languageCode,
'appSeedColor': appSeedColor,
'hiddenTabs': hiddenTabs,
'allowExperimentalUpdates': allowExperimentalUpdates,
'desktopColumns': desktopColumns,
'mobileColumns': mobileColumns,
'blurExplicitContent': blurExplicitContent,
@@ -249,6 +274,14 @@ class AppSettings {
(json['providerPriority'] as Map?) ?? defaults.providerPriority,
),
themeMode: (json['themeMode'] as String?) ?? defaults.themeMode,
languageCode:
(json['languageCode'] as String?) ?? defaults.languageCode,
appSeedColor:
(json['appSeedColor'] as num?)?.toInt() ?? defaults.appSeedColor,
hiddenTabs: List<String>.from(
(json['hiddenTabs'] as List?) ?? defaults.hiddenTabs),
allowExperimentalUpdates: (json['allowExperimentalUpdates'] as bool?) ??
defaults.allowExperimentalUpdates,
desktopColumns: (json['desktopColumns'] as num?)?.toInt() ??
defaults.desktopColumns,
mobileColumns:
@@ -488,6 +521,10 @@ class SettingsService {
},
'settingsSummary': {
'themeMode': settings.themeMode,
'languageCode': settings.languageCode,
'appSeedColor': settings.appSeedColor,
'hiddenTabs': settings.hiddenTabs,
'allowExperimentalUpdates': settings.allowExperimentalUpdates,
'nsfwEnabled': settings.nsfwEnabled,
'blurExplicitContent': settings.blurExplicitContent,
'mediaQualityMode': settings.mediaQualityMode,
+37 -6
View File
@@ -12,6 +12,8 @@ class UpdateService {
static const latestReleaseUrl =
'https://gitea.rardogsynapse.online/api/v1/repos/RarDog/RuleGelApp/releases/latest';
static const releasesUrl =
'https://gitea.rardogsynapse.online/api/v1/repos/RarDog/RuleGelApp/releases';
final Dio _dio;
final SettingsService _settingsService;
@@ -23,9 +25,7 @@ class UpdateService {
: AppSettings.defaults;
try {
final response = await _dio.get<dynamic>(latestReleaseUrl);
final data = Map<String, dynamic>.from(response.data as Map);
final info = _releaseFromJson(data);
final info = await _latestAllowedRelease(settings);
final nextSettings = settings.copyWith(
lastUpdateCheckAt: DateTime.now().toIso8601String(),
);
@@ -49,6 +49,33 @@ class UpdateService {
}
}
Future<AppUpdateInfo> _latestAllowedRelease(AppSettings settings) async {
final response = await _dio.get<dynamic>(
releasesUrl,
queryParameters: {'limit': 30},
);
final items = (response.data as List?) ?? const [];
final releases = items
.whereType<Map>()
.where((item) => item['draft'] != true)
.where((item) =>
settings.allowExperimentalUpdates || item['prerelease'] != true)
.map((item) => _releaseFromJson(Map<String, dynamic>.from(item)))
.toList(growable: false);
if (releases.isEmpty) {
final latest = await _dio.get<dynamic>(latestReleaseUrl);
return _releaseFromJson(Map<String, dynamic>.from(latest.data as Map));
}
releases.sort((a, b) {
final versionCompare = _compareVersions(b.version, a.version);
if (versionCompare != 0) return versionCompare;
final left = b.publishedAt ?? DateTime.fromMillisecondsSinceEpoch(0);
final right = a.publishedAt ?? DateTime.fromMillisecondsSinceEpoch(0);
return left.compareTo(right);
});
return releases.first;
}
Future<Result<void>> remindLater() async {
final result = await _settingsService.getSettings();
if (result is Error<AppSettings>) return Error(result.failure);
@@ -120,13 +147,17 @@ class UpdateService {
}
static bool _isNewerVersion(String latest, String current) {
return _compareVersions(latest, current) > 0;
}
static int _compareVersions(String latest, String current) {
final left = _parts(latest);
final right = _parts(current);
for (var i = 0; i < 3; i++) {
if (left[i] > right[i]) return true;
if (left[i] < right[i]) return false;
if (left[i] > right[i]) return 1;
if (left[i] < right[i]) return -1;
}
return false;
return 0;
}
static List<int> _parts(String value) {