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
@@ -42,6 +42,6 @@
|
||||
## Проверка
|
||||
|
||||
- [ ] `flutter analyze`
|
||||
- [ ] Сборка `komet` flavor
|
||||
- [ ] Сборка `qlyra` flavor
|
||||
- [ ] Ручная проверка затронутых сценариев
|
||||
- [ ] Регресс по безопасности (если затронута)
|
||||
|
||||
@@ -21,4 +21,4 @@ runs:
|
||||
- name: Cache Rust build
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: native/komet_crypto/rust
|
||||
workspaces: native/qlyra_crypto/rust
|
||||
|
||||
@@ -69,12 +69,12 @@ jobs:
|
||||
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
|
||||
exit 0
|
||||
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 "keyPassword=$KEY_PASSWORD"
|
||||
echo "keyAlias=$KEY_ALIAS"
|
||||
echo "storeFile=komet-release.jks"
|
||||
echo "storeFile=qlyra-release.jks"
|
||||
} > android/key.properties
|
||||
echo "Release signing configured."
|
||||
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
- name: Upload Universal APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-fcm-universal
|
||||
name: qlyra-android-fcm-universal
|
||||
path: build/app/outputs/flutter-apk/app-oneme-release.apk
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
- name: Upload arm64-v8a APK
|
||||
uses: actions/upload-artifact@v4
|
||||
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
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
@@ -103,7 +103,7 @@ jobs:
|
||||
- name: Upload armeabi-v7a APK
|
||||
uses: actions/upload-artifact@v4
|
||||
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
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
@@ -111,7 +111,7 @@ jobs:
|
||||
- name: Upload x86_64 APK
|
||||
uses: actions/upload-artifact@v4
|
||||
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
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
- name: Upload App Bundle artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-fcm-aab
|
||||
name: qlyra-android-fcm-aab
|
||||
path: build/app/outputs/bundle/onemeRelease/app-oneme-release.aab
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
@@ -130,7 +130,7 @@ jobs:
|
||||
- name: Upload debug symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-fcm-symbols
|
||||
name: qlyra-android-fcm-symbols
|
||||
path: build/symbols
|
||||
if-no-files-found: error
|
||||
retention-days: 90
|
||||
|
||||
@@ -69,68 +69,68 @@ jobs:
|
||||
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
|
||||
exit 0
|
||||
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 "keyPassword=$KEY_PASSWORD"
|
||||
echo "keyAlias=$KEY_ALIAS"
|
||||
echo "storeFile=komet-release.jks"
|
||||
echo "storeFile=qlyra-release.jks"
|
||||
} > android/key.properties
|
||||
echo "Release signing configured."
|
||||
|
||||
- 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
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-universal
|
||||
path: build/app/outputs/flutter-apk/app-komet-release.apk
|
||||
name: qlyra-android-universal
|
||||
path: build/app/outputs/flutter-apk/app-qlyra-release.apk
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload arm64-v8a APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-arm64-v8a
|
||||
path: build/app/outputs/flutter-apk/app-arm64-v8a-komet-release.apk
|
||||
name: qlyra-android-arm64-v8a
|
||||
path: build/app/outputs/flutter-apk/app-arm64-v8a-qlyra-release.apk
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload armeabi-v7a APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-armeabi-v7a
|
||||
path: build/app/outputs/flutter-apk/app-armeabi-v7a-komet-release.apk
|
||||
name: qlyra-android-armeabi-v7a
|
||||
path: build/app/outputs/flutter-apk/app-armeabi-v7a-qlyra-release.apk
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload x86_64 APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-x86_64
|
||||
path: build/app/outputs/flutter-apk/app-x86_64-komet-release.apk
|
||||
name: qlyra-android-x86_64
|
||||
path: build/app/outputs/flutter-apk/app-x86_64-qlyra-release.apk
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
- 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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-aab
|
||||
path: build/app/outputs/bundle/kometRelease/app-komet-release.aab
|
||||
name: qlyra-android-aab
|
||||
path: build/app/outputs/bundle/qlyraRelease/app-qlyra-release.aab
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload debug symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-android-symbols
|
||||
name: qlyra-android-symbols
|
||||
path: build/symbols
|
||||
if-no-files-found: error
|
||||
retention-days: 90
|
||||
|
||||
@@ -54,14 +54,14 @@ jobs:
|
||||
run: |
|
||||
mkdir -p dist 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
|
||||
|
||||
- name: Upload unsigned iOS artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-ios-unsigned
|
||||
path: dist/Komet-ios-unsigned.ipa
|
||||
name: qlyra-ios-unsigned
|
||||
path: dist/Qlyra-ios-unsigned.ipa
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
@@ -79,9 +79,9 @@ jobs:
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<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>
|
||||
<array><string>ru.komet.app</string></array>
|
||||
<array><string>ru.qlyra.app</string></array>
|
||||
</dict>
|
||||
</plist>
|
||||
PLIST
|
||||
@@ -104,12 +104,12 @@ jobs:
|
||||
run: |
|
||||
mkdir -p dist 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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-ios-pseudosigned
|
||||
path: dist/Komet-ios-pseudosigned.ipa
|
||||
name: qlyra-ios-pseudosigned
|
||||
path: dist/Qlyra-ios-pseudosigned.ipa
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
@@ -56,12 +56,12 @@ jobs:
|
||||
- name: Package Linux
|
||||
run: |
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-linux-x64
|
||||
path: dist/Komet-linux-x64.tar.gz
|
||||
name: qlyra-linux-x64
|
||||
path: dist/Qlyra-linux-x64.tar.gz
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
- name: Upload macOS DMG artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-macos
|
||||
name: qlyra-macos
|
||||
path: dist/*.dmg
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
@@ -52,12 +52,12 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: komet-windows-x64
|
||||
path: dist/Komet-windows-x64.zip
|
||||
name: qlyra-windows-x64
|
||||
path: dist/Qlyra-windows-x64.zip
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
@@ -60,17 +60,17 @@ jobs:
|
||||
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
|
||||
exit 0
|
||||
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 "keyPassword=$KEY_PASSWORD"
|
||||
echo "keyAlias=$KEY_ALIAS"
|
||||
echo "storeFile=komet-release.jks"
|
||||
echo "storeFile=qlyra-release.jks"
|
||||
} > android/key.properties
|
||||
echo "Release signing configured."
|
||||
|
||||
- name: Build Android APK
|
||||
run: flutter build apk --release --flavor komet
|
||||
run: flutter build apk --release --flavor qlyra
|
||||
|
||||
build-ios:
|
||||
runs-on: macos-latest
|
||||
|
||||
@@ -59,17 +59,17 @@ jobs:
|
||||
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
|
||||
exit 0
|
||||
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 "keyPassword=$KEY_PASSWORD"
|
||||
echo "keyAlias=$KEY_ALIAS"
|
||||
echo "storeFile=komet-release.jks"
|
||||
echo "storeFile=qlyra-release.jks"
|
||||
} > android/key.properties
|
||||
echo "Release signing configured."
|
||||
|
||||
- name: Build Android APK
|
||||
run: flutter build apk --release --flavor komet
|
||||
run: flutter build apk --release --flavor qlyra
|
||||
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flavor: [komet, oneme]
|
||||
flavor: [qlyra, oneme]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -70,12 +70,12 @@ jobs:
|
||||
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
|
||||
exit 0
|
||||
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 "keyPassword=$KEY_PASSWORD"
|
||||
echo "keyAlias=$KEY_ALIAS"
|
||||
echo "storeFile=komet-release.jks"
|
||||
echo "storeFile=qlyra-release.jks"
|
||||
} > android/key.properties
|
||||
echo "Release signing configured."
|
||||
|
||||
@@ -89,12 +89,12 @@ jobs:
|
||||
run: |
|
||||
F=${{ matrix.flavor }}
|
||||
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-arm64-v8a-$F-release.apk dist/Komet-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-x86_64-$F-release.apk dist/Komet-android-$F-x86_64.apk
|
||||
cp build/app/outputs/bundle/${F}Release/app-$F-release.aab dist/Komet-android-$F.aab
|
||||
tar -czf dist/Komet-android-$F-symbols.tar.gz -C build/symbols .
|
||||
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/Qlyra-android-$F-arm64-v8a.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/Qlyra-android-$F-x86_64.apk
|
||||
cp build/app/outputs/bundle/${F}Release/app-$F-release.aab dist/Qlyra-android-$F.aab
|
||||
tar -czf dist/Qlyra-android-$F-symbols.tar.gz -C build/symbols .
|
||||
|
||||
- name: Upload Android artifacts (${{ matrix.flavor }})
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -162,7 +162,7 @@ jobs:
|
||||
- name: Package Linux
|
||||
run: |
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -196,7 +196,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p dist
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -230,7 +230,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p dist 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
|
||||
- name: Install ldid
|
||||
run: brew install ldid
|
||||
@@ -246,9 +246,9 @@ jobs:
|
||||
<dict>
|
||||
<key>platform-application</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>
|
||||
<array><string>ru.komet.app</string></array>
|
||||
<array><string>ru.qlyra.app</string></array>
|
||||
<key>com.apple.private.security.no-container</key><true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -271,7 +271,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p dist 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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -297,7 +297,7 @@ jobs:
|
||||
BUILD="${{ github.event.inputs.build_number }}"
|
||||
BUILD="${BUILD:-$GITHUB_RUN_NUMBER}"
|
||||
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
|
||||
run: ls -lhR dist
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flavor: [komet, oneme]
|
||||
flavor: [qlyra, oneme]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -65,12 +65,12 @@ jobs:
|
||||
echo "KEYSTORE_BASE64 secret not set — release will be debug-signed."
|
||||
exit 0
|
||||
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 "keyPassword=$KEY_PASSWORD"
|
||||
echo "keyAlias=$KEY_ALIAS"
|
||||
echo "storeFile=komet-release.jks"
|
||||
echo "storeFile=qlyra-release.jks"
|
||||
} > android/key.properties
|
||||
echo "Release signing configured."
|
||||
|
||||
@@ -84,12 +84,12 @@ jobs:
|
||||
run: |
|
||||
F=${{ matrix.flavor }}
|
||||
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-arm64-v8a-$F-release.apk dist/Komet-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-x86_64-$F-release.apk dist/Komet-android-$F-x86_64.apk
|
||||
cp build/app/outputs/bundle/${F}Release/app-$F-release.aab dist/Komet-android-$F.aab
|
||||
tar -czf dist/Komet-android-$F-symbols.tar.gz -C build/symbols .
|
||||
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/Qlyra-android-$F-arm64-v8a.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/Qlyra-android-$F-x86_64.apk
|
||||
cp build/app/outputs/bundle/${F}Release/app-$F-release.aab dist/Qlyra-android-$F.aab
|
||||
tar -czf dist/Qlyra-android-$F-symbols.tar.gz -C build/symbols .
|
||||
|
||||
- name: Upload Android artifacts (${{ matrix.flavor }})
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -157,7 +157,7 @@ jobs:
|
||||
- name: Package Linux
|
||||
run: |
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -189,7 +189,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p dist
|
||||
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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -233,9 +233,9 @@ jobs:
|
||||
<dict>
|
||||
<key>platform-application</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>
|
||||
<array><string>ru.komet.app</string></array>
|
||||
<array><string>ru.qlyra.app</string></array>
|
||||
<key>com.apple.private.security.no-container</key><true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -258,7 +258,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p dist 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
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -286,7 +286,7 @@ jobs:
|
||||
run: |
|
||||
PUBSPEC_VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}' | cut -d'+' -f1)
|
||||
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
|
||||
run: ls -lhR dist
|
||||
@@ -305,31 +305,31 @@ jobs:
|
||||
|
||||
## Какой файл качать
|
||||
|
||||
### Android — версия Komet (без push-уведомлений)
|
||||
- **`Komet-android-komet-arm64-v8a.apk`** — рекомендуется для большинства современных телефонов (64-битный ARM).
|
||||
- `Komet-android-komet-universal.apk` — универсальный APK, работает везде, но весит больше.
|
||||
- `Komet-android-komet-armeabi-v7a.apk` — для старых 32-битных устройств.
|
||||
- `Komet-android-komet-x86_64.apk` — для эмуляторов и редких x86-устройств.
|
||||
- `Komet-android-komet.aab` — App Bundle для публикации в Google Play (не для ручной установки).
|
||||
### Android — версия Qlyra (без push-уведомлений)
|
||||
- **`Qlyra-android-qlyra-arm64-v8a.apk`** — рекомендуется для большинства современных телефонов (64-битный ARM).
|
||||
- `Qlyra-android-qlyra-universal.apk` — универсальный APK, работает везде, но весит больше.
|
||||
- `Qlyra-android-qlyra-armeabi-v7a.apk` — для старых 32-битных устройств.
|
||||
- `Qlyra-android-qlyra-x86_64.apk` — для эмуляторов и редких x86-устройств.
|
||||
- `Qlyra-android-qlyra.aab` — App Bundle для публикации в Google Play (не для ручной установки).
|
||||
|
||||
### Android — версия OneMe (с push-уведомлениями через Firebase)
|
||||
- **`Komet-android-oneme-arm64-v8a.apk`** — рекомендуется для большинства современных телефонов.
|
||||
- `Komet-android-oneme-universal.apk` — универсальный APK.
|
||||
- `Komet-android-oneme-armeabi-v7a.apk` — для старых 32-битных устройств.
|
||||
- `Komet-android-oneme-x86_64.apk` — для эмуляторов и x86-устройств.
|
||||
- `Komet-android-oneme.aab` — App Bundle для Google Play.
|
||||
- **`Qlyra-android-oneme-arm64-v8a.apk`** — рекомендуется для большинства современных телефонов.
|
||||
- `Qlyra-android-oneme-universal.apk` — универсальный APK.
|
||||
- `Qlyra-android-oneme-armeabi-v7a.apk` — для старых 32-битных устройств.
|
||||
- `Qlyra-android-oneme-x86_64.apk` — для эмуляторов и x86-устройств.
|
||||
- `Qlyra-android-oneme.aab` — App Bundle для Google Play.
|
||||
|
||||
### Windows
|
||||
- **`Komet-windows-x64.zip`** — портативная сборка для Windows 10/11 (x64). Распаковать и запустить `Komet.exe`.
|
||||
- **`Qlyra-windows-x64.zip`** — портативная сборка для Windows 10/11 (x64). Распаковать и запустить `Qlyra.exe`.
|
||||
|
||||
### 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
|
||||
- **`Komet-macos.zip`** — `.app` для macOS. Распаковать и перетащить в `/Applications`. Приложение не нотаризовано — при первом запуске разрешите через «Системные настройки → Защита и безопасность».
|
||||
- **`Qlyra-macos.zip`** — `.app` для macOS. Распаковать и перетащить в `/Applications`. Приложение не нотаризовано — при первом запуске разрешите через «Системные настройки → Защита и безопасность».
|
||||
|
||||
### iOS
|
||||
- **`Komet-ios-pseudosigned.ipa`** — IPA с псевдо-подписью (ldid).
|
||||
- **`Qlyra-ios-pseudosigned.ipa`** — IPA с псевдо-подписью (ldid).
|
||||
⚠️ Не устанавливается через App Store. Подходит для:
|
||||
- jailbreak (Filza, rootless),
|
||||
- TrollStore,
|
||||
|
||||
@@ -136,7 +136,7 @@ agents.md
|
||||
.env
|
||||
.env.*
|
||||
# Локальные дампы трафика и скрипты анализа (содержат секреты)
|
||||
komet.txt
|
||||
qlyra.txt
|
||||
original_app.txt
|
||||
fingerprint.py
|
||||
PCAPdroid_*.txt
|
||||
@@ -149,8 +149,5 @@ maxtun/
|
||||
turnprobe/
|
||||
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
|
||||
.cargo/
|
||||
third_party/kolibri/
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"cmake.sourceDirectory": "/run/media/invisedivine/Drive/! My projects/Komet/linux/runner",
|
||||
"kiroAgent.configureMCP": "Disabled"
|
||||
}
|
||||
@@ -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/ руками не правь — только через генератор.
|
||||
@@ -4,20 +4,20 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## 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
|
||||
|
||||
```bash
|
||||
flutter pub get # install dependencies
|
||||
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)
|
||||
|
||||
# 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 --split-per-abi --flavor komet --obfuscate --split-debug-info=build/symbols
|
||||
flutter build appbundle --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 qlyra --obfuscate --split-debug-info=build/symbols
|
||||
flutter build appbundle --release --flavor qlyra --obfuscate --split-debug-info=build/symbols
|
||||
|
||||
# Other platforms
|
||||
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 |
|
||||
|--------|--------|-------|
|
||||
| `komet` | `ru.komet.app` | Default, no FCM |
|
||||
| `qlyra` | `ru.qlyra.app` | Default, no FCM |
|
||||
| `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
|
||||
|
||||
@@ -97,5 +97,5 @@ Four GitHub Actions workflows in `.github/workflows/`:
|
||||
|
||||
- `flutter-dev.yml` — PR lint + Android build for dev 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
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
> [!IMPORTANT]
|
||||
> Потерялись? Возможно вы ищите старую версию Komet. Она расположена [здесь](https://github.com/KometTeam/KometOld).
|
||||
---
|
||||
<img src="assets/qlyra.png" width="100" alt="Qlyra Logo">
|
||||
|
||||
<img src="assets/komet.png" width="100" alt="Komet Logo">
|
||||
# Qlyra
|
||||
|
||||
# Komet
|
||||
Альтернативный FOSS клиент для мессенджера MAX
|
||||
Кроссплатформенный клиент для мессенджера MAX.
|
||||
|
||||
## Установка
|
||||
[Последний релиз](https://github.com/KometTeam/Komet/releases/latest) / [Telegram Канал](https://t.me/TeamKomet)
|
||||
## Android
|
||||
|
||||
Основной вариант приложения использует идентификатор `ru.qlyra.app` и flavor `qlyra`.
|
||||
|
||||
## Сборка из исходного кода
|
||||
|
||||
```console
|
||||
$ flutter build [windows|linux] [--release]
|
||||
$ flutter build apk --release --flavor qlyra
|
||||
```
|
||||
|
||||
## Хотите помочь?
|
||||
Нашли ошибку и сами её исправили? Сделайте Pull-Request.<br/>
|
||||
|
||||
@@ -11,6 +11,6 @@ GeneratedPluginRegistrant.java
|
||||
# See https://flutter.dev/to/reference-keystore
|
||||
key.properties
|
||||
app/key.properties
|
||||
app/komet-release.jks
|
||||
app/qlyra-release.jks
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
|
||||
@@ -17,7 +17,7 @@ if (hasReleaseSigning) {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "ru.komet.app"
|
||||
namespace = "ru.qlyra.app"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
@@ -32,7 +32,7 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "ru.komet.app"
|
||||
applicationId = "ru.qlyra.app"
|
||||
minSdk = maxOf(flutter.minSdkVersion, 23)
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
@@ -54,10 +54,10 @@ android {
|
||||
flavorDimensions += "distribution"
|
||||
|
||||
productFlavors {
|
||||
create("komet") {
|
||||
create("qlyra") {
|
||||
dimension = "distribution"
|
||||
isDefault = true
|
||||
applicationId = "ru.komet.app"
|
||||
applicationId = "ru.qlyra.app"
|
||||
}
|
||||
create("oneme") {
|
||||
dimension = "distribution"
|
||||
|
||||
@@ -33,15 +33,15 @@
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
|
||||
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
|
||||
<application
|
||||
android:label="Komet"
|
||||
android:label="Qlyra"
|
||||
android:name="${applicationName}"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name="ru.komet.app.MainActivity"
|
||||
android:name="ru.qlyra.app.MainActivity"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="Komet"
|
||||
android:label="Qlyra"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
@@ -69,20 +69,11 @@
|
||||
<data android:scheme="http" android:host="max.ru"/>
|
||||
<data android:scheme="http" android:host="www.max.ru"/>
|
||||
</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>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="komet"/>
|
||||
<data android:scheme="qlyra"/>
|
||||
<data android:scheme="max"/>
|
||||
</intent-filter>
|
||||
<intent-filter android:label="@string/share_target_label">
|
||||
@@ -104,12 +95,12 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity-alias
|
||||
android:name="ru.komet.app.MinimalIcon"
|
||||
android:name="ru.qlyra.app.MinimalIcon"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_minimal"
|
||||
android:label="Komet"
|
||||
android:targetActivity="ru.komet.app.MainActivity">
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="Qlyra"
|
||||
android:targetActivity="ru.qlyra.app.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
@@ -130,10 +121,10 @@
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.nfc.cardemulation.host_apdu_service"
|
||||
android:resource="@xml/komet_nfc_apdu"/>
|
||||
android:resource="@xml/qlyra_nfc_apdu"/>
|
||||
</service>
|
||||
<service
|
||||
android:name=".KometFcmService"
|
||||
android:name=".QlyraFcmService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
@@ -175,7 +166,7 @@
|
||||
android:value="2" />
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||
android:value="komet_messages" />
|
||||
android:value="qlyra_messages" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(komet_rlottie LANGUAGES C CXX ASM)
|
||||
project(qlyra_rlottie LANGUAGES C CXX ASM)
|
||||
|
||||
add_subdirectory(
|
||||
"${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.BluetoothDevice
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
@@ -20,9 +20,9 @@ object CallState {
|
||||
class CallForegroundService : Service() {
|
||||
|
||||
companion object {
|
||||
const val ACTION_START = "ru.komet.app.CALL_ONGOING_START"
|
||||
const val ACTION_STOP = "ru.komet.app.CALL_ONGOING_STOP"
|
||||
const val ACTION_SCREEN_SHARE = "ru.komet.app.CALL_SCREEN_SHARE"
|
||||
const val ACTION_START = "ru.qlyra.app.CALL_ONGOING_START"
|
||||
const val ACTION_STOP = "ru.qlyra.app.CALL_ONGOING_STOP"
|
||||
const val ACTION_SCREEN_SHARE = "ru.qlyra.app.CALL_SCREEN_SHARE"
|
||||
const val EXTRA_SCREEN_SHARE = "screenShare"
|
||||
const val ONGOING_ID = 424243
|
||||
|
||||
@@ -46,7 +46,7 @@ class CallForegroundService : Service() {
|
||||
ctx.startService(intent)
|
||||
}
|
||||
} 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)
|
||||
}
|
||||
} 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)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w("KometFcm", "startForeground failed: ${e.message}")
|
||||
Log.w("QlyraFcm", "startForeground failed: ${e.message}")
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
@@ -46,21 +46,21 @@ object CallEvents {
|
||||
}
|
||||
|
||||
object CallConst {
|
||||
const val CHANNEL_ID = "komet_calls"
|
||||
const val CHANNEL_ID = "qlyra_calls"
|
||||
const val CHANNEL_NAME = "Звонки"
|
||||
const val NOTIF_ID = 424242
|
||||
const val ACCENT = 0xFF7C6BF0.toInt()
|
||||
|
||||
const val EXTRA_CALL = "komet_call"
|
||||
const val EXTRA_ACTION = "komet_call_action"
|
||||
const val EXTRA_DECLINE_PAYLOAD = "komet_decline_payload"
|
||||
const val EXTRA_NOTIF_ID = "komet_notif_id"
|
||||
const val EXTRA_CALLER = "komet_caller"
|
||||
const val EXTRA_CALL = "qlyra_call"
|
||||
const val EXTRA_ACTION = "qlyra_call_action"
|
||||
const val EXTRA_DECLINE_PAYLOAD = "qlyra_decline_payload"
|
||||
const val EXTRA_NOTIF_ID = "qlyra_notif_id"
|
||||
const val EXTRA_CALLER = "qlyra_caller"
|
||||
|
||||
const val ACTION_RING = "ring"
|
||||
const val ACTION_ANSWER = "answer"
|
||||
const val ACTION_DECLINE = "ru.komet.app.CALL_DECLINE"
|
||||
const val ACTION_HANGUP = "ru.komet.app.CALL_HANGUP"
|
||||
const val ACTION_DECLINE = "ru.qlyra.app.CALL_DECLINE"
|
||||
const val ACTION_HANGUP = "ru.qlyra.app.CALL_HANGUP"
|
||||
|
||||
const val FLN_RECEIVER =
|
||||
"com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver"
|
||||
@@ -72,7 +72,7 @@ object CallNotifier {
|
||||
|
||||
fun showIncoming(ctx: Context, data: Map<String, String>) {
|
||||
if (AppState.resumed) {
|
||||
Log.d("KometFcm", "call push suppressed (app foreground)")
|
||||
Log.d("QlyraFcm", "call push suppressed (app foreground)")
|
||||
return
|
||||
}
|
||||
val name = data["userName"] ?: data["title"] ?: "Неизвестный"
|
||||
@@ -82,7 +82,7 @@ object CallNotifier {
|
||||
val account = data["c"] ?: ""
|
||||
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)
|
||||
|
||||
@@ -117,7 +117,7 @@ object CallNotifier {
|
||||
}
|
||||
|
||||
fun finishCall(ctx: Context, data: Map<String, String>) {
|
||||
Log.d("KometFcm", "finishCall keys=${data.keys}")
|
||||
Log.d("QlyraFcm", "finishCall keys=${data.keys}")
|
||||
CallRinger.stop()
|
||||
NotificationManagerCompat.from(ctx).cancel(CallConst.NOTIF_ID)
|
||||
CallEvents.emit("ended")
|
||||
@@ -208,7 +208,7 @@ object CallRinger {
|
||||
activeConversationId = conversationId
|
||||
|
||||
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)
|
||||
acquire(60_000L)
|
||||
}
|
||||
@@ -271,7 +271,7 @@ object CallRinger {
|
||||
rt.play()
|
||||
ringtone = rt
|
||||
} 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
|
||||
} 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 {
|
||||
ctx.sendBroadcast(fln)
|
||||
} 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 io.flutter.plugin.common.EventChannel
|
||||
|
||||
object ChatNotifications {
|
||||
const val EXTRA_CHAT = "komet_chat"
|
||||
const val EXTRA_CHAT = "qlyra_chat"
|
||||
|
||||
@Volatile
|
||||
var activeChatId: Long = 0L
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
@@ -20,7 +20,7 @@ import io.flutter.plugin.common.MethodChannel
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
object FkmChannel {
|
||||
private const val NAME = "ru.komet.app/fkm"
|
||||
private const val NAME = "ru.qlyra.app/fkm"
|
||||
const val NOTIF_PERMS_REQUEST = 7713
|
||||
|
||||
private val main = Handler(Looper.getMainLooper())
|
||||
@@ -117,7 +117,7 @@ object FkmChannel {
|
||||
val data = call.argument<Map<String, String>>("data") ?: return false
|
||||
worker.execute {
|
||||
try {
|
||||
KometNotifier(ctx).handle(data)
|
||||
QlyraNotifier(ctx).handle(data)
|
||||
FkmState.countDelivered(ctx)
|
||||
FkmService.refresh(ctx)
|
||||
} catch (e: Exception) {
|
||||
@@ -132,12 +132,12 @@ object FkmChannel {
|
||||
ctx: Context,
|
||||
call: MethodCall,
|
||||
tag: String,
|
||||
action: (KometNotifier, Map<String, String>) -> Unit,
|
||||
action: (QlyraNotifier, Map<String, String>) -> Unit,
|
||||
): Boolean {
|
||||
val data = call.argument<Map<String, String>>("data") ?: return false
|
||||
worker.execute {
|
||||
try {
|
||||
action(KometNotifier(ctx), data)
|
||||
action(QlyraNotifier(ctx), data)
|
||||
} catch (e: Exception) {
|
||||
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.NotificationChannel
|
||||
@@ -15,7 +15,7 @@ import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
|
||||
object FkmState {
|
||||
private const val PREFS = "komet_fkm"
|
||||
private const val PREFS = "qlyra_fkm"
|
||||
private const val KEY_ENABLED = "enabled"
|
||||
private const val KEY_DELIVERED = "delivered"
|
||||
|
||||
@@ -60,7 +60,7 @@ object FkmState {
|
||||
}
|
||||
|
||||
object FkmNotification {
|
||||
const val CHANNEL_ID = "komet_fkm"
|
||||
const val CHANNEL_ID = "qlyra_fkm"
|
||||
const val NOTIFICATION_ID = 424244
|
||||
|
||||
fun build(ctx: Context): Notification {
|
||||
@@ -228,7 +228,7 @@ class FkmService : Service() {
|
||||
|
||||
class FkmDisableReceiver : BroadcastReceiver() {
|
||||
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) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.Manifest
|
||||
import android.app.KeyguardManager
|
||||
@@ -52,7 +52,7 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
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 iconComponents = mapOf(
|
||||
"MainActivity" to "$iconPackage.MainActivity",
|
||||
@@ -89,7 +89,7 @@ class MainActivity : FlutterActivity() {
|
||||
const val LOG_TAG = "VpnBypass"
|
||||
const val SHARE_TAG = "ShareIntake"
|
||||
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_JITTER_MS = 400
|
||||
const val BLE_PERMS_REQUEST = 7711
|
||||
@@ -126,7 +126,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/nfc",
|
||||
"ru.qlyra.app/nfc",
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"status" -> result.success(nfcStatus())
|
||||
@@ -150,7 +150,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
EventChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/nfc_events",
|
||||
"ru.qlyra.app/nfc_events",
|
||||
).setStreamHandler(object : EventChannel.StreamHandler {
|
||||
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
|
||||
nfcEvents = events
|
||||
@@ -175,7 +175,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/app_icon",
|
||||
"ru.qlyra.app/app_icon",
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"setAppIcon" -> {
|
||||
@@ -197,7 +197,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/upload_service",
|
||||
"ru.qlyra.app/upload_service",
|
||||
).setMethodCallHandler { call, result ->
|
||||
val ctx = this
|
||||
fun uploadIntent(call: MethodCall, action: String) =
|
||||
@@ -248,7 +248,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/video_note",
|
||||
"ru.qlyra.app/video_note",
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"permission" -> requestNotePermissions(result)
|
||||
@@ -287,7 +287,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/video",
|
||||
"ru.qlyra.app/video",
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"cropSquare" -> {
|
||||
@@ -332,7 +332,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/calls",
|
||||
"ru.qlyra.app/calls",
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"consumeInitialCall" -> {
|
||||
@@ -393,7 +393,7 @@ class MainActivity : FlutterActivity() {
|
||||
),
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.w("KometFcm", "open FSI settings failed: ${e.message}")
|
||||
Log.w("QlyraFcm", "open FSI settings failed: ${e.message}")
|
||||
}
|
||||
}
|
||||
result.success(null)
|
||||
@@ -404,7 +404,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/screen",
|
||||
"ru.qlyra.app/screen",
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"setKeepAwake" -> {
|
||||
@@ -417,7 +417,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
EventChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/calls_events",
|
||||
"ru.qlyra.app/calls_events",
|
||||
).setStreamHandler(object : EventChannel.StreamHandler {
|
||||
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
|
||||
CallEvents.sink = events
|
||||
@@ -430,7 +430,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/notifications",
|
||||
"ru.qlyra.app/notifications",
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"consumeInitialChat" -> {
|
||||
@@ -453,7 +453,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
EventChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/notification_events",
|
||||
"ru.qlyra.app/notification_events",
|
||||
).setStreamHandler(object : EventChannel.StreamHandler {
|
||||
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
|
||||
ChatNotifications.sink = events
|
||||
@@ -466,7 +466,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
MethodChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/share",
|
||||
"ru.qlyra.app/share",
|
||||
).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"consumeInitialShare" -> {
|
||||
@@ -501,7 +501,7 @@ class MainActivity : FlutterActivity() {
|
||||
|
||||
EventChannel(
|
||||
flutterEngine.dartExecutor.binaryMessenger,
|
||||
"ru.komet.app/share_events",
|
||||
"ru.qlyra.app/share_events",
|
||||
).setStreamHandler(object : EventChannel.StreamHandler {
|
||||
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
|
||||
ShareIntake.sink = events
|
||||
@@ -965,7 +965,7 @@ class MainActivity : FlutterActivity() {
|
||||
override fun onDestroy() {
|
||||
shareExecutor.shutdown()
|
||||
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) }
|
||||
}
|
||||
super.onDestroy()
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
object NfcExchange {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.nfc.cardemulation.HostApduService
|
||||
import android.os.Bundle
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
@@ -26,29 +26,29 @@ import com.google.firebase.messaging.RemoteMessage
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
class KometFcmService : FirebaseMessagingService() {
|
||||
class QlyraFcmService : FirebaseMessagingService() {
|
||||
override fun onMessageReceived(message: RemoteMessage) {
|
||||
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
|
||||
val type = data["type"]
|
||||
FkmState.restore(applicationContext)
|
||||
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
|
||||
}
|
||||
KometNotifier(applicationContext).handle(data)
|
||||
QlyraNotifier(applicationContext).handle(data)
|
||||
}
|
||||
}
|
||||
|
||||
class KometNotifier(private val ctx: Context) {
|
||||
class QlyraNotifier(private val ctx: Context) {
|
||||
|
||||
companion object {
|
||||
private const val CHANNEL_ID = "komet_messages"
|
||||
private const val CHANNEL_ID = "qlyra_messages"
|
||||
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 PREFS = "komet_push"
|
||||
private const val PREFS = "qlyra_push"
|
||||
private const val FLN_RECEIVER =
|
||||
"com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver"
|
||||
private const val FLN_ACTION_TAPPED =
|
||||
@@ -336,7 +336,7 @@ class KometNotifier(private val ctx: Context) {
|
||||
.setShowWhen(true)
|
||||
.setNumber(entries.size)
|
||||
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN)
|
||||
.setContentTitle("Komet")
|
||||
.setContentTitle("Qlyra")
|
||||
.setContentText(boldLine(newest.first, newest.second))
|
||||
.setStyle(inbox)
|
||||
.build()
|
||||
@@ -399,7 +399,7 @@ class KometNotifier(private val ctx: Context) {
|
||||
.build()
|
||||
ShortcutManagerCompat.pushDynamicShortcut(ctx, shortcut)
|
||||
} 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.Context
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.app.*
|
||||
import android.content.Intent
|
||||
@@ -11,11 +11,11 @@ import androidx.core.app.NotificationCompat
|
||||
class UploadForegroundService : Service() {
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "komet_upload"
|
||||
const val CHANNEL_ID = "qlyra_upload"
|
||||
const val NOTIFICATION_ID = 9001
|
||||
const val ACTION_START = "ru.komet.app.UPLOAD_START"
|
||||
const val ACTION_UPDATE = "ru.komet.app.UPLOAD_UPDATE"
|
||||
const val ACTION_STOP = "ru.komet.app.UPLOAD_STOP"
|
||||
const val ACTION_START = "ru.qlyra.app.UPLOAD_START"
|
||||
const val ACTION_UPDATE = "ru.qlyra.app.UPLOAD_UPDATE"
|
||||
const val ACTION_STOP = "ru.qlyra.app.UPLOAD_STOP"
|
||||
const val EXTRA_TITLE = "title"
|
||||
const val EXTRA_BODY = "body"
|
||||
const val EXTRA_PROGRESS = "progress"
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.komet.app
|
||||
package ru.qlyra.app
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 197 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 49 KiB |
@@ -2,7 +2,7 @@
|
||||
<string name="upload_channel_name">Отправка медиа</string>
|
||||
<string name="fkm_channel_name">Сервис уведомлений</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_inactive">Соединение не активно</string>
|
||||
<string name="fkm_status_line">%1$s · принято %2$d</string>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<resources>
|
||||
<string name="nfc_service_description">Komet contact exchange</string>
|
||||
<string name="nfc_aid_group_description">Komet contact exchange</string>
|
||||
<string name="nfc_service_description">Qlyra contact exchange</string>
|
||||
<string name="nfc_aid_group_description">Qlyra contact exchange</string>
|
||||
<string name="upload_channel_name">Sending media</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_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_inactive">Connection inactive</string>
|
||||
<string name="fkm_status_line">%1$s · %2$d delivered</string>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:659634599081:android:00000000000000000000ab",
|
||||
"android_client_info": {
|
||||
"package_name": "ru.komet.app"
|
||||
"package_name": "ru.qlyra.app"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
|
Before Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 168 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
@@ -15,7 +15,7 @@
|
||||
<rect width="1440" height="2280" fill="#F8F4FE"/>
|
||||
|
||||
<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>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -7,7 +7,7 @@ ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
require 'json'
|
||||
|
||||
# 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
|
||||
# to the iOS 15 deployment target that firebase_core's podspec requires.
|
||||
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
|
||||
# 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_LIB_VAR = 'KOMET_OPUS_LIB'.freeze
|
||||
OPUS_LIB_VAR = 'QLYRA_OPUS_LIB'.freeze
|
||||
OPUS_FORCE_LOAD = %(-force_load "$(#{OPUS_LIB_VAR})").freeze
|
||||
OPUS_XCFRAMEWORK_DIR =
|
||||
File.expand_path(File.join('.symlinks', 'plugins', OPUS_XCFRAMEWORK), __dir__).freeze
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
4B1A4BBCD56B3CE42AD0A480 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 789A1AEF2F4FF7DEED202476 /* Pods_Runner.framework */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
AA11BB22CC33DD44EE550101 /* KometVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550001 /* KometVideo.swift */; };
|
||||
AA11BB22CC33DD44EE550102 /* KometVideoNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550002 /* KometVideoNote.swift */; };
|
||||
AA11BB22CC33DD44EE550103 /* KometNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550003 /* KometNotifications.swift */; };
|
||||
AA11BB22CC33DD44EE550101 /* QlyraVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550001 /* QlyraVideo.swift */; };
|
||||
AA11BB22CC33DD44EE550102 /* QlyraVideoNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550002 /* QlyraVideoNote.swift */; };
|
||||
AA11BB22CC33DD44EE550103 /* QlyraNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550003 /* QlyraNotifications.swift */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
AA11BB22CC33DD44EE550001 /* KometVideo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KometVideo.swift; sourceTree = "<group>"; };
|
||||
AA11BB22CC33DD44EE550002 /* KometVideoNote.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KometVideoNote.swift; sourceTree = "<group>"; };
|
||||
AA11BB22CC33DD44EE550003 /* KometNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KometNotifications.swift; sourceTree = "<group>"; };
|
||||
AA11BB22CC33DD44EE550001 /* QlyraVideo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QlyraVideo.swift; sourceTree = "<group>"; };
|
||||
AA11BB22CC33DD44EE550002 /* QlyraVideoNote.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QlyraVideoNote.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>"; };
|
||||
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; };
|
||||
@@ -164,9 +164,9 @@
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
AA11BB22CC33DD44EE550001 /* KometVideo.swift */,
|
||||
AA11BB22CC33DD44EE550002 /* KometVideoNote.swift */,
|
||||
AA11BB22CC33DD44EE550003 /* KometNotifications.swift */,
|
||||
AA11BB22CC33DD44EE550001 /* QlyraVideo.swift */,
|
||||
AA11BB22CC33DD44EE550002 /* QlyraVideoNote.swift */,
|
||||
AA11BB22CC33DD44EE550003 /* QlyraNotifications.swift */,
|
||||
AA11BB22CC33DD44EE550004 /* Runner.entitlements */,
|
||||
);
|
||||
path = Runner;
|
||||
@@ -407,9 +407,9 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
AA11BB22CC33DD44EE550101 /* KometVideo.swift in Sources */,
|
||||
AA11BB22CC33DD44EE550102 /* KometVideoNote.swift in Sources */,
|
||||
AA11BB22CC33DD44EE550103 /* KometNotifications.swift in Sources */,
|
||||
AA11BB22CC33DD44EE550101 /* QlyraVideo.swift in Sources */,
|
||||
AA11BB22CC33DD44EE550102 /* QlyraVideoNote.swift in Sources */,
|
||||
AA11BB22CC33DD44EE550103 /* QlyraNotifications.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -510,7 +510,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -527,7 +527,7 @@
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -545,7 +545,7 @@
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
@@ -561,7 +561,7 @@
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
@@ -693,7 +693,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -716,7 +716,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.komet.app;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ru.qlyra.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
final class KometStreamHandler: NSObject, FlutterStreamHandler {
|
||||
final class QlyraStreamHandler: NSObject, FlutterStreamHandler {
|
||||
private let onSink: (FlutterEventSink?) -> Void
|
||||
|
||||
init(onSink: @escaping (FlutterEventSink?) -> Void) {
|
||||
@@ -26,15 +26,15 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
private var channels: [FlutterMethodChannel] = []
|
||||
private var eventChannels: [FlutterEventChannel] = []
|
||||
private var streamHandlers: [KometStreamHandler] = []
|
||||
private var videoNote: KometVideoNote?
|
||||
private var streamHandlers: [QlyraStreamHandler] = []
|
||||
private var videoNote: QlyraVideoNote?
|
||||
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
KometNotifications.shared.start()
|
||||
QlyraNotifications.shared.start()
|
||||
|
||||
if let controller = window?.rootViewController as? FlutterViewController {
|
||||
let messenger = controller.binaryMessenger
|
||||
@@ -57,7 +57,7 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
|
||||
|
||||
private func events(_ name: String, _ messenger: FlutterBinaryMessenger,
|
||||
_ onSink: @escaping (FlutterEventSink?) -> Void) {
|
||||
let handler = KometStreamHandler(onSink: onSink)
|
||||
let handler = QlyraStreamHandler(onSink: onSink)
|
||||
let channel = FlutterEventChannel(name: name, binaryMessenger: messenger)
|
||||
channel.setStreamHandler(handler)
|
||||
streamHandlers.append(handler)
|
||||
@@ -65,7 +65,7 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
|
||||
}
|
||||
|
||||
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 {
|
||||
case "getAppIcon":
|
||||
result(UIApplication.shared.alternateIconName)
|
||||
@@ -100,23 +100,23 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
|
||||
}
|
||||
|
||||
private func registerVideo(_ messenger: FlutterBinaryMessenger) {
|
||||
method("ru.komet.app/video", messenger) { call, result in
|
||||
KometVideo.shared.handle(call, result: result)
|
||||
method("ru.qlyra.app/video", messenger) { call, result in
|
||||
QlyraVideo.shared.handle(call, result: result)
|
||||
}
|
||||
}
|
||||
|
||||
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 }
|
||||
switch call.method {
|
||||
case "permission":
|
||||
KometVideoNote.requestPermission(result)
|
||||
QlyraVideoNote.requestPermission(result)
|
||||
case "init":
|
||||
let args = call.arguments as? [String: Any] ?? [:]
|
||||
self.videoNote?.dispose()
|
||||
let recorder = KometVideoNote(registry: textures)
|
||||
let recorder = QlyraVideoNote(registry: textures)
|
||||
self.videoNote = recorder
|
||||
recorder.initialize(
|
||||
front: (args["front"] as? NSNumber)?.boolValue ?? true,
|
||||
@@ -143,7 +143,7 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
|
||||
}
|
||||
|
||||
private func withRecorder(_ result: @escaping FlutterResult,
|
||||
_ body: (KometVideoNote) -> Void) {
|
||||
_ body: (QlyraVideoNote) -> Void) {
|
||||
guard let recorder = videoNote else {
|
||||
result(FlutterError(code: "NOT_READY", message: "recorder not initialized", details: nil))
|
||||
return
|
||||
@@ -152,7 +152,7 @@ final class KometStreamHandler: NSObject, FlutterStreamHandler {
|
||||
}
|
||||
|
||||
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 {
|
||||
case "setKeepAwake":
|
||||
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) {
|
||||
method("ru.komet.app/notifications", messenger) { call, result in
|
||||
KometNotifications.shared.handle(call, result: result)
|
||||
method("ru.qlyra.app/notifications", messenger) { call, result in
|
||||
QlyraNotifications.shared.handle(call, result: result)
|
||||
}
|
||||
events("ru.komet.app/notification_events", messenger) { sink in
|
||||
KometNotifications.shared.attach(sink)
|
||||
events("ru.qlyra.app/notification_events", messenger) { sink in
|
||||
QlyraNotifications.shared.attach(sink)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 797 KiB |
|
Before Width: | Height: | Size: 439 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 700 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 32 KiB |
@@ -5,7 +5,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Komet</string>
|
||||
<string>Qlyra</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -13,7 +13,7 @@
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Komet</string>
|
||||
<string>Qlyra</string>
|
||||
<key>CFBundleIcons</key>
|
||||
<dict>
|
||||
<key>CFBundleAlternateIcons</key>
|
||||
@@ -76,10 +76,10 @@
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>ru.komet.app</string>
|
||||
<string>ru.qlyra.app</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>komet</string>
|
||||
<string>qlyra</string>
|
||||
<string>max</string>
|
||||
</array>
|
||||
</dict>
|
||||
|
||||
@@ -2,10 +2,10 @@ import Flutter
|
||||
import UIKit
|
||||
import UserNotifications
|
||||
|
||||
final class KometNotifications: NSObject {
|
||||
static let shared = KometNotifications()
|
||||
final class QlyraNotifications: NSObject {
|
||||
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 pendingChatId: Int64 = 0
|
||||
@@ -76,7 +76,7 @@ final class KometNotifications: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
extension KometNotifications: UNUserNotificationCenterDelegate {
|
||||
extension QlyraNotifications: UNUserNotificationCenterDelegate {
|
||||
func userNotificationCenter(
|
||||
_ center: UNUserNotificationCenter,
|
||||
willPresent notification: UNNotification,
|
||||
@@ -54,10 +54,10 @@ private struct VideoExportSpec {
|
||||
}
|
||||
}
|
||||
|
||||
final class KometVideo {
|
||||
static let shared = KometVideo()
|
||||
final class QlyraVideo {
|
||||
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 cancelled = false
|
||||
|
||||
@@ -3,7 +3,7 @@ import CoreImage
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
final class KometVideoNoteTexture: NSObject, FlutterTexture {
|
||||
final class QlyraVideoNoteTexture: NSObject, FlutterTexture {
|
||||
private let lock = NSLock()
|
||||
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 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 session = AVCaptureSession()
|
||||
private let videoOutput = AVCaptureVideoDataOutput()
|
||||
private let audioOutput = AVCaptureAudioDataOutput()
|
||||
private let texture = KometVideoNoteTexture()
|
||||
private let texture = QlyraVideoNoteTexture()
|
||||
|
||||
private var textureId: Int64 = 0
|
||||
private var deviceInput: AVCaptureDeviceInput?
|
||||
@@ -207,12 +207,12 @@ final class KometVideoNote: NSObject {
|
||||
guard let device = AVCaptureDevice.default(
|
||||
.builtInWideAngleCamera, for: .video, position: position)
|
||||
?? AVCaptureDevice.default(for: .video) else {
|
||||
throw NSError(domain: "KometVideoNote", code: 1,
|
||||
throw NSError(domain: "QlyraVideoNote", code: 1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "no camera found"])
|
||||
}
|
||||
let input = try AVCaptureDeviceInput(device: device)
|
||||
guard session.canAddInput(input) else {
|
||||
throw NSError(domain: "KometVideoNote", code: 2,
|
||||
throw NSError(domain: "QlyraVideoNote", code: 2,
|
||||
userInfo: [NSLocalizedDescriptionKey: "camera input rejected"])
|
||||
}
|
||||
session.addInput(input)
|
||||
@@ -270,7 +270,7 @@ final class KometVideoNote: NSObject {
|
||||
private func prepareWriter() throws {
|
||||
let directory = FileManager.default.temporaryDirectory
|
||||
let url = directory.appendingPathComponent(
|
||||
"komet_note_\(Int(Date().timeIntervalSince1970 * 1000)).mp4")
|
||||
"qlyra_note_\(Int(Date().timeIntervalSince1970 * 1000)).mp4")
|
||||
try? FileManager.default.removeItem(at: url)
|
||||
|
||||
let writer = try AVAssetWriter(outputURL: url, fileType: .mp4)
|
||||
@@ -286,7 +286,7 @@ final class KometVideoNote: NSObject {
|
||||
let video = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings)
|
||||
video.expectsMediaDataInRealTime = true
|
||||
guard writer.canAdd(video) else {
|
||||
throw NSError(domain: "KometVideoNote", code: 3,
|
||||
throw NSError(domain: "QlyraVideoNote", code: 3,
|
||||
userInfo: [NSLocalizedDescriptionKey: "video input rejected"])
|
||||
}
|
||||
writer.add(video)
|
||||
@@ -310,7 +310,7 @@ final class KometVideoNote: NSObject {
|
||||
])
|
||||
|
||||
guard writer.startWriting() else {
|
||||
throw NSError(domain: "KometVideoNote", code: 4,
|
||||
throw NSError(domain: "QlyraVideoNote", code: 4,
|
||||
userInfo: [NSLocalizedDescriptionKey: "writer refused to start"])
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ final class KometVideoNote: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
extension KometVideoNote: AVCaptureVideoDataOutputSampleBufferDelegate,
|
||||
extension QlyraVideoNote: AVCaptureVideoDataOutputSampleBufferDelegate,
|
||||
AVCaptureAudioDataOutputSampleBufferDelegate {
|
||||
func captureOutput(
|
||||
_ output: AVCaptureOutput,
|
||||
@@ -4,7 +4,7 @@
|
||||
<dict>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)ru.komet.app</string>
|
||||
<string>$(AppIdentifierPrefix)ru.qlyra.app</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -4,13 +4,13 @@ import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.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 '../core/cache/self_presence.dart';
|
||||
import '../core/config/config.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/protocol/opcode_map.dart';
|
||||
import '../core/protocol/packet.dart';
|
||||
@@ -27,11 +27,11 @@ enum SessionState { disconnected, connecting, connected, online }
|
||||
|
||||
/// Клиент API.
|
||||
///
|
||||
/// Тонкий адаптер над Rust-ядром [KolibriSession] (пакет kolibri): подключение,
|
||||
/// Тонкий адаптер над Rust-ядром [KusoftSession] (пакет kusoft): подключение,
|
||||
/// хэндшейк, пинг и реконнект живут в ядре, здесь — оркестрация жизненного цикла
|
||||
/// и сохранение прежнего интерфейса для модулей (Packet/пуши/стримы).
|
||||
class Api {
|
||||
KolibriSession? _session;
|
||||
KusoftSession? _session;
|
||||
|
||||
/// Роутер пушей (ответы на запросы ядро матчит само, диспетчер держим только
|
||||
/// ради registerHandler/pushStream).
|
||||
@@ -60,7 +60,7 @@ class Api {
|
||||
String? get callsOsVersion => _callsOsVersion;
|
||||
|
||||
/// Сырой доступ к сессии ядра — для медиа-загрузок (data-plane).
|
||||
KolibriSession? get session => _session;
|
||||
KusoftSession? get session => _session;
|
||||
|
||||
String? spoofScope;
|
||||
|
||||
@@ -284,7 +284,7 @@ class Api {
|
||||
}
|
||||
// Лог запроса/ответа ведётся из wire-лога ядра (_onWireLog) по настоящему
|
||||
// проводному seq, поэтому здесь ничего не пишем.
|
||||
final KolibriResponse resp = await session
|
||||
final KusoftResponse resp = await session
|
||||
.requestMapFull(opcode, Map<String, dynamic>.from(payload))
|
||||
.timeout(
|
||||
ServerConfig.requestTimeout,
|
||||
@@ -368,7 +368,7 @@ class Api {
|
||||
|
||||
/// Строит устройство-поля и создаёт сессию ядра. Заодно заполняет
|
||||
/// [_userAgent] и [_deviceId] для геттеров.
|
||||
Future<(KolibriSession, Stream<WireLogEvent>)> _buildSessionOptions(
|
||||
Future<(KusoftSession, Stream<WireLogEvent>)> _buildSessionOptions(
|
||||
({String host, int port, bool trustMincifryCa}) endpoint,
|
||||
) async {
|
||||
final deviceInfo = DeviceInfoPlugin();
|
||||
@@ -513,7 +513,7 @@ class Api {
|
||||
deviceLocale: deviceLocale,
|
||||
clientSessionId: clientSessionId,
|
||||
pingIntervalSecs: ServerConfig.pingInterval.inSeconds,
|
||||
pingInteractive: !KometSettings.ghostMode.value,
|
||||
pingInteractive: !QlyraSettings.ghostMode.value,
|
||||
autoReconnect: false,
|
||||
insecureTls: insecureTls,
|
||||
proxy: proxy,
|
||||
@@ -665,7 +665,7 @@ class Api {
|
||||
try {
|
||||
await session
|
||||
.requestMapFull(Opcode.ping, {
|
||||
'interactive': !KometSettings.ghostMode.value,
|
||||
'interactive': !QlyraSettings.ghostMode.value,
|
||||
})
|
||||
.timeout(const Duration(seconds: 6));
|
||||
} catch (_) {
|
||||
@@ -720,7 +720,7 @@ class Api {
|
||||
/// синхронизация interactive-флага пинга и присутствия.
|
||||
void _startLiveness() {
|
||||
_livenessTimer?.cancel();
|
||||
_lastInteractive = !KometSettings.ghostMode.value;
|
||||
_lastInteractive = !QlyraSettings.ghostMode.value;
|
||||
_livenessTimer = Timer.periodic(_livenessInterval, (_) => _tickLiveness());
|
||||
}
|
||||
|
||||
@@ -729,11 +729,11 @@ class Api {
|
||||
if (session == null || _sessionState != SessionState.online) return;
|
||||
final st = session.state();
|
||||
if (st != 'online' && st != 'connected') {
|
||||
logger.w('kolibri сессия "$st" — реконнект');
|
||||
logger.w('kusoft сессия "$st" — реконнект');
|
||||
_onDisconnected();
|
||||
return;
|
||||
}
|
||||
final interactive = !KometSettings.ghostMode.value;
|
||||
final interactive = !QlyraSettings.ghostMode.value;
|
||||
if (interactive != _lastInteractive) {
|
||||
_lastInteractive = interactive;
|
||||
try {
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import '../api.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/opcode_map.dart';
|
||||
import '../../core/protocol/packet.dart';
|
||||
@@ -534,7 +534,7 @@ class AccountModule {
|
||||
}) {
|
||||
final payload = <dynamic, dynamic>{
|
||||
'token': token,
|
||||
'interactive': interactive ?? !KometSettings.ghostMode.value,
|
||||
'interactive': interactive ?? !QlyraSettings.ghostMode.value,
|
||||
'exp': {
|
||||
'chatsCountGroups': Uint8List.fromList([0x0b, 0x32]),
|
||||
},
|
||||
@@ -645,7 +645,9 @@ class AccountModule {
|
||||
Future<ProfileData> _resurrectProfile(int accountId) async {
|
||||
if (DebugTest.berserk) {
|
||||
await AppDatabase.deleteAccount(accountId);
|
||||
logger.w('login: [BERSERK] профиль удалён из БД, форсирую регенерацию (id=$accountId)');
|
||||
logger.w(
|
||||
'login: [BERSERK] профиль удалён из БД, форсирую регенерацию (id=$accountId)',
|
||||
);
|
||||
} else {
|
||||
final cached = await AppDatabase.loadProfile(accountId);
|
||||
if (cached != null) return cached;
|
||||
@@ -656,11 +658,15 @@ class AccountModule {
|
||||
try {
|
||||
final fetched = await ContactsModule.fetchSelfProfile(_api, accountId);
|
||||
if (fetched != null) {
|
||||
logger.i('login: профиль восстановлен через CONTACT_INFO (id=$accountId)');
|
||||
logger.i(
|
||||
'login: профиль восстановлен через CONTACT_INFO (id=$accountId)',
|
||||
);
|
||||
return fetched;
|
||||
}
|
||||
} catch (e) {
|
||||
logger.w('login: восстановление профиля через CONTACT_INFO не удалось: $e');
|
||||
logger.w(
|
||||
'login: восстановление профиля через CONTACT_INFO не удалось: $e',
|
||||
);
|
||||
}
|
||||
|
||||
logger.w('login: профиль недоступен, использую заглушку (id=$accountId)');
|
||||
|
||||
@@ -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;
|
||||
|
||||
final Map<int, Animoji> _byId = {};
|
||||
|
||||
@@ -266,13 +266,14 @@ int? _otherParticipantId(dynamic participants, int currentUserId) {
|
||||
String? _nameFromContact(Map<dynamic, dynamic> contact) {
|
||||
final names = contact['names'];
|
||||
if (names is! List || names.isEmpty) return null;
|
||||
final nameRaw = names.firstWhere(
|
||||
(n) => n is Map && n['type'] == 'ONEME',
|
||||
orElse: () => names.firstWhere((n) => n is Map, orElse: () => null),
|
||||
);
|
||||
if (nameRaw is! Map) return null;
|
||||
final name = nameRaw;
|
||||
return name['name'] as String?;
|
||||
Map<dynamic, dynamic>? fallback;
|
||||
for (final entry in names) {
|
||||
if (entry is! Map) continue;
|
||||
final name = entry.cast<dynamic, dynamic>();
|
||||
fallback ??= name;
|
||||
if (name['type'] == 'ONEME') return name['name'] as String?;
|
||||
}
|
||||
return fallback?['name'] as String?;
|
||||
}
|
||||
|
||||
List<ChatSearchHit> parseSearchResult(dynamic payload) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:convert';
|
||||
|
||||
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/packet.dart';
|
||||
import '../../core/cache/info_cache.dart';
|
||||
@@ -446,7 +446,7 @@ class ChatsModule {
|
||||
|
||||
/// Sentinel в `lastMsgText` когда последнее сообщение в чате удалено,
|
||||
/// а кеша истории нет — UI должен отрисовать курсивную плашку.
|
||||
static const String lastMsgPlaceholder = '__komet_lastmsg_placeholder__';
|
||||
static const String lastMsgPlaceholder = '__qlyra_lastmsg_placeholder__';
|
||||
|
||||
ChatsModule._();
|
||||
|
||||
@@ -472,7 +472,7 @@ class ChatsModule {
|
||||
if ((row['unread_count'] as int? ?? 0) == 0) return;
|
||||
|
||||
final msgIdNum = int.tryParse(messageId);
|
||||
if (msgIdNum != null && !KometSettings.antiRead.value) {
|
||||
if (msgIdNum != null && !QlyraSettings.antiRead.value) {
|
||||
try {
|
||||
await api.sendRequest(Opcode.chatMark, {
|
||||
'type': 'READ_MESSAGE',
|
||||
@@ -501,7 +501,7 @@ class ChatsModule {
|
||||
required int remaining,
|
||||
}) async {
|
||||
final msgIdNum = int.tryParse(messageId);
|
||||
if (msgIdNum != null && !KometSettings.antiRead.value) {
|
||||
if (msgIdNum != null && !QlyraSettings.antiRead.value) {
|
||||
try {
|
||||
await api.sendRequest(Opcode.chatMark, {
|
||||
'type': 'READ_MESSAGE',
|
||||
@@ -737,7 +737,7 @@ class ChatsModule {
|
||||
}
|
||||
if (chatId == null) return;
|
||||
|
||||
final keepDeleted = KometSettings.viewDeleted.value;
|
||||
final keepDeleted = QlyraSettings.viewDeleted.value;
|
||||
final ids = payload['messageIds'];
|
||||
if (ids is List) {
|
||||
for (final raw in ids) {
|
||||
@@ -803,7 +803,7 @@ class ChatsModule {
|
||||
}
|
||||
|
||||
if (status == 'REMOVED' && msgIdStr != null) {
|
||||
final keepDeleted = KometSettings.viewDeleted.value;
|
||||
final keepDeleted = QlyraSettings.viewDeleted.value;
|
||||
if (keepDeleted) {
|
||||
await AppDatabase.markMessageDeleted(accountId, chatId, msgIdStr);
|
||||
} else {
|
||||
@@ -847,7 +847,7 @@ class ChatsModule {
|
||||
mergedPayload[entry.key.toString()] = entry.value;
|
||||
}
|
||||
final newRow = Map<String, dynamic>.from(existing);
|
||||
if (KometSettings.viewRedacted.value) {
|
||||
if (QlyraSettings.viewRedacted.value) {
|
||||
final oldText = existing['text']?.toString();
|
||||
if ((oldText ?? '') != (msgText ?? '') &&
|
||||
oldText != null &&
|
||||
|
||||
@@ -11,11 +11,7 @@ class CommentsInfo {
|
||||
final String postId;
|
||||
final int? totalCount;
|
||||
final int? updatedAt;
|
||||
const CommentsInfo({
|
||||
required this.postId,
|
||||
this.totalCount,
|
||||
this.updatedAt,
|
||||
});
|
||||
const CommentsInfo({required this.postId, this.totalCount, this.updatedAt});
|
||||
|
||||
factory CommentsInfo.fromPayload(String postId, Map payload) {
|
||||
final raw = payload['totalCount'];
|
||||
@@ -98,7 +94,8 @@ class CommentsModule {
|
||||
|
||||
final link = msg['link'];
|
||||
final postId =
|
||||
(payload['postId'] ?? (link is Map ? link['postId'] : null) ??
|
||||
(payload['postId'] ??
|
||||
(link is Map ? link['postId'] : null) ??
|
||||
msg['postId'])
|
||||
?.toString();
|
||||
if (postId == null || postId.isEmpty) return;
|
||||
|
||||
@@ -577,7 +577,7 @@ class ContactsModule {
|
||||
firstName: '$first ${i + 1}',
|
||||
lastName: last,
|
||||
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,
|
||||
options: i % 6 == 0 ? const {'OFFICIAL'} : const {},
|
||||
),
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:convert' show jsonDecode, utf8;
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:kolibri/kolibri.dart' as kb;
|
||||
import 'package:kusoft/kusoft.dart' as kb;
|
||||
|
||||
import '../api.dart';
|
||||
import '../../core/protocol/opcode_map.dart';
|
||||
@@ -47,7 +47,7 @@ class UploadError extends UploadEvent {
|
||||
}
|
||||
|
||||
/// Оркестратор медиа-загрузок: control-plane (URL, отправка сообщения) идёт
|
||||
/// обычными опкодами, data-plane (заливка на CDN) — через Rust-ядро kolibri,
|
||||
/// обычными опкодами, data-plane (заливка на CDN) — через Rust-ядро kusoft,
|
||||
/// которое стримит файл с диска (не держит его целиком в памяти).
|
||||
class FileUploader {
|
||||
final Api api;
|
||||
@@ -101,39 +101,35 @@ class FileUploader {
|
||||
var status = 0;
|
||||
String? error;
|
||||
final done = Completer<void>();
|
||||
sub =
|
||||
session
|
||||
.uploadFilePath(
|
||||
url: info.url,
|
||||
path: file.path,
|
||||
filename: filename,
|
||||
connection: 'close',
|
||||
)
|
||||
.listen(
|
||||
(e) {
|
||||
switch (e) {
|
||||
case kb.UploadEvent_Progress(:final sent, :final total):
|
||||
ctrl.add(
|
||||
UploadProgress(
|
||||
sent: sent.toInt(),
|
||||
total: total.toInt(),
|
||||
),
|
||||
);
|
||||
case kb.UploadEvent_Done(status: final s):
|
||||
status = s;
|
||||
case kb.UploadEvent_Error(:final message):
|
||||
error = message;
|
||||
}
|
||||
},
|
||||
onError: (Object err) {
|
||||
error = err.toString();
|
||||
if (!done.isCompleted) done.complete();
|
||||
},
|
||||
onDone: () {
|
||||
if (!done.isCompleted) done.complete();
|
||||
},
|
||||
cancelOnError: true,
|
||||
);
|
||||
sub = session
|
||||
.uploadFilePath(
|
||||
url: info.url,
|
||||
path: file.path,
|
||||
filename: filename,
|
||||
connection: 'close',
|
||||
)
|
||||
.listen(
|
||||
(e) {
|
||||
switch (e) {
|
||||
case kb.UploadEvent_Progress(:final sent, :final total):
|
||||
ctrl.add(
|
||||
UploadProgress(sent: sent.toInt(), total: total.toInt()),
|
||||
);
|
||||
case kb.UploadEvent_Done(status: final s):
|
||||
status = s;
|
||||
case kb.UploadEvent_Error(:final message):
|
||||
error = message;
|
||||
}
|
||||
},
|
||||
onError: (Object err) {
|
||||
error = err.toString();
|
||||
if (!done.isCompleted) done.complete();
|
||||
},
|
||||
onDone: () {
|
||||
if (!done.isCompleted) done.complete();
|
||||
},
|
||||
cancelOnError: true,
|
||||
);
|
||||
await done.future;
|
||||
if (cancelled) return;
|
||||
if (error != null) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.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/protocol/opcode_map.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)
|
||||
: results;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:async';
|
||||
|
||||
import '../../core/cache/info_cache.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/utils/logger.dart';
|
||||
import '../api.dart';
|
||||
@@ -40,7 +40,7 @@ class SelfCheckService {
|
||||
Future<void> _check() async {
|
||||
final api = _api;
|
||||
if (api == null || api.state != SessionState.online) return;
|
||||
if (!KometSettings.selfOnlineCheck.value) return;
|
||||
if (!QlyraSettings.selfOnlineCheck.value) return;
|
||||
final accountId = await TokenStorage.getActiveAccountId();
|
||||
if (accountId == null) return;
|
||||
final presence = await PresenceFetch.get(accountId, forceRefresh: true);
|
||||
|
||||
@@ -45,9 +45,7 @@ class StoriesModule {
|
||||
|
||||
int _nowMs() => DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
int _normMs(int t) => t <= 0
|
||||
? 0
|
||||
: (t < 1000000000000 ? t * 1000 : t);
|
||||
int _normMs(int t) => t <= 0 ? 0 : (t < 1000000000000 ? t * 1000 : t);
|
||||
|
||||
// ── Кэш (SQLite) ───────────────────────────────────────────────────────
|
||||
|
||||
@@ -196,9 +194,7 @@ class StoriesModule {
|
||||
final chunk = missing.sublist(i, end);
|
||||
try {
|
||||
final packet = await _api.sendRequest(Opcode.storiesGetByOwner, {
|
||||
'owners': [
|
||||
for (final id in chunk) StoryOwner(ownerId: id).toMap(),
|
||||
],
|
||||
'owners': [for (final id in chunk) StoryOwner(ownerId: id).toMap()],
|
||||
}, silent: true);
|
||||
if (packet.isError) continue;
|
||||
if (_applyOwnerPayload(packet.payload, chunk)) changed = true;
|
||||
@@ -230,7 +226,8 @@ class StoriesModule {
|
||||
}
|
||||
}
|
||||
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'];
|
||||
if (rawPeers is List) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../main.dart' show KometApp;
|
||||
import '../../main.dart' show QlyraApp;
|
||||
|
||||
enum UploadKind { photo, video, videoNote, voice, file }
|
||||
|
||||
@@ -53,7 +53,7 @@ class _NotificationJob {
|
||||
|
||||
class UploadNotificationService {
|
||||
static const MethodChannel _channel = MethodChannel(
|
||||
'ru.komet.app/upload_service',
|
||||
'ru.qlyra.app/upload_service',
|
||||
);
|
||||
static const int _minIntervalMs = 350;
|
||||
static const Duration _startDelay = Duration(milliseconds: 700);
|
||||
@@ -189,7 +189,7 @@ class UploadNotificationService {
|
||||
}
|
||||
|
||||
static AppLocalizations _localizations() {
|
||||
final context = KometApp.navigatorKey.currentContext;
|
||||
final context = QlyraApp.navigatorKey.currentContext;
|
||||
if (context != null) {
|
||||
final scoped = Localizations.of<AppLocalizations>(
|
||||
context,
|
||||
|
||||
@@ -91,7 +91,9 @@ class WebAppModule {
|
||||
throw const WebAppUnavailable('Нет соединения с сервером');
|
||||
}
|
||||
final normalizedStartParam =
|
||||
(startParam != null && startParam.trim().isNotEmpty) ? startParam : null;
|
||||
(startParam != null && startParam.trim().isNotEmpty)
|
||||
? startParam
|
||||
: null;
|
||||
final packet = await _api.sendRequest(Opcode.webAppInitData, {
|
||||
'botId': botId,
|
||||
'startParam': ?normalizedStartParam,
|
||||
|
||||
@@ -4,8 +4,7 @@ class SelfPresence {
|
||||
static final ValueNotifier<bool> isOnline = ValueNotifier(true);
|
||||
static final ValueNotifier<int?> lastSeenSeconds = ValueNotifier(null);
|
||||
|
||||
static int get _nowSeconds =>
|
||||
DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
static int get _nowSeconds => DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
|
||||
static void markOnline() {
|
||||
isOnline.value = true;
|
||||
|
||||
@@ -11,8 +11,8 @@ class CallBridge {
|
||||
CallBridge._();
|
||||
static final CallBridge instance = CallBridge._();
|
||||
|
||||
static const _method = MethodChannel('ru.komet.app/calls');
|
||||
static const _events = EventChannel('ru.komet.app/calls_events');
|
||||
static const _method = MethodChannel('ru.qlyra.app/calls');
|
||||
static const _events = EventChannel('ru.qlyra.app/calls_events');
|
||||
|
||||
bool _started = false;
|
||||
|
||||
|
||||