1
0
Fork 1

Compare commits

..

No commits in common. "2.3.3" and "0.24.0" have entirely different histories.

959 changed files with 12111 additions and 105402 deletions

View file

@ -1,12 +0,0 @@
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=true
indent_style=space
indent_size=4
[*.json]
indent_size=2
[*.{kt,kts}]
disabled_rules=import-ordering,no-wildcard-imports

View file

@ -1,12 +1,3 @@
---
name: Bug report
about: Utwórz raport błędu, aby pomóc nam ulepszyć Wulkanowego
title: ''
labels: ''
assignees: ''
---
## Co powinno się dziać ## Co powinno się dziać

View file

@ -1,20 +0,0 @@
---
name: Feature request
about: Zaproponuj nowy pomysł dla Wulkanowego
title: ''
labels: ''
assignees: ''
---
** Czy Twoja prośba o funkcję jest związana z problemem? Proszę opisz.**
Jasny i zwięzły opis problemu. Np. Zawsze jestem sfrustrowany, gdy [...]
** Opisz żądane rozwiązanie **
Jasny i zwięzły opis tego, co chcesz, aby się wydarzyło.
** Opisz alternatywy, które rozważałeś **
Jasny i zwięzły opis wszelkich rozważanych alternatywnych rozwiązań lub funkcji.
** Dodatkowy kontekst **
Dodaj inny kontekst lub zrzuty ekranu dotyczące żądania funkcji tutaj.

View file

@ -1,12 +0,0 @@
version: 2
updates:
- package-ecosystem: gradle
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
target-branch: develop
ignore:
- dependency-name: io.github.wulkanowy:sdk
reviewers:
- Faierbel

View file

@ -1,79 +0,0 @@
name: Deploy release
on:
release:
types: [ created ]
jobs:
deploy-google-play:
name: Google Play
runs-on: ubuntu-latest
timeout-minutes: 10
environment: google-play
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 17
- uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Decrypt keys
env:
ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
run: |
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
- name: Upload apk to google play
env:
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
ANDROID_PUBLISHER_CREDENTIALS: ${{ secrets.ANDROID_PUBLISHER_CREDENTIALS }}
ADMOB_PROJECT_ID: ${{ secrets.ADMOB_PROJECT_ID }}
SINGLE_SUPPORT_AD_ID: ${{ secrets.SINGLE_SUPPORT_AD_ID }}
DASHBOARD_TILE_AD_ID: ${{ secrets.DASHBOARD_TILE_AD_ID }}
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
run: ./gradlew publishPlayReleaseApps -PenableFirebase --stacktrace;
deploy-app-gallery:
name: AppGallery
runs-on: ubuntu-latest
timeout-minutes: 10
environment: app-gallery
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 17
- uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Decrypt keys
env:
ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
run: |
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/agconnect-services.json.gpg
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
- name: Prepare credentials
env:
AGC_CREDENTIALS: ${{ secrets.AGC_CREDENTIALS }}
run: echo $AGC_CREDENTIALS > ./app/src/release/agconnect-credentials.json
- name: Build and publish HMS version
env:
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
SET_BUILD_TIMESTAMP: ${{ secrets.SET_BUILD_TIMESTAMP }}
run: ./gradlew bundleHmsRelease --stacktrace && ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace

View file

@ -1,146 +0,0 @@
name: Deploy DEV
on:
push:
# branches: [ develop ]
branches: [ '!*' ]
pull_request_target:
# branches: [ develop ]
branches: [ '!*' ]
workflow_dispatch:
jobs:
deploy-appcenter:
name: App Center
runs-on: ubuntu-latest
timeout-minutes: 10
environment: app-center
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 17
- uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Set run number with offset
env:
BUILD_NUMBER_OFFSET: ${{ secrets.BUILD_NUMBER_OFFSET }}
run: echo "RUN_NUMBER=$((GITHUB_RUN_NUMBER+BUILD_NUMBER_OFFSET))" >> $GITHUB_ENV
- name: Prepare build configuration
run: |
sed -i -e "s#applicationIdSuffix \".dev\"#applicationIdSuffix \".${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/build.gradle
sed -i -e "s#.dev\"#.${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/src/debug/google-services.json
sed -i -e "s#.dev\"#.${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/src/debug/agconnect-services.json
sed -i -e '/versionNameSuffix/d' app/build.gradle
- name: Add signing config
run: |
cat >> app/build.gradle <<EOF
android.signingConfigs.debug {
storeFile file("bitrise.jks")
storePassword System.getenv("BITRISE_KEYSTORE_PASSWORD")
keyAlias System.getenv("BITRISE_KEY_ALIAS")
keyPassword System.getenv("BITRISE_KEY_PASSWORD")
}
EOF
- name: Decrypt keys
env:
BITRISE_ENCRYPT_KEY: ${{ secrets.BITRISE_ENCRYPT_KEY }}
run: |
gpg --yes --batch --passphrase=$BITRISE_ENCRYPT_KEY ./app/bitrise.jks.gpg
- name: Bump version
uses: chkfung/android-version-actions@v1.1
with:
gradlePath: app/build.gradle
versionCode: ${{ env.RUN_NUMBER }}
versionName: ${{ env.RUN_NUMBER }}-${{ github.head_ref }}
- name: Build apk
env:
BITRISE_KEYSTORE_PASSWORD: ${{ secrets.BITRISE_KEYSTORE_PASSWORD }}
BITRISE_KEY_ALIAS: ${{ secrets.BITRISE_KEY_ALIAS }}
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
run: ./gradlew assembleFdroidDebug --stacktrace
- name: Upload apk to github artifacts
uses: actions/upload-artifact@v3
with:
name: wulkanowyDEV-${{ env.RUN_NUMBER }}.apk
path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
- name: Deploy to app center
uses: wzieba/AppCenter-Github-Action@v1
with:
appName: wulkanowy/wulkanowy
token: ${{ secrets.APP_CENTER_TOKEN }}
group: Testers
file: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk
notifyTesters: true
debug: true
deploy-app-distribution:
name: App Distribution
runs-on: ubuntu-latest
timeout-minutes: 10
environment: app-distribution
if: github.event_name != 'pull_request_target'
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 17
- uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Set run number with offset
env:
BUILD_NUMBER_OFFSET: ${{ secrets.BUILD_NUMBER_OFFSET }}
run: echo "RUN_NUMBER=$((GITHUB_RUN_NUMBER+BUILD_NUMBER_OFFSET))" >> $GITHUB_ENV
- name: Add signing config
run: |
cat >> app/build.gradle <<EOF
android.signingConfigs.debug {
storeFile file("bitrise.jks")
storePassword System.getenv("BITRISE_KEYSTORE_PASSWORD")
keyAlias System.getenv("BITRISE_KEY_ALIAS")
keyPassword System.getenv("BITRISE_KEY_PASSWORD")
}
EOF
- name: Decrypt keys
env:
BITRISE_ENCRYPT_KEY: ${{ secrets.BITRISE_ENCRYPT_KEY }}
BITRISE_SERVICES_ENCRYPT_KEY: ${{ secrets.BITRISE_SERVICES_ENCRYPT_KEY }}
run: |
gpg --yes --batch --passphrase=$BITRISE_SERVICES_ENCRYPT_KEY ./app/src/debug/google-services.json.gpg
gpg --yes --batch --passphrase=$BITRISE_ENCRYPT_KEY ./app/bitrise.jks.gpg
- name: Bump version
uses: chkfung/android-version-actions@v1.1
with:
gradlePath: app/build.gradle
versionCode: ${{ env.RUN_NUMBER }}
versionName: ${{ env.RUN_NUMBER }}
- name: Build apk
env:
BITRISE_KEYSTORE_PASSWORD: ${{ secrets.BITRISE_KEYSTORE_PASSWORD }}
BITRISE_KEY_ALIAS: ${{ secrets.BITRISE_KEY_ALIAS }}
BITRISE_KEY_PASSWORD: ${{ secrets.BITRISE_KEY_PASSWORD }}
run: ./gradlew assemblePlayDebug -PenableFirebase --stacktrace
- name: Upload apk to github artifacts
uses: actions/upload-artifact@v3
with:
name: wulkanowyDEV-${{ env.RUN_NUMBER }}-dev.apk
path: app/build/outputs/apk/play/debug/app-play-debug.apk
- name: Deploy to app distribution
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{ secrets.FIREBASE_APP_ID }}
token: ${{ secrets.FIREBASE_TOKEN }}
groups: discord
file: app/build/outputs/apk/play/debug/app-play-debug.apk

View file

@ -1,90 +1,141 @@
name: Tests name: Test and deploy
on: on:
push: push:
branches: branches: [ develop ]
- master
- develop
- 'hotfix/**'
tags: [ '*' ] tags: [ '*' ]
pull_request: pull_request:
branches: [ develop ]
workflow_dispatch:
jobs: jobs:
build:
tests-fdroid: name: Pre-build
name: F-Droid
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: fkirc/skip-duplicate-actions@master - uses: fkirc/skip-duplicate-actions@master
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1 - uses: gradle/wrapper-validation-action@v1
- uses: actions/setup-java@v3 - uses: actions/setup-java@v1
with: with:
distribution: 'zulu' java-version: 11
java-version: 17 - uses: actions/cache@v2
- uses: actions/cache@v3
with: with:
path: | path: |
~/.gradle/caches ~/.gradle/caches
~/.gradle/wrapper ~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Unit tests - name: Build
run: | run: ./gradlew --build-cache compileFdroidDebugUnitTestKotlin preFdroidDebugAndroidTestBuild dexBuilderFdroidDebugAndroidTest packageFdroidDebug packageFdroidDebugAndroidTest
./gradlew testFdroidDebugUnitTest --stacktrace - name: Prepare build cache
./gradlew jacocoTestReport --stacktrace run: tar -cf prebuild.tar .build-cache .gradle app/build
- uses: codecov/codecov-action@v3 - uses: actions/upload-artifact@v2
with: with:
flags: unit name: prebuild.tar
path: prebuild.tar
tests-play: unit-tests:
name: Play name: Unit tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 10 timeout-minutes: 10
needs: [ build ]
steps: steps:
- uses: fkirc/skip-duplicate-actions@master - uses: actions/checkout@v2
- uses: actions/checkout@v3 - uses: actions/setup-java@v1
- uses: gradle/wrapper-validation-action@v1
- uses: actions/setup-java@v3
with: with:
distribution: 'zulu' java-version: 11
java-version: 17 - uses: actions/cache@v2
- uses: actions/cache@v3
with: with:
path: | path: |
~/.gradle/caches ~/.gradle/caches
~/.gradle/wrapper ~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- uses: actions/download-artifact@v2
with:
name: prebuild.tar
- name: Extract build cache
run: tar -xf prebuild.tar
- name: Unit tests - name: Unit tests
run: | run: |
./gradlew testPlayDebugUnitTest --stacktrace ./gradlew --build-cache -Pcoverage testFdroidDebugUnitTest --stacktrace
./gradlew jacocoTestReport --stacktrace ./gradlew --build-cache -Pcoverage jacocoTestReport --stacktrace
- uses: codecov/codecov-action@v3 - uses: codecov/codecov-action@v1
with: with:
flags: unit flags: unit
tests-hms: instrumentation-tests:
name: HMS name: Instrumentation tests
runs-on: ubuntu-latest runs-on: macOS-latest
timeout-minutes: 10 timeout-minutes: 15
needs: [ build ]
strategy:
fail-fast: true
matrix:
api-level: [21, 29]
steps: steps:
- uses: fkirc/skip-duplicate-actions@master - uses: actions/checkout@v2
- uses: actions/checkout@v3 - uses: actions/setup-java@v1
- uses: gradle/wrapper-validation-action@v1
- uses: actions/setup-java@v3
with: with:
distribution: 'zulu' java-version: 11
java-version: 17 - uses: actions/cache@v2
- uses: actions/cache@v3
with: with:
path: | path: |
~/.gradle/caches ~/.gradle/caches
~/.gradle/wrapper ~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Unit tests - uses: actions/download-artifact@v2
run: |
./gradlew testHmsDebugUnitTest --stacktrace
./gradlew jacocoTestReport --stacktrace
- uses: codecov/codecov-action@v3
with: with:
flags: unit name: prebuild.tar
- name: Extract build cache
run: tar -xf prebuild.tar
- name: Instrumentation tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
arch: x86
script: |
./gradlew --build-cache -Pcoverage connectedFdroidDebugAndroidTest --stacktrace
./gradlew --build-cache -Pcoverage jacocoTestReport --stacktrace
- uses: codecov/codecov-action@v1
with:
flags: instrumented,api-${{ matrix.api-level }}
deploy-google-play:
name: Deploy to google play
runs-on: ubuntu-latest
timeout-minutes: 10
environment: google-play
needs: [ build, unit-tests, instrumentation-tests ]
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 11
- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- uses: actions/download-artifact@v2
with:
name: prebuild.tar
- name: Extract build cache
run: tar -xf prebuild.tar
- name: Decrypt keys
env:
ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}
SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
run: |
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
- name: Upload apk to google play
env:
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }}
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace;

3
.gitignore vendored
View file

@ -117,6 +117,3 @@ Thumbs.db
app/src/release/agconnect-services.json app/src/release/agconnect-services.json
app/src/release/agconnect-credentials.json
.idea/deploymentTargetDropDown.xml
.idea/kotlinc.xml

View file

@ -2,8 +2,34 @@
<code_scheme name="Project" version="173"> <code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" /> <option name="LINE_SEPARATOR" value="&#10;" />
<JetCodeStyleSettings> <JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="false" />
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="false" />
<option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="false" />
<option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="false" />
<option name="CONTINUATION_INDENT_IN_SUPERTYPE_LISTS" value="false" />
<option name="CONTINUATION_INDENT_IN_IF_CONDITIONS" value="false" />
<option name="CONTINUATION_INDENT_IN_ELVIS" value="false" />
<option name="WRAP_ELVIS_EXPRESSIONS" value="0" />
</JetCodeStyleSettings> </JetCodeStyleSettings>
<MarkdownNavigatorCodeStyleSettings>
<option name="RIGHT_MARGIN" value="72" />
</MarkdownNavigatorCodeStyleSettings>
<codeStyleSettings language="XML"> <codeStyleSettings language="XML">
<indentOptions> <indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" /> <option name="CONTINUATION_INDENT_SIZE" value="4" />
@ -117,7 +143,16 @@
</arrangement> </arrangement>
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="kotlin"> <codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings> </codeStyleSettings>
</code_scheme> </code_scheme>
</component> </component>

10
.idea/migrations.xml generated
View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

View file

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2023 Wulkanowy Copyright 2019 Wulkanowy
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View file

@ -1,73 +0,0 @@
Česká verze / [Deutsche Version](README.de.md) / [English version](README.en.md) / [Polska wersja](README.md) / [Slovenská verzia](README.sk.md)
# Wulkanowy
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/)
[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases)
[![Crowdin](https://badges.crowdin.net/wulkanowy2/localized.svg)](https://translate.wulkanowy.net.pl)
Neoficiální klient deníku VULCAN UONET+ pro žáka a rodiče
## Funkce
* přihlášení pomocí emailu a hesla
* funkce z webové stránky deníku:
* známky
* statistiky známek
* frekvence
* procento frekvence
* zkoušky
* plán lekce
* dokončené lekce
* zprávy
* domácí úkoly
* poznámky
* šťastné číslo
* další lekce
* školní setkání
* informace o žáku a škole
* výpočet průměru nezávisle na preferencích školy
* upozornění, např. o nových známkách
* podpora více účtů s možností přejmenování žáků
* tmavý a černý (AMOLED) motiv
* offline režim
* volitelné reklamy na podporu projektu
## Stáhnout
Aktuální verzi si můžete stáhnout z Google Play, F-Droid nebo Huawei AppGallery
[<img src="https://play.google.com/intl/cs-CZ/badges/images/generic/cs_badge_web_generic.png"
alt="Nyní na Google Play"
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Stáhnout s F-Droid"
height="80">](https://f-droid.org/packages/io.github.wulkanowy/)
[<img src="https://i.imgur.com/baTGiDP.png"
alt="Objevuj v AppGallery"
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
Můžete si také stáhnout [vývojovou verzi](https://wulkanowy.github.io/#download), která zahrnuje nové funkce připravované pro příští vydání
## Postaveno s pomocí
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
* [Hilt](https://dagger.dev/hilt/)
* [Room](https://developer.android.com/topic/libraries/architecture/room)
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
## Spolupráce
Přispějte do projektu vytvořením PR nebo odesláním issue na GitHub.
Pro zájemce o překlad aplikace do různých jazyků poskytujeme Crowdin:
https://crowdin.com/project/wulkanowy2
## Licence
Tento projekt je licencován pod licencí Apache License 2.0 - podrobnosti v souboru [LICENSE](LICENSE)

View file

@ -1,73 +0,0 @@
[Česká verze](README.cs.md) / Deutsche Version / [English version](README.en.md) / [Polska wersja](README.md) / [Slovenská verzia](README.sk.md)
# Wulkanowy
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/)
[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases)
[![Crowdin](https://badges.crowdin.net/wulkanowy2/localized.svg)](https://translate.wulkanowy.net.pl)
Inoffizieller Android VULCAN UONET+ Registrierungsclient für Schüler und ihre Eltern
## Merkmale
* Einloggen mit E-Mail und Passwort
* Funktionen von der Registerwebsite:
* Noten
* Notenstatistik
* Anwesenheit
* Prozentsatz der Anwesenheit
* Prüfungen
* Stundenplan
* abgeschlossene Unterrichtsstunden
* Nachrichten
* Hausaufgaben
* Anmerkungen
* Glückszahl
* Zusätzliche Lektionen
* Schulkonferenzen
* Schüler- und Schulinformationen
* Berechnung des Durchschnitts unabhängig von den Präferenzen der Schule
* Benachrichtigungen, z. B. über eine neue Note
* Unterstützung für mehrere Konten mit der Möglichkeit, den Namen des Schülers zu ändern
* dunkles und schwarzes (AMOLED) Thema
* Offline-Modus
* optionale Werbungen, die es uns ermöglichen das Projekt zu unterstützen
## Herunterladen
Die aktuelle Version können Sie von der Google Play, F-Droid oder Huawei AppGallery store herunterladen
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
alt="Get it on Google Play"
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/io.github.wulkanowy/)
[<img src="appgallery_badge.png"
alt="Explore it on AppGallery"
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
Sie können auch eine [Entwicklungsversion herunterladen](https://wulkanowy.github.io/#download) die beinhaltet neue Funktionen, die für die nächste Version vorbereitet werden
## Gebaut mit
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
* [Hilt](https://dagger.dev/hilt/)
* [Room](https://developer.android.com/topic/libraries/architecture/room)
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
## Beitragen
Bitte tragen Sie zum Projekt bei, indem Sie entweder eine PR erstellen oder ein Issue auf GitHub einreichen.
Für Personen, die daran interessiert sind, die Anwendung in verschiedene Sprachen zu übersetzen, bieten wir Crowdin
https://crowdin.com/project/wulkanowy2
## Lizenz
Dieses Projekt ist unter der Apache License 2.0 lizenziert - siehe die [LIZENZ](LICENSE) Datei für Details

View file

@ -1,19 +1,18 @@
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / English version / [Polska wersja](README.md) / [Slovenská verzia](README.sk.md) [Polska wersja README](README.md)
# Wulkanowy # Wulkanowy
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Test%20and%20deploy/develop?style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/)
[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases) [![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases)
[![Crowdin](https://badges.crowdin.net/wulkanowy2/localized.svg)](https://translate.wulkanowy.net.pl)
Unofficial android VULCAN UONET+ register client for both students and their parents Unofficial android VULCAN UONET+ register client for both students and their parents
## Features ## Features
* logging in using the email and password * logging in using the email and password OR using token and pin
* functions from the register website: * functions from the register website:
* grades * grades
* grade statistics * grade statistics
@ -26,19 +25,15 @@ Unofficial android VULCAN UONET+ register client for both students and their par
* homework * homework
* notes * notes
* lucky number * lucky number
* additional lessons
* school conferences
* student and school information
* calculation of the average independently of school's preferences * calculation of the average independently of school's preferences
* notifications, e.g. about a new grade * notifications, e.g. about a new grade
* support for multiple accounts with the ability to rename students
* dark and black (AMOLED) theme * dark and black (AMOLED) theme
* offline mode * offline mode
* optional ads which allow to support the project * no ads
## Download ## Download
You can download the current version from the Google Play, F-Droid or Huawei AppGallery store You can download the current beta version from the Google Play, F-Droid or Huawei AppGallery store
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" [<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
alt="Get it on Google Play" alt="Get it on Google Play"
@ -65,9 +60,6 @@ You can also download a [development version](https://wulkanowy.github.io/#downl
Please contribute to the project either by creating a PR or submitting an issue on GitHub. Please contribute to the project either by creating a PR or submitting an issue on GitHub.
For people interested in translating the application into different languages, we provide Crowdin
https://crowdin.com/project/wulkanowy2
## License ## License
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details

View file

@ -1,19 +1,18 @@
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / [English version](README.en.md) / Polska wersja / [Slovenská verzia](README.sk.md) [English version of README](README.en.md)
# Wulkanowy # Wulkanowy
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Test%20and%20deploy/develop?style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/)
[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases) [![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases)
[![Crowdin](https://badges.crowdin.net/wulkanowy2/localized.svg)](https://translate.wulkanowy.net.pl)
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
## Funkcje ## Funkcje
* logowanie za pomocą e-maila i hasła * logowanie za pomocą e-maila i hasła LUB tokena i pinu
* funkcje ze strony internetowej dziennika: * funkcje ze strony internetowej dziennika:
* oceny * oceny
* statystyki ocen * statystyki ocen
@ -26,19 +25,15 @@ Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
* zadania domowe * zadania domowe
* uwagi * uwagi
* szczęśliwy numerek * szczęśliwy numerek
* dodatkowe lekcje
* zebrania w szkole
* informacje o uczniu i szkole
* obliczanie średniej niezależnie od preferencji szkoły * obliczanie średniej niezależnie od preferencji szkoły
* powiadomienia np. o nowej ocenie * powiadomienia np. o nowej ocenie
* obsługa wielu kont wraz z możliwością zmiany nazwy ucznia
* ciemny i czarny (AMOLED) motyw * ciemny i czarny (AMOLED) motyw
* tryb offline * tryb offilne
* opcjonalne reklamy umożliwiające wsparcie projektu * brak reklam
## Pobierz ## Pobierz
Aktualną wersję możesz pobrać ze sklepu Google Play, F-Droid lub Huawei AppGallery Aktualną wersję beta możesz pobrać ze sklepu Google Play, F-Droid lub Huawei AppGallery
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" [<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
alt="Pobierz z Google Play" alt="Pobierz z Google Play"
@ -66,9 +61,6 @@ Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#downloa
Wnieś swój wkład w projekt, tworząc PR lub wysyłając issue na GitHub. Wnieś swój wkład w projekt, tworząc PR lub wysyłając issue na GitHub.
Dla osób zainteresowanych tłumaczeniem aplikacji na różne języki udostępniamy Crowdina
https://crowdin.com/project/wulkanowy2
## Licencja ## Licencja
Ten projekt udostępniany jest na licencji Apache License 2.0 - szczegóły w pliku [LICENSE](LICENSE) Ten projekt udostępniany jest na licencji Apache License 2.0 - szczegóły w pliku [LICENSE](LICENSE)

View file

@ -1,73 +0,0 @@
[Česká verze](README.cs.md) / [Deutsche Version](README.de.md) / [English version](README.en.md) / [Polska wersja](README.md) / Slovenská verzia
# Wulkanowy
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/)
[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases)
[![Crowdin](https://badges.crowdin.net/wulkanowy2/localized.svg)](https://translate.wulkanowy.net.pl)
Neoficiálny klient denníka VULCAN UONET+ pre žiaka a rodičov
## Funkcie
* prihlásenie pomocou emailu a hesla
* funkcie z webovej stránky denníka:
* známky
* štatistiky známok
* frekvencia
* percento frekvencie
* skúšky
* plán lekcie
* dokončené lekcie
* správy
* domáce úlohy
* poznámky
* šťastné číslo
* ďalšie lekcie
* školské stretnutie
* informácie o žiakovi a škole
* výpočet priemeru nezávisle od preferencií školy
* upozornenia, napr. o nových známkach
* podpora viacerých účtov s možnosťou premenovania žiakov
* tmavý a čierny (AMOLED) motív
* offline režim
* voliteľné reklamy na podporu projektu
## Stiahnuť
Aktuálnu verziu si môžete stiahnuť z Google Play, F-Droid alebo Huawei AppGallery
[<img src="https://play.google.com/intl/sk/badges/images/generic/sk_badge_web_generic.png"
alt="Nyní na Google Play"
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Stiahnuť s F-Droid"
height="80">](https://f-droid.org/packages/io.github.wulkanowy/)
[<img src="https://i.imgur.com/sX8UyAw.png"
alt="Objavíte v AppGallery"
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
Môžete si tiež stiahnuť [vývojovú verziu](https://wulkanowy.github.io/#download), ktorá zahrňuje nové funkcie pripravované pre budúce vydanie
## Postavené s pomocou
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
* [Hilt](https://dagger.dev/hilt/)
* [Room](https://developer.android.com/topic/libraries/architecture/room)
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
## Spolupráca
Prispejte do projektu vytvorením PR alebo odoslaním issue na GitHub.
Pre záujemcov o preklad aplikácie do rôznych jazykov poskytujeme Crowdin:
https://crowdin.com/project/wulkanowy2
## Licencia
Tento projekt je licencovaný pod licenciou Apache License 2.0 - podrobnosti v súbore [LICENSE](LICENSE)

Binary file not shown.

View file

@ -1,55 +1,44 @@
import com.github.triplet.gradle.androidpublisher.ReleaseStatus
import ru.cian.huawei.publish.ReleaseNote
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlinx-serialization' apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-parcelize'
apply plugin: 'com.google.devtools.ksp'
apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics' apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.github.triplet.play' apply plugin: 'com.github.triplet.play'
apply plugin: 'ru.cian.huawei-publish'
apply plugin: 'com.mikepenz.aboutlibraries.plugin' apply plugin: 'com.mikepenz.aboutlibraries.plugin'
apply plugin: 'com.huawei.agconnect'
apply plugin: 'kotlin-kapt'
apply from: 'jacoco.gradle' apply from: 'jacoco.gradle'
apply from: 'sonarqube.gradle' apply from: 'sonarqube.gradle'
apply from: 'hooks.gradle' apply from: 'hooks.gradle'
android { android {
namespace 'io.github.wulkanowy' compileSdkVersion 30
compileSdk 34 buildToolsVersion '30.0.2'
defaultConfig { defaultConfig {
applicationId "io.github.wulkanowy" applicationId "io.github.wulkanowy"
testApplicationId "io.github.tests.wulkanowy" testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 21 minSdkVersion 17
targetSdkVersion 34 targetSdkVersion 30
versionCode 143 versionCode 78
versionName "2.3.3" versionName "0.24.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true
resValue "string", "app_name", "Wulkanowy" resValue "string", "app_name", "Wulkanowy"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
manifestPlaceholders = [ manifestPlaceholders = [
firebase_enabled: project.hasProperty("enableFirebase"), firebase_enabled: project.hasProperty("enableFirebase")
admob_project_id: ""
] ]
javaCompileOptions {
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "null" annotationProcessorOptions {
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "null" arguments += [
"room.schemaLocation": "$projectDir/schemas".toString(),
if (System.env.SET_BUILD_TIMESTAMP) { "room.incremental" : "true"
buildConfigField "long", "BUILD_TIMESTAMP", String.valueOf(System.currentTimeMillis()) ]
} else { }
buildConfigField "long", "BUILD_TIMESTAMP", "1486235849000"
} }
} }
sourceSets { sourceSets {
// https://github.com/robolectric/robolectric/issues/3928#issuecomment-395309991 androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
debug.assets.srcDirs += files("$projectDir/schemas".toString())
} }
signingConfigs { signingConfigs {
@ -67,83 +56,64 @@ android {
shrinkResources true shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release signingConfig signingConfigs.release
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"'
} }
debug { debug {
minifyEnabled false resValue "string", "app_name", "Wulkanowy DEV " + defaultConfig.versionCode
shrinkResources false
resValue "string", "app_name", "Wulkanowy DEV"
applicationIdSuffix ".dev" applicationIdSuffix ".dev"
versionNameSuffix "-dev" versionNameSuffix "-dev"
testCoverageEnabled = project.hasProperty('coverage')
ext.enableCrashlytics = project.hasProperty("enableFirebase") ext.enableCrashlytics = project.hasProperty("enableFirebase")
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"'
} }
} }
flavorDimensions += "platform" flavorDimensions "platform"
productFlavors { productFlavors {
hms { hms {
dimension "platform" dimension "platform"
manifestPlaceholders = [install_channel: "AppGallery"] minSdkVersion 19
manifestPlaceholders = [
install_channel: "AppGallery"
]
} }
play { play {
dimension "platform" dimension "platform"
manifestPlaceholders = [ manifestPlaceholders = [
install_channel : "Google Play", install_channel: "Google Play"
admob_project_id: System.getenv("ADMOB_PROJECT_ID") ?: "ca-app-pub-3940256099942544~3347511713"
] ]
buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "\"${System.getenv("SINGLE_SUPPORT_AD_ID") ?: "ca-app-pub-3940256099942544/5354046379"}\""
buildConfigField "String", "DASHBOARD_TILE_AD_ID", "\"${System.getenv("DASHBOARD_TILE_AD_ID") ?: "ca-app-pub-3940256099942544/6300978111"}\""
} }
fdroid { fdroid {
dimension "platform" dimension "platform"
manifestPlaceholders = [install_channel: "F-Droid"] manifestPlaceholders = [
install_channel: "F-Droid"
]
} }
} }
playConfigs {
play { enabled.set(true) }
}
buildFeatures { buildFeatures {
viewBinding true viewBinding = true
buildConfig true
} }
bundle { lintOptions {
language { disable 'HardwareIds'
enableSplit = false
}
}
testOptions {
unitTests.includeAndroidResources = true
// workaround HMS test errors https://github.com/robolectric/robolectric/issues/2750
unitTests.all { jvmArgs '-noverify' }
} }
compileOptions { compileOptions {
coreLibraryDesugaringEnabled true coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_1_8
} }
kotlinOptions { kotlinOptions {
jvmTarget = "17" jvmTarget = "1.8"
freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"] freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
} }
packagingOptions { packagingOptions {
resources { exclude 'META-INF/library_release.kotlin_module'
excludes += ['META-INF/library_release.kotlin_module', exclude 'META-INF/library-core_release.kotlin_module'
'META-INF/library-core_release.kotlin_module']
}
} }
aboutLibraries { aboutLibraries {
@ -151,141 +121,107 @@ android {
} }
} }
kapt {
correctErrorTypes true
}
ksp {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
play { play {
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf"
serviceAccountCredentials = file('key.p12')
defaultToAppBundles = false defaultToAppBundles = false
track = 'production' track = 'alpha'
releaseStatus = ReleaseStatus.IN_PROGRESS
userFraction = 0.99d
updatePriority = 3 updatePriority = 3
enabled.set(false)
}
huaweiPublish {
instances {
hmsRelease {
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
buildFormat = "aab"
deployType = "publish"
releaseNotes = [
new ReleaseNote(
"pl-PL",
"$projectDir/src/main/play/release-notes/pl-PL/default.txt"
)
]
}
}
} }
ext { ext {
work_manager = "2.9.0" work_manager = "2.4.0"
android_hilt = "1.1.0" room = "2.2.6"
room = "2.6.1" chucker = "3.4.0"
chucker = "4.0.0" mockk = "1.10.5"
mockk = "1.13.9" moshi = "1.11.0"
coroutines = "1.7.3"
} }
dependencies { dependencies {
implementation 'io.github.wulkanowy:sdk:2.3.5' implementation "io.github.wulkanowy:sdk:0.24.0"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'
implementation 'androidx.core:core-ktx:1.12.0' implementation "androidx.core:core-ktx:1.3.2"
implementation 'androidx.core:core-splashscreen:1.0.1' implementation "androidx.activity:activity-ktx:1.1.0"
implementation "androidx.activity:activity-ktx:1.8.2" implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.appcompat:appcompat:1.6.1" implementation "androidx.appcompat:appcompat-resources:1.2.0"
implementation "androidx.fragment:fragment-ktx:1.6.2" implementation "androidx.fragment:fragment-ktx:1.2.5"
implementation "androidx.annotation:annotation:1.7.1" implementation "androidx.annotation:annotation:1.1.0"
implementation "androidx.multidex:multidex:2.0.1"
implementation "androidx.preference:preference-ktx:1.2.1" implementation "androidx.preference:preference-ktx:1.1.1"
implementation "androidx.recyclerview:recyclerview:1.3.2" implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.viewpager2:viewpager2:1.1.0-beta02" implementation "androidx.viewpager:viewpager:1.0.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "androidx.constraintlayout:constraintlayout:2.1.4" implementation "androidx.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0" implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
implementation "com.google.android.material:material:1.10.0" implementation "com.google.android.material:material:1.2.1"
implementation "com.github.wulkanowy:material-chips-input:2.3.1" implementation "com.github.wulkanowy:material-chips-input:2.1.1"
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
implementation 'com.github.lopspower:CircularImageView:4.3.0' implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
implementation "androidx.work:work-runtime:$work_manager" implementation "androidx.work:work-runtime-ktx:$work_manager"
playImplementation "androidx.work:work-gcm:$work_manager" playImplementation "androidx.work:work-gcm:$work_manager"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-runtime:$room"
implementation "androidx.room:room-ktx:$room" implementation "androidx.room:room-ktx:$room"
ksp "androidx.room:room-compiler:$room" kapt "androidx.room:room-compiler:$room"
implementation "com.google.dagger:hilt-android:$hilt_version" implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version" kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
kapt "androidx.hilt:hilt-compiler:$android_hilt" implementation 'androidx.hilt:hilt-work:1.0.0-alpha02'
implementation "androidx.hilt:hilt-work:$android_hilt" kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
implementation 'com.github.ncapdevi:FragNav:3.3.0' implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
implementation "com.github.YarikSOffice:lingver:1.3.0" implementation "com.ncapdevi:frag-nav:3.3.0"
implementation "com.github.YarikSOffice:lingver:1.2.2"
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation "com.squareup.moshi:moshi:$moshi"
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0" implementation "com.squareup.moshi:moshi-adapters:$moshi"
implementation "com.squareup.okhttp3:logging-interceptor:4.12.0" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi"
implementation "com.jakewharton.timber:timber:4.7.1"
implementation "com.jakewharton.timber:timber:5.0.1" implementation "at.favre.lib:slf4j-timber:1.0.1"
implementation 'com.github.Faierbel:slf4j-timber:2.0' implementation "fr.bipi.treessence:treessence:0.3.2"
implementation 'com.github.bastienpaulfr:Treessence:1.1.2'
implementation "com.mikepenz:aboutlibraries-core:$about_libraries" implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
implementation 'io.coil-kt:coil:2.5.0' implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
implementation "io.github.wulkanowy:AppKillerManager:3.0.1" implementation "io.coil-kt:coil:1.1.1"
implementation 'me.xdrop:fuzzywuzzy:1.4.0' implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
implementation 'com.fredporciuncula:flow-preferences:1.9.1' implementation 'me.xdrop:fuzzywuzzy:1.3.1'
implementation 'org.apache.commons:commons-text:1.11.0'
playImplementation platform('com.google.firebase:firebase-bom:32.7.0') playImplementation platform('com.google.firebase:firebase-bom:26.3.0')
playImplementation 'com.google.firebase:firebase-analytics' playImplementation 'com.google.firebase:firebase-analytics-ktx'
playImplementation 'com.google.firebase:firebase-messaging' playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx'
playImplementation "com.google.firebase:firebase-inappmessaging-ktx"
playImplementation 'com.google.firebase:firebase-messaging:'
playImplementation 'com.google.firebase:firebase-crashlytics:' playImplementation 'com.google.firebase:firebase-crashlytics:'
playImplementation 'com.google.firebase:firebase-config' playImplementation 'com.google.android.play:core-ktx:1.8.1'
playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
playImplementation 'com.google.android.gms:play-services-ads:22.6.0' hmsImplementation 'com.huawei.hms:hianalytics:5.1.0.301'
playImplementation "com.google.android.play:integrity:1.3.0" hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.4.2.301'
playImplementation 'com.google.android.play:app-update-ktx:2.1.0'
playImplementation 'com.google.android.play:review-ktx:2.0.1'
playImplementation "com.google.android.ump:user-messaging-platform:2.1.0"
hmsImplementation 'com.huawei.hms:hianalytics:6.12.0.300' releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.9.1.303'
releaseImplementation "com.github.chuckerteam.chucker:library-no-op:$chucker" debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
debugImplementation "com.amitshekhar.android:debug-db:1.0.6"
debugImplementation "com.github.chuckerteam.chucker:library:$chucker" testImplementation "junit:junit:4.13.1"
debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:1.0.6'
debugImplementation 'com.github.haroldadmin:WhatTheStack:1.0.0-alpha04'
testImplementation "junit:junit:4.13.2"
testImplementation "io.mockk:mockk:$mockk" testImplementation "io.mockk:mockk:$mockk"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines" testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2'
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testImplementation 'org.robolectric:robolectric:4.11.1' androidTestImplementation "androidx.test:core:1.3.0"
testImplementation "androidx.test:runner:1.5.2" androidTestImplementation "androidx.test:runner:1.3.0"
testImplementation "androidx.test.ext:junit:1.1.5" androidTestImplementation "androidx.test.ext:junit:1.1.2"
testImplementation "androidx.test:core:1.5.0"
testImplementation "androidx.room:room-testing:$room"
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version"
androidTestImplementation "androidx.test:core:1.5.0"
androidTestImplementation "androidx.test:runner:1.5.2"
androidTestImplementation "androidx.test.ext:junit:1.1.5"
androidTestImplementation "io.mockk:mockk-android:$mockk" androidTestImplementation "io.mockk:mockk-android:$mockk"
androidTestImplementation "androidx.room:room-testing:$room"
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
} }
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.huawei.agconnect'

View file

@ -1,23 +1,23 @@
apply plugin: "jacoco" apply plugin: "jacoco"
jacoco { jacoco {
toolVersion "0.8.11" toolVersion "0.8.5"
reportsDirectory.set(file("$buildDir/reports")) reportsDir = file("$buildDir/reports")
} }
tasks.withType(Test).configureEach { tasks.withType(Test) {
jacoco.includeNoLocationClasses = true jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*'] jacoco.excludes = ['jdk.internal.*']
} }
tasks.register('jacocoTestReport', JacocoReport) { task jacocoTestReport(type: JacocoReport) {
group = "Reporting" group = "Reporting"
description = "Generate Jacoco coverage reports" description = "Generate Jacoco coverage reports"
reports { reports {
xml.required.set(true) xml.enabled = true
html.required.set(true) html.enabled = true
} }
def excludes = ['**/R.class', def excludes = ['**/R.class',

BIN
app/key.p12.gpg Normal file

Binary file not shown.

View file

@ -1,22 +1,33 @@
# General # Optimizations
-optimizationpasses 5
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-dontobfuscate -dontobfuscate
-ignorewarnings -allowaccessmodification
-repackageclasses ''
-verbose
#Config for wulkanowy #Keep all wulkanowy files
-keep class io.github.wulkanowy.** {*;} -keep class io.github.wulkanowy.** {*;}
#Config for firebase crashlitycs #Config for anallitycs
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable -keepattributes SourceFile,LineNumberTable
-keep class com.crashlytics.** {*;}
-keep public class * extends java.lang.Exception -keep public class * extends java.lang.Exception
-dontwarn com.crashlytics.**
#Config for Okio and OkHttp #Config for OkHttp
-dontwarn javax.annotation.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase -keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-dontwarn org.codehaus.mojo.animal_sniffer.* -dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.ConscryptPlatform -dontwarn okhttp3.internal.platform.ConscryptPlatform
-dontwarn javax.annotation.**
#Config for MPAndroidChart #Config for MPAndroidChart
@ -27,16 +38,8 @@
-keep class com.google.android.material.tabs.** { *; } -keep class com.google.android.material.tabs.** { *; }
#Config for HMS SDK #Config for About Libraries
-keepattributes *Annotation* -keep class .R
-keepattributes Exceptions -keep class **.R$* {
-keepattributes InnerClasses <fields>;
-keepattributes Signature }
-keep class com.huawei.agconnect.**{*;}
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
#Config for Wulkanowy SDK
-keep,allowobfuscation,allowshrinking class retrofit2.Response

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
package io.github.wulkanowy.data
import io.github.wulkanowy.utils.DispatchersProvider
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
class TestDispatchersProvider : DispatchersProvider() {
override val backgroundThread: CoroutineDispatcher
get() = Dispatchers.Unconfined
}

View file

@ -3,45 +3,33 @@ package io.github.wulkanowy.data.db.migrations
import android.content.Context import android.content.Context
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.room.Room import androidx.room.Room
import androidx.room.migration.Migration
import androidx.room.testing.MigrationTestHelper import androidx.room.testing.MigrationTestHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.utils.AppInfo
import org.junit.Rule import org.junit.Rule
abstract class AbstractMigrationTest { abstract class AbstractMigrationTest {
val dbName = "migration-test" val dbName = "migration-test"
private val context: Context get() = ApplicationProvider.getApplicationContext()
@get:Rule @get:Rule
val helper: MigrationTestHelper = MigrationTestHelper( val helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(), InstrumentationRegistry.getInstrumentation(),
AppDatabase::class.java, AppDatabase::class.java.canonicalName,
listOf(Migration55()),
FrameworkSQLiteOpenHelperFactory() FrameworkSQLiteOpenHelperFactory()
) )
fun runMigrationsAndValidate(migration: Migration) {
helper.runMigrationsAndValidate(dbName, migration.endVersion, true, migration).close()
}
fun getMigratedRoomDatabase(): AppDatabase { fun getMigratedRoomDatabase(): AppDatabase {
val database = Room.databaseBuilder( val context = ApplicationProvider.getApplicationContext<Context>()
ApplicationProvider.getApplicationContext(), val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
AppDatabase::class.java, AppDatabase::class.java, dbName)
dbName .addMigrations(*AppDatabase.getMigrations(SharedPrefProvider(PreferenceManager
).addMigrations( .getDefaultSharedPreferences(context)))
*AppDatabase.getMigrations(
SharedPrefProvider(PreferenceManager.getDefaultSharedPreferences(context)),
AppInfo()
) )
).build() .build()
// close the database and release any stream resources when the test finishes // close the database and release any stream resources when the test finishes
helper.closeWhenFinished(database) helper.closeWhenFinished(database)
return database return database

View file

@ -2,38 +2,32 @@ package io.github.wulkanowy.data.db.migrations
import android.content.ContentValues import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL import android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL
import android.os.Build
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import dagger.hilt.android.testing.HiltAndroidTest import androidx.test.ext.junit.runners.AndroidJUnit4
import dagger.hilt.android.testing.HiltTestApplication
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import kotlin.test.assertEquals import kotlin.test.assertEquals
@HiltAndroidTest @RunWith(AndroidJUnit4::class)
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class)
class Migration12Test : AbstractMigrationTest() { class Migration12Test : AbstractMigrationTest() {
@Test @Test
fun twoNotRelatedStudents() { fun twoNotRelatedStudents() {
helper.createDatabase(dbName, 11).apply { helper.createDatabase(dbName, 11).apply {
// user 1 // user 1
createStudent(this, 1) createStudent(this, 1, true)
createSemester(this, 1, false, 5, 1) createSemester(this, 1, false, 5, 1)
createSemester(this, 1, true, 5, 2) createSemester(this, 1, true, 5, 2)
// user 2 // user 2
createStudent(this, 2) createStudent(this, 2, true)
createSemester(this, 2, false, 6, 1) createSemester(this, 2, false, 6, 1)
createSemester(this, 2, true, 6, 2) createSemester(this, 2, true, 6, 2)
close() close()
} }
runMigrationsAndValidate(Migration12()) helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
val db = getMigratedRoomDatabase() val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() } val students = runBlocking { db.studentDao.loadAll() }
@ -49,21 +43,20 @@ class Migration12Test : AbstractMigrationTest() {
assertEquals(2, studentId) assertEquals(2, studentId)
assertEquals(6, classId) assertEquals(6, classId)
} }
db.close()
} }
@Test @Test
fun removeStudentsWithoutClassId() { fun removeStudentsWithoutClassId() {
helper.createDatabase(dbName, 11).apply { helper.createDatabase(dbName, 11).apply {
// user 1 // user 1
createStudent(this, 1) createStudent(this, 1, true)
createSemester(this, 1, false, 0, 2) createSemester(this, 1, false, 0, 2)
createStudent(this, 2) createStudent(this, 2, true)
createSemester(this, 2, true, 1, 2) createSemester(this, 2, true, 1, 2)
close() close()
} }
runMigrationsAndValidate(Migration12()) helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
val db = getMigratedRoomDatabase() val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() } val students = runBlocking { db.studentDao.loadAll() }
@ -74,23 +67,22 @@ class Migration12Test : AbstractMigrationTest() {
assertEquals(2, studentId) assertEquals(2, studentId)
assertEquals(1, classId) assertEquals(1, classId)
} }
db.close()
} }
@Test @Test
fun ensureThereIsOnlyOneCurrentStudent() { fun ensureThereIsOnlyOneCurrentStudent() {
helper.createDatabase(dbName, 11).apply { helper.createDatabase(dbName, 11).apply {
// user 1 // user 1
createStudent(this, 1) createStudent(this, 1, true)
createSemester(this, 1, true, 5, 2) createSemester(this, 1, true, 5, 2)
createStudent(this, 2) createStudent(this, 2, true)
createSemester(this, 2, true, 6, 2) createSemester(this, 2, true, 6, 2)
createStudent(this, 3) createStudent(this, 3, true)
createSemester(this, 3, false, 7, 2) createSemester(this, 3, false, 7, 2)
close() close()
} }
runMigrationsAndValidate(Migration12()) helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
val db = getMigratedRoomDatabase() val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() } val students = runBlocking { db.studentDao.loadAll() }
@ -109,10 +101,9 @@ class Migration12Test : AbstractMigrationTest() {
assertEquals(studentId, 3) assertEquals(studentId, 3)
assertEquals(true, isCurrent) assertEquals(true, isCurrent)
} }
db.close()
} }
private fun createStudent(db: SupportSQLiteDatabase, studentId: Int) { private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, isCurrent: Boolean) {
db.insert("Students", CONFLICT_FAIL, ContentValues().apply { db.insert("Students", CONFLICT_FAIL, ContentValues().apply {
put("endpoint", "https://fakelog.cf") put("endpoint", "https://fakelog.cf")
put("loginType", "STANDARD") put("loginType", "STANDARD")
@ -123,7 +114,7 @@ class Migration12Test : AbstractMigrationTest() {
put("student_name", "Jan Kowalski") put("student_name", "Jan Kowalski")
put("school_id", "000123") put("school_id", "000123")
put("school_name", "") put("school_name", "")
put("is_current", true) put("is_current", isCurrent)
put("registration_date", "0") put("registration_date", "0")
}) })
} }

View file

@ -2,26 +2,17 @@ package io.github.wulkanowy.data.db.migrations
import android.content.ContentValues import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import android.os.Build
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.HiltTestApplication
import io.github.wulkanowy.data.db.Converters import io.github.wulkanowy.data.db.Converters
import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Semester
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import java.time.LocalDate.of import java.time.LocalDate.of
import kotlin.test.assertFalse import kotlin.test.assertFalse
import kotlin.test.assertTrue import kotlin.test.assertTrue
@HiltAndroidTest
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class)
class Migration13Test : AbstractMigrationTest() { class Migration13Test : AbstractMigrationTest() {
@Test @Test
@ -57,8 +48,6 @@ class Migration13Test : AbstractMigrationTest() {
assertEquals("C", className) assertEquals("C", className)
assertEquals("Publiczna szkoła Wulkanowego-fejka nr 2 w fakelog.cf", schoolName) assertEquals("Publiczna szkoła Wulkanowego-fejka nr 2 w fakelog.cf", schoolName)
} }
db.close()
} }
@Test @Test
@ -87,30 +76,28 @@ class Migration13Test : AbstractMigrationTest() {
assertEquals("", className) assertEquals("", className)
assertEquals("Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", schoolName) assertEquals("Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", schoolName)
} }
db.close()
} }
@Test @Test
fun markAtLeastAndOnlyOneSemesterAtCurrent() { fun markAtLeastAndOnlyOneSemesterAtCurrent() {
helper.createDatabase(dbName, 12).apply { helper.createDatabase(dbName, 12).apply {
createStudent(this, 1, "", 5) createStudent(this, 1, "", 5)
createSemester(this, 1, 1, 1, false) createSemester(this, 1, 5, 1, 1, false)
createSemester(this, 1, 2, 1, false) createSemester(this, 1, 5, 2, 1, false)
createSemester(this, 1, 3, 2, false) createSemester(this, 1, 5, 3, 2, false)
createSemester(this, 1, 4, 2, false) createSemester(this, 1, 5, 4, 2, false)
createStudent(this, 2, "", 5) createStudent(this, 2, "", 5)
createSemester(this, 2, 5, 5, true) createSemester(this, 2, 5, 5, 5, true)
createSemester(this, 2, 6, 5, true) createSemester(this, 2, 5, 6, 5, true)
createSemester(this, 2, 7, 55, true) createSemester(this, 2, 5, 7, 55, true)
createSemester(this, 2, 8, 55, true) createSemester(this, 2, 5, 8, 55, true)
createStudent(this, 3, "", 5) createStudent(this, 3, "", 5)
createSemester(this, 3, 11, 99, false) createSemester(this, 3, 5, 11, 99, false)
createSemester(this, 3, 12, 99, false) createSemester(this, 3, 5, 12, 99, false)
createSemester(this, 3, 13, 100, false) createSemester(this, 3, 5, 13, 100, false)
createSemester(this, 3, 14, 100, true) createSemester(this, 3, 5, 14, 100, true)
close() close()
} }
@ -152,32 +139,28 @@ class Migration13Test : AbstractMigrationTest() {
assertFalse(semesters[2].second) assertFalse(semesters[2].second)
assertTrue(semesters[3].second) assertTrue(semesters[3].second)
} }
db.close()
} }
private fun getSemesters(db: SupportSQLiteDatabase, query: String): List<Pair<Semester, Boolean>> { private fun getSemesters(db: SupportSQLiteDatabase, query: String): List<Pair<Semester, Boolean>> {
val semesters = mutableListOf<Pair<Semester, Boolean>>() val semesters = mutableListOf<Pair<Semester, Boolean>>()
db.query(query).use { val cursor = db.query(query)
if (it.moveToFirst()) { if (cursor.moveToFirst()) {
do { do {
semesters.add(Semester( semesters.add(Semester(
studentId = it.getInt(1), studentId = cursor.getInt(1),
diaryId = it.getInt(2), diaryId = cursor.getInt(2),
kindergartenDiaryId = 0, diaryName = cursor.getString(3),
diaryName = it.getString(3), semesterId = cursor.getInt(4),
semesterId = it.getInt(4), semesterName = cursor.getInt(5),
semesterName = it.getInt(5), classId = cursor.getInt(7),
classId = it.getInt(7), unitId = cursor.getInt(8),
unitId = it.getInt(8), schoolYear = cursor.getInt(9),
schoolYear = it.getInt(9), start = Converters().timestampToDate(cursor.getLong(10))!!,
start = Converters().timestampToLocalDate(it.getLong(10))!!, end = Converters().timestampToDate(cursor.getLong(11))!!
end = Converters().timestampToLocalDate(it.getLong(11))!! ) to (cursor.getInt(6) == 1))
) to (it.getInt(6) == 1)) } while (cursor.moveToNext())
} while (it.moveToNext())
} }
}
return semesters.toList() return semesters.toList()
} }
@ -198,13 +181,7 @@ class Migration13Test : AbstractMigrationTest() {
}) })
} }
private fun createSemester( private fun createSemester(db: SupportSQLiteDatabase, studentId: Int, classId: Int, semesterId: Int, diaryId: Int, isCurrent: Boolean = false) {
db: SupportSQLiteDatabase,
studentId: Int,
semesterId: Int,
diaryId: Int,
isCurrent: Boolean = false
) {
db.insert("Semesters", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { db.insert("Semesters", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
put("student_id", studentId) put("student_id", studentId)
put("diary_id", diaryId) put("diary_id", diaryId)
@ -212,7 +189,7 @@ class Migration13Test : AbstractMigrationTest() {
put("semester_id", semesterId) put("semester_id", semesterId)
put("semester_name", "1") put("semester_name", "1")
put("is_current", isCurrent) put("is_current", isCurrent)
put("class_id", 5) put("class_id", classId)
put("unit_id", "99") put("unit_id", "99")
}) })
} }

View file

@ -2,21 +2,12 @@ package io.github.wulkanowy.data.db.migrations
import android.content.ContentValues import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import android.os.Build
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.HiltTestApplication
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import kotlin.random.Random import kotlin.random.Random
@HiltAndroidTest
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class)
class Migration27Test : AbstractMigrationTest() { class Migration27Test : AbstractMigrationTest() {
@Test @Test
@ -27,7 +18,7 @@ class Migration27Test : AbstractMigrationTest() {
close() close()
} }
runMigrationsAndValidate(Migration27()) helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
val db = getMigratedRoomDatabase() val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() } val students = runBlocking { db.studentDao.loadAll() }
@ -39,8 +30,6 @@ class Migration27Test : AbstractMigrationTest() {
assertEquals(123, userLoginId) assertEquals(123, userLoginId)
assertEquals("Student Jan", userName) assertEquals("Student Jan", userName)
} }
db.close()
} }
@Test @Test
@ -51,7 +40,7 @@ class Migration27Test : AbstractMigrationTest() {
close() close()
} }
runMigrationsAndValidate(Migration27()) helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
val db = getMigratedRoomDatabase() val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() } val students = runBlocking { db.studentDao.loadAll() }
@ -63,8 +52,6 @@ class Migration27Test : AbstractMigrationTest() {
assertEquals(2, userLoginId) assertEquals(2, userLoginId)
assertEquals("Unit Jan", userName) assertEquals("Unit Jan", userName)
} }
db.close()
} }
@Test @Test
@ -77,7 +64,7 @@ class Migration27Test : AbstractMigrationTest() {
close() close()
} }
runMigrationsAndValidate(Migration27()) helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
val db = getMigratedRoomDatabase() val db = getMigratedRoomDatabase()
val students = runBlocking { db.studentDao.loadAll() } val students = runBlocking { db.studentDao.loadAll() }
@ -94,8 +81,6 @@ class Migration27Test : AbstractMigrationTest() {
assertEquals(333, userLoginId) assertEquals(333, userLoginId)
assertEquals("Unit Tomasz", userName) assertEquals("Unit Tomasz", userName)
} }
db.close()
} }
private fun createStudent(db: SupportSQLiteDatabase, id: Long, userLoginId: Int, studentName: String) { private fun createStudent(db: SupportSQLiteDatabase, id: Long, userLoginId: Int, studentName: String) {

View file

@ -1,55 +1,20 @@
{ {
"agcgw":{ "agcgw":{
"backurl": "connect-dre.hispace.hicloud.com", "backurl":"connect-dre.dbankcloud.cn",
"url": "connect-dre.dbankcloud.cn", "url":"connect-dre.hispace.hicloud.com"
"websocketbackurl": "connect-ws-dre.hispace.dbankcloud.com",
"websocketurl": "connect-ws-dre.hispace.dbankcloud.cn"
},
"agcgw_all": {
"CN": "connect-drcn.dbankcloud.cn",
"CN_back": "connect-drcn.hispace.hicloud.com",
"DE": "connect-dre.dbankcloud.cn",
"DE_back": "connect-dre.hispace.hicloud.com",
"RU": "connect-drru.hispace.dbankcloud.ru",
"RU_back": "connect-drru.hispace.dbankcloud.cn",
"SG": "connect-dra.dbankcloud.cn",
"SG_back": "connect-dra.hispace.hicloud.com"
},
"websocketgw_all": {
"CN": "connect-ws-drcn.hispace.dbankcloud.cn",
"CN_back": "connect-ws-drcn.hispace.dbankcloud.com",
"DE": "connect-ws-dre.hispace.dbankcloud.cn",
"DE_back": "connect-ws-dre.hispace.dbankcloud.com",
"RU": "connect-ws-drru.hispace.dbankcloud.ru",
"RU_back": "connect-ws-drru.hispace.dbankcloud.cn",
"SG": "connect-ws-dra.hispace.dbankcloud.cn",
"SG_back": "connect-ws-dra.hispace.dbankcloud.com"
}, },
"client":{ "client":{
"cp_id":"890048000024105546", "cp_id":"890048000024105546",
"product_id": "736430079244736562", "product_id":"",
"client_id": "514530959291319360", "client_id":"",
"client_secret": "C42522DBF17D3D4BBE9D9C1783A54484B7E6844B388B7A67502D36A633A4186B", "client_secret":"",
"project_id": "736430079244736562", "app_id":"101440411",
"app_id": "106552551", "package_name":"io.github.wulkanowy.dev",
"api_key": "CgB6e3x9BUNiq+r8ebCHNojjjYsMT4pJSjjNDOkm9owtBb6rVI6LjnASoZBRxbjjhObcrV5gANo99fI/eKZDTbWS", "api_key":""
"package_name": "io.github.wulkanowy.dev"
},
"oauth_client": {
"client_id": "106552551",
"client_type": 1
},
"app_info": {
"app_id": "106552551",
"package_name": "io.github.wulkanowy.dev"
}, },
"service":{ "service":{
"analytics":{ "analytics":{
"collector_url":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn", "collector_url":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
"collector_url_ru": "datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com",
"collector_url_sg": "datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn",
"collector_url_de": "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
"collector_url_cn": "datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
"resource_id":"p1", "resource_id":"p1",
"channel_id":"" "channel_id":""
}, },
@ -57,36 +22,12 @@
"url":"https://search-dre.cloud.huawei.com" "url":"https://search-dre.cloud.huawei.com"
}, },
"cloudstorage":{ "cloudstorage":{
"storage_url_sg_back": "https://agc-storage-dra.cloud.huawei.asia", "storage_url":"https://ops-dre.agcstorage.link"
"storage_url_ru_back": "https://agc-storage-drru.cloud.huawei.ru",
"storage_url_ru": "https://agc-storage-drru.cloud.huawei.ru",
"storage_url_de_back": "https://agc-storage-dre.cloud.huawei.eu",
"storage_url_de": "https://ops-dre.agcstorage.link",
"storage_url": "https://agc-storage-drcn.platform.dbankcloud.cn",
"storage_url_sg": "https://ops-dra.agcstorage.link",
"storage_url_cn_back": "https://agc-storage-drcn.cloud.huawei.com.cn",
"storage_url_cn": "https://agc-storage-drcn.platform.dbankcloud.cn"
}, },
"ml":{ "ml":{
"mlservice_url":"ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn" "mlservice_url":"ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
} }
}, },
"region":"DE", "region":"DE",
"configuration_version": "3.0", "configuration_version":"1.0"
"appInfos": [
{
"package_name": "io.github.wulkanowy.dev",
"client": {
"app_id": "106552551"
},
"app_info": {
"package_name": "io.github.wulkanowy.dev",
"app_id": "106552551"
},
"oauth_client": {
"client_type": 1,
"client_id": "106552551"
}
}
]
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

View file

@ -1,19 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<group
android:scaleX="0.92"
android:scaleY="0.92"
android:translateX="0.96"
android:translateY="0.96">
<path
android:fillColor="#FFF"
android:pathData="M3.9512,2A2,2 0,0 0,2 4L2,18A2,2 0,0 0,4 20L10.0996,20C11.3596,21.24 13.09,22 15,22A7,7 0,0 0,15.7988 21.9551L15.7988,19.7832A4.85,4.85 0,0 1,15 19.8496C12.32,19.8496 10.1504,17.68 10.1504,15A4.85,4.85 0,0 1,15 10.1504C17.4677,10.1504 19.4978,11.9912 19.8047,14.375C20.566,14.3758 21.3108,14.5325 21.9922,14.834C21.9491,12.9905 21.2036,11.3226 20,10.0996L20,4A2,2 0,0 0,18 2L4,2A2,2 0,0 0,3.9512 2zM4,5L10,5L10,8L4,8L4,5zM12,5L18,5L18,8L12,8L12,5zM4,10L10.0996,10C9.2596,10.82 8.6291,11.85 8.2891,13L4,13L4,10zM14,12L14,15.6895L15.7988,16.7266L15.7988,14.9922L15.5,14.8203L15.5,12L14,12zM4,15L8,15C8,16.07 8.2399,17.09 8.6699,18L4,18L4,15z" />
<path
android:fillColor="#FFF"
android:pathData="m17.298,24v-8.1249h2.5c0.7143,0 1.3523,0.1618 1.9141,0.4855 0.5655,0.3199 1.0063,0.7775 1.3225,1.3728 0.3162,0.5915 0.4743,1.2649 0.4743,2.0201v0.3739c0,0.7552 -0.1562,1.4267 -0.4687,2.0145 -0.3088,0.5878 -0.7459,1.0435 -1.3114,1.3672C21.1633,23.8326 20.5253,23.9963 19.8148,24ZM18.9721,17.2311v5.4241h0.8091c0.6548,0 1.1551,-0.2139 1.5011,-0.6417 0.346,-0.4278 0.5227,-1.0398 0.5301,-1.8359v-0.4297c0,-0.8259 -0.1711,-1.4509 -0.5134,-1.875 -0.3423,-0.4278 -0.8426,-0.6417 -1.5011,-0.6417z" />
</group>
</vector>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/colorIcon" /> <background android:drawable="@color/colorPrimary" />
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" /> <foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
<monochrome android:drawable="@drawable/ic_launcher_foreground_dev_mono" />
</adaptive-icon> </adaptive-icon>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/colorPrimary" />
<foreground android:drawable="@drawable/ic_launcher_foreground_dev" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -1,31 +0,0 @@
package io.github.wulkanowy.utils
import android.content.Context
import android.view.View
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Inject
@Suppress("unused")
class AdsHelper @Inject constructor(
@ApplicationContext private val context: Context,
private val preferencesRepository: PreferencesRepository
) {
val isMobileAdsSdkInitialized = MutableStateFlow(false)
val canShowAd = false
fun initialize() {
preferencesRepository.isAdsEnabled = false
preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS
}
@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER")
suspend fun getDashboardTileAdBanner(width: Int): AdBanner {
throw IllegalStateException("Can't get ad banner (F-droid)")
}
}
data class AdBanner(val view: View)

View file

@ -8,7 +8,15 @@ import javax.inject.Singleton
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
class AnalyticsHelper @Inject constructor() { class AnalyticsHelper @Inject constructor() {
fun logEvent(name: String, vararg params: Pair<String, Any?>) = Unit fun logEvent(name: String, vararg params: Pair<String, Any?>) {
fun setCurrentScreen(activity: Activity, name: String?) = Unit // do nothing
fun popCurrentScreen(name: String?) = Unit }
fun setCurrentScreen(activity: Activity, name: String?) {
// do nothing
}
fun popCurrentScreen(name: String?) {
// do nothing
}
} }

View file

@ -1,18 +0,0 @@
package io.github.wulkanowy.utils
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.ui.modules.main.MainActivity
import javax.inject.Singleton
import javax.inject.Inject
@Suppress("UNUSED_PARAMETER", "unused")
@Singleton
class InAppReviewHelper @Inject constructor(
@ApplicationContext private val context: Context
) {
fun showInAppReview(activity: MainActivity) {
// do nothing
}
}

View file

@ -1,13 +0,0 @@
package io.github.wulkanowy.utils
import android.view.View
import javax.inject.Inject
class InAppUpdateHelper @Inject constructor() {
lateinit var messageContainer: View
fun checkAndInstallUpdates() {}
fun onResume() {}
}

View file

@ -1,11 +0,0 @@
package io.github.wulkanowy.utils
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class IntegrityHelper @Inject constructor() {
@Suppress("UNUSED_PARAMETER")
fun getIntegrityToken(requestId: String): String? = null
}

View file

@ -1,7 +0,0 @@
package io.github.wulkanowy.utils
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper()

View file

@ -0,0 +1,17 @@
package io.github.wulkanowy.utils
import android.app.Activity
import android.view.View
import javax.inject.Inject
@Suppress("UNUSED_PARAMETER")
class UpdateHelper @Inject constructor() {
lateinit var messageContainer: View
fun checkAndInstallUpdates(activity: Activity) {}
fun onActivityResult(requestCode: Int, resultCode: Int) {}
fun onResume(activity: Activity) {}
}

View file

@ -1,30 +0,0 @@
package io.github.wulkanowy.utils
import android.content.Context
import android.view.View
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Inject
@Suppress("unused")
class AdsHelper @Inject constructor(
@ApplicationContext private val context: Context,
private val preferencesRepository: PreferencesRepository
) {
val isMobileAdsSdkInitialized = MutableStateFlow(false)
val canShowAd = false
fun initialize() {
preferencesRepository.isAdsEnabled = false
preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS
}
@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER")
suspend fun getDashboardTileAdBanner(width: Int): AdBanner {
throw IllegalStateException("Can't get ad banner (HMS)")
}
}
data class AdBanner(val view: View)

View file

@ -3,38 +3,26 @@ package io.github.wulkanowy.utils
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import com.huawei.agconnect.crash.AGConnectCrash
import com.huawei.hms.analytics.HiAnalytics import com.huawei.hms.analytics.HiAnalytics
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.data.repositories.PreferencesRepository
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class AnalyticsHelper @Inject constructor( class AnalyticsHelper @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context
preferencesRepository: PreferencesRepository,
appInfo: AppInfo,
) { ) {
private val analytics by lazy { HiAnalytics.getInstance(context) } private val analytics by lazy { HiAnalytics.getInstance(context) }
private val connectCrash by lazy { AGConnectCrash.getInstance() }
init {
if (!appInfo.isDebug) {
connectCrash.setUserId(preferencesRepository.installationId)
}
}
fun logEvent(name: String, vararg params: Pair<String, Any?>) { fun logEvent(name: String, vararg params: Pair<String, Any?>) {
Bundle().apply { Bundle().apply {
params.forEach { (key, value) -> params.forEach {
if (value == null) return@forEach if (it.second == null) return@forEach
when (value) { when (it.second) {
is String -> putString(key, value) is String, is String? -> putString(it.first, it.second as String)
is Int -> putInt(key, value) is Int, is Int? -> putInt(it.first, it.second as Int)
is Boolean -> putBoolean(key, value) is Boolean, is Boolean? -> putBoolean(it.first, it.second as Boolean)
} }
} }
analytics.onEvent(name, this) analytics.onEvent(name, this)

View file

@ -2,8 +2,12 @@ package io.github.wulkanowy.utils
import android.util.Log import android.util.Log
import com.huawei.agconnect.crash.AGConnectCrash import com.huawei.agconnect.crash.AGConnectCrash
import fr.bipi.treessence.base.FormatterPriorityTree import fr.bipi.tressence.base.FormatterPriorityTree
import fr.bipi.treessence.common.StackTraceRecorder import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
import java.io.InterruptedIOException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) { class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
@ -16,17 +20,34 @@ class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
} }
} }
class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR, ExceptionFilter) { class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR) {
private val connectCrash by lazy { AGConnectCrash.getInstance() } private val connectCrash by lazy { AGConnectCrash.getInstance() }
override fun skipLog(priority: Int, tag: String?, message: String, t: Throwable?): Boolean {
return when (t) {
is FeatureDisabledException,
is FeatureNotAvailableException,
is UnknownHostException,
is SocketTimeoutException,
is InterruptedIOException -> true
else -> super.skipLog(priority, tag, message, t)
}
}
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
if (skipLog(priority, tag, message, t)) return if (skipLog(priority, tag, message, t)) return
// Disabled due to a bug in the Huawei library
/*connectCrash.setCustomKey("priority", priority)
connectCrash.setCustomKey("tag", tag.orEmpty())
connectCrash.setCustomKey("message", message)
if (t != null) { if (t != null) {
connectCrash.recordException(t) connectCrash.recordException(t)
} else { } else {
connectCrash.recordException(StackTraceRecorder(format(priority, tag, message))) connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
} }*/
} }
} }

View file

@ -1,18 +0,0 @@
package io.github.wulkanowy.utils
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.ui.modules.main.MainActivity
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
@Suppress("UNUSED_PARAMETER", "unused")
class InAppReviewHelper @Inject constructor(
@ApplicationContext private val context: Context
) {
fun showInAppReview(activity: MainActivity) {
// do nothing
}
}

View file

@ -1,13 +0,0 @@
package io.github.wulkanowy.utils
import android.view.View
import javax.inject.Inject
class InAppUpdateHelper @Inject constructor() {
lateinit var messageContainer: View
fun checkAndInstallUpdates() {}
fun onResume() {}
}

View file

@ -1,11 +0,0 @@
package io.github.wulkanowy.utils
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class IntegrityHelper @Inject constructor() {
@Suppress("UNUSED_PARAMETER")
fun getIntegrityToken(requestId: String): String? = null
}

View file

@ -1,7 +0,0 @@
package io.github.wulkanowy.utils
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper()

View file

@ -0,0 +1,17 @@
package io.github.wulkanowy.utils
import android.app.Activity
import android.view.View
import javax.inject.Inject
@Suppress("UNUSED_PARAMETER")
class UpdateHelper @Inject constructor() {
lateinit var messageContainer: View
fun checkAndInstallUpdates(activity: Activity) {}
fun onActivityResult(requestCode: Int, resultCode: Int) {}
fun onResume(activity: Activity) {}
}

View file

@ -1,15 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="io.github.wulkanowy"
android:installLocation="internalOnly"> android:installLocation="internalOnly">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<queries> <queries>
<intent> <intent>
@ -20,34 +18,20 @@
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<data android:scheme="https" /> <data android:scheme="https" />
</intent> </intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="mailto" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="tel" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="geo" />
</intent>
</queries> </queries>
<application <application
android:name=".WulkanowyApp" android:name=".WulkanowyApp"
android:allowBackup="false" android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="false" android:supportsRtl="false"
android:theme="@style/WulkanowyTheme" android:theme="@style/WulkanowyTheme"
tools:ignore="DataExtractionRules,UnusedAttribute"> android:usesCleartextTraffic="true"
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
<activity <activity
android:name=".ui.modules.splash.SplashActivity" android:name=".ui.modules.splash.SplashActivity"
android:exported="true"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/WulkanowyTheme.SplashScreen" android:theme="@style/WulkanowyTheme.SplashScreen"
tools:ignore="LockedOrientationActivity"> tools:ignore="LockedOrientationActivity">
@ -60,7 +44,7 @@
android:name=".ui.modules.login.LoginActivity" android:name=".ui.modules.login.LoginActivity"
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
android:label="@string/login_title" android:label="@string/login_title"
android:theme="@style/WulkanowyTheme.Login" android:theme="@style/WulkanowyTheme.NoActionBar"
android:windowSoftInputMode="adjustResize" /> android:windowSoftInputMode="adjustResize" />
<activity <activity
android:name=".ui.modules.main.MainActivity" android:name=".ui.modules.main.MainActivity"
@ -77,7 +61,6 @@
<activity <activity
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity" android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:exported="true"
android:noHistory="true" android:noHistory="true"
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher"> android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
<intent-filter> <intent-filter>
@ -87,7 +70,6 @@
<activity <activity
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity" android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:exported="true"
android:noHistory="true" android:noHistory="true"
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher"> android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
<intent-filter> <intent-filter>
@ -98,22 +80,6 @@
<service <service
android:name=".services.widgets.TimetableWidgetService" android:name=".services.widgets.TimetableWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" /> android:permission="android.permission.BIND_REMOTEVIEWS" />
<service
android:name=".services.piggyback.VulcanNotificationListenerService"
android:exported="true"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<service
android:name=".services.messaging.AppMessagingService"
android:exported="false"
tools:ignore="MissingClass">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<receiver <receiver
android:name=".ui.modules.timetablewidget.TimetableWidgetProvider" android:name=".ui.modules.timetablewidget.TimetableWidgetProvider"
@ -128,7 +94,6 @@
</receiver> </receiver>
<receiver <receiver
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider" android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"
android:exported="true"
android:label="@string/lucky_number_title"> android:label="@string/lucky_number_title">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
@ -141,9 +106,11 @@
<receiver android:name=".services.alarm.TimetableNotificationReceiver" /> <receiver android:name=".services.alarm.TimetableNotificationReceiver" />
<provider <provider
android:name="androidx.startup.InitializationProvider" android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.androidx-startup" android:authorities="${applicationId}.workmanager-init"
android:exported="false"
tools:node="remove" /> tools:node="remove" />
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider" android:authorities="${applicationId}.fileprovider"
@ -154,44 +121,44 @@
android:resource="@xml/provider_paths" /> android:resource="@xml/provider_paths" />
</provider> </provider>
<meta-data
android:name="install_channel"
android:value="${install_channel}" />
<!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false --> <!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false -->
<!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html --> <!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html -->
<provider <provider
android:name="com.google.firebase.provider.FirebaseInitProvider" android:name="com.google.firebase.provider.FirebaseInitProvider"
android:authorities="${applicationId}.firebaseinitprovider" android:authorities="${applicationId}.firebaseinitprovider"
android:enabled="${firebase_enabled}" android:enabled="${firebase_enabled}"
android:exported="false" android:exported="false" />
tools:ignore="MissingClass" />
<meta-data
android:name="install_channel"
android:value="${install_channel}" />
<meta-data <meta-data
android:name="firebase_analytics_collection_enabled" android:name="firebase_analytics_collection_enabled"
android:value="${firebase_enabled}" /> android:value="${firebase_enabled}" />
<meta-data <meta-data
android:name="google_analytics_adid_collection_enabled" android:name="google_analytics_adid_collection_enabled"
android:value="${firebase_enabled}" /> android:value="${firebase_enabled}" />
<meta-data <meta-data
android:name="firebase_crashlytics_collection_enabled" android:name="firebase_crashlytics_collection_enabled"
android:value="${firebase_enabled}" /> android:value="${firebase_enabled}" />
<meta-data <meta-data
android:name="firebase_messaging_auto_init_enabled" android:name="firebase_messaging_auto_init_enabled"
android:value="${firebase_enabled}" /> android:value="${firebase_enabled}" />
<meta-data <meta-data
android:name="firebase_inapp_messaging_auto_data_collection_enabled" android:name="firebase_inapp_messaging_auto_data_collection_enabled"
android:value="${firebase_enabled}" /> android:value="${firebase_enabled}" />
<meta-data <meta-data
android:name="com.google.firebase.messaging.default_notification_icon" android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_stat_all" /> android:resource="@drawable/ic_stat_push" />
<meta-data <meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id" android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="push_channel" /> android:value="push_channel" />
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="${admob_project_id}" />
<meta-data
android:name="com.google.android.gms.ads.DELAY_APP_MEASUREMENT_INIT"
android:value="true" />
</application> </application>
</manifest> </manifest>

View file

@ -34,25 +34,5 @@
{ {
"displayName": "Mateusz Idziejczak", "displayName": "Mateusz Idziejczak",
"githubUsername": "Luncenok" "githubUsername": "Luncenok"
},
{
"displayName": "Daniel Olczyk",
"githubUsername": "MRmlik12"
},
{
"displayName": "Damian Czupryn",
"githubUsername": "Daxxxis"
},
{
"displayName": "Kamil Studziński",
"githubUsername": "studzinskik"
},
{
"displayName": "Tomasz F.",
"githubUsername": "Pengwius"
},
{
"displayName": "Antoni Paduch",
"githubUsername": "janAte1"
} }
] ]

View file

@ -1,14 +1,16 @@
package io.github.wulkanowy package io.github.wulkanowy
import android.app.Application import android.app.Application
import android.content.Context
import android.util.Log.DEBUG import android.util.Log.DEBUG
import android.util.Log.INFO import android.util.Log.INFO
import android.util.Log.VERBOSE import android.util.Log.VERBOSE
import androidx.hilt.work.HiltWorkerFactory import androidx.hilt.work.HiltWorkerFactory
import androidx.multidex.MultiDex
import androidx.work.Configuration import androidx.work.Configuration
import com.yariksoffice.lingver.Lingver import com.yariksoffice.lingver.Lingver
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
import fr.bipi.treessence.file.FileLoggerTree import fr.bipi.tressence.file.FileLoggerTree
import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.ui.base.ThemeManager import io.github.wulkanowy.ui.base.ThemeManager
import io.github.wulkanowy.utils.ActivityLifecycleLogger import io.github.wulkanowy.utils.ActivityLifecycleLogger
@ -17,13 +19,15 @@ import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.CrashLogExceptionTree import io.github.wulkanowy.utils.CrashLogExceptionTree
import io.github.wulkanowy.utils.CrashLogTree import io.github.wulkanowy.utils.CrashLogTree
import io.github.wulkanowy.utils.DebugLogTree import io.github.wulkanowy.utils.DebugLogTree
import io.github.wulkanowy.utils.RemoteConfigHelper
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@HiltAndroidApp @HiltAndroidApp
class WulkanowyApp : Application(), Configuration.Provider { class WulkanowyApp : Application(), Configuration.Provider {
@Inject
lateinit var workerFactory: HiltWorkerFactory
@Inject @Inject
lateinit var themeManager: ThemeManager lateinit var themeManager: ThemeManager
@ -36,31 +40,24 @@ class WulkanowyApp : Application(), Configuration.Provider {
@Inject @Inject
lateinit var analyticsHelper: AnalyticsHelper lateinit var analyticsHelper: AnalyticsHelper
@Inject override fun attachBaseContext(base: Context?) {
lateinit var remoteConfigHelper: RemoteConfigHelper super.attachBaseContext(base)
MultiDex.install(this)
@Inject }
lateinit var workerFactory: HiltWorkerFactory
override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
.build()
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
initializeAppLanguage() Lingver.init(this)
themeManager.applyDefaultTheme() themeManager.applyDefaultTheme()
remoteConfigHelper.initialize()
initLogging() initLogging()
logCurrentLanguage()
} }
private fun initLogging() { private fun initLogging() {
if (appInfo.isDebug) { if (appInfo.isDebug) {
Timber.plant(DebugLogTree()) Timber.plant(DebugLogTree())
Timber.plant( Timber.plant(FileLoggerTree.Builder()
FileLoggerTree.Builder()
.withFileName("wulkanowy.%g.log") .withFileName("wulkanowy.%g.log")
.withDirName(applicationContext.filesDir.absolutePath) .withDirName(applicationContext.filesDir.absolutePath)
.withFileLimit(10) .withFileLimit(10)
@ -74,14 +71,18 @@ class WulkanowyApp : Application(), Configuration.Provider {
registerActivityLifecycleCallbacks(ActivityLifecycleLogger()) registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
} }
private fun initializeAppLanguage() { private fun logCurrentLanguage() {
Lingver.init(this) val newLang = if (preferencesRepository.appLanguage == "system") {
appInfo.systemLanguage
if (preferencesRepository.appLanguage == "system") {
Lingver.getInstance().setFollowSystemLocale(this)
analyticsHelper.logEvent("language", "startup" to appInfo.systemLanguage)
} else { } else {
analyticsHelper.logEvent("language", "startup" to preferencesRepository.appLanguage) preferencesRepository.appLanguage
} }
analyticsHelper.logEvent("language", "startup" to newLang)
} }
override fun getWorkManagerConfiguration() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
.build()
} }

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