Compare commits
No commits in common. "develop" and "v4.12.1" have entirely different histories.
2
.github/utils/_get_password.py
vendored
@ -23,6 +23,8 @@ def get_password(
|
||||
auth_plugin="mysql_native_password",
|
||||
)
|
||||
|
||||
print(f"Generating passwords for version {version_name} ({version_code})")
|
||||
|
||||
password = base64.b64encode(secrets.token_bytes(16)).decode()
|
||||
iv = secrets.token_bytes(16)
|
||||
|
||||
|
4
.github/utils/_utils.py
vendored
@ -102,9 +102,7 @@ def get_commit_log(project_dir: str, format: str, max_lines: int = None) -> str:
|
||||
)
|
||||
|
||||
log = subprocess.run(
|
||||
args=f"git log {last_tag}..HEAD --format=%an%x00%at%x00%h%x00%s%x00%D".split(
|
||||
" "
|
||||
),
|
||||
args=f"git log {last_tag}..HEAD --format=%an%x00%at%x00%h%x00%s%x00%D".split(" "),
|
||||
cwd=project_dir,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
|
29
.github/utils/bump_nightly.py
vendored
@ -1,7 +1,10 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import requests
|
||||
|
||||
from _utils import (
|
||||
get_commit_log,
|
||||
@ -15,20 +18,38 @@ if __name__ == "__main__":
|
||||
print("usage: bump_nightly.py <project dir>")
|
||||
exit(-1)
|
||||
|
||||
repo = os.getenv("GITHUB_REPOSITORY")
|
||||
sha = os.getenv("GITHUB_SHA")
|
||||
|
||||
if not repo or not sha:
|
||||
print("Missing GitHub environment variables.")
|
||||
exit(-1)
|
||||
|
||||
with requests.get(
|
||||
f"https://api.github.com/repos/{repo}/actions/runs?per_page=5&status=success"
|
||||
) as r:
|
||||
data = json.loads(r.text)
|
||||
runs = [run for run in data["workflow_runs"] if run["head_sha"] == sha]
|
||||
if runs:
|
||||
print("::set-output name=hasNewChanges::false")
|
||||
exit(0)
|
||||
|
||||
print("::set-output name=hasNewChanges::true")
|
||||
|
||||
project_dir = get_project_dir()
|
||||
|
||||
(version_code, version_name) = read_gradle_version(project_dir)
|
||||
version_name = version_name.split("+")[0]
|
||||
|
||||
date = datetime.now(tz=ZoneInfo("Europe/Warsaw"))
|
||||
date = datetime.now()
|
||||
if date.hour > 6:
|
||||
version_name += "+daily." + date.strftime("%Y%m%d-%H%M")
|
||||
else:
|
||||
date -= timedelta(days=1)
|
||||
version_name += "+nightly." + date.strftime("%Y%m%d")
|
||||
|
||||
print("appVersionName=" + version_name)
|
||||
print("appVersionCode=" + str(version_code))
|
||||
print("::set-output name=appVersionName::" + version_name)
|
||||
print("::set-output name=appVersionCode::" + str(version_code))
|
||||
|
||||
write_gradle_version(project_dir, version_code, version_name)
|
||||
|
||||
|
23
.github/utils/check_nightly.py
vendored
@ -1,23 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
import requests
|
||||
|
||||
if __name__ == "__main__":
|
||||
repo = os.getenv("GITHUB_REPOSITORY")
|
||||
sha = os.getenv("GITHUB_SHA")
|
||||
|
||||
if not repo or not sha:
|
||||
print("Missing GitHub environment variables.")
|
||||
exit(-1)
|
||||
|
||||
with requests.get(
|
||||
f"https://api.github.com/repos/{repo}/actions/runs?per_page=5&status=success"
|
||||
) as r:
|
||||
data = json.loads(r.text)
|
||||
runs = [run for run in data["workflow_runs"] if run["head_sha"] == sha]
|
||||
if runs:
|
||||
print("hasNewChanges=false")
|
||||
exit(0)
|
||||
|
||||
print("hasNewChanges=true")
|
25
.github/utils/extract_changelogs.py
vendored
@ -12,24 +12,24 @@ if __name__ == "__main__":
|
||||
|
||||
(version_code, version_name) = read_gradle_version(project_dir)
|
||||
|
||||
print("appVersionName=" + version_name)
|
||||
print("appVersionCode=" + str(version_code))
|
||||
print("::set-output name=appVersionName::" + version_name)
|
||||
print("::set-output name=appVersionCode::" + str(version_code))
|
||||
|
||||
dir = f"{project_dir}/app/release/whatsnew-{version_name}/"
|
||||
os.makedirs(dir, exist_ok=True)
|
||||
|
||||
print("changelogDir=" + dir)
|
||||
print("::set-output name=changelogDir::" + dir)
|
||||
|
||||
(title, changelog) = get_changelog(project_dir, format="plain")
|
||||
|
||||
# plain text changelog - Firebase App Distribution
|
||||
with open(dir + "whatsnew_titled.txt", "w", encoding="utf-8") as f:
|
||||
with open(dir + "whatsnew-titled.txt", "w", encoding="utf-8") as f:
|
||||
f.write(title)
|
||||
f.write("\n")
|
||||
f.write(changelog)
|
||||
print("changelogPlainTitledFile=" + dir + "whatsnew_titled.txt")
|
||||
print("::set-output name=changelogPlainTitledFile::" + dir + "whatsnew-titled.txt")
|
||||
|
||||
print("changelogTitle=" + title)
|
||||
print("::set-output name=changelogTitle::" + title)
|
||||
|
||||
# plain text changelog, max 500 chars - Google Play
|
||||
with open(dir + "whatsnew-pl-PL", "w", encoding="utf-8") as f:
|
||||
@ -41,31 +41,32 @@ if __name__ == "__main__":
|
||||
changelog = changelog.strip()
|
||||
f.write(changelog)
|
||||
|
||||
print("changelogPlainFile=" + dir + "whatsnew-pl-PL")
|
||||
print("::set-output name=changelogPlainFile::" + dir + "whatsnew-pl-PL")
|
||||
|
||||
# markdown changelog - Discord webhook
|
||||
(_, changelog) = get_changelog(project_dir, format="markdown")
|
||||
with open(dir + "whatsnew.md", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("changelogMarkdownFile=" + dir + "whatsnew.md")
|
||||
print("::set-output name=changelogMarkdownFile::" + dir + "whatsnew.md")
|
||||
|
||||
# html changelog - version info in DB
|
||||
(_, changelog) = get_changelog(project_dir, format="html")
|
||||
with open(dir + "whatsnew.html", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("changelogHtmlFile=" + dir + "whatsnew.html")
|
||||
print("::set-output name=changelogHtmlFile::" + dir + "whatsnew.html")
|
||||
|
||||
|
||||
changelog = get_commit_log(project_dir, format="plain", max_lines=10)
|
||||
with open(dir + "commit_log.txt", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("commitLogPlainFile=" + dir + "commit_log.txt")
|
||||
print("::set-output name=commitLogPlainFile::" + dir + "commit_log.txt")
|
||||
|
||||
changelog = get_commit_log(project_dir, format="markdown", max_lines=10)
|
||||
with open(dir + "commit_log.md", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("commitLogMarkdownFile=" + dir + "commit_log.md")
|
||||
print("::set-output name=commitLogMarkdownFile::" + dir + "commit_log.md")
|
||||
|
||||
changelog = get_commit_log(project_dir, format="html", max_lines=10)
|
||||
with open(dir + "commit_log.html", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("commitLogHtmlFile=" + dir + "commit_log.html")
|
||||
print("::set-output name=commitLogHtmlFile::" + dir + "commit_log.html")
|
||||
|
@ -13,7 +13,7 @@ if __name__ == "__main__":
|
||||
|
||||
files = glob.glob(f"{project_dir}/app/release/*.*")
|
||||
for file in files:
|
||||
file_relative = file.replace(project_dir + "/", "")
|
||||
file_relative = file.replace(os.getenv("GITHUB_WORKSPACE") + "/", "")
|
||||
if "-aligned.apk" in file:
|
||||
os.unlink(file)
|
||||
elif "-signed.apk" in file:
|
||||
@ -22,5 +22,5 @@ if __name__ == "__main__":
|
||||
os.unlink(new_file)
|
||||
os.rename(file, new_file)
|
||||
elif ".apk" in file or ".aab" in file:
|
||||
print("signedReleaseFile=" + file)
|
||||
print("signedReleaseFileRelative=" + file_relative)
|
||||
print("::set-output name=signedReleaseFile::" + file)
|
||||
print("::set-output name=signedReleaseFileRelative::" + file_relative)
|
25
.github/utils/save_version.py
vendored
@ -3,7 +3,6 @@ import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from time import time
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import mysql.connector as mysql
|
||||
from dotenv import load_dotenv
|
||||
@ -60,22 +59,12 @@ def save_version(
|
||||
build_date = int(os.stat(file).st_mtime)
|
||||
bundle_name_play = output_aab_play
|
||||
|
||||
build_date = datetime.fromtimestamp(
|
||||
build_date,
|
||||
tz=ZoneInfo("Europe/Warsaw"),
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
build_date = datetime.fromtimestamp(build_date).strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
if build_type in ["nightly", "daily"]:
|
||||
download_url = apk_server_nightly + apk_name if apk_name else None
|
||||
else:
|
||||
# download_url = apk_server_release + apk_name if apk_name else None
|
||||
download_url = (
|
||||
f"https://github.com/szkolny-eu/szkolny-android/releases/download/v{version_name}/{apk_name}"
|
||||
if apk_name
|
||||
else None
|
||||
)
|
||||
if download_url:
|
||||
print("downloadUrl=" + download_url)
|
||||
download_url = apk_server_release + apk_name if apk_name else None
|
||||
|
||||
cols = [
|
||||
"versionCode",
|
||||
@ -130,12 +119,4 @@ if __name__ == "__main__":
|
||||
APK_SERVER_RELEASE = os.getenv("APK_SERVER_RELEASE")
|
||||
APK_SERVER_NIGHTLY = os.getenv("APK_SERVER_NIGHTLY")
|
||||
|
||||
save_version(
|
||||
project_dir,
|
||||
DB_HOST,
|
||||
DB_USER,
|
||||
DB_PASS,
|
||||
DB_NAME,
|
||||
APK_SERVER_RELEASE,
|
||||
APK_SERVER_NIGHTLY,
|
||||
)
|
||||
save_version(project_dir, DB_HOST, DB_USER, DB_PASS, DB_NAME, APK_SERVER_RELEASE, APK_SERVER_NIGHTLY)
|
||||
|
6
.github/utils/sign.py
vendored
@ -31,6 +31,8 @@ def sign(
|
||||
SIGNING_FORMAT = "$param1.{}.$param2"
|
||||
CPP_FORMAT = "/*{}*/\nstatic toys AES_IV[16] = {{\n\t{} }};"
|
||||
|
||||
print(f"Writing passwords for version {version_name} ({version_code})")
|
||||
|
||||
iv_hex = " ".join(["{:02x}".format(x) for x in iv])
|
||||
iv_cpp = ", ".join(["0x{:02x}".format(x) for x in iv])
|
||||
|
||||
@ -69,8 +71,8 @@ if __name__ == "__main__":
|
||||
version_name, version_code, DB_HOST, DB_USER, DB_PASS, DB_NAME
|
||||
)
|
||||
|
||||
print("appVersionName=" + version_name)
|
||||
print("appVersionCode=" + str(version_code))
|
||||
print("::set-output name=appVersionName::" + version_name)
|
||||
print("::set-output name=appVersionCode::" + str(version_code))
|
||||
|
||||
sign(
|
||||
project_dir,
|
||||
|
37
.github/utils/webhook_discord.py
vendored
@ -1,7 +1,6 @@
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import requests
|
||||
from dotenv import load_dotenv
|
||||
@ -12,7 +11,8 @@ from _utils import get_changelog, get_commit_log, get_project_dir, read_gradle_v
|
||||
def post_webhook(
|
||||
project_dir: str,
|
||||
apk_file: str,
|
||||
download_url: str,
|
||||
apk_server_release: str,
|
||||
apk_server_nightly: str,
|
||||
webhook_release: str,
|
||||
webhook_testing: str,
|
||||
):
|
||||
@ -25,13 +25,16 @@ def post_webhook(
|
||||
testing = ["dev", "beta", "nightly", "daily"]
|
||||
testing = build_type in testing
|
||||
|
||||
apk_name = os.path.basename(apk_file)
|
||||
if build_type in ["nightly", "daily"]:
|
||||
download_url = apk_server_nightly + apk_name
|
||||
else:
|
||||
download_url = apk_server_release + apk_name
|
||||
|
||||
if testing:
|
||||
build_date = int(os.stat(apk_file).st_mtime)
|
||||
if build_date:
|
||||
build_date = datetime.fromtimestamp(
|
||||
build_date,
|
||||
tz=ZoneInfo("Europe/Warsaw"),
|
||||
).strftime("%Y-%m-%d %H:%M")
|
||||
build_date = datetime.fromtimestamp(build_date).strftime("%Y-%m-%d %H:%M")
|
||||
|
||||
# untagged release, get commit log
|
||||
if build_type in ["nightly", "daily"]:
|
||||
@ -45,17 +48,13 @@ def post_webhook(
|
||||
requests.post(url=webhook_testing, json=webhook)
|
||||
else:
|
||||
changelog = get_changelog(project_dir, format="markdown")
|
||||
webhook = get_webhook_release(version_name, changelog, download_url)
|
||||
webhook = get_webhook_release(changelog, download_url)
|
||||
requests.post(url=webhook_release, json=webhook)
|
||||
|
||||
|
||||
def get_webhook_release(version_name: str, changelog: str, download_url: str):
|
||||
def get_webhook_release(changelog: str, download_url: str):
|
||||
(title, content) = changelog
|
||||
return {
|
||||
"content": (
|
||||
f"__**{title}**__\n{content}\n[Szkolny.eu {version_name}]({download_url})"
|
||||
),
|
||||
}
|
||||
return {"content": f"__**{title}**__\n{content}\n{download_url}"}
|
||||
|
||||
|
||||
def get_webhook_testing(
|
||||
@ -74,11 +73,9 @@ def get_webhook_testing(
|
||||
"fields": [
|
||||
{
|
||||
"name": f"Wersja `{version_name}`",
|
||||
"value": (
|
||||
f"[Pobierz .APK]({download_url})"
|
||||
"value": f"[Pobierz .APK]({download_url})"
|
||||
if download_url
|
||||
else "*Pobieranie niedostępne*"
|
||||
),
|
||||
else "*Pobieranie niedostępne*",
|
||||
"inline": False,
|
||||
},
|
||||
{
|
||||
@ -106,14 +103,16 @@ if __name__ == "__main__":
|
||||
|
||||
load_dotenv()
|
||||
APK_FILE = os.getenv("APK_FILE")
|
||||
DOWNLOAD_URL = os.getenv("DOWNLOAD_URL")
|
||||
APK_SERVER_RELEASE = os.getenv("APK_SERVER_RELEASE")
|
||||
APK_SERVER_NIGHTLY = os.getenv("APK_SERVER_NIGHTLY")
|
||||
WEBHOOK_RELEASE = os.getenv("WEBHOOK_RELEASE")
|
||||
WEBHOOK_TESTING = os.getenv("WEBHOOK_TESTING")
|
||||
|
||||
post_webhook(
|
||||
project_dir,
|
||||
APK_FILE,
|
||||
DOWNLOAD_URL,
|
||||
APK_SERVER_RELEASE,
|
||||
APK_SERVER_NIGHTLY,
|
||||
WEBHOOK_RELEASE,
|
||||
WEBHOOK_TESTING,
|
||||
)
|
||||
|
195
.github/workflows/_build.yml
vendored
@ -1,195 +0,0 @@
|
||||
name: "[reusable] Szkolny.eu Build"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
nightly:
|
||||
type: boolean
|
||||
default: false
|
||||
build-apk:
|
||||
type: boolean
|
||||
default: false
|
||||
build-aab:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
release-ssh:
|
||||
type: boolean
|
||||
default: false
|
||||
release-github:
|
||||
type: boolean
|
||||
default: false
|
||||
release-firebase:
|
||||
type: boolean
|
||||
default: false
|
||||
release-google-play:
|
||||
type: boolean
|
||||
default: false
|
||||
release-discord:
|
||||
type: boolean
|
||||
default: false
|
||||
secrets:
|
||||
APK_SERVER_NIGHTLY:
|
||||
APK_SERVER_RELEASE:
|
||||
DB_HOST:
|
||||
DB_NAME:
|
||||
DB_PASS:
|
||||
DB_USER:
|
||||
FIREBASE_APP_ID:
|
||||
FIREBASE_GROUPS_NIGHTLY:
|
||||
FIREBASE_GROUPS_RELEASE:
|
||||
FIREBASE_SERVICE_ACCOUNT_JSON:
|
||||
KEY_ALIAS_PASSWORD:
|
||||
KEY_ALIAS:
|
||||
KEY_STORE_PASSWORD:
|
||||
KEY_STORE:
|
||||
PLAY_RELEASE_TRACK:
|
||||
PLAY_SERVICE_ACCOUNT_JSON:
|
||||
SSH_IP:
|
||||
SSH_KEY:
|
||||
SSH_PATH_NIGHTLY:
|
||||
SSH_PATH_RELEASE:
|
||||
SSH_USERNAME:
|
||||
WEBHOOK_RELEASE:
|
||||
WEBHOOK_TESTING:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
clean: false
|
||||
- name: Setup JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "17"
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
- name: Install Python packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
python-dotenv
|
||||
pycryptodome
|
||||
mysql-connector-python
|
||||
requests
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
|
||||
- name: Bump nightly version
|
||||
if: ${{ inputs.nightly }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/bump_nightly.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
- name: Write signing passwords and keystore
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
KEY_STORE: ${{ secrets.KEY_STORE }}
|
||||
run: |
|
||||
python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit >> $GITHUB_OUTPUT
|
||||
echo $KEY_STORE | base64 --decode > keystore.jks
|
||||
- name: Clean build artifacts
|
||||
run: |
|
||||
rm -rf app/release/*
|
||||
rm -rf app/build/outputs/apk/*
|
||||
rm -rf app/build/outputs/bundle/*
|
||||
|
||||
- name: Build app with Gradle
|
||||
if: ${{ inputs.build-apk || inputs.build-aab }}
|
||||
run: |
|
||||
chmod +x ./gradlew
|
||||
./gradlew \
|
||||
${{ inputs.build-apk && 'assembleOfficialRelease' || '' }} \
|
||||
${{ inputs.build-aab && 'bundlePlayRelease' || '' }} \
|
||||
-P android.injected.signing.store.file=${{ github.workspace }}/keystore.jks \
|
||||
-P android.injected.signing.store.password=${{ secrets.KEY_STORE_PASSWORD }} \
|
||||
-P android.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} \
|
||||
-P android.injected.signing.key.password=${{ secrets.KEY_ALIAS_PASSWORD }}
|
||||
|
||||
- name: Upload release to server
|
||||
if: ${{ inputs.release-ssh }}
|
||||
uses: easingthemes/ssh-deploy@v2.1.6
|
||||
env:
|
||||
REMOTE_HOST: ${{ secrets.SSH_IP }}
|
||||
REMOTE_USER: ${{ secrets.SSH_USERNAME }}
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
|
||||
SOURCE: app/release/
|
||||
TARGET: ${{ inputs.nightly && secrets.SSH_PATH_NIGHTLY || secrets.SSH_PATH_RELEASE }}
|
||||
|
||||
- name: Find signed artifacts
|
||||
id: artifacts
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/find_artifacts.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
- name: Extract release changelogs
|
||||
id: changelog
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
- name: Save version to database
|
||||
id: save
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }}
|
||||
APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Release on GitHub
|
||||
if: ${{ inputs.release-github }}
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ steps.changelog.outputs.changelogTitle }}
|
||||
body_path: ${{ steps.changelog.outputs.changelogMarkdownFile }}
|
||||
files: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Distribute to App Distribution
|
||||
if: ${{ inputs.release-firebase }}
|
||||
uses: wzieba/Firebase-Distribution-Github-Action@v1
|
||||
with:
|
||||
appId: ${{ secrets.FIREBASE_APP_ID }}
|
||||
serviceCredentialsFileContent: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_JSON }}
|
||||
file: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
groups: ${{ inputs.nightly && secrets.FIREBASE_GROUPS_NIGHTLY || secrets.FIREBASE_GROUPS_RELEASE }}
|
||||
releaseNotesFile: ${{ inputs.nightly && steps.changelog.outputs.commitLogPlainFile || steps.changelog.outputs.changelogPlainTitledFile }}
|
||||
|
||||
- name: Publish AAB to Google Play
|
||||
if: ${{ inputs.release-google-play }}
|
||||
uses: r0adkll/upload-google-play@v1
|
||||
with:
|
||||
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
|
||||
packageName: pl.szczodrzynski.edziennik
|
||||
releaseFiles: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
releaseName: ${{ steps.changelog.outputs.appVersionName }}
|
||||
track: ${{ secrets.PLAY_RELEASE_TRACK }}
|
||||
whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }}
|
||||
status: completed
|
||||
|
||||
- name: Post Discord webhook
|
||||
if: ${{ inputs.release-discord }}
|
||||
env:
|
||||
APK_FILE: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
DOWNLOAD_URL: ${{ steps.save.outputs.downloadUrl }}
|
||||
WEBHOOK_RELEASE: ${{ secrets.WEBHOOK_RELEASE }}
|
||||
WEBHOOK_TESTING: ${{ secrets.WEBHOOK_TESTING }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/webhook_discord.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload workflow artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: ${{ steps.changelog.outputs.appVersionName }}
|
||||
path: |
|
||||
app/release/whatsnew*/
|
||||
app/release/*.apk
|
||||
app/release/*.aab
|
||||
app/release/*.json
|
||||
app/release/*.txt
|
154
.github/workflows/build-nightly-apk.yml
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
name: Nightly build
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# 23:30 UTC, 0:30 or 1:30 CET/CEST
|
||||
- cron: "30 23 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: Prepare build environment
|
||||
runs-on: self-hosted
|
||||
outputs:
|
||||
hasNewChanges: ${{ steps.nightly.outputs.hasNewChanges }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
clean: false
|
||||
- name: Set executable permissions to gradlew
|
||||
run: chmod +x ./gradlew
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
- name: Install packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
python-dotenv
|
||||
pycryptodome
|
||||
mysql-connector-python
|
||||
requests
|
||||
- name: Bump nightly version
|
||||
id: nightly
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/bump_nightly.py $GITHUB_WORKSPACE
|
||||
- name: Write signing passwords
|
||||
if: steps.nightly.outputs.hasNewChanges
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit
|
||||
build:
|
||||
name: Build APK
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- prepare
|
||||
if: ${{ needs.prepare.outputs.hasNewChanges == 'true' }}
|
||||
outputs:
|
||||
androidHome: ${{ env.ANDROID_HOME }}
|
||||
androidSdkRoot: ${{ env.ANDROID_SDK_ROOT }}
|
||||
steps:
|
||||
- name: Setup JDK 11
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v2
|
||||
- name: Clean build artifacts
|
||||
run: |
|
||||
rm -rf app/release/*
|
||||
rm -rf app/build/outputs/apk/*
|
||||
rm -rf app/build/outputs/bundle/*
|
||||
- name: Assemble official release with Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: assembleOfficialRelease
|
||||
sign:
|
||||
name: Sign APK
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- build
|
||||
outputs:
|
||||
signedReleaseFile: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
signedReleaseFileRelative: ${{ steps.artifacts.outputs.signedReleaseFileRelative }}
|
||||
steps:
|
||||
- name: Sign build artifacts
|
||||
id: sign_app
|
||||
uses: r0adkll/sign-android-release@v1
|
||||
with:
|
||||
releaseDirectory: app/release
|
||||
signingKeyBase64: ${{ secrets.KEY_STORE }}
|
||||
alias: ${{ secrets.KEY_ALIAS }}
|
||||
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
keyPassword: ${{ secrets.KEY_ALIAS_PASSWORD }}
|
||||
env:
|
||||
ANDROID_HOME: ${{ needs.build.outputs.androidHome }}
|
||||
ANDROID_SDK_ROOT: ${{ needs.build.outputs.androidSdkRoot }}
|
||||
BUILD_TOOLS_VERSION: "30.0.2"
|
||||
- name: Rename signed artifacts
|
||||
id: artifacts
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/rename_artifacts.py $GITHUB_WORKSPACE
|
||||
publish:
|
||||
name: Publish APK
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- sign
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
|
||||
- name: Extract changelogs
|
||||
id: changelog
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE
|
||||
|
||||
- name: Upload APK to SFTP
|
||||
uses: easingthemes/ssh-deploy@v2.1.6
|
||||
env:
|
||||
REMOTE_HOST: ${{ secrets.SSH_IP }}
|
||||
REMOTE_USER: ${{ secrets.SSH_USERNAME }}
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
|
||||
SOURCE: ${{ needs.sign.outputs.signedReleaseFileRelative }}
|
||||
TARGET: ${{ secrets.SSH_PATH_NIGHTLY }}
|
||||
- name: Save version metadata
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }}
|
||||
APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE
|
||||
|
||||
- name: Distribute to App Distribution
|
||||
uses: wzieba/Firebase-Distribution-Github-Action@v1
|
||||
with:
|
||||
appId: ${{ secrets.FIREBASE_APP_ID }}
|
||||
token: ${{ secrets.FIREBASE_TOKEN }}
|
||||
groups: ${{ secrets.FIREBASE_GROUPS_NIGHTLY }}
|
||||
file: ${{ needs.sign.outputs.signedReleaseFile }}
|
||||
releaseNotesFile: ${{ steps.changelog.outputs.commitLogPlainFile }}
|
||||
|
||||
- name: Post Discord webhook
|
||||
env:
|
||||
APK_FILE: ${{ needs.sign.outputs.signedReleaseFile }}
|
||||
APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }}
|
||||
APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }}
|
||||
WEBHOOK_RELEASE: ${{ secrets.WEBHOOK_RELEASE }}
|
||||
WEBHOOK_TESTING: ${{ secrets.WEBHOOK_TESTING }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/webhook_discord.py $GITHUB_WORKSPACE
|
||||
|
||||
- name: Upload workflow artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
if: true
|
||||
with:
|
||||
name: ${{ steps.changelog.outputs.appVersionName }}
|
||||
path: |
|
||||
app/release/whatsnew*/
|
||||
app/release/*.apk
|
||||
app/release/*.aab
|
||||
app/release/*.json
|
||||
app/release/*.txt
|
131
.github/workflows/build-release-aab-play.yml
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
name: Release build - Google Play [AAB]
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: Prepare build environment
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
clean: false
|
||||
- name: Set executable permissions to gradlew
|
||||
run: chmod +x ./gradlew
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
- name: Install packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
python-dotenv
|
||||
pycryptodome
|
||||
mysql-connector-python
|
||||
requests
|
||||
- name: Write signing passwords
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit
|
||||
build:
|
||||
name: Build App Bundle
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- prepare
|
||||
outputs:
|
||||
androidHome: ${{ env.ANDROID_HOME }}
|
||||
androidSdkRoot: ${{ env.ANDROID_SDK_ROOT }}
|
||||
steps:
|
||||
- name: Setup JDK 11
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v2
|
||||
- name: Clean build artifacts
|
||||
run: |
|
||||
rm -rf app/release/*
|
||||
rm -rf app/build/outputs/apk/*
|
||||
rm -rf app/build/outputs/bundle/*
|
||||
- name: Bundle play release with Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: bundlePlayRelease
|
||||
sign:
|
||||
name: Sign App Bundle
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- build
|
||||
outputs:
|
||||
signedReleaseFile: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
signedReleaseFileRelative: ${{ steps.artifacts.outputs.signedReleaseFileRelative }}
|
||||
steps:
|
||||
- name: Sign build artifacts
|
||||
id: sign_app
|
||||
uses: r0adkll/sign-android-release@v1
|
||||
with:
|
||||
releaseDirectory: app/release
|
||||
signingKeyBase64: ${{ secrets.KEY_STORE }}
|
||||
alias: ${{ secrets.KEY_ALIAS }}
|
||||
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
keyPassword: ${{ secrets.KEY_ALIAS_PASSWORD }}
|
||||
env:
|
||||
ANDROID_HOME: ${{ needs.build.outputs.androidHome }}
|
||||
ANDROID_SDK_ROOT: ${{ needs.build.outputs.androidSdkRoot }}
|
||||
BUILD_TOOLS_VERSION: "30.0.2"
|
||||
- name: Rename signed artifacts
|
||||
id: artifacts
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/rename_artifacts.py $GITHUB_WORKSPACE
|
||||
publish:
|
||||
name: Publish App Bundle
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- sign
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
|
||||
- name: Extract changelogs
|
||||
id: changelog
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE
|
||||
|
||||
- name: Save version metadata
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }}
|
||||
APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE
|
||||
|
||||
- name: Publish AAB to Google Play
|
||||
uses: r0adkll/upload-google-play@v1
|
||||
if: ${{ endsWith(needs.sign.outputs.signedReleaseFile, '.aab') }}
|
||||
with:
|
||||
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
|
||||
packageName: pl.szczodrzynski.edziennik
|
||||
releaseFile: ${{ needs.sign.outputs.signedReleaseFile }}
|
||||
releaseName: ${{ steps.changelog.outputs.appVersionName }}
|
||||
track: ${{ secrets.PLAY_RELEASE_TRACK }}
|
||||
whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }}
|
||||
|
||||
- name: Upload workflow artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
if: always()
|
||||
with:
|
||||
name: ${{ steps.changelog.outputs.appVersionName }}
|
||||
path: |
|
||||
app/release/whatsnew*/
|
||||
app/release/*.apk
|
||||
app/release/*.aab
|
||||
app/release/*.json
|
||||
app/release/*.txt
|
154
.github/workflows/build-release-apk.yml
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
name: Release build - official
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: Prepare build environment
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
clean: false
|
||||
- name: Set executable permissions to gradlew
|
||||
run: chmod +x ./gradlew
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
- name: Install packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
python-dotenv
|
||||
pycryptodome
|
||||
mysql-connector-python
|
||||
requests
|
||||
- name: Write signing passwords
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit
|
||||
build:
|
||||
name: Build APK
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- prepare
|
||||
outputs:
|
||||
androidHome: ${{ env.ANDROID_HOME }}
|
||||
androidSdkRoot: ${{ env.ANDROID_SDK_ROOT }}
|
||||
steps:
|
||||
- name: Setup JDK 11
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v2
|
||||
- name: Clean build artifacts
|
||||
run: |
|
||||
rm -rf app/release/*
|
||||
rm -rf app/build/outputs/apk/*
|
||||
rm -rf app/build/outputs/bundle/*
|
||||
- name: Assemble official release with Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: assembleOfficialRelease
|
||||
sign:
|
||||
name: Sign APK
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- build
|
||||
outputs:
|
||||
signedReleaseFile: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
signedReleaseFileRelative: ${{ steps.artifacts.outputs.signedReleaseFileRelative }}
|
||||
steps:
|
||||
- name: Sign build artifacts
|
||||
id: sign_app
|
||||
uses: r0adkll/sign-android-release@v1
|
||||
with:
|
||||
releaseDirectory: app/release
|
||||
signingKeyBase64: ${{ secrets.KEY_STORE }}
|
||||
alias: ${{ secrets.KEY_ALIAS }}
|
||||
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
keyPassword: ${{ secrets.KEY_ALIAS_PASSWORD }}
|
||||
env:
|
||||
ANDROID_HOME: ${{ needs.build.outputs.androidHome }}
|
||||
ANDROID_SDK_ROOT: ${{ needs.build.outputs.androidSdkRoot }}
|
||||
BUILD_TOOLS_VERSION: "30.0.2"
|
||||
- name: Rename signed artifacts
|
||||
id: artifacts
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/rename_artifacts.py $GITHUB_WORKSPACE
|
||||
publish:
|
||||
name: Publish APK
|
||||
runs-on: self-hosted
|
||||
needs:
|
||||
- sign
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
|
||||
- name: Extract changelogs
|
||||
id: changelog
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE
|
||||
|
||||
- name: Upload APK to SFTP
|
||||
uses: easingthemes/ssh-deploy@v2.1.6
|
||||
env:
|
||||
REMOTE_HOST: ${{ secrets.SSH_IP }}
|
||||
REMOTE_USER: ${{ secrets.SSH_USERNAME }}
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
|
||||
SOURCE: ${{ needs.sign.outputs.signedReleaseFileRelative }}
|
||||
TARGET: ${{ secrets.SSH_PATH_RELEASE }}
|
||||
- name: Save version metadata
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }}
|
||||
APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE
|
||||
|
||||
- name: Distribute to App Distribution
|
||||
uses: wzieba/Firebase-Distribution-Github-Action@v1
|
||||
with:
|
||||
appId: ${{ secrets.FIREBASE_APP_ID }}
|
||||
token: ${{ secrets.FIREBASE_TOKEN }}
|
||||
groups: ${{ secrets.FIREBASE_GROUPS_RELEASE }}
|
||||
file: ${{ needs.sign.outputs.signedReleaseFile }}
|
||||
releaseNotesFile: ${{ steps.changelog.outputs.changelogPlainTitledFile }}
|
||||
- name: Release on GitHub
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ steps.changelog.outputs.changelogTitle }}
|
||||
body_path: ${{ steps.changelog.outputs.changelogMarkdownFile }}
|
||||
files: ${{ needs.sign.outputs.signedReleaseFile }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Post Discord webhook
|
||||
env:
|
||||
APK_FILE: ${{ needs.sign.outputs.signedReleaseFile }}
|
||||
APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }}
|
||||
APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }}
|
||||
WEBHOOK_RELEASE: ${{ secrets.WEBHOOK_RELEASE }}
|
||||
WEBHOOK_TESTING: ${{ secrets.WEBHOOK_TESTING }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/webhook_discord.py $GITHUB_WORKSPACE
|
||||
|
||||
- name: Upload workflow artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
if: true
|
||||
with:
|
||||
name: ${{ steps.changelog.outputs.appVersionName }}
|
||||
path: |
|
||||
app/release/whatsnew*/
|
||||
app/release/*.apk
|
||||
app/release/*.aab
|
||||
app/release/*.json
|
||||
app/release/*.txt
|
13
.github/workflows/push-master.yml
vendored
@ -1,13 +0,0 @@
|
||||
name: Push (master)
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
jobs:
|
||||
build:
|
||||
name: Build for Google Play (AAB)
|
||||
uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop
|
||||
with:
|
||||
build-aab: true
|
||||
release-ssh: true
|
||||
release-google-play: true
|
||||
secrets: inherit
|
15
.github/workflows/release.yml
vendored
@ -1,15 +0,0 @@
|
||||
name: Release
|
||||
on:
|
||||
push:
|
||||
tags: ["v*.*.*"]
|
||||
jobs:
|
||||
build:
|
||||
name: Build release (APK)
|
||||
uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop
|
||||
with:
|
||||
build-apk: true
|
||||
release-ssh: true
|
||||
release-github: true
|
||||
release-firebase: true
|
||||
release-discord: true
|
||||
secrets: inherit
|
42
.github/workflows/schedule-dispatch.yml
vendored
@ -1,42 +0,0 @@
|
||||
name: Schedule/dispatch
|
||||
on:
|
||||
schedule:
|
||||
# 23:30 UTC, 0:30 or 1:30 CET/CEST
|
||||
- cron: "30 23 * * *"
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
check:
|
||||
name: Check new changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
hasNewChanges: ${{ steps.nightly.outputs.hasNewChanges }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
clean: false
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
- name: Install packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
requests
|
||||
- name: Check new changes
|
||||
id: nightly
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/check_nightly.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
|
||||
build:
|
||||
name: Build nightly release (APK)
|
||||
needs:
|
||||
- check
|
||||
if: ${{ needs.check.outputs.hasNewChanges == 'true' }}
|
||||
uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop
|
||||
with:
|
||||
nightly: true
|
||||
build-apk: true
|
||||
release-ssh: true
|
||||
release-firebase: true
|
||||
release-discord: true
|
||||
secrets: inherit
|
27
.idea/codeStyles/Project.xml
generated
@ -1,33 +1,9 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="LAYOUT_SETTINGS">
|
||||
<value>
|
||||
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="MANIFEST_SETTINGS">
|
||||
<value>
|
||||
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="OTHER_SETTINGS">
|
||||
<value>
|
||||
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||
</value>
|
||||
</option>
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="ALLOW_TRAILING_COMMA" value="true" />
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="JSON">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
<option name="SMART_TABS" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
@ -143,9 +119,6 @@
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||
<option name="PARAMETER_ANNOTATION_WRAP" value="2" />
|
||||
<option name="ENUM_CONSTANTS_WRAP" value="2" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
3
.idea/dictionaries/Kuba.xml
generated
@ -4,9 +4,7 @@
|
||||
<w>autoryzacji</w>
|
||||
<w>ciasteczko</w>
|
||||
<w>csrf</w>
|
||||
<w>daynight</w>
|
||||
<w>edziennik</w>
|
||||
<w>eggfall</w>
|
||||
<w>elearning</w>
|
||||
<w>gson</w>
|
||||
<w>hebe</w>
|
||||
@ -15,7 +13,6 @@
|
||||
<w>synergia</w>
|
||||
<w>szczodrzyński</w>
|
||||
<w>szkolny</w>
|
||||
<w>usos</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
@ -6,13 +6,13 @@
|
||||
[](https://szkolny.eu/)
|
||||
[](https://szkolny.eu/facebook)
|
||||
|
||||

|
||||

|
||||
[](https://github.com/szkolny-eu/szkolny-android/releases/latest)
|
||||

|
||||
|
||||
[](https://github.com/szkolny-eu/szkolny-android/actions/workflows/release.yml)
|
||||
[](https://github.com/szkolny-eu/szkolny-android/actions/workflows/push-master.yml)
|
||||
[](https://github.com/szkolny-eu/szkolny-android/actions/workflows/schedule-dispatch.yml)
|
||||
[](https://github.com/szkolny-eu/szkolny-android/actions/workflows/build-release-apk.yml)
|
||||
[](https://github.com/szkolny-eu/szkolny-android/actions/workflows/build-release-aab-play.yml)
|
||||
[](https://github.com/szkolny-eu/szkolny-android/actions/workflows/build-nightly-apk.yml)
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -10,10 +10,8 @@ apply from: 'git-info.gradle'
|
||||
android {
|
||||
compileSdkVersion setup.compileSdk
|
||||
|
||||
namespace "pl.szczodrzynski.edziennik"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "pl.szczodrzynski.edziennik"
|
||||
applicationId 'pl.szczodrzynski.edziennik'
|
||||
minSdkVersion setup.minSdk
|
||||
targetSdkVersion setup.targetSdk
|
||||
|
||||
@ -22,7 +20,6 @@ android {
|
||||
|
||||
buildConfigField "java.util.Map<String, String>", "GIT_INFO", gitInfoMap
|
||||
buildConfigField "String", "VERSION_BASE", "\"${release.versionName}\""
|
||||
|
||||
manifestPlaceholders = [
|
||||
buildTimestamp: String.valueOf(System.currentTimeMillis())
|
||||
]
|
||||
@ -39,8 +36,6 @@ android {
|
||||
arguments {
|
||||
arg("room.schemaLocation", "$projectDir/schemas")
|
||||
}
|
||||
|
||||
correctErrorTypes = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,12 +43,10 @@ android {
|
||||
debug {
|
||||
getIsDefault().set(true)
|
||||
minifyEnabled = false
|
||||
applicationIdSuffix = ".debug"
|
||||
manifestPlaceholders = [
|
||||
buildTimestamp: "0"
|
||||
buildTimestamp: 0
|
||||
]
|
||||
}
|
||||
|
||||
release {
|
||||
minifyEnabled = true
|
||||
shrinkResources = true
|
||||
@ -61,35 +54,28 @@ android {
|
||||
proguardFiles fileTree('proguard').asList().toArray()
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions += "platform"
|
||||
|
||||
flavorDimensions "platform"
|
||||
productFlavors {
|
||||
unofficial {
|
||||
getIsDefault().set(true)
|
||||
versionName "${release.versionName}-${gitInfo.versionSuffix}"
|
||||
}
|
||||
|
||||
official {}
|
||||
play {}
|
||||
}
|
||||
|
||||
variantFilter { variant ->
|
||||
def flavors = variant.flavors*.name
|
||||
setIgnore(variant.buildType.name == "debug" && !flavors.contains("unofficial") || flavors.contains("main"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
unofficial {
|
||||
java.srcDirs = ["src/main/java", "src/play-not/java"]
|
||||
manifest.srcFile("src/play-not/AndroidManifest.xml")
|
||||
}
|
||||
|
||||
official {
|
||||
java.srcDirs = ["src/main/java", "src/play-not/java"]
|
||||
manifest.srcFile("src/play-not/AndroidManifest.xml")
|
||||
}
|
||||
|
||||
play {
|
||||
java.srcDirs = ["src/main/java", "src/play/java"]
|
||||
}
|
||||
@ -98,45 +84,37 @@ android {
|
||||
defaultConfig {
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
dataBinding = true
|
||||
viewBinding = true
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled = true
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs += "-Xcontext-receivers"
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
resources {
|
||||
excludes += ['META-INF/library-core_release.kotlin_module']
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "src/main/cpp/CMakeLists.txt"
|
||||
version "3.10.2"
|
||||
}
|
||||
}
|
||||
|
||||
lint {
|
||||
checkReleaseBuilds false
|
||||
}
|
||||
}
|
||||
|
||||
tasks.whenTaskAdded { task ->
|
||||
if (!(task.name == "assembleUnofficialRelease" || task.name == "assembleOfficialRelease" || task.name == "signPlayReleaseBundle"))
|
||||
if (!task.name.endsWith("Release") && !task.name.endsWith("ReleaseWithR8"))
|
||||
return
|
||||
|
||||
def renameTaskName = "rename${task.name.capitalize()}"
|
||||
|
||||
def flavor = ""
|
||||
@ -146,22 +124,17 @@ tasks.whenTaskAdded { task ->
|
||||
flavor = task.name.substring("assemble".length(), task.name.indexOf("Release")).uncapitalize()
|
||||
if (task.name.startsWith("minify"))
|
||||
flavor = task.name.substring("minify".length(), task.name.indexOf("Release")).uncapitalize()
|
||||
if (task.name.startsWith("sign"))
|
||||
flavor = task.name.substring("sign".length(), task.name.indexOf("Release")).uncapitalize()
|
||||
|
||||
if (flavor != "") {
|
||||
tasks.register(renameTaskName, Copy) {
|
||||
dependsOn(task.name)
|
||||
duplicatesStrategy DuplicatesStrategy.FAIL
|
||||
tasks.create(renameTaskName, Copy) {
|
||||
from file("${projectDir}/${flavor}/release/"),
|
||||
file("${projectDir}/build/outputs/apk/${flavor}/release/"),
|
||||
file("${projectDir}/build/outputs/mapping/${flavor}Release/"),
|
||||
file("${projectDir}/build/outputs/bundle/${flavor}Release/")
|
||||
include "*-release.aab", "*-release.apk", "mapping.txt", "output-metadata.json"
|
||||
file("${buildDir}/outputs/mapping/${flavor}Release/"),
|
||||
file("${buildDir}/outputs/apk/${flavor}/release/"),
|
||||
file("${buildDir}/outputs/bundle/${flavor}Release/")
|
||||
include "*.aab", "*.apk", "mapping.txt", "output-metadata.json"
|
||||
destinationDir file("${projectDir}/release/")
|
||||
rename ".+?\\.(.+)", "Edziennik_${android.defaultConfig.versionName}_${flavor}." + '$1'
|
||||
}
|
||||
|
||||
task.finalizedBy(renameTaskName)
|
||||
}
|
||||
}
|
||||
@ -172,29 +145,28 @@ dependencies {
|
||||
// Language cores
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation "androidx.multidex:multidex:2.0.1"
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.4"
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
||||
|
||||
// Android Jetpack
|
||||
implementation "androidx.appcompat:appcompat:1.7.0"
|
||||
implementation "androidx.appcompat:appcompat:1.5.1"
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||
implementation "androidx.core:core-ktx:1.13.1"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.2"
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:2.7.7"
|
||||
implementation "androidx.recyclerview:recyclerview:1.3.2"
|
||||
implementation "androidx.room:room-runtime:2.6.1"
|
||||
implementation "androidx.room:room-ktx:2.6.1"
|
||||
implementation "androidx.work:work-runtime-ktx:2.9.0"
|
||||
kapt "androidx.room:room-compiler:2.6.1"
|
||||
implementation "androidx.core:core-ktx:1.9.0"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:2.5.2"
|
||||
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||
implementation "androidx.room:room-runtime:2.4.3"
|
||||
implementation "androidx.work:work-runtime-ktx:2.7.1"
|
||||
kapt "androidx.room:room-compiler:2.4.3"
|
||||
|
||||
// Google design libs
|
||||
implementation "com.google.android.material:material:1.12.0"
|
||||
implementation "com.google.android.material:material:1.6.1"
|
||||
implementation "com.google.android.flexbox:flexbox:3.0.0"
|
||||
|
||||
// Play Services/Firebase
|
||||
implementation "com.google.android.gms:play-services-wearable:18.2.0"
|
||||
implementation "com.google.android.gms:play-services-wearable:17.1.0"
|
||||
implementation("com.google.firebase:firebase-core") { version { strictly "19.0.2" } }
|
||||
implementation "com.google.firebase:firebase-crashlytics:19.0.1"
|
||||
implementation "com.google.firebase:firebase-crashlytics:18.2.13"
|
||||
implementation("com.google.firebase:firebase-messaging") { version { strictly "20.1.3" } }
|
||||
|
||||
// OkHttp, Retrofit, Gson, Jsoup
|
||||
@ -202,13 +174,12 @@ dependencies {
|
||||
implementation "com.squareup.retrofit2:retrofit:2.9.0"
|
||||
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
|
||||
implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
|
||||
implementation 'com.google.code.gson:gson:2.11.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.8'
|
||||
implementation 'org.jsoup:jsoup:1.14.3'
|
||||
implementation "pl.droidsonroids:jspoon:1.3.2"
|
||||
implementation "pl.droidsonroids.retrofit2:converter-jspoon:1.3.2"
|
||||
|
||||
// Szkolny.eu libraries/forks
|
||||
implementation project(":navlib")
|
||||
implementation "eu.szkolny:android-snowfall:1ca9ea2da3"
|
||||
implementation "eu.szkolny:agendacalendarview:1.0.4"
|
||||
implementation "eu.szkolny:cafebar:5bf0c618de"
|
||||
@ -216,22 +187,20 @@ dependencies {
|
||||
implementation "eu.szkolny:material-about-library:1d5ebaf47c"
|
||||
implementation "eu.szkolny:mhttp:af4b62e6e9"
|
||||
implementation "eu.szkolny:nachos:0e5dfcaceb"
|
||||
implementation "eu.szkolny.selective-dao:annotation:6a337f9"
|
||||
implementation "eu.szkolny.selective-dao:annotation:27f8f3f194"
|
||||
officialImplementation "eu.szkolny:ssl-provider:1.0.0"
|
||||
unofficialImplementation "eu.szkolny:ssl-provider:1.0.0"
|
||||
|
||||
implementation "pl.szczodrzynski:navlib:0.8.0"
|
||||
implementation "pl.szczodrzynski:numberslidingpicker:2921225f76"
|
||||
implementation "pl.szczodrzynski:recyclertablayout:700f980584"
|
||||
implementation "pl.szczodrzynski:tachyon:551943a6b5"
|
||||
kapt "eu.szkolny.selective-dao:codegen:6a337f9"
|
||||
kapt "eu.szkolny.selective-dao:codegen:27f8f3f194"
|
||||
|
||||
// Iconics & related
|
||||
implementation "com.mikepenz:iconics-core:5.3.2"
|
||||
implementation "com.mikepenz:iconics-views:5.3.2"
|
||||
implementation "com.mikepenz:materialdrawer:9.0.1"
|
||||
implementation "com.mikepenz:community-material-typeface:5.8.55.0-kotlin@aar"
|
||||
implementation 'com.mikepenz:google-material-typeface:4.0.0.2-kotlin@aar'
|
||||
implementation "eu.szkolny:szkolny-font:95eabe7"
|
||||
implementation "eu.szkolny:szkolny-font:77e33acc2a"
|
||||
|
||||
// Other dependencies
|
||||
implementation "cat.ereza:customactivityoncrash:2.3.0"
|
||||
@ -239,14 +208,14 @@ dependencies {
|
||||
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
||||
implementation "com.github.Applandeo:Material-Calendar-View:15de569cbc" // https://github.com/Applandeo/Material-Calendar-View
|
||||
implementation "com.github.CanHub:Android-Image-Cropper:2.2.2" // https://github.com/CanHub/Android-Image-Cropper
|
||||
implementation "com.github.ChuckerTeam.Chucker:library:3.5.2" // https://github.com/ChuckerTeam/chucker
|
||||
implementation "com.github.ChuckerTeam.Chucker:library:3.0.1" // https://github.com/ChuckerTeam/chucker
|
||||
implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2" // https://github.com/antonKozyriatskyi/CircularProgressIndicator
|
||||
implementation "com.github.bassaer:chatmessageview:2.0.1" // https://github.com/bassaer/ChatMessageView
|
||||
implementation "com.github.hypertrack:hyperlog-android:0.0.10" // https://github.com/hypertrack/hyperlog-android
|
||||
implementation "com.github.smuyyh:JsonViewer:V1.0.6" // https://github.com/smuyyh/JsonViewer
|
||||
implementation "com.github.underwindfall.PowerPermission:powerpermission-coroutines:1.4.0" // https://github.com/underwindfall/PowerPermission
|
||||
implementation "com.github.underwindfall.PowerPermission:powerpermission:1.4.0" // https://github.com/underwindfall/PowerPermission
|
||||
implementation "com.github.wulkanowy.uonet-request-signer:hebe-jvm:a99ca50a31" // https://github.com/wulkanowy/uonet-request-signer
|
||||
implementation 'com.jakewharton.timber:timber:5.0.1'
|
||||
implementation "com.jaredrummler:colorpicker:1.1.0"
|
||||
implementation "io.coil-kt:coil:1.1.1"
|
||||
implementation "me.dm7.barcodescanner:zxing:1.9.8"
|
||||
|
@ -5,7 +5,7 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.eclipse.jgit:org.eclipse.jgit:5.5.+"
|
||||
|
@ -36,37 +36,6 @@
|
||||
"status": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:640759989760:android:4aa71407b25cdc8d",
|
||||
"android_client_info": {
|
||||
"package_name": "pl.szczodrzynski.edziennik.debug"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "640759989760-6f8q00u864lnuh3gh36e8g4cer9lv8pv.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyAvq9HMPxulz9ntdAHZ0eZuPf2YQs4nDSU"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"analytics_service": {
|
||||
"status": 1
|
||||
},
|
||||
"appinvite_service": {
|
||||
"status": 1,
|
||||
"other_platform_oauth_client": []
|
||||
},
|
||||
"ads_service": {
|
||||
"status": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
|
33
app/proguard-rules.pro
vendored
@ -19,13 +19,9 @@
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
-keepattributes Signature
|
||||
-keep class android.support.v7.widget.** { *; }
|
||||
-keep class com.google.gson.reflect.TypeToken { *; }
|
||||
-keep class * extends com.google.gson.reflect.TypeToken
|
||||
|
||||
-keep class pl.szczodrzynski.edziennik.utils.models.** { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.enums.* { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.entity.Event { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.full.EventFull { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage { *; }
|
||||
@ -35,9 +31,6 @@
|
||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.timetable.WidgetTimetableProvider
|
||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.notifications.WidgetNotificationsProvider
|
||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.luckynumber.WidgetLuckyNumberProvider
|
||||
-keep class pl.szczodrzynski.edziennik.data.config.AppData { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.config.AppData$** { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.core.manager.TextStylingManager$HtmlMode { *; }
|
||||
|
||||
-keepnames class androidx.appcompat.view.menu.MenuBuilder { setHeaderTitleInt(java.lang.CharSequence); }
|
||||
-keepnames class androidx.appcompat.view.menu.MenuPopupHelper { showPopup(int, int, boolean, boolean); }
|
||||
@ -45,20 +38,6 @@
|
||||
-keepclassmembernames class androidx.appcompat.view.menu.MenuItemImpl { private *; }
|
||||
|
||||
-keepclassmembernames class com.mikepenz.materialdrawer.widget.MiniDrawerSliderView { private *; }
|
||||
-keepclassmembernames class com.mikepenz.iconics.internal.IconicsViewsAttrsApplier {
|
||||
<fields>;
|
||||
readIconicsTextView(android.content.Context, android.util.AttributeSet, com.mikepenz.iconics.internal.CompoundIconsBundle);
|
||||
getIconicsImageViewDrawable(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclassmembernames class com.mikepenz.iconics.internal.CompoundIconsBundle {
|
||||
setIcons(android.widget.TextView);
|
||||
}
|
||||
|
||||
# for RecyclerTabView
|
||||
-keepclassmembernames class com.google.android.material.tabs.TabLayout { *; }
|
||||
-keepclassmembernames class com.google.android.material.tabs.TabLayout$TabView { *; }
|
||||
-keepclassmembernames class com.google.android.material.tabs.TabIndicatorInterpolator { *; }
|
||||
|
||||
-keep class .R
|
||||
-keep class **.R$* {
|
||||
@ -72,17 +51,6 @@
|
||||
|
||||
-keep class com.google.android.material.tabs.** {*;}
|
||||
|
||||
# Exclude AgendaCalendarView
|
||||
# Preserve generic type information for EventRenderer and its subclasses
|
||||
-keepclassmembers class * extends com.github.tibolte.agendacalendarview.render.EventRenderer {
|
||||
<fields>;
|
||||
<methods>;
|
||||
}
|
||||
|
||||
# Keep the EventRenderer class itself and all its subclasses
|
||||
-keep class com.github.tibolte.agendacalendarview.render.EventRenderer
|
||||
-keep class * extends com.github.tibolte.agendacalendarview.render.EventRenderer
|
||||
|
||||
# ServiceLoader support
|
||||
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
|
||||
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
|
||||
@ -98,7 +66,6 @@
|
||||
|
||||
-keep class pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing { public final byte[] pleaseStopRightNow(java.lang.String, long); }
|
||||
|
||||
-keepclassmembers class pl.szczodrzynski.edziennik.ui.login.qr.* { *; }
|
||||
-keepclassmembers class pl.szczodrzynski.edziennik.data.api.szkolny.request.** { *; }
|
||||
-keepclassmembers class pl.szczodrzynski.edziennik.data.api.szkolny.response.** { *; }
|
||||
-keepclassmembernames class pl.szczodrzynski.edziennik.ui.login.LoginInfo$Platform { *; }
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 874 B |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 24 KiB |
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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="pl.szczodrzynski.edziennik">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
@ -11,21 +12,19 @@
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
|
||||
<!-- PowerPermission uses minSdk 21, it's safe to override as it is used only in >= 23 -->
|
||||
<uses-sdk
|
||||
tools:overrideLibrary="com.qifan.powerpermission.coroutines, com.qifan.powerpermission.core, com.mikepenz:materialdrawer, com.mikepenz.iconics.typeface.library.navlibfont, androidx.appcompat.resources, androidx.appcompat, com.google.android.gms.wearable, com.google.android.gms.base, com.google.firebase.crashlytics, com.google.firebase.sessions, com.google.firebase.ktx, com.google.firebase, com.google.android.gms.tasks, com.google.android.gms.common, com.google.firebase.components" />
|
||||
<uses-sdk tools:overrideLibrary="com.qifan.powerpermission.coroutines, com.qifan.powerpermission.core" />
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="@xml/backup_descriptor"
|
||||
android:icon="@mipmap/ic_launcher_v5"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme.M3.Blue"
|
||||
android:theme="@style/AppTheme.Dark"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
@ -41,6 +40,7 @@
|
||||
|___/ -->
|
||||
<activity android:name=".MainActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:exported="true"
|
||||
android:theme="@style/SplashTheme">
|
||||
@ -67,7 +67,7 @@
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:exported="true"
|
||||
android:theme="@style/AppTheme.M3.NoDisplay">
|
||||
android:theme="@style/AppTheme.Dark.NoDisplay">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
@ -84,14 +84,14 @@
|
||||
android:resource="@xml/widget_timetable_info" />
|
||||
</receiver>
|
||||
<service android:name=".ui.widgets.timetable.WidgetTimetableService"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" android:foregroundServiceType="dataSync"/>
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
<activity android:name=".ui.widgets.LessonDialogActivity"
|
||||
android:label=""
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:exported="true"
|
||||
android:theme="@style/AppTheme.M3.NoDisplay" />
|
||||
android:theme="@style/AppTheme.Dark.NoDisplay" />
|
||||
<!-- NOTIFICATIONS -->
|
||||
<receiver android:name=".ui.widgets.notifications.WidgetNotificationsProvider"
|
||||
android:label="@string/widget_notifications_title"
|
||||
@ -105,7 +105,7 @@
|
||||
android:resource="@xml/widget_notifications_info" />
|
||||
</receiver>
|
||||
<service android:name=".ui.widgets.notifications.WidgetNotificationsService"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" android:foregroundServiceType="dataSync"/>
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
<!-- LUCKY NUMBER -->
|
||||
<receiver android:name=".ui.widgets.luckynumber.WidgetLuckyNumberProvider"
|
||||
android:label="@string/widget_lucky_number_title"
|
||||
@ -126,44 +126,39 @@
|
||||
/ ____ \ (__| |_| |\ V /| | |_| | __/\__ \
|
||||
/_/ \_\___|\__|_| \_/ |_|\__|_|\___||___/
|
||||
-->
|
||||
<activity android:name=".ui.main.CrashActivity"
|
||||
<activity android:name=".ui.base.CrashActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:process=":error_activity"
|
||||
android:exported="false"
|
||||
android:theme="@style/DeadTheme" />
|
||||
<activity android:name=".ui.intro.ChangelogIntroActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/app_name"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.Intro" />
|
||||
<activity android:name=".ui.login.LoginActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:launchMode="singleTop"
|
||||
android:exported="false"
|
||||
android:theme="@style/AppTheme.M3" />
|
||||
android:theme="@style/AppTheme.Light" />
|
||||
<activity android:name=".ui.home.CounterActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/AppTheme.M3" />
|
||||
android:theme="@style/AppTheme.Black" />
|
||||
<activity android:name=".ui.feedback.FeedbackActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:label="@string/app_name"
|
||||
android:exported="false"
|
||||
android:theme="@style/AppTheme.M3" />
|
||||
android:theme="@style/AppTheme" />
|
||||
<activity android:name=".ui.settings.SettingsLicenseActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:theme="@style/AppTheme.M3" />
|
||||
android:theme="@style/AppTheme" />
|
||||
<activity android:name="com.canhub.cropper.CropImageActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:theme="@style/Base.Theme.AppCompat" />
|
||||
<activity android:name=".ui.login.oauth.OAuthLoginActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.MaterialComponents.Light.DarkActionBar" />
|
||||
<activity android:name=".ui.login.recaptcha.RecaptchaActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.MaterialComponents.Light.DarkActionBar" />
|
||||
<activity android:name=".ui.main.BuildInvalidActivity" android:exported="false" />
|
||||
<activity android:name=".ui.base.BuildInvalidActivity" android:exported="false" />
|
||||
<activity android:name=".ui.settings.contributors.ContributorsActivity" android:exported="false" />
|
||||
|
||||
<!-- _____ _
|
||||
| __ \ (_)
|
||||
@ -172,7 +167,7 @@
|
||||
| | \ \ __/ (_| __/ |\ V / __/ | \__ \
|
||||
|_| \_\___|\___\___|_| \_/ \___|_| |___/
|
||||
-->
|
||||
<receiver android:name=".core.receiver.UserPresentReceiver"
|
||||
<receiver android:name=".receivers.UserPresentReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
@ -185,7 +180,7 @@
|
||||
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name=".core.receiver.SzkolnyReceiver"
|
||||
<receiver android:name=".receivers.SzkolnyReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="pl.szczodrzynski.edziennik.SZKOLNY_MAIN" />
|
||||
@ -199,15 +194,15 @@
|
||||
____) | __/ | \ V /| | (_| __/\__ \
|
||||
|_____/ \___|_| \_/ |_|\___\___||___/
|
||||
-->
|
||||
<service android:name=".data.api.ApiService" android:foregroundServiceType="dataSync"/>
|
||||
<service android:name=".core.firebase.MyFirebaseService"
|
||||
android:exported="false" android:foregroundServiceType="dataSync">
|
||||
<service android:name=".data.api.ApiService" />
|
||||
<service android:name=".data.firebase.MyFirebaseService"
|
||||
android:exported="false">
|
||||
<intent-filter android:priority="10000000">
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service android:name=".sync.UpdateDownloaderService" android:foregroundServiceType="dataSync"/>
|
||||
<service android:name=".sync.UpdateDownloaderService" />
|
||||
|
||||
<!--
|
||||
_____ _ _
|
||||
|
@ -1,11 +1,12 @@
|
||||
<h3>Wersja 4.14, 2025-02-02</h3>
|
||||
<h3>Wersja 4.12.1, 2022-09-23</h3>
|
||||
<ul>
|
||||
<li>USOS: <b>dodano obsługę ocen</b>.</li>
|
||||
<li>USOS: obliczanie średniej za studia oraz punktów ECTS.</li>
|
||||
<li>USOS: poprawiono brak planu zajęć po rozpoczęciu roku.</li>
|
||||
<li>Wyłączono archiwizator profili.</li>
|
||||
<li>Vulcan UONET+: naprawiono działanie systemu wiadomości. @Antoni-Czaplicki</li>
|
||||
<li>Vulcan UONET+: naprawiono błędy wersji 4.11.9 i starszych.</li>
|
||||
<li>Poprawiono wyświetlanie lekcji odwołanych na stronie głównej.</li>
|
||||
<li>Dodano dostęp do Laboratorium na ekranie logowania.</li>
|
||||
<li>Usunięto obsługę dziennika EduDziennik. [*]</li>
|
||||
</ul>
|
||||
<br>
|
||||
<br>
|
||||
Dzięki za korzystanie ze Szkolnego!<br>
|
||||
<i>© [Kuba Szczodrzyński](@kuba2k2) 2025</i>
|
||||
<i>© [Kuba Szczodrzyński](@kuba2k2), [Kacper Ziubryniewicz](@kapi2289) 2022</i>
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
project(szkolny-signing)
|
||||
|
||||
# Creates and names a library, sets it as either STATIC
|
||||
# or SHARED, and provides the relative paths to its source code.
|
||||
# You can define multiple libraries, and CMake builds them for you.
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
/*secret password - removed for source code publication*/
|
||||
static toys AES_IV[16] = {
|
||||
0xee, 0x23, 0xf1, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
0xdf, 0xe4, 0x2d, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
||||
|
||||
|
@ -4,9 +4,14 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.graphics.drawable.Icon
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.multidex.MultiDexApplication
|
||||
import androidx.work.Configuration
|
||||
@ -14,91 +19,65 @@ import cat.ereza.customactivityoncrash.config.CaocConfig
|
||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||
import com.chuckerteam.chucker.api.RetentionManager
|
||||
import com.google.firebase.FirebaseApp
|
||||
import com.google.firebase.FirebaseOptions
|
||||
import com.google.firebase.iid.FirebaseInstanceId
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.google.gson.Gson
|
||||
import com.hypertrack.hyperlog.HyperLog
|
||||
import com.mikepenz.iconics.Iconics
|
||||
import im.wangchao.mhttp.MHttp
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.*
|
||||
import me.leolin.shortcutbadger.ShortcutBadger
|
||||
import okhttp3.OkHttpClient
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.core.manager.AttendanceManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.AvailabilityManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.BuildManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.EventManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.FirebaseManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.GradesManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.LoggingManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.MessageManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.NoteManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.NotificationManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.PermissionManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.ShortcutManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.TextStylingManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.TimetableManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.UiManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.UpdateManager
|
||||
import pl.szczodrzynski.edziennik.core.manager.UserActionManager
|
||||
import pl.szczodrzynski.edziennik.core.network.DumbCookieJar
|
||||
import pl.szczodrzynski.edziennik.core.work.SyncWorker
|
||||
import pl.szczodrzynski.edziennik.core.work.UpdateWorker
|
||||
import pl.szczodrzynski.edziennik.config.Config
|
||||
import pl.szczodrzynski.edziennik.data.api.events.ProfileListEmptyEvent
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing
|
||||
import pl.szczodrzynski.edziennik.data.config.AppData
|
||||
import pl.szczodrzynski.edziennik.data.config.Config
|
||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.enums.LoginType
|
||||
import pl.szczodrzynski.edziennik.ext.DAY
|
||||
import pl.szczodrzynski.edziennik.ext.MS
|
||||
import pl.szczodrzynski.edziennik.ext.setLanguage
|
||||
import pl.szczodrzynski.edziennik.network.SSLProviderInstaller
|
||||
import pl.szczodrzynski.edziennik.ui.main.CrashActivity
|
||||
import pl.szczodrzynski.edziennik.utils.PermissionChecker
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import timber.log.Timber
|
||||
import pl.szczodrzynski.edziennik.network.cookie.DumbCookieJar
|
||||
import pl.szczodrzynski.edziennik.sync.SyncWorker
|
||||
import pl.szczodrzynski.edziennik.sync.UpdateWorker
|
||||
import pl.szczodrzynski.edziennik.ui.base.CrashActivity
|
||||
import pl.szczodrzynski.edziennik.utils.*
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
import pl.szczodrzynski.edziennik.utils.managers.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
companion object {
|
||||
@Volatile
|
||||
lateinit var db: AppDb
|
||||
private set
|
||||
lateinit var config: Config
|
||||
|
||||
// private set // for LabFragment
|
||||
lateinit var profile: Profile
|
||||
private set
|
||||
lateinit var data: AppData
|
||||
private set
|
||||
val profileId
|
||||
get() = profile.id
|
||||
|
||||
var enableChucker = false
|
||||
var debugMode = false
|
||||
var devMode = false
|
||||
}
|
||||
|
||||
val api by lazy { SzkolnyApi(this) }
|
||||
val attendanceManager by lazy { AttendanceManager(this) }
|
||||
val availabilityManager by lazy { AvailabilityManager(this) }
|
||||
val buildManager by lazy { BuildManager(this) }
|
||||
val eventManager by lazy { EventManager(this) }
|
||||
val firebaseManager by lazy { FirebaseManager(this) }
|
||||
val notificationChannelsManager by lazy { NotificationChannelsManager(this) }
|
||||
val userActionManager by lazy { UserActionManager(this) }
|
||||
val gradesManager by lazy { GradesManager(this) }
|
||||
val loggingManager by lazy { LoggingManager(this) }
|
||||
val timetableManager by lazy { TimetableManager(this) }
|
||||
val eventManager by lazy { EventManager(this) }
|
||||
val permissionManager by lazy { PermissionManager(this) }
|
||||
val attendanceManager by lazy { AttendanceManager(this) }
|
||||
val buildManager by lazy { BuildManager(this) }
|
||||
val availabilityManager by lazy { AvailabilityManager(this) }
|
||||
val textStylingManager by lazy { TextStylingManager(this) }
|
||||
val messageManager by lazy { MessageManager(this) }
|
||||
val noteManager by lazy { NoteManager(this) }
|
||||
val notificationManager by lazy { NotificationManager(this) }
|
||||
val permissionManager by lazy { PermissionManager(this) }
|
||||
val shortcutManager by lazy { ShortcutManager(this) }
|
||||
val textStylingManager by lazy { TextStylingManager(this) }
|
||||
val timetableManager by lazy { TimetableManager(this) }
|
||||
val uiManager by lazy { UiManager(this) }
|
||||
val updateManager by lazy { UpdateManager(this) }
|
||||
val userActionManager by lazy { UserActionManager(this) }
|
||||
|
||||
val db
|
||||
get() = App.db
|
||||
@ -108,14 +87,11 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
get() = App.profile
|
||||
val profileId
|
||||
get() = App.profileId
|
||||
val data
|
||||
get() = App.data
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
override val workManagerConfiguration: Configuration = Configuration.Builder()
|
||||
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
||||
.setMinimumLoggingLevel(Log.VERBOSE)
|
||||
.build()
|
||||
|
||||
@ -145,9 +121,11 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
SSLProviderInstaller.enableSupportedTls(builder, enableCleartext = true)
|
||||
|
||||
if (devMode) {
|
||||
HyperLog.initialize(this)
|
||||
HyperLog.setLogLevel(Log.VERBOSE)
|
||||
HyperLog.setLogFormat(DebugLogFormat(this))
|
||||
if (enableChucker) {
|
||||
val chuckerCollector =
|
||||
ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
|
||||
val chuckerCollector = ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
|
||||
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
|
||||
builder.addInterceptor(chuckerInterceptor)
|
||||
}
|
||||
@ -162,7 +140,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
|
||||
MHttp.instance().customOkHttpClient(http)
|
||||
}
|
||||
|
||||
val cookieJar by lazy { DumbCookieJar(this) }
|
||||
|
||||
/* _____ _ _
|
||||
@ -173,12 +150,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
|_____/|_|\__, |_| |_|\__,_|\__|\__,_|_| \___|
|
||||
__/ |
|
||||
|__*/
|
||||
val deviceId: String by lazy {
|
||||
Settings.Secure.getString(
|
||||
contentResolver,
|
||||
Settings.Secure.ANDROID_ID
|
||||
) ?: ""
|
||||
}
|
||||
val deviceId: String by lazy { Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID) ?: "" }
|
||||
private var unreadBadgesAvailable = true
|
||||
|
||||
/* _____ _
|
||||
@ -189,25 +161,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
\___/|_| |_|\_____|_| \___|\__,_|\__\__*/
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
// initialize Timber to enable basic logging
|
||||
Timber.plant(loggingManager.logcatTree)
|
||||
Timber.i("Initializing Szkolny.eu app v${BuildConfig.VERSION_NAME}")
|
||||
// initialize core objects
|
||||
AppData.read(this)
|
||||
App.db = AppDb(this)
|
||||
// read and migrate global config
|
||||
App.config = Config(this)
|
||||
App.config.migrate()
|
||||
// add database logging to Timber
|
||||
Timber.plant(loggingManager.databaseTree)
|
||||
Timber.i("Initialized Szkolny.eu app v${BuildConfig.VERSION_NAME}")
|
||||
|
||||
devMode = config.devMode ?: BuildConfig.DEBUG
|
||||
if (config.devModePassword != null)
|
||||
checkDevModePassword()
|
||||
enableChucker = config.enableChucker ?: devMode
|
||||
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||
CaocConfig.Builder.create()
|
||||
.backgroundMode(CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM)
|
||||
@ -223,37 +176,37 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
.apply()
|
||||
Iconics.init(applicationContext)
|
||||
Iconics.respectFontBoundsDefault = true
|
||||
Signing.getCert(this)
|
||||
Utils.initializeStorageDir(this)
|
||||
buildHttp()
|
||||
|
||||
uiManager.applyNightMode()
|
||||
uiManager.applyLanguage(this)
|
||||
// initialize companion object values
|
||||
App.db = AppDb(this)
|
||||
App.config = Config(App.db)
|
||||
App.profile = Profile(0, 0, 0, "")
|
||||
debugMode = BuildConfig.DEBUG
|
||||
devMode = config.devMode ?: debugMode
|
||||
enableChucker = config.enableChucker ?: devMode
|
||||
|
||||
if (!profileLoadById(config.lastProfileId)) {
|
||||
val success = db.profileDao().firstId?.let { profileLoadById(it) }
|
||||
if (success != true)
|
||||
profileLoad(Profile(0, 0, LoginType.TEMPLATE, ""))
|
||||
db.profileDao().firstId?.let { profileLoadById(it) }
|
||||
}
|
||||
|
||||
launch(Dispatchers.Default) {
|
||||
buildManager.fetchInstalledTime()
|
||||
firebaseManager.initializeApps()
|
||||
loggingManager.cleanupIfNeeded()
|
||||
loggingManager.cleanupHyperLogDatabase()
|
||||
notificationManager.registerAllChannels()
|
||||
shortcutManager.createShortcuts()
|
||||
buildHttp()
|
||||
|
||||
if (config.appVersionCore < BuildConfig.VERSION_CODE) {
|
||||
// force syncing all endpoints on update
|
||||
db.endpointTimerDao().clear()
|
||||
config.sync.lastAppSync = 0L
|
||||
config.hash = "invalid"
|
||||
config.appVersionCore = BuildConfig.VERSION_CODE
|
||||
Themes.themeInt = config.ui.theme
|
||||
config.ui.language?.let {
|
||||
setLanguage(it)
|
||||
}
|
||||
|
||||
Signing.getCert(this)
|
||||
|
||||
launch {
|
||||
withContext(Dispatchers.Default) {
|
||||
config.migrate(this@App)
|
||||
|
||||
SSLProviderInstaller.install(applicationContext, this@App::buildHttp)
|
||||
|
||||
if (config.devModePassword != null)
|
||||
checkDevModePassword()
|
||||
|
||||
if (config.sync.enabled)
|
||||
SyncWorker.scheduleNext(this@App, false)
|
||||
else
|
||||
@ -263,6 +216,159 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
UpdateWorker.scheduleNext(this@App, false)
|
||||
else
|
||||
UpdateWorker.cancelNext(this@App)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
val shortcutManager = getSystemService(ShortcutManager::class.java)
|
||||
|
||||
val shortcutTimetable = ShortcutInfo.Builder(this@App, "item_timetable")
|
||||
.setShortLabel(getString(R.string.shortcut_timetable)).setLongLabel(getString(R.string.shortcut_timetable))
|
||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_timetable))
|
||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE))
|
||||
.build()
|
||||
|
||||
val shortcutAgenda = ShortcutInfo.Builder(this@App, "item_agenda")
|
||||
.setShortLabel(getString(R.string.shortcut_agenda)).setLongLabel(getString(R.string.shortcut_agenda))
|
||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_agenda))
|
||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_AGENDA))
|
||||
.build()
|
||||
|
||||
val shortcutGrades = ShortcutInfo.Builder(this@App, "item_grades")
|
||||
.setShortLabel(getString(R.string.shortcut_grades)).setLongLabel(getString(R.string.shortcut_grades))
|
||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_grades))
|
||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_GRADES))
|
||||
.build()
|
||||
|
||||
val shortcutHomework = ShortcutInfo.Builder(this@App, "item_homeworks")
|
||||
.setShortLabel(getString(R.string.shortcut_homework)).setLongLabel(getString(R.string.shortcut_homework))
|
||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_homework))
|
||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOMEWORK))
|
||||
.build()
|
||||
|
||||
val shortcutMessages = ShortcutInfo.Builder(this@App, "item_messages")
|
||||
.setShortLabel(getString(R.string.shortcut_messages)).setLongLabel(getString(R.string.shortcut_messages))
|
||||
.setIcon(Icon.createWithResource(this@App, R.mipmap.ic_shortcut_messages))
|
||||
.setIntent(Intent(Intent.ACTION_MAIN, null, this@App, MainActivity::class.java)
|
||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_MESSAGES))
|
||||
.build()
|
||||
|
||||
shortcutManager.dynamicShortcuts = listOf(
|
||||
shortcutTimetable,
|
||||
shortcutAgenda,
|
||||
shortcutGrades,
|
||||
shortcutHomework,
|
||||
shortcutMessages
|
||||
)
|
||||
} // shortcuts - end
|
||||
|
||||
notificationChannelsManager.registerAllChannels()
|
||||
|
||||
|
||||
if (config.appInstalledTime == 0L)
|
||||
try {
|
||||
config.appInstalledTime = packageManager.getPackageInfo(packageName, 0).firstInstallTime
|
||||
config.appRateSnackbarTime = config.appInstalledTime + 7 * DAY * MS
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
val pushMobidziennikApp = FirebaseApp.initializeApp(
|
||||
this@App,
|
||||
FirebaseOptions.Builder()
|
||||
.setProjectId("mobidziennik")
|
||||
.setStorageBucket("mobidziennik.appspot.com")
|
||||
.setDatabaseUrl("https://mobidziennik.firebaseio.com")
|
||||
.setGcmSenderId("747285019373")
|
||||
.setApiKey("AIzaSyCi5LmsZ5BBCQnGtrdvWnp1bWLCNP8OWQE")
|
||||
.setApplicationId("1:747285019373:android:f6341bf7b158621d")
|
||||
.build(),
|
||||
"Mobidziennik2"
|
||||
)
|
||||
|
||||
val pushLibrusApp = FirebaseApp.initializeApp(
|
||||
this@App,
|
||||
FirebaseOptions.Builder()
|
||||
.setProjectId("synergiadru")
|
||||
.setStorageBucket("synergiadru.appspot.com")
|
||||
.setDatabaseUrl("https://synergiadru.firebaseio.com")
|
||||
.setGcmSenderId("513056078587")
|
||||
.setApiKey("AIzaSyDfTuEoYPKdv4aceEws1CO3n0-HvTndz-o")
|
||||
.setApplicationId("1:513056078587:android:1e29083b760af544")
|
||||
.build(),
|
||||
"Librus"
|
||||
)
|
||||
|
||||
val pushVulcanApp = FirebaseApp.initializeApp(
|
||||
this@App,
|
||||
FirebaseOptions.Builder()
|
||||
.setProjectId("dzienniczekplus")
|
||||
.setStorageBucket("dzienniczekplus.appspot.com")
|
||||
.setDatabaseUrl("https://dzienniczekplus.firebaseio.com")
|
||||
.setGcmSenderId("987828170337")
|
||||
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
|
||||
.setApplicationId("1:987828170337:android:ac97431a0a4578c3")
|
||||
.build(),
|
||||
"Vulcan"
|
||||
)
|
||||
|
||||
val pushVulcanHebeApp = FirebaseApp.initializeApp(
|
||||
this@App,
|
||||
FirebaseOptions.Builder()
|
||||
.setProjectId("dzienniczekplus")
|
||||
.setStorageBucket("dzienniczekplus.appspot.com")
|
||||
.setDatabaseUrl("https://dzienniczekplus.firebaseio.com")
|
||||
.setGcmSenderId("987828170337")
|
||||
.setApiKey("AIzaSyDW8MUtanHy64_I0oCpY6cOxB3jrvJd_iA")
|
||||
.setApplicationId("1:987828170337:android:7e16404b9e5deaaa")
|
||||
.build(),
|
||||
"VulcanHebe"
|
||||
)
|
||||
|
||||
try {
|
||||
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener { instanceIdResult ->
|
||||
val token = instanceIdResult.token
|
||||
d("Firebase", "Got App token: $token")
|
||||
config.sync.tokenApp = token
|
||||
}
|
||||
FirebaseInstanceId.getInstance(pushMobidziennikApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
||||
val token = instanceIdResult.token
|
||||
d("Firebase", "Got Mobidziennik2 token: $token")
|
||||
if (token != config.sync.tokenMobidziennik) {
|
||||
config.sync.tokenMobidziennik = token
|
||||
config.sync.tokenMobidziennikList = listOf()
|
||||
}
|
||||
}
|
||||
FirebaseInstanceId.getInstance(pushLibrusApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
||||
val token = instanceIdResult.token
|
||||
d("Firebase", "Got Librus token: $token")
|
||||
if (token != config.sync.tokenLibrus) {
|
||||
config.sync.tokenLibrus = token
|
||||
config.sync.tokenLibrusList = listOf()
|
||||
}
|
||||
}
|
||||
FirebaseInstanceId.getInstance(pushVulcanApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
||||
val token = instanceIdResult.token
|
||||
d("Firebase", "Got Vulcan token: $token")
|
||||
if (token != config.sync.tokenVulcan) {
|
||||
config.sync.tokenVulcan = token
|
||||
config.sync.tokenVulcanList = listOf()
|
||||
}
|
||||
}
|
||||
FirebaseInstanceId.getInstance(pushVulcanHebeApp).instanceId.addOnSuccessListener { instanceIdResult ->
|
||||
val token = instanceIdResult.token
|
||||
d("Firebase", "Got VulcanHebe token: $token")
|
||||
if (token != config.sync.tokenVulcanHebe) {
|
||||
config.sync.tokenVulcanHebe = token
|
||||
config.sync.tokenVulcanHebeList = listOf()
|
||||
}
|
||||
}
|
||||
FirebaseMessaging.getInstance().subscribeToTopic(packageName)
|
||||
} catch (e: IllegalStateException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
db.metadataDao().countUnseen().observeForever { count: Int ->
|
||||
@ -270,34 +376,16 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
unreadBadgesAvailable = ShortcutBadger.applyCount(this@App, count)
|
||||
}
|
||||
}
|
||||
|
||||
fun profileLoad(profile: Profile) {
|
||||
App.profile = profile
|
||||
App.config.lastProfileId = profile.id
|
||||
try {
|
||||
App.data = AppData.get(profile.loginStoreType)
|
||||
Timber.d("Loaded AppData: ${App.data}")
|
||||
// apply newly-added config overrides, if not changed by the user yet
|
||||
for ((key, value) in App.data.configOverrides) {
|
||||
val config = App.profile.config
|
||||
if (key !in config)
|
||||
config[key] = value
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Cannot load AppData")
|
||||
Toast.makeText(this, R.string.app_cannot_load_data, Toast.LENGTH_LONG).show()
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun profileLoadById(profileId: Int): Boolean {
|
||||
db.profileDao().getByIdNow(profileId)?.also {
|
||||
profileLoad(it)
|
||||
App.profile = it
|
||||
App.config.lastProfileId = it.id
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun profileLoad(profileId: Int, onSuccess: (profile: Profile) -> Unit) {
|
||||
launch {
|
||||
val success = withContext(Dispatchers.Default) {
|
||||
@ -309,7 +397,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
profileLoadLast(onSuccess)
|
||||
}
|
||||
}
|
||||
|
||||
fun profileLoadLast(onSuccess: (profile: Profile) -> Unit) {
|
||||
launch {
|
||||
val success = withContext(Dispatchers.Default) {
|
||||
@ -317,29 +404,24 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
}
|
||||
if (!success) {
|
||||
EventBus.getDefault().post(ProfileListEmptyEvent())
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
onSuccess(profile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun profileSave() = profileSave(profile)
|
||||
fun profileSave(profile: Profile) {
|
||||
if (profile.id == profileId)
|
||||
App.profile = profile
|
||||
launch(Dispatchers.Default) {
|
||||
App.db.profileDao().add(profile)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkDevModePassword() {
|
||||
devMode = devMode || try {
|
||||
Utils.AESCrypt.decrypt(
|
||||
"nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=",
|
||||
config.devModePassword
|
||||
) == "ok here you go it's enabled now"
|
||||
devMode = try {
|
||||
Utils.AESCrypt.decrypt("nWFVxY65Pa8/aRrT7EylNAencmOD+IxUY2Gg/beiIWY=", config.devModePassword) == "ok here you go it's enabled now" || BuildConfig.DEBUG
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
e.printStackTrace()
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
interface AbstractConfig {
|
||||
fun set(key: String, value: String?)
|
||||
}
|
155
app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.BuildConfig
|
||||
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
||||
import pl.szczodrzynski.edziennik.config.utils.*
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
|
||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
||||
companion object {
|
||||
const val DATA_VERSION = 12
|
||||
}
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Default
|
||||
|
||||
val values: HashMap<String, String?> = hashMapOf()
|
||||
|
||||
val ui by lazy { ConfigUI(this) }
|
||||
val sync by lazy { ConfigSync(this) }
|
||||
val timetable by lazy { ConfigTimetable(this) }
|
||||
val grades by lazy { ConfigGrades(this) }
|
||||
|
||||
private var mDataVersion: Int? = null
|
||||
var dataVersion: Int
|
||||
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
||||
set(value) { set("dataVersion", value); mDataVersion = value }
|
||||
|
||||
private var mHash: String? = null
|
||||
var hash: String
|
||||
get() { mHash = mHash ?: values.get("hash", ""); return mHash ?: "" }
|
||||
set(value) { set("hash", value); mHash = value }
|
||||
|
||||
private var mLastProfileId: Int? = null
|
||||
var lastProfileId: Int
|
||||
get() { mLastProfileId = mLastProfileId ?: values.get("lastProfileId", 0); return mLastProfileId ?: 0 }
|
||||
set(value) { set("lastProfileId", value); mLastProfileId = value }
|
||||
|
||||
private var mUpdatesChannel: String? = null
|
||||
var updatesChannel: String
|
||||
get() { mUpdatesChannel = mUpdatesChannel ?: values.get("updatesChannel", "release"); return mUpdatesChannel ?: "release" }
|
||||
set(value) { set("updatesChannel", value); mUpdatesChannel = value }
|
||||
private var mUpdate: Update? = null
|
||||
var update: Update?
|
||||
get() { mUpdate = mUpdate ?: values.get("update", null as Update?); return mUpdate ?: null as Update? }
|
||||
set(value) { set("update", value); mUpdate = value }
|
||||
|
||||
private var mAppVersion: Int? = null
|
||||
var appVersion: Int
|
||||
get() { mAppVersion = mAppVersion ?: values.get("appVersion", BuildConfig.VERSION_CODE); return mAppVersion ?: BuildConfig.VERSION_CODE }
|
||||
set(value) { set("appVersion", value); mAppVersion = value }
|
||||
|
||||
private var mLoginFinished: Boolean? = null
|
||||
var loginFinished: Boolean
|
||||
get() { mLoginFinished = mLoginFinished ?: values.get("loginFinished", false); return mLoginFinished ?: false }
|
||||
set(value) { set("loginFinished", value); mLoginFinished = value }
|
||||
|
||||
private var mPrivacyPolicyAccepted: Boolean? = null
|
||||
var privacyPolicyAccepted: Boolean
|
||||
get() { mPrivacyPolicyAccepted = mPrivacyPolicyAccepted ?: values.get("privacyPolicyAccepted", false); return mPrivacyPolicyAccepted ?: false }
|
||||
set(value) { set("privacyPolicyAccepted", value); mPrivacyPolicyAccepted = value }
|
||||
|
||||
private var mDevMode: Boolean? = null
|
||||
var devMode: Boolean?
|
||||
get() { mDevMode = mDevMode ?: values.getBooleanOrNull("debugMode"); return mDevMode }
|
||||
set(value) { set("debugMode", value?.toString()); mDevMode = value }
|
||||
|
||||
private var mEnableChucker: Boolean? = null
|
||||
var enableChucker: Boolean?
|
||||
get() { mEnableChucker = mEnableChucker ?: values.getBooleanOrNull("enableChucker"); return mEnableChucker }
|
||||
set(value) { set("enableChucker", value?.toString()); mEnableChucker = value }
|
||||
|
||||
private var mDevModePassword: String? = null
|
||||
var devModePassword: String?
|
||||
get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword }
|
||||
set(value) { set("devModePassword", value); mDevModePassword = value }
|
||||
|
||||
private var mAppInstalledTime: Long? = null
|
||||
var appInstalledTime: Long
|
||||
get() { mAppInstalledTime = mAppInstalledTime ?: values.get("appInstalledTime", 0L); return mAppInstalledTime ?: 0L }
|
||||
set(value) { set("appInstalledTime", value); mAppInstalledTime = value }
|
||||
|
||||
private var mAppRateSnackbarTime: Long? = null
|
||||
var appRateSnackbarTime: Long
|
||||
get() { mAppRateSnackbarTime = mAppRateSnackbarTime ?: values.get("appRateSnackbarTime", 0L); return mAppRateSnackbarTime ?: 0L }
|
||||
set(value) { set("appRateSnackbarTime", value); mAppRateSnackbarTime = value }
|
||||
|
||||
private var mRunSync: Boolean? = null
|
||||
var runSync: Boolean
|
||||
get() { mRunSync = mRunSync ?: values.get("runSync", false); return mRunSync ?: false }
|
||||
set(value) { set("runSync", value); mRunSync = value }
|
||||
|
||||
private var mWidgetConfigs: JsonObject? = null
|
||||
var widgetConfigs: JsonObject
|
||||
get() { mWidgetConfigs = mWidgetConfigs ?: values.get("widgetConfigs", JsonObject()); return mWidgetConfigs ?: JsonObject() }
|
||||
set(value) { set("widgetConfigs", value); mWidgetConfigs = value }
|
||||
|
||||
private var mArchiverEnabled: Boolean? = null
|
||||
var archiverEnabled: Boolean
|
||||
get() { mArchiverEnabled = mArchiverEnabled ?: values.get("archiverEnabled", true); return mArchiverEnabled ?: true }
|
||||
set(value) { set("archiverEnabled", value); mArchiverEnabled = value }
|
||||
|
||||
private var mValidation: String? = null
|
||||
var validation: String?
|
||||
get() { mValidation = mValidation ?: values["buildValidation"]; return mValidation }
|
||||
set(value) { set("buildValidation", value); mValidation = value }
|
||||
|
||||
private var mApiInvalidCert: String? = null
|
||||
var apiInvalidCert: String?
|
||||
get() { mApiInvalidCert = mApiInvalidCert ?: values["apiInvalidCert"]; return mApiInvalidCert }
|
||||
set(value) { set("apiInvalidCert", value); mApiInvalidCert = value }
|
||||
|
||||
private var mApiAvailabilityCheck: Boolean? = null
|
||||
var apiAvailabilityCheck: Boolean
|
||||
get() { mApiAvailabilityCheck = mApiAvailabilityCheck ?: values.get("apiAvailabilityCheck", true); return mApiAvailabilityCheck ?: true }
|
||||
set(value) { set("apiAvailabilityCheck", value); mApiAvailabilityCheck = value }
|
||||
|
||||
private var rawEntries: List<ConfigEntry> = db.configDao().getAllNow()
|
||||
private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
|
||||
init {
|
||||
rawEntries.toHashMap(-1, values)
|
||||
}
|
||||
fun migrate(app: App) {
|
||||
if (dataVersion < DATA_VERSION)
|
||||
ConfigMigration(app, this)
|
||||
}
|
||||
fun getFor(profileId: Int): ProfileConfig {
|
||||
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, db.configDao().getAllNow(profileId)).also {
|
||||
profileConfigs[profileId] = it
|
||||
}
|
||||
}
|
||||
fun forProfile() = getFor(App.profileId)
|
||||
|
||||
fun setProfile(profileId: Int) {
|
||||
}
|
||||
|
||||
override fun set(key: String, value: String?) {
|
||||
values[key] = value
|
||||
launch {
|
||||
db.configDao().add(ConfigEntry(-1, key, value))
|
||||
}
|
||||
}
|
||||
}
|