Rebrand application as Qlyra
Build Android (FCM) / build-android-fcm (push) Canceled after 0s
Build Android / build-android (push) Canceled after 0s
Build iOS / build-ios (push) Canceled after 0s
Build Linux / build-linux (push) Canceled after 0s
Build macOS / build-macos (push) Canceled after 0s
Build Windows / build-windows (push) Canceled after 0s
Release (main) / android (oneme) (push) Canceled after 0s
Release (main) / android (qlyra) (push) Canceled after 0s
Release (main) / windows (push) Canceled after 0s
Release (main) / linux (push) Canceled after 0s
Release (main) / macos (push) Canceled after 0s
Release (main) / ios (push) Canceled after 0s
Release (main) / release (push) Canceled after 0s

This commit is contained in:
sevenhill
2026-08-30 13:16:17 +03:00
parent 0245f792de
commit f74057ce9b
592 changed files with 38233 additions and 1899 deletions
+1 -1
View File
@@ -309,7 +309,7 @@ class DebugSessionLog {
if (totalEntries == 0 && totalLogs == 0) return null;
final info = StringBuffer();
info.writeln('Komet — отладочный лог');
info.writeln('Qlyra — отладочный лог');
if (endpoint != null) info.writeln('Сервер: $endpoint');
info.writeln('Экспортирован: ${DateTime.now().toIso8601String()}');
info.writeln('Период: последние ${_retention.inHours} часа');
+1 -2
View File
@@ -32,8 +32,7 @@ class EmojiKeywordIndex {
});
}
List<String> get all =>
List.unmodifiable(_entries.map((e) => e.emoji));
List<String> get all => List.unmodifiable(_entries.map((e) => e.emoji));
List<String> search(String query) {
final targets = resolve(query);
+1 -1
View File
@@ -1,7 +1,7 @@
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// Centralized tactile feedback for Komet.
/// Centralized tactile feedback for Qlyra.
///
/// Wraps Flutter's [HapticFeedback] so the whole app speaks one tactile
/// "language": the same gesture always feels the same. Composite patterns
+5 -2
View File
@@ -7,7 +7,8 @@ const int _avatarTargetBytes = 900 * 1024;
/// Maximum accepted size for a user-picked avatar before compression.
const int kMaxAvatarBytes = 8 * 1024 * 1024;
Future<Uint8List?> compressAvatar(Uint8List input) => compute(_encodeAvatar, input);
Future<Uint8List?> compressAvatar(Uint8List input) =>
compute(_encodeAvatar, input);
Future<Uint8List?> encodeRgbaToJpeg(Uint8List rgba, int width, int height) =>
compute(_encodeRgba, (rgba, width, height));
@@ -29,7 +30,9 @@ Uint8List? _encodeAvatar(Uint8List input) {
final decoded = img.decodeImage(input);
if (decoded == null) return null;
final oriented = img.bakeOrientation(decoded);
final image = oriented.width > _avatarMaxDimension || oriented.height > _avatarMaxDimension
final image =
oriented.width > _avatarMaxDimension ||
oriented.height > _avatarMaxDimension
? img.copyResize(
oriented,
width: oriented.width >= oriented.height ? _avatarMaxDimension : null,
+1 -1
View File
@@ -23,7 +23,7 @@ bool leavesWebView(String? scheme) {
return !_webViewSchemes.contains(scheme.toLowerCase());
}
const Set<String> _appSchemes = {'komet', 'max'};
const Set<String> _appSchemes = {'qlyra', 'max'};
Future<void> openExternalUrl(BuildContext context, String url) async {
final appUri = Uri.tryParse(url.trim());
+4 -4
View File
@@ -6,7 +6,7 @@ import 'package:logger/logger.dart';
import 'debug_session_log.dart';
Level _minimumLogLevel() {
const raw = String.fromEnvironment('KOMET_LOG_LEVEL', defaultValue: '');
const raw = String.fromEnvironment('QLYRA_LOG_LEVEL', defaultValue: '');
switch (raw.toLowerCase()) {
case 'trace':
return Level.trace;
@@ -42,7 +42,7 @@ LogFilter _logFilter() {
final logger = Logger(
filter: _logFilter(),
level: _minimumLogLevel(),
printer: KometLogPrinter(),
printer: QlyraLogPrinter(),
output: MultiOutput([ConsoleOutput(), DebugSessionLogOutput()]),
);
@@ -115,8 +115,8 @@ AnsiColor _levelColor(Level level) {
return AnsiColor.fg(AnsiColor.grey(0.5));
}
class KometLogPrinter extends LogPrinter {
KometLogPrinter({this.colors = true});
class QlyraLogPrinter extends LogPrinter {
QlyraLogPrinter({this.colors = true});
final bool colors;
+1 -1
View File
@@ -9,7 +9,7 @@ class ScreenWake {
static final ScreenWake instance = ScreenWake._();
static const _channel = MethodChannel('ru.komet.app/screen');
static const _channel = MethodChannel('ru.qlyra.app/screen');
final Set<Object> _holders = <Object>{};
+4 -1
View File
@@ -54,7 +54,10 @@ class _TiledSvgPatternState extends State<TiledSvgPattern> {
if (_image != cached) setState(() => _image = cached);
return;
}
final future = _pending.putIfAbsent(key, () => _rasterize(widget.asset, px));
final future = _pending.putIfAbsent(
key,
() => _rasterize(widget.asset, px),
);
try {
final image = await future;
_cache[key] = image;
+26 -21
View File
@@ -39,9 +39,10 @@ class UpdateCheckResult {
}
abstract class UpdateChecker {
static const String _owner = 'KometTeam';
static const String _repo = 'Komet';
static const String _userAgent = 'KometUpdateChecker';
static const String _userAgent = 'QlyraUpdateChecker';
static const String _baseUrl = 'https://argus.kusoft.xyz';
static const String _manifestUrl =
'$_baseUrl/api/apps/qlyra/manifest?platform=android&channel=stable';
static const String _lastCheckKey = 'update_last_check_ms';
static const String _skippedTagKey = 'update_skipped_tag';
@@ -132,41 +133,45 @@ abstract class UpdateChecker {
await prefs.setString(_skippedTagKey, tag);
}
static String get _releasesPage =>
'https://github.com/$_owner/$_repo/releases';
static String get _releasesPage => _manifestUrl;
static Future<Map<String, dynamic>?> _fetchLatestRelease() async {
final uri = Uri.parse(
'https://api.github.com/repos/$_owner/$_repo/releases?per_page=10',
);
final uri = Uri.parse(_manifestUrl);
final client = HttpClient()..connectionTimeout = _timeout;
try {
final req = await client.getUrl(uri);
req.headers
..set(HttpHeaders.userAgentHeader, _userAgent)
..set(HttpHeaders.acceptHeader, 'application/vnd.github+json');
..set(HttpHeaders.acceptHeader, 'application/json');
final resp = await req.close().timeout(_timeout);
if (resp.statusCode != HttpStatus.ok) {
await resp.drain<void>();
throw HttpException(
'GitHub returned HTTP ${resp.statusCode}',
uri: uri,
);
throw HttpException('Argus returned HTTP ${resp.statusCode}', uri: uri);
}
final body = await resp
.transform(const Utf8Decoder())
.join()
.timeout(_timeout);
final decoded = jsonDecode(body);
if (decoded is! List) {
throw const FormatException('Invalid GitHub releases response');
if (decoded is! Map || decoded['release'] is! Map) {
throw const FormatException('Invalid Argus manifest response');
}
for (final entry in decoded) {
if (entry is! Map) continue;
if (entry['draft'] == true) continue;
return entry.cast<String, dynamic>();
}
return null;
final release = (decoded['release'] as Map).cast<String, dynamic>();
final version = release['version'] as String?;
final downloadPath = release['downloadPath'] as String?;
if (version == null || downloadPath == null) return null;
final downloadUrl = Uri.parse(_baseUrl).resolve(downloadPath).toString();
return {
'tag_name': version,
'html_url': downloadUrl,
'body': release['notes'] as String? ?? '',
'assets': [
{
'name': 'qlyra-qlyra-universal.apk',
'browser_download_url': downloadUrl,
},
],
};
} finally {
client.close(force: true);
}
+5 -3
View File
@@ -57,7 +57,9 @@ abstract class UpdateInstaller {
if (!Platform.isAndroid || info.assets.isEmpty) return null;
final packageInfo = await PackageInfo.fromPlatform();
final flavor = packageInfo.packageName == 'ru.oneme.app' ? 'oneme' : 'komet';
final flavor = packageInfo.packageName == 'ru.oneme.app'
? 'oneme'
: 'qlyra';
final androidInfo = await DeviceInfoPlugin().androidInfo;
final abis = androidInfo.supportedAbis;
@@ -83,13 +85,13 @@ abstract class UpdateInstaller {
) async {
final dir = await getTemporaryDirectory();
final safeTag = tag.replaceAll(RegExp(r'[^A-Za-z0-9._-]'), '_');
final file = File('${dir.path}/komet-update-$safeTag.apk');
final file = File('${dir.path}/qlyra-update-$safeTag.apk');
final part = File('${file.path}.part');
final client = HttpClient();
try {
final request = await client.getUrl(Uri.parse(url));
request.headers.set(HttpHeaders.userAgentHeader, 'KometUpdateInstaller');
request.headers.set(HttpHeaders.userAgentHeader, 'QlyraUpdateInstaller');
final response = await request.close();
if (response.statusCode != HttpStatus.ok) {
await response.drain<void>();