Compare commits
No commits in common. "master" and "v1.1.0" have entirely different histories.
@ -1,101 +0,0 @@
|
|||||||
|
|
||||||
# https://docs.gitea.com/next/usage/actions/quickstart
|
|
||||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
|
||||||
# https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
|
|
||||||
|
|
||||||
# Configurable with a few commit messages:
|
|
||||||
# - [skip-tests] Skip the test stage
|
|
||||||
# - [skip-deployment] Skip the deployment stage
|
|
||||||
# - [skip-ci] Skip all stages (the whole ci/cd)
|
|
||||||
#
|
|
||||||
|
|
||||||
name: Build Docker and Deploy
|
|
||||||
run-name: Build & Deploy ${{ gitea.ref }} on ${{ gitea.actor }}
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: ['master']
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_server:
|
|
||||||
name: Build Docker Container
|
|
||||||
runs-on: bfb-cicd-latest
|
|
||||||
if: >-
|
|
||||||
!contains(github.event.head_commit.message, '[skip-ci]') &&
|
|
||||||
!contains(github.event.head_commit.message, '[skip-deployment]')
|
|
||||||
steps:
|
|
||||||
- run: echo -n "${{ secrets.DOCKER_REG_PASS }}" | docker login registry.blackforestbytes.com -u docker --password-stdin
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- run: cd "${{ gitea.workspace }}/scnserver" && make clean
|
|
||||||
- run: cd "${{ gitea.workspace }}/scnserver" && make docker
|
|
||||||
- run: cd "${{ gitea.workspace }}/scnserver" && make push-docker
|
|
||||||
|
|
||||||
test_server:
|
|
||||||
name: Run Unit-Tests
|
|
||||||
runs-on: bfb-cicd-latest
|
|
||||||
if: >-
|
|
||||||
!contains(github.event.head_commit.message, '[skip-ci]') &&
|
|
||||||
!contains(github.event.head_commit.message, '[skip-tests]')
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Get Commiter Info
|
|
||||||
id: commiter_info
|
|
||||||
run: |
|
|
||||||
echo "NAME=$( git log -n 1 --pretty=format:%an )" >> $GITHUB_OUTPUT
|
|
||||||
echo "MAIL=$( git log -n 1 --pretty=format:%ae )" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: '${{ gitea.workspace }}/scnserver/go.mod'
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: Print Go Version
|
|
||||||
run: go version
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: cd "${{ gitea.workspace }}/scnserver" && make dgi && make swagger && SCN_TEST_LOGLEVEL=WARN make test
|
|
||||||
|
|
||||||
- name: Send failure mail
|
|
||||||
if: failure()
|
|
||||||
uses: dawidd6/action-send-mail@v3
|
|
||||||
with:
|
|
||||||
server_address: smtp.fastmail.com
|
|
||||||
server_port: 465
|
|
||||||
secure: true
|
|
||||||
username: ${{secrets.MAIL_USERNAME}}
|
|
||||||
password: ${{secrets.MAIL_PASSWORD}}
|
|
||||||
subject: Pipeline on '${{ gitea.repository }}' failed
|
|
||||||
to: ${{ steps.commiter_info.outputs.MAIL }}
|
|
||||||
from: Gitea Actions <gitea_actions@blackforestbytes.de>
|
|
||||||
body: "Go to https://gogs.blackforestbytes.com/${{ gitea.repository }}/actions"
|
|
||||||
|
|
||||||
deploy_server:
|
|
||||||
name: Deploy to Server
|
|
||||||
needs: [build_server, test_server]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: >-
|
|
||||||
!cancelled() &&
|
|
||||||
!contains(github.event.head_commit.message, '[skip-ci]') &&
|
|
||||||
!contains(github.event.head_commit.message, '[skip-deployment]') &&
|
|
||||||
needs.build_server.result == 'success' &&
|
|
||||||
(needs.test_server.result == 'skipped' || needs.test_server.result == 'success')
|
|
||||||
steps:
|
|
||||||
- name: Execute deploy on remote (via ssh)
|
|
||||||
uses: appleboy/ssh-action@v1.0.0
|
|
||||||
with:
|
|
||||||
host: simplecloudnotifier.de
|
|
||||||
username: bfb-deploy-bot
|
|
||||||
port: 4477
|
|
||||||
key: "${{ secrets.SSH_KEY_BFBDEPLOYBOT }}"
|
|
||||||
script: cd /var/docker/deploy-scripts/simplecloudnotifier && ./deploy.sh master "${{ gitea.sha }}" || exit 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
.aider*
|
|
6
android/.idea/AndroidProjectSystem.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="AndroidProjectSystem">
|
|
||||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
85
android/.idea/assetWizardSettings.xml
generated
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="WizardSettings">
|
||||||
|
<option name="children">
|
||||||
|
<map>
|
||||||
|
<entry key="imageWizard">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="children">
|
||||||
|
<map>
|
||||||
|
<entry key="imageAssetPanel">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="children">
|
||||||
|
<map>
|
||||||
|
<entry key="launcherLegacy">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="assetType" value="IMAGE" />
|
||||||
|
<entry key="cropped" value="true" />
|
||||||
|
<entry key="iconShape" value="NONE" />
|
||||||
|
<entry key="imageAsset" value="F:\Eigene Dateien\Dropbox\Programming\Java\AndroidStudioProjects\SimpleCloudNotifier\data\icon_512_nobox.png" />
|
||||||
|
<entry key="outputName" value="ic_notification_full" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="notification">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="assetType" value="IMAGE" />
|
||||||
|
<entry key="imageAsset" value="F:\Eigene Dateien\Dropbox\Programming\Java\AndroidStudioProjects\SimpleCloudNotifier\data\icon_512_transparent.png" />
|
||||||
|
<entry key="outputName" value="ic_notification_white" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="outputIconType" value="LAUNCHER_LEGACY" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="vectorWizard">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="children">
|
||||||
|
<map>
|
||||||
|
<entry key="vectorAssetStep">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="assetSourceType" value="FILE" />
|
||||||
|
<entry key="outputName" value="ic_garbage" />
|
||||||
|
<entry key="sourceFile" value="C:\Users\Mike\Downloads\garbage.svg" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
134
android/.idea/codeStyles/Project.xml
generated
@ -1,113 +1,29 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<codeStyleSettings language="XML">
|
<Objective-C-extensions>
|
||||||
<arrangement>
|
<file>
|
||||||
<rules>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||||
<section>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||||
<rule>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||||
<match>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||||
<AND>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||||
<NAME>xmlns:android</NAME>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||||
<XML_ATTRIBUTE />
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||||
</AND>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||||
</match>
|
</file>
|
||||||
</rule>
|
<class>
|
||||||
</section>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||||
<section>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||||
<rule>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||||
<match>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||||
<AND>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||||
<NAME>xmlns:.*</NAME>
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||||
<XML_ATTRIBUTE />
|
</class>
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
<extensions>
|
||||||
</AND>
|
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
||||||
</match>
|
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||||
<order>BY_NAME</order>
|
</extensions>
|
||||||
</rule>
|
</Objective-C-extensions>
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:id</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:name</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>name</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>style</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
</rules>
|
|
||||||
</arrangement>
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
10
android/.idea/deploymentTargetDropDown.xml
generated
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="deploymentTargetDropDown">
|
|
||||||
<value>
|
|
||||||
<entry key="app">
|
|
||||||
<State />
|
|
||||||
</entry>
|
|
||||||
</value>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
10
android/.idea/deploymentTargetSelector.xml
generated
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="deploymentTargetSelector">
|
|
||||||
<selectionStates>
|
|
||||||
<SelectionState runConfigName="app">
|
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
|
||||||
</SelectionState>
|
|
||||||
</selectionStates>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
40
android/.idea/jarRepositories.xml
generated
@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="RemoteRepositoriesConfiguration">
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="central" />
|
|
||||||
<option name="name" value="Maven Central repository" />
|
|
||||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="jboss.community" />
|
|
||||||
<option name="name" value="JBoss Community repository" />
|
|
||||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="maven2" />
|
|
||||||
<option name="name" value="maven2" />
|
|
||||||
<option name="url" value="https://dl.bintray.com/gericop/maven" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="maven3" />
|
|
||||||
<option name="name" value="maven3" />
|
|
||||||
<option name="url" value="https://maven.google.com" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="BintrayJCenter" />
|
|
||||||
<option name="name" value="BintrayJCenter" />
|
|
||||||
<option name="url" value="https://jcenter.bintray.com/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="maven" />
|
|
||||||
<option name="name" value="maven" />
|
|
||||||
<option name="url" value="https://jitpack.io" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="Google" />
|
|
||||||
<option name="name" value="Google" />
|
|
||||||
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
|
||||||
</remote-repository>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
10
android/.idea/migrations.xml
generated
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectMigrations">
|
|
||||||
<option name="MigrateToGradleLocalJavaHome">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
11
android/.idea/runConfigurations.xml
generated
@ -3,14 +3,9 @@
|
|||||||
<component name="RunConfigurationProducerService">
|
<component name="RunConfigurationProducerService">
|
||||||
<option name="ignoredProducers">
|
<option name="ignoredProducers">
|
||||||
<set>
|
<set>
|
||||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
compileSdkVersion 28
|
||||||
|
|
||||||
def versionPropsFile = file('version.properties')
|
def versionPropsFile = file('version.properties')
|
||||||
def vNumber
|
def vNumber
|
||||||
@ -16,7 +16,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.blackforestbytes.simplecloudnotifier"
|
applicationId "com.blackforestbytes.simplecloudnotifier"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 28
|
||||||
versionCode vNumber
|
versionCode vNumber
|
||||||
versionName vName
|
versionName vName
|
||||||
}
|
}
|
||||||
@ -30,88 +30,81 @@ android {
|
|||||||
targetCompatibility 1.8
|
targetCompatibility 1.8
|
||||||
sourceCompatibility 1.8
|
sourceCompatibility 1.8
|
||||||
}
|
}
|
||||||
namespace 'com.blackforestbytes.simplecloudnotifier'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.0.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.0.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
implementation 'com.google.firebase:firebase-core:18.0.0'
|
implementation 'com.google.firebase:firebase-core:16.0.4'
|
||||||
implementation 'com.google.firebase:firebase-messaging:21.0.0'
|
implementation 'com.google.firebase:firebase-messaging:17.3.4'
|
||||||
implementation 'com.google.android.gms:play-services-ads:19.5.0'
|
implementation 'com.google.android.gms:play-services-ads:17.1.0'
|
||||||
implementation 'com.android.billingclient:billing:3.0.1'
|
implementation 'com.android.billingclient:billing:1.2'
|
||||||
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
|
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
|
||||||
implementation 'com.github.kenglxn.QRGen:android:2.5.0'
|
implementation 'com.github.kenglxn.QRGen:android:2.5.0'
|
||||||
implementation "com.github.DeweyReed:UltimateMusicPicker:2.0.0"
|
implementation "com.github.DeweyReed:UltimateMusicPicker:2.0.0"
|
||||||
implementation 'com.github.duanhong169:colorpicker:1.1.5'
|
implementation 'com.github.duanhong169:colorpicker:1.1.5'
|
||||||
|
|
||||||
implementation 'net.danlew:android.joda:2.10.7.1'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
|
||||||
tasks.register("updateVersion") {
|
task updateVersion << {
|
||||||
group = 'Custom'
|
def lastTag = ['git', 'describe', "--abbrev=0", "--tags"].execute().text.trim()
|
||||||
|
|
||||||
doLast {
|
def versionPropsFile = file('version.properties')
|
||||||
def lastTag = ['git', 'describe', "--abbrev=0", "--tags"].execute().text.trim()
|
if (!versionPropsFile.canRead()) throw new FileNotFoundException("Could not read version.properties!")
|
||||||
|
Properties versionProps = new Properties()
|
||||||
|
new FileInputStream(versionPropsFile).withCloseable { fis -> versionProps.load(fis) }
|
||||||
|
|
||||||
def versionPropsFile = file('version.properties')
|
def matcher = lastTag =~ /^v([0-9]+)\.([0-9]+)\.([0-9]+)$/
|
||||||
if (!versionPropsFile.canRead()) throw new FileNotFoundException("Could not read version.properties!")
|
|
||||||
Properties versionProps = new Properties()
|
|
||||||
new FileInputStream(versionPropsFile).withCloseable { fis -> versionProps.load(fis) }
|
|
||||||
|
|
||||||
def matcher = lastTag =~ /^v([0-9]+)\.([0-9]+)\.([0-9]+)$/
|
if (!matcher.matches()) throw new Exception("Last Tag ('" + lastTag + "') has invalid format :(")
|
||||||
|
|
||||||
if (!matcher.matches()) throw new Exception("Last Tag ('" + lastTag + "') has invalid format :(")
|
def vName = (matcher[0][1] as Integer) + "." + (matcher[0][2] as Integer) + "." + (matcher[0][3] as Integer)
|
||||||
|
def vCode = versionProps['VERSION_CODE'] as Integer
|
||||||
|
|
||||||
def vName = (matcher[0][1] as Integer) + "." + (matcher[0][2] as Integer) + "." + (matcher[0][3] as Integer)
|
if (new File(".do_publish_beta_release").exists()) new File(".do_publish_beta_release").delete()
|
||||||
def vCode = versionProps['VERSION_CODE'] as Integer
|
if (new File(".do_publish_prod_release").exists()) new File(".do_publish_prod_release").delete()
|
||||||
|
|
||||||
if (new File(".do_publish_beta_release").exists()) new File(".do_publish_beta_release").delete()
|
if (vName == versionProps['VERSION_NAME'].toString()) {
|
||||||
if (new File(".do_publish_prod_release").exists()) new File(".do_publish_prod_release").delete()
|
println "This version was already built - skip deployment"
|
||||||
|
} else if (vName.endsWith(".0")) {
|
||||||
|
println ""
|
||||||
|
println "====================================================================="
|
||||||
|
println "====================================================================="
|
||||||
|
println "(!) This is a new PRODUCTION release - create deployment trigger file"
|
||||||
|
println "====================================================================="
|
||||||
|
println "====================================================================="
|
||||||
|
println ""
|
||||||
|
|
||||||
if (vName == versionProps['VERSION_NAME'].toString()) {
|
vCode++
|
||||||
println "This version was already built - skip deployment"
|
new File(".do_publish_prod_release").createNewFile()
|
||||||
} else if (vName.endsWith(".0")) {
|
|
||||||
println ""
|
|
||||||
println "====================================================================="
|
|
||||||
println "====================================================================="
|
|
||||||
println "(!) This is a new PRODUCTION release - create deployment trigger file"
|
|
||||||
println "====================================================================="
|
|
||||||
println "====================================================================="
|
|
||||||
println ""
|
|
||||||
|
|
||||||
vCode++
|
versionProps['VERSION_NAME'] = vName.toString()
|
||||||
new File(".do_publish_prod_release").createNewFile()
|
versionProps['VERSION_CODE'] = vCode.toString()
|
||||||
|
|
||||||
versionProps['VERSION_NAME'] = vName.toString()
|
versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
|
||||||
versionProps['VERSION_CODE'] = vCode.toString()
|
} else {
|
||||||
|
println ""
|
||||||
|
println "==============================================================="
|
||||||
|
println "(!) This is a new beta release - create deployment trigger file"
|
||||||
|
println "==============================================================="
|
||||||
|
println ""
|
||||||
|
|
||||||
versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
|
vCode++
|
||||||
} else {
|
new File(".do_publish_beta_release").createNewFile()
|
||||||
println ""
|
|
||||||
println "==============================================================="
|
|
||||||
println "(!) This is a new beta release - create deployment trigger file"
|
|
||||||
println "==============================================================="
|
|
||||||
println ""
|
|
||||||
|
|
||||||
vCode++
|
versionProps['VERSION_NAME'] = vName.toString()
|
||||||
new File(".do_publish_beta_release").createNewFile()
|
versionProps['VERSION_CODE'] = vCode.toString()
|
||||||
|
|
||||||
versionProps['VERSION_NAME'] = vName.toString()
|
versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
|
||||||
versionProps['VERSION_CODE'] = vCode.toString()
|
|
||||||
|
|
||||||
versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,67 +1,43 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="com.blackforestbytes.simplecloudnotifier">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="com.android.vending.BILLING" />
|
<uses-permission android:name="com.android.vending.BILLING" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".SCNApp"
|
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
|
android:name="SCNApp"
|
||||||
android:icon="@drawable/icon"
|
android:icon="@drawable/icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:ignore="GoogleAppIndexingWarning">
|
tools:ignore="GoogleAppIndexingWarning">
|
||||||
|
|
||||||
<activity android:name=".view.MainActivity">
|
<activity android:name=".view.MainActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<provider
|
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/icon" />
|
||||||
android:name="androidx.core.content.FileProvider"
|
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" />
|
||||||
android:authorities="com.blackforestbytes.simplecloudnotifier.fileprovider"
|
<meta-data android:name="com.google.android.gms.ads.AD_MANAGER_APP" android:value="true"/>
|
||||||
android:grantUriPermissions="true"
|
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-3320562328966175~7579972005"/>
|
||||||
android:exported="false">
|
|
||||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" />
|
|
||||||
</provider>
|
|
||||||
|
|
||||||
|
<service android:name=".service.FBMService" android:exported="false">
|
||||||
<meta-data
|
|
||||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
|
||||||
android:resource="@drawable/icon" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.firebase.messaging.default_notification_color"
|
|
||||||
android:resource="@color/colorAccent" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.android.gms.ads.AD_MANAGER_APP"
|
|
||||||
android:value="true" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
|
||||||
android:value="ca-app-pub-3320562328966175~7579972005" />
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".service.FBMService"
|
|
||||||
android:exported="false">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<receiver
|
<receiver android:name=".service.BroadcastReceiverService" android:exported="false" />
|
||||||
android:name=".service.BroadcastReceiverService"
|
|
||||||
android:exported="false" />
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".view.debug.QueryLogActivity"
|
|
||||||
android:label="@string/title_activity_query_log"
|
|
||||||
android:theme="@style/AppTheme" />
|
|
||||||
<activity android:name=".view.debug.SingleQueryLogActivity" />
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -5,7 +5,6 @@ import android.content.Context;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.billingclient.api.BillingClient;
|
import com.android.billingclient.api.BillingClient;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.QueryLog;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.view.AccountFragment;
|
import com.blackforestbytes.simplecloudnotifier.view.AccountFragment;
|
||||||
import com.blackforestbytes.simplecloudnotifier.view.MainActivity;
|
import com.blackforestbytes.simplecloudnotifier.view.MainActivity;
|
||||||
import com.blackforestbytes.simplecloudnotifier.view.TabAdapter;
|
import com.blackforestbytes.simplecloudnotifier.view.TabAdapter;
|
||||||
@ -100,5 +99,4 @@ public class SCNApp extends Application implements LifecycleObserver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Config for collapsed line count
|
//TODO TabLayout indicator does not corretly animate when directly clicking on tabs
|
||||||
//TODO: Sometimes ads but promode
|
|
@ -9,8 +9,6 @@ import java.util.TimeZone;
|
|||||||
|
|
||||||
public class CMessage
|
public class CMessage
|
||||||
{
|
{
|
||||||
public boolean IsExpandedInAdapter = false;
|
|
||||||
|
|
||||||
public final long SCN_ID;
|
public final long SCN_ID;
|
||||||
public final long Timestamp;
|
public final long Timestamp;
|
||||||
public final String Title;
|
public final String Title;
|
||||||
|
@ -35,11 +35,6 @@ public class CMessageList
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CMessageList()
|
private CMessageList()
|
||||||
{
|
|
||||||
reloadPrefs();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reloadPrefs()
|
|
||||||
{
|
{
|
||||||
synchronized (msg_lock)
|
synchronized (msg_lock)
|
||||||
{
|
{
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.model;
|
|
||||||
|
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
|
|
||||||
public enum LogLevel
|
|
||||||
{
|
|
||||||
DEBUG,
|
|
||||||
INFO,
|
|
||||||
WARN,
|
|
||||||
ERROR;
|
|
||||||
|
|
||||||
public String toUIString()
|
|
||||||
{
|
|
||||||
switch (this)
|
|
||||||
{
|
|
||||||
case DEBUG: return "Debug";
|
|
||||||
case INFO: return "Info";
|
|
||||||
case WARN: return "Warning";
|
|
||||||
case ERROR: return "Error";
|
|
||||||
default: return "???";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getColor()
|
|
||||||
{
|
|
||||||
switch (this)
|
|
||||||
{
|
|
||||||
case DEBUG: return Color.GRAY;
|
|
||||||
case WARN: return Color.rgb(171, 145, 68);
|
|
||||||
case INFO: return Color.BLACK;
|
|
||||||
case ERROR: return Color.RED;
|
|
||||||
default: return Color.MAGENTA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int asInt()
|
|
||||||
{
|
|
||||||
switch (this)
|
|
||||||
{
|
|
||||||
case DEBUG: return 0;
|
|
||||||
case WARN: return 1;
|
|
||||||
case INFO: return 2;
|
|
||||||
case ERROR: return 3;
|
|
||||||
default: return 999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LogLevel fromInt(int i)
|
|
||||||
{
|
|
||||||
if (i == 0) return LogLevel.DEBUG;
|
|
||||||
if (i == 1) return LogLevel.WARN;
|
|
||||||
if (i == 2) return LogLevel.INFO;
|
|
||||||
if (i == 3) return LogLevel.ERROR;
|
|
||||||
|
|
||||||
return LogLevel.ERROR; // ????
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.model;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.collections.CollectionHelper;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class QueryLog
|
|
||||||
{
|
|
||||||
private final static int MAX_HISTORY_SIZE = 192;
|
|
||||||
|
|
||||||
private static QueryLog _instance;
|
|
||||||
public static QueryLog inst() { if (_instance == null) synchronized (QueryLog.class) { if (_instance == null) _instance = new QueryLog(); } return _instance; }
|
|
||||||
|
|
||||||
private QueryLog(){ reloadPrefs(); }
|
|
||||||
|
|
||||||
private final List<SingleQuery> history = new ArrayList<>();
|
|
||||||
|
|
||||||
public synchronized void add(SingleQuery r)
|
|
||||||
{
|
|
||||||
history.add(r);
|
|
||||||
while (history.size() > MAX_HISTORY_SIZE) history.remove(0);
|
|
||||||
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized List<SingleQuery> get()
|
|
||||||
{
|
|
||||||
List<SingleQuery> r = new ArrayList<>(history);
|
|
||||||
CollectionHelper.sort_inplace(r, (o1, o2) -> (-1) * o1.Timestamp.compareTo(o2.Timestamp));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void save()
|
|
||||||
{
|
|
||||||
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("QueryLog", Context.MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor e = sharedPref.edit();
|
|
||||||
|
|
||||||
e.clear();
|
|
||||||
|
|
||||||
e.putInt("history_count", history.size());
|
|
||||||
|
|
||||||
for (int i = 0; i < history.size(); i++) history.get(i).save(e, "message["+(i+1000)+"]");
|
|
||||||
|
|
||||||
e.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void reloadPrefs()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Context c = SCNApp.getContext();
|
|
||||||
SharedPreferences sharedPref = c.getSharedPreferences("QueryLog", Context.MODE_PRIVATE);
|
|
||||||
int count = sharedPref.getInt("history_count", 0);
|
|
||||||
for (int i=0; i < count; i++) history.add(SingleQuery.load(sharedPref, "message["+(i+1000)+"]"));
|
|
||||||
|
|
||||||
CollectionHelper.sort_inplace(history, (o1, o2) -> (-1) * o1.Timestamp.compareTo(o2.Timestamp));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.e("SC:QL:Load", e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,11 +6,11 @@ import android.content.SharedPreferences;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.android.billingclient.api.Purchase;
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple3;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
||||||
import com.blackforestbytes.simplecloudnotifier.service.IABService;
|
import com.blackforestbytes.simplecloudnotifier.service.IABService;
|
||||||
import com.google.firebase.installations.FirebaseInstallations;
|
import com.google.firebase.iid.FirebaseInstanceId;
|
||||||
|
|
||||||
public class SCNSettings
|
public class SCNSettings
|
||||||
{
|
{
|
||||||
@ -52,8 +52,7 @@ public class SCNSettings
|
|||||||
|
|
||||||
public boolean Enabled = true;
|
public boolean Enabled = true;
|
||||||
public int LocalCacheSize = 500;
|
public int LocalCacheSize = 500;
|
||||||
public boolean EnableDeleteSwipe = false;
|
public boolean EnableDeleteSwipe = true;
|
||||||
public int PreviewLineCount = 6;
|
|
||||||
|
|
||||||
public final NotificationSettings PriorityLow = new NotificationSettings(PriorityEnum.LOW);
|
public final NotificationSettings PriorityLow = new NotificationSettings(PriorityEnum.LOW);
|
||||||
public final NotificationSettings PriorityNorm = new NotificationSettings(PriorityEnum.NORMAL);
|
public final NotificationSettings PriorityNorm = new NotificationSettings(PriorityEnum.NORMAL);
|
||||||
@ -62,11 +61,6 @@ public class SCNSettings
|
|||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
public SCNSettings()
|
public SCNSettings()
|
||||||
{
|
|
||||||
reloadPrefs();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reloadPrefs()
|
|
||||||
{
|
{
|
||||||
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("Config", Context.MODE_PRIVATE);
|
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("Config", Context.MODE_PRIVATE);
|
||||||
|
|
||||||
@ -83,7 +77,6 @@ public class SCNSettings
|
|||||||
Enabled = sharedPref.getBoolean("app_enabled", Enabled);
|
Enabled = sharedPref.getBoolean("app_enabled", Enabled);
|
||||||
LocalCacheSize = sharedPref.getInt("local_cache_size", LocalCacheSize);
|
LocalCacheSize = sharedPref.getInt("local_cache_size", LocalCacheSize);
|
||||||
EnableDeleteSwipe = sharedPref.getBoolean("do_del_swipe", EnableDeleteSwipe);
|
EnableDeleteSwipe = sharedPref.getBoolean("do_del_swipe", EnableDeleteSwipe);
|
||||||
PreviewLineCount = sharedPref.getInt("preview_line_count", PreviewLineCount);
|
|
||||||
|
|
||||||
PriorityLow.EnableLED = sharedPref.getBoolean("priority_low:enabled_led", PriorityLow.EnableLED);
|
PriorityLow.EnableLED = sharedPref.getBoolean("priority_low:enabled_led", PriorityLow.EnableLED);
|
||||||
PriorityLow.EnableSound = sharedPref.getBoolean("priority_low:enabled_sound", PriorityLow.EnableSound);
|
PriorityLow.EnableSound = sharedPref.getBoolean("priority_low:enabled_sound", PriorityLow.EnableSound);
|
||||||
@ -127,14 +120,10 @@ public class SCNSettings
|
|||||||
e.putString( "user_key", user_key);
|
e.putString( "user_key", user_key);
|
||||||
e.putString( "fcm_token_local", fcm_token_local);
|
e.putString( "fcm_token_local", fcm_token_local);
|
||||||
e.putString( "fcm_token_server", fcm_token_server);
|
e.putString( "fcm_token_server", fcm_token_server);
|
||||||
e.putBoolean("promode_local", promode_local);
|
|
||||||
e.putBoolean("promode_server", promode_server);
|
|
||||||
e.putString( "promode_token", promode_token);
|
|
||||||
|
|
||||||
e.putBoolean("app_enabled", Enabled);
|
e.putBoolean("app_enabled", Enabled);
|
||||||
e.putInt( "local_cache_size", LocalCacheSize);
|
e.putInt( "local_cache_size", LocalCacheSize);
|
||||||
e.putBoolean("do_del_swipe", EnableDeleteSwipe);
|
e.putBoolean("do_del_swipe", EnableDeleteSwipe);
|
||||||
e.putInt( "preview_line_count", PreviewLineCount);
|
|
||||||
|
|
||||||
e.putBoolean("priority_low:enabled_led", PriorityLow.EnableLED);
|
e.putBoolean("priority_low:enabled_led", PriorityLow.EnableLED);
|
||||||
e.putBoolean("priority_low:enabled_sound", PriorityLow.EnableSound);
|
e.putBoolean("priority_low:enabled_sound", PriorityLow.EnableSound);
|
||||||
@ -182,13 +171,13 @@ public class SCNSettings
|
|||||||
return base + "index.php?preset_user_id="+user_id+"&preset_user_key="+user_key;
|
return base + "index.php?preset_user_id="+user_id+"&preset_user_key="+user_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setServerToken(String token, View loader, boolean force)
|
public void setServerToken(String token, View loader)
|
||||||
{
|
{
|
||||||
if (isConnected())
|
if (isConnected())
|
||||||
{
|
{
|
||||||
fcm_token_local = token;
|
fcm_token_local = token;
|
||||||
save();
|
save();
|
||||||
if (!fcm_token_local.equals(fcm_token_server) || force) ServerCommunication.updateFCMToken(user_id, user_key, fcm_token_local, loader);
|
if (!fcm_token_local.equals(fcm_token_server)) ServerCommunication.updateFCMToken(user_id, user_key, fcm_token_local, loader);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -200,12 +189,13 @@ public class SCNSettings
|
|||||||
}
|
}
|
||||||
|
|
||||||
// called at app start
|
// called at app start
|
||||||
public void work(Activity a, boolean force)
|
public void work(Activity a)
|
||||||
{
|
{
|
||||||
FirebaseInstallations.getInstance().getId().addOnSuccessListener(a, newToken ->
|
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(a, instanceIdResult ->
|
||||||
{
|
{
|
||||||
|
String newToken = instanceIdResult.getToken();
|
||||||
Log.d("FB::GetInstanceId", newToken);
|
Log.d("FB::GetInstanceId", newToken);
|
||||||
SCNSettings.inst().setServerToken(newToken, null, force);
|
SCNSettings.inst().setServerToken(newToken, null);
|
||||||
}).addOnCompleteListener(r ->
|
}).addOnCompleteListener(r ->
|
||||||
{
|
{
|
||||||
if (isConnected()) ServerCommunication.info(user_id, user_key, null);
|
if (isConnected()) ServerCommunication.info(user_id, user_key, null);
|
||||||
@ -231,15 +221,16 @@ public class SCNSettings
|
|||||||
|
|
||||||
if (promode_server != promode_local) updateProState(loader);
|
if (promode_server != promode_local) updateProState(loader);
|
||||||
|
|
||||||
if (!Str.equals(fcm_token_local, fcm_token_server)) work(a, false);
|
if (!Str.equals(fcm_token_local, fcm_token_server)) work(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// get token then register
|
// get token then register
|
||||||
FirebaseInstallations.getInstance().getId().addOnSuccessListener(a, newToken ->
|
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(a, instanceIdResult ->
|
||||||
{
|
{
|
||||||
|
String newToken = instanceIdResult.getToken();
|
||||||
Log.d("FB::GetInstanceId", newToken);
|
Log.d("FB::GetInstanceId", newToken);
|
||||||
SCNSettings.inst().setServerToken(newToken, loader, false); // does register in here
|
SCNSettings.inst().setServerToken(newToken, loader); // does register in here
|
||||||
}).addOnCompleteListener(r ->
|
}).addOnCompleteListener(r ->
|
||||||
{
|
{
|
||||||
if (isConnected()) ServerCommunication.info(user_id, user_key, null); // info again for safety
|
if (isConnected()) ServerCommunication.info(user_id, user_key, null); // info again for safety
|
||||||
@ -249,17 +240,14 @@ public class SCNSettings
|
|||||||
|
|
||||||
public void updateProState(View loader)
|
public void updateProState(View loader)
|
||||||
{
|
{
|
||||||
Tuple3<Boolean, Boolean, String> state = IABService.inst().getPurchaseCachedExtended(IABService.IAB_PRO_MODE);
|
Purchase purch = IABService.inst().getPurchaseCached(IABService.IAB_PRO_MODE);
|
||||||
if (!state.Item2) return; // not initialized
|
boolean promode_real = (purch != null);
|
||||||
|
|
||||||
boolean promode_real = state.Item1;
|
|
||||||
|
|
||||||
if (promode_real != promode_local || promode_real != promode_server)
|
if (promode_real != promode_local || promode_real != promode_server)
|
||||||
{
|
{
|
||||||
promode_local = promode_real;
|
promode_local = promode_real;
|
||||||
promode_token = promode_real ? state.Item3 : "";
|
|
||||||
save();
|
|
||||||
|
|
||||||
|
promode_token = promode_real ? purch.getPurchaseToken() : "";
|
||||||
updateProStateOnServer(loader);
|
updateProStateOnServer(loader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,12 @@ import android.util.Log;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||||
|
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple5;
|
||||||
|
import com.blackforestbytes.simplecloudnotifier.lib.lambda.Func1to0;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.lambda.Func5to0;
|
import com.blackforestbytes.simplecloudnotifier.lib.lambda.Func5to0;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
||||||
import com.blackforestbytes.simplecloudnotifier.service.FBMService;
|
import com.blackforestbytes.simplecloudnotifier.service.FBMService;
|
||||||
|
|
||||||
import org.joda.time.Instant;
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -47,20 +48,20 @@ public class ServerCommunication
|
|||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e)
|
public void onFailure(Call call, IOException e)
|
||||||
{
|
{
|
||||||
handleError("register", call, null, Str.Empty, true, e);
|
Log.e("SC:register", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
|
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response)
|
public void onResponse(Call call, Response response)
|
||||||
{
|
{
|
||||||
String r = Str.Empty;
|
|
||||||
try (ResponseBody responseBody = response.body())
|
try (ResponseBody responseBody = response.body())
|
||||||
{
|
{
|
||||||
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
|
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
String r = responseBody.string();
|
||||||
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||||
@ -68,7 +69,6 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
handleNonSuccess("register", call, response, r);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,12 +81,11 @@ public class ServerCommunication
|
|||||||
SCNSettings.inst().save();
|
SCNSettings.inst().save();
|
||||||
|
|
||||||
SCNApp.refreshAccountTab();
|
SCNApp.refreshAccountTab();
|
||||||
|
|
||||||
handleSuccess("register", call, response, r);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("register", call, response, r, false, e);
|
Log.e("SC:register", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -97,7 +96,8 @@ public class ServerCommunication
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("register", null, null, Str.Empty, false, e);
|
Log.e("SC:register", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ public class ServerCommunication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(BASE_URL + "update.php?user_id="+id+"&user_key="+key+"&fcm_token="+token)
|
.url(BASE_URL + "updateFCMToken.php?user_id="+id+"&user_key="+key+"&fcm_token="+token)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
client.newCall(request).enqueue(new Callback()
|
client.newCall(request).enqueue(new Callback()
|
||||||
@ -114,20 +114,20 @@ public class ServerCommunication
|
|||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e)
|
public void onFailure(Call call, IOException e)
|
||||||
{
|
{
|
||||||
handleError("update<1>", call, null, Str.Empty, true, e);
|
Log.e("SC:update_1", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
|
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response)
|
public void onResponse(Call call, Response response)
|
||||||
{
|
{
|
||||||
String r = Str.Empty;
|
|
||||||
try (ResponseBody responseBody = response.body())
|
try (ResponseBody responseBody = response.body())
|
||||||
{
|
{
|
||||||
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
|
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
String r = responseBody.string();
|
||||||
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||||
@ -135,7 +135,6 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
handleNonSuccess("update<1>", call, response, r);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,12 +147,10 @@ public class ServerCommunication
|
|||||||
SCNSettings.inst().save();
|
SCNSettings.inst().save();
|
||||||
|
|
||||||
SCNApp.refreshAccountTab();
|
SCNApp.refreshAccountTab();
|
||||||
|
|
||||||
handleSuccess("update<1>", call, response, r);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("update<1>", call, response, r, false, e);
|
Log.e("SC:update_1", e.toString());
|
||||||
SCNApp.showToast("Communication with server failed", 4000);
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -165,7 +162,8 @@ public class ServerCommunication
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("update<1>", null, null, Str.Empty, false, e);
|
Log.e("SC:update_1", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,35 +172,30 @@ public class ServerCommunication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(BASE_URL + "update.php?user_id=" + id + "&user_key=" + key)
|
.url(BASE_URL + "updateFCMToken.php?user_id=" + id + "&user_key=" + key)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
client.newCall(request).enqueue(new Callback() {
|
client.newCall(request).enqueue(new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e)
|
public void onFailure(Call call, IOException e) {
|
||||||
{
|
Log.e("SC:update_2", e.toString());
|
||||||
handleError("update<1>", call, null, Str.Empty, true, e);
|
|
||||||
SCNApp.showToast("Communication with server failed", 4000);
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response)
|
public void onResponse(Call call, Response response) {
|
||||||
{
|
try (ResponseBody responseBody = response.body()) {
|
||||||
String r = Str.Empty;
|
|
||||||
try (ResponseBody responseBody = response.body())
|
|
||||||
{
|
|
||||||
if (!response.isSuccessful())
|
if (!response.isSuccessful())
|
||||||
throw new IOException("Unexpected code " + response);
|
throw new IOException("Unexpected code " + response);
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
String r = responseBody.string();
|
||||||
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||||
|
|
||||||
if (!json_bool(json, "success")) {
|
if (!json_bool(json, "success")) {
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
handleNonSuccess("update<2>", call, response, r);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,16 +207,10 @@ public class ServerCommunication
|
|||||||
SCNSettings.inst().save();
|
SCNSettings.inst().save();
|
||||||
|
|
||||||
SCNApp.refreshAccountTab();
|
SCNApp.refreshAccountTab();
|
||||||
|
} catch (Exception e) {
|
||||||
handleSuccess("update<2>", call, response, r);
|
Log.e("SC:update_2", e.toString());
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
handleError("update<2>", call, response, r, false, e);
|
|
||||||
SCNApp.showToast("Communication with server failed", 4000);
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
} finally {
|
||||||
finally
|
|
||||||
{
|
|
||||||
SCNApp.runOnUiThread(() -> {
|
SCNApp.runOnUiThread(() -> {
|
||||||
if (loader != null) loader.setVisibility(View.GONE);
|
if (loader != null) loader.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
@ -233,7 +220,8 @@ public class ServerCommunication
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("update<2>", null, null, Str.Empty, false, e);
|
Log.e("SC:update_2", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,23 +236,21 @@ public class ServerCommunication
|
|||||||
client.newCall(request).enqueue(new Callback() {
|
client.newCall(request).enqueue(new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e) {
|
public void onFailure(Call call, IOException e) {
|
||||||
handleError("info", call, null, Str.Empty, true, e);
|
Log.e("SC:info", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
SCNApp.runOnUiThread(() -> {
|
SCNApp.runOnUiThread(() -> {
|
||||||
if (loader != null) loader.setVisibility(View.GONE);
|
if (loader != null) loader.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response)
|
public void onResponse(Call call, Response response) {
|
||||||
{
|
try (ResponseBody responseBody = response.body()) {
|
||||||
String r = Str.Empty;
|
|
||||||
try (ResponseBody responseBody = response.body())
|
|
||||||
{
|
|
||||||
if (!response.isSuccessful())
|
if (!response.isSuccessful())
|
||||||
throw new IOException("Unexpected code " + response);
|
throw new IOException("Unexpected code " + response);
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
String r = responseBody.string();
|
||||||
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||||
@ -272,7 +258,6 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
handleNonSuccess("info", call, response, r);
|
|
||||||
|
|
||||||
int errid = json.optInt("errid", 0);
|
int errid = json.optInt("errid", 0);
|
||||||
|
|
||||||
@ -305,23 +290,21 @@ public class ServerCommunication
|
|||||||
|
|
||||||
if (json_int(json, "unack_count")>0) ServerCommunication.requery(id, key, loader);
|
if (json_int(json, "unack_count")>0) ServerCommunication.requery(id, key, loader);
|
||||||
|
|
||||||
handleSuccess("info", call, response, r);
|
} catch (Exception e) {
|
||||||
}
|
Log.e("SC:info", e.toString());
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
handleError("info", call, response, r, false, e);
|
|
||||||
SCNApp.showToast("Communication with server failed", 4000);
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
} finally {
|
||||||
finally
|
SCNApp.runOnUiThread(() -> {
|
||||||
{
|
if (loader != null) loader.setVisibility(View.GONE);
|
||||||
SCNApp.runOnUiThread(() -> { if (loader != null) loader.setVisibility(View.GONE); });
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("info", null, null, Str.Empty, false, e);
|
Log.e("SC:info", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,23 +319,21 @@ public class ServerCommunication
|
|||||||
client.newCall(request).enqueue(new Callback() {
|
client.newCall(request).enqueue(new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e) {
|
public void onFailure(Call call, IOException e) {
|
||||||
handleError("requery", call, null, Str.Empty, true, e);
|
Log.e("SC:requery", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
SCNApp.runOnUiThread(() -> {
|
SCNApp.runOnUiThread(() -> {
|
||||||
if (loader != null) loader.setVisibility(View.GONE);
|
if (loader != null) loader.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response)
|
public void onResponse(Call call, Response response) {
|
||||||
{
|
try (ResponseBody responseBody = response.body()) {
|
||||||
String r = Str.Empty;
|
|
||||||
try (ResponseBody responseBody = response.body())
|
|
||||||
{
|
|
||||||
if (!response.isSuccessful())
|
if (!response.isSuccessful())
|
||||||
throw new IOException("Unexpected code " + response);
|
throw new IOException("Unexpected code " + response);
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
String r = responseBody.string();
|
||||||
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||||
@ -360,7 +341,6 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
handleNonSuccess("requery", call, response, r);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,15 +359,10 @@ public class ServerCommunication
|
|||||||
FBMService.recieveData(time, title, content, prio, scn_id, true);
|
FBMService.recieveData(time, title, content, prio, scn_id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSuccess("requery", call, response, r);
|
} catch (Exception e) {
|
||||||
}
|
Log.e("SC:info", e.toString());
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
handleError("requery", call, response, r, false, e);
|
|
||||||
SCNApp.showToast("Communication with server failed", 4000);
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
} finally {
|
||||||
finally
|
|
||||||
{
|
|
||||||
SCNApp.runOnUiThread(() -> {
|
SCNApp.runOnUiThread(() -> {
|
||||||
if (loader != null) loader.setVisibility(View.GONE);
|
if (loader != null) loader.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
@ -397,7 +372,8 @@ public class ServerCommunication
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("requery", null, null, Str.Empty, false, e);
|
Log.e("SC:requery", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,31 +387,27 @@ public class ServerCommunication
|
|||||||
.url(BASE_URL + "upgrade.php?user_id=" + id + "&user_key=" + key + "&pro=" + pro + "&pro_token=" + URLEncoder.encode(pro_token, "utf-8"))
|
.url(BASE_URL + "upgrade.php?user_id=" + id + "&user_key=" + key + "&pro=" + pro + "&pro_token=" + URLEncoder.encode(pro_token, "utf-8"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
client.newCall(request).enqueue(new Callback()
|
client.newCall(request).enqueue(new Callback() {
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e)
|
public void onFailure(Call call, IOException e) {
|
||||||
{
|
Log.e("SC:upgrade", e.toString());
|
||||||
handleError("upgrade", call, null, Str.Empty, true, e);
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response)
|
public void onResponse(Call call, Response response) {
|
||||||
{
|
try (ResponseBody responseBody = response.body()) {
|
||||||
String r = Str.Empty;
|
if (!response.isSuccessful())
|
||||||
try (ResponseBody responseBody = response.body())
|
throw new IOException("Unexpected code " + response);
|
||||||
{
|
|
||||||
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
|
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
String r = responseBody.string();
|
||||||
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||||
|
|
||||||
if (!json_bool(json, "success")) {
|
if (!json_bool(json, "success")) {
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
handleNonSuccess("upgrade", call, response, r);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,15 +418,10 @@ public class ServerCommunication
|
|||||||
SCNSettings.inst().save();
|
SCNSettings.inst().save();
|
||||||
|
|
||||||
SCNApp.refreshAccountTab();
|
SCNApp.refreshAccountTab();
|
||||||
|
} catch (Exception e) {
|
||||||
handleSuccess("upgrade", call, response, r);
|
Log.e("SC:upgrade", e.toString());
|
||||||
}
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
catch (Exception e)
|
} finally {
|
||||||
{
|
|
||||||
handleError("upgrade", call, response, r, false, e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
SCNApp.runOnUiThread(() -> { if (loader != null) loader.setVisibility(View.GONE); });
|
SCNApp.runOnUiThread(() -> { if (loader != null) loader.setVisibility(View.GONE); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -462,7 +429,8 @@ public class ServerCommunication
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("upgrade", null, null, Str.Empty, false, e);
|
e.printStackTrace();
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,47 +442,37 @@ public class ServerCommunication
|
|||||||
.url(BASE_URL + "ack.php?user_id=" + id + "&user_key=" + key + "&scn_msg_id=" + msg_scn_id)
|
.url(BASE_URL + "ack.php?user_id=" + id + "&user_key=" + key + "&scn_msg_id=" + msg_scn_id)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
client.newCall(request).enqueue(new Callback()
|
client.newCall(request).enqueue(new Callback() {
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e)
|
public void onFailure(Call call, IOException e) {
|
||||||
{
|
Log.e("SC:ack", e.toString());
|
||||||
handleError("ack", call, null, Str.Empty, true, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response)
|
public void onResponse(Call call, Response response)
|
||||||
{
|
{
|
||||||
String r = Str.Empty;
|
try (ResponseBody responseBody = response.body()) {
|
||||||
try (ResponseBody responseBody = response.body())
|
|
||||||
{
|
|
||||||
if (!response.isSuccessful())
|
if (!response.isSuccessful())
|
||||||
throw new IOException("Unexpected code " + response);
|
throw new IOException("Unexpected code " + response);
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
String r = responseBody.string();
|
||||||
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||||
|
|
||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success")) SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
{
|
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
|
||||||
handleNonSuccess("ack", call, response, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSuccess("ack", call, response, r);
|
} catch (Exception e) {
|
||||||
}
|
Log.e("SC:ack", e.toString());
|
||||||
catch (Exception e)
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
{
|
|
||||||
handleError("ack", call, response, r, false, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("ack", null, null, Str.Empty, false, e);
|
Log.e("SC:ack", e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,21 +487,21 @@ public class ServerCommunication
|
|||||||
client.newCall(request).enqueue(new Callback() {
|
client.newCall(request).enqueue(new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e) {
|
public void onFailure(Call call, IOException e) {
|
||||||
handleError("expand", call, null, Str.Empty, true, e);
|
Log.e("SC:expand", e.toString());
|
||||||
SCNApp.runOnUiThread(() -> { if (loader != null) loader.setVisibility(View.GONE); });
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
|
SCNApp.runOnUiThread(() -> {
|
||||||
|
if (loader != null) loader.setVisibility(View.GONE);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call call, Response response)
|
public void onResponse(Call call, Response response) {
|
||||||
{
|
try (ResponseBody responseBody = response.body()) {
|
||||||
String r = Str.Empty;
|
|
||||||
try (ResponseBody responseBody = response.body())
|
|
||||||
{
|
|
||||||
if (!response.isSuccessful())
|
if (!response.isSuccessful())
|
||||||
throw new IOException("Unexpected code " + response);
|
throw new IOException("Unexpected code " + response);
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
String r = responseBody.string();
|
||||||
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
Log.d("Server::Response", request.url().toString()+"\n"+r);
|
||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||||
@ -551,7 +509,6 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
handleNonSuccess("expand", call, response, r);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,22 +522,21 @@ public class ServerCommunication
|
|||||||
|
|
||||||
okResult.invoke(title, content, prio, time, scn_id);
|
okResult.invoke(title, content, prio, time, scn_id);
|
||||||
|
|
||||||
handleSuccess("expand", call, response, r);
|
} catch (Exception e) {
|
||||||
}
|
Log.e("SC:expand", e.toString());
|
||||||
catch (Exception e)
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
{
|
} finally {
|
||||||
handleError("expand", call, response, r, false, e);
|
SCNApp.runOnUiThread(() -> {
|
||||||
}
|
if (loader != null) loader.setVisibility(View.GONE);
|
||||||
finally
|
});
|
||||||
{
|
|
||||||
SCNApp.runOnUiThread(() -> { if (loader != null) loader.setVisibility(View.GONE); });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
handleError("expand", null, null, Str.Empty, false, e);
|
Log.e("SC:expand", e.toString());
|
||||||
|
SCNApp.showToast("Communication with server failed", 4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,79 +564,4 @@ public class ServerCommunication
|
|||||||
{
|
{
|
||||||
return o.getString(key);
|
return o.getString(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void handleSuccess(String source, Call call, Response resp, String respBody)
|
|
||||||
{
|
|
||||||
Log.d("SC:"+source, respBody);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Instant i = Instant.now();
|
|
||||||
String s = source;
|
|
||||||
String u = call.request().url().toString();
|
|
||||||
int rc = resp.code();
|
|
||||||
String r = respBody;
|
|
||||||
LogLevel l = LogLevel.INFO;
|
|
||||||
|
|
||||||
SingleQuery q = new SingleQuery(l, i, s, u, r, rc, "SUCCESS");
|
|
||||||
QueryLog.inst().add(q);
|
|
||||||
}
|
|
||||||
catch (Exception e2)
|
|
||||||
{
|
|
||||||
Log.e("SC:HandleSuccess", e2.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void handleNonSuccess(String source, Call call, Response resp, String respBody)
|
|
||||||
{
|
|
||||||
Log.d("SC:"+source, respBody);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Instant i = Instant.now();
|
|
||||||
String s = source;
|
|
||||||
String u = call.request().url().toString();
|
|
||||||
int rc = resp.code();
|
|
||||||
String r = respBody;
|
|
||||||
LogLevel l = LogLevel.WARN;
|
|
||||||
|
|
||||||
SingleQuery q = new SingleQuery(l, i, s, u, r, rc, "NON-SUCCESS");
|
|
||||||
QueryLog.inst().add(q);
|
|
||||||
}
|
|
||||||
catch (Exception e2)
|
|
||||||
{
|
|
||||||
Log.e("SC:HandleSuccess", e2.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void handleError(String source, Call call, Response resp, String respBody, boolean isio, Exception e)
|
|
||||||
{
|
|
||||||
Log.e("SC:"+source, e.toString());
|
|
||||||
|
|
||||||
if (isio)
|
|
||||||
{
|
|
||||||
SCNApp.showToast("Can't connect to server", 3000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SCNApp.showToast("Communication with server failed", 4000);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Instant i = Instant.now();
|
|
||||||
String s = source;
|
|
||||||
String u = (call==null)?Str.Empty:call.request().url().toString();
|
|
||||||
int rc = (resp==null)?-1:resp.code();
|
|
||||||
String r = respBody;
|
|
||||||
LogLevel l = isio?LogLevel.WARN:LogLevel.ERROR;
|
|
||||||
|
|
||||||
SingleQuery q = new SingleQuery(l, i, s, u, r, rc, e.toString());
|
|
||||||
QueryLog.inst().add(q);
|
|
||||||
}
|
|
||||||
catch (Exception e2)
|
|
||||||
{
|
|
||||||
Log.e("SC:HandleError", e2.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.model;
|
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.BaseBundle;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
|
||||||
|
|
||||||
import org.joda.time.Instant;
|
|
||||||
|
|
||||||
public class SingleQuery
|
|
||||||
{
|
|
||||||
public final Instant Timestamp;
|
|
||||||
|
|
||||||
public final LogLevel Level;
|
|
||||||
public final String Name;
|
|
||||||
public final String URL;
|
|
||||||
public final String Response;
|
|
||||||
public final int ResponseCode;
|
|
||||||
public final String ExceptionString;
|
|
||||||
|
|
||||||
public SingleQuery(LogLevel l, Instant i, String n, String u, String r, int rc, String e)
|
|
||||||
{
|
|
||||||
Level=l;
|
|
||||||
Timestamp=i;
|
|
||||||
Name=n;
|
|
||||||
URL=u;
|
|
||||||
Response=r;
|
|
||||||
ResponseCode=rc;
|
|
||||||
ExceptionString=e;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(SharedPreferences.Editor e, String base)
|
|
||||||
{
|
|
||||||
e.putInt(base+".Level", Level.asInt());
|
|
||||||
e.putLong(base+".Timestamp", Timestamp.getMillis());
|
|
||||||
e.putString(base+".Name", Name);
|
|
||||||
e.putString(base+".URL", URL);
|
|
||||||
e.putString(base+".Response", Response);
|
|
||||||
e.putInt(base+".ResponseCode", ResponseCode);
|
|
||||||
e.putString(base+".ExceptionString", ExceptionString);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(BaseBundle e, String base)
|
|
||||||
{
|
|
||||||
e.putInt(base+".Level", Level.asInt());
|
|
||||||
e.putLong(base+".Timestamp", Timestamp.getMillis());
|
|
||||||
e.putString(base+".Name", Name);
|
|
||||||
e.putString(base+".URL", URL);
|
|
||||||
e.putString(base+".Response", Response);
|
|
||||||
e.putInt(base+".ResponseCode", ResponseCode);
|
|
||||||
e.putString(base+".ExceptionString", ExceptionString);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SingleQuery load(SharedPreferences e, String base)
|
|
||||||
{
|
|
||||||
return new SingleQuery
|
|
||||||
(
|
|
||||||
LogLevel.fromInt(e.getInt(base+".Level", 0)),
|
|
||||||
new Instant(e.getLong(base+".Timestamp", 0)),
|
|
||||||
e.getString(base+".Name", Str.Empty),
|
|
||||||
e.getString(base+".URL", Str.Empty),
|
|
||||||
e.getString(base+".Response", Str.Empty),
|
|
||||||
e.getInt(base+".ResponseCode", -1),
|
|
||||||
e.getString(base+".ExceptionString", Str.Empty)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SingleQuery load(BaseBundle e, String base)
|
|
||||||
{
|
|
||||||
return new SingleQuery
|
|
||||||
(
|
|
||||||
LogLevel.fromInt(e.getInt(base+".Level", 0)),
|
|
||||||
new Instant(e.getLong(base+".Timestamp", 0)),
|
|
||||||
e.getString(base+".Name", Str.Empty),
|
|
||||||
e.getString(base+".URL", Str.Empty),
|
|
||||||
e.getString(base+".Response", Str.Empty),
|
|
||||||
e.getInt(base+".ResponseCode", -1),
|
|
||||||
e.getString(base+".ExceptionString", Str.Empty)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,21 +4,16 @@ import android.util.Log;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple4;
|
||||||
|
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple5;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.CMessage;
|
import com.blackforestbytes.simplecloudnotifier.model.CMessage;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.LogLevel;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.PriorityEnum;
|
import com.blackforestbytes.simplecloudnotifier.model.PriorityEnum;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.QueryLog;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication;
|
import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SingleQuery;
|
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||||
import com.google.firebase.messaging.RemoteMessage;
|
import com.google.firebase.messaging.RemoteMessage;
|
||||||
|
|
||||||
import org.joda.time.Instant;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
public class FBMService extends FirebaseMessagingService
|
public class FBMService extends FirebaseMessagingService
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@ -47,10 +42,6 @@ public class FBMService extends FirebaseMessagingService
|
|||||||
long scn_id = Long.parseLong(remoteMessage.getData().get("scn_msg_id"));
|
long scn_id = Long.parseLong(remoteMessage.getData().get("scn_msg_id"));
|
||||||
boolean trimmed = Boolean.parseBoolean(remoteMessage.getData().get("trimmed"));
|
boolean trimmed = Boolean.parseBoolean(remoteMessage.getData().get("trimmed"));
|
||||||
|
|
||||||
|
|
||||||
SingleQuery q = new SingleQuery(LogLevel.INFO, Instant.now(), "FBM<recieve>", Str.Empty, new JSONObject(remoteMessage.getData()).toString(), 0, "SUCCESS");
|
|
||||||
QueryLog.inst().add(q);
|
|
||||||
|
|
||||||
if (trimmed)
|
if (trimmed)
|
||||||
{
|
{
|
||||||
ServerCommunication.expand(SCNSettings.inst().user_id, SCNSettings.inst().user_key, scn_id, null, (i1, i2, i3, i4, i5) -> recieveData(i4, i1, i2, i3, i5, false));
|
ServerCommunication.expand(SCNSettings.inst().user_id, SCNSettings.inst().user_key, scn_id, null, (i1, i2, i3, i4, i5) -> recieveData(i4, i1, i2, i3, i5, false));
|
||||||
|
@ -2,37 +2,23 @@ package com.blackforestbytes.simplecloudnotifier.service;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.billingclient.api.BillingClient;
|
import com.android.billingclient.api.BillingClient;
|
||||||
import com.android.billingclient.api.BillingClientStateListener;
|
import com.android.billingclient.api.BillingClientStateListener;
|
||||||
import com.android.billingclient.api.BillingFlowParams;
|
import com.android.billingclient.api.BillingFlowParams;
|
||||||
import com.android.billingclient.api.BillingResult;
|
|
||||||
import com.android.billingclient.api.Purchase;
|
import com.android.billingclient.api.Purchase;
|
||||||
import com.android.billingclient.api.PurchasesUpdatedListener;
|
import com.android.billingclient.api.PurchasesUpdatedListener;
|
||||||
import com.android.billingclient.api.SkuDetails;
|
|
||||||
import com.android.billingclient.api.SkuDetailsParams;
|
|
||||||
import com.android.billingclient.api.SkuDetailsResponseListener;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple2;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple3;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.lambda.Func0to0;
|
import com.blackforestbytes.simplecloudnotifier.lib.lambda.Func0to0;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
||||||
import com.blackforestbytes.simplecloudnotifier.view.MainActivity;
|
import com.blackforestbytes.simplecloudnotifier.view.MainActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Dictionary;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import static androidx.constraintlayout.widget.Constraints.TAG;
|
import static androidx.constraintlayout.widget.Constraints.TAG;
|
||||||
@ -59,72 +45,18 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SimplePurchaseState { YES, NO, UNINITIALIZED }
|
|
||||||
|
|
||||||
private BillingClient client;
|
private BillingClient client;
|
||||||
private boolean isServiceConnected;
|
private boolean isServiceConnected;
|
||||||
private final List<Purchase> purchases = new ArrayList<>();
|
private final List<Purchase> purchases = new ArrayList<>();
|
||||||
private boolean _isInitialized = false;
|
|
||||||
|
|
||||||
private final Map<String, Boolean> _localCache= new HashMap<>();
|
|
||||||
|
|
||||||
public IABService(Context c)
|
public IABService(Context c)
|
||||||
{
|
{
|
||||||
_isInitialized = false;
|
|
||||||
|
|
||||||
loadCache();
|
|
||||||
|
|
||||||
client = BillingClient
|
client = BillingClient
|
||||||
.newBuilder(c)
|
.newBuilder(c)
|
||||||
.setListener(this)
|
.setListener(this)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
startServiceConnection(this::queryPurchases, false);
|
startServiceConnection(this::queryPurchases, false);
|
||||||
startServiceConnection(this::querySkuDetails, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reloadPrefs()
|
|
||||||
{
|
|
||||||
loadCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadCache()
|
|
||||||
{
|
|
||||||
_localCache.clear();
|
|
||||||
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("IAB", Context.MODE_PRIVATE);
|
|
||||||
int count = sharedPref.getInt("c", 0);
|
|
||||||
for (int i=0; i < count; i++)
|
|
||||||
{
|
|
||||||
String k = sharedPref.getString("["+i+"]->key", null);
|
|
||||||
boolean v = sharedPref.getBoolean("["+i+"]->value", false);
|
|
||||||
if (k==null)continue;
|
|
||||||
_localCache.put(k, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveCache()
|
|
||||||
{
|
|
||||||
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("IAB", Context.MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor= sharedPref.edit();
|
|
||||||
|
|
||||||
editor.putInt("c", _localCache.size());
|
|
||||||
int i = 0;
|
|
||||||
for (Map.Entry<String, Boolean> e : _localCache.entrySet())
|
|
||||||
{
|
|
||||||
editor.putString("["+i+"]->key", e.getKey());
|
|
||||||
editor.putBoolean("["+i+"]->value", e.getValue());
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
private synchronized void updateCache(String k, boolean v)
|
|
||||||
{
|
|
||||||
if (_localCache.containsKey(k) && _localCache.get(k)==v) return;
|
|
||||||
|
|
||||||
_localCache.put(k, v);
|
|
||||||
saveCache();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void queryPurchases()
|
public void queryPurchases()
|
||||||
@ -135,16 +67,14 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
Purchase.PurchasesResult purchasesResult = client.queryPurchases(BillingClient.SkuType.INAPP);
|
Purchase.PurchasesResult purchasesResult = client.queryPurchases(BillingClient.SkuType.INAPP);
|
||||||
Log.i(TAG, "Querying purchases elapsed time: " + (System.currentTimeMillis() - time) + "ms");
|
Log.i(TAG, "Querying purchases elapsed time: " + (System.currentTimeMillis() - time) + "ms");
|
||||||
|
|
||||||
if (purchasesResult.getResponseCode() == BillingClient.BillingResponseCode.OK)
|
if (purchasesResult.getResponseCode() == BillingClient.BillingResponse.OK)
|
||||||
{
|
{
|
||||||
for (Purchase p : Objects.requireNonNull(purchasesResult.getPurchasesList()))
|
for (Purchase p : purchasesResult.getPurchasesList())
|
||||||
{
|
{
|
||||||
handlePurchase(p, false);
|
handlePurchase(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
_isInitialized = true;
|
boolean newProMode = getPurchaseCached(IAB_PRO_MODE) != null;
|
||||||
|
|
||||||
boolean newProMode = getPurchaseCachedSimple(IAB_PRO_MODE);
|
|
||||||
if (newProMode != SCNSettings.inst().promode_local)
|
if (newProMode != SCNSettings.inst().promode_local)
|
||||||
{
|
{
|
||||||
refreshProModeListener();
|
refreshProModeListener();
|
||||||
@ -159,39 +89,20 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
executeServiceRequest(queryToExecute, false);
|
executeServiceRequest(queryToExecute, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void querySkuDetails() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void purchase(Activity a, String id)
|
public void purchase(Activity a, String id)
|
||||||
{
|
{
|
||||||
Func0to0 queryRequest = () -> {
|
executeServiceRequest(() ->
|
||||||
// Query the purchase async
|
{
|
||||||
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
|
BillingFlowParams flowParams = BillingFlowParams
|
||||||
params.setSkusList(Collections.singletonList(id)).setType(BillingClient.SkuType.INAPP);
|
.newBuilder()
|
||||||
client.querySkuDetailsAsync(params.build(), (billingResult, skuDetailsList) ->
|
.setSku(id)
|
||||||
{
|
.setType(BillingClient.SkuType.INAPP) // SkuType.SUB for subscription
|
||||||
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK || skuDetailsList == null || skuDetailsList.size() != 1)
|
.build();
|
||||||
{
|
client.launchBillingFlow(a, flowParams);
|
||||||
SCNApp.showToast("Could not find product", Toast.LENGTH_SHORT);
|
}, true);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
executeServiceRequest(() ->
|
|
||||||
{
|
|
||||||
BillingFlowParams flowParams = BillingFlowParams
|
|
||||||
.newBuilder()
|
|
||||||
.setSkuDetails(skuDetailsList.get(0))
|
|
||||||
.build();
|
|
||||||
client.launchBillingFlow(a, flowParams);
|
|
||||||
}, true);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
executeServiceRequest(queryRequest, false);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeServiceRequest(Func0to0 runnable, final boolean userRequest)
|
private void executeServiceRequest(Func0to0 runnable, final boolean userRequest) {
|
||||||
{
|
|
||||||
if (isServiceConnected)
|
if (isServiceConnected)
|
||||||
{
|
{
|
||||||
runnable.invoke();
|
runnable.invoke();
|
||||||
@ -213,37 +124,34 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases)
|
public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases)
|
||||||
{
|
{
|
||||||
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null)
|
if (responseCode == BillingClient.BillingResponse.OK && purchases != null)
|
||||||
{
|
{
|
||||||
for (Purchase purchase : purchases)
|
for (Purchase purchase : purchases)
|
||||||
{
|
{
|
||||||
handlePurchase(purchase, true);
|
handlePurchase(purchase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED && purchases != null)
|
else if (responseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED && purchases != null)
|
||||||
{
|
{
|
||||||
for (Purchase purchase : purchases)
|
for (Purchase purchase : purchases)
|
||||||
{
|
{
|
||||||
handlePurchase(purchase, true);
|
handlePurchase(purchase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handlePurchase(Purchase purchase, boolean triggerUpdate)
|
private void handlePurchase(Purchase purchase)
|
||||||
{
|
{
|
||||||
Log.d(TAG, "Got a verified purchase: " + purchase);
|
Log.d(TAG, "Got a verified purchase: " + purchase);
|
||||||
|
|
||||||
purchases.add(purchase);
|
purchases.add(purchase);
|
||||||
|
|
||||||
if (triggerUpdate) refreshProModeListener();
|
refreshProModeListener();
|
||||||
|
|
||||||
updateCache(purchase.getSku(), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshProModeListener()
|
private void refreshProModeListener() {
|
||||||
{
|
|
||||||
MainActivity ma = SCNApp.getMainActivity();
|
MainActivity ma = SCNApp.getMainActivity();
|
||||||
if (ma != null) ma.adpTabs.tab3.updateProState();
|
if (ma != null) ma.adpTabs.tab3.updateProState();
|
||||||
if (ma != null) ma.adpTabs.tab1.updateProState();
|
if (ma != null) ma.adpTabs.tab1.updateProState();
|
||||||
@ -255,9 +163,9 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
client.startConnection(new BillingClientStateListener()
|
client.startConnection(new BillingClientStateListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onBillingSetupFinished(@NonNull BillingResult billingResult)
|
public void onBillingSetupFinished(@BillingClient.BillingResponse int billingResponseCode)
|
||||||
{
|
{
|
||||||
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK)
|
if (billingResponseCode == BillingClient.BillingResponse.OK)
|
||||||
{
|
{
|
||||||
isServiceConnected = true;
|
isServiceConnected = true;
|
||||||
if (executeOnSuccess != null) executeOnSuccess.invoke();
|
if (executeOnSuccess != null) executeOnSuccess.invoke();
|
||||||
@ -275,31 +183,13 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getPurchaseCachedSimple(String id)
|
public Purchase getPurchaseCached(String id)
|
||||||
{
|
{
|
||||||
return getPurchaseCachedExtended(id).Item1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
public Tuple3<Boolean, Boolean, String> getPurchaseCachedExtended(String id)
|
|
||||||
{
|
|
||||||
// <state, initialized, token>
|
|
||||||
|
|
||||||
if (!_isInitialized)
|
|
||||||
{
|
|
||||||
if (_localCache.containsKey(id) && _localCache.get(id)) return new Tuple3<>(true, false, Str.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Purchase p : purchases)
|
for (Purchase p : purchases)
|
||||||
{
|
{
|
||||||
if (Str.equals(p.getSku(), id))
|
if (Str.equals(p.getSku(), id)) return p;
|
||||||
{
|
|
||||||
updateCache(id, true);
|
|
||||||
return new Tuple3<>(true, true, p.getPurchaseToken());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCache(id, false);
|
return null;
|
||||||
return new Tuple3<>(false, true, Str.Empty);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,7 @@ public class NotificationService
|
|||||||
channel0.setDescription("Push notifications from the server with low priority.\nGo to the in-app settings to configure ringtone, volume and vibrations");
|
channel0.setDescription("Push notifications from the server with low priority.\nGo to the in-app settings to configure ringtone, volume and vibrations");
|
||||||
channel0.setSound(null, null);
|
channel0.setSound(null, null);
|
||||||
channel0.setVibrationPattern(null);
|
channel0.setVibrationPattern(null);
|
||||||
channel0.setLightColor(Color.CYAN);
|
channel0.setLightColor(Color.BLUE);
|
||||||
channel0.enableLights(true);
|
|
||||||
notifman.createNotificationChannel(channel0);
|
notifman.createNotificationChannel(channel0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,8 +77,7 @@ public class NotificationService
|
|||||||
channel1.setDescription("Push notifications from the server with low priority.\nGo to the in-app settings to configure ringtone, volume and vibrations");
|
channel1.setDescription("Push notifications from the server with low priority.\nGo to the in-app settings to configure ringtone, volume and vibrations");
|
||||||
channel1.setSound(null, null);
|
channel1.setSound(null, null);
|
||||||
channel1.setVibrationPattern(null);
|
channel1.setVibrationPattern(null);
|
||||||
channel1.setLightColor(Color.CYAN);
|
channel1.setLightColor(Color.BLUE);
|
||||||
channel1.enableLights(true);
|
|
||||||
notifman.createNotificationChannel(channel1);
|
notifman.createNotificationChannel(channel1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,9 +89,7 @@ public class NotificationService
|
|||||||
channel2.setDescription("Push notifications from the server with low priority.\nGo to the in-app settings to configure ringtone, volume and vibrations");
|
channel2.setDescription("Push notifications from the server with low priority.\nGo to the in-app settings to configure ringtone, volume and vibrations");
|
||||||
channel2.setSound(null, null);
|
channel2.setSound(null, null);
|
||||||
channel2.setVibrationPattern(null);
|
channel2.setVibrationPattern(null);
|
||||||
channel2.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
channel2.setLightColor(Color.BLUE);
|
||||||
channel2.setLightColor(Color.CYAN);
|
|
||||||
channel2.enableLights(true);
|
|
||||||
notifman.createNotificationChannel(channel2);
|
notifman.createNotificationChannel(channel2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,9 +115,9 @@ public class NotificationService
|
|||||||
{
|
{
|
||||||
Vibrator v = (Vibrator) SCNApp.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
Vibrator v = (Vibrator) SCNApp.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
|
v.vibrate(VibrationEffect.createOneShot(1500, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||||
} else {
|
} else {
|
||||||
v.vibrate(500);
|
v.vibrate(1500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,10 +225,10 @@ public class NotificationService
|
|||||||
if (msg.Priority == PriorityEnum.NORMAL) mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
if (msg.Priority == PriorityEnum.NORMAL) mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
||||||
if (msg.Priority == PriorityEnum.HIGH) mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
if (msg.Priority == PriorityEnum.HIGH) mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||||
|
|
||||||
Intent intent = new Intent(ctxt, MainActivity.class);
|
Intent intnt_click = new Intent(SCNApp.getContext(), BroadcastReceiverService.class);
|
||||||
PendingIntent pi = PendingIntent.getActivity(ctxt, 0, intent, 0);
|
intnt_click.putExtra(BroadcastReceiverService.ID_KEY, BroadcastReceiverService.NOTIF_SHOW_MAIN);
|
||||||
|
PendingIntent pi = PendingIntent.getBroadcast(ctxt, 0, intnt_click, 0);
|
||||||
mBuilder.setContentIntent(pi);
|
mBuilder.setContentIntent(pi);
|
||||||
|
|
||||||
NotificationManager mNotificationManager = (NotificationManager) ctxt.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager mNotificationManager = (NotificationManager) ctxt.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
if (mNotificationManager == null) return;
|
if (mNotificationManager == null) return;
|
||||||
|
|
||||||
@ -258,7 +254,7 @@ public class NotificationService
|
|||||||
if (ns.EnableVibration)
|
if (ns.EnableVibration)
|
||||||
{
|
{
|
||||||
Vibrator v = (Vibrator) SCNApp.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
Vibrator v = (Vibrator) SCNApp.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||||
v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
|
v.vibrate(VibrationEffect.createOneShot(1500, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (ns.EnableLED) { } // no LED in Android-O -- configure via Channel
|
//if (ns.EnableLED) { } // no LED in Android-O -- configure via Channel
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.util;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.widget.ScrollView;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
|
||||||
|
|
||||||
public class MaxHeightScrollView extends ScrollView
|
|
||||||
{
|
|
||||||
public int maxHeight = Integer.MAX_VALUE;//dp
|
|
||||||
|
|
||||||
public MaxHeightScrollView(Context context)
|
|
||||||
{
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MaxHeightScrollView(Context context, AttributeSet attrs)
|
|
||||||
{
|
|
||||||
super(context, attrs);
|
|
||||||
|
|
||||||
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView, 0, 0);
|
|
||||||
try {
|
|
||||||
maxHeight = a.getInteger(R.styleable.MaxHeightScrollView_maxHeightOverride, Integer.MAX_VALUE);
|
|
||||||
} finally {
|
|
||||||
a.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr)
|
|
||||||
{
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
|
|
||||||
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView, 0, 0);
|
|
||||||
try {
|
|
||||||
maxHeight = a.getInteger(R.styleable.MaxHeightScrollView_maxHeightOverride, Integer.MAX_VALUE);
|
|
||||||
} finally {
|
|
||||||
a.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
|
||||||
{
|
|
||||||
heightMeasureSpec = MeasureSpec.makeMeasureSpec(dpToPx(getResources(), maxHeight), MeasureSpec.AT_MOST);
|
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int dpToPx(Resources res, int dp)
|
|
||||||
{
|
|
||||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.util;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
|
|
||||||
public abstract class TextChangedListener<T> implements TextWatcher {
|
|
||||||
private T target;
|
|
||||||
|
|
||||||
public TextChangedListener(T target) {
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
this.onTextChanged(target, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void onTextChanged(T target, Editable s);
|
|
||||||
}
|
|
@ -1,23 +1,14 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.view;
|
package com.blackforestbytes.simplecloudnotifier.view;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
import com.blackforestbytes.simplecloudnotifier.R;
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.QueryLog;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
||||||
import com.blackforestbytes.simplecloudnotifier.service.IABService;
|
import com.blackforestbytes.simplecloudnotifier.service.IABService;
|
||||||
import com.blackforestbytes.simplecloudnotifier.service.NotificationService;
|
import com.blackforestbytes.simplecloudnotifier.service.NotificationService;
|
||||||
import com.blackforestbytes.simplecloudnotifier.view.debug.QueryLogActivity;
|
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
@ -25,12 +16,6 @@ import androidx.appcompat.widget.Toolbar;
|
|||||||
import androidx.viewpager.widget.PagerAdapter;
|
import androidx.viewpager.widget.PagerAdapter;
|
||||||
import androidx.viewpager.widget.ViewPager;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.ObjectInputStream;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity
|
public class MainActivity extends AppCompatActivity
|
||||||
{
|
{
|
||||||
public TabAdapter adpTabs;
|
public TabAdapter adpTabs;
|
||||||
@ -39,8 +24,6 @@ public class MainActivity extends AppCompatActivity
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
QueryLog.inst();
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
@ -50,7 +33,6 @@ public class MainActivity extends AppCompatActivity
|
|||||||
layoutRoot = findViewById(R.id.layoutRoot);
|
layoutRoot = findViewById(R.id.layoutRoot);
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
toolbar.setOnClickListener(this::onToolbackClicked);
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
ViewPager viewPager = findViewById(R.id.pager);
|
ViewPager viewPager = findViewById(R.id.pager);
|
||||||
@ -79,7 +61,7 @@ public class MainActivity extends AppCompatActivity
|
|||||||
|
|
||||||
SCNApp.register(this);
|
SCNApp.register(this);
|
||||||
IABService.startup(this);
|
IABService.startup(this);
|
||||||
SCNSettings.inst().work(this, true);
|
SCNSettings.inst().work(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -99,126 +81,4 @@ public class MainActivity extends AppCompatActivity
|
|||||||
CMessageList.inst().fullSave();
|
CMessageList.inst().fullSave();
|
||||||
IABService.inst().destroy();
|
IABService.inst().destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int clickCount = 0;
|
|
||||||
private long lastClick = 0;
|
|
||||||
private void onToolbackClicked(View v)
|
|
||||||
{
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
if (now - lastClick > 200) clickCount=0;
|
|
||||||
clickCount++;
|
|
||||||
lastClick = now;
|
|
||||||
|
|
||||||
if (clickCount == 4) startActivity(new Intent(this, QueryLogActivity.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
if(requestCode == 1991 && resultCode == RESULT_OK)
|
|
||||||
{
|
|
||||||
Uri uri = data.getData(); //The uri with the location of the file
|
|
||||||
|
|
||||||
Context ctxt = this;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ObjectInputStream stream = new ObjectInputStream(getContentResolver().openInputStream(uri));
|
|
||||||
|
|
||||||
Map<String, ?> d1 = (Map<String, ?>)stream.readObject();
|
|
||||||
Map<String, ?> d2 = (Map<String, ?>)stream.readObject();
|
|
||||||
Map<String, ?> d3 = (Map<String, ?>)stream.readObject();
|
|
||||||
Map<String, ?> d4 = (Map<String, ?>)stream.readObject();
|
|
||||||
|
|
||||||
stream.close();
|
|
||||||
|
|
||||||
runOnUiThread(() ->
|
|
||||||
{
|
|
||||||
|
|
||||||
SharedPreferences.Editor e1 = ctxt.getSharedPreferences("Config", Context.MODE_PRIVATE).edit();
|
|
||||||
SharedPreferences.Editor e2 = ctxt.getSharedPreferences("IAB", Context.MODE_PRIVATE).edit();
|
|
||||||
SharedPreferences.Editor e3 = ctxt.getSharedPreferences("CMessageList", Context.MODE_PRIVATE).edit();
|
|
||||||
SharedPreferences.Editor e4 = ctxt.getSharedPreferences("QueryLog", Context.MODE_PRIVATE).edit();
|
|
||||||
|
|
||||||
e1.clear();
|
|
||||||
for (Map.Entry<String, ?> entry : d1.entrySet())
|
|
||||||
{
|
|
||||||
if (entry.getValue() instanceof String) e1.putString(entry.getKey(), (String)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Boolean) e1.putBoolean(entry.getKey(), (Boolean)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Float) e1.putFloat(entry.getKey(), (Float)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Integer) e1.putInt(entry.getKey(), (Integer)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Long) e1.putLong(entry.getKey(), (Long)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Set<?>) e1.putStringSet(entry.getKey(), (Set<String>)entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
e2.clear();
|
|
||||||
for (Map.Entry<String, ?> entry : d2.entrySet())
|
|
||||||
{
|
|
||||||
if (entry.getValue() instanceof String) e2.putString(entry.getKey(), (String)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Boolean) e2.putBoolean(entry.getKey(), (Boolean)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Float) e2.putFloat(entry.getKey(), (Float)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Integer) e2.putInt(entry.getKey(), (Integer)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Long) e2.putLong(entry.getKey(), (Long)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Set<?>) e2.putStringSet(entry.getKey(), (Set<String>)entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
e2.clear();
|
|
||||||
for (Map.Entry<String, ?> entry : d3.entrySet())
|
|
||||||
{
|
|
||||||
if (entry.getValue() instanceof String) e3.putString(entry.getKey(), (String)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Boolean) e3.putBoolean(entry.getKey(), (Boolean)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Float) e3.putFloat(entry.getKey(), (Float)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Integer) e3.putInt(entry.getKey(), (Integer)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Long) e3.putLong(entry.getKey(), (Long)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Set<?>) e3.putStringSet(entry.getKey(), (Set<String>)entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
e4.clear();
|
|
||||||
for (Map.Entry<String, ?> entry : d4.entrySet())
|
|
||||||
{
|
|
||||||
if (entry.getValue() instanceof String) e4.putString(entry.getKey(), (String)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Boolean) e4.putBoolean(entry.getKey(), (Boolean)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Float) e4.putFloat(entry.getKey(), (Float)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Integer) e4.putInt(entry.getKey(), (Integer)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Long) e4.putLong(entry.getKey(), (Long)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Set<?>) e4.putStringSet(entry.getKey(), (Set<String>)entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
e1.apply();
|
|
||||||
e2.apply();
|
|
||||||
e3.apply();
|
|
||||||
e4.apply();
|
|
||||||
|
|
||||||
|
|
||||||
SCNSettings.inst().reloadPrefs();
|
|
||||||
IABService.inst().reloadPrefs();
|
|
||||||
CMessageList.inst().reloadPrefs();
|
|
||||||
QueryLog.inst().reloadPrefs();
|
|
||||||
|
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
|
||||||
setSupportActionBar(toolbar);
|
|
||||||
|
|
||||||
ViewPager viewPager = findViewById(R.id.pager);
|
|
||||||
PagerAdapter adapter = adpTabs = new TabAdapter(getSupportFragmentManager());
|
|
||||||
viewPager.setAdapter(adapter);
|
|
||||||
|
|
||||||
TabLayout tabLayout = findViewById(R.id.tab_layout);
|
|
||||||
tabLayout.setupWithViewPager(viewPager);
|
|
||||||
|
|
||||||
|
|
||||||
SCNSettings.inst().work(this, true);
|
|
||||||
|
|
||||||
SCNApp.showToast("Backup imported", Toast.LENGTH_LONG);
|
|
||||||
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.e("Import:Err", e.toString());
|
|
||||||
SCNApp.showToast("Import failed", Toast.LENGTH_LONG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.view;
|
package com.blackforestbytes.simplecloudnotifier.view;
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -10,11 +9,8 @@ import android.widget.RelativeLayout;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
import com.blackforestbytes.simplecloudnotifier.R;
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.CMessage;
|
import com.blackforestbytes.simplecloudnotifier.model.CMessage;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
|
||||||
import com.google.android.material.button.MaterialButton;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -57,7 +53,7 @@ public class MessageAdapter extends RecyclerView.Adapter
|
|||||||
{
|
{
|
||||||
CMessage msg = CMessageList.inst().tryGetFromBack(position);
|
CMessage msg = CMessageList.inst().tryGetFromBack(position);
|
||||||
MessagePresenter view = (MessagePresenter) holder;
|
MessagePresenter view = (MessagePresenter) holder;
|
||||||
view.setMessage(msg, position);
|
view.setMessage(msg);
|
||||||
|
|
||||||
viewHolders.put(view, true);
|
viewHolders.put(view, true);
|
||||||
}
|
}
|
||||||
@ -114,11 +110,7 @@ public class MessageAdapter extends RecyclerView.Adapter
|
|||||||
public RelativeLayout viewForeground;
|
public RelativeLayout viewForeground;
|
||||||
public RelativeLayout viewBackground;
|
public RelativeLayout viewBackground;
|
||||||
|
|
||||||
public MaterialButton btnShare;
|
|
||||||
public MaterialButton btnDelete;
|
|
||||||
|
|
||||||
private CMessage data;
|
private CMessage data;
|
||||||
private int datapos;
|
|
||||||
|
|
||||||
MessagePresenter(View itemView)
|
MessagePresenter(View itemView)
|
||||||
{
|
{
|
||||||
@ -129,8 +121,6 @@ public class MessageAdapter extends RecyclerView.Adapter
|
|||||||
ivPriority = itemView.findViewById(R.id.ivPriority);
|
ivPriority = itemView.findViewById(R.id.ivPriority);
|
||||||
viewForeground = itemView.findViewById(R.id.layoutFront);
|
viewForeground = itemView.findViewById(R.id.layoutFront);
|
||||||
viewBackground = itemView.findViewById(R.id.layoutBack);
|
viewBackground = itemView.findViewById(R.id.layoutBack);
|
||||||
btnShare = itemView.findViewById(R.id.btnShare);
|
|
||||||
btnDelete = itemView.findViewById(R.id.btnDelete);
|
|
||||||
|
|
||||||
itemView.setOnClickListener(this);
|
itemView.setOnClickListener(this);
|
||||||
tvTimestamp.setOnClickListener(this);
|
tvTimestamp.setOnClickListener(this);
|
||||||
@ -138,22 +128,9 @@ public class MessageAdapter extends RecyclerView.Adapter
|
|||||||
tvMessage.setOnClickListener(this);
|
tvMessage.setOnClickListener(this);
|
||||||
ivPriority.setOnClickListener(this);
|
ivPriority.setOnClickListener(this);
|
||||||
viewForeground.setOnClickListener(this);
|
viewForeground.setOnClickListener(this);
|
||||||
|
|
||||||
btnShare.setOnClickListener(v ->
|
|
||||||
{
|
|
||||||
if (data == null) return;
|
|
||||||
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
|
|
||||||
sharingIntent.setType("text/plain");
|
|
||||||
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, data.Title);
|
|
||||||
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, data.Content);
|
|
||||||
SCNApp.getMainActivity().startActivity(Intent.createChooser(sharingIntent, "Share message"));
|
|
||||||
|
|
||||||
});
|
|
||||||
btnDelete.setOnClickListener(v -> { if (data != null) SCNApp.getMainActivity().adpTabs.tab1.deleteMessage(datapos); });
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMessage(CMessage msg, int pos)
|
void setMessage(CMessage msg)
|
||||||
{
|
{
|
||||||
tvTimestamp.setText(msg.formatTimestamp());
|
tvTimestamp.setText(msg.formatTimestamp());
|
||||||
tvTitle.setText(msg.Title);
|
tvTitle.setText(msg.Title);
|
||||||
@ -178,49 +155,21 @@ public class MessageAdapter extends RecyclerView.Adapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = msg;
|
data = msg;
|
||||||
datapos = pos;
|
|
||||||
|
|
||||||
if (msg.IsExpandedInAdapter) expand(true); else collapse(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expand(boolean force)
|
|
||||||
{
|
|
||||||
if (data != null && data.IsExpandedInAdapter && !force) return;
|
|
||||||
if (data != null) data.IsExpandedInAdapter = true;
|
|
||||||
if (tvMessage != null) tvMessage.setMaxLines(9999);
|
|
||||||
if (btnDelete != null) btnDelete.setVisibility(View.VISIBLE);
|
|
||||||
if (btnShare != null) btnShare.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private int norm(int i) { return (i<=0)?0:((i>9999)?9999:i); }
|
|
||||||
|
|
||||||
private void collapse(boolean force)
|
|
||||||
{
|
|
||||||
if (data != null && !data.IsExpandedInAdapter && !force) return;
|
|
||||||
if (data != null) data.IsExpandedInAdapter = false;
|
|
||||||
if (tvMessage != null) tvMessage.setMaxLines(norm(SCNSettings.inst().PreviewLineCount));
|
|
||||||
if (btnDelete != null) btnDelete.setVisibility(View.GONE);
|
|
||||||
if (btnShare != null) btnShare.setVisibility(View.GONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v)
|
public void onClick(View v)
|
||||||
{
|
{
|
||||||
if (data.IsExpandedInAdapter)
|
|
||||||
{
|
|
||||||
collapse(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MessagePresenter holder : MessageAdapter.this.viewHolders.keySet())
|
for (MessagePresenter holder : MessageAdapter.this.viewHolders.keySet())
|
||||||
{
|
{
|
||||||
if (holder == null) continue;
|
if (holder == null) continue;
|
||||||
if (holder == this) continue;
|
if (holder == this) continue;
|
||||||
holder.collapse(false);
|
if (holder.tvMessage == null) continue;
|
||||||
|
if (holder.tvMessage.getMaxLines() == 6) continue;
|
||||||
|
holder.tvMessage.setMaxLines(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
expand(false);
|
tvMessage.setMaxLines(9999);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ public class NotificationsFragment extends Fragment implements MessageAdapterTou
|
|||||||
|
|
||||||
public void updateProState()
|
public void updateProState()
|
||||||
{
|
{
|
||||||
if (adView != null) adView.setVisibility(IABService.inst().getPurchaseCachedSimple(IABService.IAB_PRO_MODE) ? View.GONE : View.VISIBLE);
|
if (adView != null) adView.setVisibility(IABService.inst().getPurchaseCached(IABService.IAB_PRO_MODE) != null ? View.GONE : View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -66,25 +66,15 @@ public class NotificationsFragment extends Fragment implements MessageAdapterTou
|
|||||||
{
|
{
|
||||||
if (viewHolder instanceof MessageAdapter.MessagePresenter)
|
if (viewHolder instanceof MessageAdapter.MessagePresenter)
|
||||||
{
|
{
|
||||||
deleteMessage(viewHolder.getAdapterPosition());
|
final int deletedIndex = viewHolder.getAdapterPosition();
|
||||||
|
|
||||||
|
final CMessage deletedItem = adpMessages.removeItem(viewHolder.getAdapterPosition());
|
||||||
|
String name = deletedItem.Title;
|
||||||
|
|
||||||
|
Snackbar snackbar = Snackbar.make(SCNApp.getMainActivity().layoutRoot, name + " removed", Snackbar.LENGTH_LONG);
|
||||||
|
snackbar.setAction("UNDO", view -> adpMessages.restoreItem(deletedItem, deletedIndex));
|
||||||
|
snackbar.setActionTextColor(Color.YELLOW);
|
||||||
|
snackbar.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteMessage(int pos)
|
|
||||||
{
|
|
||||||
final int deletedIndex = pos;
|
|
||||||
|
|
||||||
final CMessage deletedItem = adpMessages.removeItem(pos);
|
|
||||||
String name = deletedItem.Title;
|
|
||||||
|
|
||||||
Snackbar snackbar = Snackbar.make(SCNApp.getMainActivity().layoutRoot, name + " removed", Snackbar.LENGTH_LONG);
|
|
||||||
snackbar.setAction("UNDO", view -> adpMessages.restoreItem(deletedItem, deletedIndex));
|
|
||||||
snackbar.setActionTextColor(Color.YELLOW);
|
|
||||||
snackbar.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateDeleteSwipeEnabled()
|
|
||||||
{
|
|
||||||
if (touchHelper != null) touchHelper.updateEnabled();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.view;
|
package com.blackforestbytes.simplecloudnotifier.view;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.media.AudioAttributes;
|
import android.media.AudioAttributes;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
|
import android.media.Ringtone;
|
||||||
|
import android.media.RingtoneManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -17,7 +17,6 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
@ -25,26 +24,21 @@ import android.widget.Switch;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import com.android.billingclient.api.Purchase;
|
||||||
import androidx.core.content.FileProvider;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
import com.blackforestbytes.simplecloudnotifier.R;
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||||
|
import com.blackforestbytes.simplecloudnotifier.lib.android.ThreadUtils;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.lambda.FI;
|
import com.blackforestbytes.simplecloudnotifier.lib.lambda.FI;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
||||||
import com.blackforestbytes.simplecloudnotifier.service.IABService;
|
import com.blackforestbytes.simplecloudnotifier.service.IABService;
|
||||||
import com.blackforestbytes.simplecloudnotifier.util.TextChangedListener;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectOutputStream;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
import top.defaults.colorpicker.ColorPickerPopup;
|
import top.defaults.colorpicker.ColorPickerPopup;
|
||||||
import xyz.aprildown.ultimatemusicpicker.MusicPickerListener;
|
import xyz.aprildown.ultimatemusicpicker.MusicPickerListener;
|
||||||
import xyz.aprildown.ultimatemusicpicker.UltimateMusicPicker;
|
import xyz.aprildown.ultimatemusicpicker.UltimateMusicPicker;
|
||||||
@ -57,7 +51,6 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
private TextView prefUpgradeAccount_msg;
|
private TextView prefUpgradeAccount_msg;
|
||||||
private TextView prefUpgradeAccount_info;
|
private TextView prefUpgradeAccount_info;
|
||||||
private Switch prefEnableDeleteSwipe;
|
private Switch prefEnableDeleteSwipe;
|
||||||
private EditText prefPreviewLineCount;
|
|
||||||
|
|
||||||
private Switch prefMsgLowEnableSound;
|
private Switch prefMsgLowEnableSound;
|
||||||
private TextView prefMsgLowRingtone_value;
|
private TextView prefMsgLowRingtone_value;
|
||||||
@ -95,9 +88,6 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
private SeekBar prefMsgHighVolume;
|
private SeekBar prefMsgHighVolume;
|
||||||
private ImageView prefMsgHighVolumeTest;
|
private ImageView prefMsgHighVolumeTest;
|
||||||
|
|
||||||
private Button prefBtnImport;
|
|
||||||
private Button prefBtnExport;
|
|
||||||
|
|
||||||
private int musicPickerSwitch = -1;
|
private int musicPickerSwitch = -1;
|
||||||
|
|
||||||
private MediaPlayer[] mPlayers = new MediaPlayer[3];
|
private MediaPlayer[] mPlayers = new MediaPlayer[3];
|
||||||
@ -127,7 +117,6 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
prefUpgradeAccount_msg = v.findViewById(R.id.prefUpgradeAccount2);
|
prefUpgradeAccount_msg = v.findViewById(R.id.prefUpgradeAccount2);
|
||||||
prefUpgradeAccount_info = v.findViewById(R.id.prefUpgradeAccount_info);
|
prefUpgradeAccount_info = v.findViewById(R.id.prefUpgradeAccount_info);
|
||||||
prefEnableDeleteSwipe = v.findViewById(R.id.prefEnableDeleteSwipe);
|
prefEnableDeleteSwipe = v.findViewById(R.id.prefEnableDeleteSwipe);
|
||||||
prefPreviewLineCount = v.findViewById(R.id.prefPreviewLineCount);
|
|
||||||
|
|
||||||
prefMsgLowEnableSound = v.findViewById(R.id.prefMsgLowEnableSound);
|
prefMsgLowEnableSound = v.findViewById(R.id.prefMsgLowEnableSound);
|
||||||
prefMsgLowRingtone_value = v.findViewById(R.id.prefMsgLowRingtone_value);
|
prefMsgLowRingtone_value = v.findViewById(R.id.prefMsgLowRingtone_value);
|
||||||
@ -161,19 +150,11 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
prefMsgHighLedColor_value = v.findViewById(R.id.prefMsgHighLedColor_value);
|
prefMsgHighLedColor_value = v.findViewById(R.id.prefMsgHighLedColor_value);
|
||||||
prefMsgHighLedColor_container = v.findViewById(R.id.prefMsgHighLedColor_container);
|
prefMsgHighLedColor_container = v.findViewById(R.id.prefMsgHighLedColor_container);
|
||||||
prefMsgHighEnableVibrations = v.findViewById(R.id.prefMsgHighEnableVibrations);
|
prefMsgHighEnableVibrations = v.findViewById(R.id.prefMsgHighEnableVibrations);
|
||||||
prefMsgHighForceVolume = v.findViewById(R.id.prefMsgHighForceVolume);
|
prefMsgHighForceVolume = v.findViewById(R.id.prefMsgHighForceVolume);
|
||||||
prefMsgHighVolume = v.findViewById(R.id.prefMsgHighVolume);
|
prefMsgHighVolume = v.findViewById(R.id.prefMsgHighVolume);
|
||||||
prefMsgHighVolumeTest = v.findViewById(R.id.btnHighVolumeTest);
|
prefMsgHighVolumeTest = v.findViewById(R.id.btnHighVolumeTest);
|
||||||
|
|
||||||
prefBtnExport = v.findViewById(R.id.prefExport);
|
|
||||||
prefBtnImport = v.findViewById(R.id.prefImport);
|
|
||||||
|
|
||||||
ArrayAdapter<Integer> plcsa = new ArrayAdapter<>(v.getContext(), android.R.layout.simple_spinner_item, SCNSettings.CHOOSABLE_CACHE_SIZES);
|
|
||||||
plcsa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
prefLocalCacheSize.setAdapter(plcsa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
private void updateUI()
|
private void updateUI()
|
||||||
{
|
{
|
||||||
SCNSettings s = SCNSettings.inst();
|
SCNSettings s = SCNSettings.inst();
|
||||||
@ -182,13 +163,15 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
|
|
||||||
if (prefAppEnabled.isChecked() != s.Enabled) prefAppEnabled.setChecked(s.Enabled);
|
if (prefAppEnabled.isChecked() != s.Enabled) prefAppEnabled.setChecked(s.Enabled);
|
||||||
if (prefEnableDeleteSwipe.isChecked() != s.EnableDeleteSwipe) prefEnableDeleteSwipe.setChecked(s.EnableDeleteSwipe);
|
if (prefEnableDeleteSwipe.isChecked() != s.EnableDeleteSwipe) prefEnableDeleteSwipe.setChecked(s.EnableDeleteSwipe);
|
||||||
if (!prefPreviewLineCount.getText().toString().equals(Integer.toString(s.PreviewLineCount))) prefPreviewLineCount.setText(Integer.toString(s.PreviewLineCount));
|
|
||||||
|
|
||||||
prefUpgradeAccount.setVisibility( SCNSettings.inst().promode_local ? View.GONE : View.VISIBLE);
|
prefUpgradeAccount.setVisibility( SCNSettings.inst().promode_local ? View.GONE : View.VISIBLE);
|
||||||
prefUpgradeAccount_info.setVisibility(SCNSettings.inst().promode_local ? View.GONE : View.VISIBLE);
|
prefUpgradeAccount_info.setVisibility(SCNSettings.inst().promode_local ? View.GONE : View.VISIBLE);
|
||||||
prefUpgradeAccount_msg.setVisibility( SCNSettings.inst().promode_local ? View.VISIBLE : View.GONE );
|
prefUpgradeAccount_msg.setVisibility( SCNSettings.inst().promode_local ? View.VISIBLE : View.GONE );
|
||||||
|
|
||||||
if (prefLocalCacheSize.getSelectedItemPosition() != getCacheSizeIndex(s.LocalCacheSize)) prefLocalCacheSize.setSelection(getCacheSizeIndex(s.LocalCacheSize));
|
ArrayAdapter<Integer> plcsa = new ArrayAdapter<>(c, android.R.layout.simple_spinner_item, SCNSettings.CHOOSABLE_CACHE_SIZES);
|
||||||
|
plcsa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
prefLocalCacheSize.setAdapter(plcsa);
|
||||||
|
prefLocalCacheSize.setSelection(getCacheSizeIndex(s.LocalCacheSize));
|
||||||
|
|
||||||
if (prefMsgLowEnableSound.isChecked() != s.PriorityLow.EnableSound) prefMsgLowEnableSound.setChecked(s.PriorityLow.EnableSound);
|
if (prefMsgLowEnableSound.isChecked() != s.PriorityLow.EnableSound) prefMsgLowEnableSound.setChecked(s.PriorityLow.EnableSound);
|
||||||
if (!prefMsgLowRingtone_value.getText().equals(s.PriorityLow.SoundName)) prefMsgLowRingtone_value.setText(s.PriorityLow.SoundName);
|
if (!prefMsgLowRingtone_value.getText().equals(s.PriorityLow.SoundName)) prefMsgLowRingtone_value.setText(s.PriorityLow.SoundName);
|
||||||
@ -236,12 +219,6 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
|
|
||||||
prefAppEnabled.setOnCheckedChangeListener((a,b) -> { boolean prev=s.Enabled; s.Enabled=b; saveAndUpdate(); updateEnabled(prev, b); });
|
prefAppEnabled.setOnCheckedChangeListener((a,b) -> { boolean prev=s.Enabled; s.Enabled=b; saveAndUpdate(); updateEnabled(prev, b); });
|
||||||
prefEnableDeleteSwipe.setOnCheckedChangeListener((a,b) -> { s.EnableDeleteSwipe=b; saveAndUpdate(); });
|
prefEnableDeleteSwipe.setOnCheckedChangeListener((a,b) -> { s.EnableDeleteSwipe=b; saveAndUpdate(); });
|
||||||
prefPreviewLineCount.addTextChangedListener(new TextChangedListener<EditText>(prefPreviewLineCount) {
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(EditText target, Editable ed) {
|
|
||||||
if (!ed.toString().isEmpty()) try { s.PreviewLineCount=Integer.parseInt(ed.toString()); saveAndUpdate(); } catch (Exception e) { /* */ }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
prefLocalCacheSize.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
|
prefLocalCacheSize.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
|
||||||
{
|
{
|
||||||
@ -254,9 +231,6 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
|
|
||||||
prefUpgradeAccount.setOnClickListener(a -> onUpgradeAccount());
|
prefUpgradeAccount.setOnClickListener(a -> onUpgradeAccount());
|
||||||
|
|
||||||
prefBtnExport.setOnClickListener(a -> onExport());
|
|
||||||
prefBtnImport.setOnClickListener(a -> onImport());
|
|
||||||
|
|
||||||
prefMsgLowEnableSound.setOnCheckedChangeListener((a,b) -> { s.PriorityLow.EnableSound=b; saveAndUpdate(); });
|
prefMsgLowEnableSound.setOnCheckedChangeListener((a,b) -> { s.PriorityLow.EnableSound=b; saveAndUpdate(); });
|
||||||
prefMsgLowRingtone_container.setOnClickListener(a -> chooseRingtoneLow());
|
prefMsgLowRingtone_container.setOnClickListener(a -> chooseRingtoneLow());
|
||||||
prefMsgLowRepeatSound.setOnCheckedChangeListener((a,b) -> { s.PriorityLow.RepeatSound=b; saveAndUpdate(); });
|
prefMsgLowRepeatSound.setOnCheckedChangeListener((a,b) -> { s.PriorityLow.RepeatSound=b; saveAndUpdate(); });
|
||||||
@ -288,55 +262,6 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
prefMsgHighVolumeTest.setOnClickListener((v) -> { if (s.PriorityHigh.ForceVolume) playTestSound(2, prefMsgHighVolumeTest, s.PriorityHigh.SoundSource, s.PriorityHigh.ForceVolumeValue); });
|
prefMsgHighVolumeTest.setOnClickListener((v) -> { if (s.PriorityHigh.ForceVolume) playTestSound(2, prefMsgHighVolumeTest, s.PriorityHigh.SoundSource, s.PriorityHigh.ForceVolumeValue); });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onExport()
|
|
||||||
{
|
|
||||||
Context ctxt = getContext();
|
|
||||||
if (ctxt == null) return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File outputDir = ctxt.getCacheDir(); // context being the Activity pointer
|
|
||||||
File outputFile = File.createTempFile("scn_export_", ".dat", outputDir);
|
|
||||||
|
|
||||||
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(outputFile));
|
|
||||||
|
|
||||||
Map<String, ?> d1 = ctxt.getSharedPreferences("Config", Context.MODE_PRIVATE).getAll();
|
|
||||||
Map<String, ?> d2 = ctxt.getSharedPreferences("IAB", Context.MODE_PRIVATE).getAll();
|
|
||||||
Map<String, ?> d3 = ctxt.getSharedPreferences("CMessageList", Context.MODE_PRIVATE).getAll();
|
|
||||||
Map<String, ?> d4 = ctxt.getSharedPreferences("QueryLog", Context.MODE_PRIVATE).getAll();
|
|
||||||
|
|
||||||
output.writeObject(d1);
|
|
||||||
output.writeObject(d2);
|
|
||||||
output.writeObject(d3);
|
|
||||||
output.writeObject(d4);
|
|
||||||
|
|
||||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
|
||||||
|
|
||||||
Uri uri = FileProvider.getUriForFile(ctxt, "com.blackforestbytes.simplecloudnotifier.fileprovider", outputFile);
|
|
||||||
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
|
||||||
intent.setType("*/*");
|
|
||||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
|
|
||||||
startActivity(Intent.createChooser(intent, "Export"));
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
Log.e("Export:Err", e.toString());
|
|
||||||
SCNApp.showToast("Export failed", Toast.LENGTH_LONG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onImport()
|
|
||||||
{
|
|
||||||
SCNApp.getMainActivity().setContentView(R.layout.activity_main);
|
|
||||||
|
|
||||||
Intent intent = new Intent()
|
|
||||||
.setType("*/*")
|
|
||||||
.setAction(Intent.ACTION_GET_CONTENT);
|
|
||||||
|
|
||||||
((MainActivity)getActivity()).startActivityForResult(Intent.createChooser(intent, "Select a file"), 1991);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateEnabled(boolean prev, boolean now)
|
private void updateEnabled(boolean prev, boolean now)
|
||||||
{
|
{
|
||||||
if (!prev && now)
|
if (!prev && now)
|
||||||
@ -416,7 +341,7 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
{
|
{
|
||||||
SCNSettings.inst().save();
|
SCNSettings.inst().save();
|
||||||
updateUI();
|
updateUI();
|
||||||
SCNApp.getMainActivity().adpTabs.tab1.updateDeleteSwipeEnabled();
|
SCNApp.getMainActivity().adpTabs.tab1.touchHelper.updateEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onUpgradeAccount()
|
private void onUpgradeAccount()
|
||||||
@ -426,11 +351,11 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
|
|
||||||
public void updateProState()
|
public void updateProState()
|
||||||
{
|
{
|
||||||
boolean pmode = IABService.inst().getPurchaseCachedSimple(IABService.IAB_PRO_MODE);
|
Purchase p = IABService.inst().getPurchaseCached(IABService.IAB_PRO_MODE);
|
||||||
|
|
||||||
if (prefUpgradeAccount != null) prefUpgradeAccount.setVisibility( pmode ? View.GONE : View.VISIBLE);
|
if (prefUpgradeAccount != null) prefUpgradeAccount.setVisibility( p != null ? View.GONE : View.VISIBLE);
|
||||||
if (prefUpgradeAccount_info != null) prefUpgradeAccount_info.setVisibility(pmode ? View.GONE : View.VISIBLE);
|
if (prefUpgradeAccount_info != null) prefUpgradeAccount_info.setVisibility(p != null ? View.GONE : View.VISIBLE);
|
||||||
if (prefUpgradeAccount_msg != null) prefUpgradeAccount_msg.setVisibility( pmode ? View.VISIBLE : View.GONE );
|
if (prefUpgradeAccount_msg != null) prefUpgradeAccount_msg.setVisibility( p != null ? View.VISIBLE : View.GONE );
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCacheSizeIndex(int value)
|
private int getCacheSizeIndex(int value)
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.view.debug;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.QueryLog;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SingleQuery;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
|
||||||
|
|
||||||
public class QueryLogActivity extends AppCompatActivity
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_querylog);
|
|
||||||
|
|
||||||
ListView lvMain = findViewById(R.id.lvQueryList);
|
|
||||||
SingleQuery[] arr = QueryLog.inst().get().toArray(new SingleQuery[0]);
|
|
||||||
QueryLogAdapter a = new QueryLogAdapter(this, arr);
|
|
||||||
lvMain.setAdapter(a);
|
|
||||||
|
|
||||||
lvMain.setOnItemClickListener((parent, view, position, id) ->
|
|
||||||
{
|
|
||||||
if (position >= 0 && position < arr.length)
|
|
||||||
{
|
|
||||||
Intent i = new Intent(QueryLogActivity.this, SingleQueryLogActivity.class);
|
|
||||||
Bundle b = new Bundle();
|
|
||||||
arr[position].save(b, "data");
|
|
||||||
i.putExtra("query", b);
|
|
||||||
startActivity(i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.view.debug;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SingleQuery;
|
|
||||||
|
|
||||||
import org.joda.time.format.DateTimeFormat;
|
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
|
||||||
|
|
||||||
public class QueryLogAdapter extends ArrayAdapter<SingleQuery>
|
|
||||||
{
|
|
||||||
public static DateTimeFormatter UI_FULLTIME_FORMATTER = DateTimeFormat.forPattern("HH:mm:ss");
|
|
||||||
|
|
||||||
public QueryLogAdapter(@NonNull Context context, @NonNull SingleQuery[] objects)
|
|
||||||
{
|
|
||||||
super(context, R.layout.adapter_querylog, objects);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, @NonNull ViewGroup parent)
|
|
||||||
{
|
|
||||||
View v = convertView;
|
|
||||||
|
|
||||||
if (v == null) {
|
|
||||||
LayoutInflater vi;
|
|
||||||
vi = LayoutInflater.from(getContext());
|
|
||||||
v = vi.inflate(R.layout.adapter_querylog, parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleQuery p = getItem(position);
|
|
||||||
|
|
||||||
if (p != null)
|
|
||||||
{
|
|
||||||
TextView tt1 = v.findViewById(R.id.list_item_debuglogrow_time);
|
|
||||||
if (tt1 != null) tt1.setText(p.Timestamp.toString(UI_FULLTIME_FORMATTER));
|
|
||||||
if (tt1 != null) tt1.setTextColor(Color.BLACK);
|
|
||||||
|
|
||||||
TextView tt2 = v.findViewById(R.id.list_item_debuglogrow_level);
|
|
||||||
if (tt2 != null) tt2.setText(p.Level.toUIString());
|
|
||||||
if (tt2 != null) tt2.setTextColor(Color.BLACK);
|
|
||||||
|
|
||||||
TextView tt3 = v.findViewById(R.id.list_item_debuglogrow_info);
|
|
||||||
if (tt3 != null) tt3.setText("");
|
|
||||||
if (tt3 != null) tt3.setTextColor(Color.BLUE);
|
|
||||||
|
|
||||||
TextView tt4 = v.findViewById(R.id.list_item_debuglogrow_id);
|
|
||||||
if (tt4 != null) tt4.setText(p.Name);
|
|
||||||
if (tt4 != null) tt4.setTextColor(p.Level.getColor());
|
|
||||||
|
|
||||||
TextView tt5 = v.findViewById(R.id.list_item_debuglogrow_message);
|
|
||||||
if (tt5 != null) tt5.setText(p.ExceptionString.length()> 40 ? p.ExceptionString.substring(0, 40-3)+"..." : p.ExceptionString);
|
|
||||||
if (tt5 != null) tt5.setTextColor(p.Level.getColor());
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.view.debug;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.CompactJsonFormatter;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SingleQuery;
|
|
||||||
|
|
||||||
import org.joda.time.format.DateTimeFormat;
|
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class SingleQueryLogActivity extends AppCompatActivity
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_singlequerylog);
|
|
||||||
|
|
||||||
SingleQuery q = SingleQuery.load(getIntent().getBundleExtra("query"), "data");
|
|
||||||
|
|
||||||
this.<TextView>findViewById(R.id.tvQL_Timestamp).setText(q.Timestamp.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")));
|
|
||||||
this.<TextView>findViewById(R.id.tvQL_Level).setText(q.Level.toUIString());
|
|
||||||
this.<TextView>findViewById(R.id.tvQL_Level).setTextColor(q.Level.getColor());
|
|
||||||
this.<TextView>findViewById(R.id.tvQL_Name).setText(q.Name);
|
|
||||||
this.<TextView>findViewById(R.id.tvQL_URL).setText(q.URL.replace("?", "\r\n?").replace("&", "\r\n&"));
|
|
||||||
this.<TextView>findViewById(R.id.tvQL_Response).setText(CompactJsonFormatter.formatJSON(q.Response, 999));
|
|
||||||
this.<TextView>findViewById(R.id.tvQL_ResponseCode).setText(Integer.toString(q.ResponseCode));
|
|
||||||
this.<TextView>findViewById(R.id.tvQL_ExceptionString).setText(q.ExceptionString);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
|
|
||||||
<solid android:color="@android:color/white" />
|
|
||||||
<stroke android:width="1dip" android:color="#888888"/>
|
|
||||||
</shape>
|
|
@ -1,10 +0,0 @@
|
|||||||
<vector
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="12sp"
|
|
||||||
android:height="12sp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
|
|
||||||
</vector>
|
|
@ -1,16 +0,0 @@
|
|||||||
<vector
|
|
||||||
android:height="12sp"
|
|
||||||
android:width="12sp"
|
|
||||||
android:viewportHeight="53"
|
|
||||||
android:viewportWidth="53"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M42.943,6H33.5V3c0,-1.654 -1.346,-3 -3,-3h-8c-1.654,0 -3,1.346 -3,3v3h-9.443C8.096,6 6.5,7.596 6.5,9.557V14h2h36h2V9.557C46.5,7.596 44.904,6 42.943,6zM31.5,6h-10V3c0,-0.552 0.449,-1 1,-1h8c0.551,0 1,0.448 1,1V6z"/>
|
|
||||||
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M8.5,49.271C8.5,51.327 10.173,53 12.229,53h28.541c2.057,0 3.729,-1.673 3.729,-3.729V16h-36V49.271z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
@ -1,31 +1,31 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout android:id="@+id/layoutRoot"
|
<RelativeLayout
|
||||||
|
android:id="@+id/layoutRoot"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
tools:showIn="@layout/activity_main">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<androidx.appcompat.widget.Toolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
app:titleTextColor="@color/colorOnPrimary"
|
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorPrimary"
|
||||||
android:elevation="6dp"
|
android:elevation="6dp"
|
||||||
android:minHeight="?attr/actionBarSize" />
|
android:minHeight="?attr/actionBarSize"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
<com.google.android.material.tabs.TabLayout
|
||||||
android:id="@+id/tab_layout"
|
android:id="@+id/tab_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/toolbar"
|
android:layout_below="@+id/toolbar"
|
||||||
app:titleTextColor="@color/colorOnPrimary"
|
|
||||||
app:tabTextColor="@color/colorOnPrimary"
|
|
||||||
app:tabSelectedTextColor="@color/colorSecondary"
|
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorPrimary"
|
||||||
android:elevation="6dp"
|
android:elevation="6dp"
|
||||||
android:minHeight="?attr/actionBarSize" />
|
android:minHeight="?attr/actionBarSize"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
||||||
|
|
||||||
<androidx.viewpager.widget.ViewPager
|
<androidx.viewpager.widget.ViewPager
|
||||||
android:id="@+id/pager"
|
android:id="@+id/pager"
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/layoutRoot"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<ListView
|
|
||||||
android:id="@+id/lvQueryList"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
@ -1,240 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:padding="4sp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:text="Server Query" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:text="Timestamp" />
|
|
||||||
|
|
||||||
<com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView
|
|
||||||
app:maxHeightOverride="100"
|
|
||||||
android:background="@drawable/simple_black_border"
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvQL_Timestamp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:padding="1dip"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:text="" />
|
|
||||||
|
|
||||||
</com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:text="Level" />
|
|
||||||
|
|
||||||
<com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView
|
|
||||||
app:maxHeightOverride="100"
|
|
||||||
android:background="@drawable/simple_black_border"
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvQL_Level"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:padding="1dip"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:text="" />
|
|
||||||
|
|
||||||
</com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:text="Name" />
|
|
||||||
|
|
||||||
<com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView
|
|
||||||
app:maxHeightOverride="100"
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:background="@drawable/simple_black_border"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvQL_Name"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:padding="1dip"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:text="" />
|
|
||||||
|
|
||||||
</com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:text="URL" />
|
|
||||||
|
|
||||||
<com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView
|
|
||||||
app:maxHeightOverride="100"
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:background="@drawable/simple_black_border"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvQL_URL"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:padding="1dip"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:text=""/>
|
|
||||||
|
|
||||||
</com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:text="ResponeCode" />
|
|
||||||
|
|
||||||
<com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView
|
|
||||||
app:maxHeightOverride="64"
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:background="@drawable/simple_black_border"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvQL_ResponseCode"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:padding="1dip"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:text="" />
|
|
||||||
|
|
||||||
</com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:text="Response" />
|
|
||||||
|
|
||||||
|
|
||||||
<com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView
|
|
||||||
app:maxHeightOverride="100"
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:background="@drawable/simple_black_border"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvQL_Response"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:padding="1dip"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:text="" />
|
|
||||||
|
|
||||||
</com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:text="Exception" />
|
|
||||||
|
|
||||||
<com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView
|
|
||||||
app:maxHeightOverride="100"
|
|
||||||
android:layout_margin="2dip"
|
|
||||||
android:background="@drawable/simple_black_border"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvQL_ExceptionString"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:padding="1dip"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:text="" />
|
|
||||||
|
|
||||||
</com.blackforestbytes.simplecloudnotifier.util.MaxHeightScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
@ -1,50 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/list_item_imagerow"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="96dp"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/list_item_debuglogrow_time"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/list_item_debuglogrow_level"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/list_item_debuglogrow_info"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/list_item_debuglogrow_id"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/list_item_debuglogrow_message"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -198,27 +198,19 @@
|
|||||||
app:layout_constraintBottom_toTopOf="@+id/btnAccountReset"
|
app:layout_constraintBottom_toTopOf="@+id/btnAccountReset"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/ic_img_quota" />
|
app:layout_constraintTop_toBottomOf="@+id/ic_img_quota" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/btnAccountReset"
|
android:id="@+id/btnAccountReset"
|
||||||
app:cornerRadius="0dp"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:backgroundTint="#fa315b"
|
|
||||||
android:text="@string/str_reset_account"
|
android:text="@string/str_reset_account"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/btnClearLocalStorage" />
|
app:layout_constraintBottom_toTopOf="@+id/btnClearLocalStorage" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/btnClearLocalStorage"
|
android:id="@+id/btnClearLocalStorage"
|
||||||
app:cornerRadius="0dp"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Clear Messages"
|
android:text="Clear Messages"
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:backgroundTint="#607D8B"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
@ -95,46 +95,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="48dp" />
|
android:minHeight="48dp" />
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:layout_marginBottom="2dp"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:background="#c0c0c0"/>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="48dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvPreviewLineCount"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/str_previewlinecount"
|
|
||||||
android:textColor="#000"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/prefPreviewLineCount"
|
|
||||||
app:layout_constraintHorizontal_bias="0"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:minWidth="64dp"
|
|
||||||
android:id="@+id/prefPreviewLineCount"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="number"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:importantForAutofill="no"
|
|
||||||
tools:ignore="LabelFor,UnusedAttribute" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
@ -151,10 +111,8 @@
|
|||||||
android:gravity="center|center"
|
android:gravity="center|center"
|
||||||
android:minHeight="48dp">
|
android:minHeight="48dp">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/prefUpgradeAccount"
|
android:id="@+id/prefUpgradeAccount"
|
||||||
app:cornerRadius="0dp"
|
|
||||||
android:backgroundTint="#4CAF50"
|
|
||||||
android:text="@string/str_upgrade_account"
|
android:text="@string/str_upgrade_account"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
@ -805,24 +763,6 @@
|
|||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/prefExport"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="12dp"
|
|
||||||
app:cornerRadius="0dp"
|
|
||||||
android:backgroundTint="#444444"
|
|
||||||
android:text="@string/export_settings" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/prefImport"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="12dp"
|
|
||||||
app:cornerRadius="0dp"
|
|
||||||
android:backgroundTint="#666666"
|
|
||||||
android:text="@string/import_settings" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -108,43 +108,6 @@
|
|||||||
android:paddingTop="3dp"
|
android:paddingTop="3dp"
|
||||||
android:contentDescription="@string/desc_priority_icon" />
|
android:contentDescription="@string/desc_priority_icon" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnShare"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.Icon"
|
|
||||||
app:cornerRadius="0dp"
|
|
||||||
app:icon="@drawable/ic_share_small"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="25dp"
|
|
||||||
android:layout_marginEnd="8sp"
|
|
||||||
android:insetTop="0dp"
|
|
||||||
android:insetBottom="0dp"
|
|
||||||
android:insetLeft="0dp"
|
|
||||||
android:insetRight="0dp"
|
|
||||||
android:textSize="12sp"
|
|
||||||
card_view:layout_constraintTop_toBottomOf="@id/tvMessage"
|
|
||||||
app:layout_constraintRight_toLeftOf="@id/btnDelete"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:backgroundTint="#03A9F4"
|
|
||||||
android:text="Share" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnDelete"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.Icon"
|
|
||||||
app:cornerRadius="0dp"
|
|
||||||
app:icon="@drawable/ic_trash_small"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="25dp"
|
|
||||||
android:insetTop="0dp"
|
|
||||||
android:insetBottom="0dp"
|
|
||||||
android:insetLeft="0dp"
|
|
||||||
android:insetRight="0dp"
|
|
||||||
android:textSize="12sp"
|
|
||||||
card_view:layout_constraintTop_toBottomOf="@id/tvMessage"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:backgroundTint="#F44336"
|
|
||||||
android:text="Delete"/>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<declare-styleable name="MaxHeightScrollView">
|
|
||||||
<attr name="maxHeightOverride" format="integer" />
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -6,9 +6,6 @@
|
|||||||
<color name="colorHeader">#3F51B5</color>
|
<color name="colorHeader">#3F51B5</color>
|
||||||
<color name="colorHeaderForeground">#FFFFFF</color>
|
<color name="colorHeaderForeground">#FFFFFF</color>
|
||||||
|
|
||||||
<color name="colorOnPrimary">#ecf0f1</color>
|
|
||||||
<color name="colorSecondary">#FF5722</color>
|
|
||||||
|
|
||||||
<color name="colorBlack">#000</color>
|
<color name="colorBlack">#000</color>
|
||||||
|
|
||||||
<color name="bg_row_background">#fa315b</color>
|
<color name="bg_row_background">#fa315b</color>
|
||||||
|
@ -6,5 +6,4 @@
|
|||||||
<dimen name="padd_10">10dp</dimen>
|
<dimen name="padd_10">10dp</dimen>
|
||||||
<dimen name="ic_delete">30dp</dimen>
|
<dimen name="ic_delete">30dp</dimen>
|
||||||
<dimen name="thumbnail">90dp</dimen>
|
<dimen name="thumbnail">90dp</dimen>
|
||||||
<dimen name="fab_margin">16dp</dimen>
|
|
||||||
</resources>
|
</resources>
|
@ -30,13 +30,9 @@
|
|||||||
<string name="str_enable_vibration">Enable notification vibration</string>
|
<string name="str_enable_vibration">Enable notification vibration</string>
|
||||||
<string name="str_upgrade_account">Upgrade account</string>
|
<string name="str_upgrade_account">Upgrade account</string>
|
||||||
<string name="str_deleteswipe">Delete messages by swiping left</string>
|
<string name="str_deleteswipe">Delete messages by swiping left</string>
|
||||||
<string name="str_previewlinecount">Number of visibile lines in collapsed messages</string>
|
|
||||||
<string name="str_promode">Thank you for supporting the app and using the pro mode</string>
|
<string name="str_promode">Thank you for supporting the app and using the pro mode</string>
|
||||||
<string name="str_promode_info">Increase your daily quota, remove the ad banner and support the developer (that\'s me)</string>
|
<string name="str_promode_info">Increase your daily quota, remove the ad banner and support the developer (that\'s me)</string>
|
||||||
<string name="volume_icon">Volume icon</string>
|
<string name="volume_icon">Volume icon</string>
|
||||||
<string name="play_test_sound">Play test sound</string>
|
<string name="play_test_sound">Play test sound</string>
|
||||||
<string name="delete">DELETE</string>
|
<string name="delete">DELETE</string>
|
||||||
<string name="title_activity_query_log">QueryLogActivity</string>
|
|
||||||
<string name="import_settings">Import settings</string>
|
|
||||||
<string name="export_settings">Export settings</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,20 +1,13 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
|
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
<!-- your app branding color for the app bar -->
|
<!-- your app branding color for the app bar -->
|
||||||
<item name="colorPrimary">#3F51B5</item>
|
<item name="colorPrimary">#3F51B5</item>
|
||||||
|
|
||||||
<!-- darker variant for the status bar and contextual app bars -->
|
<!-- darker variant for the status bar and contextual app bars -->
|
||||||
<item name="colorPrimaryDark">#303F9F</item>
|
<item name="colorPrimaryDark">#303F9F</item>
|
||||||
|
|
||||||
<!-- theme UI controls like checkboxes and text fields -->
|
<!-- theme UI controls like checkboxes and text fields -->
|
||||||
<item name="colorAccent">#FF5722</item>
|
<item name="colorAccent">#FF4081</item>
|
||||||
<item name="colorSecondary">#FF5722</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.MaterialComponents.Dark.ActionBar" />
|
|
||||||
|
|
||||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.MaterialComponents.Light" />
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
<paths>
|
|
||||||
<files-path path="/" name="files" />
|
|
||||||
<cache-path path="/" name="cache" />
|
|
||||||
<external-path path="/" name="external" />
|
|
||||||
<external-files-path path="/" name="external-files" />
|
|
||||||
<external-cache-path path="/" name="external-cache" />
|
|
||||||
</paths>
|
|
@ -1,3 +1,3 @@
|
|||||||
#Thu Mar 05 15:29:10 UTC 2020
|
#Mon Nov 19 12:30:54 CET 2018
|
||||||
VERSION_NAME=1.8.0
|
VERSION_NAME=1.0.0
|
||||||
VERSION_CODE=23
|
VERSION_CODE=14
|
||||||
|
@ -7,8 +7,8 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:8.9.1'
|
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||||
classpath 'com.google.gms:google-services:4.3.10'
|
classpath 'com.google.gms:google-services:4.2.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,3 @@ org.gradle.jvmargs=-Xmx1536m
|
|||||||
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
android.defaults.buildfeatures.buildconfig=true
|
|
||||||
android.nonTransitiveRClass=false
|
|
||||||
android.nonFinalResIds=false
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#Tue Nov 03 14:10:19 CET 2020
|
#Wed Sep 26 22:10:14 CEST 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||||
|
58
androidExportReader/.gitignore
vendored
@ -1,58 +0,0 @@
|
|||||||
# Created by https://www.toptal.com/developers/gitignore/api/java,gradle
|
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle
|
|
||||||
|
|
||||||
### Java ###
|
|
||||||
# Compiled class file
|
|
||||||
*.class
|
|
||||||
|
|
||||||
# Log file
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# BlueJ files
|
|
||||||
*.ctxt
|
|
||||||
|
|
||||||
# Mobile Tools for Java (J2ME)
|
|
||||||
.mtj.tmp/
|
|
||||||
|
|
||||||
# Package Files #
|
|
||||||
*.jar
|
|
||||||
*.war
|
|
||||||
*.nar
|
|
||||||
*.ear
|
|
||||||
*.zip
|
|
||||||
*.tar.gz
|
|
||||||
*.rar
|
|
||||||
|
|
||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
|
||||||
hs_err_pid*
|
|
||||||
replay_pid*
|
|
||||||
|
|
||||||
### Gradle ###
|
|
||||||
.gradle
|
|
||||||
**/build/
|
|
||||||
!src/**/build/
|
|
||||||
|
|
||||||
# Ignore Gradle GUI config
|
|
||||||
gradle-app.setting
|
|
||||||
|
|
||||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
|
||||||
!gradle-wrapper.jar
|
|
||||||
|
|
||||||
# Avoid ignore Gradle wrappper properties
|
|
||||||
!gradle-wrapper.properties
|
|
||||||
|
|
||||||
# Cache of project
|
|
||||||
.gradletasknamecache
|
|
||||||
|
|
||||||
# Eclipse Gradle plugin generated files
|
|
||||||
# Eclipse Core
|
|
||||||
.project
|
|
||||||
# JDT-specific (Eclipse Java Development Tools)
|
|
||||||
.classpath
|
|
||||||
|
|
||||||
### Gradle Patch ###
|
|
||||||
# Java heap dump
|
|
||||||
*.hprof
|
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/java,gradle
|
|
||||||
|
|
8
androidExportReader/.idea/.gitignore
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
6
androidExportReader/.idea/compiler.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompilerConfiguration">
|
|
||||||
<bytecodeTargetLevel target="18" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
17
androidExportReader/.idea/gradle.xml
generated
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
|
||||||
<component name="GradleSettings">
|
|
||||||
<option name="linkedExternalProjectsSettings">
|
|
||||||
<GradleProjectSettings>
|
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="modules">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</GradleProjectSettings>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,11 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="JavadocReference" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" />
|
|
||||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
|
||||||
<option name="processCode" value="true" />
|
|
||||||
<option name="processLiterals" value="true" />
|
|
||||||
<option name="processComments" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
25
androidExportReader/.idea/jarRepositories.xml
generated
@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="RemoteRepositoriesConfiguration">
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="central" />
|
|
||||||
<option name="name" value="Maven Central repository" />
|
|
||||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="jboss.community" />
|
|
||||||
<option name="name" value="JBoss Community repository" />
|
|
||||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="MavenRepo" />
|
|
||||||
<option name="name" value="MavenRepo" />
|
|
||||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="maven" />
|
|
||||||
<option name="name" value="maven" />
|
|
||||||
<option name="url" value="https://jitpack.io" />
|
|
||||||
</remote-repository>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
10
androidExportReader/.idea/misc.xml
generated
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="openjdk-18" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
6
androidExportReader/.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'gradle.plugin.com.github.johnrengelman:shadow:7.1.2'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id("com.github.johnrengelman.shadow") version "7.1.2"
|
|
||||||
id 'application'
|
|
||||||
}
|
|
||||||
|
|
||||||
group 'com.blackforestbytes'
|
|
||||||
version '1.0-SNAPSHOT'
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url "https://jitpack.io" }
|
|
||||||
}
|
|
||||||
|
|
||||||
application {
|
|
||||||
mainClass = 'com.blackforestbytes.Main'
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes 'Main-Class': application.mainClass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.jar {
|
|
||||||
manifest.attributes["Main-Class"] = application.mainClass
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'com.github.RalleYTN:SimpleJSON:2.1.1'
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
|
|
||||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
|
||||||
distributionPath=wrapper/dists
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
|
240
androidExportReader/gradlew
vendored
@ -1,240 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright © 2015-2021 the original authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
#
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# Gradle start up script for POSIX generated by Gradle.
|
|
||||||
#
|
|
||||||
# Important for running:
|
|
||||||
#
|
|
||||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
|
||||||
# noncompliant, but you have some other compliant shell such as ksh or
|
|
||||||
# bash, then to run this script, type that shell name before the whole
|
|
||||||
# command line, like:
|
|
||||||
#
|
|
||||||
# ksh Gradle
|
|
||||||
#
|
|
||||||
# Busybox and similar reduced shells will NOT work, because this script
|
|
||||||
# requires all of these POSIX shell features:
|
|
||||||
# * functions;
|
|
||||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
|
||||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
|
||||||
# * compound commands having a testable exit status, especially «case»;
|
|
||||||
# * various built-in commands including «command», «set», and «ulimit».
|
|
||||||
#
|
|
||||||
# Important for patching:
|
|
||||||
#
|
|
||||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
|
||||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
|
||||||
#
|
|
||||||
# The "traditional" practice of packing multiple parameters into a
|
|
||||||
# space-separated string is a well documented source of bugs and security
|
|
||||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
|
||||||
# options in "$@", and eventually passing that to Java.
|
|
||||||
#
|
|
||||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
|
||||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
|
||||||
# see the in-line comments for details.
|
|
||||||
#
|
|
||||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
|
||||||
# Darwin, MinGW, and NonStop.
|
|
||||||
#
|
|
||||||
# (3) This script is generated from the Groovy template
|
|
||||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
|
||||||
# within the Gradle project.
|
|
||||||
#
|
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
|
||||||
app_path=$0
|
|
||||||
|
|
||||||
# Need this for daisy-chained symlinks.
|
|
||||||
while
|
|
||||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
|
||||||
[ -h "$app_path" ]
|
|
||||||
do
|
|
||||||
ls=$( ls -ld "$app_path" )
|
|
||||||
link=${ls#*' -> '}
|
|
||||||
case $link in #(
|
|
||||||
/*) app_path=$link ;; #(
|
|
||||||
*) app_path=$APP_HOME$link ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=${0##*/}
|
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
||||||
MAX_FD=maximum
|
|
||||||
|
|
||||||
warn () {
|
|
||||||
echo "$*"
|
|
||||||
} >&2
|
|
||||||
|
|
||||||
die () {
|
|
||||||
echo
|
|
||||||
echo "$*"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
} >&2
|
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
|
||||||
cygwin=false
|
|
||||||
msys=false
|
|
||||||
darwin=false
|
|
||||||
nonstop=false
|
|
||||||
case "$( uname )" in #(
|
|
||||||
CYGWIN* ) cygwin=true ;; #(
|
|
||||||
Darwin* ) darwin=true ;; #(
|
|
||||||
MSYS* | MINGW* ) msys=true ;; #(
|
|
||||||
NONSTOP* ) nonstop=true ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
|
||||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
|
||||||
else
|
|
||||||
JAVACMD=$JAVA_HOME/bin/java
|
|
||||||
fi
|
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
location of your Java installation."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
JAVACMD=java
|
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
location of your Java installation."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|
||||||
case $MAX_FD in #(
|
|
||||||
max*)
|
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
|
||||||
warn "Could not query maximum file descriptor limit"
|
|
||||||
esac
|
|
||||||
case $MAX_FD in #(
|
|
||||||
'' | soft) :;; #(
|
|
||||||
*)
|
|
||||||
ulimit -n "$MAX_FD" ||
|
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Collect all arguments for the java command, stacking in reverse order:
|
|
||||||
# * args from the command line
|
|
||||||
# * the main class name
|
|
||||||
# * -classpath
|
|
||||||
# * -D...appname settings
|
|
||||||
# * --module-path (only if needed)
|
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
||||||
if "$cygwin" || "$msys" ; then
|
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
|
||||||
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
for arg do
|
|
||||||
if
|
|
||||||
case $arg in #(
|
|
||||||
-*) false ;; # don't mess with options #(
|
|
||||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
|
||||||
[ -e "$t" ] ;; #(
|
|
||||||
*) false ;;
|
|
||||||
esac
|
|
||||||
then
|
|
||||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
|
||||||
fi
|
|
||||||
# Roll the args list around exactly as many times as the number of
|
|
||||||
# args, so each arg winds up back in the position where it started, but
|
|
||||||
# possibly modified.
|
|
||||||
#
|
|
||||||
# NB: a `for` loop captures its iteration list before it begins, so
|
|
||||||
# changing the positional parameters here affects neither the number of
|
|
||||||
# iterations, nor the values presented in `arg`.
|
|
||||||
shift # remove old arg
|
|
||||||
set -- "$@" "$arg" # push replacement arg
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
|
||||||
# double quotes to make sure that they get re-expanded; and
|
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
|
||||||
|
|
||||||
set -- \
|
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
|
||||||
-classpath "$CLASSPATH" \
|
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
|
||||||
"$@"
|
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
|
||||||
if ! command -v xargs >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
die "xargs is not available"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
|
||||||
#
|
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
|
||||||
#
|
|
||||||
# In Bash we could simply go:
|
|
||||||
#
|
|
||||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
|
||||||
# set -- "${ARGS[@]}" "$@"
|
|
||||||
#
|
|
||||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
|
||||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
|
||||||
# character that might be a shell metacharacter, then use eval to reverse
|
|
||||||
# that process (while maintaining the separation between arguments), and wrap
|
|
||||||
# the whole thing up as a single "set" statement.
|
|
||||||
#
|
|
||||||
# This will of course break if any of these variables contains a newline or
|
|
||||||
# an unmatched quote.
|
|
||||||
#
|
|
||||||
|
|
||||||
eval "set -- $(
|
|
||||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
|
||||||
xargs -n1 |
|
|
||||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
|
||||||
tr '\n' ' '
|
|
||||||
)" '"$@"'
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
|
91
androidExportReader/gradlew.bat
vendored
@ -1,91 +0,0 @@
|
|||||||
@rem
|
|
||||||
@rem Copyright 2015 the original author or authors.
|
|
||||||
@rem
|
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
@rem you may not use this file except in compliance with the License.
|
|
||||||
@rem You may obtain a copy of the License at
|
|
||||||
@rem
|
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
@rem
|
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
|
||||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
@rem See the License for the specific language governing permissions and
|
|
||||||
@rem limitations under the License.
|
|
||||||
@rem
|
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
|
||||||
@rem ##########################################################################
|
|
||||||
@rem
|
|
||||||
@rem Gradle startup script for Windows
|
|
||||||
@rem
|
|
||||||
@rem ##########################################################################
|
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
|
||||||
set APP_BASE_NAME=%~n0
|
|
||||||
set APP_HOME=%DIRNAME%
|
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
|
||||||
|
|
||||||
@rem Find java.exe
|
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
echo.
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
echo location of your Java installation.
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
|
||||||
echo.
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
echo location of your Java installation.
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:execute
|
|
||||||
@rem Setup the command line
|
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
|
||||||
|
|
||||||
:end
|
|
||||||
@rem End local scope for the variables with windows NT shell
|
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
|
||||||
|
|
||||||
:fail
|
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
||||||
rem the _cmd.exe /c_ return code!
|
|
||||||
set EXIT_CODE=%ERRORLEVEL%
|
|
||||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
|
||||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
|
||||||
exit /b %EXIT_CODE%
|
|
||||||
|
|
||||||
:mainEnd
|
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
|
||||||
|
|
||||||
:omega
|
|
@ -1,2 +0,0 @@
|
|||||||
rootProject.name = 'androidExportReader'
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
|||||||
package com.blackforestbytes;
|
|
||||||
|
|
||||||
import de.ralleytn.simple.json.JSONArray;
|
|
||||||
import de.ralleytn.simple.json.JSONFormatter;
|
|
||||||
import de.ralleytn.simple.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.ObjectInputStream;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.nio.file.FileSystems;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class Main {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static void main(String[] args) {
|
|
||||||
if (args.length != 1) {
|
|
||||||
System.err.println("call with ./androidExportConvert scn_export.dat");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
var path = FileSystems.getDefault().getPath(args[0]).normalize().toAbsolutePath().toUri().toURL();
|
|
||||||
|
|
||||||
ObjectInputStream stream = new ObjectInputStream(path.openStream());
|
|
||||||
|
|
||||||
Map<String, ?> d1 = new HashMap<>((Map<String, ?>)stream.readObject());
|
|
||||||
Map<String, ?> d2 = new HashMap<>((Map<String, ?>)stream.readObject());
|
|
||||||
Map<String, ?> d3 = new HashMap<>((Map<String, ?>)stream.readObject());
|
|
||||||
Map<String, ?> d4 = new HashMap<>((Map<String, ?>)stream.readObject());
|
|
||||||
|
|
||||||
stream.close();
|
|
||||||
|
|
||||||
JSONObject root = new JSONObject();
|
|
||||||
|
|
||||||
var subConfig = new JSONObject();
|
|
||||||
var subIAB = new JSONArray();
|
|
||||||
var subCMessageList = new JSONArray();
|
|
||||||
var subAcks = new JSONArray();
|
|
||||||
var subQueryLog = new JSONArray();
|
|
||||||
|
|
||||||
for (Map.Entry<String, ?> entry : d1.entrySet())
|
|
||||||
{
|
|
||||||
if (entry.getValue() instanceof String) subConfig.put(entry.getKey(), (String)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Boolean) subConfig.put(entry.getKey(), (Boolean)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Float) subConfig.put(entry.getKey(), (Float)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Integer) subConfig.put(entry.getKey(), (Integer)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Long) subConfig.put(entry.getKey(), (Long)entry.getValue());
|
|
||||||
if (entry.getValue() instanceof Set<?>) subConfig.put(entry.getKey(), ((Set<String>)entry.getValue()).toArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < (Integer)d2.get("c"); i++) {
|
|
||||||
var obj = new JSONObject();
|
|
||||||
obj.put("key", d2.get("["+i+"]->key"));
|
|
||||||
obj.put("value", d2.get("["+i+"]->value"));
|
|
||||||
subIAB.add(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < (Integer)d3.get("message_count"); i++) {
|
|
||||||
if (d3.get("message["+i+"].scnid") == null)
|
|
||||||
throw new Exception("ONF");
|
|
||||||
|
|
||||||
var obj = new JSONObject();
|
|
||||||
obj.put("timestamp", d3.get("message["+i+"].timestamp"));
|
|
||||||
obj.put("title", d3.get("message["+i+"].title"));
|
|
||||||
obj.put("content", d3.get("message["+i+"].content"));
|
|
||||||
obj.put("priority", d3.get("message["+i+"].priority"));
|
|
||||||
obj.put("scnid", d3.get("message["+i+"].scnid"));
|
|
||||||
subCMessageList.add(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
subAcks.addAll(((Set<String>)d3.get("acks")).stream().map(p -> Long.decode("0x"+p)).toList());
|
|
||||||
|
|
||||||
for (int i = 0; i < (Integer)d4.get("history_count"); i++) {
|
|
||||||
if (d4.get("message["+(i+1000)+"].Name") == null)
|
|
||||||
throw new Exception("ONF");
|
|
||||||
|
|
||||||
var obj = new JSONObject();
|
|
||||||
obj.put("Level", d4.get("message["+(i+1000)+"].Level"));
|
|
||||||
obj.put("Timestamp", d4.get("message["+(i+1000)+"].Timestamp"));
|
|
||||||
obj.put("Name", d4.get("message["+(i+1000)+"].Name"));
|
|
||||||
obj.put("URL", d4.get("message["+(i+1000)+"].URL"));
|
|
||||||
obj.put("Response", d4.get("message["+(i+1000)+"].Response"));
|
|
||||||
obj.put("ResponseCode", d4.get("message["+(i+1000)+"].ResponseCode"));
|
|
||||||
obj.put("ExceptionString", d4.get("message["+(i+1000)+"].ExceptionString"));
|
|
||||||
subQueryLog.add(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
root.put("config", subConfig);
|
|
||||||
root.put("iab", subIAB);
|
|
||||||
root.put("cmessagelist", subCMessageList);
|
|
||||||
root.put("acks", subAcks);
|
|
||||||
root.put("querylog", subQueryLog);
|
|
||||||
|
|
||||||
System.out.println(new JSONFormatter().format(root.toString()));
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
BIN
data/icon.ora
BIN
data/phone.ora
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $title
|
|
||||||
* @param string $content
|
|
||||||
* @param int $priority
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function sendSCN($title, $content, $priority) {
|
|
||||||
global $config;
|
|
||||||
|
|
||||||
$data =
|
|
||||||
[
|
|
||||||
'user_id' => '', //TODO set your userid
|
|
||||||
'user_key' => '', //TODO set your userkey
|
|
||||||
'title' => $title,
|
|
||||||
'content' => $content,
|
|
||||||
'priority' => $priority,
|
|
||||||
];
|
|
||||||
|
|
||||||
$ch = curl_init();
|
|
||||||
|
|
||||||
curl_setopt($ch, CURLOPT_URL, "https://simplecloudnotifier.blackforestbytes.com/send.php");
|
|
||||||
curl_setopt($ch, CURLOPT_POST, 1);
|
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
|
|
||||||
$result = curl_exec($ch);
|
|
||||||
|
|
||||||
curl_close($ch);
|
|
||||||
if ($result === false) return false;
|
|
||||||
|
|
||||||
$json = json_decode($result, true);
|
|
||||||
return $json['success'];
|
|
||||||
}
|
|
@ -21,7 +21,6 @@ user_key="????????????????????????????????????????????????????????????????"
|
|||||||
|
|
||||||
title=$1
|
title=$1
|
||||||
content=""
|
content=""
|
||||||
sendtime=$(date +%s)
|
|
||||||
|
|
||||||
if [ "$#" -gt 1 ]; then
|
if [ "$#" -gt 1 ]; then
|
||||||
content=$2
|
content=$2
|
||||||
@ -38,7 +37,7 @@ usr_msg_id=$(uuidgen)
|
|||||||
while true ; do
|
while true ; do
|
||||||
|
|
||||||
curlresp=$(curl -s -o /dev/null -w "%{http_code}" \
|
curlresp=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
-d "user_id=$user_id" -d "user_key=$user_key" -d "title=$title" -d "timestamp=$sendtime" \
|
-d "user_id=$user_id" -d "user_key=$user_key" -d "title=$title" \
|
||||||
-d "content=$content" -d "priority=$priority" -d "msg_id=$usr_msg_id" \
|
-d "content=$content" -d "priority=$priority" -d "msg_id=$usr_msg_id" \
|
||||||
https://scn.blackforestbytes.com/send.php)
|
https://scn.blackforestbytes.com/send.php)
|
||||||
|
|
||||||
|
60
flutter/.gitignore
vendored
@ -1,60 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
*.keystore
|
|
||||||
|
|
||||||
firepit-log.txt
|
|
||||||
flutter_jank_*
|
|
||||||
|
|
||||||
_releases/*
|
|
||||||
|
|
||||||
|
|
||||||
#######################################################################################################################
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Miscellaneous
|
|
||||||
*.class
|
|
||||||
*.log
|
|
||||||
*.pyc
|
|
||||||
*.swp
|
|
||||||
.DS_Store
|
|
||||||
.atom/
|
|
||||||
.buildlog/
|
|
||||||
.history
|
|
||||||
.svn/
|
|
||||||
migrate_working_dir/
|
|
||||||
|
|
||||||
# IntelliJ related
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
*.iws
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# The .vscode folder contains launch configuration and tasks you configure in
|
|
||||||
# VS Code which you may wish to be included in version control, so this line
|
|
||||||
# is commented out by default.
|
|
||||||
#.vscode/
|
|
||||||
|
|
||||||
# Flutter/Dart/Pub related
|
|
||||||
**/doc/api/
|
|
||||||
**/ios/Flutter/.last_build_id
|
|
||||||
.dart_tool/
|
|
||||||
.flutter-plugins
|
|
||||||
.flutter-plugins-dependencies
|
|
||||||
.pub-cache/
|
|
||||||
.pub/
|
|
||||||
/build/
|
|
||||||
|
|
||||||
# Symbolication related
|
|
||||||
app.*.symbols
|
|
||||||
|
|
||||||
# Obfuscation related
|
|
||||||
app.*.map.json
|
|
||||||
|
|
||||||
# Android Studio will place build artifacts here
|
|
||||||
/android/app/debug
|
|
||||||
/android/app/profile
|
|
||||||
/android/app/release
|
|
||||||
|
|
||||||
/lib/git_stamp/
|
|
@ -1,45 +0,0 @@
|
|||||||
# This file tracks properties of this Flutter project.
|
|
||||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
|
||||||
#
|
|
||||||
# This file should be version controlled and should not be manually edited.
|
|
||||||
|
|
||||||
version:
|
|
||||||
revision: "41456452f29d64e8deb623a3c927524bcf9f111b"
|
|
||||||
channel: "stable"
|
|
||||||
|
|
||||||
project_type: app
|
|
||||||
|
|
||||||
# Tracks metadata for the flutter migrate command
|
|
||||||
migration:
|
|
||||||
platforms:
|
|
||||||
- platform: root
|
|
||||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
- platform: android
|
|
||||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
- platform: ios
|
|
||||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
- platform: linux
|
|
||||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
- platform: macos
|
|
||||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
- platform: web
|
|
||||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
- platform: windows
|
|
||||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
|
||||||
|
|
||||||
# User provided section
|
|
||||||
|
|
||||||
# List of Local paths (relative to this file) that should be
|
|
||||||
# ignored by the migrate tool.
|
|
||||||
#
|
|
||||||
# Files that are not part of the templates will be ignored by default.
|
|
||||||
unmanaged_files:
|
|
||||||
- 'lib/main.dart'
|
|
||||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
|
25
flutter/.vscode/launch.json
vendored
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "flutter",
|
|
||||||
"request": "launch",
|
|
||||||
"type": "dart"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "flutter (profile mode)",
|
|
||||||
"request": "launch",
|
|
||||||
"type": "dart",
|
|
||||||
"flutterMode": "profile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "flutter (release mode)",
|
|
||||||
"request": "launch",
|
|
||||||
"type": "dart",
|
|
||||||
"flutterMode": "release"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
# Setup
|
|
||||||
#
|
|
||||||
# flutter config --jdk-dir "/usr/lib/jvm/default-runtime/bin"
|
|
||||||
# sudo archlinux-java set java-17-openjdk
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# runs app locally (linux)
|
|
||||||
run-linux: gen
|
|
||||||
dart run build_runner build
|
|
||||||
_JAVA_OPTIONS="" flutter run -d linux
|
|
||||||
|
|
||||||
# runs app locally (web | not really supported)
|
|
||||||
run-web: gen
|
|
||||||
dart run build_runner build
|
|
||||||
_JAVA_OPTIONS="" flutter run -d chrome
|
|
||||||
|
|
||||||
# runs on android device (must have network adb enabled teh correct IP)
|
|
||||||
run-android: gen
|
|
||||||
ping -c1 10.10.10.177
|
|
||||||
adb connect 10.10.10.177:5555
|
|
||||||
flutter pub run build_runner build
|
|
||||||
_JAVA_OPTIONS="" flutter run -d 10.10.10.177:5555
|
|
||||||
|
|
||||||
install-release: gen
|
|
||||||
# Install on Pixel 7a
|
|
||||||
flutter build apk --release
|
|
||||||
flutter run --release -d 35221JEHN07157
|
|
||||||
|
|
||||||
build-release: gen
|
|
||||||
flutter build apk --release
|
|
||||||
flutter build appbundle --release
|
|
||||||
flutter build linux --release
|
|
||||||
|
|
||||||
test:
|
|
||||||
dart analyze
|
|
||||||
|
|
||||||
fix:
|
|
||||||
dart fix --apply
|
|
||||||
|
|
||||||
gen:
|
|
||||||
./_utils/inc_buildnum.sh
|
|
||||||
dart run build_runner build
|
|
||||||
dart run git_stamp git_stamp --build-type lite --limit 2
|
|
||||||
|
|
||||||
# run `make run` in another terminal (or another variant of flutter run)
|
|
||||||
autoreload:
|
|
||||||
@
|
|
||||||
@_utils/autoreload.sh
|
|
||||||
|
|
||||||
icons:
|
|
||||||
flutter pub run flutter_launcher_icons -f "flutter_launcher_icons.yaml"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
cd android && ./gradlew clean
|
|
||||||
flutter clean
|
|
||||||
|
|
||||||
# upgrade all packages (add --major-versions even updates across new major versions)
|
|
||||||
# https://docs.flutter.dev/release/upgrade
|
|
||||||
# upgrading flutter can be done via `flutter upgrade`: https://docs.flutter.dev/release/upgrade
|
|
||||||
# android/gradle updates should be done via androidStudio: https://docs.flutter.dev/release/breaking-changes/android-java-gradle-migration-guide
|
|
||||||
upgrade:
|
|
||||||
flutter upgrade
|
|
||||||
flutter pub upgrade
|
|
||||||
flutter doctor
|
|
||||||
|
|
||||||
aider:
|
|
||||||
aider --model gemini-2.5-pro --no-auto-commits --no-dirty-commits --test-cmd "flutter build linux" --auto-test --subtree-only
|
|
@ -1,17 +0,0 @@
|
|||||||
### Links
|
|
||||||
|
|
||||||
|
|
||||||
- https://pub.dev/packages/font_awesome_flutter
|
|
||||||
- https://fontawesome.com/search
|
|
||||||
|
|
||||||
- https://docs.flutter.dev/ui/widgets
|
|
||||||
- https://docs.flutter.dev/ui/widgets/material
|
|
||||||
|
|
||||||
- https://docs.flutter.dev/cookbook/persistence/sqlite
|
|
||||||
- https://pub.dev/packages/sqflite
|
|
||||||
- https://pub.dev/packages/sqflite_common_ffi
|
|
||||||
|
|
||||||
- https://pub.dev/packages/hive
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
|||||||
|
|
||||||
# TODO
|
|
||||||
|
|
||||||
- [x] Message List
|
|
||||||
* [x] CRUD
|
|
||||||
- [x] Message Big-View
|
|
||||||
- [x] Search/Filter Messages
|
|
||||||
- [x] Channel List
|
|
||||||
* [x] Show subs
|
|
||||||
* [x] CRUD
|
|
||||||
* [x] what about unsubbed foreign channels? - thex should still be visible (or should they, do i still get the messages?)
|
|
||||||
- [x] Sub List
|
|
||||||
* [x] Sub/Unsub/Accept/Deny
|
|
||||||
- [x] Debug List (Show logs, requests)
|
|
||||||
- [x] Key List
|
|
||||||
* [x] CRUD
|
|
||||||
- [x] Auto R-only key for admin, use for QR+link+send
|
|
||||||
- [ ] settings
|
|
||||||
- [?] notifications
|
|
||||||
- [?] push navigation stack
|
|
||||||
- [/] read + migrate old SharedPrefs (or not? - who uses SCN even??)
|
|
||||||
- [x] Account-Page
|
|
||||||
- [x] Logout
|
|
||||||
- [x] Send-page
|
|
||||||
|
|
||||||
- [ ] Still @ERROR on scn-init, but no logs? - better persist error (write in SharedPrefs at error_$date=txt ?), also perhaps print first error line in scn-init notification?
|
|
||||||
|
|
||||||
- [x] fix time format (in message-list, in card, top right) - midnight is shown as "24:05" instead of "00:05" - thats weird
|
|
||||||
|
|
||||||
- [x] Add scrollbar
|
|
||||||
-> https://api.flutter.dev/flutter/material/Scrollbar-class.html
|
|
||||||
|
|
||||||
- [x] you cant unsubscribe from foreign channel without completely loosing subscription.
|
|
||||||
perhaps subscriptions should have two cofirmed bool (both must be true to receive messages): confirmed-owner && confirmed-subscriber
|
|
||||||
Then the subscriber can unconfirm his half - without loosing the owner confirmation
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
# TODO iOS specific
|
|
||||||
|
|
||||||
- [ ] payment / pro
|
|
||||||
- [ ] show notifiactions (foreground/background/etc)
|
|
||||||
- [ ] handle click-on-notifications should open message
|
|
||||||
- [ ] share message
|
|
||||||
- [ ] scan QR
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
# TODO Server
|
|
||||||
|
|
||||||
- [ ] Switch server to sq style from faby
|
|
||||||
- [ ] switch from mattn to go-sqlite
|
|
||||||
- [ ] Single struct for model/db/json
|
|
||||||
- [ ] use ginext
|
|
||||||
- [ ] use sq.Query | sq.Update | sq.InsertAndQuery | ....
|
|
||||||
- [ ] sq.DBOptions - enable CommentTrimmer and DefaultConverter
|
|
||||||
- [ ] run unit-tests...
|
|
||||||
- [ ] Copy db.Migrate code
|
|
||||||
|
|
||||||
- [ ] Disable compat | remove code
|
|
||||||
- [x] compat message title
|
|
||||||
- [ ] ...
|
|
||||||
- [ ] RWLock directly in go - prevent/reduce db-locked exception
|
|
@ -1,57 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# shellcheck disable=SC2002 # disable useless-cat warning
|
|
||||||
|
|
||||||
set -o nounset # disallow usage of unset vars ( set -u )
|
|
||||||
#set -o errexit # Exit immediately if a pipeline returns non-zero. ( set -e )
|
|
||||||
#set -o errtrace # Allow the above trap be inherited by all functions in the script. ( set -E )
|
|
||||||
set -o pipefail # Return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status
|
|
||||||
IFS=$'\n\t' # Set $IFS to only newline and tab.
|
|
||||||
|
|
||||||
# shellcheck disable=SC2034
|
|
||||||
cr=$'\n'
|
|
||||||
|
|
||||||
function black() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[30m$1\\x1B[0m"; else echo "$1"; fi }
|
|
||||||
function red() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[31m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function green() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[32m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function yellow(){ if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[33m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function blue() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[34m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function purple(){ if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[35m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function cyan() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[36m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function white() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[37m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
|
|
||||||
# cd "$(dirname "$0")" || exit 1 # (optionally) cd to directory where script is located
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pids="$( pgrep -f 'flutter_tools\.[s]napshot run' || echo '' )"
|
|
||||||
|
|
||||||
if [ -z "$pids" ]; then
|
|
||||||
red "No [flutter run] process found - exiting"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
trap 'echo "reseived SIGNAL<EXIT> - exiting"; jobs -p | xargs kill ; exit 0' EXIT
|
|
||||||
trap 'echo "reseived SIGNAL<SIGINT> - exiting"; jobs -p | xargs kill ; exit 0' SIGINT
|
|
||||||
trap 'echo "reseived SIGNAL<SIGTERM> - exiting"; jobs -p | xargs kill ; exit 0' SIGTERM
|
|
||||||
trap 'echo "reseived SIGNAL<SIGQUIT> - exiting"; jobs -p | xargs kill ; exit 0' SIGQUIT
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
while IFS= read -r pid; do
|
|
||||||
blue "Listening for changes in lib/ directory - sending signals to ${pid}..."
|
|
||||||
done <<< "$pids"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
while IFS= read -r pid; do
|
|
||||||
{
|
|
||||||
while true; do
|
|
||||||
find lib/ -name '*.dart' | entr -d -p sh -c "echo 'File(s) changed - Sending SIGUSR to $pid' ; kill -USR1 $pid";
|
|
||||||
yellow 'File list changed - restart';
|
|
||||||
done
|
|
||||||
} &
|
|
||||||
done <<< "$pids"
|
|
||||||
|
|
||||||
wait # wait for all background jobs to finish
|
|
||||||
|
|
||||||
echo "DONE."
|
|
@ -1,41 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# shellcheck disable=SC2002 # disable useless-cat warning
|
|
||||||
|
|
||||||
set -o nounset # disallow usage of unset vars ( set -u )
|
|
||||||
set -o errexit # Exit immediately if a pipeline returns non-zero. ( set -e )
|
|
||||||
set -o errtrace # Allow the above trap be inherited by all functions in the script. ( set -E )
|
|
||||||
set -o pipefail # Return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status
|
|
||||||
IFS=$'\n\t' # Set $IFS to only newline and tab.
|
|
||||||
|
|
||||||
# shellcheck disable=SC2034
|
|
||||||
cr=$'\n'
|
|
||||||
|
|
||||||
function black() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[30m$1\\x1B[0m"; else echo "$1"; fi }
|
|
||||||
function red() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[31m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function green() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[32m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function yellow(){ if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[33m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function blue() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[34m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function purple(){ if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[35m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function cyan() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[36m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
function white() { if [ -t 1 ] && [ -n "$(tput colors)" ] && [ "$(tput colors)" -ge 8 ]; then echo -e "\\x1B[37m$1\\x1B[0m"; else echo "$1"; fi; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
path_to_pubspec="$(dirname "$0")/../pubspec.yaml"
|
|
||||||
current_version=$(awk '/^version:/ {print $2}' $path_to_pubspec)
|
|
||||||
current_version_without_build=$(echo "$current_version" | sed 's/\+.*//')
|
|
||||||
|
|
||||||
gitcount="$(git log | grep "^commit" | wc -l | xargs)"
|
|
||||||
new_version="$current_version_without_build+$gitcount"
|
|
||||||
|
|
||||||
echo "Setting pubspec.yaml version $current_version to $new_version"
|
|
||||||
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
||||||
# macOS sed (requires a space after -i)
|
|
||||||
sed -i '' -e "s/version: $current_version/version: $new_version/g" $path_to_pubspec
|
|
||||||
else
|
|
||||||
# GNU sed (requires no space after -i)
|
|
||||||
sed -i'' -e "s/version: $current_version/version: $new_version/g" $path_to_pubspec
|
|
||||||
fi
|
|
@ -1,117 +0,0 @@
|
|||||||
|
|
||||||
include:
|
|
||||||
- package:lints/recommended.yaml
|
|
||||||
- package:flutter_lints/flutter.yaml
|
|
||||||
|
|
||||||
linter:
|
|
||||||
|
|
||||||
|
|
||||||
rules:
|
|
||||||
always_use_package_imports: true,
|
|
||||||
avoid_empty_else: true,
|
|
||||||
avoid_returning_null_for_future: true,
|
|
||||||
avoid_type_to_string: true,
|
|
||||||
avoid_types_as_parameter_names: true,
|
|
||||||
avoid_web_libraries_in_flutter: true,
|
|
||||||
collection_methods_unrelated_type: true,
|
|
||||||
discarded_futures: true,
|
|
||||||
empty_statements: true,
|
|
||||||
hash_and_equals: true,
|
|
||||||
implicit_reopen: true,
|
|
||||||
invalid_case_patterns: true,
|
|
||||||
invariant_booleans: true,
|
|
||||||
no_duplicate_case_values: true,
|
|
||||||
no_logic_in_create_state: true,
|
|
||||||
no_self_assignments: true,
|
|
||||||
no_wildcard_variable_uses: true,
|
|
||||||
prefer_void_to_null: true,
|
|
||||||
unnecessary_statements: true,
|
|
||||||
valid_regexps: true,
|
|
||||||
always_declare_return_types: true,
|
|
||||||
always_put_control_body_on_new_line: true,
|
|
||||||
always_specify_types: true,
|
|
||||||
annotate_overrides: true,
|
|
||||||
annotate_redeclares: true,
|
|
||||||
avoid_annotating_with_dynamic: true,
|
|
||||||
avoid_function_literals_in_foreach_calls: true,
|
|
||||||
avoid_init_to_null: true,
|
|
||||||
avoid_null_checks_in_equality_operators: true,
|
|
||||||
avoid_renaming_method_parameters: true,
|
|
||||||
avoid_return_types_on_setters: true,
|
|
||||||
avoid_returning_null: true,
|
|
||||||
avoid_returning_null_for_void: true,
|
|
||||||
avoid_returning_this: true,
|
|
||||||
avoid_shadowing_type_parameters: true,
|
|
||||||
avoid_single_cascade_in_expression_statements: true,
|
|
||||||
avoid_unnecessary_containers: true,
|
|
||||||
avoid_unused_constructor_parameters: true,
|
|
||||||
avoid_void_async: true,
|
|
||||||
await_only_futures: true,
|
|
||||||
camel_case_extensions: true,
|
|
||||||
camel_case_types: true,
|
|
||||||
cast_nullable_to_non_nullable: true,
|
|
||||||
constant_identifier_names: true,
|
|
||||||
empty_catches: true,
|
|
||||||
eol_at_end_of_file: true,
|
|
||||||
exhaustive_cases: true,
|
|
||||||
file_names: true,
|
|
||||||
no_literal_bool_comparisons: true,
|
|
||||||
null_check_on_nullable_type_parameter: true,
|
|
||||||
null_closures: true,
|
|
||||||
overridden_fields: true,
|
|
||||||
prefer_adjacent_string_concatenation: true,
|
|
||||||
prefer_collection_literals: true,
|
|
||||||
prefer_conditional_assignment: true,
|
|
||||||
prefer_const_constructors: true,
|
|
||||||
prefer_const_constructors_in_immutables: true,
|
|
||||||
prefer_const_declarations: true,
|
|
||||||
prefer_const_literals_to_create_immutables: true,
|
|
||||||
prefer_contains: true,
|
|
||||||
prefer_final_fields: true,
|
|
||||||
prefer_for_elements_to_map_fromIterable: true,
|
|
||||||
prefer_function_declarations_over_variables: true,
|
|
||||||
prefer_generic_function_type_aliases: true,
|
|
||||||
prefer_if_null_operators: true,
|
|
||||||
prefer_initializing_formals: true,
|
|
||||||
prefer_inlined_adds: true,
|
|
||||||
prefer_interpolation_to_compose_strings: true,
|
|
||||||
prefer_is_empty: true,
|
|
||||||
prefer_is_not_empty: true,
|
|
||||||
prefer_is_not_operator: true,
|
|
||||||
prefer_iterable_whereType: true,
|
|
||||||
prefer_null_aware_operators: true,
|
|
||||||
prefer_spread_collections: true,
|
|
||||||
prefer_typing_uninitialized_variables: true,
|
|
||||||
provide_deprecation_message: true,
|
|
||||||
recursive_getters: true,
|
|
||||||
sized_box_for_whitespace: true,
|
|
||||||
type_init_formals: true,
|
|
||||||
type_literal_in_constant_pattern: true,
|
|
||||||
unnecessary_const: true,
|
|
||||||
unnecessary_constructor_name: true,
|
|
||||||
unnecessary_getters_setters: true,
|
|
||||||
unnecessary_late: true,
|
|
||||||
unnecessary_new: true,
|
|
||||||
unnecessary_null_aware_assignments: true,
|
|
||||||
unnecessary_null_in_if_null_operators: true,
|
|
||||||
unnecessary_nullable_for_final_variable_declarations: true,
|
|
||||||
unnecessary_overrides: true,
|
|
||||||
unnecessary_string_escapes: true,
|
|
||||||
unnecessary_string_interpolations: true,
|
|
||||||
unnecessary_this: true,
|
|
||||||
unnecessary_to_list_in_spreads: true,
|
|
||||||
use_full_hex_values_for_flutter_colors: true,
|
|
||||||
use_function_type_syntax_for_parameters: true,
|
|
||||||
use_rethrow_when_possible: true,
|
|
||||||
use_string_in_part_of_directives: true,
|
|
||||||
use_super_parameters: true,
|
|
||||||
void_checks: true,
|
|
||||||
depend_on_referenced_packages: true,
|
|
||||||
package_names: true,
|
|
||||||
secure_pubspec_urls: true,
|
|
||||||
|
|
||||||
analyzer:
|
|
||||||
language:
|
|
||||||
strict-casts: true
|
|
||||||
strict-inference: true
|
|
||||||
strict-raw-types: true
|
|
17
flutter/android/.gitignore
vendored
@ -1,17 +0,0 @@
|
|||||||
gradle-wrapper.jar
|
|
||||||
/.gradle
|
|
||||||
/captures/
|
|
||||||
/gradlew
|
|
||||||
/gradlew.bat
|
|
||||||
/local.properties
|
|
||||||
GeneratedPluginRegistrant.java
|
|
||||||
|
|
||||||
# Remember to never publicly share your keystore.
|
|
||||||
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
|
||||||
key.properties
|
|
||||||
**/*.keystore
|
|
||||||
**/*.jks
|
|
||||||
|
|
||||||
build/
|
|
||||||
|
|
||||||
app/.cxx/
|
|
@ -1,87 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "com.android.application"
|
|
||||||
// START: FlutterFire Configuration
|
|
||||||
id 'com.google.gms.google-services'
|
|
||||||
// END: FlutterFire Configuration
|
|
||||||
id "kotlin-android"
|
|
||||||
id "dev.flutter.flutter-gradle-plugin"
|
|
||||||
}
|
|
||||||
|
|
||||||
def localProperties = new Properties()
|
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
|
||||||
if (localPropertiesFile.exists()) {
|
|
||||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
|
||||||
localProperties.load(reader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
|
||||||
if (flutterVersionCode == null) {
|
|
||||||
flutterVersionCode = '1'
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
|
||||||
if (flutterVersionName == null) {
|
|
||||||
flutterVersionName = '1.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
def keystoreProperties = new Properties()
|
|
||||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
|
||||||
if (keystorePropertiesFile.exists()) {
|
|
||||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace "com.blackforestbytes.simplecloudnotifier"
|
|
||||||
compileSdkVersion flutter.compileSdkVersion
|
|
||||||
ndkVersion "27.0.12077973" // should be `flutter.ndkVersion` - but some plugins need 27, even though flutter still has the default value of 26 (flutter 3.29 | 2025-04-12)
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
coreLibraryDesugaringEnabled true
|
|
||||||
sourceCompatibility JavaVersion.VERSION_17
|
|
||||||
targetCompatibility JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = '17'
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main.java.srcDirs += 'src/main/kotlin'
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId "com.blackforestbytes.simplecloudnotifier"
|
|
||||||
minSdkVersion flutter.minSdkVersion
|
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
|
||||||
versionCode flutterVersionCode.toInteger()
|
|
||||||
versionName flutterVersionName
|
|
||||||
multiDexEnabled true
|
|
||||||
}
|
|
||||||
|
|
||||||
signingConfigs {
|
|
||||||
release {
|
|
||||||
keyAlias keystoreProperties['keyAlias']
|
|
||||||
keyPassword keystoreProperties['keyPassword']
|
|
||||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
|
||||||
storePassword keystoreProperties['storePassword']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
signingConfig signingConfigs.release
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flutter {
|
|
||||||
source '../..'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'androidx.window:window:1.0.0'
|
|
||||||
implementation 'androidx.window:window-java:1.0.0'
|
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"project_info": {
|
|
||||||
"project_number": "232728961679",
|
|
||||||
"firebase_url": "https://simplecloudnotifier-ea7ef.firebaseio.com",
|
|
||||||
"project_id": "simplecloudnotifier-ea7ef",
|
|
||||||
"storage_bucket": "simplecloudnotifier-ea7ef.appspot.com"
|
|
||||||
},
|
|
||||||
"client": [
|
|
||||||
{
|
|
||||||
"client_info": {
|
|
||||||
"mobilesdk_app_id": "1:232728961679:android:23c75317f79601c9",
|
|
||||||
"android_client_info": {
|
|
||||||
"package_name": "com.blackforestbytes.simplecloudnotifier"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "232728961679-o7gig6f684mp1l1ok7719v3jf3csejc1.apps.googleusercontent.com",
|
|
||||||
"client_type": 1,
|
|
||||||
"android_info": {
|
|
||||||
"package_name": "com.blackforestbytes.simplecloudnotifier",
|
|
||||||
"certificate_hash": "3bcafbd39256422f0cb51fd446a228c26543afb4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client_id": "232728961679-t1h2eo5keha2lrvhsvdr5kgbkbfkja0o.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"api_key": [
|
|
||||||
{
|
|
||||||
"current_key": "AIzaSyBasR6JLAjM5Ut0rPb0euE_9DdDoTkcvKQ"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"services": {
|
|
||||||
"appinvite_service": {
|
|
||||||
"other_platform_oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "232728961679-f2951kg24ngsttkhd96qhcr8j3lc8nnk.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client_id": "232728961679-bsbtc6orskaqafc8gtsuqia53f6ree48.apps.googleusercontent.com",
|
|
||||||
"client_type": 2,
|
|
||||||
"ios_info": {
|
|
||||||
"bundle_id": "com.blackforestbytes.SimpleCloudNotifier",
|
|
||||||
"app_store_id": "6455594868"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"configuration_version": "1"
|
|
||||||
}
|
|
27
flutter/android/app/proguard-rules.pro
vendored
@ -1,27 +0,0 @@
|
|||||||
## Gson rules
|
|
||||||
# Gson uses generic type information stored in a class file when working with fields. Proguard
|
|
||||||
# removes such information by default, so configure it to keep all of it.
|
|
||||||
-keepattributes Signature
|
|
||||||
|
|
||||||
# For using GSON @Expose annotation
|
|
||||||
-keepattributes *Annotation*
|
|
||||||
|
|
||||||
# Gson specific classes
|
|
||||||
-dontwarn sun.misc.**
|
|
||||||
#-keep class com.google.gson.stream.** { *; }
|
|
||||||
|
|
||||||
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
|
|
||||||
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
|
|
||||||
-keep class * extends com.google.gson.TypeAdapter
|
|
||||||
-keep class * implements com.google.gson.TypeAdapterFactory
|
|
||||||
-keep class * implements com.google.gson.JsonSerializer
|
|
||||||
-keep class * implements com.google.gson.JsonDeserializer
|
|
||||||
|
|
||||||
# Prevent R8 from leaving Data object members always null
|
|
||||||
-keepclassmembers,allowobfuscation class * {
|
|
||||||
@com.google.gson.annotations.SerializedName <fields>;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
|
|
||||||
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
|
|
||||||
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
|
|
@ -1,7 +0,0 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<!-- The INTERNET permission is required for development. Specifically,
|
|
||||||
the Flutter tool needs it to communicate with the running application
|
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
|
||||||
-->
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
</manifest>
|
|
@ -1,43 +0,0 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
|
||||||
<uses-permission android:name="com.android.vending.BILLING" />
|
|
||||||
|
|
||||||
<application
|
|
||||||
android:label="simplecloudnotifier"
|
|
||||||
android:name="${applicationName}"
|
|
||||||
android:icon="@mipmap/launcher_icon">
|
|
||||||
<activity
|
|
||||||
android:name=".MainActivity"
|
|
||||||
android:exported="true"
|
|
||||||
android:launchMode="singleTop"
|
|
||||||
android:theme="@style/LaunchTheme"
|
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
|
||||||
android:hardwareAccelerated="true"
|
|
||||||
android:windowSoftInputMode="adjustResize">
|
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
|
||||||
the Android process has started. This theme is visible to the user
|
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
|
||||||
to determine the Window background behind the Flutter UI. -->
|
|
||||||
<meta-data
|
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
|
||||||
android:resource="@style/NormalTheme"
|
|
||||||
/>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
|
|
||||||
|
|
||||||
<!-- Don't delete the meta-data below.
|
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
|
||||||
<meta-data
|
|
||||||
android:name="flutterEmbedding"
|
|
||||||
android:value="2" />
|
|
||||||
</application>
|
|
||||||
</manifest>
|
|
@ -1,6 +0,0 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier
|
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
|
||||||
}
|
|
Before Width: | Height: | Size: 472 B |
Before Width: | Height: | Size: 320 B |
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Modify this file to customize your launch splash screen -->
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:drawable="?android:colorBackground" />
|
|
||||||
|
|
||||||
<!-- You can insert your own image assets here -->
|
|
||||||
<!-- <item>
|
|
||||||
<bitmap
|
|
||||||
android:gravity="center"
|
|
||||||
android:src="@mipmap/launch_image" />
|
|
||||||
</item> -->
|
|
||||||
</layer-list>
|
|
@ -1,34 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportHeight="108"
|
|
||||||
android:viewportWidth="108">
|
|
||||||
<path
|
|
||||||
android:fillType="evenOdd"
|
|
||||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
|
||||||
android:strokeColor="#00000000"
|
|
||||||
android:strokeWidth="1">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="78.5885"
|
|
||||||
android:endY="90.9159"
|
|
||||||
android:startX="48.7653"
|
|
||||||
android:startY="61.0927"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#44000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:fillType="nonZero"
|
|
||||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
|
||||||
android:strokeColor="#00000000"
|
|
||||||
android:strokeWidth="1" />
|
|
||||||
</vector>
|
|
Before Width: | Height: | Size: 551 B |
Before Width: | Height: | Size: 949 B |
Before Width: | Height: | Size: 1.0 KiB |
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Modify this file to customize your launch splash screen -->
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:drawable="@android:color/white" />
|
|
||||||
|
|
||||||
<!-- You can insert your own image assets here -->
|
|
||||||
<!-- <item>
|
|
||||||
<bitmap
|
|
||||||
android:gravity="center"
|
|
||||||
android:src="@mipmap/launch_image" />
|
|
||||||
</item> -->
|
|
||||||
</layer-list>
|
|
Before Width: | Height: | Size: 544 B |
Before Width: | Height: | Size: 5.3 KiB |