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
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:
@@ -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} часа');
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>{};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
|
||||
Reference in New Issue
Block a user