forked from github/wulkanowy-mirror
Merge branch '0.7.x'
This commit is contained in:
commit
f2855d598d
@ -16,8 +16,8 @@ android {
|
|||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 29
|
versionCode 30
|
||||||
versionName "0.7.3"
|
versionName "0.7.4"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
@ -25,6 +25,15 @@ android {
|
|||||||
fabric_api_key: System.getenv("FABRIC_API_KEY") ?: "null",
|
fabric_api_key: System.getenv("FABRIC_API_KEY") ?: "null",
|
||||||
crashlytics_enabled: project.hasProperty("enableCrashlytics")
|
crashlytics_enabled: project.hasProperty("enableCrashlytics")
|
||||||
]
|
]
|
||||||
|
javaCompileOptions {
|
||||||
|
annotationProcessorOptions {
|
||||||
|
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
@ -77,7 +86,7 @@ play {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation('com.github.wulkanowy:api:master-SNAPSHOT') { exclude module: "threetenbp" }
|
implementation('com.github.wulkanowy:api:44323f6') { 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"
|
||||||
@ -86,8 +95,8 @@ dependencies {
|
|||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
|
|
||||||
implementation "androidx.work:work-runtime:2.0.0"
|
implementation "android.arch.work:work-runtime:1.0.0"
|
||||||
implementation "androidx.work:work-rxjava2:2.0.0"
|
implementation "android.arch.work:work-rxjava2:1.0.0"
|
||||||
|
|
||||||
implementation "androidx.room:room-runtime:2.1.0-alpha06"
|
implementation "androidx.room:room-runtime:2.1.0-alpha06"
|
||||||
implementation "androidx.room:room-rxjava2:2.1.0-alpha06"
|
implementation "androidx.room:room-rxjava2:2.1.0-alpha06"
|
||||||
@ -137,6 +146,7 @@ dependencies {
|
|||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
||||||
androidTestImplementation "io.mockk:mockk-android:1.9.2"
|
androidTestImplementation "io.mockk:mockk-android:1.9.2"
|
||||||
androidTestImplementation 'org.mockito:mockito-android:2.25.1'
|
androidTestImplementation 'org.mockito:mockito-android:2.25.1'
|
||||||
|
androidTestImplementation "androidx.room:room-testing:2.1.0-alpha06"
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1325
app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json
Normal file
1325
app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json
Normal file
File diff suppressed because it is too large
Load Diff
1332
app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json
Normal file
1332
app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,159 @@
|
|||||||
|
package io.github.wulkanowy.data.db.migrations
|
||||||
|
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.room.testing.MigrationTestHelper
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class Migration12Test {
|
||||||
|
|
||||||
|
private val dbName = "migration-test"
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val helper: MigrationTestHelper = MigrationTestHelper(
|
||||||
|
InstrumentationRegistry.getInstrumentation(),
|
||||||
|
AppDatabase::class.java.canonicalName,
|
||||||
|
FrameworkSQLiteOpenHelperFactory()
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun migrate11To12_twoNotRelatedStudents() {
|
||||||
|
helper.createDatabase(dbName, 11).apply {
|
||||||
|
// user 1
|
||||||
|
createStudent(this, 1, true)
|
||||||
|
createSemester(this, 1, false, 5, 1)
|
||||||
|
createSemester(this, 1, true, 5, 2)
|
||||||
|
|
||||||
|
// user 2
|
||||||
|
createStudent(this, 2, true)
|
||||||
|
createSemester(this, 2, false, 6, 1)
|
||||||
|
createSemester(this, 2, true, 6, 2)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||||
|
|
||||||
|
val db = getMigratedRoomDatabase()
|
||||||
|
val students = db.studentDao.loadAll().blockingGet()
|
||||||
|
|
||||||
|
assertEquals(2, students.size)
|
||||||
|
|
||||||
|
students[0].run {
|
||||||
|
assertEquals(1, studentId)
|
||||||
|
assertEquals(5, classId)
|
||||||
|
}
|
||||||
|
|
||||||
|
students[1].run {
|
||||||
|
assertEquals(2, studentId)
|
||||||
|
assertEquals(6, classId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun migrate11To12_removeStudentsWithoutClassId() {
|
||||||
|
helper.createDatabase(dbName, 11).apply {
|
||||||
|
// user 1
|
||||||
|
createStudent(this, 1, true)
|
||||||
|
createSemester(this, 1, false, 0, 2)
|
||||||
|
createStudent(this, 2, true)
|
||||||
|
createSemester(this, 2, true, 1, 2)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||||
|
|
||||||
|
val db = getMigratedRoomDatabase()
|
||||||
|
val students = db.studentDao.loadAll().blockingGet()
|
||||||
|
|
||||||
|
assertEquals(1, students.size)
|
||||||
|
|
||||||
|
students[0].run {
|
||||||
|
assertEquals(2, studentId)
|
||||||
|
assertEquals(1, classId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun migrate11To12_ensureThereIsOnlyOneCurrentStudent() {
|
||||||
|
helper.createDatabase(dbName, 11).apply {
|
||||||
|
// user 1
|
||||||
|
createStudent(this, 1, true)
|
||||||
|
createSemester(this, 1, true, 5, 2)
|
||||||
|
createStudent(this, 2, true)
|
||||||
|
createSemester(this, 2, true, 6, 2)
|
||||||
|
createStudent(this, 3, true)
|
||||||
|
createSemester(this, 3, false, 7, 2)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||||
|
|
||||||
|
val db = getMigratedRoomDatabase()
|
||||||
|
val students = db.studentDao.loadAll().blockingGet()
|
||||||
|
|
||||||
|
assertEquals(3, students.size)
|
||||||
|
|
||||||
|
students[0].run {
|
||||||
|
assertEquals(studentId, 1)
|
||||||
|
assertEquals(false, isCurrent)
|
||||||
|
}
|
||||||
|
students[1].run {
|
||||||
|
assertEquals(studentId, 2)
|
||||||
|
assertEquals(false, isCurrent)
|
||||||
|
}
|
||||||
|
students[2].run {
|
||||||
|
assertEquals(studentId, 3)
|
||||||
|
assertEquals(true, isCurrent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, isCurrent: Boolean) {
|
||||||
|
db.insert("Students", CONFLICT_FAIL, ContentValues().apply {
|
||||||
|
put("endpoint", "https://fakelog.cf")
|
||||||
|
put("loginType", "STANDARD")
|
||||||
|
put("email", "jan@fakelog.cf")
|
||||||
|
put("password", "******")
|
||||||
|
put("symbol", "Default")
|
||||||
|
put("student_id", studentId)
|
||||||
|
put("student_name", "Jan Kowalski")
|
||||||
|
put("school_id", "000123")
|
||||||
|
put("school_name", "")
|
||||||
|
put("is_current", isCurrent)
|
||||||
|
put("registration_date", "0")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSemester(db: SupportSQLiteDatabase, studentId: Int, isCurrent: Boolean, classId: Int, diaryId: Int) {
|
||||||
|
db.insert("Semesters", CONFLICT_FAIL, ContentValues().apply {
|
||||||
|
put("student_id", studentId)
|
||||||
|
put("diary_id", diaryId)
|
||||||
|
put("diary_name", "IA")
|
||||||
|
put("semester_id", diaryId * 5)
|
||||||
|
put("semester_name", "1")
|
||||||
|
put("is_current", isCurrent)
|
||||||
|
put("class_id", classId)
|
||||||
|
put("unit_id", "99")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMigratedRoomDatabase(): AppDatabase {
|
||||||
|
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
|
||||||
|
AppDatabase::class.java, dbName)
|
||||||
|
.addMigrations(Migration12())
|
||||||
|
.build()
|
||||||
|
// close the database and release any stream resources when the test finishes
|
||||||
|
helper.closeWhenFinished(database)
|
||||||
|
return database
|
||||||
|
}
|
||||||
|
}
|
@ -42,7 +42,7 @@ class RecipientLocalTest {
|
|||||||
))
|
))
|
||||||
|
|
||||||
val recipients = recipientLocal.getRecipients(
|
val recipients = recipientLocal.getRecipients(
|
||||||
Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", true, LocalDateTime.now()),
|
Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", 1, true, LocalDateTime.now()),
|
||||||
2,
|
2,
|
||||||
ReportingUnit(1, 4, "", 0, "", emptyList())
|
ReportingUnit(1, 4, "", 0, "", emptyList())
|
||||||
).blockingGet()
|
).blockingGet()
|
||||||
|
@ -39,7 +39,7 @@ class StudentLocalTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun saveAndReadTest() {
|
fun saveAndReadTest() {
|
||||||
studentLocal.saveStudent(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, symbol = "", registrationDate = now()))
|
studentLocal.saveStudent(Student(email = "test", password = "test123", schoolSymbol = "23", endpoint = "fakelog.cf", loginType = "AUTO", isCurrent = true, studentName = "", schoolName = "", studentId = 0, classId = 1, symbol = "", registrationDate = now()))
|
||||||
.blockingGet()
|
.blockingGet()
|
||||||
|
|
||||||
val student = studentLocal.getCurrentStudent(true).blockingGet()
|
val student = studentLocal.getCurrentStudent(true).blockingGet()
|
||||||
|
@ -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
|
||||||
|
classId = student.classId
|
||||||
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)
|
||||||
@ -28,6 +29,7 @@ class ApiHelper @Inject constructor(private val api: Api) {
|
|||||||
this.symbol = symbol
|
this.symbol = symbol
|
||||||
host = URL(endpoint).run { host + ":$port".removeSuffix(":-1") }
|
host = URL(endpoint).run { host + ":$port".removeSuffix(":-1") }
|
||||||
ssl = endpoint.startsWith("https")
|
ssl = endpoint.startsWith("https")
|
||||||
|
useNewStudent = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import io.github.wulkanowy.data.db.entities.Subject
|
|||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration10
|
import io.github.wulkanowy.data.db.migrations.Migration10
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration11
|
import io.github.wulkanowy.data.db.migrations.Migration11
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration12
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration2
|
import io.github.wulkanowy.data.db.migrations.Migration2
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||||
@ -74,13 +75,13 @@ import javax.inject.Singleton
|
|||||||
Recipient::class
|
Recipient::class
|
||||||
],
|
],
|
||||||
version = AppDatabase.VERSION_SCHEMA,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = false
|
exportSchema = true
|
||||||
)
|
)
|
||||||
@TypeConverters(Converters::class)
|
@TypeConverters(Converters::class)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 11
|
const val VERSION_SCHEMA = 12
|
||||||
|
|
||||||
fun newInstance(context: Context): AppDatabase {
|
fun newInstance(context: Context): AppDatabase {
|
||||||
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
||||||
@ -97,7 +98,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
Migration8(),
|
Migration8(),
|
||||||
Migration9(),
|
Migration9(),
|
||||||
Migration10(),
|
Migration10(),
|
||||||
Migration11()
|
Migration11(),
|
||||||
|
Migration12()
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,6 @@ interface SemesterDao {
|
|||||||
@Delete
|
@Delete
|
||||||
fun deleteAll(semester: List<Semester>)
|
fun deleteAll(semester: List<Semester>)
|
||||||
|
|
||||||
@Query("SELECT * FROM Semesters WHERE student_id = :studentId")
|
@Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId")
|
||||||
fun loadAll(studentId: Int): Maybe<List<Semester>>
|
fun loadAll(studentId: Int, classId: Int): Maybe<List<Semester>>
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ interface StudentDao {
|
|||||||
@Query("SELECT * FROM Students")
|
@Query("SELECT * FROM Students")
|
||||||
fun loadAll(): Maybe<List<Student>>
|
fun loadAll(): Maybe<List<Student>>
|
||||||
|
|
||||||
@Query("UPDATE Students SET is_current = 1 WHERE student_id = :studentId")
|
@Query("UPDATE Students SET is_current = 1 WHERE id = :id")
|
||||||
fun updateCurrent(studentId: Int)
|
fun updateCurrent(id: Long)
|
||||||
|
|
||||||
@Query("UPDATE Students SET is_current = 0")
|
@Query("UPDATE Students SET is_current = 0")
|
||||||
fun resetCurrent()
|
fun resetCurrent()
|
||||||
|
@ -7,7 +7,7 @@ import androidx.room.PrimaryKey
|
|||||||
import org.threeten.bp.LocalDateTime
|
import org.threeten.bp.LocalDateTime
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id"], unique = true)])
|
@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id", "class_id"], unique = true)])
|
||||||
data class Student(
|
data class Student(
|
||||||
|
|
||||||
val endpoint: String,
|
val endpoint: String,
|
||||||
@ -32,6 +32,9 @@ data class Student(
|
|||||||
@ColumnInfo(name = "school_name")
|
@ColumnInfo(name = "school_name")
|
||||||
val schoolName: String,
|
val schoolName: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "class_id")
|
||||||
|
val classId: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "is_current")
|
@ColumnInfo(name = "is_current")
|
||||||
val isCurrent: Boolean,
|
val isCurrent: Boolean,
|
||||||
|
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package io.github.wulkanowy.data.db.migrations
|
||||||
|
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
|
||||||
|
class Migration12 : Migration(11, 12) {
|
||||||
|
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
createTempStudentsTable(database)
|
||||||
|
replaceStudentTable(database)
|
||||||
|
updateStudentsWithClassId(database, getStudentsIds(database))
|
||||||
|
removeStudentsWithNoClassId(database)
|
||||||
|
ensureThereIsOnlyOneCurrentStudent(database)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTempStudentsTable(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("""
|
||||||
|
CREATE TABLE IF NOT EXISTS Students_tmp (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
endpoint TEXT NOT NULL,
|
||||||
|
loginType TEXT NOT NULL,
|
||||||
|
email TEXT NOT NULL,
|
||||||
|
password TEXT NOT NULL,
|
||||||
|
symbol TEXT NOT NULL,
|
||||||
|
student_id INTEGER NOT NULL,
|
||||||
|
student_name TEXT NOT NULL,
|
||||||
|
school_id TEXT NOT NULL,
|
||||||
|
school_name TEXT NOT NULL,
|
||||||
|
is_current INTEGER NOT NULL,
|
||||||
|
registration_date INTEGER NOT NULL,
|
||||||
|
class_id INTEGER NOT NULL
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun replaceStudentTable(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
|
||||||
|
database.execSQL("INSERT INTO Students_tmp SELECT * FROM Students")
|
||||||
|
database.execSQL("DROP TABLE Students")
|
||||||
|
database.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getStudentsIds(database: SupportSQLiteDatabase): List<Int> {
|
||||||
|
val students = mutableListOf<Int>()
|
||||||
|
val studentsCursor = database.query("SELECT student_id FROM Students")
|
||||||
|
if (studentsCursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
students.add(studentsCursor.getInt(0))
|
||||||
|
} while (studentsCursor.moveToNext())
|
||||||
|
}
|
||||||
|
return students
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateStudentsWithClassId(database: SupportSQLiteDatabase, students: List<Int>) {
|
||||||
|
students.forEach {
|
||||||
|
database.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeStudentsWithNoClassId(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("DELETE FROM Students WHERE class_id = 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ensureThereIsOnlyOneCurrentStudent(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("UPDATE Students SET is_current = 0")
|
||||||
|
database.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package io.github.wulkanowy.data.exceptions
|
||||||
|
|
||||||
|
class NoCurrentStudentException : Exception("There no set current student in database")
|
@ -19,6 +19,6 @@ class SemesterLocal @Inject constructor(private val semesterDb: SemesterDao) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getSemesters(student: Student): Maybe<List<Semester>> {
|
fun getSemesters(student: Student): Maybe<List<Semester>> {
|
||||||
return semesterDb.loadAll(student.studentId).filter { !it.isEmpty() }
|
return semesterDb.loadAll(student.studentId, student.classId).filter { !it.isEmpty() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ class StudentLocal @Inject constructor(
|
|||||||
return Completable.fromCallable {
|
return Completable.fromCallable {
|
||||||
studentDb.run {
|
studentDb.run {
|
||||||
resetCurrent()
|
resetCurrent()
|
||||||
updateCurrent(student.studentId)
|
updateCurrent(student.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ class StudentRemote @Inject constructor(private val api: Api) {
|
|||||||
studentName = student.studentName,
|
studentName = student.studentName,
|
||||||
schoolSymbol = student.schoolSymbol,
|
schoolSymbol = student.schoolSymbol,
|
||||||
schoolName = student.schoolName,
|
schoolName = student.schoolName,
|
||||||
|
classId = student.classId,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
loginType = student.loginType.name,
|
loginType = student.loginType.name,
|
||||||
isCurrent = false,
|
isCurrent = false,
|
||||||
|
@ -4,6 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
|||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
import io.github.wulkanowy.data.ApiHelper
|
import io.github.wulkanowy.data.ApiHelper
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
@ -36,7 +37,7 @@ class StudentRepository @Inject constructor(
|
|||||||
|
|
||||||
fun getCurrentStudent(decryptPass: Boolean = true): Single<Student> {
|
fun getCurrentStudent(decryptPass: Boolean = true): Single<Student> {
|
||||||
return local.getCurrentStudent(decryptPass)
|
return local.getCurrentStudent(decryptPass)
|
||||||
.switchIfEmpty(Maybe.error(NoSuchElementException("No current student")))
|
.switchIfEmpty(Maybe.error(NoCurrentStudentException()))
|
||||||
.toSingle()
|
.toSingle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ class SyncManager @Inject constructor(
|
|||||||
fun startSyncWorker(restart: Boolean = false) {
|
fun startSyncWorker(restart: Boolean = false) {
|
||||||
if (preferencesRepository.isServiceEnabled && !now().isHolidays) {
|
if (preferencesRepository.isServiceEnabled && !now().isHolidays) {
|
||||||
workManager.enqueueUniquePeriodicWork(SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
|
workManager.enqueueUniquePeriodicWork(SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
|
||||||
PeriodicWorkRequest.Builder(SyncWorker::class.java, preferencesRepository.servicesInterval, MINUTES)
|
PeriodicWorkRequest.Builder(SyncWorker::class.java, preferencesRepository.servicesInterval, MINUTES, 10, MINUTES)
|
||||||
.setBackoffCriteria(EXPONENTIAL, 30, MINUTES)
|
.setBackoffCriteria(EXPONENTIAL, 30, MINUTES)
|
||||||
.setConstraints(Constraints.Builder()
|
.setConstraints(Constraints.Builder()
|
||||||
.setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) METERED else UNMETERED)
|
.setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) METERED else UNMETERED)
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package io.github.wulkanowy.ui.base.session
|
package io.github.wulkanowy.ui.base.session
|
||||||
|
|
||||||
|
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
|
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
|
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
|
|
||||||
open class BaseSessionFragment : BaseFragment(), BaseSessionView {
|
open class BaseSessionFragment : BaseFragment(), BaseSessionView {
|
||||||
@ -8,4 +11,11 @@ open class BaseSessionFragment : BaseFragment(), BaseSessionView {
|
|||||||
override fun showExpiredDialog() {
|
override fun showExpiredDialog() {
|
||||||
(activity as? MainActivity)?.showExpiredDialog()
|
(activity as? MainActivity)?.showExpiredDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openLoginView() {
|
||||||
|
activity?.also {
|
||||||
|
startActivity(LoginActivity.getStartIntent(it)
|
||||||
|
.apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ open class BaseSessionPresenter<T : BaseSessionView>(private val errorHandler: S
|
|||||||
|
|
||||||
override fun onAttachView(view: T) {
|
override fun onAttachView(view: T) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
errorHandler.onDecryptionFail = { view.showExpiredDialog() }
|
errorHandler.apply {
|
||||||
|
onDecryptionFail = { view.showExpiredDialog() }
|
||||||
|
onNoCurrentStudent = { view.openLoginView() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,4 +5,6 @@ import io.github.wulkanowy.ui.base.BaseView
|
|||||||
interface BaseSessionView : BaseView {
|
interface BaseSessionView : BaseView {
|
||||||
|
|
||||||
fun showExpiredDialog()
|
fun showExpiredDialog()
|
||||||
|
|
||||||
|
fun openLoginView()
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.base.session
|
|||||||
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import com.readystatesoftware.chuck.api.ChuckCollector
|
import com.readystatesoftware.chuck.api.ChuckCollector
|
||||||
|
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.security.ScramblerException
|
import io.github.wulkanowy.utils.security.ScramblerException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -13,9 +14,12 @@ open class SessionErrorHandler @Inject constructor(
|
|||||||
|
|
||||||
var onDecryptionFail: () -> Unit = {}
|
var onDecryptionFail: () -> Unit = {}
|
||||||
|
|
||||||
|
var onNoCurrentStudent: () -> Unit = {}
|
||||||
|
|
||||||
override fun proceed(error: Throwable) {
|
override fun proceed(error: Throwable) {
|
||||||
when (error) {
|
when (error) {
|
||||||
is ScramblerException -> onDecryptionFail()
|
is ScramblerException -> onDecryptionFail()
|
||||||
|
is NoCurrentStudentException -> onNoCurrentStudent()
|
||||||
else -> super.proceed(error)
|
else -> super.proceed(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -23,5 +27,6 @@ open class SessionErrorHandler @Inject constructor(
|
|||||||
override fun clear() {
|
override fun clear() {
|
||||||
super.clear()
|
super.clear()
|
||||||
onDecryptionFail = {}
|
onDecryptionFail = {}
|
||||||
|
onNoCurrentStudent = {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
Wersja 0.7.3
|
Wersja 0.7.4
|
||||||
|
|
||||||
Naprawiliśmy:
|
Naprawiliśmy:
|
||||||
- naprawiono problemy ze stabilnością podczas odświeżania danych
|
- problem ze stabilnością na androidach 4 i 5
|
||||||
|
- problem z przełączaniem kont, jeśli zalogowany był jednocześnie uczeń i rodzic
|
||||||
|
- problem z odświeżaniem danych, jeśli uczeń przeniósł się z klasy do klasy w bieżącym roku szkolnym
|
||||||
|
|
||||||
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.3
|
Dodaliśmy:
|
||||||
|
- nową opcję zmiany wartości plusa i minusa na 0.75
|
||||||
|
|
||||||
|
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases/tag/0.7.4
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@null" />
|
||||||
<stroke
|
<stroke
|
||||||
android:width="1dip"
|
android:width="1dip"
|
||||||
android:color="#61000000" />
|
android:color="#61000000" />
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
<item>0,25</item>
|
<item>0,25</item>
|
||||||
<item>0,33</item>
|
<item>0,33</item>
|
||||||
<item>0,5</item>
|
<item>0,5</item>
|
||||||
|
<item>0,75</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="grade_color_scheme_entries">
|
<string-array name="grade_color_scheme_entries">
|
||||||
|
@ -50,12 +50,14 @@
|
|||||||
<item>0,25</item>
|
<item>0,25</item>
|
||||||
<item>0,33</item>
|
<item>0,33</item>
|
||||||
<item>0,5</item>
|
<item>0,5</item>
|
||||||
|
<item>0,75</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="grade_modifier_value" translatable="false">
|
<string-array name="grade_modifier_value" translatable="false">
|
||||||
<item>0.0</item>
|
<item>0.0</item>
|
||||||
<item>0.25</item>
|
<item>0.25</item>
|
||||||
<item>0.33</item>
|
<item>0.33</item>
|
||||||
<item>0.5</item>
|
<item>0.5</item>
|
||||||
|
<item>0.75</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="grade_color_scheme_entries">
|
<string-array name="grade_color_scheme_entries">
|
||||||
|
@ -22,7 +22,7 @@ class StudentRemoteTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRemoteAll() {
|
fun testRemoteAll() {
|
||||||
doReturn(Single.just(listOf(Student("", "", 1, "test", "", "", Api.LoginType.AUTO))))
|
doReturn(Single.just(listOf(Student("", "", 1, "test", "", "", 1, Api.LoginType.AUTO))))
|
||||||
.`when`(mockApi).getStudents()
|
.`when`(mockApi).getStudents()
|
||||||
|
|
||||||
val students = StudentRemote(mockApi).getStudents("", "", "").blockingGet()
|
val students = StudentRemote(mockApi).getStudents("", "", "").blockingGet()
|
||||||
|
@ -86,7 +86,7 @@ class LoginFormPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun loginTest() {
|
fun loginTest() {
|
||||||
val studentTest = Student(email = "test@", password = "123", endpoint = "https://fakelog.cf", loginType = "AUTO", studentName = "", schoolSymbol = "", schoolName = "", studentId = 0, isCurrent = false, symbol = "", registrationDate = now())
|
val studentTest = Student(email = "test@", password = "123", endpoint = "https://fakelog.cf", loginType = "AUTO", studentName = "", schoolSymbol = "", schoolName = "", studentId = 0, classId = 1, isCurrent = false, symbol = "", registrationDate = now())
|
||||||
doReturn(Single.just(listOf(studentTest)))
|
doReturn(Single.just(listOf(studentTest)))
|
||||||
.`when`(repository).getStudents(anyString(), anyString(), anyString(), anyString())
|
.`when`(repository).getStudents(anyString(), anyString(), anyString(), anyString())
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class LoginStudentSelectPresenterTest {
|
|||||||
|
|
||||||
private lateinit var presenter: LoginStudentSelectPresenter
|
private lateinit var presenter: LoginStudentSelectPresenter
|
||||||
|
|
||||||
private val testStudent by lazy { Student(email = "test", password = "test123", endpoint = "https://fakelog.cf", loginType = "AUTO", symbol = "", isCurrent = false, studentId = 0, schoolName = "", schoolSymbol = "", studentName = "", registrationDate = now()) }
|
private val testStudent by lazy { Student(email = "test", password = "test123", endpoint = "https://fakelog.cf", loginType = "AUTO", symbol = "", isCurrent = false, studentId = 0, schoolName = "", schoolSymbol = "", classId = 1, studentName = "", registrationDate = now()) }
|
||||||
|
|
||||||
private val testException by lazy { RuntimeException("Problem") }
|
private val testException by lazy { RuntimeException("Problem") }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user