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
@@ -42,6 +42,6 @@
## Проверка ## Проверка
- [ ] `flutter analyze` - [ ] `flutter analyze`
- [ ] Сборка `komet` flavor - [ ] Сборка `qlyra` flavor
- [ ] Ручная проверка затронутых сценариев - [ ] Ручная проверка затронутых сценариев
- [ ] Регресс по безопасности (если затронута) - [ ] Регресс по безопасности (если затронута)
+1 -1
View File
@@ -21,4 +21,4 @@ runs:
- name: Cache Rust build - name: Cache Rust build
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
with: with:
workspaces: native/komet_crypto/rust workspaces: native/qlyra_crypto/rust
+8 -8
View File
@@ -69,12 +69,12 @@ jobs:
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed." echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
exit 0 exit 0
fi fi
echo "$KEYSTORE_BASE64" | base64 -d > android/app/komet-release.jks echo "$KEYSTORE_BASE64" | base64 -d > android/app/qlyra-release.jks
{ {
echo "storePassword=$KEYSTORE_PASSWORD" echo "storePassword=$KEYSTORE_PASSWORD"
echo "keyPassword=$KEY_PASSWORD" echo "keyPassword=$KEY_PASSWORD"
echo "keyAlias=$KEY_ALIAS" echo "keyAlias=$KEY_ALIAS"
echo "storeFile=komet-release.jks" echo "storeFile=qlyra-release.jks"
} > android/key.properties } > android/key.properties
echo "Release signing configured." echo "Release signing configured."
@@ -87,7 +87,7 @@ jobs:
- name: Upload Universal APK - name: Upload Universal APK
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-fcm-universal name: qlyra-android-fcm-universal
path: build/app/outputs/flutter-apk/app-oneme-release.apk path: build/app/outputs/flutter-apk/app-oneme-release.apk
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
@@ -95,7 +95,7 @@ jobs:
- name: Upload arm64-v8a APK - name: Upload arm64-v8a APK
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-fcm-arm64-v8a name: qlyra-android-fcm-arm64-v8a
path: build/app/outputs/flutter-apk/app-arm64-v8a-oneme-release.apk path: build/app/outputs/flutter-apk/app-arm64-v8a-oneme-release.apk
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
@@ -103,7 +103,7 @@ jobs:
- name: Upload armeabi-v7a APK - name: Upload armeabi-v7a APK
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-fcm-armeabi-v7a name: qlyra-android-fcm-armeabi-v7a
path: build/app/outputs/flutter-apk/app-armeabi-v7a-oneme-release.apk path: build/app/outputs/flutter-apk/app-armeabi-v7a-oneme-release.apk
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
@@ -111,7 +111,7 @@ jobs:
- name: Upload x86_64 APK - name: Upload x86_64 APK
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-fcm-x86_64 name: qlyra-android-fcm-x86_64
path: build/app/outputs/flutter-apk/app-x86_64-oneme-release.apk path: build/app/outputs/flutter-apk/app-x86_64-oneme-release.apk
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
@@ -122,7 +122,7 @@ jobs:
- name: Upload App Bundle artifact - name: Upload App Bundle artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-fcm-aab name: qlyra-android-fcm-aab
path: build/app/outputs/bundle/onemeRelease/app-oneme-release.aab path: build/app/outputs/bundle/onemeRelease/app-oneme-release.aab
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
@@ -130,7 +130,7 @@ jobs:
- name: Upload debug symbols - name: Upload debug symbols
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-fcm-symbols name: qlyra-android-fcm-symbols
path: build/symbols path: build/symbols
if-no-files-found: error if-no-files-found: error
retention-days: 90 retention-days: 90
+16 -16
View File
@@ -69,68 +69,68 @@ jobs:
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed." echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
exit 0 exit 0
fi fi
echo "$KEYSTORE_BASE64" | base64 -d > android/app/komet-release.jks echo "$KEYSTORE_BASE64" | base64 -d > android/app/qlyra-release.jks
{ {
echo "storePassword=$KEYSTORE_PASSWORD" echo "storePassword=$KEYSTORE_PASSWORD"
echo "keyPassword=$KEY_PASSWORD" echo "keyPassword=$KEY_PASSWORD"
echo "keyAlias=$KEY_ALIAS" echo "keyAlias=$KEY_ALIAS"
echo "storeFile=komet-release.jks" echo "storeFile=qlyra-release.jks"
} > android/key.properties } > android/key.properties
echo "Release signing configured." echo "Release signing configured."
- name: Build Universal APK - name: Build Universal APK
run: flutter build apk --release --flavor komet --obfuscate --split-debug-info=build/symbols run: flutter build apk --release --flavor qlyra --obfuscate --split-debug-info=build/symbols
- name: Build Split APKs - name: Build Split APKs
run: flutter build apk --release --split-per-abi --flavor komet --obfuscate --split-debug-info=build/symbols run: flutter build apk --release --split-per-abi --flavor qlyra --obfuscate --split-debug-info=build/symbols
- name: Upload Universal APK - name: Upload Universal APK
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-universal name: qlyra-android-universal
path: build/app/outputs/flutter-apk/app-komet-release.apk path: build/app/outputs/flutter-apk/app-qlyra-release.apk
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
- name: Upload arm64-v8a APK - name: Upload arm64-v8a APK
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-arm64-v8a name: qlyra-android-arm64-v8a
path: build/app/outputs/flutter-apk/app-arm64-v8a-komet-release.apk path: build/app/outputs/flutter-apk/app-arm64-v8a-qlyra-release.apk
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
- name: Upload armeabi-v7a APK - name: Upload armeabi-v7a APK
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-armeabi-v7a name: qlyra-android-armeabi-v7a
path: build/app/outputs/flutter-apk/app-armeabi-v7a-komet-release.apk path: build/app/outputs/flutter-apk/app-armeabi-v7a-qlyra-release.apk
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
- name: Upload x86_64 APK - name: Upload x86_64 APK
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-x86_64 name: qlyra-android-x86_64
path: build/app/outputs/flutter-apk/app-x86_64-komet-release.apk path: build/app/outputs/flutter-apk/app-x86_64-qlyra-release.apk
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
- name: Build App Bundle - name: Build App Bundle
run: flutter build appbundle --release --flavor komet --obfuscate --split-debug-info=build/symbols run: flutter build appbundle --release --flavor qlyra --obfuscate --split-debug-info=build/symbols
- name: Upload App Bundle artifact - name: Upload App Bundle artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-aab name: qlyra-android-aab
path: build/app/outputs/bundle/kometRelease/app-komet-release.aab path: build/app/outputs/bundle/qlyraRelease/app-qlyra-release.aab
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
- name: Upload debug symbols - name: Upload debug symbols
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-android-symbols name: qlyra-android-symbols
path: build/symbols path: build/symbols
if-no-files-found: error if-no-files-found: error
retention-days: 90 retention-days: 90
+8 -8
View File
@@ -54,14 +54,14 @@ jobs:
run: | run: |
mkdir -p dist build/ios/Payload mkdir -p dist build/ios/Payload
cp -R build/ios/iphoneos/Runner.app build/ios/Payload/ cp -R build/ios/iphoneos/Runner.app build/ios/Payload/
(cd build/ios && zip -qr ../../dist/Komet-ios-unsigned.ipa Payload) (cd build/ios && zip -qr ../../dist/Qlyra-ios-unsigned.ipa Payload)
rm -rf build/ios/Payload rm -rf build/ios/Payload
- name: Upload unsigned iOS artifact - name: Upload unsigned iOS artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-ios-unsigned name: qlyra-ios-unsigned
path: dist/Komet-ios-unsigned.ipa path: dist/Qlyra-ios-unsigned.ipa
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
@@ -79,9 +79,9 @@ jobs:
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>get-task-allow</key><true/> <key>get-task-allow</key><true/>
<key>application-identifier</key><string>ru.komet.app</string> <key>application-identifier</key><string>ru.qlyra.app</string>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>
<array><string>ru.komet.app</string></array> <array><string>ru.qlyra.app</string></array>
</dict> </dict>
</plist> </plist>
PLIST PLIST
@@ -104,12 +104,12 @@ jobs:
run: | run: |
mkdir -p dist build/ios/Payload mkdir -p dist build/ios/Payload
cp -R build/ios/iphoneos/Runner.app build/ios/Payload/ cp -R build/ios/iphoneos/Runner.app build/ios/Payload/
(cd build/ios && zip -qr ../../dist/Komet-ios-pseudosigned.ipa Payload) (cd build/ios && zip -qr ../../dist/Qlyra-ios-pseudosigned.ipa Payload)
- name: Upload iOS artifact - name: Upload iOS artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-ios-pseudosigned name: qlyra-ios-pseudosigned
path: dist/Komet-ios-pseudosigned.ipa path: dist/Qlyra-ios-pseudosigned.ipa
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
+3 -3
View File
@@ -56,12 +56,12 @@ jobs:
- name: Package Linux - name: Package Linux
run: | run: |
mkdir -p dist mkdir -p dist
tar -C build/linux/x64/release/bundle -czf dist/Komet-linux-x64.tar.gz . tar -C build/linux/x64/release/bundle -czf dist/Qlyra-linux-x64.tar.gz .
- name: Upload Linux artifact - name: Upload Linux artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-linux-x64 name: qlyra-linux-x64
path: dist/Komet-linux-x64.tar.gz path: dist/Qlyra-linux-x64.tar.gz
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
+1 -1
View File
@@ -51,7 +51,7 @@ jobs:
- name: Upload macOS DMG artifact - name: Upload macOS DMG artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-macos name: qlyra-macos
path: dist/*.dmg path: dist/*.dmg
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
+3 -3
View File
@@ -52,12 +52,12 @@ jobs:
shell: pwsh shell: pwsh
run: | run: |
New-Item -ItemType Directory -Force -Path dist | Out-Null New-Item -ItemType Directory -Force -Path dist | Out-Null
Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath dist/Komet-windows-x64.zip Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath dist/Qlyra-windows-x64.zip
- name: Upload Windows artifact - name: Upload Windows artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: komet-windows-x64 name: qlyra-windows-x64
path: dist/Komet-windows-x64.zip path: dist/Qlyra-windows-x64.zip
if-no-files-found: error if-no-files-found: error
retention-days: 30 retention-days: 30
+3 -3
View File
@@ -60,17 +60,17 @@ jobs:
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed." echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
exit 0 exit 0
fi fi
echo "$KEYSTORE_BASE64" | base64 -d > android/app/komet-release.jks echo "$KEYSTORE_BASE64" | base64 -d > android/app/qlyra-release.jks
{ {
echo "storePassword=$KEYSTORE_PASSWORD" echo "storePassword=$KEYSTORE_PASSWORD"
echo "keyPassword=$KEY_PASSWORD" echo "keyPassword=$KEY_PASSWORD"
echo "keyAlias=$KEY_ALIAS" echo "keyAlias=$KEY_ALIAS"
echo "storeFile=komet-release.jks" echo "storeFile=qlyra-release.jks"
} > android/key.properties } > android/key.properties
echo "Release signing configured." echo "Release signing configured."
- name: Build Android APK - name: Build Android APK
run: flutter build apk --release --flavor komet run: flutter build apk --release --flavor qlyra
build-ios: build-ios:
runs-on: macos-latest runs-on: macos-latest
+3 -3
View File
@@ -59,17 +59,17 @@ jobs:
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed." echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
exit 0 exit 0
fi fi
echo "$KEYSTORE_BASE64" | base64 -d > android/app/komet-release.jks echo "$KEYSTORE_BASE64" | base64 -d > android/app/qlyra-release.jks
{ {
echo "storePassword=$KEYSTORE_PASSWORD" echo "storePassword=$KEYSTORE_PASSWORD"
echo "keyPassword=$KEY_PASSWORD" echo "keyPassword=$KEY_PASSWORD"
echo "keyAlias=$KEY_ALIAS" echo "keyAlias=$KEY_ALIAS"
echo "storeFile=komet-release.jks" echo "storeFile=qlyra-release.jks"
} > android/key.properties } > android/key.properties
echo "Release signing configured." echo "Release signing configured."
- name: Build Android APK - name: Build Android APK
run: flutter build apk --release --flavor komet run: flutter build apk --release --flavor qlyra
linux: linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
+17 -17
View File
@@ -23,7 +23,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
flavor: [komet, oneme] flavor: [qlyra, oneme]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
@@ -70,12 +70,12 @@ jobs:
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed." echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
exit 0 exit 0
fi fi
echo "$KEYSTORE_BASE64" | base64 -d > android/app/komet-release.jks echo "$KEYSTORE_BASE64" | base64 -d > android/app/qlyra-release.jks
{ {
echo "storePassword=$KEYSTORE_PASSWORD" echo "storePassword=$KEYSTORE_PASSWORD"
echo "keyPassword=$KEY_PASSWORD" echo "keyPassword=$KEY_PASSWORD"
echo "keyAlias=$KEY_ALIAS" echo "keyAlias=$KEY_ALIAS"
echo "storeFile=komet-release.jks" echo "storeFile=qlyra-release.jks"
} > android/key.properties } > android/key.properties
echo "Release signing configured." echo "Release signing configured."
@@ -89,12 +89,12 @@ jobs:
run: | run: |
F=${{ matrix.flavor }} F=${{ matrix.flavor }}
mkdir -p dist mkdir -p dist
cp build/app/outputs/flutter-apk/app-$F-release.apk dist/Komet-android-$F-universal.apk cp build/app/outputs/flutter-apk/app-$F-release.apk dist/Qlyra-android-$F-universal.apk
cp build/app/outputs/flutter-apk/app-arm64-v8a-$F-release.apk dist/Komet-android-$F-arm64-v8a.apk cp build/app/outputs/flutter-apk/app-arm64-v8a-$F-release.apk dist/Qlyra-android-$F-arm64-v8a.apk
cp build/app/outputs/flutter-apk/app-armeabi-v7a-$F-release.apk dist/Komet-android-$F-armeabi-v7a.apk cp build/app/outputs/flutter-apk/app-armeabi-v7a-$F-release.apk dist/Qlyra-android-$F-armeabi-v7a.apk
cp build/app/outputs/flutter-apk/app-x86_64-$F-release.apk dist/Komet-android-$F-x86_64.apk cp build/app/outputs/flutter-apk/app-x86_64-$F-release.apk dist/Qlyra-android-$F-x86_64.apk
cp build/app/outputs/bundle/${F}Release/app-$F-release.aab dist/Komet-android-$F.aab cp build/app/outputs/bundle/${F}Release/app-$F-release.aab dist/Qlyra-android-$F.aab
tar -czf dist/Komet-android-$F-symbols.tar.gz -C build/symbols . tar -czf dist/Qlyra-android-$F-symbols.tar.gz -C build/symbols .
- name: Upload Android artifacts (${{ matrix.flavor }}) - name: Upload Android artifacts (${{ matrix.flavor }})
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -127,7 +127,7 @@ jobs:
shell: pwsh shell: pwsh
run: | run: |
New-Item -ItemType Directory -Force -Path dist | Out-Null New-Item -ItemType Directory -Force -Path dist | Out-Null
Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath dist/Komet-windows-x64.zip Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath dist/Qlyra-windows-x64.zip
- name: Upload Windows artifact - name: Upload Windows artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -162,7 +162,7 @@ jobs:
- name: Package Linux - name: Package Linux
run: | run: |
mkdir -p dist mkdir -p dist
tar -C build/linux/x64/release/bundle -czf dist/Komet-linux-x64.tar.gz . tar -C build/linux/x64/release/bundle -czf dist/Qlyra-linux-x64.tar.gz .
- name: Upload Linux artifact - name: Upload Linux artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -196,7 +196,7 @@ jobs:
run: | run: |
mkdir -p dist mkdir -p dist
APP=$(find build/macos/Build/Products/Release -maxdepth 1 -name "*.app" | head -1) APP=$(find build/macos/Build/Products/Release -maxdepth 1 -name "*.app" | head -1)
ditto -c -k --keepParent "$APP" dist/Komet-macos.zip ditto -c -k --keepParent "$APP" dist/Qlyra-macos.zip
- name: Upload macOS artifact - name: Upload macOS artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -230,7 +230,7 @@ jobs:
run: | run: |
mkdir -p dist build/ios/Payload mkdir -p dist build/ios/Payload
cp -R build/ios/iphoneos/Runner.app build/ios/Payload/ cp -R build/ios/iphoneos/Runner.app build/ios/Payload/
(cd build/ios && zip -qr ../../dist/Komet-ios-unsigned.ipa Payload) (cd build/ios && zip -qr ../../dist/Qlyra-ios-unsigned.ipa Payload)
rm -rf build/ios/Payload rm -rf build/ios/Payload
- name: Install ldid - name: Install ldid
run: brew install ldid run: brew install ldid
@@ -246,9 +246,9 @@ jobs:
<dict> <dict>
<key>platform-application</key><true/> <key>platform-application</key><true/>
<key>get-task-allow</key><true/> <key>get-task-allow</key><true/>
<key>application-identifier</key><string>ru.komet.app</string> <key>application-identifier</key><string>ru.qlyra.app</string>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>
<array><string>ru.komet.app</string></array> <array><string>ru.qlyra.app</string></array>
<key>com.apple.private.security.no-container</key><true/> <key>com.apple.private.security.no-container</key><true/>
</dict> </dict>
</plist> </plist>
@@ -271,7 +271,7 @@ jobs:
run: | run: |
mkdir -p dist build/ios/Payload mkdir -p dist build/ios/Payload
cp -R build/ios/iphoneos/Runner.app build/ios/Payload/ cp -R build/ios/iphoneos/Runner.app build/ios/Payload/
(cd build/ios && zip -qr ../../dist/Komet-ios-pseudosigned.ipa Payload) (cd build/ios && zip -qr ../../dist/Qlyra-ios-pseudosigned.ipa Payload)
- name: Upload iOS artifact - name: Upload iOS artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -297,7 +297,7 @@ jobs:
BUILD="${{ github.event.inputs.build_number }}" BUILD="${{ github.event.inputs.build_number }}"
BUILD="${BUILD:-$GITHUB_RUN_NUMBER}" BUILD="${BUILD:-$GITHUB_RUN_NUMBER}"
echo "tag=v${BRANCH_VERSION}-dev.${BUILD}" >> "$GITHUB_OUTPUT" echo "tag=v${BRANCH_VERSION}-dev.${BUILD}" >> "$GITHUB_OUTPUT"
echo "name=Komet ${BRANCH_VERSION}-dev (build ${BUILD})" >> "$GITHUB_OUTPUT" echo "name=Qlyra ${BRANCH_VERSION}-dev (build ${BUILD})" >> "$GITHUB_OUTPUT"
- name: List artifacts - name: List artifacts
run: ls -lhR dist run: ls -lhR dist
+31 -31
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
flavor: [komet, oneme] flavor: [qlyra, oneme]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
@@ -65,12 +65,12 @@ jobs:
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed." echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
exit 0 exit 0
fi fi
echo "$KEYSTORE_BASE64" | base64 -d > android/app/komet-release.jks echo "$KEYSTORE_BASE64" | base64 -d > android/app/qlyra-release.jks
{ {
echo "storePassword=$KEYSTORE_PASSWORD" echo "storePassword=$KEYSTORE_PASSWORD"
echo "keyPassword=$KEY_PASSWORD" echo "keyPassword=$KEY_PASSWORD"
echo "keyAlias=$KEY_ALIAS" echo "keyAlias=$KEY_ALIAS"
echo "storeFile=komet-release.jks" echo "storeFile=qlyra-release.jks"
} > android/key.properties } > android/key.properties
echo "Release signing configured." echo "Release signing configured."
@@ -84,12 +84,12 @@ jobs:
run: | run: |
F=${{ matrix.flavor }} F=${{ matrix.flavor }}
mkdir -p dist mkdir -p dist
cp build/app/outputs/flutter-apk/app-$F-release.apk dist/Komet-android-$F-universal.apk cp build/app/outputs/flutter-apk/app-$F-release.apk dist/Qlyra-android-$F-universal.apk
cp build/app/outputs/flutter-apk/app-arm64-v8a-$F-release.apk dist/Komet-android-$F-arm64-v8a.apk cp build/app/outputs/flutter-apk/app-arm64-v8a-$F-release.apk dist/Qlyra-android-$F-arm64-v8a.apk
cp build/app/outputs/flutter-apk/app-armeabi-v7a-$F-release.apk dist/Komet-android-$F-armeabi-v7a.apk cp build/app/outputs/flutter-apk/app-armeabi-v7a-$F-release.apk dist/Qlyra-android-$F-armeabi-v7a.apk
cp build/app/outputs/flutter-apk/app-x86_64-$F-release.apk dist/Komet-android-$F-x86_64.apk cp build/app/outputs/flutter-apk/app-x86_64-$F-release.apk dist/Qlyra-android-$F-x86_64.apk
cp build/app/outputs/bundle/${F}Release/app-$F-release.aab dist/Komet-android-$F.aab cp build/app/outputs/bundle/${F}Release/app-$F-release.aab dist/Qlyra-android-$F.aab
tar -czf dist/Komet-android-$F-symbols.tar.gz -C build/symbols . tar -czf dist/Qlyra-android-$F-symbols.tar.gz -C build/symbols .
- name: Upload Android artifacts (${{ matrix.flavor }}) - name: Upload Android artifacts (${{ matrix.flavor }})
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -122,7 +122,7 @@ jobs:
shell: pwsh shell: pwsh
run: | run: |
New-Item -ItemType Directory -Force -Path dist | Out-Null New-Item -ItemType Directory -Force -Path dist | Out-Null
Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath dist/Komet-windows-x64.zip Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath dist/Qlyra-windows-x64.zip
- name: Upload Windows artifact - name: Upload Windows artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -157,7 +157,7 @@ jobs:
- name: Package Linux - name: Package Linux
run: | run: |
mkdir -p dist mkdir -p dist
tar -C build/linux/x64/release/bundle -czf dist/Komet-linux-x64.tar.gz . tar -C build/linux/x64/release/bundle -czf dist/Qlyra-linux-x64.tar.gz .
- name: Upload Linux artifact - name: Upload Linux artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -189,7 +189,7 @@ jobs:
run: | run: |
mkdir -p dist mkdir -p dist
APP=$(find build/macos/Build/Products/Release -maxdepth 1 -name "*.app" | head -1) APP=$(find build/macos/Build/Products/Release -maxdepth 1 -name "*.app" | head -1)
ditto -c -k --keepParent "$APP" dist/Komet-macos.zip ditto -c -k --keepParent "$APP" dist/Qlyra-macos.zip
- name: Upload macOS artifact - name: Upload macOS artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -233,9 +233,9 @@ jobs:
<dict> <dict>
<key>platform-application</key><true/> <key>platform-application</key><true/>
<key>get-task-allow</key><true/> <key>get-task-allow</key><true/>
<key>application-identifier</key><string>ru.komet.app</string> <key>application-identifier</key><string>ru.qlyra.app</string>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>
<array><string>ru.komet.app</string></array> <array><string>ru.qlyra.app</string></array>
<key>com.apple.private.security.no-container</key><true/> <key>com.apple.private.security.no-container</key><true/>
</dict> </dict>
</plist> </plist>
@@ -258,7 +258,7 @@ jobs:
run: | run: |
mkdir -p dist build/ios/Payload mkdir -p dist build/ios/Payload
cp -R build/ios/iphoneos/Runner.app build/ios/Payload/ cp -R build/ios/iphoneos/Runner.app build/ios/Payload/
(cd build/ios && zip -qr ../../dist/Komet-ios-pseudosigned.ipa Payload) (cd build/ios && zip -qr ../../dist/Qlyra-ios-pseudosigned.ipa Payload)
- name: Upload iOS artifact - name: Upload iOS artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -286,7 +286,7 @@ jobs:
run: | run: |
PUBSPEC_VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}' | cut -d'+' -f1) PUBSPEC_VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}' | cut -d'+' -f1)
echo "tag=v${PUBSPEC_VERSION}+${GITHUB_RUN_NUMBER}" >> "$GITHUB_OUTPUT" echo "tag=v${PUBSPEC_VERSION}+${GITHUB_RUN_NUMBER}" >> "$GITHUB_OUTPUT"
echo "name=Komet ${PUBSPEC_VERSION} (сборка ${GITHUB_RUN_NUMBER})" >> "$GITHUB_OUTPUT" echo "name=Qlyra ${PUBSPEC_VERSION} (сборка ${GITHUB_RUN_NUMBER})" >> "$GITHUB_OUTPUT"
- name: List artifacts - name: List artifacts
run: ls -lhR dist run: ls -lhR dist
@@ -305,31 +305,31 @@ jobs:
## Какой файл качать ## Какой файл качать
### Android — версия Komet (без push-уведомлений) ### Android — версия Qlyra (без push-уведомлений)
- **`Komet-android-komet-arm64-v8a.apk`** — рекомендуется для большинства современных телефонов (64-битный ARM). - **`Qlyra-android-qlyra-arm64-v8a.apk`** — рекомендуется для большинства современных телефонов (64-битный ARM).
- `Komet-android-komet-universal.apk` — универсальный APK, работает везде, но весит больше. - `Qlyra-android-qlyra-universal.apk` — универсальный APK, работает везде, но весит больше.
- `Komet-android-komet-armeabi-v7a.apk` — для старых 32-битных устройств. - `Qlyra-android-qlyra-armeabi-v7a.apk` — для старых 32-битных устройств.
- `Komet-android-komet-x86_64.apk` — для эмуляторов и редких x86-устройств. - `Qlyra-android-qlyra-x86_64.apk` — для эмуляторов и редких x86-устройств.
- `Komet-android-komet.aab` — App Bundle для публикации в Google Play (не для ручной установки). - `Qlyra-android-qlyra.aab` — App Bundle для публикации в Google Play (не для ручной установки).
### Android — версия OneMe (с push-уведомлениями через Firebase) ### Android — версия OneMe (с push-уведомлениями через Firebase)
- **`Komet-android-oneme-arm64-v8a.apk`** — рекомендуется для большинства современных телефонов. - **`Qlyra-android-oneme-arm64-v8a.apk`** — рекомендуется для большинства современных телефонов.
- `Komet-android-oneme-universal.apk` — универсальный APK. - `Qlyra-android-oneme-universal.apk` — универсальный APK.
- `Komet-android-oneme-armeabi-v7a.apk` — для старых 32-битных устройств. - `Qlyra-android-oneme-armeabi-v7a.apk` — для старых 32-битных устройств.
- `Komet-android-oneme-x86_64.apk` — для эмуляторов и x86-устройств. - `Qlyra-android-oneme-x86_64.apk` — для эмуляторов и x86-устройств.
- `Komet-android-oneme.aab` — App Bundle для Google Play. - `Qlyra-android-oneme.aab` — App Bundle для Google Play.
### Windows ### Windows
- **`Komet-windows-x64.zip`** — портативная сборка для Windows 10/11 (x64). Распаковать и запустить `Komet.exe`. - **`Qlyra-windows-x64.zip`** — портативная сборка для Windows 10/11 (x64). Распаковать и запустить `Qlyra.exe`.
### Linux ### Linux
- **`Komet-linux-x64.tar.gz`** — сборка для 64-битного Linux. Требуются `libgtk-3`, `libsecret-1`, `libjsoncpp`. Распаковать и запустить бинарник. - **`Qlyra-linux-x64.tar.gz`** — сборка для 64-битного Linux. Требуются `libgtk-3`, `libsecret-1`, `libjsoncpp`. Распаковать и запустить бинарник.
### macOS ### macOS
- **`Komet-macos.zip`** — `.app` для macOS. Распаковать и перетащить в `/Applications`. Приложение не нотаризовано — при первом запуске разрешите через «Системные настройки → Защита и безопасность». - **`Qlyra-macos.zip`** — `.app` для macOS. Распаковать и перетащить в `/Applications`. Приложение не нотаризовано — при первом запуске разрешите через «Системные настройки → Защита и безопасность».
### iOS ### iOS
- **`Komet-ios-pseudosigned.ipa`** — IPA с псевдо-подписью (ldid). - **`Qlyra-ios-pseudosigned.ipa`** — IPA с псевдо-подписью (ldid).
⚠️ Не устанавливается через App Store. Подходит для: ⚠️ Не устанавливается через App Store. Подходит для:
- jailbreak (Filza, rootless), - jailbreak (Filza, rootless),
- TrollStore, - TrollStore,
+1 -4
View File
@@ -136,7 +136,7 @@ agents.md
.env .env
.env.* .env.*
# Локальные дампы трафика и скрипты анализа (содержат секреты) # Локальные дампы трафика и скрипты анализа (содержат секреты)
komet.txt qlyra.txt
original_app.txt original_app.txt
fingerprint.py fingerprint.py
PCAPdroid_*.txt PCAPdroid_*.txt
@@ -149,8 +149,5 @@ maxtun/
turnprobe/ turnprobe/
test/live_server_probe_test.dart test/live_server_probe_test.dart
# local kolibri development: point the plugin at third_party/kolibri and the
# Rust core at third_party/kolibri/kolibri-net instead of the published ones
pubspec_overrides.yaml pubspec_overrides.yaml
.cargo/ .cargo/
third_party/kolibri/
-4
View File
@@ -1,4 +0,0 @@
{
"cmake.sourceDirectory": "/run/media/invisedivine/Drive/! My projects/Komet/linux/runner",
"kiroAgent.configureMCP": "Disabled"
}
-8
View File
@@ -1,8 +0,0 @@
Не оставляй комментарии в код
Старайся писать чистый код
Лучше качество чем количество
Когда при исправления какой то ошибки/добавление новой возникает ситуация 50/50 где можно выбрать починить сейчас но костылём, или чинить долго, упорно, может даже вообще не починить и переписать пол приложения - выбирай долго и упорно.
ВМЕСТО СНЕКБАРОВ ИСПОЛЬЗУЙ НАШИ КАСТОМНЫЕ УВЕДОМЛЕНИЕ showCustomNotification(context, 'текст')
Never leave real data in test files, including existing message contents or real IDs captured from requests. Use synthetic fixtures instead.
Не пытайся собирать APK/AAB (flutter build apk, flutter build appbundle, gradle assemble) — сборку запускает пользователь, тебе достаточно flutter analyze
Если делаешь кнопку, где иконка переключается перечёркнутая/неперечёркнутая (вспышка, микрофон, звук, уведомления) — она должна анимироваться lottie-иконкой, а не подменяться мгновенно: добавь спеку в SLASH_SPECS в tool/make_morph_icons.py (fill=1.0, если кнопка рисует Icon(..., fill: 1)), прогони python3 tool/make_morph_icons.py и выводи через LottieSlashIcon. Ассеты в assets/lottie/ руками не правь — только через генератор.
+8 -8
View File
@@ -4,20 +4,20 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project ## Project
Komet is a cross-platform Flutter messaging client (Android, iOS, macOS, Windows, Linux, Web) that communicates via a custom packet-based protocol with MessagePack serialization and Zstd compression. Qlyra is a cross-platform Flutter messaging client (Android, iOS, macOS, Windows, Linux, Web) that communicates via a custom packet-based protocol with MessagePack serialization and Zstd compression.
## Commands ## Commands
```bash ```bash
flutter pub get # install dependencies flutter pub get # install dependencies
flutter analyze # lint / static analysis flutter analyze # lint / static analysis
flutter run # run on connected device (default: komet flavor) flutter run # run on connected device (default: qlyra flavor)
flutter run --flavor oneme -t lib/main.dart # run oneme flavor (FCM) flutter run --flavor oneme -t lib/main.dart # run oneme flavor (FCM)
# Android builds (release builds use obfuscation; keep symbols to de-obfuscate crashes) # Android builds (release builds use obfuscation; keep symbols to de-obfuscate crashes)
flutter build apk --release --flavor komet --obfuscate --split-debug-info=build/symbols flutter build apk --release --flavor qlyra --obfuscate --split-debug-info=build/symbols
flutter build apk --release --split-per-abi --flavor komet --obfuscate --split-debug-info=build/symbols flutter build apk --release --split-per-abi --flavor qlyra --obfuscate --split-debug-info=build/symbols
flutter build appbundle --release --flavor komet --obfuscate --split-debug-info=build/symbols flutter build appbundle --release --flavor qlyra --obfuscate --split-debug-info=build/symbols
# Other platforms # Other platforms
flutter build ios --release --no-codesign flutter build ios --release --no-codesign
@@ -35,10 +35,10 @@ Android builds require **Java 17**. Gradle memory is configured to `-Xmx4096m`.
| Flavor | App ID | Notes | | Flavor | App ID | Notes |
|--------|--------|-------| |--------|--------|-------|
| `komet` | `ru.komet.app` | Default, no FCM | | `qlyra` | `ru.qlyra.app` | Default, no FCM |
| `oneme` | `ru.oneme.app` | FCM push notifications via Firebase | | `oneme` | `ru.oneme.app` | FCM push notifications via Firebase |
Flavor-specific Android resources live in `android/app/src/komet/` and `android/app/src/oneme/`. Flavor-specific Android resources live in `android/app/src/qlyra/` and `android/app/src/oneme/`.
## Architecture ## Architecture
@@ -97,5 +97,5 @@ Four GitHub Actions workflows in `.github/workflows/`:
- `flutter-dev.yml` — PR lint + Android build for dev branch - `flutter-dev.yml` — PR lint + Android build for dev branch
- `flutter-main.yml` — PR lint + all-platform builds for main branch - `flutter-main.yml` — PR lint + all-platform builds for main branch
- `build-android.yml` — production APKs + AAB (`komet` flavor), triggered on push to main - `build-android.yml` — production APKs + AAB (`qlyra` flavor), triggered on push to main
- `build-android-fcm.yml` — production APKs + AAB (`oneme` flavor with FCM), triggered on push to main - `build-android-fcm.yml` — production APKs + AAB (`oneme` flavor with FCM), triggered on push to main
+8 -11
View File
@@ -1,19 +1,16 @@
> [!IMPORTANT] <img src="assets/qlyra.png" width="100" alt="Qlyra Logo">
> Потерялись? Возможно вы ищите старую версию Komet. Она расположена [здесь](https://github.com/KometTeam/KometOld).
---
<img src="assets/komet.png" width="100" alt="Komet Logo"> # Qlyra
# Komet Кроссплатформенный клиент для мессенджера MAX.
Альтернативный FOSS клиент для мессенджера MAX
## Установка ## Android
[Последний релиз](https://github.com/KometTeam/Komet/releases/latest) / [Telegram Канал](https://t.me/TeamKomet)
Основной вариант приложения использует идентификатор `ru.qlyra.app` и flavor `qlyra`.
## Сборка из исходного кода ## Сборка из исходного кода
```console ```console
$ flutter build [windows|linux] [--release] $ flutter build [windows|linux] [--release]
$ flutter build apk --release --flavor qlyra
``` ```
## Хотите помочь?
Нашли ошибку и сами её исправили? Сделайте Pull-Request.<br/>
+1 -1
View File
@@ -11,6 +11,6 @@ GeneratedPluginRegistrant.java
# See https://flutter.dev/to/reference-keystore # See https://flutter.dev/to/reference-keystore
key.properties key.properties
app/key.properties app/key.properties
app/komet-release.jks app/qlyra-release.jks
**/*.keystore **/*.keystore
**/*.jks **/*.jks
+4 -4
View File
@@ -17,7 +17,7 @@ if (hasReleaseSigning) {
} }
android { android {
namespace = "ru.komet.app" namespace = "ru.qlyra.app"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion
@@ -32,7 +32,7 @@ android {
} }
defaultConfig { defaultConfig {
applicationId = "ru.komet.app" applicationId = "ru.qlyra.app"
minSdk = maxOf(flutter.minSdkVersion, 23) minSdk = maxOf(flutter.minSdkVersion, 23)
targetSdk = flutter.targetSdkVersion targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode versionCode = flutter.versionCode
@@ -54,10 +54,10 @@ android {
flavorDimensions += "distribution" flavorDimensions += "distribution"
productFlavors { productFlavors {
create("komet") { create("qlyra") {
dimension = "distribution" dimension = "distribution"
isDefault = true isDefault = true
applicationId = "ru.komet.app" applicationId = "ru.qlyra.app"
} }
create("oneme") { create("oneme") {
dimension = "distribution" dimension = "distribution"
+11 -20
View File
@@ -33,15 +33,15 @@
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/> <uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
<application <application
android:label="Komet" android:label="Qlyra"
android:name="${applicationName}" android:name="${applicationName}"
android:enableOnBackInvokedCallback="true" android:enableOnBackInvokedCallback="true"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
android:name="ru.komet.app.MainActivity" android:name="ru.qlyra.app.MainActivity"
android:exported="true" android:exported="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="Komet" android:label="Qlyra"
android:launchMode="singleTop" android:launchMode="singleTop"
android:taskAffinity="" android:taskAffinity=""
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
@@ -69,20 +69,11 @@
<data android:scheme="http" android:host="max.ru"/> <data android:scheme="http" android:host="max.ru"/>
<data android:scheme="http" android:host="www.max.ru"/> <data android:scheme="http" android:host="www.max.ru"/>
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https" android:host="komet.pw"/>
<data android:scheme="https" android:host="www.komet.pw"/>
<data android:path="/export-logs"/>
<data android:path="/export-logs/"/>
</intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW"/> <action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="komet"/> <data android:scheme="qlyra"/>
<data android:scheme="max"/> <data android:scheme="max"/>
</intent-filter> </intent-filter>
<intent-filter android:label="@string/share_target_label"> <intent-filter android:label="@string/share_target_label">
@@ -104,12 +95,12 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity-alias <activity-alias
android:name="ru.komet.app.MinimalIcon" android:name="ru.qlyra.app.MinimalIcon"
android:enabled="false" android:enabled="false"
android:exported="true" android:exported="true"
android:icon="@mipmap/ic_launcher_minimal" android:icon="@mipmap/ic_launcher"
android:label="Komet" android:label="Qlyra"
android:targetActivity="ru.komet.app.MainActivity"> android:targetActivity="ru.qlyra.app.MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
@@ -130,10 +121,10 @@
</intent-filter> </intent-filter>
<meta-data <meta-data
android:name="android.nfc.cardemulation.host_apdu_service" android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/komet_nfc_apdu"/> android:resource="@xml/qlyra_nfc_apdu"/>
</service> </service>
<service <service
android:name=".KometFcmService" android:name=".QlyraFcmService"
android:exported="false"> android:exported="false">
<intent-filter> <intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" /> <action android:name="com.google.firebase.MESSAGING_EVENT" />
@@ -175,7 +166,7 @@
android:value="2" /> android:value="2" />
<meta-data <meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id" android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="komet_messages" /> android:value="qlyra_messages" />
</application> </application>
<!-- Required to query activities that can process text, see: <!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and https://developer.android.com/training/package-visibility and
+1 -1
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(komet_rlottie LANGUAGES C CXX ASM) project(qlyra_rlottie LANGUAGES C CXX ASM)
add_subdirectory( add_subdirectory(
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../../third_party/rlottie_build" "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../third_party/rlottie_build"
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothDevice
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.app.Service import android.app.Service
import android.content.Context import android.content.Context
@@ -20,9 +20,9 @@ object CallState {
class CallForegroundService : Service() { class CallForegroundService : Service() {
companion object { companion object {
const val ACTION_START = "ru.komet.app.CALL_ONGOING_START" const val ACTION_START = "ru.qlyra.app.CALL_ONGOING_START"
const val ACTION_STOP = "ru.komet.app.CALL_ONGOING_STOP" const val ACTION_STOP = "ru.qlyra.app.CALL_ONGOING_STOP"
const val ACTION_SCREEN_SHARE = "ru.komet.app.CALL_SCREEN_SHARE" const val ACTION_SCREEN_SHARE = "ru.qlyra.app.CALL_SCREEN_SHARE"
const val EXTRA_SCREEN_SHARE = "screenShare" const val EXTRA_SCREEN_SHARE = "screenShare"
const val ONGOING_ID = 424243 const val ONGOING_ID = 424243
@@ -46,7 +46,7 @@ class CallForegroundService : Service() {
ctx.startService(intent) ctx.startService(intent)
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.w("KometFcm", "screen share FGS update failed: ${e.message}") Log.w("QlyraFcm", "screen share FGS update failed: ${e.message}")
} }
} }
@@ -63,7 +63,7 @@ class CallForegroundService : Service() {
ctx.startService(intent) ctx.startService(intent)
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.w("KometFcm", "ongoing FGS start failed: ${e.message}") Log.w("QlyraFcm", "ongoing FGS start failed: ${e.message}")
} }
} }
@@ -160,7 +160,7 @@ class CallForegroundService : Service() {
startForeground(ONGOING_ID, notif) startForeground(ONGOING_ID, notif)
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.w("KometFcm", "startForeground failed: ${e.message}") Log.w("QlyraFcm", "startForeground failed: ${e.message}")
stopSelf() stopSelf()
} }
} }
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
@@ -46,21 +46,21 @@ object CallEvents {
} }
object CallConst { object CallConst {
const val CHANNEL_ID = "komet_calls" const val CHANNEL_ID = "qlyra_calls"
const val CHANNEL_NAME = "Звонки" const val CHANNEL_NAME = "Звонки"
const val NOTIF_ID = 424242 const val NOTIF_ID = 424242
const val ACCENT = 0xFF7C6BF0.toInt() const val ACCENT = 0xFF7C6BF0.toInt()
const val EXTRA_CALL = "komet_call" const val EXTRA_CALL = "qlyra_call"
const val EXTRA_ACTION = "komet_call_action" const val EXTRA_ACTION = "qlyra_call_action"
const val EXTRA_DECLINE_PAYLOAD = "komet_decline_payload" const val EXTRA_DECLINE_PAYLOAD = "qlyra_decline_payload"
const val EXTRA_NOTIF_ID = "komet_notif_id" const val EXTRA_NOTIF_ID = "qlyra_notif_id"
const val EXTRA_CALLER = "komet_caller" const val EXTRA_CALLER = "qlyra_caller"
const val ACTION_RING = "ring" const val ACTION_RING = "ring"
const val ACTION_ANSWER = "answer" const val ACTION_ANSWER = "answer"
const val ACTION_DECLINE = "ru.komet.app.CALL_DECLINE" const val ACTION_DECLINE = "ru.qlyra.app.CALL_DECLINE"
const val ACTION_HANGUP = "ru.komet.app.CALL_HANGUP" const val ACTION_HANGUP = "ru.qlyra.app.CALL_HANGUP"
const val FLN_RECEIVER = const val FLN_RECEIVER =
"com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" "com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver"
@@ -72,7 +72,7 @@ object CallNotifier {
fun showIncoming(ctx: Context, data: Map<String, String>) { fun showIncoming(ctx: Context, data: Map<String, String>) {
if (AppState.resumed) { if (AppState.resumed) {
Log.d("KometFcm", "call push suppressed (app foreground)") Log.d("QlyraFcm", "call push suppressed (app foreground)")
return return
} }
val name = data["userName"] ?: data["title"] ?: "Неизвестный" val name = data["userName"] ?: data["title"] ?: "Неизвестный"
@@ -82,7 +82,7 @@ object CallNotifier {
val account = data["c"] ?: "" val account = data["c"] ?: ""
val callJson = JSONObject(data as Map<*, *>).toString() val callJson = JSONObject(data as Map<*, *>).toString()
Log.d("KometFcm", "showIncoming caller=$callerId conv=$conversationId keys=${data.keys}") Log.d("QlyraFcm", "showIncoming caller=$callerId conv=$conversationId keys=${data.keys}")
ensureChannel(ctx) ensureChannel(ctx)
@@ -117,7 +117,7 @@ object CallNotifier {
} }
fun finishCall(ctx: Context, data: Map<String, String>) { fun finishCall(ctx: Context, data: Map<String, String>) {
Log.d("KometFcm", "finishCall keys=${data.keys}") Log.d("QlyraFcm", "finishCall keys=${data.keys}")
CallRinger.stop() CallRinger.stop()
NotificationManagerCompat.from(ctx).cancel(CallConst.NOTIF_ID) NotificationManagerCompat.from(ctx).cancel(CallConst.NOTIF_ID)
CallEvents.emit("ended") CallEvents.emit("ended")
@@ -208,7 +208,7 @@ object CallRinger {
activeConversationId = conversationId activeConversationId = conversationId
val power = ctx.getSystemService(Context.POWER_SERVICE) as PowerManager val power = ctx.getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock = power.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "komet:call").apply { wakeLock = power.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "qlyra:call").apply {
setReferenceCounted(false) setReferenceCounted(false)
acquire(60_000L) acquire(60_000L)
} }
@@ -271,7 +271,7 @@ object CallRinger {
rt.play() rt.play()
ringtone = rt ringtone = rt
} catch (e: Exception) { } catch (e: Exception) {
Log.w("KometFcm", "ringtone failed: ${e.message}") Log.w("QlyraFcm", "ringtone failed: ${e.message}")
} }
} }
@@ -288,7 +288,7 @@ object CallRinger {
} }
vibrator = vib vibrator = vib
} catch (e: Exception) { } catch (e: Exception) {
Log.w("KometFcm", "vibrate failed: ${e.message}") Log.w("QlyraFcm", "vibrate failed: ${e.message}")
} }
} }
} }
@@ -315,7 +315,7 @@ class CallActionReceiver : BroadcastReceiver() {
try { try {
ctx.sendBroadcast(fln) ctx.sendBroadcast(fln)
} catch (e: Exception) { } catch (e: Exception) {
Log.w("KometFcm", "decline broadcast failed: ${e.message}") Log.w("QlyraFcm", "decline broadcast failed: ${e.message}")
} }
} }
} }
@@ -1,10 +1,10 @@
package ru.komet.app package ru.qlyra.app
import android.content.Intent import android.content.Intent
import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.EventChannel
object ChatNotifications { object ChatNotifications {
const val EXTRA_CHAT = "komet_chat" const val EXTRA_CHAT = "qlyra_chat"
@Volatile @Volatile
var activeChatId: Long = 0L var activeChatId: Long = 0L
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.Manifest import android.Manifest
import android.app.Activity import android.app.Activity
@@ -20,7 +20,7 @@ import io.flutter.plugin.common.MethodChannel
import java.util.concurrent.Executors import java.util.concurrent.Executors
object FkmChannel { object FkmChannel {
private const val NAME = "ru.komet.app/fkm" private const val NAME = "ru.qlyra.app/fkm"
const val NOTIF_PERMS_REQUEST = 7713 const val NOTIF_PERMS_REQUEST = 7713
private val main = Handler(Looper.getMainLooper()) private val main = Handler(Looper.getMainLooper())
@@ -117,7 +117,7 @@ object FkmChannel {
val data = call.argument<Map<String, String>>("data") ?: return false val data = call.argument<Map<String, String>>("data") ?: return false
worker.execute { worker.execute {
try { try {
KometNotifier(ctx).handle(data) QlyraNotifier(ctx).handle(data)
FkmState.countDelivered(ctx) FkmState.countDelivered(ctx)
FkmService.refresh(ctx) FkmService.refresh(ctx)
} catch (e: Exception) { } catch (e: Exception) {
@@ -132,12 +132,12 @@ object FkmChannel {
ctx: Context, ctx: Context,
call: MethodCall, call: MethodCall,
tag: String, tag: String,
action: (KometNotifier, Map<String, String>) -> Unit, action: (QlyraNotifier, Map<String, String>) -> Unit,
): Boolean { ): Boolean {
val data = call.argument<Map<String, String>>("data") ?: return false val data = call.argument<Map<String, String>>("data") ?: return false
worker.execute { worker.execute {
try { try {
action(KometNotifier(ctx), data) action(QlyraNotifier(ctx), data)
} catch (e: Exception) { } catch (e: Exception) {
Log.w("Fkm", "$tag failed: ${e.message}") Log.w("Fkm", "$tag failed: ${e.message}")
} }
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.app.Notification import android.app.Notification
import android.app.NotificationChannel import android.app.NotificationChannel
@@ -15,7 +15,7 @@ import android.util.Log
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
object FkmState { object FkmState {
private const val PREFS = "komet_fkm" private const val PREFS = "qlyra_fkm"
private const val KEY_ENABLED = "enabled" private const val KEY_ENABLED = "enabled"
private const val KEY_DELIVERED = "delivered" private const val KEY_DELIVERED = "delivered"
@@ -60,7 +60,7 @@ object FkmState {
} }
object FkmNotification { object FkmNotification {
const val CHANNEL_ID = "komet_fkm" const val CHANNEL_ID = "qlyra_fkm"
const val NOTIFICATION_ID = 424244 const val NOTIFICATION_ID = 424244
fun build(ctx: Context): Notification { fun build(ctx: Context): Notification {
@@ -228,7 +228,7 @@ class FkmService : Service() {
class FkmDisableReceiver : BroadcastReceiver() { class FkmDisableReceiver : BroadcastReceiver() {
companion object { companion object {
const val ACTION_DISABLE = "ru.komet.app.FKM_DISABLE" const val ACTION_DISABLE = "ru.qlyra.app.FKM_DISABLE"
} }
override fun onReceive(ctx: Context, intent: Intent) { override fun onReceive(ctx: Context, intent: Intent) {
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.Manifest import android.Manifest
import android.app.KeyguardManager import android.app.KeyguardManager
@@ -52,7 +52,7 @@ import java.util.concurrent.atomic.AtomicBoolean
class MainActivity : FlutterActivity() { class MainActivity : FlutterActivity() {
private val channelName = "ru.komet.app/vpn_bypass" private val channelName = "ru.qlyra.app/vpn_bypass"
private val iconPackage = MainActivity::class.java.name.substringBeforeLast('.') private val iconPackage = MainActivity::class.java.name.substringBeforeLast('.')
private val iconComponents = mapOf( private val iconComponents = mapOf(
"MainActivity" to "$iconPackage.MainActivity", "MainActivity" to "$iconPackage.MainActivity",
@@ -89,7 +89,7 @@ class MainActivity : FlutterActivity() {
const val LOG_TAG = "VpnBypass" const val LOG_TAG = "VpnBypass"
const val SHARE_TAG = "ShareIntake" const val SHARE_TAG = "ShareIntake"
const val NFC_TAG = "NfcExchange" const val NFC_TAG = "NfcExchange"
const val KEEP_ENGINE_ID = "komet_keep_engine" const val KEEP_ENGINE_ID = "qlyra_keep_engine"
const val NFC_PHASE_MIN_MS = 350L const val NFC_PHASE_MIN_MS = 350L
const val NFC_PHASE_JITTER_MS = 400 const val NFC_PHASE_JITTER_MS = 400
const val BLE_PERMS_REQUEST = 7711 const val BLE_PERMS_REQUEST = 7711
@@ -126,7 +126,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/nfc", "ru.qlyra.app/nfc",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"status" -> result.success(nfcStatus()) "status" -> result.success(nfcStatus())
@@ -150,7 +150,7 @@ class MainActivity : FlutterActivity() {
EventChannel( EventChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/nfc_events", "ru.qlyra.app/nfc_events",
).setStreamHandler(object : EventChannel.StreamHandler { ).setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
nfcEvents = events nfcEvents = events
@@ -175,7 +175,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/app_icon", "ru.qlyra.app/app_icon",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"setAppIcon" -> { "setAppIcon" -> {
@@ -197,7 +197,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/upload_service", "ru.qlyra.app/upload_service",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
val ctx = this val ctx = this
fun uploadIntent(call: MethodCall, action: String) = fun uploadIntent(call: MethodCall, action: String) =
@@ -248,7 +248,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/video_note", "ru.qlyra.app/video_note",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"permission" -> requestNotePermissions(result) "permission" -> requestNotePermissions(result)
@@ -287,7 +287,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/video", "ru.qlyra.app/video",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"cropSquare" -> { "cropSquare" -> {
@@ -332,7 +332,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/calls", "ru.qlyra.app/calls",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"consumeInitialCall" -> { "consumeInitialCall" -> {
@@ -393,7 +393,7 @@ class MainActivity : FlutterActivity() {
), ),
) )
} catch (e: Exception) { } catch (e: Exception) {
Log.w("KometFcm", "open FSI settings failed: ${e.message}") Log.w("QlyraFcm", "open FSI settings failed: ${e.message}")
} }
} }
result.success(null) result.success(null)
@@ -404,7 +404,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/screen", "ru.qlyra.app/screen",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"setKeepAwake" -> { "setKeepAwake" -> {
@@ -417,7 +417,7 @@ class MainActivity : FlutterActivity() {
EventChannel( EventChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/calls_events", "ru.qlyra.app/calls_events",
).setStreamHandler(object : EventChannel.StreamHandler { ).setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
CallEvents.sink = events CallEvents.sink = events
@@ -430,7 +430,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/notifications", "ru.qlyra.app/notifications",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"consumeInitialChat" -> { "consumeInitialChat" -> {
@@ -453,7 +453,7 @@ class MainActivity : FlutterActivity() {
EventChannel( EventChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/notification_events", "ru.qlyra.app/notification_events",
).setStreamHandler(object : EventChannel.StreamHandler { ).setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
ChatNotifications.sink = events ChatNotifications.sink = events
@@ -466,7 +466,7 @@ class MainActivity : FlutterActivity() {
MethodChannel( MethodChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/share", "ru.qlyra.app/share",
).setMethodCallHandler { call, result -> ).setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"consumeInitialShare" -> { "consumeInitialShare" -> {
@@ -501,7 +501,7 @@ class MainActivity : FlutterActivity() {
EventChannel( EventChannel(
flutterEngine.dartExecutor.binaryMessenger, flutterEngine.dartExecutor.binaryMessenger,
"ru.komet.app/share_events", "ru.qlyra.app/share_events",
).setStreamHandler(object : EventChannel.StreamHandler { ).setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
ShareIntake.sink = events ShareIntake.sink = events
@@ -965,7 +965,7 @@ class MainActivity : FlutterActivity() {
override fun onDestroy() { override fun onDestroy() {
shareExecutor.shutdown() shareExecutor.shutdown()
if (keepEngineAlive() && isFinishing) { if (keepEngineAlive() && isFinishing) {
Log.d("KometFcm", "task removed, caching engine (call=${CallState.inCall} fkm=${FkmState.enabled})") Log.d("QlyraFcm", "task removed, caching engine (call=${CallState.inCall} fkm=${FkmState.enabled})")
flutterEngine?.let { FlutterEngineCache.getInstance().put(KEEP_ENGINE_ID, it) } flutterEngine?.let { FlutterEngineCache.getInstance().put(KEEP_ENGINE_ID, it) }
} }
super.onDestroy() super.onDestroy()
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
object NfcExchange { object NfcExchange {
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.nfc.cardemulation.HostApduService import android.nfc.cardemulation.HostApduService
import android.os.Bundle import android.os.Bundle
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
@@ -26,29 +26,29 @@ import com.google.firebase.messaging.RemoteMessage
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
class KometFcmService : FirebaseMessagingService() { class QlyraFcmService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) { override fun onMessageReceived(message: RemoteMessage) {
val data = message.data val data = message.data
Log.d("KometFcm", "onMessageReceived type=${data["type"]} keys=${data.keys}") Log.d("QlyraFcm", "onMessageReceived type=${data["type"]} keys=${data.keys}")
if (data.isEmpty()) return if (data.isEmpty()) return
val type = data["type"] val type = data["type"]
FkmState.restore(applicationContext) FkmState.restore(applicationContext)
if (FkmState.enabled && type != "InboundCall" && type != "CallFinished") { if (FkmState.enabled && type != "InboundCall" && type != "CallFinished") {
Log.d("KometFcm", "message push dropped: FKM handles messages") Log.d("QlyraFcm", "message push dropped: FKM handles messages")
return return
} }
KometNotifier(applicationContext).handle(data) QlyraNotifier(applicationContext).handle(data)
} }
} }
class KometNotifier(private val ctx: Context) { class QlyraNotifier(private val ctx: Context) {
companion object { companion object {
private const val CHANNEL_ID = "komet_messages" private const val CHANNEL_ID = "qlyra_messages"
private const val CHANNEL_NAME = "Сообщения" private const val CHANNEL_NAME = "Сообщения"
private const val GROUP_KEY = "komet_messages_group" private const val GROUP_KEY = "qlyra_messages_group"
private const val SUMMARY_ID = 424200 private const val SUMMARY_ID = 424200
private const val PREFS = "komet_push" private const val PREFS = "qlyra_push"
private const val FLN_RECEIVER = private const val FLN_RECEIVER =
"com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" "com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver"
private const val FLN_ACTION_TAPPED = private const val FLN_ACTION_TAPPED =
@@ -336,7 +336,7 @@ class KometNotifier(private val ctx: Context) {
.setShowWhen(true) .setShowWhen(true)
.setNumber(entries.size) .setNumber(entries.size)
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN)
.setContentTitle("Komet") .setContentTitle("Qlyra")
.setContentText(boldLine(newest.first, newest.second)) .setContentText(boldLine(newest.first, newest.second))
.setStyle(inbox) .setStyle(inbox)
.build() .build()
@@ -399,7 +399,7 @@ class KometNotifier(private val ctx: Context) {
.build() .build()
ShortcutManagerCompat.pushDynamicShortcut(ctx, shortcut) ShortcutManagerCompat.pushDynamicShortcut(ctx, shortcut)
} catch (e: Exception) { } catch (e: Exception) {
Log.w("KometFcm", "shortcut push failed: $e") Log.w("QlyraFcm", "shortcut push failed: $e")
} }
} }
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.content.ContentResolver import android.content.ContentResolver
import android.content.Context import android.content.Context
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.app.* import android.app.*
import android.content.Intent import android.content.Intent
@@ -11,11 +11,11 @@ import androidx.core.app.NotificationCompat
class UploadForegroundService : Service() { class UploadForegroundService : Service() {
companion object { companion object {
const val CHANNEL_ID = "komet_upload" const val CHANNEL_ID = "qlyra_upload"
const val NOTIFICATION_ID = 9001 const val NOTIFICATION_ID = 9001
const val ACTION_START = "ru.komet.app.UPLOAD_START" const val ACTION_START = "ru.qlyra.app.UPLOAD_START"
const val ACTION_UPDATE = "ru.komet.app.UPLOAD_UPDATE" const val ACTION_UPDATE = "ru.qlyra.app.UPLOAD_UPDATE"
const val ACTION_STOP = "ru.komet.app.UPLOAD_STOP" const val ACTION_STOP = "ru.qlyra.app.UPLOAD_STOP"
const val EXTRA_TITLE = "title" const val EXTRA_TITLE = "title"
const val EXTRA_BODY = "body" const val EXTRA_BODY = "body"
const val EXTRA_PROGRESS = "progress" const val EXTRA_PROGRESS = "progress"
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -1,4 +1,4 @@
package ru.komet.app package ru.qlyra.app
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 49 KiB

@@ -2,7 +2,7 @@
<string name="upload_channel_name">Отправка медиа</string> <string name="upload_channel_name">Отправка медиа</string>
<string name="fkm_channel_name">Сервис уведомлений</string> <string name="fkm_channel_name">Сервис уведомлений</string>
<string name="fkm_channel_description">Держит фоновое соединение с сервером</string> <string name="fkm_channel_description">Держит фоновое соединение с сервером</string>
<string name="fkm_title">Komet · сервис уведомлений</string> <string name="fkm_title">Qlyra · сервис уведомлений</string>
<string name="fkm_status_active">Соединение активно</string> <string name="fkm_status_active">Соединение активно</string>
<string name="fkm_status_inactive">Соединение не активно</string> <string name="fkm_status_inactive">Соединение не активно</string>
<string name="fkm_status_line">%1$s · принято %2$d</string> <string name="fkm_status_line">%1$s · принято %2$d</string>
+3 -3
View File
@@ -1,10 +1,10 @@
<resources> <resources>
<string name="nfc_service_description">Komet contact exchange</string> <string name="nfc_service_description">Qlyra contact exchange</string>
<string name="nfc_aid_group_description">Komet contact exchange</string> <string name="nfc_aid_group_description">Qlyra contact exchange</string>
<string name="upload_channel_name">Sending media</string> <string name="upload_channel_name">Sending media</string>
<string name="fkm_channel_name">Notification service</string> <string name="fkm_channel_name">Notification service</string>
<string name="fkm_channel_description">Keeps the background connection to the server alive</string> <string name="fkm_channel_description">Keeps the background connection to the server alive</string>
<string name="fkm_title">Komet · notification service</string> <string name="fkm_title">Qlyra · notification service</string>
<string name="fkm_status_active">Connection active</string> <string name="fkm_status_active">Connection active</string>
<string name="fkm_status_inactive">Connection inactive</string> <string name="fkm_status_inactive">Connection inactive</string>
<string name="fkm_status_line">%1$s · %2$d delivered</string> <string name="fkm_status_line">%1$s · %2$d delivered</string>
@@ -9,7 +9,7 @@
"client_info": { "client_info": {
"mobilesdk_app_id": "1:659634599081:android:00000000000000000000ab", "mobilesdk_app_id": "1:659634599081:android:00000000000000000000ab",
"android_client_info": { "android_client_info": {
"package_name": "ru.komet.app" "package_name": "ru.qlyra.app"
} }
}, },
"oauth_client": [], "oauth_client": [],
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

@@ -15,7 +15,7 @@
<rect width="1440" height="2280" fill="#F8F4FE"/> <rect width="1440" height="2280" fill="#F8F4FE"/>
<g id="header"> <g id="header">
<text x="64" y="84" class="title" fill="#1B1B21">Komet — Design System</text> <text x="64" y="84" class="title" fill="#1B1B21">Qlyra — Design System</text>
<text x="64" y="112" class="small" fill="#46464F">Seed #C1C4FF · Material 3 Expressive · Inter</text> <text x="64" y="112" class="small" fill="#46464F">Seed #C1C4FF · Material 3 Expressive · Inter</text>
</g> </g>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

+2 -2
View File
@@ -7,7 +7,7 @@ ENV['COCOAPODS_DISABLE_STATS'] = 'true'
require 'json' require 'json'
# Firebase is Android-only: FCM is used solely by the `oneme` flavor, and on # Firebase is Android-only: FCM is used solely by the `oneme` flavor, and on
# iOS there is a single `ru.komet.app` bundle that never initialises push. # iOS there is a single `ru.qlyra.app` bundle that never initialises push.
# Keep the Firebase SDK out of the iOS build entirely so iOS is not forced up # Keep the Firebase SDK out of the iOS build entirely so iOS is not forced up
# to the iOS 15 deployment target that firebase_core's podspec requires. # to the iOS 15 deployment target that firebase_core's podspec requires.
FIREBASE_IOS_PLUGINS = %w[firebase_core firebase_messaging].freeze FIREBASE_IOS_PLUGINS = %w[firebase_core firebase_messaging].freeze
@@ -79,7 +79,7 @@ end
# xcframeworks into the pod target's own build dir, so for Runner that variable # xcframeworks into the pod target's own build dir, so for Runner that variable
# expands to a file nothing ever produces and Xcode fails on the missing input. # expands to a file nothing ever produces and Xcode fails on the missing input.
OPUS_XCFRAMEWORK = 'ogg_opus_player/darwin/Frameworks/libopus.xcframework'.freeze OPUS_XCFRAMEWORK = 'ogg_opus_player/darwin/Frameworks/libopus.xcframework'.freeze
OPUS_LIB_VAR = 'KOMET_OPUS_LIB'.freeze OPUS_LIB_VAR = 'QLYRA_OPUS_LIB'.freeze
OPUS_FORCE_LOAD = %(-force_load "$(#{OPUS_LIB_VAR})").freeze OPUS_FORCE_LOAD = %(-force_load "$(#{OPUS_LIB_VAR})").freeze
OPUS_XCFRAMEWORK_DIR = OPUS_XCFRAMEWORK_DIR =
File.expand_path(File.join('.symlinks', 'plugins', OPUS_XCFRAMEWORK), __dir__).freeze File.expand_path(File.join('.symlinks', 'plugins', OPUS_XCFRAMEWORK), __dir__).freeze
+18 -18
View File
@@ -12,9 +12,9 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
4B1A4BBCD56B3CE42AD0A480 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 789A1AEF2F4FF7DEED202476 /* Pods_Runner.framework */; }; 4B1A4BBCD56B3CE42AD0A480 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 789A1AEF2F4FF7DEED202476 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
AA11BB22CC33DD44EE550101 /* KometVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550001 /* KometVideo.swift */; }; AA11BB22CC33DD44EE550101 /* QlyraVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550001 /* QlyraVideo.swift */; };
AA11BB22CC33DD44EE550102 /* KometVideoNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550002 /* KometVideoNote.swift */; }; AA11BB22CC33DD44EE550102 /* QlyraVideoNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550002 /* QlyraVideoNote.swift */; };
AA11BB22CC33DD44EE550103 /* KometNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550003 /* KometNotifications.swift */; }; AA11BB22CC33DD44EE550103 /* QlyraNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550003 /* QlyraNotifications.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@@ -59,9 +59,9 @@
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
AA11BB22CC33DD44EE550001 /* KometVideo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KometVideo.swift; sourceTree = "<group>"; }; AA11BB22CC33DD44EE550001 /* QlyraVideo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QlyraVideo.swift; sourceTree = "<group>"; };
AA11BB22CC33DD44EE550002 /* KometVideoNote.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KometVideoNote.swift; sourceTree = "<group>"; }; AA11BB22CC33DD44EE550002 /* QlyraVideoNote.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QlyraVideoNote.swift; sourceTree = "<group>"; };
AA11BB22CC33DD44EE550003 /* KometNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KometNotifications.swift; sourceTree = "<group>"; }; AA11BB22CC33DD44EE550003 /* QlyraNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QlyraNotifications.swift; sourceTree = "<group>"; };
AA11BB22CC33DD44EE550004 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; }; AA11BB22CC33DD44EE550004 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
782E66FE4E292DCFD0D1B7D2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; }; 782E66FE4E292DCFD0D1B7D2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
789A1AEF2F4FF7DEED202476 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 789A1AEF2F4FF7DEED202476 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -164,9 +164,9 @@
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
AA11BB22CC33DD44EE550001 /* KometVideo.swift */, AA11BB22CC33DD44EE550001 /* QlyraVideo.swift */,
AA11BB22CC33DD44EE550002 /* KometVideoNote.swift */, AA11BB22CC33DD44EE550002 /* QlyraVideoNote.swift */,
AA11BB22CC33DD44EE550003 /* KometNotifications.swift */, AA11BB22CC33DD44EE550003 /* QlyraNotifications.swift */,
AA11BB22CC33DD44EE550004 /* Runner.entitlements */, AA11BB22CC33DD44EE550004 /* Runner.entitlements */,
); );
path = Runner; path = Runner;
@@ -407,9 +407,9 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
AA11BB22CC33DD44EE550101 /* KometVideo.swift in Sources */, AA11BB22CC33DD44EE550101 /* QlyraVideo.swift in Sources */,
AA11BB22CC33DD44EE550102 /* KometVideoNote.swift in Sources */, AA11BB22CC33DD44EE550102 /* QlyraVideoNote.swift in Sources */,
AA11BB22CC33DD44EE550103 /* KometNotifications.swift in Sources */, AA11BB22CC33DD44EE550103 /* QlyraNotifications.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -510,7 +510,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app; PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -527,7 +527,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -545,7 +545,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -561,7 +561,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -693,7 +693,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app; PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -716,7 +716,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app; PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
+18 -18
View File
@@ -1,7 +1,7 @@
import Flutter import Flutter
import UIKit import UIKit
final class KometStreamHandler: NSObject, FlutterStreamHandler { final class QlyraStreamHandler: NSObject, FlutterStreamHandler {
private let onSink: (FlutterEventSink?) -> Void private let onSink: (FlutterEventSink?) -> Void
init(onSink: @escaping (FlutterEventSink?) -> Void) { init(onSink: @escaping (FlutterEventSink?) -> Void) {
@@ -26,15 +26,15 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate {
private var channels: [FlutterMethodChannel] = [] private var channels: [FlutterMethodChannel] = []
private var eventChannels: [FlutterEventChannel] = [] private var eventChannels: [FlutterEventChannel] = []
private var streamHandlers: [KometStreamHandler] = [] private var streamHandlers: [QlyraStreamHandler] = []
private var videoNote: KometVideoNote? private var videoNote: QlyraVideoNote?
override func application( override func application(
_ application: UIApplication, _ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool { ) -> Bool {
GeneratedPluginRegistrant.register(with: self) GeneratedPluginRegistrant.register(with: self)
KometNotifications.shared.start() QlyraNotifications.shared.start()
if let controller = window?.rootViewController as? FlutterViewController { if let controller = window?.rootViewController as? FlutterViewController {
let messenger = controller.binaryMessenger let messenger = controller.binaryMessenger
@@ -57,7 +57,7 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
private func events(_ name: String, _ messenger: FlutterBinaryMessenger, private func events(_ name: String, _ messenger: FlutterBinaryMessenger,
_ onSink: @escaping (FlutterEventSink?) -> Void) { _ onSink: @escaping (FlutterEventSink?) -> Void) {
let handler = KometStreamHandler(onSink: onSink) let handler = QlyraStreamHandler(onSink: onSink)
let channel = FlutterEventChannel(name: name, binaryMessenger: messenger) let channel = FlutterEventChannel(name: name, binaryMessenger: messenger)
channel.setStreamHandler(handler) channel.setStreamHandler(handler)
streamHandlers.append(handler) streamHandlers.append(handler)
@@ -65,7 +65,7 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
} }
private func registerAppIcon(_ messenger: FlutterBinaryMessenger) { private func registerAppIcon(_ messenger: FlutterBinaryMessenger) {
method("ru.komet.app/app_icon", messenger) { call, result in method("ru.qlyra.app/app_icon", messenger) { call, result in
switch call.method { switch call.method {
case "getAppIcon": case "getAppIcon":
result(UIApplication.shared.alternateIconName) result(UIApplication.shared.alternateIconName)
@@ -100,23 +100,23 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
} }
private func registerVideo(_ messenger: FlutterBinaryMessenger) { private func registerVideo(_ messenger: FlutterBinaryMessenger) {
method("ru.komet.app/video", messenger) { call, result in method("ru.qlyra.app/video", messenger) { call, result in
KometVideo.shared.handle(call, result: result) QlyraVideo.shared.handle(call, result: result)
} }
} }
private func registerVideoNote(_ messenger: FlutterBinaryMessenger) { private func registerVideoNote(_ messenger: FlutterBinaryMessenger) {
guard let textures = registrar(forPlugin: "KometVideoNote")?.textures() else { return } guard let textures = registrar(forPlugin: "QlyraVideoNote")?.textures() else { return }
method("ru.komet.app/video_note", messenger) { [weak self] call, result in method("ru.qlyra.app/video_note", messenger) { [weak self] call, result in
guard let self = self else { return } guard let self = self else { return }
switch call.method { switch call.method {
case "permission": case "permission":
KometVideoNote.requestPermission(result) QlyraVideoNote.requestPermission(result)
case "init": case "init":
let args = call.arguments as? [String: Any] ?? [:] let args = call.arguments as? [String: Any] ?? [:]
self.videoNote?.dispose() self.videoNote?.dispose()
let recorder = KometVideoNote(registry: textures) let recorder = QlyraVideoNote(registry: textures)
self.videoNote = recorder self.videoNote = recorder
recorder.initialize( recorder.initialize(
front: (args["front"] as? NSNumber)?.boolValue ?? true, front: (args["front"] as? NSNumber)?.boolValue ?? true,
@@ -143,7 +143,7 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
} }
private func withRecorder(_ result: @escaping FlutterResult, private func withRecorder(_ result: @escaping FlutterResult,
_ body: (KometVideoNote) -> Void) { _ body: (QlyraVideoNote) -> Void) {
guard let recorder = videoNote else { guard let recorder = videoNote else {
result(FlutterError(code: "NOT_READY", message: "recorder not initialized", details: nil)) result(FlutterError(code: "NOT_READY", message: "recorder not initialized", details: nil))
return return
@@ -152,7 +152,7 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
} }
private func registerScreen(_ messenger: FlutterBinaryMessenger) { private func registerScreen(_ messenger: FlutterBinaryMessenger) {
method("ru.komet.app/screen", messenger) { call, result in method("ru.qlyra.app/screen", messenger) { call, result in
switch call.method { switch call.method {
case "setKeepAwake": case "setKeepAwake":
let enabled = ((call.arguments as? [String: Any])?["enabled"] as? NSNumber)?.boolValue ?? false let enabled = ((call.arguments as? [String: Any])?["enabled"] as? NSNumber)?.boolValue ?? false
@@ -167,11 +167,11 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
} }
private func registerNotifications(_ messenger: FlutterBinaryMessenger) { private func registerNotifications(_ messenger: FlutterBinaryMessenger) {
method("ru.komet.app/notifications", messenger) { call, result in method("ru.qlyra.app/notifications", messenger) { call, result in
KometNotifications.shared.handle(call, result: result) QlyraNotifications.shared.handle(call, result: result)
} }
events("ru.komet.app/notification_events", messenger) { sink in events("ru.qlyra.app/notification_events", messenger) { sink in
KometNotifications.shared.attach(sink) QlyraNotifications.shared.attach(sink)
} }
} }
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 797 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 B

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 32 KiB

+4 -4
View File
@@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Komet</string> <string>Qlyra</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@@ -13,7 +13,7 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Komet</string> <string>Qlyra</string>
<key>CFBundleIcons</key> <key>CFBundleIcons</key>
<dict> <dict>
<key>CFBundleAlternateIcons</key> <key>CFBundleAlternateIcons</key>
@@ -76,10 +76,10 @@
<array> <array>
<dict> <dict>
<key>CFBundleURLName</key> <key>CFBundleURLName</key>
<string>ru.komet.app</string> <string>ru.qlyra.app</string>
<key>CFBundleURLSchemes</key> <key>CFBundleURLSchemes</key>
<array> <array>
<string>komet</string> <string>qlyra</string>
<string>max</string> <string>max</string>
</array> </array>
</dict> </dict>
@@ -2,10 +2,10 @@ import Flutter
import UIKit import UIKit
import UserNotifications import UserNotifications
final class KometNotifications: NSObject { final class QlyraNotifications: NSObject {
static let shared = KometNotifications() static let shared = QlyraNotifications()
private static let chatKeys = ["komet_chat", "chatId", "chat_id"] private static let chatKeys = ["qlyra_chat", "chatId", "chat_id"]
private var sink: FlutterEventSink? private var sink: FlutterEventSink?
private var pendingChatId: Int64 = 0 private var pendingChatId: Int64 = 0
@@ -76,7 +76,7 @@ final class KometNotifications: NSObject {
} }
} }
extension KometNotifications: UNUserNotificationCenterDelegate { extension QlyraNotifications: UNUserNotificationCenterDelegate {
func userNotificationCenter( func userNotificationCenter(
_ center: UNUserNotificationCenter, _ center: UNUserNotificationCenter,
willPresent notification: UNNotification, willPresent notification: UNNotification,
@@ -54,10 +54,10 @@ private struct VideoExportSpec {
} }
} }
final class KometVideo { final class QlyraVideo {
static let shared = KometVideo() static let shared = QlyraVideo()
private let queue = DispatchQueue(label: "ru.komet.app.video", qos: .userInitiated) private let queue = DispatchQueue(label: "ru.qlyra.app.video", qos: .userInitiated)
private var session: AVAssetExportSession? private var session: AVAssetExportSession?
private var cancelled = false private var cancelled = false
@@ -3,7 +3,7 @@ import CoreImage
import Flutter import Flutter
import UIKit import UIKit
final class KometVideoNoteTexture: NSObject, FlutterTexture { final class QlyraVideoNoteTexture: NSObject, FlutterTexture {
private let lock = NSLock() private let lock = NSLock()
private var latest: CVPixelBuffer? private var latest: CVPixelBuffer?
@@ -21,15 +21,15 @@ final class KometVideoNoteTexture: NSObject, FlutterTexture {
} }
} }
final class KometVideoNote: NSObject { final class QlyraVideoNote: NSObject {
private let registry: FlutterTextureRegistry private let registry: FlutterTextureRegistry
private let queue = DispatchQueue(label: "ru.komet.app.videonote", qos: .userInitiated) private let queue = DispatchQueue(label: "ru.qlyra.app.videonote", qos: .userInitiated)
private let ciContext = CIContext(options: [.useSoftwareRenderer: false]) private let ciContext = CIContext(options: [.useSoftwareRenderer: false])
private let session = AVCaptureSession() private let session = AVCaptureSession()
private let videoOutput = AVCaptureVideoDataOutput() private let videoOutput = AVCaptureVideoDataOutput()
private let audioOutput = AVCaptureAudioDataOutput() private let audioOutput = AVCaptureAudioDataOutput()
private let texture = KometVideoNoteTexture() private let texture = QlyraVideoNoteTexture()
private var textureId: Int64 = 0 private var textureId: Int64 = 0
private var deviceInput: AVCaptureDeviceInput? private var deviceInput: AVCaptureDeviceInput?
@@ -207,12 +207,12 @@ final class KometVideoNote: NSObject {
guard let device = AVCaptureDevice.default( guard let device = AVCaptureDevice.default(
.builtInWideAngleCamera, for: .video, position: position) .builtInWideAngleCamera, for: .video, position: position)
?? AVCaptureDevice.default(for: .video) else { ?? AVCaptureDevice.default(for: .video) else {
throw NSError(domain: "KometVideoNote", code: 1, throw NSError(domain: "QlyraVideoNote", code: 1,
userInfo: [NSLocalizedDescriptionKey: "no camera found"]) userInfo: [NSLocalizedDescriptionKey: "no camera found"])
} }
let input = try AVCaptureDeviceInput(device: device) let input = try AVCaptureDeviceInput(device: device)
guard session.canAddInput(input) else { guard session.canAddInput(input) else {
throw NSError(domain: "KometVideoNote", code: 2, throw NSError(domain: "QlyraVideoNote", code: 2,
userInfo: [NSLocalizedDescriptionKey: "camera input rejected"]) userInfo: [NSLocalizedDescriptionKey: "camera input rejected"])
} }
session.addInput(input) session.addInput(input)
@@ -270,7 +270,7 @@ final class KometVideoNote: NSObject {
private func prepareWriter() throws { private func prepareWriter() throws {
let directory = FileManager.default.temporaryDirectory let directory = FileManager.default.temporaryDirectory
let url = directory.appendingPathComponent( let url = directory.appendingPathComponent(
"komet_note_\(Int(Date().timeIntervalSince1970 * 1000)).mp4") "qlyra_note_\(Int(Date().timeIntervalSince1970 * 1000)).mp4")
try? FileManager.default.removeItem(at: url) try? FileManager.default.removeItem(at: url)
let writer = try AVAssetWriter(outputURL: url, fileType: .mp4) let writer = try AVAssetWriter(outputURL: url, fileType: .mp4)
@@ -286,7 +286,7 @@ final class KometVideoNote: NSObject {
let video = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings) let video = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings)
video.expectsMediaDataInRealTime = true video.expectsMediaDataInRealTime = true
guard writer.canAdd(video) else { guard writer.canAdd(video) else {
throw NSError(domain: "KometVideoNote", code: 3, throw NSError(domain: "QlyraVideoNote", code: 3,
userInfo: [NSLocalizedDescriptionKey: "video input rejected"]) userInfo: [NSLocalizedDescriptionKey: "video input rejected"])
} }
writer.add(video) writer.add(video)
@@ -310,7 +310,7 @@ final class KometVideoNote: NSObject {
]) ])
guard writer.startWriting() else { guard writer.startWriting() else {
throw NSError(domain: "KometVideoNote", code: 4, throw NSError(domain: "QlyraVideoNote", code: 4,
userInfo: [NSLocalizedDescriptionKey: "writer refused to start"]) userInfo: [NSLocalizedDescriptionKey: "writer refused to start"])
} }
@@ -363,7 +363,7 @@ final class KometVideoNote: NSObject {
} }
} }
extension KometVideoNote: AVCaptureVideoDataOutputSampleBufferDelegate, extension QlyraVideoNote: AVCaptureVideoDataOutputSampleBufferDelegate,
AVCaptureAudioDataOutputSampleBufferDelegate { AVCaptureAudioDataOutputSampleBufferDelegate {
func captureOutput( func captureOutput(
_ output: AVCaptureOutput, _ output: AVCaptureOutput,
+1 -1
View File
@@ -4,7 +4,7 @@
<dict> <dict>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>
<array> <array>
<string>$(AppIdentifierPrefix)ru.komet.app</string> <string>$(AppIdentifierPrefix)ru.qlyra.app</string>
</array> </array>
</dict> </dict>
</plist> </plist>
+12 -12
View File
@@ -4,13 +4,13 @@ import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter_timezone/flutter_timezone.dart'; import 'package:flutter_timezone/flutter_timezone.dart';
import 'package:kolibri/kolibri.dart'; import 'package:kusoft/kusoft.dart';
import 'package:timezone/data/latest_all.dart' as tz; import 'package:timezone/data/latest_all.dart' as tz;
import '../core/cache/self_presence.dart'; import '../core/cache/self_presence.dart';
import '../core/config/config.dart'; import '../core/config/config.dart';
import '../core/config/countries.dart'; import '../core/config/countries.dart';
import '../core/config/komet_settings.dart'; import '../core/config/qlyra_settings.dart';
import '../core/config/proxy_config.dart'; import '../core/config/proxy_config.dart';
import '../core/protocol/opcode_map.dart'; import '../core/protocol/opcode_map.dart';
import '../core/protocol/packet.dart'; import '../core/protocol/packet.dart';
@@ -27,11 +27,11 @@ enum SessionState { disconnected, connecting, connected, online }
/// Клиент API. /// Клиент API.
/// ///
/// Тонкий адаптер над Rust-ядром [KolibriSession] (пакет kolibri): подключение, /// Тонкий адаптер над Rust-ядром [KusoftSession] (пакет kusoft): подключение,
/// хэндшейк, пинг и реконнект живут в ядре, здесь — оркестрация жизненного цикла /// хэндшейк, пинг и реконнект живут в ядре, здесь — оркестрация жизненного цикла
/// и сохранение прежнего интерфейса для модулей (Packet/пуши/стримы). /// и сохранение прежнего интерфейса для модулей (Packet/пуши/стримы).
class Api { class Api {
KolibriSession? _session; KusoftSession? _session;
/// Роутер пушей (ответы на запросы ядро матчит само, диспетчер держим только /// Роутер пушей (ответы на запросы ядро матчит само, диспетчер держим только
/// ради registerHandler/pushStream). /// ради registerHandler/pushStream).
@@ -60,7 +60,7 @@ class Api {
String? get callsOsVersion => _callsOsVersion; String? get callsOsVersion => _callsOsVersion;
/// Сырой доступ к сессии ядра — для медиа-загрузок (data-plane). /// Сырой доступ к сессии ядра — для медиа-загрузок (data-plane).
KolibriSession? get session => _session; KusoftSession? get session => _session;
String? spoofScope; String? spoofScope;
@@ -284,7 +284,7 @@ class Api {
} }
// Лог запроса/ответа ведётся из wire-лога ядра (_onWireLog) по настоящему // Лог запроса/ответа ведётся из wire-лога ядра (_onWireLog) по настоящему
// проводному seq, поэтому здесь ничего не пишем. // проводному seq, поэтому здесь ничего не пишем.
final KolibriResponse resp = await session final KusoftResponse resp = await session
.requestMapFull(opcode, Map<String, dynamic>.from(payload)) .requestMapFull(opcode, Map<String, dynamic>.from(payload))
.timeout( .timeout(
ServerConfig.requestTimeout, ServerConfig.requestTimeout,
@@ -368,7 +368,7 @@ class Api {
/// Строит устройство-поля и создаёт сессию ядра. Заодно заполняет /// Строит устройство-поля и создаёт сессию ядра. Заодно заполняет
/// [_userAgent] и [_deviceId] для геттеров. /// [_userAgent] и [_deviceId] для геттеров.
Future<(KolibriSession, Stream<WireLogEvent>)> _buildSessionOptions( Future<(KusoftSession, Stream<WireLogEvent>)> _buildSessionOptions(
({String host, int port, bool trustMincifryCa}) endpoint, ({String host, int port, bool trustMincifryCa}) endpoint,
) async { ) async {
final deviceInfo = DeviceInfoPlugin(); final deviceInfo = DeviceInfoPlugin();
@@ -513,7 +513,7 @@ class Api {
deviceLocale: deviceLocale, deviceLocale: deviceLocale,
clientSessionId: clientSessionId, clientSessionId: clientSessionId,
pingIntervalSecs: ServerConfig.pingInterval.inSeconds, pingIntervalSecs: ServerConfig.pingInterval.inSeconds,
pingInteractive: !KometSettings.ghostMode.value, pingInteractive: !QlyraSettings.ghostMode.value,
autoReconnect: false, autoReconnect: false,
insecureTls: insecureTls, insecureTls: insecureTls,
proxy: proxy, proxy: proxy,
@@ -665,7 +665,7 @@ class Api {
try { try {
await session await session
.requestMapFull(Opcode.ping, { .requestMapFull(Opcode.ping, {
'interactive': !KometSettings.ghostMode.value, 'interactive': !QlyraSettings.ghostMode.value,
}) })
.timeout(const Duration(seconds: 6)); .timeout(const Duration(seconds: 6));
} catch (_) { } catch (_) {
@@ -720,7 +720,7 @@ class Api {
/// синхронизация interactive-флага пинга и присутствия. /// синхронизация interactive-флага пинга и присутствия.
void _startLiveness() { void _startLiveness() {
_livenessTimer?.cancel(); _livenessTimer?.cancel();
_lastInteractive = !KometSettings.ghostMode.value; _lastInteractive = !QlyraSettings.ghostMode.value;
_livenessTimer = Timer.periodic(_livenessInterval, (_) => _tickLiveness()); _livenessTimer = Timer.periodic(_livenessInterval, (_) => _tickLiveness());
} }
@@ -729,11 +729,11 @@ class Api {
if (session == null || _sessionState != SessionState.online) return; if (session == null || _sessionState != SessionState.online) return;
final st = session.state(); final st = session.state();
if (st != 'online' && st != 'connected') { if (st != 'online' && st != 'connected') {
logger.w('kolibri сессия "$st" — реконнект'); logger.w('kusoft сессия "$st" — реконнект');
_onDisconnected(); _onDisconnected();
return; return;
} }
final interactive = !KometSettings.ghostMode.value; final interactive = !QlyraSettings.ghostMode.value;
if (interactive != _lastInteractive) { if (interactive != _lastInteractive) {
_lastInteractive = interactive; _lastInteractive = interactive;
try { try {
+11 -5
View File
@@ -3,7 +3,7 @@ import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import '../api.dart'; import '../api.dart';
import '../../core/config/debug_test.dart'; import '../../core/config/debug_test.dart';
import '../../core/config/komet_settings.dart'; import '../../core/config/qlyra_settings.dart';
import '../../core/protocol/chat_cache_fingerprint.dart'; import '../../core/protocol/chat_cache_fingerprint.dart';
import '../../core/protocol/opcode_map.dart'; import '../../core/protocol/opcode_map.dart';
import '../../core/protocol/packet.dart'; import '../../core/protocol/packet.dart';
@@ -534,7 +534,7 @@ class AccountModule {
}) { }) {
final payload = <dynamic, dynamic>{ final payload = <dynamic, dynamic>{
'token': token, 'token': token,
'interactive': interactive ?? !KometSettings.ghostMode.value, 'interactive': interactive ?? !QlyraSettings.ghostMode.value,
'exp': { 'exp': {
'chatsCountGroups': Uint8List.fromList([0x0b, 0x32]), 'chatsCountGroups': Uint8List.fromList([0x0b, 0x32]),
}, },
@@ -645,7 +645,9 @@ class AccountModule {
Future<ProfileData> _resurrectProfile(int accountId) async { Future<ProfileData> _resurrectProfile(int accountId) async {
if (DebugTest.berserk) { if (DebugTest.berserk) {
await AppDatabase.deleteAccount(accountId); await AppDatabase.deleteAccount(accountId);
logger.w('login: [BERSERK] профиль удалён из БД, форсирую регенерацию (id=$accountId)'); logger.w(
'login: [BERSERK] профиль удалён из БД, форсирую регенерацию (id=$accountId)',
);
} else { } else {
final cached = await AppDatabase.loadProfile(accountId); final cached = await AppDatabase.loadProfile(accountId);
if (cached != null) return cached; if (cached != null) return cached;
@@ -656,11 +658,15 @@ class AccountModule {
try { try {
final fetched = await ContactsModule.fetchSelfProfile(_api, accountId); final fetched = await ContactsModule.fetchSelfProfile(_api, accountId);
if (fetched != null) { if (fetched != null) {
logger.i('login: профиль восстановлен через CONTACT_INFO (id=$accountId)'); logger.i(
'login: профиль восстановлен через CONTACT_INFO (id=$accountId)',
);
return fetched; return fetched;
} }
} catch (e) { } catch (e) {
logger.w('login: восстановление профиля через CONTACT_INFO не удалось: $e'); logger.w(
'login: восстановление профиля через CONTACT_INFO не удалось: $e',
);
} }
logger.w('login: профиль недоступен, использую заглушку (id=$accountId)'); logger.w('login: профиль недоступен, использую заглушку (id=$accountId)');
+1 -1
View File
@@ -20,7 +20,7 @@ class AnimojiModule {
'😍', '😍',
]; ];
static const String _recentsKey = 'komet_recent_animoji'; static const String _recentsKey = 'qlyra_recent_animoji';
static const int _maxRecents = 24; static const int _maxRecents = 24;
final Map<int, Animoji> _byId = {}; final Map<int, Animoji> _byId = {};
+8 -7
View File
@@ -266,13 +266,14 @@ int? _otherParticipantId(dynamic participants, int currentUserId) {
String? _nameFromContact(Map<dynamic, dynamic> contact) { String? _nameFromContact(Map<dynamic, dynamic> contact) {
final names = contact['names']; final names = contact['names'];
if (names is! List || names.isEmpty) return null; if (names is! List || names.isEmpty) return null;
final nameRaw = names.firstWhere( Map<dynamic, dynamic>? fallback;
(n) => n is Map && n['type'] == 'ONEME', for (final entry in names) {
orElse: () => names.firstWhere((n) => n is Map, orElse: () => null), if (entry is! Map) continue;
); final name = entry.cast<dynamic, dynamic>();
if (nameRaw is! Map) return null; fallback ??= name;
final name = nameRaw; if (name['type'] == 'ONEME') return name['name'] as String?;
return name['name'] as String?; }
return fallback?['name'] as String?;
} }
List<ChatSearchHit> parseSearchResult(dynamic payload) { List<ChatSearchHit> parseSearchResult(dynamic payload) {
+7 -7
View File
@@ -3,7 +3,7 @@ import 'dart:convert';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import '../../core/config/komet_settings.dart'; import '../../core/config/qlyra_settings.dart';
import '../../core/protocol/opcode_map.dart'; import '../../core/protocol/opcode_map.dart';
import '../../core/protocol/packet.dart'; import '../../core/protocol/packet.dart';
import '../../core/cache/info_cache.dart'; import '../../core/cache/info_cache.dart';
@@ -446,7 +446,7 @@ class ChatsModule {
/// Sentinel в `lastMsgText` когда последнее сообщение в чате удалено, /// Sentinel в `lastMsgText` когда последнее сообщение в чате удалено,
/// а кеша истории нет — UI должен отрисовать курсивную плашку. /// а кеша истории нет — UI должен отрисовать курсивную плашку.
static const String lastMsgPlaceholder = '__komet_lastmsg_placeholder__'; static const String lastMsgPlaceholder = '__qlyra_lastmsg_placeholder__';
ChatsModule._(); ChatsModule._();
@@ -472,7 +472,7 @@ class ChatsModule {
if ((row['unread_count'] as int? ?? 0) == 0) return; if ((row['unread_count'] as int? ?? 0) == 0) return;
final msgIdNum = int.tryParse(messageId); final msgIdNum = int.tryParse(messageId);
if (msgIdNum != null && !KometSettings.antiRead.value) { if (msgIdNum != null && !QlyraSettings.antiRead.value) {
try { try {
await api.sendRequest(Opcode.chatMark, { await api.sendRequest(Opcode.chatMark, {
'type': 'READ_MESSAGE', 'type': 'READ_MESSAGE',
@@ -501,7 +501,7 @@ class ChatsModule {
required int remaining, required int remaining,
}) async { }) async {
final msgIdNum = int.tryParse(messageId); final msgIdNum = int.tryParse(messageId);
if (msgIdNum != null && !KometSettings.antiRead.value) { if (msgIdNum != null && !QlyraSettings.antiRead.value) {
try { try {
await api.sendRequest(Opcode.chatMark, { await api.sendRequest(Opcode.chatMark, {
'type': 'READ_MESSAGE', 'type': 'READ_MESSAGE',
@@ -737,7 +737,7 @@ class ChatsModule {
} }
if (chatId == null) return; if (chatId == null) return;
final keepDeleted = KometSettings.viewDeleted.value; final keepDeleted = QlyraSettings.viewDeleted.value;
final ids = payload['messageIds']; final ids = payload['messageIds'];
if (ids is List) { if (ids is List) {
for (final raw in ids) { for (final raw in ids) {
@@ -803,7 +803,7 @@ class ChatsModule {
} }
if (status == 'REMOVED' && msgIdStr != null) { if (status == 'REMOVED' && msgIdStr != null) {
final keepDeleted = KometSettings.viewDeleted.value; final keepDeleted = QlyraSettings.viewDeleted.value;
if (keepDeleted) { if (keepDeleted) {
await AppDatabase.markMessageDeleted(accountId, chatId, msgIdStr); await AppDatabase.markMessageDeleted(accountId, chatId, msgIdStr);
} else { } else {
@@ -847,7 +847,7 @@ class ChatsModule {
mergedPayload[entry.key.toString()] = entry.value; mergedPayload[entry.key.toString()] = entry.value;
} }
final newRow = Map<String, dynamic>.from(existing); final newRow = Map<String, dynamic>.from(existing);
if (KometSettings.viewRedacted.value) { if (QlyraSettings.viewRedacted.value) {
final oldText = existing['text']?.toString(); final oldText = existing['text']?.toString();
if ((oldText ?? '') != (msgText ?? '') && if ((oldText ?? '') != (msgText ?? '') &&
oldText != null && oldText != null &&
+3 -6
View File
@@ -11,11 +11,7 @@ class CommentsInfo {
final String postId; final String postId;
final int? totalCount; final int? totalCount;
final int? updatedAt; final int? updatedAt;
const CommentsInfo({ const CommentsInfo({required this.postId, this.totalCount, this.updatedAt});
required this.postId,
this.totalCount,
this.updatedAt,
});
factory CommentsInfo.fromPayload(String postId, Map payload) { factory CommentsInfo.fromPayload(String postId, Map payload) {
final raw = payload['totalCount']; final raw = payload['totalCount'];
@@ -98,7 +94,8 @@ class CommentsModule {
final link = msg['link']; final link = msg['link'];
final postId = final postId =
(payload['postId'] ?? (link is Map ? link['postId'] : null) ?? (payload['postId'] ??
(link is Map ? link['postId'] : null) ??
msg['postId']) msg['postId'])
?.toString(); ?.toString();
if (postId == null || postId.isEmpty) return; if (postId == null || postId.isEmpty) return;
+1 -1
View File
@@ -577,7 +577,7 @@ class ContactsModule {
firstName: '$first ${i + 1}', firstName: '$first ${i + 1}',
lastName: last, lastName: last,
phone: 79000000000 + i, phone: 79000000000 + i,
baseUrl: 'https://i.pravatar.cc/150?u=komet_debug_$i', baseUrl: 'https://i.pravatar.cc/150?u=qlyra_debug_$i',
updateTime: 1, updateTime: 1,
options: i % 6 == 0 ? const {'OFFICIAL'} : const {}, options: i % 6 == 0 ? const {'OFFICIAL'} : const {},
), ),
+31 -35
View File
@@ -3,7 +3,7 @@ import 'dart:convert' show jsonDecode, utf8;
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:kolibri/kolibri.dart' as kb; import 'package:kusoft/kusoft.dart' as kb;
import '../api.dart'; import '../api.dart';
import '../../core/protocol/opcode_map.dart'; import '../../core/protocol/opcode_map.dart';
@@ -47,7 +47,7 @@ class UploadError extends UploadEvent {
} }
/// Оркестратор медиа-загрузок: control-plane (URL, отправка сообщения) идёт /// Оркестратор медиа-загрузок: control-plane (URL, отправка сообщения) идёт
/// обычными опкодами, data-plane (заливка на CDN) — через Rust-ядро kolibri, /// обычными опкодами, data-plane (заливка на CDN) — через Rust-ядро kusoft,
/// которое стримит файл с диска (не держит его целиком в памяти). /// которое стримит файл с диска (не держит его целиком в памяти).
class FileUploader { class FileUploader {
final Api api; final Api api;
@@ -101,39 +101,35 @@ class FileUploader {
var status = 0; var status = 0;
String? error; String? error;
final done = Completer<void>(); final done = Completer<void>();
sub = sub = session
session .uploadFilePath(
.uploadFilePath( url: info.url,
url: info.url, path: file.path,
path: file.path, filename: filename,
filename: filename, connection: 'close',
connection: 'close', )
) .listen(
.listen( (e) {
(e) { switch (e) {
switch (e) { case kb.UploadEvent_Progress(:final sent, :final total):
case kb.UploadEvent_Progress(:final sent, :final total): ctrl.add(
ctrl.add( UploadProgress(sent: sent.toInt(), total: total.toInt()),
UploadProgress( );
sent: sent.toInt(), case kb.UploadEvent_Done(status: final s):
total: total.toInt(), status = s;
), case kb.UploadEvent_Error(:final message):
); error = message;
case kb.UploadEvent_Done(status: final s): }
status = s; },
case kb.UploadEvent_Error(:final message): onError: (Object err) {
error = message; error = err.toString();
} if (!done.isCompleted) done.complete();
}, },
onError: (Object err) { onDone: () {
error = err.toString(); if (!done.isCompleted) done.complete();
if (!done.isCompleted) done.complete(); },
}, cancelOnError: true,
onDone: () { );
if (!done.isCompleted) done.complete();
},
cancelOnError: true,
);
await done.future; await done.future;
if (cancelled) return; if (cancelled) return;
if (error != null) { if (error != null) {
+2 -2
View File
@@ -3,7 +3,7 @@ import 'dart:convert';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../api.dart'; import '../api.dart';
import '../../core/config/komet_settings.dart'; import '../../core/config/qlyra_settings.dart';
import '../../core/contacts/device_contacts_service.dart'; import '../../core/contacts/device_contacts_service.dart';
import '../../core/protocol/opcode_map.dart'; import '../../core/protocol/opcode_map.dart';
import '../../core/protocol/packet.dart'; import '../../core/protocol/packet.dart';
@@ -737,7 +737,7 @@ class MessagesModule {
} }
} }
final toSave = KometSettings.viewRedacted.value && results.isNotEmpty final toSave = QlyraSettings.viewRedacted.value && results.isNotEmpty
? await _mergeEditHistory(accountId, chatId, results) ? await _mergeEditHistory(accountId, chatId, results)
: results; : results;
+2 -2
View File
@@ -2,7 +2,7 @@ import 'dart:async';
import '../../core/cache/info_cache.dart'; import '../../core/cache/info_cache.dart';
import '../../core/cache/self_presence.dart'; import '../../core/cache/self_presence.dart';
import '../../core/config/komet_settings.dart'; import '../../core/config/qlyra_settings.dart';
import '../../core/storage/token_storage.dart'; import '../../core/storage/token_storage.dart';
import '../../core/utils/logger.dart'; import '../../core/utils/logger.dart';
import '../api.dart'; import '../api.dart';
@@ -40,7 +40,7 @@ class SelfCheckService {
Future<void> _check() async { Future<void> _check() async {
final api = _api; final api = _api;
if (api == null || api.state != SessionState.online) return; if (api == null || api.state != SessionState.online) return;
if (!KometSettings.selfOnlineCheck.value) return; if (!QlyraSettings.selfOnlineCheck.value) return;
final accountId = await TokenStorage.getActiveAccountId(); final accountId = await TokenStorage.getActiveAccountId();
if (accountId == null) return; if (accountId == null) return;
final presence = await PresenceFetch.get(accountId, forceRefresh: true); final presence = await PresenceFetch.get(accountId, forceRefresh: true);
+4 -7
View File
@@ -45,9 +45,7 @@ class StoriesModule {
int _nowMs() => DateTime.now().millisecondsSinceEpoch; int _nowMs() => DateTime.now().millisecondsSinceEpoch;
int _normMs(int t) => t <= 0 int _normMs(int t) => t <= 0 ? 0 : (t < 1000000000000 ? t * 1000 : t);
? 0
: (t < 1000000000000 ? t * 1000 : t);
// ── Кэш (SQLite) ─────────────────────────────────────────────────────── // ── Кэш (SQLite) ───────────────────────────────────────────────────────
@@ -196,9 +194,7 @@ class StoriesModule {
final chunk = missing.sublist(i, end); final chunk = missing.sublist(i, end);
try { try {
final packet = await _api.sendRequest(Opcode.storiesGetByOwner, { final packet = await _api.sendRequest(Opcode.storiesGetByOwner, {
'owners': [ 'owners': [for (final id in chunk) StoryOwner(ownerId: id).toMap()],
for (final id in chunk) StoryOwner(ownerId: id).toMap(),
],
}, silent: true); }, silent: true);
if (packet.isError) continue; if (packet.isError) continue;
if (_applyOwnerPayload(packet.payload, chunk)) changed = true; if (_applyOwnerPayload(packet.payload, chunk)) changed = true;
@@ -230,7 +226,8 @@ class StoriesModule {
} }
} }
for (final id in requested) { for (final id in requested) {
if (!seen.contains(id) && _peerPreviews.remove(id) != null) changed = true; if (!seen.contains(id) && _peerPreviews.remove(id) != null)
changed = true;
} }
final rawPeers = data['peerStories']; final rawPeers = data['peerStories'];
if (rawPeers is List) { if (rawPeers is List) {
@@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import '../../l10n/app_localizations.dart'; import '../../l10n/app_localizations.dart';
import '../../main.dart' show KometApp; import '../../main.dart' show QlyraApp;
enum UploadKind { photo, video, videoNote, voice, file } enum UploadKind { photo, video, videoNote, voice, file }
@@ -53,7 +53,7 @@ class _NotificationJob {
class UploadNotificationService { class UploadNotificationService {
static const MethodChannel _channel = MethodChannel( static const MethodChannel _channel = MethodChannel(
'ru.komet.app/upload_service', 'ru.qlyra.app/upload_service',
); );
static const int _minIntervalMs = 350; static const int _minIntervalMs = 350;
static const Duration _startDelay = Duration(milliseconds: 700); static const Duration _startDelay = Duration(milliseconds: 700);
@@ -189,7 +189,7 @@ class UploadNotificationService {
} }
static AppLocalizations _localizations() { static AppLocalizations _localizations() {
final context = KometApp.navigatorKey.currentContext; final context = QlyraApp.navigatorKey.currentContext;
if (context != null) { if (context != null) {
final scoped = Localizations.of<AppLocalizations>( final scoped = Localizations.of<AppLocalizations>(
context, context,
+3 -1
View File
@@ -91,7 +91,9 @@ class WebAppModule {
throw const WebAppUnavailable('Нет соединения с сервером'); throw const WebAppUnavailable('Нет соединения с сервером');
} }
final normalizedStartParam = final normalizedStartParam =
(startParam != null && startParam.trim().isNotEmpty) ? startParam : null; (startParam != null && startParam.trim().isNotEmpty)
? startParam
: null;
final packet = await _api.sendRequest(Opcode.webAppInitData, { final packet = await _api.sendRequest(Opcode.webAppInitData, {
'botId': botId, 'botId': botId,
'startParam': ?normalizedStartParam, 'startParam': ?normalizedStartParam,
+1 -2
View File
@@ -4,8 +4,7 @@ class SelfPresence {
static final ValueNotifier<bool> isOnline = ValueNotifier(true); static final ValueNotifier<bool> isOnline = ValueNotifier(true);
static final ValueNotifier<int?> lastSeenSeconds = ValueNotifier(null); static final ValueNotifier<int?> lastSeenSeconds = ValueNotifier(null);
static int get _nowSeconds => static int get _nowSeconds => DateTime.now().millisecondsSinceEpoch ~/ 1000;
DateTime.now().millisecondsSinceEpoch ~/ 1000;
static void markOnline() { static void markOnline() {
isOnline.value = true; isOnline.value = true;
+2 -2
View File
@@ -11,8 +11,8 @@ class CallBridge {
CallBridge._(); CallBridge._();
static final CallBridge instance = CallBridge._(); static final CallBridge instance = CallBridge._();
static const _method = MethodChannel('ru.komet.app/calls'); static const _method = MethodChannel('ru.qlyra.app/calls');
static const _events = EventChannel('ru.komet.app/calls_events'); static const _events = EventChannel('ru.qlyra.app/calls_events');
bool _started = false; bool _started = false;

Some files were not shown because too many files have changed in this diff Show More