1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-19 22:49:08 -05:00

Migrate to firebase (#196)

This commit is contained in:
Mikołaj Pich 2018-12-14 00:20:54 +01:00 committed by Rafał Borcz
parent 229bfe8d22
commit 5ee979447f
37 changed files with 255 additions and 151 deletions

View File

@ -113,7 +113,7 @@ jobs:
adb shell input keyevent 82 adb shell input keyevent 82
- run: - run:
name: Run instrumented tests name: Run instrumented tests
command: ./gradlew clean createDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex -PdisableCrashlytics command: ./gradlew clean createDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
- run: - run:
name: Collect logs from emulator name: Collect logs from emulator
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt command: adb logcat -d > ./app/build/reports/logcat_emulator.txt
@ -153,11 +153,12 @@ jobs:
- run: - run:
name: Decrypt keys name: Decrypt keys
command: | command: |
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg
openssl aes-256-cbc -d -in ./app/key-encrypted.p12 -k $ENCRYPT_KEY >> ./app/key.p12 openssl aes-256-cbc -d -in ./app/key-encrypted.p12 -k $ENCRYPT_KEY >> ./app/key.p12
openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks
- run: - run:
name: Publish release name: Publish release
command: ./gradlew publishRelease --no-daemon --stacktrace --console=plain -PdisablePreDex command: ./gradlew publishRelease --no-daemon --stacktrace --console=plain -PenableCrashlytics -PdisablePreDex
workflows: workflows:
version: 2 version: 2

View File

@ -49,17 +49,18 @@ script:
- fossa --no-ansi || true - fossa --no-ansi || true
- ./gradlew lint -x fabricGenerateResourcesRelease --stacktrace --daemon - ./gradlew lint -x fabricGenerateResourcesRelease --stacktrace --daemon
- ./gradlew test -x fabricGenerateResourcesRelease --stacktrace --daemon - ./gradlew test -x fabricGenerateResourcesRelease --stacktrace --daemon
- ./gradlew createDebugCoverageReport --stacktrace -PdisableCrashlytics --daemon - ./gradlew createDebugCoverageReport --stacktrace --daemon
- ./gradlew jacocoTestReport --stacktrace --daemon - ./gradlew jacocoTestReport --stacktrace --daemon
- if [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" == "master" ]; then - if [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" == "master" ]; then
git fetch --unshallow; git fetch --unshallow;
./gradlew sonarqube -x test -x lint -x fabricGenerateResourcesRelease -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} -PdisableCrashlytics --stacktrace --daemon; ./gradlew sonarqube -x test -x lint -x fabricGenerateResourcesRelease -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} --stacktrace --daemon;
fi fi
- | - |
if [ $TRAVIS_TAG ]; then if [ $TRAVIS_TAG ]; then
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg;
openssl aes-256-cbc -d -in ./app/key-encrypted.p12 -k $ENCRYPT_KEY >> ./app/key.p12; openssl aes-256-cbc -d -in ./app/key-encrypted.p12 -k $ENCRYPT_KEY >> ./app/key.p12;
openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks; openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks;
./gradlew publishRelease --stacktrace; ./gradlew publishRelease -PenableCrashlytics --stacktrace;
fi fi
after_success: after_success:

View File

@ -7,8 +7,6 @@ apply plugin: 'com.github.triplet.play'
apply from: 'jacoco.gradle' apply from: 'jacoco.gradle'
apply from: 'sonarqube.gradle' apply from: 'sonarqube.gradle'
def fabricApiKey = System.getenv("FABRIC_API_KEY") ?: "null"
android { android {
compileSdkVersion 28 compileSdkVersion 28
buildToolsVersion '28.0.3' buildToolsVersion '28.0.3'
@ -31,7 +29,7 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
playAccountConfig = playAccountConfigs.defaultAccountConfig playAccountConfig = playAccountConfigs.defaultAccountConfig
manifestPlaceholders = [fabricApiKey: fabricApiKey] manifestPlaceholders = [crashlytics_enabled: project.hasProperty("enableCrashlytics")]
} }
signingConfigs { signingConfigs {
@ -45,17 +43,17 @@ android {
buildTypes { buildTypes {
release { release {
buildConfigField "boolean", "FABRIC_ENABLED", "true" buildConfigField "boolean", "CRASHLYTICS_ENABLED", "true"
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release signingConfig signingConfigs.release
} }
debug { debug {
buildConfigField "boolean", "FABRIC_ENABLED", fabricApiKey != "null" && !project.hasProperty("disableCrashlytics") ? "true" : "false" buildConfigField "boolean", "CRASHLYTICS_ENABLED", project.hasProperty("enableCrashlytics") ? "true" : "false"
applicationIdSuffix ".dev" applicationIdSuffix ".dev"
versionNameSuffix "-dev" versionNameSuffix "-dev"
testCoverageEnabled = true testCoverageEnabled = true
ext.enableCrashlytics = fabricApiKey != "null" && !project.hasProperty("disableCrashlytics") ext.enableCrashlytics = project.hasProperty("enableCrashlytics")
multiDexKeepProguard file('proguard-multidex-rules.pro') multiDexKeepProguard file('proguard-multidex-rules.pro')
} }
} }
@ -81,7 +79,7 @@ configurations.all {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation('com.github.wulkanowy:api:6a73b0e') { exclude module: "threetenbp" } implementation('com.github.wulkanowy:api:88e279e') { exclude module: "threetenbp" }
implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.appcompat:appcompat:1.0.2" implementation "androidx.appcompat:appcompat:1.0.2"
@ -115,12 +113,9 @@ dependencies {
implementation "com.jakewharton.timber:timber:4.7.1" implementation "com.jakewharton.timber:timber:4.7.1"
implementation "at.favre.lib:slf4j-timber:1.0.1" implementation "at.favre.lib:slf4j-timber:1.0.1"
implementation("com.crashlytics.sdk.android:crashlytics:2.9.7@aar") {
transitive = true implementation 'com.google.firebase:firebase-core:16.0.6'
} implementation 'com.crashlytics.sdk.android:crashlytics:2.9.7'
implementation("com.crashlytics.sdk.android:answers:1.4.5@aar") {
transitive = true
}
debugImplementation "com.amitshekhar.android:debug-db:1.0.4" debugImplementation "com.amitshekhar.android:debug-db:1.0.4"
@ -135,3 +130,5 @@ dependencies {
androidTestImplementation "org.mockito:mockito-android:2.23.4" androidTestImplementation "org.mockito:mockito-android:2.23.4"
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
} }
apply plugin: 'com.google.gms.google-services'

View File

@ -0,0 +1,42 @@
{
"project_info": {
"project_number": "",
"firebase_url": "",
"project_id": "",
"storage_bucket": ""
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:1091101852179:android:b558a25f65d088b1",
"android_client_info": {
"package_name": "io.github.wulkanowy.dev"
}
},
"oauth_client": [
{
"client_id": "",
"client_type": 3
}
],
"api_key": [
{
"current_key": ""
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}

Binary file not shown.

View File

@ -63,7 +63,7 @@
</receiver> </receiver>
<meta-data <meta-data
android:name="io.fabric.ApiKey" android:name="firebase_crashlytics_collection_enabled"
android:value="${fabricApiKey}" /> android:value="${crashlytics_enabled}" />
</application> </application>
</manifest> </manifest>

View File

@ -4,7 +4,6 @@ import android.content.Context
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.multidex.MultiDex import androidx.multidex.MultiDex
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.core.CrashlyticsCore import com.crashlytics.android.core.CrashlyticsCore
import com.jakewharton.threetenabp.AndroidThreeTen import com.jakewharton.threetenabp.AndroidThreeTen
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
@ -45,8 +44,7 @@ class WulkanowyApp : DaggerApplication() {
private fun initializeFabric() { private fun initializeFabric() {
Fabric.with(Fabric.Builder(this).kits( Fabric.with(Fabric.Builder(this).kits(
Crashlytics.Builder().core(CrashlyticsCore.Builder().disabled(!BuildConfig.FABRIC_ENABLED).build()).build(), Crashlytics.Builder().core(CrashlyticsCore.Builder().disabled(!BuildConfig.CRASHLYTICS_ENABLED).build()).build()
Answers()
).debuggable(BuildConfig.DEBUG).build()) ).debuggable(BuildConfig.DEBUG).build())
Timber.plant(CrashlyticsTree()) Timber.plant(CrashlyticsTree())
} }

View File

@ -14,6 +14,7 @@ class ApiHelper @Inject constructor(private val api: Api) {
symbol = student.symbol symbol = student.symbol
schoolSymbol = student.schoolSymbol schoolSymbol = student.schoolSymbol
studentId = student.studentId studentId = student.studentId
useNewStudent = false
host = URL(student.endpoint).run { host + ":$port".removeSuffix(":-1") } host = URL(student.endpoint).run { host + ":$port".removeSuffix(":-1") }
ssl = student.endpoint.startsWith("https") ssl = student.endpoint.startsWith("https")
loginType = Api.LoginType.valueOf(student.loginType) loginType = Api.LoginType.valueOf(student.loginType)
@ -24,4 +25,3 @@ class ApiHelper @Inject constructor(private val api: Api) {
initApi(Student(email = email, password = password, symbol = symbol, endpoint = endpoint, loginType = "AUTO")) initApi(Student(email = email, password = password, symbol = symbol, endpoint = endpoint, loginType = "AUTO"))
} }
} }

View File

@ -25,7 +25,7 @@ class GradeRemote @Inject constructor(private val api: Api) {
modifier = it.modifier, modifier = it.modifier,
comment = it.comment, comment = it.comment,
color = it.color, color = it.color,
gradeSymbol = it.symbol, gradeSymbol = it.symbol ?: "",
description = it.description, description = it.description,
weight = it.weight, weight = it.weight,
weightValue = it.weightValue, weightValue = it.weightValue,

View File

@ -3,11 +3,13 @@ package io.github.wulkanowy.di
import android.content.Context import android.content.Context
import com.firebase.jobdispatcher.FirebaseJobDispatcher import com.firebase.jobdispatcher.FirebaseJobDispatcher
import com.firebase.jobdispatcher.GooglePlayDriver import com.firebase.jobdispatcher.GooglePlayDriver
import com.google.firebase.analytics.FirebaseAnalytics
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.WulkanowyApp import io.github.wulkanowy.WulkanowyApp
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import javax.inject.Singleton import javax.inject.Singleton
@ -28,4 +30,8 @@ internal class AppModule {
@Singleton @Singleton
@Provides @Provides
fun provideJobDispatcher(context: Context) = FirebaseJobDispatcher(GooglePlayDriver(context)) fun provideJobDispatcher(context: Context) = FirebaseJobDispatcher(GooglePlayDriver(context))
@Singleton
@Provides
fun provideFirebaseAnalyticsHelper(context: Context) = FirebaseAnalyticsHelper(FirebaseAnalytics.getInstance(context))
} }

View File

@ -6,23 +6,31 @@ import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL2
import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL3 import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL3
import io.github.wulkanowy.data.ErrorHandler import io.github.wulkanowy.data.ErrorHandler
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class AboutPresenter @Inject constructor(errorHandler: ErrorHandler) : BasePresenter<AboutView>(errorHandler) { class AboutPresenter @Inject constructor(
errorHandler: ErrorHandler,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<AboutView>(errorHandler) {
fun onExtraSelect(type: Libs.SpecialButton?) { fun onExtraSelect(type: Libs.SpecialButton?) {
view?.run { view?.run {
when (type) { when (type) {
SPECIAL1 -> { SPECIAL1 -> {
Timber.i("Opening github page") Timber.i("Opening github page")
analytics.logEvent("open_page", mapOf("name" to "github"))
openSourceWebView() openSourceWebView()
} }
SPECIAL2 -> { SPECIAL2 -> {
Timber.i("Opening issues page") Timber.i("Opening issues page")
analytics.logEvent("open_page", mapOf("name" to "issues"))
openIssuesWebView() openIssuesWebView()
} }
SPECIAL3 -> { } SPECIAL3 -> {
//empty for now
}
} }
} }
} }

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.attendance package io.github.wulkanowy.ui.modules.attendance
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.repositories.AttendanceRepository import io.github.wulkanowy.data.repositories.AttendanceRepository
import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.PreferencesRepository
@ -7,9 +8,9 @@ import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.main.MainErrorHandler import io.github.wulkanowy.ui.modules.main.MainErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.isHolidays import io.github.wulkanowy.utils.isHolidays
import io.github.wulkanowy.utils.logEvent
import io.github.wulkanowy.utils.nextSchoolDay import io.github.wulkanowy.utils.nextSchoolDay
import io.github.wulkanowy.utils.previousOrSameSchoolDay import io.github.wulkanowy.utils.previousOrSameSchoolDay
import io.github.wulkanowy.utils.previousSchoolDay import io.github.wulkanowy.utils.previousSchoolDay
@ -26,7 +27,8 @@ class AttendancePresenter @Inject constructor(
private val attendanceRepository: AttendanceRepository, private val attendanceRepository: AttendanceRepository,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val prefRepository: PreferencesRepository private val prefRepository: PreferencesRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<AttendanceView>(errorHandler) { ) : BasePresenter<AttendanceView>(errorHandler) {
lateinit var currentDate: LocalDate lateinit var currentDate: LocalDate
@ -42,13 +44,11 @@ class AttendancePresenter @Inject constructor(
fun onPreviousDay() { fun onPreviousDay() {
loadData(currentDate.previousSchoolDay) loadData(currentDate.previousSchoolDay)
reloadView() reloadView()
logEvent("Attendance day changed", mapOf("button" to "prev", "date" to currentDate.toFormattedString()))
} }
fun onNextDay() { fun onNextDay() {
loadData(currentDate.nextSchoolDay) loadData(currentDate.nextSchoolDay)
reloadView() reloadView()
logEvent("Attendance day changed", mapOf("button" to "next", "date" to currentDate.toFormattedString()))
} }
fun onSwipeRefresh() { fun onSwipeRefresh() {
@ -105,7 +105,7 @@ class AttendancePresenter @Inject constructor(
showEmpty(it.isEmpty()) showEmpty(it.isEmpty())
showContent(it.isNotEmpty()) showContent(it.isNotEmpty())
} }
logEvent("Attendance load", mapOf("items" to it.size, "forceRefresh" to forceRefresh, "date" to currentDate.toFormattedString())) analytics.logEvent("load_attendance", mapOf("items" to it.size, "force_refresh" to forceRefresh, START_DATE to currentDate.toFormattedString("yyyy-MM-dd")))
}) { }) {
view?.run { showEmpty(isViewEmpty) } view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -8,10 +8,10 @@ import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.repositories.SubjectRepostory import io.github.wulkanowy.data.repositories.SubjectRepostory
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.calculatePercentage import io.github.wulkanowy.utils.calculatePercentage
import io.github.wulkanowy.utils.getFormattedName import io.github.wulkanowy.utils.getFormattedName
import io.github.wulkanowy.utils.logEvent
import java.lang.String.format import java.lang.String.format
import java.util.Locale.FRANCE import java.util.Locale.FRANCE
import java.util.concurrent.TimeUnit.MILLISECONDS import java.util.concurrent.TimeUnit.MILLISECONDS
@ -23,7 +23,8 @@ class AttendanceSummaryPresenter @Inject constructor(
private val subjectRepository: SubjectRepostory, private val subjectRepository: SubjectRepostory,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val schedulers: SchedulersProvider private val schedulers: SchedulersProvider,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<AttendanceSummaryView>(errorHandler) { ) : BasePresenter<AttendanceSummaryView>(errorHandler) {
private var subjects = emptyList<Subject>() private var subjects = emptyList<Subject>()
@ -74,7 +75,7 @@ class AttendanceSummaryPresenter @Inject constructor(
showContent(it.first.isNotEmpty()) showContent(it.first.isNotEmpty())
updateDataSet(it.first, it.second) updateDataSet(it.first, it.second)
} }
logEvent("Attendance load", mapOf("forceRefresh" to forceRefresh)) analytics.logEvent("load_attendance_summary", mapOf("items" to it.first.size, "force_refresh" to forceRefresh, "item_id" to subjectId))
}) { }) {
view?.run { showEmpty(isViewEmpty) } view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.exam package io.github.wulkanowy.ui.modules.exam
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.repositories.ExamRepository import io.github.wulkanowy.data.repositories.ExamRepository
@ -7,10 +8,10 @@ import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.main.MainErrorHandler import io.github.wulkanowy.ui.modules.main.MainErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.friday import io.github.wulkanowy.utils.friday
import io.github.wulkanowy.utils.isHolidays import io.github.wulkanowy.utils.isHolidays
import io.github.wulkanowy.utils.logEvent
import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextOrSameSchoolDay
import io.github.wulkanowy.utils.toFormattedString import io.github.wulkanowy.utils.toFormattedString
@ -25,7 +26,8 @@ class ExamPresenter @Inject constructor(
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val examRepository: ExamRepository, private val examRepository: ExamRepository,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<ExamView>(errorHandler) { ) : BasePresenter<ExamView>(errorHandler) {
lateinit var currentDate: LocalDate lateinit var currentDate: LocalDate
@ -41,13 +43,11 @@ class ExamPresenter @Inject constructor(
fun onPreviousWeek() { fun onPreviousWeek() {
loadData(currentDate.minusDays(7)) loadData(currentDate.minusDays(7))
reloadView() reloadView()
logEvent("Exam week changed", mapOf("button" to "prev", "date" to currentDate.toFormattedString()))
} }
fun onNextWeek() { fun onNextWeek() {
loadData(currentDate.plusDays(7)) loadData(currentDate.plusDays(7))
reloadView() reloadView()
logEvent("Exam week changed", mapOf("button" to "next", "date" to currentDate.toFormattedString()))
} }
fun onSwipeRefresh() { fun onSwipeRefresh() {
@ -92,7 +92,7 @@ class ExamPresenter @Inject constructor(
showEmpty(it.isEmpty()) showEmpty(it.isEmpty())
showContent(it.isNotEmpty()) showContent(it.isNotEmpty())
} }
logEvent("Exam load", mapOf("items" to it.size, "forceRefresh" to forceRefresh, "date" to currentDate.toFormattedString())) analytics.logEvent("load_exam", mapOf("items" to it.size, "force_refresh" to forceRefresh, START_DATE to currentDate.toFormattedString("yyyy-MM-dd")))
}) { }) {
view?.run { showEmpty(isViewEmpty) } view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -5,8 +5,8 @@ import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.main.MainErrorHandler import io.github.wulkanowy.ui.modules.main.MainErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.logEvent
import io.reactivex.Completable import io.reactivex.Completable
import java.util.concurrent.TimeUnit.MILLISECONDS import java.util.concurrent.TimeUnit.MILLISECONDS
import javax.inject.Inject import javax.inject.Inject
@ -15,7 +15,8 @@ class GradePresenter @Inject constructor(
private val errorHandler: MainErrorHandler, private val errorHandler: MainErrorHandler,
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<GradeView>(errorHandler) { ) : BasePresenter<GradeView>(errorHandler) {
var selectedIndex = 0 var selectedIndex = 0
@ -52,7 +53,7 @@ class GradePresenter @Inject constructor(
notifyChildrenSemesterChange() notifyChildrenSemesterChange()
loadChild(it.currentPageIndex) loadChild(it.currentPageIndex)
} }
logEvent("Semester changed", mapOf("number" to index + 1)) analytics.logEvent("changed_semester", mapOf("number" to index + 1))
} }
} }

View File

@ -8,10 +8,10 @@ import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.main.MainErrorHandler import io.github.wulkanowy.ui.modules.main.MainErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.calcAverage import io.github.wulkanowy.utils.calcAverage
import io.github.wulkanowy.utils.changeModifier import io.github.wulkanowy.utils.changeModifier
import io.github.wulkanowy.utils.logEvent
import io.github.wulkanowy.utils.valueColor import io.github.wulkanowy.utils.valueColor
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -22,7 +22,8 @@ class GradeDetailsPresenter @Inject constructor(
private val gradeRepository: GradeRepository, private val gradeRepository: GradeRepository,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val preferencesRepository: PreferencesRepository private val preferencesRepository: PreferencesRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<GradeDetailsView>(errorHandler) { ) : BasePresenter<GradeDetailsView>(errorHandler) {
private var currentSemesterId = 0 private var currentSemesterId = 0
@ -113,7 +114,7 @@ class GradeDetailsPresenter @Inject constructor(
showContent(it.isNotEmpty()) showContent(it.isNotEmpty())
updateData(it) updateData(it)
} }
logEvent("Grade details load", mapOf("items" to it.size, "forceRefresh" to forceRefresh)) analytics.logEvent("load_grade_details", mapOf("items" to it.size, "force_refresh" to forceRefresh))
}) { }) {
view?.run { showEmpty(isViewEmpty) } view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -8,10 +8,10 @@ import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.main.MainErrorHandler import io.github.wulkanowy.ui.modules.main.MainErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.calcAverage import io.github.wulkanowy.utils.calcAverage
import io.github.wulkanowy.utils.changeModifier import io.github.wulkanowy.utils.changeModifier
import io.github.wulkanowy.utils.logEvent
import java.lang.String.format import java.lang.String.format
import java.util.Locale.FRANCE import java.util.Locale.FRANCE
import javax.inject.Inject import javax.inject.Inject
@ -23,7 +23,8 @@ class GradeSummaryPresenter @Inject constructor(
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val preferencesRepository: PreferencesRepository, private val preferencesRepository: PreferencesRepository,
private val schedulers: SchedulersProvider private val schedulers: SchedulersProvider,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<GradeSummaryView>(errorHandler) { ) : BasePresenter<GradeSummaryView>(errorHandler) {
override fun onAttachView(view: GradeSummaryView) { override fun onAttachView(view: GradeSummaryView) {
@ -68,7 +69,7 @@ class GradeSummaryPresenter @Inject constructor(
showContent(it.first.isNotEmpty()) showContent(it.first.isNotEmpty())
updateData(it.first, it.second) updateData(it.first, it.second)
} }
logEvent("Grade summary load", mapOf("items" to it.first.size, "forceRefresh" to forceRefresh)) analytics.logEvent("load_grade_summary", mapOf("items" to it.first.size, "force_refresh" to forceRefresh))
}) { }) {
view?.run { showEmpty(isViewEmpty) } view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -1,14 +1,15 @@
package io.github.wulkanowy.ui.modules.homework package io.github.wulkanowy.ui.modules.homework
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.repositories.HomeworkRepository import io.github.wulkanowy.data.repositories.HomeworkRepository
import io.github.wulkanowy.data.repositories.SemesterRepository import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.main.MainErrorHandler import io.github.wulkanowy.ui.modules.main.MainErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.isHolidays import io.github.wulkanowy.utils.isHolidays
import io.github.wulkanowy.utils.logEvent
import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextOrSameSchoolDay
import io.github.wulkanowy.utils.nextSchoolDay import io.github.wulkanowy.utils.nextSchoolDay
import io.github.wulkanowy.utils.previousSchoolDay import io.github.wulkanowy.utils.previousSchoolDay
@ -22,7 +23,8 @@ class HomeworkPresenter @Inject constructor(
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val homeworkRepository: HomeworkRepository, private val homeworkRepository: HomeworkRepository,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<HomeworkView>(errorHandler) { ) : BasePresenter<HomeworkView>(errorHandler) {
lateinit var currentDate: LocalDate lateinit var currentDate: LocalDate
@ -38,13 +40,11 @@ class HomeworkPresenter @Inject constructor(
fun onPreviousDay() { fun onPreviousDay() {
loadData(currentDate.previousSchoolDay) loadData(currentDate.previousSchoolDay)
reloadView() reloadView()
logEvent("Homework day changed", mapOf("button" to "prev", "date" to currentDate.toFormattedString()))
} }
fun onNextDay() { fun onNextDay() {
loadData(currentDate.nextSchoolDay) loadData(currentDate.nextSchoolDay)
reloadView() reloadView()
logEvent("Homework day changed", mapOf("button" to "next", "date" to currentDate.toFormattedString()))
} }
fun onSwipeRefresh() { fun onSwipeRefresh() {
@ -78,7 +78,7 @@ class HomeworkPresenter @Inject constructor(
showEmpty(it.isEmpty()) showEmpty(it.isEmpty())
showContent(it.isNotEmpty()) showContent(it.isNotEmpty())
} }
logEvent("Homework load", mapOf("items" to it.size, "forceRefresh" to forceRefresh, "date" to currentDate.toFormattedString())) analytics.logEvent("load_homework", mapOf("items" to it.size, "force_refresh" to forceRefresh, START_DATE to currentDate.toFormattedString("yyyy-MM-dd")))
}) { }) {
view?.run { showEmpty(isViewEmpty()) } view?.run { showEmpty(isViewEmpty()) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -1,18 +1,21 @@
package io.github.wulkanowy.ui.modules.login.form package io.github.wulkanowy.ui.modules.login.form
import com.google.firebase.analytics.FirebaseAnalytics.Event.SIGN_UP
import com.google.firebase.analytics.FirebaseAnalytics.Param.GROUP_ID
import com.google.firebase.analytics.FirebaseAnalytics.Param.SUCCESS
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.logEvent
import io.github.wulkanowy.utils.logRegister
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class LoginFormPresenter @Inject constructor( class LoginFormPresenter @Inject constructor(
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val errorHandler: LoginErrorHandler, private val errorHandler: LoginErrorHandler,
private val studentRepository: StudentRepository private val studentRepository: StudentRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<LoginFormView>(errorHandler) { ) : BasePresenter<LoginFormView>(errorHandler) {
private var wasEmpty = false private var wasEmpty = false
@ -57,15 +60,14 @@ class LoginFormPresenter @Inject constructor(
} else if (it.isEmpty() && wasEmpty) { } else if (it.isEmpty() && wasEmpty) {
showSymbolInput() showSymbolInput()
setErrorSymbolIncorrect() setErrorSymbolIncorrect()
logRegister("No student found", false, if (symbol.isEmpty()) "nil" else symbol, endpoint) analytics.logEvent(SIGN_UP, mapOf(SUCCESS to false, "students" to it.size, "endpoint" to endpoint, GROUP_ID to symbol.ifEmpty { "nil" }))
} else { } else {
switchOptionsView() switchOptionsView()
logEvent("Found students", mapOf("students" to it.size, "symbol" to it.joinToString { student -> student.symbol }, "endpoint" to endpoint))
} }
} }
}, { }, {
analytics.logEvent(SIGN_UP, mapOf(SUCCESS to true, "endpoint" to endpoint, GROUP_ID to symbol.ifEmpty { "nil" }))
errorHandler.dispatch(it) errorHandler.dispatch(it)
logRegister(it.localizedMessage, false, if (symbol.isEmpty()) "nil" else symbol, endpoint)
})) }))
} }

View File

@ -1,13 +1,16 @@
package io.github.wulkanowy.ui.modules.login.options package io.github.wulkanowy.ui.modules.login.options
import com.google.firebase.analytics.FirebaseAnalytics.Event.SIGN_UP
import com.google.firebase.analytics.FirebaseAnalytics.Param.GROUP_ID
import com.google.firebase.analytics.FirebaseAnalytics.Param.SUCCESS
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.SemesterRepository import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.logRegister
import io.reactivex.Single import io.reactivex.Single
import javax.inject.Inject import javax.inject.Inject
@ -15,7 +18,8 @@ class LoginOptionsPresenter @Inject constructor(
private val errorHandler: LoginErrorHandler, private val errorHandler: LoginErrorHandler,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository, private val semesterRepository: SemesterRepository,
private val schedulers: SchedulersProvider private val schedulers: SchedulersProvider,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<LoginOptionsView>(errorHandler) { ) : BasePresenter<LoginOptionsView>(errorHandler) {
override fun onAttachView(view: LoginOptionsView) { override fun onAttachView(view: LoginOptionsView) {
@ -56,7 +60,7 @@ class LoginOptionsPresenter @Inject constructor(
} }
} }
.subscribe({ .subscribe({
logRegister("Success", true, student.symbol, student.endpoint) analytics.logEvent(SIGN_UP, mapOf(SUCCESS to true, "students" to 1, "endpoint" to student.endpoint, GROUP_ID to student.symbol))
view?.openMainView() view?.openMainView()
}, { }, {
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -1,11 +1,13 @@
package io.github.wulkanowy.ui.modules.main package io.github.wulkanowy.ui.modules.main
import com.google.firebase.analytics.FirebaseAnalytics.Event.APP_OPEN
import com.google.firebase.analytics.FirebaseAnalytics.Param.DESTINATION
import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.services.job.ServiceHelper import io.github.wulkanowy.services.job.ServiceHelper
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.logLogin
import io.reactivex.Completable import io.reactivex.Completable
import javax.inject.Inject import javax.inject.Inject
@ -14,7 +16,8 @@ class MainPresenter @Inject constructor(
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val prefRepository: PreferencesRepository, private val prefRepository: PreferencesRepository,
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val serviceHelper: ServiceHelper private val serviceHelper: ServiceHelper,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<MainView>(errorHandler) { ) : BasePresenter<MainView>(errorHandler) {
fun onAttachView(view: MainView, initMenuIndex: Int) { fun onAttachView(view: MainView, initMenuIndex: Int) {
@ -27,11 +30,12 @@ class MainPresenter @Inject constructor(
} }
serviceHelper.startFullSyncService() serviceHelper.startFullSyncService()
when (initMenuIndex) { analytics.logEvent(APP_OPEN, mapOf(DESTINATION to when (initMenuIndex) {
1 -> logLogin("Grades") 1 -> "Grades"
3 -> logLogin("Timetable") 3 -> "Timetable"
4 -> logLogin("More") 4 -> "More"
} else -> "User action"
}))
} }
fun onViewStart() { fun onViewStart() {

View File

@ -1,11 +1,12 @@
package io.github.wulkanowy.ui.modules.message.preview package io.github.wulkanowy.ui.modules.message.preview
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
import io.github.wulkanowy.data.ErrorHandler import io.github.wulkanowy.data.ErrorHandler
import io.github.wulkanowy.data.repositories.MessagesRepository import io.github.wulkanowy.data.repositories.MessagesRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.logEvent
import io.github.wulkanowy.utils.toFormattedString import io.github.wulkanowy.utils.toFormattedString
import javax.inject.Inject import javax.inject.Inject
@ -13,7 +14,8 @@ class MessagePreviewPresenter @Inject constructor(
private val errorHandler: ErrorHandler, private val errorHandler: ErrorHandler,
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val messagesRepository: MessagesRepository, private val messagesRepository: MessagesRepository,
private val studentRepository: StudentRepository private val studentRepository: StudentRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<MessagePreviewView>(errorHandler) { ) : BasePresenter<MessagePreviewView>(errorHandler) {
var messageId: Int = 0 var messageId: Int = 0
@ -32,9 +34,9 @@ class MessagePreviewPresenter @Inject constructor(
.subscribeOn(schedulers.backgroundThread) .subscribeOn(schedulers.backgroundThread)
.observeOn(schedulers.mainThread) .observeOn(schedulers.mainThread)
.doFinally { view?.showProgress(false) } .doFinally { view?.showProgress(false) }
.subscribe({ messages -> .subscribe({ message ->
view?.run { view?.run {
messages.let { message.let {
setSubject(if (it.subject.isNotBlank()) it.subject else noSubjectString) setSubject(if (it.subject.isNotBlank()) it.subject else noSubjectString)
setDate(it.date?.toFormattedString("yyyy-MM-dd HH:mm:ss")) setDate(it.date?.toFormattedString("yyyy-MM-dd HH:mm:ss"))
setContent(it.content) setContent(it.content)
@ -43,7 +45,7 @@ class MessagePreviewPresenter @Inject constructor(
else setSender(it.sender) else setSender(it.sender)
} }
} }
logEvent("Message load", mapOf("length" to messages.content?.length)) analytics.logEvent("load_attendance", mapOf(START_DATE to message.date?.toFormattedString("yyyy.MM.dd"), "lenght" to message.content?.length))
}) { }) {
view?.showMessageError() view?.showMessageError()
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -7,8 +7,8 @@ import io.github.wulkanowy.data.repositories.MessagesRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.message.MessageItem import io.github.wulkanowy.ui.modules.message.MessageItem
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.logEvent
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -16,7 +16,8 @@ class MessageTabPresenter @Inject constructor(
private val errorHandler: ErrorHandler, private val errorHandler: ErrorHandler,
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val messagesRepository: MessagesRepository, private val messagesRepository: MessagesRepository,
private val studentRepository: StudentRepository private val studentRepository: StudentRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<MessageTabView>(errorHandler) { ) : BasePresenter<MessageTabView>(errorHandler) {
lateinit var folder: MessagesRepository.MessageFolder lateinit var folder: MessagesRepository.MessageFolder
@ -52,7 +53,7 @@ class MessageTabPresenter @Inject constructor(
showContent(it.isNotEmpty()) showContent(it.isNotEmpty())
updateData(it) updateData(it)
} }
logEvent("Message tab load", mapOf("items" to it.size, "forceRefresh" to forceRefresh)) analytics.logEvent("load_messages", mapOf("items" to it.size, "folder" to folder.name))
}) { }) {
view?.run { showEmpty(isViewEmpty) } view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -7,8 +7,8 @@ import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.main.MainErrorHandler import io.github.wulkanowy.ui.modules.main.MainErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.logEvent
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -17,7 +17,8 @@ class NotePresenter @Inject constructor(
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val noteRepository: NoteRepository, private val noteRepository: NoteRepository,
private val semesterRepository: SemesterRepository private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<NoteView>(errorHandler) { ) : BasePresenter<NoteView>(errorHandler) {
override fun onAttachView(view: NoteView) { override fun onAttachView(view: NoteView) {
@ -49,7 +50,7 @@ class NotePresenter @Inject constructor(
showEmpty(it.isEmpty()) showEmpty(it.isEmpty())
showContent(it.isNotEmpty()) showContent(it.isNotEmpty())
} }
logEvent("Note load", mapOf("items" to it.size, "forceRefresh" to forceRefresh)) analytics.logEvent("load_note", mapOf("items" to it.size, "force_refresh" to forceRefresh))
}, { }, {
view?.run { showEmpty(isViewEmpty) } view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -4,15 +4,16 @@ import io.github.wulkanowy.data.ErrorHandler
import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.services.job.ServiceHelper import io.github.wulkanowy.services.job.ServiceHelper
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.isHolidays import io.github.wulkanowy.utils.isHolidays
import io.github.wulkanowy.utils.logEvent
import org.threeten.bp.LocalDate.now import org.threeten.bp.LocalDate.now
import javax.inject.Inject import javax.inject.Inject
class SettingsPresenter @Inject constructor( class SettingsPresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
private val preferencesRepository: PreferencesRepository, private val preferencesRepository: PreferencesRepository,
private val serviceHelper: ServiceHelper private val serviceHelper: ServiceHelper,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<SettingsView>(errorHandler) { ) : BasePresenter<SettingsView>(errorHandler) {
override fun onAttachView(view: SettingsView) { override fun onAttachView(view: SettingsView) {
@ -38,6 +39,6 @@ class SettingsPresenter @Inject constructor(
} }
} }
logEvent("Setting changed", mapOf("name" to key)) analytics.logEvent("setting_changed", mapOf("name" to key))
} }
} }

View File

@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.modules.splash
import io.github.wulkanowy.data.ErrorHandler import io.github.wulkanowy.data.ErrorHandler
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.utils.logLogin
import javax.inject.Inject import javax.inject.Inject
class SplashPresenter @Inject constructor( class SplashPresenter @Inject constructor(
@ -14,10 +13,8 @@ class SplashPresenter @Inject constructor(
override fun onAttachView(view: SplashView) { override fun onAttachView(view: SplashView) {
super.onAttachView(view) super.onAttachView(view)
view.run { view.run {
if (studentRepository.isStudentSaved) { if (studentRepository.isStudentSaved) openMainView()
logLogin("Open app") else openLoginView()
openMainView()
} else openLoginView()
} }
} }
} }

View File

@ -1,14 +1,15 @@
package io.github.wulkanowy.ui.modules.timetable package io.github.wulkanowy.ui.modules.timetable
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import io.github.wulkanowy.data.repositories.SemesterRepository import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.repositories.TimetableRepository import io.github.wulkanowy.data.repositories.TimetableRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.main.MainErrorHandler import io.github.wulkanowy.ui.modules.main.MainErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.isHolidays import io.github.wulkanowy.utils.isHolidays
import io.github.wulkanowy.utils.logEvent
import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextOrSameSchoolDay
import io.github.wulkanowy.utils.nextSchoolDay import io.github.wulkanowy.utils.nextSchoolDay
import io.github.wulkanowy.utils.previousSchoolDay import io.github.wulkanowy.utils.previousSchoolDay
@ -24,7 +25,8 @@ class TimetablePresenter @Inject constructor(
private val schedulers: SchedulersProvider, private val schedulers: SchedulersProvider,
private val timetableRepository: TimetableRepository, private val timetableRepository: TimetableRepository,
private val studentRepository: StudentRepository, private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository private val semesterRepository: SemesterRepository,
private val analytics: FirebaseAnalyticsHelper
) : BasePresenter<TimetableView>(errorHandler) { ) : BasePresenter<TimetableView>(errorHandler) {
lateinit var currentDate: LocalDate lateinit var currentDate: LocalDate
@ -40,13 +42,11 @@ class TimetablePresenter @Inject constructor(
fun onPreviousDay() { fun onPreviousDay() {
loadData(currentDate.previousSchoolDay) loadData(currentDate.previousSchoolDay)
reloadView() reloadView()
logEvent("Timetable day changed", mapOf("button" to "prev", "date" to currentDate.toFormattedString()))
} }
fun onNextDay() { fun onNextDay() {
loadData(currentDate.nextSchoolDay) loadData(currentDate.nextSchoolDay)
reloadView() reloadView()
logEvent("Timetable day changed", mapOf("button" to "next", "date" to currentDate.toFormattedString()))
} }
fun onSwipeRefresh() { fun onSwipeRefresh() {
@ -90,7 +90,7 @@ class TimetablePresenter @Inject constructor(
showEmpty(it.isEmpty()) showEmpty(it.isEmpty())
showContent(it.isNotEmpty()) showContent(it.isNotEmpty())
} }
logEvent("Timetable load", mapOf("items" to it.size, "forceRefresh" to forceRefresh, "date" to currentDate.toFormattedString())) analytics.logEvent("load_attendance", mapOf("items" to it.size, "force_refresh" to forceRefresh, START_DATE to currentDate.toFormattedString("yyyy-MM-dd")))
}) { }) {
view?.run { showEmpty(isViewEmpty) } view?.run { showEmpty(isViewEmpty) }
errorHandler.dispatch(it) errorHandler.dispatch(it)

View File

@ -15,7 +15,7 @@ import io.github.wulkanowy.data.db.SharedPrefHelper
import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.services.widgets.TimetableWidgetService
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU_INDEX import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU_INDEX
import io.github.wulkanowy.utils.logEvent import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextOrSameSchoolDay
import io.github.wulkanowy.utils.nextSchoolDay import io.github.wulkanowy.utils.nextSchoolDay
import io.github.wulkanowy.utils.previousSchoolDay import io.github.wulkanowy.utils.previousSchoolDay
@ -29,6 +29,9 @@ class TimetableWidgetProvider : AppWidgetProvider() {
@Inject @Inject
lateinit var sharedPref: SharedPrefHelper lateinit var sharedPref: SharedPrefHelper
@Inject
lateinit var analytics: FirebaseAnalyticsHelper
companion object { companion object {
const val EXTRA_TOGGLED_WIDGET_ID = "extraToggledWidget" const val EXTRA_TOGGLED_WIDGET_ID = "extraToggledWidget"
@ -91,7 +94,11 @@ class TimetableWidgetProvider : AppWidgetProvider() {
} }
BUTTON_RESET -> sharedPref.putLong(widgetKey, LocalDate.now().nextOrSameSchoolDay.toEpochDay(), true) BUTTON_RESET -> sharedPref.putLong(widgetKey, LocalDate.now().nextOrSameSchoolDay.toEpochDay(), true)
} }
button?.also { btn -> if (btn.isNotBlank()) logEvent("Widget day changed", mapOf("button" to button)) } button?.also { btn ->
if (btn.isNotBlank()) {
analytics.logEvent("changed_timetable_widget_day", mapOf("button" to button))
}
}
} }
} }
super.onReceive(context, intent) super.onReceive(context, intent)

View File

@ -1,49 +0,0 @@
package io.github.wulkanowy.utils
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.answers.CustomEvent
import com.crashlytics.android.answers.LoginEvent
import com.crashlytics.android.answers.SignUpEvent
import timber.log.Timber
import kotlin.math.min
fun logLogin(method: String) {
try {
Answers.getInstance().logLogin(LoginEvent().putMethod(method))
} catch (e: Throwable) {
Timber.d(e)
}
}
fun logRegister(message: String, result: Boolean, symbol: String, endpoint: String) {
try {
Answers.getInstance().logSignUp(SignUpEvent()
.putMethod("Login activity")
.putSuccess(result)
.putCustomAttribute("symbol", symbol)
.putCustomAttribute("message", message.substring(0, min(message.length, 100)))
.putCustomAttribute("endpoint", endpoint)
)
} catch (e: Throwable) {
Timber.d(e)
}
}
fun <T> logEvent(name: String, params: Map<String, T>) {
try {
Answers.getInstance().logCustom(CustomEvent(name)
.apply {
params.forEach {
when {
it.value is String -> putCustomAttribute(it.key, it.value as String)
it.value is Number -> putCustomAttribute(it.key, it.value as Number)
it.value is Boolean -> putCustomAttribute(it.key, if ((it.value as Boolean)) "true" else "false")
else -> Timber.w("logEvent() unknown value type: ${it.value}")
}
}
}
)
} catch (e: Throwable) {
Timber.d(e)
}
}

View File

@ -0,0 +1,23 @@
package io.github.wulkanowy.utils
import android.os.Bundle
import com.google.firebase.analytics.FirebaseAnalytics
import javax.inject.Singleton
@Singleton
class FirebaseAnalyticsHelper(private val analytics: FirebaseAnalytics) {
fun logEvent(name: String, params: Map<String, Any?>) {
Bundle().apply {
params.forEach {
if (it.value == null) return@forEach
when (it.value) {
is String, is String? -> putString(it.key, it.value as String)
is Int, is Int? -> putInt(it.key, it.value as Int)
is Boolean, is Boolean? -> putBoolean(it.key, it.value as Boolean)
}
}
analytics.logEvent(name, this)
}
}
}

View File

@ -0,0 +1,42 @@
{
"project_info": {
"project_number": "",
"firebase_url": "",
"project_id": "",
"storage_bucket": ""
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:1091101852179:android:b558a25f65d088b1",
"android_client_info": {
"package_name": "io.github.wulkanowy"
}
},
"oauth_client": [
{
"client_id": "",
"client_type": 3
}
],
"api_key": [
{
"current_key": ""
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}

Binary file not shown.

View File

@ -22,7 +22,7 @@ class StudentRemoteTest {
@Test @Test
fun testRemoteAll() { fun testRemoteAll() {
doReturn(Single.just(listOf(Pupil("", "", 1, "test", "", "", Api.LoginType.AUTO)))) doReturn(Single.just(listOf(Pupil("", "", 1, "test", "", "", "", Api.LoginType.AUTO))))
.`when`(mockApi).getPupils() .`when`(mockApi).getPupils()
val students = StudentRemote(mockApi).getStudents("", "", "").blockingGet() val students = StudentRemote(mockApi).getStudents("", "", "").blockingGet()

View File

@ -4,6 +4,7 @@ import io.github.wulkanowy.TestSchedulersProvider
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.reactivex.Single import io.reactivex.Single
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -27,13 +28,16 @@ class LoginFormPresenterTest {
@Mock @Mock
lateinit var errorHandler: LoginErrorHandler lateinit var errorHandler: LoginErrorHandler
@Mock
lateinit var analytics: FirebaseAnalyticsHelper
private lateinit var presenter: LoginFormPresenter private lateinit var presenter: LoginFormPresenter
@Before @Before
fun initPresenter() { fun initPresenter() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
clearInvocations(repository, loginFormView) clearInvocations(repository, loginFormView)
presenter = LoginFormPresenter(TestSchedulersProvider(), errorHandler, repository) presenter = LoginFormPresenter(TestSchedulersProvider(), errorHandler, repository, analytics)
presenter.onAttachView(loginFormView) presenter.onAttachView(loginFormView)
} }
@ -125,7 +129,6 @@ class LoginFormPresenterTest {
verify(loginFormView, times(2)).showContent(true) verify(loginFormView, times(2)).showContent(true)
verify(loginFormView, times(2)).showSymbolInput() verify(loginFormView, times(2)).showSymbolInput()
verify(loginFormView).setErrorSymbolIncorrect() verify(loginFormView).setErrorSymbolIncorrect()
} }
@Test @Test

View File

@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.SemesterRepository import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Single import io.reactivex.Single
import org.junit.Before import org.junit.Before
@ -30,6 +31,9 @@ class LoginOptionsPresenterTest {
@Mock @Mock
lateinit var semesterRepository: SemesterRepository lateinit var semesterRepository: SemesterRepository
@Mock
lateinit var analytics: FirebaseAnalyticsHelper
private lateinit var presenter: LoginOptionsPresenter private lateinit var presenter: LoginOptionsPresenter
private val testStudent by lazy { Student(email = "test", password = "test123", endpoint = "https://fakelog.cf", loginType = "AUTO") } private val testStudent by lazy { Student(email = "test", password = "test123", endpoint = "https://fakelog.cf", loginType = "AUTO") }
@ -41,7 +45,7 @@ class LoginOptionsPresenterTest {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
clearInvocations(studentRepository, loginOptionsView) clearInvocations(studentRepository, loginOptionsView)
clearInvocations(semesterRepository, loginOptionsView) clearInvocations(semesterRepository, loginOptionsView)
presenter = LoginOptionsPresenter(errorHandler, studentRepository, semesterRepository, TestSchedulersProvider()) presenter = LoginOptionsPresenter(errorHandler, studentRepository, semesterRepository, TestSchedulersProvider(), analytics)
presenter.onAttachView(loginOptionsView) presenter.onAttachView(loginOptionsView)
} }

View File

@ -4,6 +4,7 @@ import io.github.wulkanowy.TestSchedulersProvider
import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.services.job.ServiceHelper import io.github.wulkanowy.services.job.ServiceHelper
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.mockito.Mock import org.mockito.Mock
@ -28,6 +29,9 @@ class MainPresenterTest {
@Mock @Mock
lateinit var mainView: MainView lateinit var mainView: MainView
@Mock
lateinit var analytics: FirebaseAnalyticsHelper
private lateinit var presenter: MainPresenter private lateinit var presenter: MainPresenter
@Before @Before
@ -35,7 +39,7 @@ class MainPresenterTest {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
clearInvocations(mainView) clearInvocations(mainView)
presenter = MainPresenter(errorHandler, studentRepository, prefRepository, TestSchedulersProvider(), serviceHelper) presenter = MainPresenter(errorHandler, studentRepository, prefRepository, TestSchedulersProvider(), serviceHelper, analytics)
presenter.onAttachView(mainView, -1) presenter.onAttachView(mainView, -1)
} }

View File

@ -10,7 +10,8 @@ buildscript {
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.android.tools.build:gradle:3.2.1' classpath 'com.android.tools.build:gradle:3.2.1'
classpath "io.fabric.tools:gradle:1.26.0" classpath 'com.google.gms:google-services:4.2.0'
classpath "io.fabric.tools:gradle:1.26.1"
classpath "com.github.triplet.gradle:play-publisher:1.2.2" classpath "com.github.triplet.gradle:play-publisher:1.2.2"
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2" classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2"
classpath 'com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta02' classpath 'com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta02'