mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-02-21 19:24:44 +01:00
Merge branch 'release/0.19.0'
This commit is contained in:
commit
9f87b92937
@ -14,7 +14,7 @@ cache:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- develop
|
- develop
|
||||||
- 0.18.3
|
- 0.19.0
|
||||||
|
|
||||||
android:
|
android:
|
||||||
licenses:
|
licenses:
|
||||||
|
@ -17,8 +17,8 @@ android {
|
|||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 17
|
minSdkVersion 17
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 62
|
versionCode 63
|
||||||
versionName "0.18.3"
|
versionName "0.19.0"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
resValue "string", "app_name", "Wulkanowy"
|
resValue "string", "app_name", "Wulkanowy"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
@ -77,8 +77,8 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewBinding {
|
buildFeatures {
|
||||||
enabled = true
|
viewBinding = true
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
@ -124,14 +124,14 @@ configurations.all {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:sdk:0.18.3"
|
implementation "io.github.wulkanowy:sdk:0.19.0"
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "androidx.core:core-ktx:1.2.0"
|
implementation "androidx.core:core-ktx:1.2.0"
|
||||||
implementation "androidx.activity:activity-ktx:1.1.0"
|
implementation "androidx.activity:activity-ktx:1.1.0"
|
||||||
implementation "androidx.appcompat:appcompat:1.2.0-rc01"
|
implementation "androidx.appcompat:appcompat:1.2.0-rc01"
|
||||||
implementation "androidx.appcompat:appcompat-resources:1.1.0"
|
implementation "androidx.appcompat:appcompat-resources:1.1.0"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.2.4"
|
implementation "androidx.fragment:fragment-ktx:1.2.5"
|
||||||
implementation "androidx.annotation:annotation:1.1.0"
|
implementation "androidx.annotation:annotation:1.1.0"
|
||||||
implementation "androidx.multidex:multidex:2.0.1"
|
implementation "androidx.multidex:multidex:2.0.1"
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ dependencies {
|
|||||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||||
implementation "com.google.android.material:material:1.1.0"
|
implementation "com.google.android.material:material:1.1.0"
|
||||||
implementation "com.github.wulkanowy:material-chips-input:2.0.1"
|
implementation "com.github.wulkanowy:material-chips-input:2.1.1"
|
||||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||||
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
|
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
|
||||||
|
|
||||||
@ -180,12 +180,13 @@ dependencies {
|
|||||||
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
||||||
implementation "io.coil-kt:coil:0.11.0"
|
implementation "io.coil-kt:coil:0.11.0"
|
||||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
||||||
|
implementation 'me.xdrop:fuzzywuzzy:1.3.1'
|
||||||
|
|
||||||
playImplementation 'com.google.firebase:firebase-analytics:17.4.2'
|
playImplementation 'com.google.firebase:firebase-analytics:17.4.3'
|
||||||
playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.0.7'
|
playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.0.7'
|
||||||
playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.0.7"
|
playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.0.7"
|
||||||
playImplementation 'com.google.firebase:firebase-messaging:20.2.0'
|
playImplementation 'com.google.firebase:firebase-messaging:20.2.0'
|
||||||
playImplementation 'com.google.firebase:firebase-crashlytics:17.0.0'
|
playImplementation 'com.google.firebase:firebase-crashlytics:17.0.1'
|
||||||
playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
|
playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
|
||||||
|
|
||||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||||
|
@ -1741,4 +1741,4 @@
|
|||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd101f5a26a024f62e6fee161e421b882')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd101f5a26a024f62e6fee161e421b882')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1768
app/schemas/io.github.wulkanowy.data.db.AppDatabase/26.json
Normal file
1768
app/schemas/io.github.wulkanowy.data.db.AppDatabase/26.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -120,23 +120,23 @@ class Migration13Test : AbstractMigrationTest() {
|
|||||||
assertEquals(2, first.diaryId)
|
assertEquals(2, first.diaryId)
|
||||||
}
|
}
|
||||||
|
|
||||||
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
|
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let { semesters ->
|
||||||
assertTrue { it.single { it.second }.second }
|
assertTrue { semesters.single { it.second }.second }
|
||||||
assertEquals(1970, it[0].first.schoolYear)
|
assertEquals(1970, semesters[0].first.schoolYear)
|
||||||
assertEquals(of(1970, 1, 1), it[0].first.end)
|
assertEquals(of(1970, 1, 1), semesters[0].first.end)
|
||||||
assertEquals(of(1970, 1, 1), it[0].first.start)
|
assertEquals(of(1970, 1, 1), semesters[0].first.start)
|
||||||
assertFalse(it[0].second)
|
assertFalse(semesters[0].second)
|
||||||
assertFalse(it[1].second)
|
assertFalse(semesters[1].second)
|
||||||
assertFalse(it[2].second)
|
assertFalse(semesters[2].second)
|
||||||
assertTrue(it[3].second)
|
assertTrue(semesters[3].second)
|
||||||
}
|
}
|
||||||
|
|
||||||
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
|
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let { semesters ->
|
||||||
assertTrue { it.single { it.second }.second }
|
assertTrue { semesters.single { it.second }.second }
|
||||||
assertFalse(it[0].second)
|
assertFalse(semesters[0].second)
|
||||||
assertFalse(it[1].second)
|
assertFalse(semesters[1].second)
|
||||||
assertFalse(it[2].second)
|
assertFalse(semesters[2].second)
|
||||||
assertTrue(it[3].second)
|
assertTrue(semesters[3].second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import org.junit.After
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
import org.threeten.bp.LocalDate.now
|
import org.threeten.bp.LocalDate.now
|
||||||
import org.threeten.bp.LocalDate.of
|
import org.threeten.bp.LocalDate.of
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -35,9 +36,18 @@ class AttendanceLocalTest {
|
|||||||
@Test
|
@Test
|
||||||
fun saveAndReadTest() {
|
fun saveAndReadTest() {
|
||||||
attendanceLocal.saveAttendance(listOf(
|
attendanceLocal.saveAttendance(listOf(
|
||||||
Attendance(1, 2, 3, of(2018, 9, 10), 0, "", "", false, false, false, false, false, false, false, SentExcuseStatus.ACCEPTED.name),
|
getAttendanceEntity(
|
||||||
Attendance(1, 2, 3, of(2018, 9, 14), 0, "", "", false, false, false, false, false, false, false, SentExcuseStatus.WAITING.name),
|
of(2018, 9, 10),
|
||||||
Attendance(1, 2, 3, of(2018, 9, 17), 0, "", "", false, false, false, false, false, false, false, SentExcuseStatus.ACCEPTED.name)
|
SentExcuseStatus.ACCEPTED
|
||||||
|
),
|
||||||
|
getAttendanceEntity(
|
||||||
|
of(2018, 9, 14),
|
||||||
|
SentExcuseStatus.WAITING
|
||||||
|
),
|
||||||
|
getAttendanceEntity(
|
||||||
|
of(2018, 9, 17),
|
||||||
|
SentExcuseStatus.ACCEPTED
|
||||||
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
val attendance = attendanceLocal
|
val attendance = attendanceLocal
|
||||||
@ -50,4 +60,25 @@ class AttendanceLocalTest {
|
|||||||
assertEquals(attendance[0].date, of(2018, 9, 10))
|
assertEquals(attendance[0].date, of(2018, 9, 10))
|
||||||
assertEquals(attendance[1].date, of(2018, 9, 14))
|
assertEquals(attendance[1].date, of(2018, 9, 14))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getAttendanceEntity(
|
||||||
|
date: LocalDate,
|
||||||
|
excuseStatus: SentExcuseStatus
|
||||||
|
) = Attendance(
|
||||||
|
studentId = 1,
|
||||||
|
diaryId = 2,
|
||||||
|
timeId = 3,
|
||||||
|
date = date,
|
||||||
|
number = 0,
|
||||||
|
subject = "",
|
||||||
|
name = "",
|
||||||
|
presence = false,
|
||||||
|
absence = false,
|
||||||
|
exemption = false,
|
||||||
|
lateness = false,
|
||||||
|
excused = false,
|
||||||
|
deleted = false,
|
||||||
|
excusable = false,
|
||||||
|
excuseStatus = excuseStatus.name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import androidx.test.core.app.ApplicationProvider
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
package io.github.wulkanowy.utils
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
open class TimberTreeNoOp : Timber.Tree() {
|
open class TimberTreeNoOp : Timber.Tree() {
|
||||||
|
94
app/src/main/assets/message-print-page.html
Normal file
94
app/src/main/assets/message-print-page.html
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="pl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>%SUBJECT% | Wulkanowy</title>
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
margin: 2.5cm;
|
||||||
|
size: A4;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
line-height: 1.5;
|
||||||
|
letter-spacing: 1pt;
|
||||||
|
font-size: 24pt;
|
||||||
|
font-weight: 200;
|
||||||
|
margin: 0 0 0.5cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
margin: 0.5cm 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info div {
|
||||||
|
font-size: 14pt;
|
||||||
|
font-weight: 400;
|
||||||
|
margin: 0.5cm 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-weight: 200;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1pt;
|
||||||
|
font-size: 10pt;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.25cm;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-top: 0.5cm;
|
||||||
|
font-size: 14pt;
|
||||||
|
font-weight: 400;
|
||||||
|
text-align: justify;
|
||||||
|
font-family: serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content p {
|
||||||
|
page-break-after: auto;
|
||||||
|
page-break-inside: auto;
|
||||||
|
margin-bottom: 0.6cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
font-size: 11pt;
|
||||||
|
font-weight: 200;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: rgba(0, 0, 0, 0.5)
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.5cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .logo {
|
||||||
|
height: 0.5cm;
|
||||||
|
width: 0.5cm;
|
||||||
|
display: block;
|
||||||
|
margin-right: 0.2cm;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 class="title">%SUBJECT%</h1>
|
||||||
|
<hr>
|
||||||
|
<div class="info">
|
||||||
|
%INFO%
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<img src="wulkanowy-logo-black.svg" class="logo">
|
||||||
|
Wulkanowy Dzienniczek
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="content">
|
||||||
|
<h4>Treść wiadomości</h4>
|
||||||
|
%CONTENT%
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
74
app/src/main/assets/wulkanowy-logo-black.svg
Normal file
74
app/src/main/assets/wulkanowy-logo-black.svg
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
version="1.1"
|
||||||
|
id="Layer_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 1024 1024"
|
||||||
|
xml:space="preserve"
|
||||||
|
width="1024"
|
||||||
|
height="1024"><metadata
|
||||||
|
id="metadata15"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs13" /><style
|
||||||
|
type="text/css"
|
||||||
|
id="style2">
|
||||||
|
.st0{fill:#D32F2F;}
|
||||||
|
.st1{fill:#AD2A2A;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
</style><g
|
||||||
|
id="layer4"
|
||||||
|
style="display:none;fill:#808080"><rect
|
||||||
|
id="XMLID_57_"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
class="st0"
|
||||||
|
width="3584"
|
||||||
|
height="1024"
|
||||||
|
style="display:inline;fill:#808080;stroke-width:1.02195609" /></g><g
|
||||||
|
id="layer3"
|
||||||
|
style="display:none;fill:#808080"><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="M 3046.8164,390.66602 3134.3164,542 v 91.33398 L 3524.9824,1024 H 3584 V 732.18359 L 3242.4824,390.66602 h -23.666 l -53.0352,94.63086 -94.6308,-94.63086 z"
|
||||||
|
id="path18992" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="m 2746.9824,390.66602 62,242.66796 L 3199.6484,1024 H 3584 V 940.68359 L 3033.9824,390.66602 h -21 l -21.9043,90.92773 -90.9277,-90.92773 h -18.5 l -25.4043,88.26367 -88.2637,-88.26367 z"
|
||||||
|
id="path18990" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="m 2620.8164,387.33398 c -18.6667,0 -35.1667,4.60982 -49.5,13.83204 -14.3333,9.11111 -25.4451,22.22287 -33.334,39.33398 -7.7778,17 -11.666,36.5549 -11.666,58.66602 v 25 c 0,34.44444 8.7216,61.83463 26.166,82.16796 L 2970.1484,1024 h 323.168 l -623.166,-623.16602 c -14.2222,-9 -30.6673,-13.5 -49.334,-13.5 z"
|
||||||
|
id="path18988" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="M 2293.4824,390.66602 V 633.33398 L 2684.1484,1024 h 423.336 l -633.334,-633.33398 h -20.334 v 139.66601 l -139.666,-139.66601 z"
|
||||||
|
id="path18984" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="M 1864.8164,390.66602 V 633.33398 L 2255.4824,1024 h 413.334 l -633.334,-633.33398 h -25.832 l -60.584,63.75 -63.75,-63.75 z"
|
||||||
|
id="path18978" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="M 1684.8164,390.66602 V 633.33398 L 2075.4824,1024 h 263.334 l -633.334,-633.33398 z"
|
||||||
|
id="path18976" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="m 1133.6504,390.66602 62,242.66796 L 1586.3164,1024 h 467.668 l -633.334,-633.33398 h -21 l -21.9043,90.92773 -90.9277,-90.92773 h -18.5 l -25.4043,88.26367 -88.2637,-88.26367 z"
|
||||||
|
id="path19059" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="m 1456.4824,390.66602 v 167.16796 c 0.5556,24.66667 8.5007,44 23.834,58 L 1888.4824,1024 h 372.168 l -633.334,-633.33398 h -20.666 V 520.5 l -129.834,-129.83398 z"
|
||||||
|
id="path18966" /><path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;display:inline;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="M 2146.3164,390.66602 2054.4824,633.33398 2445.1484,1024 h 354.002 l -633.334,-633.33398 z"
|
||||||
|
id="path18982" /><path
|
||||||
|
style="display:inline;fill:#808080;stroke-width:0.78179646"
|
||||||
|
d="M 637.15234,214.95703 487.75,364.35742 466.01562,386.0918 c 0.31273,0.31271 0.54872,0.54666 0.70508,0.85937 0.0782,0.23454 0.23432,0.54671 0.3125,0.78125 0.31272,0.54726 0.47071,1.17339 0.47071,1.79883 0.0782,0.54726 -0.0799,1.01725 -0.31446,1.48633 -0.23454,0.54725 -0.70285,1.40597 -1.09375,1.79687 l 150.8086,149.71485 -23.68946,23.6875 -12.74414,-12.74219 -13.44726,-13.44727 -78.80469,-78.80664 -11.17969,-11.17968 -7.5039,-7.50391 -35.41602,-35.17969 -3.08984,-0.98047 -4.33594,4.26367 v 0.46876 c 0,7.34888 0.38998,15.00865 -1.48633,22.20117 -0.85998,3.28355 -2.34444,6.25595 -4.14258,8.91406 -0.15636,0.15636 -0.23627,0.23426 -0.31445,0.39062 -1.87631,2.57993 -4.06471,4.84619 -6.48828,6.95704 -5.3944,4.53442 -11.25752,8.67896 -17.27734,12.50976 -0.15637,0.0782 -0.23427,0.1562 -0.39063,0.23438 -2.11085,1.40723 -4.3012,2.7354 -6.49023,4.06445 -8.91248,5.39439 -18.37192,10.08772 -28.37891,13.13672 -1.25087,0.31272 -2.42317,-0.001 -3.36133,-0.70508 l -6.01953,5.94141 c 1.25087,0.62543 2.03136,1.87776 1.875,3.51953 -10e-6,0.15636 -0.0762,0.23231 -0.0762,0.38867 0,0.0782 -0.0781,0.23628 -0.0781,0.31445 -1.32905,4.45624 -2.34505,8.98897 -3.2832,13.60156 -0.15636,0.70363 -0.23622,1.33154 -0.39258,2.03516 -0.85997,4.37806 -1.64209,8.83288 -2.3457,13.21094 0.23453,5.3944 0.39263,11.0234 0.31445,16.65234 v 0.39258 c -0.0782,7.66161 -0.78373,15.32114 -2.8164,22.51367 -2.26721,8.28704 -6.64376,15.63728 -10.55274,23.22071 -0.0782,0.15636 -0.15815,0.23426 -0.23633,0.39062 -1.25088,2.42357 -2.49924,4.92399 -3.59375,7.50391 -4.84714,11.33605 -7.42749,23.92328 -10.55468,35.88476 -0.23454,0.70362 -0.39046,1.48578 -0.625,2.26758 0,0.15636 -0.0801,0.23427 -0.0801,0.39063 -2.97082,11.10151 -6.09819,22.28173 -10.94532,32.75781 -1.40724,2.97082 -2.81531,5.86322 -4.3789,8.75586 -0.15636,0.23454 -0.23231,0.46858 -0.38867,0.70312 -0.62544,1.09451 -1.25152,2.26871 -1.87696,3.44141 -0.0782,0.15636 -0.15619,0.23426 -0.23437,0.39062 -3.51809,6.25438 -7.27098,12.43118 -10.78906,18.68555 -5.0035,8.8343 -8.99075,18.13635 -13.83789,27.04883 -0.0782,0.15636 -0.1562,0.23426 -0.23438,0.39062 -0.70362,1.32905 -1.48579,2.65728 -2.26758,3.98633 -5.0035,8.20887 -10.63256,16.0279 -16.57422,23.61133 -0.15635,0.15636 -0.23426,0.3124 -0.39062,0.46875 -0.7818,1.01634 -1.48578,1.95443 -2.26758,2.89258 -3.90898,4.92532 -7.97378,9.85009 -11.96094,14.77539 -0.0782,0.15637 -0.23432,0.23622 -0.3125,0.39258 -8.75612,10.71061 -17.35628,21.49761 -24.54883,33.30273 0,0.70362 -0.15602,1.33159 -0.46874,1.95703 -1.25087,2.42357 -2.65734,4.68971 -3.90821,7.11328 -0.0782,0.15636 0.62511,1.24989 0.46875,1.40625 L 429.86133,1024 H 1463.0215 L 661.85547,222.92969 c -0.93816,2.11087 -5.23681,1.40935 -7.34766,-0.23242 -1.71995,-1.32906 -3.12603,-3.05147 -4.45508,-4.84961 -0.62544,-0.31271 -1.25168,-0.62288 -1.64257,-0.85743 -2.89265,-1.40723 -6.09933,-1.48632 -9.30469,-1.48632 -0.7818,-0.0782 -1.40588,-0.23416 -1.95313,-0.54688 z m -206.12304,191.41992 0.11914,-0.11523 -0.23438,0.0781 z"
|
||||||
|
id="XMLID_64_" /></g><g
|
||||||
|
id="layer2"
|
||||||
|
style="display:inline;fill:#000000;fill-opacity:0.49803922"><path
|
||||||
|
id="XMLID_42_"
|
||||||
|
d="m 295.17362,965.05417 c 1.0692,3.47527 0.5346,7.21786 -1.3367,10.29214 l -25.7972,41.83679 c -2.5396,4.1436 -7.2178,6.8169 -12.297,6.8169 H 14.345318 C 3.1176178,1024 -3.6991822,1012.2376 2.3157178,1003.4158 L 157.76692,774.44928 c 0.9356,-1.33663 1.4704,-2.80694 1.8713,-4.27723 l 71.2428,-304.21933 c 0.8021,-3.60893 3.2081,-6.6832 6.6833,-8.55449 l 96.5054,-52.93096 c 3.4753,-1.8713 5.8812,-4.94557 6.6832,-8.68816 l 12.9654,-56.53988 c 2.6733,-11.76242 19.5151,-14.30205 26.1981,-4.00991 l 4.6783,7.48519 c 2.0049,3.20793 2.5396,7.21785 1.2031,10.82678 l -87.9511,254.22895 c -0.6683,2.00497 -0.9355,4.1436 -0.5346,6.28223 l 21.9209,121.63426 c 0.401,2.40595 0.1334,4.94556 -0.9357,7.21785 l -52.2625,117.357 c -1.203,2.80696 -1.4704,5.88123 -0.5347,8.68817 z M 1009.7413,1024 H 843.46322 c -4.8117,0 -9.2228,-2.4059 -11.8959,-6.1485 L 719.69042,860.52891 c -0.6683,-1.0693 -1.3366,-2.13861 -1.7375,-3.3416 l -55.4707,-162.00078 c -1.0692,-3.20793 -3.6088,-6.01489 -6.8169,-7.61886 l -135.8026,-68.56965 c -3.7426,-1.87127 -6.4159,-5.34655 -7.2179,-9.22281 l -20.0495,-99.44603 c -0.2674,-1.60396 -0.9357,-3.20793 -2.005,-4.67824 l -46.1141,-67.76766 c -2.5396,-3.74259 -2.9405,-8.28717 -1.0693,-12.2971 l 28.0694,-60.01513 c 2.1387,-4.54457 6.817,-7.61886 12.1634,-7.88619 l 52.129,-3.07427 c 3.0742,-0.1337 5.8812,-1.20296 8.1536,-3.07427 l 38.3615,-29.80707 c 7.2178,-5.61388 18.1784,-3.20794 22.0546,4.67824 l 132.1937,268.93201 c 0.5346,1.20297 0.9357,2.40595 1.2029,3.60894 l 16.3072,108.13418 c 0.4009,2.53963 1.4701,4.8119 3.2079,6.6832 l 263.31808,288.17958 c 7.7525,8.5545 1.203,22.0546 -10.8269,22.0546 z M 363.20852,182.58501 c 0,-30.60907 19.3812,-56.94088 47.1834,-69.23798 -2.005,-3.3416 -3.2079,-6.95052 -3.2079,-10.82678 0,-14.836705 17.109,-26.866465 38.0942,-26.866465 0.5346,0 0.9356,0 1.4704,0 8.688,-14.43572 25.2624,-24.19318 44.2426,-24.19318 1.3367,0 2.6733,0 4.01,0.1337 1.7377,0.13369 3.4753,-0.66833 4.4109,-2.00497 14.0347,-21.38624 49.5894,-36.62394 91.159,-36.62394 15.3712,0 29.9406,2.13863 42.906,5.74756 3.0744,-5.07924 9.8911,-8.5545 17.7773,-8.5545 8.9556,0 16.5744,4.54458 18.8466,10.82678 10.9606,-12.69809 29.5398,-20.98524 50.6587,-20.98524 33.6834,0 60.9508,21.25257 60.9508,47.45072 0,3.20793 -0.401,6.2822 -1.203,9.35647 -0.5346,2.13864 0.6683,4.27725 2.9407,5.07924 21.5199,7.88618 36.0893,22.85655 36.0893,39.965535 0,19.51495 -18.8466,36.22296 -45.4458,42.77249 -2.1387,0.53466 -3.4753,2.40595 -3.4753,4.41092 0,0.1337 0,0.26731 0,0.40098 0,15.10404 -14.9704,27.5348 -34.218,28.87144 0.1333,0.66833 0.1333,1.33663 0.1333,2.13862 0,29.00509 -55.2031,52.3963 -123.2382,52.3963 -14.7029,0 -28.7377,-1.06932 -41.7031,-3.07427 0,0.26733 0,0.40099 0,0.66832 0,12.02975 -15.5051,21.78723 -34.4854,21.78723 -1.0692,0 -2.0049,0 -2.9405,-0.13369 1.3367,2.9406 2.005,6.01487 2.005,9.22281 0,18.71296 -23.6586,33.81699 -52.9311,33.81699 -3.2079,0 -6.2821,-0.1337 -9.3563,-0.53466 -2.4061,-0.26731 -4.6783,1.20299 -5.2131,3.47529 -2.5396,9.35647 -10.693,16.17333 -20.4504,16.17333 -11.7625,0 -21.119,-10.0248 -21.119,-22.32189 0,-5.74755 2.005,-10.96045 5.3466,-14.83671 1.203,-1.33663 1.6039,-3.20793 0.8019,-4.81191 -1.8713,-3.47526 -2.6733,-7.08419 -2.6733,-10.96044 v 0 c 0,-2.13862 -1.7376,-3.87626 -3.8763,-4.4109 -36.2228,-8.01985 -63.4903,-38.22792 -63.4903,-74.3172 z m 306.8925,726.06294 c 0.5348,1.60398 0.6683,3.20796 0.6683,4.94558 l -7.7525,97.97577 c -0.5346,6.9505 -6.6832,12.4307 -14.1683,12.4307 h -250.219 c -5.3466,0 -10.2921,-3.0743 -12.6982,-7.4852 l -41.3021,-76.72312 c -0.2673,-0.401 -0.401,-0.80199 -0.5347,-1.20298 l -38.8962,-94.23313 c -1.4702,-3.3416 -1.203,-7.21785 0.4011,-10.42581 l 64.5596,-126.31249 c 1.604,-3.07427 1.8712,-6.6832 0.6683,-9.89114 l -31.5447,-87.41626 c -1.0693,-3.07428 -0.9356,-6.54955 0.4011,-9.49015 l 52.6636,-112.14412 c 5.3464,-11.22778 22.8565,-10.29212 26.5991,1.47031 l 16.4407,51.05965 50.124,134.19868 c 1.3367,3.7426 4.5446,6.6832 8.5545,8.01985 l 106.9312,36.49027 c 4.1435,1.47032 7.3516,4.54458 8.6881,8.42084 z"
|
||||||
|
style="fill:#000000;stroke-width:0.78179646;fill-opacity:0.49803922" /><g
|
||||||
|
aria-label="WULKANOWY"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:341.33334351px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto Light';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:0.49803922;stroke:none"
|
||||||
|
id="text4752" /></g></svg>
|
After Width: | Height: | Size: 13 KiB |
@ -1,17 +1,15 @@
|
|||||||
package io.github.wulkanowy.data
|
package io.github.wulkanowy.data
|
||||||
|
|
||||||
import android.app.AlarmManager
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.res.AssetManager
|
import android.content.res.AssetManager
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import androidx.core.content.getSystemService
|
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.WalledGardenInternetObservingStrategy
|
|
||||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||||
import com.chuckerteam.chucker.api.RetentionManager
|
import com.chuckerteam.chucker.api.RetentionManager
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.WalledGardenInternetObservingStrategy
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
|
@ -68,6 +68,7 @@ import io.github.wulkanowy.data.db.migrations.Migration22
|
|||||||
import io.github.wulkanowy.data.db.migrations.Migration23
|
import io.github.wulkanowy.data.db.migrations.Migration23
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration24
|
import io.github.wulkanowy.data.db.migrations.Migration24
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration25
|
import io.github.wulkanowy.data.db.migrations.Migration25
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration26
|
||||||
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
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||||
@ -110,7 +111,7 @@ import javax.inject.Singleton
|
|||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 25
|
const val VERSION_SCHEMA = 26
|
||||||
|
|
||||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
||||||
return arrayOf(
|
return arrayOf(
|
||||||
@ -137,7 +138,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
Migration22(),
|
Migration22(),
|
||||||
Migration23(),
|
Migration23(),
|
||||||
Migration24(),
|
Migration24(),
|
||||||
Migration25()
|
Migration25(),
|
||||||
|
Migration26()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.entities
|
|||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
import org.threeten.bp.LocalDateTime
|
||||||
|
|
||||||
@Entity(tableName = "GradesSummary")
|
@Entity(tableName = "GradesSummary")
|
||||||
data class GradeSummary(
|
data class GradeSummary(
|
||||||
@ -36,4 +37,16 @@ data class GradeSummary(
|
|||||||
) {
|
) {
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
|
@ColumnInfo(name = "is_predicted_grade_notified")
|
||||||
|
var isPredictedGradeNotified: Boolean = true
|
||||||
|
|
||||||
|
@ColumnInfo(name = "is_final_grade_notified")
|
||||||
|
var isFinalGradeNotified: Boolean = true
|
||||||
|
|
||||||
|
@ColumnInfo(name = "predicted_grade_last_change")
|
||||||
|
var predictedGradeLastChange: LocalDateTime = LocalDateTime.now()
|
||||||
|
|
||||||
|
@ColumnInfo(name = "final_grade_last_change")
|
||||||
|
var finalGradeLastChange: LocalDateTime = LocalDateTime.now()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package io.github.wulkanowy.data.db.migrations
|
||||||
|
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
|
||||||
|
class Migration26 : Migration(25, 26) {
|
||||||
|
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_predicted_grade_notified INTEGER NOT NULL DEFAULT 1")
|
||||||
|
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_final_grade_notified INTEGER NOT NULL DEFAULT 1")
|
||||||
|
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN predicted_grade_last_change INTEGER NOT NULL DEFAULT 0")
|
||||||
|
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN final_grade_last_change INTEGER NOT NULL DEFAULT 0")
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ import javax.inject.Singleton
|
|||||||
@Singleton
|
@Singleton
|
||||||
class AppCreatorRepository @Inject constructor(private val assets: AssetManager) {
|
class AppCreatorRepository @Inject constructor(private val assets: AssetManager) {
|
||||||
fun getAppCreators(): Single<List<Contributor>> {
|
fun getAppCreators(): Single<List<Contributor>> {
|
||||||
return Single.fromCallable<List<Contributor>> {
|
return Single.fromCallable {
|
||||||
Gson().fromJson(
|
Gson().fromJson(
|
||||||
assets.open("contributors.json").bufferedReader().use { it.readText() },
|
assets.open("contributors.json").bufferedReader().use { it.readText() },
|
||||||
Array<Contributor>::class.java
|
Array<Contributor>::class.java
|
||||||
|
@ -13,7 +13,7 @@ class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
|||||||
|
|
||||||
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Exam>> {
|
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Exam>> {
|
||||||
return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
||||||
.filter { !it.isEmpty() }
|
.filter { it.isNotEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveExams(exams: List<Exam>) {
|
fun saveExams(exams: List<Exam>) {
|
||||||
|
@ -27,6 +27,10 @@ class GradeLocal @Inject constructor(
|
|||||||
gradeDb.updateAll(grades)
|
gradeDb.updateAll(grades)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||||
|
gradeSummaryDb.updateAll(gradesSummary)
|
||||||
|
}
|
||||||
|
|
||||||
fun getGradesDetails(semester: Semester): Maybe<List<Grade>> {
|
fun getGradesDetails(semester: Semester): Maybe<List<Grade>> {
|
||||||
return gradeDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
|
return gradeDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import io.github.wulkanowy.data.db.entities.Student
|
|||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
import org.threeten.bp.LocalDateTime
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -43,7 +44,31 @@ class GradeRepository @Inject constructor(
|
|||||||
local.getGradesSummary(semester).toSingle(emptyList())
|
local.getGradesSummary(semester).toSingle(emptyList())
|
||||||
.doOnSuccess { old ->
|
.doOnSuccess { old ->
|
||||||
local.deleteGradesSummary(old.uniqueSubtract(newSummary))
|
local.deleteGradesSummary(old.uniqueSubtract(newSummary))
|
||||||
local.saveGradesSummary(newSummary.uniqueSubtract(old))
|
local.saveGradesSummary(newSummary.uniqueSubtract(old)
|
||||||
|
.onEach { summary ->
|
||||||
|
val oldSummary = old.find { oldSummary -> oldSummary.subject == summary.subject }
|
||||||
|
summary.isPredictedGradeNotified = when {
|
||||||
|
summary.predictedGrade.isEmpty() -> true
|
||||||
|
notify && oldSummary?.predictedGrade != summary.predictedGrade -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
summary.isFinalGradeNotified = when {
|
||||||
|
summary.finalGrade.isEmpty() -> true
|
||||||
|
notify && oldSummary?.finalGrade != summary.finalGrade -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.predictedGradeLastChange = when {
|
||||||
|
oldSummary == null -> LocalDateTime.now()
|
||||||
|
summary.predictedGrade != oldSummary.predictedGrade -> LocalDateTime.now()
|
||||||
|
else -> oldSummary.predictedGradeLastChange
|
||||||
|
}
|
||||||
|
summary.finalGradeLastChange = when {
|
||||||
|
oldSummary == null -> LocalDateTime.now()
|
||||||
|
summary.finalGrade != oldSummary.finalGrade -> LocalDateTime.now()
|
||||||
|
else -> oldSummary.finalGradeLastChange
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.flatMap {
|
}.flatMap {
|
||||||
@ -63,6 +88,14 @@ class GradeRepository @Inject constructor(
|
|||||||
return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } }.toSingle(emptyList())
|
return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } }.toSingle(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getNotNotifiedPredictedGrades(semester: Semester): Single<List<GradeSummary>> {
|
||||||
|
return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } }.toSingle(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNotNotifiedFinalGrades(semester: Semester): Single<List<GradeSummary>> {
|
||||||
|
return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } }.toSingle(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
fun updateGrade(grade: Grade): Completable {
|
fun updateGrade(grade: Grade): Completable {
|
||||||
return Completable.fromCallable { local.updateGrades(listOf(grade)) }
|
return Completable.fromCallable { local.updateGrades(listOf(grade)) }
|
||||||
}
|
}
|
||||||
@ -70,4 +103,8 @@ class GradeRepository @Inject constructor(
|
|||||||
fun updateGrades(grades: List<Grade>): Completable {
|
fun updateGrades(grades: List<Grade>): Completable {
|
||||||
return Completable.fromCallable { local.updateGrades(grades) }
|
return Completable.fromCallable { local.updateGrades(grades) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateGradesSummary(gradesSummary: List<GradeSummary>): Completable {
|
||||||
|
return Completable.fromCallable { local.updateGradesSummary(gradesSummary) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import javax.inject.Singleton
|
|||||||
class RecipientLocal @Inject constructor(private val recipientDb: RecipientDao) {
|
class RecipientLocal @Inject constructor(private val recipientDb: RecipientDao) {
|
||||||
|
|
||||||
fun getRecipients(student: Student, role: Int, unit: ReportingUnit): Maybe<List<Recipient>> {
|
fun getRecipients(student: Student, role: Int, unit: ReportingUnit): Maybe<List<Recipient>> {
|
||||||
return recipientDb.load(student.studentId, role, unit.realId).filter { !it.isEmpty() }
|
return recipientDb.load(student.studentId, role, unit.realId).filter { it.isNotEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveRecipients(recipients: List<Recipient>): List<Long> {
|
fun saveRecipients(recipients: List<Recipient>): List<Long> {
|
||||||
|
@ -11,7 +11,7 @@ import javax.inject.Singleton
|
|||||||
class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: ReportingUnitDao) {
|
class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: ReportingUnitDao) {
|
||||||
|
|
||||||
fun getReportingUnits(student: Student): Maybe<List<ReportingUnit>> {
|
fun getReportingUnits(student: Student): Maybe<List<ReportingUnit>> {
|
||||||
return reportingUnitDb.load(student.studentId).filter { !it.isEmpty() }
|
return reportingUnitDb.load(student.studentId).filter { it.isNotEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getReportingUnit(student: Student, unitId: Int): Maybe<ReportingUnit> {
|
fun getReportingUnit(student: Student, unitId: Int): Maybe<ReportingUnit> {
|
||||||
|
@ -14,7 +14,7 @@ class StudentRemote @Inject constructor(private val sdk: Sdk) {
|
|||||||
private fun mapStudents(students: List<SdkStudent>, email: String, password: String): List<Student> {
|
private fun mapStudents(students: List<SdkStudent>, email: String, password: String): List<Student> {
|
||||||
return students.map { student ->
|
return students.map { student ->
|
||||||
Student(
|
Student(
|
||||||
email = email,
|
email = email.ifBlank { student.email },
|
||||||
password = password,
|
password = password,
|
||||||
isParent = student.isParent,
|
isParent = student.isParent,
|
||||||
symbol = student.symbol,
|
symbol = student.symbol,
|
||||||
|
@ -9,7 +9,7 @@ import javax.inject.Inject
|
|||||||
class GradeStatisticsWork @Inject constructor(private val gradeStatisticsRepository: GradeStatisticsRepository) : Work {
|
class GradeStatisticsWork @Inject constructor(private val gradeStatisticsRepository: GradeStatisticsRepository) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return gradeStatisticsRepository.getGradesStatistics(student, semester, "Wszystkie", false, true)
|
return gradeStatisticsRepository.getGradesStatistics(student, semester, "Wszystkie", false, forceRefresh = true)
|
||||||
.ignoreElement()
|
.ignoreElement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import androidx.core.app.NotificationCompat.PRIORITY_HIGH
|
|||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||||
@ -30,17 +31,21 @@ class GradeWork @Inject constructor(
|
|||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable)
|
return gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable)
|
||||||
.flatMap { gradeRepository.getNotNotifiedGrades(semester) }
|
.ignoreElement()
|
||||||
.flatMapCompletable {
|
.concatWith(Completable.concatArray(gradeRepository.getNotNotifiedGrades(semester).flatMapCompletable {
|
||||||
if (it.isNotEmpty()) notify(it)
|
if (it.isNotEmpty()) notifyDetails(it)
|
||||||
gradeRepository.updateGrades(it.onEach { grade -> grade.isNotified = true })
|
gradeRepository.updateGrades(it.onEach { grade -> grade.isNotified = true })
|
||||||
}
|
}, gradeRepository.getNotNotifiedPredictedGrades(semester).flatMapCompletable {
|
||||||
|
if (it.isNotEmpty()) notifyPredicted(it)
|
||||||
|
gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isPredictedGradeNotified = true })
|
||||||
|
}, gradeRepository.getNotNotifiedFinalGrades(semester).flatMapCompletable {
|
||||||
|
if (it.isNotEmpty()) notifyFinal(it)
|
||||||
|
gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isFinalGradeNotified = true })
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun notify(grades: List<Grade>) {
|
private fun getNotificationBuilder(): NotificationCompat.Builder {
|
||||||
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewGradesChannel.CHANNEL_ID)
|
return NotificationCompat.Builder(context, NewGradesChannel.CHANNEL_ID)
|
||||||
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items, grades.size, grades.size))
|
|
||||||
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items, grades.size, grades.size))
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_grade)
|
.setSmallIcon(R.drawable.ic_stat_grade)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setPriority(PRIORITY_HIGH)
|
.setPriority(PRIORITY_HIGH)
|
||||||
@ -49,6 +54,12 @@ class GradeWork @Inject constructor(
|
|||||||
.setContentIntent(
|
.setContentIntent(
|
||||||
PendingIntent.getActivity(context, MainView.Section.GRADE.id,
|
PendingIntent.getActivity(context, MainView.Section.GRADE.id,
|
||||||
MainActivity.getStartIntent(context, MainView.Section.GRADE, true), FLAG_UPDATE_CURRENT))
|
MainActivity.getStartIntent(context, MainView.Section.GRADE, true), FLAG_UPDATE_CURRENT))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun notifyDetails(grades: List<Grade>) {
|
||||||
|
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder()
|
||||||
|
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items, grades.size, grades.size))
|
||||||
|
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items, grades.size, grades.size))
|
||||||
.setStyle(NotificationCompat.InboxStyle().run {
|
.setStyle(NotificationCompat.InboxStyle().run {
|
||||||
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
|
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
|
||||||
grades.forEach { addLine("${it.subject}: ${it.entry}") }
|
grades.forEach { addLine("${it.subject}: ${it.entry}") }
|
||||||
@ -57,4 +68,30 @@ class GradeWork @Inject constructor(
|
|||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun notifyPredicted(gradesSummary: List<GradeSummary>) {
|
||||||
|
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder()
|
||||||
|
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items_predicted, gradesSummary.size, gradesSummary.size))
|
||||||
|
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items_predicted, gradesSummary.size, gradesSummary.size))
|
||||||
|
.setStyle(NotificationCompat.InboxStyle().run {
|
||||||
|
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, gradesSummary.size, gradesSummary.size))
|
||||||
|
gradesSummary.forEach { addLine("${it.subject}: ${it.predictedGrade}") }
|
||||||
|
this
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun notifyFinal(gradesSummary: List<GradeSummary>) {
|
||||||
|
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder()
|
||||||
|
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items_final, gradesSummary.size, gradesSummary.size))
|
||||||
|
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items_final, gradesSummary.size, gradesSummary.size))
|
||||||
|
.setStyle(NotificationCompat.InboxStyle().run {
|
||||||
|
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, gradesSummary.size, gradesSummary.size))
|
||||||
|
gradesSummary.forEach { addLine("${it.subject}: ${it.finalGrade}") }
|
||||||
|
this
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,9 @@ class LogViewerPresenter @Inject constructor(
|
|||||||
disposable.add(loggerRepository.getLogFiles()
|
disposable.add(loggerRepository.getLogFiles()
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
.observeOn(schedulers.mainThread)
|
.observeOn(schedulers.mainThread)
|
||||||
.subscribe({
|
.subscribe({ files ->
|
||||||
Timber.i("Loading logs files result: ${it.joinToString { it.name }}")
|
Timber.i("Loading logs files result: ${files.joinToString { it.name }}")
|
||||||
view?.shareLogs(it)
|
view?.shareLogs(files)
|
||||||
}, {
|
}, {
|
||||||
Timber.i("Loading logs files result: An exception occurred")
|
Timber.i("Loading logs files result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.account
|
||||||
|
|
||||||
|
data class Account(val email: String, val isParent: Boolean)
|
@ -3,33 +3,72 @@ package io.github.wulkanowy.ui.modules.account
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.PorterDuff
|
import android.graphics.PorterDuff
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View.GONE
|
||||||
|
import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.databinding.HeaderAccountBinding
|
||||||
import io.github.wulkanowy.databinding.ItemAccountBinding
|
import io.github.wulkanowy.databinding.ItemAccountBinding
|
||||||
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AccountAdapter @Inject constructor() : RecyclerView.Adapter<AccountAdapter.ItemViewHolder>() {
|
class AccountAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
var items = emptyList<Student>()
|
var items = emptyList<AccountItem<*>>()
|
||||||
|
|
||||||
var onClickListener: (Student) -> Unit = {}
|
var onClickListener: (Student) -> Unit = {}
|
||||||
|
|
||||||
override fun getItemCount() = items.size
|
override fun getItemCount() = items.size
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
|
override fun getItemViewType(position: Int) = items[position].viewType.id
|
||||||
ItemAccountBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
|
||||||
)
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
val inflater = LayoutInflater.from(parent.context)
|
||||||
|
|
||||||
|
return when (viewType) {
|
||||||
|
AccountItem.ViewType.HEADER.id -> HeaderViewHolder(HeaderAccountBinding.inflate(inflater, parent, false))
|
||||||
|
AccountItem.ViewType.ITEM.id -> ItemViewHolder(ItemAccountBinding.inflate(inflater, parent, false))
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
when (holder) {
|
||||||
|
is HeaderViewHolder -> bindHeaderViewHolder(holder.binding, items[position].value as Account)
|
||||||
|
is ItemViewHolder -> bindItemViewHolder(holder.binding, items[position].value as Student)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindHeaderViewHolder(binding: HeaderAccountBinding, account: Account) {
|
||||||
|
with(binding) {
|
||||||
|
accountHeaderEmail.text = account.email
|
||||||
|
accountHeaderType.setText(if (account.isParent) R.string.account_type_parent else R.string.account_type_student)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
|
private fun bindItemViewHolder(binding: ItemAccountBinding, student: Student) {
|
||||||
val student = items[position]
|
with(binding) {
|
||||||
|
|
||||||
with(holder.binding) {
|
|
||||||
accountItemName.text = "${student.studentName} ${student.className}"
|
accountItemName.text = "${student.studentName} ${student.className}"
|
||||||
accountItemSchool.text = student.schoolName
|
accountItemSchool.text = student.schoolName
|
||||||
|
with(accountItemLoginMode) {
|
||||||
|
visibility = when (Sdk.Mode.valueOf(student.loginMode)) {
|
||||||
|
Sdk.Mode.API -> {
|
||||||
|
setText(R.string.account_login_mobile_api)
|
||||||
|
VISIBLE
|
||||||
|
}
|
||||||
|
Sdk.Mode.HYBRID -> {
|
||||||
|
setText(R.string.account_login_hybrid)
|
||||||
|
VISIBLE
|
||||||
|
}
|
||||||
|
Sdk.Mode.SCRAPPER -> {
|
||||||
|
GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
with(accountItemImage) {
|
with(accountItemImage) {
|
||||||
val colorImage = if (student.isCurrent) context.getThemeAttrColor(R.attr.colorPrimary)
|
val colorImage = if (student.isCurrent) context.getThemeAttrColor(R.attr.colorPrimary)
|
||||||
@ -42,5 +81,8 @@ class AccountAdapter @Inject constructor() : RecyclerView.Adapter<AccountAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HeaderViewHolder(val binding: HeaderAccountBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root)
|
||||||
|
|
||||||
class ItemViewHolder(val binding: ItemAccountBinding) : RecyclerView.ViewHolder(binding.root)
|
class ItemViewHolder(val binding: ItemAccountBinding) : RecyclerView.ViewHolder(binding.root)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import android.widget.Toast.LENGTH_LONG
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.databinding.DialogAccountBinding
|
import io.github.wulkanowy.databinding.DialogAccountBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||||
@ -54,7 +53,7 @@ class AccountDialog : BaseDialogFragment<DialogAccountBinding>(), AccountView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateData(data: List<Student>) {
|
override fun updateData(data: List<AccountItem<*>>) {
|
||||||
with(accountAdapter) {
|
with(accountAdapter) {
|
||||||
items = data
|
items = data
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.account
|
||||||
|
|
||||||
|
data class AccountItem<out T>(val value: T, val viewType: ViewType) {
|
||||||
|
|
||||||
|
enum class ViewType(val id: Int) {
|
||||||
|
HEADER(1),
|
||||||
|
ITEM(2)
|
||||||
|
}
|
||||||
|
}
|
@ -83,11 +83,20 @@ class AccountPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createAccountItems(items: List<Student>): List<AccountItem<*>> {
|
||||||
|
return items.groupBy { Account(it.email, it.isParent) }.map { (account, students) ->
|
||||||
|
listOf(AccountItem(account, AccountItem.ViewType.HEADER)) + students.map { student ->
|
||||||
|
AccountItem(student, AccountItem.ViewType.ITEM)
|
||||||
|
}
|
||||||
|
}.flatten()
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadData() {
|
private fun loadData() {
|
||||||
Timber.i("Loading account data started")
|
Timber.i("Loading account data started")
|
||||||
disposable.add(studentRepository.getSavedStudents(false)
|
disposable.add(studentRepository.getSavedStudents(false)
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
.observeOn(schedulers.mainThread)
|
.observeOn(schedulers.mainThread)
|
||||||
|
.map { createAccountItems(it) }
|
||||||
.subscribe({
|
.subscribe({
|
||||||
Timber.i("Loading account result: Success")
|
Timber.i("Loading account result: Success")
|
||||||
view?.updateData(it)
|
view?.updateData(it)
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package io.github.wulkanowy.ui.modules.account
|
package io.github.wulkanowy.ui.modules.account
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
|
||||||
interface AccountView : BaseView {
|
interface AccountView : BaseView {
|
||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
|
|
||||||
fun updateData(data: List<Student>)
|
fun updateData(data: List<AccountItem<*>>)
|
||||||
|
|
||||||
fun dismissView()
|
fun dismissView()
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ import org.threeten.bp.LocalDate
|
|||||||
import org.threeten.bp.LocalDate.now
|
import org.threeten.bp.LocalDate.now
|
||||||
import org.threeten.bp.LocalDate.ofEpochDay
|
import org.threeten.bp.LocalDate.ofEpochDay
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AttendancePresenter @Inject constructor(
|
class AttendancePresenter @Inject constructor(
|
||||||
|
@ -98,7 +98,7 @@ class GradeAverageProvider @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun List<GradeSummary>.emulateEmptySummaries(student: Student, semester: Semester, grades: List<Pair<String, List<Grade>>>, calcAverage: Boolean): List<GradeSummary> {
|
private fun List<GradeSummary>.emulateEmptySummaries(student: Student, semester: Semester, grades: List<Pair<String, List<Grade>>>, calcAverage: Boolean): List<GradeSummary> {
|
||||||
if (isNotEmpty() && size == grades.size) return this
|
if (isNotEmpty() && size > grades.size) return this
|
||||||
|
|
||||||
return grades.mapIndexed { i, (subject, details) ->
|
return grades.mapIndexed { i, (subject, details) ->
|
||||||
singleOrNull { it.subject == subject }?.let { return@mapIndexed it }
|
singleOrNull { it.subject == subject }?.let { return@mapIndexed it }
|
||||||
|
@ -63,7 +63,7 @@ class MessagePreviewAdapter @Inject constructor() :
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun bindMessage(holder: MessageViewHolder, message: Message) {
|
private fun bindMessage(holder: MessageViewHolder, message: Message) {
|
||||||
with(holder.binding) {
|
with(holder.binding) {
|
||||||
messagePreviewSubject.text = if (message.subject.isNotBlank()) message.subject else root.context.getString(R.string.message_no_subject)
|
messagePreviewSubject.text = message.subject.ifBlank { root.context.getString(R.string.message_no_subject) }
|
||||||
messagePreviewDate.text = root.context.getString(R.string.message_date, message.date.toFormattedString("yyyy-MM-dd HH:mm:ss"))
|
messagePreviewDate.text = root.context.getString(R.string.message_date, message.date.toFormattedString("yyyy-MM-dd HH:mm:ss"))
|
||||||
messagePreviewContent.text = message.content
|
messagePreviewContent.text = message.content
|
||||||
messagePreviewAuthor.text = if (message.folderId == MessageFolder.SENT.id) "${root.context.getString(R.string.message_to)} ${message.recipient}"
|
messagePreviewAuthor.text = if (message.folderId == MessageFolder.SENT.id) "${root.context.getString(R.string.message_to)} ${message.recipient}"
|
||||||
|
@ -1,12 +1,20 @@
|
|||||||
package io.github.wulkanowy.ui.modules.message.preview
|
package io.github.wulkanowy.ui.modules.message.preview
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.print.PrintAttributes
|
||||||
|
import android.print.PrintManager
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
|
import android.webkit.WebResourceRequest
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.core.content.getSystemService
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
@ -17,6 +25,8 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
|||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
||||||
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
||||||
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
|
import io.github.wulkanowy.utils.shareText
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MessagePreviewFragment :
|
class MessagePreviewFragment :
|
||||||
@ -29,18 +39,31 @@ class MessagePreviewFragment :
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var previewAdapter: MessagePreviewAdapter
|
lateinit var previewAdapter: MessagePreviewAdapter
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var appInfo: AppInfo
|
||||||
|
|
||||||
private var menuReplyButton: MenuItem? = null
|
private var menuReplyButton: MenuItem? = null
|
||||||
|
|
||||||
private var menuForwardButton: MenuItem? = null
|
private var menuForwardButton: MenuItem? = null
|
||||||
|
|
||||||
private var menuDeleteButton: MenuItem? = null
|
private var menuDeleteButton: MenuItem? = null
|
||||||
|
|
||||||
|
private var menuShareButton: MenuItem? = null
|
||||||
|
|
||||||
|
private var menuPrintButton: MenuItem? = null
|
||||||
|
|
||||||
override val titleStringId: Int
|
override val titleStringId: Int
|
||||||
get() = R.string.message_title
|
get() = R.string.message_title
|
||||||
|
|
||||||
override val deleteMessageSuccessString: String
|
override val deleteMessageSuccessString: String
|
||||||
get() = getString(R.string.message_delete_success)
|
get() = getString(R.string.message_delete_success)
|
||||||
|
|
||||||
|
override val messageNoSubjectString: String
|
||||||
|
get() = getString(R.string.message_no_subject)
|
||||||
|
|
||||||
|
override val printHTML: String
|
||||||
|
get() = requireContext().assets.open("message-print-page.html").bufferedReader().use { it.readText() }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val MESSAGE_ID_KEY = "message_id"
|
const val MESSAGE_ID_KEY = "message_id"
|
||||||
|
|
||||||
@ -77,6 +100,8 @@ class MessagePreviewFragment :
|
|||||||
menuReplyButton = menu.findItem(R.id.messagePreviewMenuReply)
|
menuReplyButton = menu.findItem(R.id.messagePreviewMenuReply)
|
||||||
menuForwardButton = menu.findItem(R.id.messagePreviewMenuForward)
|
menuForwardButton = menu.findItem(R.id.messagePreviewMenuForward)
|
||||||
menuDeleteButton = menu.findItem(R.id.messagePreviewMenuDelete)
|
menuDeleteButton = menu.findItem(R.id.messagePreviewMenuDelete)
|
||||||
|
menuShareButton = menu.findItem(R.id.messagePreviewMenuShare)
|
||||||
|
menuPrintButton = menu.findItem(R.id.messagePreviewMenuPrint)
|
||||||
presenter.onCreateOptionsMenu()
|
presenter.onCreateOptionsMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +110,8 @@ class MessagePreviewFragment :
|
|||||||
R.id.messagePreviewMenuReply -> presenter.onReply()
|
R.id.messagePreviewMenuReply -> presenter.onReply()
|
||||||
R.id.messagePreviewMenuForward -> presenter.onForward()
|
R.id.messagePreviewMenuForward -> presenter.onForward()
|
||||||
R.id.messagePreviewMenuDelete -> presenter.onMessageDelete()
|
R.id.messagePreviewMenuDelete -> presenter.onMessageDelete()
|
||||||
|
R.id.messagePreviewMenuShare -> presenter.onShare()
|
||||||
|
R.id.messagePreviewMenuPrint -> presenter.onPrint()
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,6 +135,8 @@ class MessagePreviewFragment :
|
|||||||
menuReplyButton?.isVisible = show
|
menuReplyButton?.isVisible = show
|
||||||
menuForwardButton?.isVisible = show
|
menuForwardButton?.isVisible = show
|
||||||
menuDeleteButton?.isVisible = show
|
menuDeleteButton?.isVisible = show
|
||||||
|
menuShareButton?.isVisible = show
|
||||||
|
menuPrintButton?.isVisible = show && appInfo.systemVersion >= Build.VERSION_CODES.LOLLIPOP
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setDeletedOptionsLabels() {
|
override fun setDeletedOptionsLabels() {
|
||||||
@ -138,6 +167,38 @@ class MessagePreviewFragment :
|
|||||||
context?.let { it.startActivity(SendMessageActivity.getStartIntent(it, message)) }
|
context?.let { it.startActivity(SendMessageActivity.getStartIntent(it, message)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun shareText(text: String, subject: String) {
|
||||||
|
context?.shareText(text, subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
override fun printDocument(html: String, jobName: String) {
|
||||||
|
val webView = WebView(activity)
|
||||||
|
webView.webViewClient = object : WebViewClient() {
|
||||||
|
|
||||||
|
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest) = false
|
||||||
|
|
||||||
|
override fun onPageFinished(view: WebView, url: String) {
|
||||||
|
createWebPrintJob(view, jobName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webView.loadDataWithBaseURL("file:///android_asset/", html, "text/HTML", "UTF-8", null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
private fun createWebPrintJob(webView: WebView, jobName: String) {
|
||||||
|
activity?.getSystemService<PrintManager>()?.let { printManager ->
|
||||||
|
val printAdapter = webView.createPrintDocumentAdapter(jobName)
|
||||||
|
|
||||||
|
printManager.print(
|
||||||
|
jobName,
|
||||||
|
printAdapter,
|
||||||
|
PrintAttributes.Builder().build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun popView() {
|
override fun popView() {
|
||||||
(activity as MainActivity).popView()
|
(activity as MainActivity).popView()
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
package io.github.wulkanowy.ui.modules.message.preview
|
package io.github.wulkanowy.ui.modules.message.preview
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Build
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
|
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||||
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -15,11 +20,14 @@ class MessagePreviewPresenter @Inject constructor(
|
|||||||
errorHandler: ErrorHandler,
|
errorHandler: ErrorHandler,
|
||||||
studentRepository: StudentRepository,
|
studentRepository: StudentRepository,
|
||||||
private val messageRepository: MessageRepository,
|
private val messageRepository: MessageRepository,
|
||||||
private val analytics: FirebaseAnalyticsHelper
|
private val analytics: FirebaseAnalyticsHelper,
|
||||||
|
private var appInfo: AppInfo
|
||||||
) : BasePresenter<MessagePreviewView>(errorHandler, studentRepository, schedulers) {
|
) : BasePresenter<MessagePreviewView>(errorHandler, studentRepository, schedulers) {
|
||||||
|
|
||||||
var message: Message? = null
|
var message: Message? = null
|
||||||
|
|
||||||
|
var attachments: List<MessageAttachment>? = null
|
||||||
|
|
||||||
private lateinit var lastError: Throwable
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
private var retryCallback: () -> Unit = {}
|
private var retryCallback: () -> Unit = {}
|
||||||
@ -56,6 +64,7 @@ class MessagePreviewPresenter @Inject constructor(
|
|||||||
.subscribe({ message ->
|
.subscribe({ message ->
|
||||||
Timber.i("Loading message ${message.message.messageId} preview result: Success ")
|
Timber.i("Loading message ${message.message.messageId} preview result: Success ")
|
||||||
this@MessagePreviewPresenter.message = message.message
|
this@MessagePreviewPresenter.message = message.message
|
||||||
|
this@MessagePreviewPresenter.attachments = message.attachments
|
||||||
view?.apply {
|
view?.apply {
|
||||||
setMessageWithAttachment(message)
|
setMessageWithAttachment(message)
|
||||||
initOptions()
|
initOptions()
|
||||||
@ -87,6 +96,60 @@ class MessagePreviewPresenter @Inject constructor(
|
|||||||
} else false
|
} else false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onShare(): Boolean {
|
||||||
|
message?.let {
|
||||||
|
var text = "Temat: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}\n" + when (it.sender.isNotEmpty()) {
|
||||||
|
true -> "Od: ${it.sender}\n"
|
||||||
|
false -> "Do: ${it.recipient}\n"
|
||||||
|
} + "Data: ${it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${it.content}"
|
||||||
|
|
||||||
|
attachments?.let { attachments ->
|
||||||
|
if (attachments.isNotEmpty()) {
|
||||||
|
text += "\n\nZałączniki:"
|
||||||
|
|
||||||
|
attachments.forEach { attachment ->
|
||||||
|
text += "\n${attachment.filename}: ${attachment.url}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view?.shareText(text, "FW: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
fun onPrint(): Boolean {
|
||||||
|
if (appInfo.systemVersion < Build.VERSION_CODES.LOLLIPOP) return false
|
||||||
|
message?.let {
|
||||||
|
val dateString = it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")
|
||||||
|
val infoContent = "<div><h4>Data wysłania</h4>$dateString</div>" + when {
|
||||||
|
it.sender.isNotEmpty() -> "<div><h4>Od</h4>${it.sender}</div>"
|
||||||
|
else -> "<div><h4>Do</h4>${it.recipient}</div>"
|
||||||
|
}
|
||||||
|
|
||||||
|
val messageContent = "<p>${it.content}</p>"
|
||||||
|
.replace(Regex("[\\n\\r]{2,}"), "</p><p>")
|
||||||
|
.replace(Regex("[\\n\\r]"), "<br>")
|
||||||
|
|
||||||
|
val jobName = "Wiadomość " + when {
|
||||||
|
it.sender.isNotEmpty() -> "od ${it.sender}"
|
||||||
|
else -> "do ${it.recipient}"
|
||||||
|
} + " $dateString: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }} | Wulkanowy"
|
||||||
|
|
||||||
|
view?.apply {
|
||||||
|
val html = printHTML
|
||||||
|
.replace("%SUBJECT%", it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() })
|
||||||
|
.replace("%CONTENT%", messageContent)
|
||||||
|
.replace("%INFO%", infoContent)
|
||||||
|
printDocument(html, jobName)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun deleteMessage() {
|
private fun deleteMessage() {
|
||||||
message?.let { message ->
|
message?.let { message ->
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package io.github.wulkanowy.ui.modules.message.preview
|
package io.github.wulkanowy.ui.modules.message.preview
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
@ -8,6 +10,10 @@ interface MessagePreviewView : BaseView {
|
|||||||
|
|
||||||
val deleteMessageSuccessString: String
|
val deleteMessageSuccessString: String
|
||||||
|
|
||||||
|
val messageNoSubjectString: String
|
||||||
|
|
||||||
|
val printHTML: String
|
||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
|
|
||||||
fun setMessageWithAttachment(item: MessageWithAttachment)
|
fun setMessageWithAttachment(item: MessageWithAttachment)
|
||||||
@ -34,5 +40,10 @@ interface MessagePreviewView : BaseView {
|
|||||||
|
|
||||||
fun openMessageForward(message: Message?)
|
fun openMessageForward(message: Message?)
|
||||||
|
|
||||||
|
fun shareText(text: String, subject: String)
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
fun printDocument(html: String, jobName: String)
|
||||||
|
|
||||||
fun popView()
|
fun popView()
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,9 @@ import android.graphics.Typeface
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.RecyclerView.NO_POSITION
|
import androidx.recyclerview.widget.RecyclerView.NO_POSITION
|
||||||
import androidx.recyclerview.widget.SortedList
|
|
||||||
import androidx.recyclerview.widget.SortedListAdapterCallback
|
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.github.wulkanowy.data.repositories.message.MessageFolder
|
import io.github.wulkanowy.data.repositories.message.MessageFolder
|
||||||
@ -20,39 +19,23 @@ class MessageTabAdapter @Inject constructor() :
|
|||||||
|
|
||||||
var onClickListener: (Message, position: Int) -> Unit = { _, _ -> }
|
var onClickListener: (Message, position: Int) -> Unit = { _, _ -> }
|
||||||
|
|
||||||
private val items = SortedList(Message::class.java, object :
|
private var items = mutableListOf<Message>()
|
||||||
SortedListAdapterCallback<Message>(this) {
|
|
||||||
|
|
||||||
override fun compare(item1: Message, item2: Message): Int {
|
fun setDataItems(data: List<Message>) {
|
||||||
return item2.date.compareTo(item1.date)
|
val diffResult = DiffUtil.calculateDiff(MessageTabDiffUtil(items, data))
|
||||||
}
|
items = data.toMutableList()
|
||||||
|
diffResult.dispatchUpdatesTo(this)
|
||||||
override fun areContentsTheSame(oldItem: Message?, newItem: Message?): Boolean {
|
|
||||||
return oldItem == newItem
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun areItemsTheSame(item1: Message, item2: Message): Boolean {
|
|
||||||
return item1 == item2
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
fun replaceAll(models: List<Message>) {
|
|
||||||
items.beginBatchedUpdates()
|
|
||||||
for (i in items.size() - 1 downTo 0) {
|
|
||||||
val model = items.get(i)
|
|
||||||
if (model !in models) {
|
|
||||||
items.remove(model)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
items.addAll(models)
|
|
||||||
items.endBatchedUpdates()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateItem(position: Int, item: Message) {
|
fun updateItem(position: Int, item: Message) {
|
||||||
items.updateItemAt(position, item)
|
val currentItem = items[position]
|
||||||
|
items[position] = item
|
||||||
|
if (item != currentItem) {
|
||||||
|
notifyItemChanged(position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = items.size()
|
override fun getItemCount() = items.size
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
|
||||||
ItemMessageBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
ItemMessageBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
@ -85,4 +68,19 @@ class MessageTabAdapter @Inject constructor() :
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ItemViewHolder(val binding: ItemMessageBinding) : RecyclerView.ViewHolder(binding.root)
|
class ItemViewHolder(val binding: ItemMessageBinding) : RecyclerView.ViewHolder(binding.root)
|
||||||
|
|
||||||
|
private class MessageTabDiffUtil(private val old: List<Message>, private val new: List<Message>) :
|
||||||
|
DiffUtil.Callback() {
|
||||||
|
override fun getOldListSize(): Int = old.size
|
||||||
|
|
||||||
|
override fun getNewListSize(): Int = new.size
|
||||||
|
|
||||||
|
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||||
|
return old[oldItemPosition].id == new[newItemPosition].id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||||
|
return old[oldItemPosition] == new[newItemPosition]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateData(data: List<Message>) {
|
override fun updateData(data: List<Message>) {
|
||||||
tabAdapter.replaceAll(data)
|
tabAdapter.setDataItems(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateItem(item: Message, position: Int) {
|
override fun updateItem(item: Message, position: Int) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package io.github.wulkanowy.ui.modules.message.tab
|
package io.github.wulkanowy.ui.modules.message.tab
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.github.wulkanowy.data.repositories.message.MessageFolder
|
import io.github.wulkanowy.data.repositories.message.MessageFolder
|
||||||
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
||||||
@ -11,8 +10,13 @@ import io.github.wulkanowy.ui.base.ErrorHandler
|
|||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
import io.reactivex.subjects.PublishSubject
|
||||||
|
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
class MessageTabPresenter @Inject constructor(
|
class MessageTabPresenter @Inject constructor(
|
||||||
schedulers: SchedulersProvider,
|
schedulers: SchedulersProvider,
|
||||||
@ -31,9 +35,12 @@ class MessageTabPresenter @Inject constructor(
|
|||||||
|
|
||||||
private var messages = emptyList<Message>()
|
private var messages = emptyList<Message>()
|
||||||
|
|
||||||
|
private val searchQuery = PublishSubject.create<String>()
|
||||||
|
|
||||||
fun onAttachView(view: MessageTabView, folder: MessageFolder) {
|
fun onAttachView(view: MessageTabView, folder: MessageFolder) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.initView()
|
view.initView()
|
||||||
|
initializeSearchStream()
|
||||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
this.folder = folder
|
this.folder = folder
|
||||||
}
|
}
|
||||||
@ -76,38 +83,35 @@ class MessageTabPresenter @Inject constructor(
|
|||||||
|
|
||||||
private fun loadData(forceRefresh: Boolean) {
|
private fun loadData(forceRefresh: Boolean) {
|
||||||
Timber.i("Loading $folder message data started")
|
Timber.i("Loading $folder message data started")
|
||||||
disposable.apply {
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
clear()
|
.flatMap { student ->
|
||||||
add(studentRepository.getCurrentStudent()
|
semesterRepository.getCurrentSemester(student)
|
||||||
.flatMap { student ->
|
.flatMap { messageRepository.getMessages(student, it, folder, forceRefresh) }
|
||||||
semesterRepository.getCurrentSemester(student)
|
}
|
||||||
.flatMap { messageRepository.getMessages(student, it, folder, forceRefresh) }
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
|
.observeOn(schedulers.mainThread)
|
||||||
|
.doFinally {
|
||||||
|
view?.run {
|
||||||
|
showRefresh(false)
|
||||||
|
showProgress(false)
|
||||||
|
enableSwipe(true)
|
||||||
|
notifyParentDataLoaded()
|
||||||
}
|
}
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
}
|
||||||
.observeOn(schedulers.mainThread)
|
.subscribe({
|
||||||
.doFinally {
|
Timber.i("Loading $folder message result: Success")
|
||||||
view?.run {
|
messages = it
|
||||||
showRefresh(false)
|
view?.updateData(getFilteredData(lastSearchQuery))
|
||||||
showProgress(false)
|
analytics.logEvent(
|
||||||
enableSwipe(true)
|
"load_data",
|
||||||
notifyParentDataLoaded()
|
"type" to "messages",
|
||||||
}
|
"items" to it.size,
|
||||||
}
|
"folder" to folder.name
|
||||||
.subscribe({
|
)
|
||||||
Timber.i("Loading $folder message result: Success")
|
}) {
|
||||||
messages = it
|
Timber.i("Loading $folder message result: An exception occurred")
|
||||||
onSearchQueryTextChange(lastSearchQuery)
|
errorHandler.dispatch(it)
|
||||||
analytics.logEvent(
|
})
|
||||||
"load_data",
|
|
||||||
"type" to "messages",
|
|
||||||
"items" to it.size,
|
|
||||||
"folder" to folder.name
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Timber.i("Loading $folder message result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
@ -121,25 +125,36 @@ class MessageTabPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
|
||||||
fun onSearchQueryTextChange(query: String) {
|
fun onSearchQueryTextChange(query: String) {
|
||||||
lastSearchQuery = query
|
if (query != searchQuery.toString())
|
||||||
|
searchQuery.onNext(query)
|
||||||
|
}
|
||||||
|
|
||||||
val lowerCaseQuery = query.toLowerCase()
|
private fun initializeSearchStream() {
|
||||||
val filteredList = mutableListOf<Message>()
|
disposable.add(searchQuery
|
||||||
messages.forEach {
|
.debounce(250, TimeUnit.MILLISECONDS)
|
||||||
if (lowerCaseQuery in it.subject.toLowerCase() ||
|
.map { query ->
|
||||||
lowerCaseQuery in it.sender.toLowerCase() ||
|
lastSearchQuery = query
|
||||||
lowerCaseQuery in it.recipient.toLowerCase() ||
|
getFilteredData(query)
|
||||||
lowerCaseQuery in it.date.toFormattedString()
|
|
||||||
) {
|
|
||||||
filteredList.add(it)
|
|
||||||
}
|
}
|
||||||
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
|
.observeOn(schedulers.mainThread)
|
||||||
|
.subscribe({
|
||||||
|
Timber.d("Applying filter. Full list: ${messages.size}, filtered: ${it.size}")
|
||||||
|
updateData(it)
|
||||||
|
}) { Timber.e(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFilteredData(query: String): List<Message> {
|
||||||
|
return if (query.trim().isEmpty()) {
|
||||||
|
messages.sortedByDescending { it.date }
|
||||||
|
} else {
|
||||||
|
messages
|
||||||
|
.map { it to calculateMatchRatio(it, query) }
|
||||||
|
.sortedByDescending { it.second }
|
||||||
|
.filter { it.second > 5000 }
|
||||||
|
.map { it.first }
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.d("Applying filter. Full list: ${messages.size}, filtered: ${filteredList.size}")
|
|
||||||
|
|
||||||
updateData(filteredList)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateData(data: List<Message>) {
|
private fun updateData(data: List<Message>) {
|
||||||
@ -151,4 +166,42 @@ class MessageTabPresenter @Inject constructor(
|
|||||||
resetListPosition()
|
resetListPosition()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun calculateMatchRatio(message: Message, query: String): Int {
|
||||||
|
val subjectRatio = FuzzySearch.tokenSortPartialRatio(
|
||||||
|
query.toLowerCase(Locale.getDefault()),
|
||||||
|
message.subject
|
||||||
|
)
|
||||||
|
|
||||||
|
val senderOrRecipientRatio = FuzzySearch.tokenSortPartialRatio(
|
||||||
|
query.toLowerCase(Locale.getDefault()),
|
||||||
|
if (message.sender.isNotEmpty()) message.sender.toLowerCase(Locale.getDefault())
|
||||||
|
else message.recipient.toLowerCase(Locale.getDefault())
|
||||||
|
)
|
||||||
|
|
||||||
|
val dateRatio = listOf(
|
||||||
|
FuzzySearch.ratio(
|
||||||
|
query.toLowerCase(Locale.getDefault()),
|
||||||
|
message.date.toFormattedString("dd.MM").toLowerCase(Locale.getDefault())
|
||||||
|
),
|
||||||
|
FuzzySearch.ratio(
|
||||||
|
query.toLowerCase(Locale.getDefault()),
|
||||||
|
message.date.toFormattedString("dd.MM.yyyy").toLowerCase(Locale.getDefault())
|
||||||
|
),
|
||||||
|
FuzzySearch.ratio(
|
||||||
|
query.toLowerCase(Locale.getDefault()),
|
||||||
|
message.date.toFormattedString("d MMMM").toLowerCase(Locale.getDefault())
|
||||||
|
),
|
||||||
|
FuzzySearch.ratio(
|
||||||
|
query.toLowerCase(Locale.getDefault()),
|
||||||
|
message.date.toFormattedString("d MMMM yyyy").toLowerCase(Locale.getDefault())
|
||||||
|
)
|
||||||
|
).max() ?: 0
|
||||||
|
|
||||||
|
|
||||||
|
return (subjectRatio.toDouble().pow(2)
|
||||||
|
+ senderOrRecipientRatio.toDouble().pow(2)
|
||||||
|
+ dateRatio.toDouble().pow(2) * 2
|
||||||
|
).toInt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ class CompletedLessonsPresenter @Inject constructor(
|
|||||||
completedLessonsErrorHandler.showErrorMessage = ::showErrorViewOnError
|
completedLessonsErrorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
completedLessonsErrorHandler.onFeatureDisabled = {
|
completedLessonsErrorHandler.onFeatureDisabled = {
|
||||||
this.view?.showFeatureDisabled()
|
this.view?.showFeatureDisabled()
|
||||||
this.view?.showEmpty(true);
|
this.view?.showEmpty(true)
|
||||||
Timber.i("Completed lessons feature disabled by school")
|
Timber.i("Completed lessons feature disabled by school")
|
||||||
}
|
}
|
||||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||||
|
@ -71,4 +71,17 @@ fun Context.openDialer(phone: String) {
|
|||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.shareText(text: String, subject: String?) {
|
||||||
|
val sendIntent: Intent = Intent().apply {
|
||||||
|
action = Intent.ACTION_SEND
|
||||||
|
putExtra(Intent.EXTRA_TEXT, text)
|
||||||
|
if (subject != null) {
|
||||||
|
putExtra(Intent.EXTRA_SUBJECT, subject)
|
||||||
|
}
|
||||||
|
type = "text/plain"
|
||||||
|
}
|
||||||
|
val shareIntent = Intent.createChooser(sendIntent, null)
|
||||||
|
startActivity(shareIntent)
|
||||||
|
}
|
||||||
|
|
||||||
fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT
|
fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT
|
||||||
|
@ -52,4 +52,4 @@ class LifecycleAwareVariableActivity<T : Any> : ReadWriteProperty<AppCompatActiv
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
fun <T : Any> Fragment.lifecycleAwareVariable() = LifecycleAwareVariable<T>()
|
fun <T : Any> Fragment.lifecycleAwareVariable() = LifecycleAwareVariable<T>()
|
||||||
|
|
||||||
fun <T : Any> AppCompatActivity.lifecycleAwareVariable() = LifecycleAwareVariableActivity<T>()
|
fun <T : Any> lifecycleAwareVariable() = LifecycleAwareVariableActivity<T>()
|
||||||
|
@ -23,6 +23,8 @@ fun Sdk.init(student: Student): Sdk {
|
|||||||
certKey = student.certificateKey
|
certKey = student.certificateKey
|
||||||
privateKey = student.privateKey
|
privateKey = student.privateKey
|
||||||
|
|
||||||
|
emptyCookieJarInterceptor = true
|
||||||
|
|
||||||
Timber.d("Sdk in ${student.loginMode} mode reinitialized")
|
Timber.d("Sdk in ${student.loginMode} mode reinitialized")
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
Wersja 0.18.3
|
Wersja 0.19.0
|
||||||
- poprawiliśmy liczenie średniej i dodaliśmy nowy sposób jej liczenia w ustawieniach
|
- naprawiliśmy pokazywanie brakujących przedmiotów na liście podsumowania ocen
|
||||||
- naprawiliśmy usuwanie wiadomości
|
- ulepszyliśmy wygląd menadżera kont
|
||||||
- naprawiliśmy wysyłanie wiadomości na Lubelskim Portalu Oświatowym
|
- ulepszyliśmy wyszukiwarkę wiadomości
|
||||||
|
- dodaliśmy powiadomienia o proponowanych i końcowych ocenach
|
||||||
|
- dodaliśmy opcję udostępniania i drukowania wiadomości
|
||||||
|
|
||||||
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
||||||
|
13
app/src/main/res/drawable/ic_menu_message_print.xml
Normal file
13
app/src/main/res/drawable/ic_menu_message_print.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="#FFFFFF"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,8h-1L18,3L6,3v5L5,8c-1.66,0 -3,1.34 -3,3v6h4v4h12v-4h4v-6c0,-1.66 -1.34,-3 -3,-3zM8,5h8v3L8,8L8,5zM16,17v2L8,19v-4h8v2zM18,15v-2L6,13v2L4,15v-4c0,-0.55 0.45,-1 1,-1h14c0.55,0 1,0.45 1,1v4h-2z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M18,11.5m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" />
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_menu_message_share.xml
Normal file
10
app/src/main/res/drawable/ic_menu_message_share.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="#FFFFFF"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92s2.92,-1.31 2.92,-2.92c0,-1.61 -1.31,-2.92 -2.92,-2.92zM18,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM6,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM18,20.02c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1z" />
|
||||||
|
</vector>
|
@ -5,45 +5,60 @@
|
|||||||
android:layout_width="300dp"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/accountDialogTitle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:paddingStart="24dp"
|
|
||||||
android:paddingLeft="24dp"
|
|
||||||
android:paddingEnd="24dp"
|
|
||||||
android:paddingRight="24dp"
|
|
||||||
android:text="@string/account_title"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:firstBaselineToTopHeight="40dp" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/accountDialogRecycler"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/accountDialogTitle"
|
android:orientation="vertical">
|
||||||
android:overScrollMode="never"
|
|
||||||
tools:itemCount="3"
|
|
||||||
tools:listitem="@layout/item_account" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<TextView
|
||||||
android:id="@+id/accountDialogAdd"
|
android:id="@+id/accountDialogTitle"
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:paddingStart="24dp"
|
||||||
android:layout_below="@id/accountDialogRecycler"
|
android:paddingLeft="24dp"
|
||||||
android:layout_margin="8dp"
|
android:paddingEnd="24dp"
|
||||||
android:text="@string/account_add_new"
|
android:paddingRight="24dp"
|
||||||
android:textColor="?android:textColorPrimary" />
|
android:text="@string/account_title"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:firstBaselineToTopHeight="40dp" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/accountDialogRemove"
|
android:id="@+id/accountDialogRecycler"
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_below="@id/accountDialogRecycler"
|
android:layout_weight="1"
|
||||||
android:layout_alignParentEnd="true"
|
android:overScrollMode="never"
|
||||||
android:layout_margin="8dp"
|
tools:itemCount="3"
|
||||||
android:text="@string/account_logout" />
|
tools:listitem="@layout/item_account" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/accountDialogAdd"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:text="@string/account_add_new"
|
||||||
|
android:textColor="?android:textColorPrimary" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/accountDialogRemove"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:text="@string/account_logout" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
28
app/src/main/res/layout/header_account.xml
Normal file
28
app/src/main/res/layout/header_account.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
tools:context=".ui.modules.account.AccountAdapter">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/accountHeaderEmail"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="14sp"
|
||||||
|
tools:text="jan@fakelog.cf" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/accountHeaderType"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
tools:text="Konto ucznia" />
|
||||||
|
</LinearLayout>
|
@ -3,20 +3,17 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="56dp"
|
android:layout_height="wrap_content"
|
||||||
android:background="?selectableItemBackground"
|
android:background="?selectableItemBackground"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="24dp"
|
android:paddingVertical="8dp"
|
||||||
android:paddingLeft="24dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:paddingEnd="24dp"
|
|
||||||
android:paddingRight="24dp"
|
|
||||||
tools:context=".ui.modules.account.AccountAdapter">
|
tools:context=".ui.modules.account.AccountAdapter">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/accountItemImage"
|
android:id="@+id/accountItemImage"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:srcCompat="@drawable/ic_all_account"
|
app:srcCompat="@drawable/ic_all_account"
|
||||||
@ -27,7 +24,7 @@
|
|||||||
android:id="@+id/accountItemName"
|
android:id="@+id/accountItemName"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="20dp"
|
android:layout_marginStart="16dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
@ -40,7 +37,7 @@
|
|||||||
android:id="@+id/accountItemSchool"
|
android:id="@+id/accountItemSchool"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="20dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
@ -50,4 +47,21 @@
|
|||||||
app:layout_constraintStart_toEndOf="@id/accountItemImage"
|
app:layout_constraintStart_toEndOf="@id/accountItemImage"
|
||||||
app:layout_constraintTop_toBottomOf="@id/accountItemName"
|
app:layout_constraintTop_toBottomOf="@id/accountItemName"
|
||||||
tools:text="@tools:sample/lorem/random" />
|
tools:text="@tools:sample/lorem/random" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/accountItemLoginMode"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="3dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/accountItemImage"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/accountItemSchool"
|
||||||
|
tools:text="Tryb API mobilne"
|
||||||
|
tools:visibility="visible" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
@ -22,4 +22,18 @@
|
|||||||
android:title="@string/message_delete"
|
android:title="@string/message_delete"
|
||||||
app:iconTint="@color/material_on_surface_emphasis_medium"
|
app:iconTint="@color/material_on_surface_emphasis_medium"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/messagePreviewMenuShare"
|
||||||
|
android:icon="@drawable/ic_menu_message_share"
|
||||||
|
android:orderInCategory="1"
|
||||||
|
android:title="@string/message_share"
|
||||||
|
app:iconTint="@color/material_on_surface_emphasis_medium"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/messagePreviewMenuPrint"
|
||||||
|
android:icon="@drawable/ic_menu_message_print"
|
||||||
|
android:orderInCategory="1"
|
||||||
|
android:title="@string/message_print"
|
||||||
|
app:iconTint="@color/material_on_surface_emphasis_medium"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
</menu>
|
</menu>
|
||||||
|
@ -36,8 +36,8 @@
|
|||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="grade_average_mode_entries">
|
<string-array name="grade_average_mode_entries">
|
||||||
<item>Durchschnittsnote für das 2. Semester</item>
|
<item>Durchschnittsnote für das 2. Semester</item>
|
||||||
<item>Average of grades from both semesters</item>
|
<item>Durchschnitt der Noten aus beiden Semestern</item>
|
||||||
<item>Durchschnitt der Bewertungen für das ganze Jahr</item>
|
<item>Durchschnitt der Noten aus dem ganzen Jahr</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="timetable_show_whole_class_entries">
|
<string-array name="timetable_show_whole_class_entries">
|
||||||
<item>Nicht zeigen</item>
|
<item>Nicht zeigen</item>
|
||||||
|
@ -103,10 +103,26 @@
|
|||||||
<item quantity="one">Neue Note</item>
|
<item quantity="one">Neue Note</item>
|
||||||
<item quantity="other">Neue Noten</item>
|
<item quantity="other">Neue Noten</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_predicted">
|
||||||
|
<item quantity="one">New predicted grade</item>
|
||||||
|
<item quantity="other">New predicted grades</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_final">
|
||||||
|
<item quantity="one">New final grade</item>
|
||||||
|
<item quantity="other">New final grades</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="grade_notify_new_items">
|
<plurals name="grade_notify_new_items">
|
||||||
<item quantity="one">Du hast %1$d Note bekommen</item>
|
<item quantity="one">Du hast %1$d Note bekommen</item>
|
||||||
<item quantity="other">Du hast %1$d Noten bekommen</item>
|
<item quantity="other">Du hast %1$d Noten bekommen</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_predicted">
|
||||||
|
<item quantity="one">You received %1$d predicted grade</item>
|
||||||
|
<item quantity="other">You received %1$d predicted grades</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_final">
|
||||||
|
<item quantity="one">You received %1$d final grade</item>
|
||||||
|
<item quantity="other">You received %1$d final grades</item>
|
||||||
|
</plurals>
|
||||||
<!--Timetable-->
|
<!--Timetable-->
|
||||||
<string name="timetable_lesson">Lektion</string>
|
<string name="timetable_lesson">Lektion</string>
|
||||||
<string name="timetable_room">Klassenzimmer</string>
|
<string name="timetable_room">Klassenzimmer</string>
|
||||||
@ -172,6 +188,8 @@
|
|||||||
<string name="message_move_to_bin">In den Korb wandern</string>
|
<string name="message_move_to_bin">In den Korb wandern</string>
|
||||||
<string name="message_delete_forever">Dauerhaft löschen</string>
|
<string name="message_delete_forever">Dauerhaft löschen</string>
|
||||||
<string name="message_delete_success">Nachricht erfolgreich gelöscht</string>
|
<string name="message_delete_success">Nachricht erfolgreich gelöscht</string>
|
||||||
|
<string name="message_share">Share</string>
|
||||||
|
<string name="message_print">Print</string>
|
||||||
<string name="message_subject">Thema</string>
|
<string name="message_subject">Thema</string>
|
||||||
<string name="message_content">Inhalt</string>
|
<string name="message_content">Inhalt</string>
|
||||||
<string name="message_send_successful">Nachricht erfolgreich gesendet</string>
|
<string name="message_send_successful">Nachricht erfolgreich gesendet</string>
|
||||||
@ -214,7 +232,7 @@
|
|||||||
<string name="lucky_number_header">Die heutige Glücksnummer ist </string>
|
<string name="lucky_number_header">Die heutige Glücksnummer ist </string>
|
||||||
<string name="lucky_number_empty">Keine Information über die Glücksnummer.</string>
|
<string name="lucky_number_empty">Keine Information über die Glücksnummer.</string>
|
||||||
<string name="lucky_number_notify_new_item_title">Glücksnummer für heute</string>
|
<string name="lucky_number_notify_new_item_title">Glücksnummer für heute</string>
|
||||||
<string name="lucky_number_notify_new_item">Die heutige Glücksnummer ist: </string>
|
<string name="lucky_number_notify_new_item">Die heutige Glücksnummer ist: %d</string>
|
||||||
<!--Mobile devices-->
|
<!--Mobile devices-->
|
||||||
<string name="mobile_devices_title">Mobile Geräte</string>
|
<string name="mobile_devices_title">Mobile Geräte</string>
|
||||||
<string name="mobile_devices_no_items">Keine Geräte</string>
|
<string name="mobile_devices_no_items">Keine Geräte</string>
|
||||||
@ -245,6 +263,10 @@
|
|||||||
<string name="account_logout">Abmelden</string>
|
<string name="account_logout">Abmelden</string>
|
||||||
<string name="account_confirm">Wollen Sie sich von einem aktiven Studenten abmelden?</string>
|
<string name="account_confirm">Wollen Sie sich von einem aktiven Studenten abmelden?</string>
|
||||||
<string name="account_logout_student">Abmeldung von Student</string>
|
<string name="account_logout_student">Abmeldung von Student</string>
|
||||||
|
<string name="account_type_student">Student account</string>
|
||||||
|
<string name="account_type_parent">Parent account</string>
|
||||||
|
<string name="account_login_mobile_api">Mobile API mode</string>
|
||||||
|
<string name="account_login_hybrid">Hybrid mode</string>
|
||||||
<!--About-->
|
<!--About-->
|
||||||
<string name="about_version">Version der App</string>
|
<string name="about_version">Version der App</string>
|
||||||
<string name="about_contributor">Mitarbeiter</string>
|
<string name="about_contributor">Mitarbeiter</string>
|
||||||
@ -270,8 +292,8 @@
|
|||||||
<string name="logviewer_share">Logs teilen</string>
|
<string name="logviewer_share">Logs teilen</string>
|
||||||
<string name="logviewer_refresh">Aktualisieren</string>
|
<string name="logviewer_refresh">Aktualisieren</string>
|
||||||
<!--Error dialog-->
|
<!--Error dialog-->
|
||||||
<string name="dialog_error_check_update">Check for updates</string>
|
<string name="dialog_error_check_update">Auf Updates prüfen</string>
|
||||||
<string name="dialog_error_check_update_message">Before reporting a bug, check first if an update with the bug fix is available</string>
|
<string name="dialog_error_check_update_message">Bevor Sie einen Fehler melden, prüfen Sie zuerst, ob ein Update mit der Fehlerbehebung verfügbar ist</string>
|
||||||
<!--Generic-->
|
<!--Generic-->
|
||||||
<string name="all_content">Inhalt</string>
|
<string name="all_content">Inhalt</string>
|
||||||
<string name="all_retry">Wiederhol</string>
|
<string name="all_retry">Wiederhol</string>
|
||||||
@ -289,7 +311,7 @@
|
|||||||
<string name="all_prev">Zurück</string>
|
<string name="all_prev">Zurück</string>
|
||||||
<string name="all_next">Nächste</string>
|
<string name="all_next">Nächste</string>
|
||||||
<string name="all_search">Suchen</string>
|
<string name="all_search">Suchen</string>
|
||||||
<string name="all_search_hint">Suchen...</string>
|
<string name="all_search_hint">Suchen…</string>
|
||||||
<!--Timetable Widget-->
|
<!--Timetable Widget-->
|
||||||
<string name="widget_timetable_no_items">Keine Lektionen</string>
|
<string name="widget_timetable_no_items">Keine Lektionen</string>
|
||||||
<string name="widget_timetable_theme_title">Thema wählen</string>
|
<string name="widget_timetable_theme_title">Thema wählen</string>
|
||||||
|
@ -107,12 +107,36 @@
|
|||||||
<item quantity="many">Nowe oceny</item>
|
<item quantity="many">Nowe oceny</item>
|
||||||
<item quantity="other">Nowe oceny</item>
|
<item quantity="other">Nowe oceny</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_predicted">
|
||||||
|
<item quantity="one">Nowa ocena przewidywana</item>
|
||||||
|
<item quantity="few">Nowe oceny przewidywane</item>
|
||||||
|
<item quantity="many">Nowe oceny przewidywane</item>
|
||||||
|
<item quantity="other">Nowe oceny przewidywane</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_final">
|
||||||
|
<item quantity="one">Nowa ocena końcowa</item>
|
||||||
|
<item quantity="few">Nowe oceny końcowe</item>
|
||||||
|
<item quantity="many">Nowe oceny końcowe</item>
|
||||||
|
<item quantity="other">Nowe oceny końcowe</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="grade_notify_new_items">
|
<plurals name="grade_notify_new_items">
|
||||||
<item quantity="one">Masz %1$d nową ocenę</item>
|
<item quantity="one">Masz %1$d nową ocenę</item>
|
||||||
<item quantity="few">Masz %1$d nowe oceny</item>
|
<item quantity="few">Masz %1$d nowe oceny</item>
|
||||||
<item quantity="many">Masz %1$d nowych ocen</item>
|
<item quantity="many">Masz %1$d nowych ocen</item>
|
||||||
<item quantity="other">Masz %1$d nowych ocen</item>
|
<item quantity="other">Masz %1$d nowych ocen</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_predicted">
|
||||||
|
<item quantity="one">Masz %1$d nową przewidywaną ocenę</item>
|
||||||
|
<item quantity="few">Masz %1$d nowe przewidywane oceny</item>
|
||||||
|
<item quantity="many">Masz %1$d nowych przewidywanych ocen</item>
|
||||||
|
<item quantity="other">Masz %1$d nowych przewidywanych ocen</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_final">
|
||||||
|
<item quantity="one">Masz %1$d nową końcową ocenę</item>
|
||||||
|
<item quantity="few">Masz %1$d nowe końcowe oceny</item>
|
||||||
|
<item quantity="many">Masz %1$d nowych końcowych ocen</item>
|
||||||
|
<item quantity="other">Masz %1$d nowych końcowych ocen</item>
|
||||||
|
</plurals>
|
||||||
<!--Timetable-->
|
<!--Timetable-->
|
||||||
<string name="timetable_lesson">Lekcja</string>
|
<string name="timetable_lesson">Lekcja</string>
|
||||||
<string name="timetable_room">Sala</string>
|
<string name="timetable_room">Sala</string>
|
||||||
@ -180,6 +204,8 @@
|
|||||||
<string name="message_move_to_bin">Przenieś do kosza</string>
|
<string name="message_move_to_bin">Przenieś do kosza</string>
|
||||||
<string name="message_delete_forever">Usuń trwale</string>
|
<string name="message_delete_forever">Usuń trwale</string>
|
||||||
<string name="message_delete_success">Wiadomość usunięta pomyślnie</string>
|
<string name="message_delete_success">Wiadomość usunięta pomyślnie</string>
|
||||||
|
<string name="message_share">Udostępnij</string>
|
||||||
|
<string name="message_print">Drukuj</string>
|
||||||
<string name="message_subject">Temat</string>
|
<string name="message_subject">Temat</string>
|
||||||
<string name="message_content">Treść</string>
|
<string name="message_content">Treść</string>
|
||||||
<string name="message_send_successful">Wiadomość wysłana pomyślnie</string>
|
<string name="message_send_successful">Wiadomość wysłana pomyślnie</string>
|
||||||
@ -265,6 +291,10 @@
|
|||||||
<string name="account_logout">Wyloguj</string>
|
<string name="account_logout">Wyloguj</string>
|
||||||
<string name="account_confirm">Czy chcesz wylogować aktualnego ucznia?</string>
|
<string name="account_confirm">Czy chcesz wylogować aktualnego ucznia?</string>
|
||||||
<string name="account_logout_student">Wylogowanie ucznia</string>
|
<string name="account_logout_student">Wylogowanie ucznia</string>
|
||||||
|
<string name="account_type_student">Konto ucznia</string>
|
||||||
|
<string name="account_type_parent">Konto rodzica</string>
|
||||||
|
<string name="account_login_mobile_api">Tryb API mobilne</string>
|
||||||
|
<string name="account_login_hybrid">Tryb hybrydowy</string>
|
||||||
<!--About-->
|
<!--About-->
|
||||||
<string name="about_version">Wersja aplikacji</string>
|
<string name="about_version">Wersja aplikacji</string>
|
||||||
<string name="about_contributor">Twórcy</string>
|
<string name="about_contributor">Twórcy</string>
|
||||||
@ -309,7 +339,7 @@
|
|||||||
<string name="all_prev">Poprzedni</string>
|
<string name="all_prev">Poprzedni</string>
|
||||||
<string name="all_next">Następny</string>
|
<string name="all_next">Następny</string>
|
||||||
<string name="all_search">Szukaj</string>
|
<string name="all_search">Szukaj</string>
|
||||||
<string name="all_search_hint">Szukaj...</string>
|
<string name="all_search_hint">Szukaj…</string>
|
||||||
<!--Timetable Widget-->
|
<!--Timetable Widget-->
|
||||||
<string name="widget_timetable_no_items">Brak lekcji</string>
|
<string name="widget_timetable_no_items">Brak lekcji</string>
|
||||||
<string name="widget_timetable_theme_title">Wybierz motyw</string>
|
<string name="widget_timetable_theme_title">Wybierz motyw</string>
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
<string-array name="grade_average_mode_entries">
|
<string-array name="grade_average_mode_entries">
|
||||||
<item>Средняя оценка со 2 семестра</item>
|
<item>Средняя оценка со 2 семестра</item>
|
||||||
<item>Average of grades from both semesters</item>
|
<item>Average of grades from both semesters</item>
|
||||||
<item>Средняя оценка с целого года</item>
|
<item>Average of grades from the whole year</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="timetable_show_whole_class_entries">
|
<string-array name="timetable_show_whole_class_entries">
|
||||||
<item>Не показывать</item>
|
<item>Не показывать</item>
|
||||||
|
@ -107,12 +107,36 @@
|
|||||||
<item quantity="many">Новые оценки</item>
|
<item quantity="many">Новые оценки</item>
|
||||||
<item quantity="other">Новые оценки</item>
|
<item quantity="other">Новые оценки</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_predicted">
|
||||||
|
<item quantity="one">New predicted grade</item>
|
||||||
|
<item quantity="few">New predicted grades</item>
|
||||||
|
<item quantity="many">New predicted grades</item>
|
||||||
|
<item quantity="other">New predicted grades</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_final">
|
||||||
|
<item quantity="one">New final grade</item>
|
||||||
|
<item quantity="few">New final grades</item>
|
||||||
|
<item quantity="many">New final grades</item>
|
||||||
|
<item quantity="other">New final grades</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="grade_notify_new_items">
|
<plurals name="grade_notify_new_items">
|
||||||
<item quantity="one">Вы получили %1$d оценку</item>
|
<item quantity="one">Вы получили %1$d оценку</item>
|
||||||
<item quantity="few">Вы получили %1$d оценки</item>
|
<item quantity="few">Вы получили %1$d оценки</item>
|
||||||
<item quantity="many">Вы получили %1$d оценок</item>
|
<item quantity="many">Вы получили %1$d оценок</item>
|
||||||
<item quantity="other">Вы получили %1$d оценок</item>
|
<item quantity="other">Вы получили %1$d оценок</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_predicted">
|
||||||
|
<item quantity="one">You received %1$d predicted grade</item>
|
||||||
|
<item quantity="few">You received %1$d predicted grades</item>
|
||||||
|
<item quantity="many">You received %1$d predicted grades</item>
|
||||||
|
<item quantity="other">You received %1$d predicted grades</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_final">
|
||||||
|
<item quantity="one">You received %1$d final grade</item>
|
||||||
|
<item quantity="few">You received %1$d final grades</item>
|
||||||
|
<item quantity="many">You received %1$d final grades</item>
|
||||||
|
<item quantity="other">You received %1$d final grades</item>
|
||||||
|
</plurals>
|
||||||
<!--Timetable-->
|
<!--Timetable-->
|
||||||
<string name="timetable_lesson">Урок</string>
|
<string name="timetable_lesson">Урок</string>
|
||||||
<string name="timetable_room">Аудитория</string>
|
<string name="timetable_room">Аудитория</string>
|
||||||
@ -180,6 +204,8 @@
|
|||||||
<string name="message_move_to_bin">Перенести в корзину</string>
|
<string name="message_move_to_bin">Перенести в корзину</string>
|
||||||
<string name="message_delete_forever">Удалить навсегда</string>
|
<string name="message_delete_forever">Удалить навсегда</string>
|
||||||
<string name="message_delete_success">Сообщение успешно удалено</string>
|
<string name="message_delete_success">Сообщение успешно удалено</string>
|
||||||
|
<string name="message_share">Share</string>
|
||||||
|
<string name="message_print">Print</string>
|
||||||
<string name="message_subject">Тема</string>
|
<string name="message_subject">Тема</string>
|
||||||
<string name="message_content">Текст</string>
|
<string name="message_content">Текст</string>
|
||||||
<string name="message_send_successful">Сообщение успешно отправлено</string>
|
<string name="message_send_successful">Сообщение успешно отправлено</string>
|
||||||
@ -265,6 +291,10 @@
|
|||||||
<string name="account_logout">Выйти</string>
|
<string name="account_logout">Выйти</string>
|
||||||
<string name="account_confirm">Вы точно хотите выйти из данного аккаунта?</string>
|
<string name="account_confirm">Вы точно хотите выйти из данного аккаунта?</string>
|
||||||
<string name="account_logout_student">Выйти</string>
|
<string name="account_logout_student">Выйти</string>
|
||||||
|
<string name="account_type_student">Student account</string>
|
||||||
|
<string name="account_type_parent">Parent account</string>
|
||||||
|
<string name="account_login_mobile_api">Mobile API mode</string>
|
||||||
|
<string name="account_login_hybrid">Hybrid mode</string>
|
||||||
<!--About-->
|
<!--About-->
|
||||||
<string name="about_version">Версия приложения</string>
|
<string name="about_version">Версия приложения</string>
|
||||||
<string name="about_contributor">Разработчики</string>
|
<string name="about_contributor">Разработчики</string>
|
||||||
@ -309,7 +339,7 @@
|
|||||||
<string name="all_prev">Предыдущий</string>
|
<string name="all_prev">Предыдущий</string>
|
||||||
<string name="all_next">Следующий</string>
|
<string name="all_next">Следующий</string>
|
||||||
<string name="all_search">Поиск</string>
|
<string name="all_search">Поиск</string>
|
||||||
<string name="all_search_hint">Поиск...</string>
|
<string name="all_search_hint">Поиск…</string>
|
||||||
<!--Timetable Widget-->
|
<!--Timetable Widget-->
|
||||||
<string name="widget_timetable_no_items">Нет уроков</string>
|
<string name="widget_timetable_no_items">Нет уроков</string>
|
||||||
<string name="widget_timetable_theme_title">Выбрать тему</string>
|
<string name="widget_timetable_theme_title">Выбрать тему</string>
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
<string-array name="grade_average_mode_entries">
|
<string-array name="grade_average_mode_entries">
|
||||||
<item>Середня оцінка з 2 семестру</item>
|
<item>Середня оцінка з 2 семестру</item>
|
||||||
<item>Average of grades from both semesters</item>
|
<item>Average of grades from both semesters</item>
|
||||||
<item>Середня оцінка за весь рік</item>
|
<item>Average of grades from the whole year</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="timetable_show_whole_class_entries">
|
<string-array name="timetable_show_whole_class_entries">
|
||||||
<item>Не показувати</item>
|
<item>Не показувати</item>
|
||||||
|
@ -107,12 +107,36 @@
|
|||||||
<item quantity="many">Нові оцінки</item>
|
<item quantity="many">Нові оцінки</item>
|
||||||
<item quantity="other">Нові оцінки</item>
|
<item quantity="other">Нові оцінки</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_predicted">
|
||||||
|
<item quantity="one">New predicted grade</item>
|
||||||
|
<item quantity="few">New predicted grades</item>
|
||||||
|
<item quantity="many">New predicted grades</item>
|
||||||
|
<item quantity="other">New predicted grades</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_final">
|
||||||
|
<item quantity="one">New final grade</item>
|
||||||
|
<item quantity="few">New final grades</item>
|
||||||
|
<item quantity="many">New final grades</item>
|
||||||
|
<item quantity="other">New final grades</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="grade_notify_new_items">
|
<plurals name="grade_notify_new_items">
|
||||||
<item quantity="one">Ви отримали %1$d оцінку</item>
|
<item quantity="one">Ви отримали %1$d оцінку</item>
|
||||||
<item quantity="few">Ви отримали %1$d оцінки</item>
|
<item quantity="few">Ви отримали %1$d оцінки</item>
|
||||||
<item quantity="many">Ви отримали %1$d оцінок</item>
|
<item quantity="many">Ви отримали %1$d оцінок</item>
|
||||||
<item quantity="other">Ви отримали %1$d оцінок</item>
|
<item quantity="other">Ви отримали %1$d оцінок</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_predicted">
|
||||||
|
<item quantity="one">You received %1$d predicted grade</item>
|
||||||
|
<item quantity="few">You received %1$d predicted grades</item>
|
||||||
|
<item quantity="many">You received %1$d predicted grades</item>
|
||||||
|
<item quantity="other">You received %1$d predicted grades</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_final">
|
||||||
|
<item quantity="one">You received %1$d final grade</item>
|
||||||
|
<item quantity="few">You received %1$d final grades</item>
|
||||||
|
<item quantity="many">You received %1$d final grades</item>
|
||||||
|
<item quantity="other">You received %1$d final grades</item>
|
||||||
|
</plurals>
|
||||||
<!--Timetable-->
|
<!--Timetable-->
|
||||||
<string name="timetable_lesson">Урок</string>
|
<string name="timetable_lesson">Урок</string>
|
||||||
<string name="timetable_room">Аудиторія</string>
|
<string name="timetable_room">Аудиторія</string>
|
||||||
@ -180,6 +204,8 @@
|
|||||||
<string name="message_move_to_bin">Перемістити у кошик</string>
|
<string name="message_move_to_bin">Перемістити у кошик</string>
|
||||||
<string name="message_delete_forever">Видалити назавжди</string>
|
<string name="message_delete_forever">Видалити назавжди</string>
|
||||||
<string name="message_delete_success">Повідомлення було успішно видалено</string>
|
<string name="message_delete_success">Повідомлення було успішно видалено</string>
|
||||||
|
<string name="message_share">Share</string>
|
||||||
|
<string name="message_print">Print</string>
|
||||||
<string name="message_subject">Тема</string>
|
<string name="message_subject">Тема</string>
|
||||||
<string name="message_content">Зміст</string>
|
<string name="message_content">Зміст</string>
|
||||||
<string name="message_send_successful">Повідомлення було успішно відправлено</string>
|
<string name="message_send_successful">Повідомлення було успішно відправлено</string>
|
||||||
@ -265,6 +291,10 @@
|
|||||||
<string name="account_logout">Вийти</string>
|
<string name="account_logout">Вийти</string>
|
||||||
<string name="account_confirm">Ви впевнені, що хочете вийти з цього аккаунту?</string>
|
<string name="account_confirm">Ви впевнені, що хочете вийти з цього аккаунту?</string>
|
||||||
<string name="account_logout_student">Вийти з аккаунту учня</string>
|
<string name="account_logout_student">Вийти з аккаунту учня</string>
|
||||||
|
<string name="account_type_student">Student account</string>
|
||||||
|
<string name="account_type_parent">Parent account</string>
|
||||||
|
<string name="account_login_mobile_api">Mobile API mode</string>
|
||||||
|
<string name="account_login_hybrid">Hybrid mode</string>
|
||||||
<!--About-->
|
<!--About-->
|
||||||
<string name="about_version">Версія додатка</string>
|
<string name="about_version">Версія додатка</string>
|
||||||
<string name="about_contributor">Розробники</string>
|
<string name="about_contributor">Розробники</string>
|
||||||
@ -309,7 +339,7 @@
|
|||||||
<string name="all_prev">Попередній</string>
|
<string name="all_prev">Попередній</string>
|
||||||
<string name="all_next">Наступний</string>
|
<string name="all_next">Наступний</string>
|
||||||
<string name="all_search">Пошук</string>
|
<string name="all_search">Пошук</string>
|
||||||
<string name="all_search_hint">Пошук...</string>
|
<string name="all_search_hint">Пошук…</string>
|
||||||
<!--Timetable Widget-->
|
<!--Timetable Widget-->
|
||||||
<string name="widget_timetable_no_items">Брак уроків</string>
|
<string name="widget_timetable_no_items">Брак уроків</string>
|
||||||
<string name="widget_timetable_theme_title">Увібрати тему</string>
|
<string name="widget_timetable_theme_title">Увібрати тему</string>
|
||||||
|
@ -113,10 +113,26 @@
|
|||||||
<item quantity="one">New grade</item>
|
<item quantity="one">New grade</item>
|
||||||
<item quantity="other">New grades</item>
|
<item quantity="other">New grades</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_predicted">
|
||||||
|
<item quantity="one">New predicted grade</item>
|
||||||
|
<item quantity="other">New predicted grades</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_new_items_final">
|
||||||
|
<item quantity="one">New final grade</item>
|
||||||
|
<item quantity="other">New final grades</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="grade_notify_new_items">
|
<plurals name="grade_notify_new_items">
|
||||||
<item quantity="one">You received %1$d grade</item>
|
<item quantity="one">You received %1$d grade</item>
|
||||||
<item quantity="other">You received %1$d grades</item>
|
<item quantity="other">You received %1$d grades</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_predicted">
|
||||||
|
<item quantity="one">You received %1$d predicted grade</item>
|
||||||
|
<item quantity="other">You received %1$d predicted grades</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="grade_notify_new_items_final">
|
||||||
|
<item quantity="one">You received %1$d final grade</item>
|
||||||
|
<item quantity="other">You received %1$d final grades</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
|
||||||
<!--Timetable-->
|
<!--Timetable-->
|
||||||
@ -194,6 +210,8 @@
|
|||||||
<string name="message_move_to_bin">Move to trash</string>
|
<string name="message_move_to_bin">Move to trash</string>
|
||||||
<string name="message_delete_forever">Delete permanently</string>
|
<string name="message_delete_forever">Delete permanently</string>
|
||||||
<string name="message_delete_success">Message deleted successfully</string>
|
<string name="message_delete_success">Message deleted successfully</string>
|
||||||
|
<string name="message_share">Share</string>
|
||||||
|
<string name="message_print">Print</string>
|
||||||
<string name="message_subject">Subject</string>
|
<string name="message_subject">Subject</string>
|
||||||
<string name="message_content">Content</string>
|
<string name="message_content">Content</string>
|
||||||
<string name="message_send_successful">Message sent successfully</string>
|
<string name="message_send_successful">Message sent successfully</string>
|
||||||
@ -282,6 +300,10 @@
|
|||||||
<string name="account_logout">Logout</string>
|
<string name="account_logout">Logout</string>
|
||||||
<string name="account_confirm">Do you want to log out of an active student?</string>
|
<string name="account_confirm">Do you want to log out of an active student?</string>
|
||||||
<string name="account_logout_student">Student logout</string>
|
<string name="account_logout_student">Student logout</string>
|
||||||
|
<string name="account_type_student">Student account</string>
|
||||||
|
<string name="account_type_parent">Parent account</string>
|
||||||
|
<string name="account_login_mobile_api">Mobile API mode</string>
|
||||||
|
<string name="account_login_hybrid">Hybrid mode</string>
|
||||||
|
|
||||||
|
|
||||||
<!--About-->
|
<!--About-->
|
||||||
@ -339,7 +361,7 @@
|
|||||||
<string name="all_prev">Prev</string>
|
<string name="all_prev">Prev</string>
|
||||||
<string name="all_next">Next</string>
|
<string name="all_next">Next</string>
|
||||||
<string name="all_search">Search</string>
|
<string name="all_search">Search</string>
|
||||||
<string name="all_search_hint">Search...</string>
|
<string name="all_search_hint">Search…</string>
|
||||||
|
|
||||||
|
|
||||||
<!--Timetable Widget-->
|
<!--Timetable Widget-->
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy
|
package io.github.wulkanowy
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
@ -72,3 +73,25 @@ fun getTimetableEntity(
|
|||||||
teacher = "",
|
teacher = "",
|
||||||
teacherOld = ""
|
teacherOld = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun getMessageEntity(
|
||||||
|
messageId: Int,
|
||||||
|
content: String,
|
||||||
|
unread: Boolean
|
||||||
|
) = Message(
|
||||||
|
studentId = 1,
|
||||||
|
realId = 1,
|
||||||
|
messageId = messageId,
|
||||||
|
sender = "",
|
||||||
|
senderId = 1,
|
||||||
|
recipient = "",
|
||||||
|
subject = "",
|
||||||
|
content = content,
|
||||||
|
date = now(),
|
||||||
|
folderId = 1,
|
||||||
|
unread = unread,
|
||||||
|
unreadBy = 1,
|
||||||
|
readBy = 1,
|
||||||
|
removed = false,
|
||||||
|
hasAttachments = false
|
||||||
|
)
|
||||||
|
@ -2,10 +2,10 @@ package io.github.wulkanowy.data.repositories.message
|
|||||||
|
|
||||||
import androidx.room.EmptyResultSetException
|
import androidx.room.EmptyResultSetException
|
||||||
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.db.entities.Message
|
|
||||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.UnitTestInternetObservingStrategy
|
import io.github.wulkanowy.data.repositories.UnitTestInternetObservingStrategy
|
||||||
|
import io.github.wulkanowy.getMessageEntity
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import io.reactivex.observers.TestObserver
|
import io.reactivex.observers.TestObserver
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
@ -15,7 +15,6 @@ import org.mockito.Mock
|
|||||||
import org.mockito.Mockito.`when`
|
import org.mockito.Mockito.`when`
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
import org.threeten.bp.LocalDateTime.now
|
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
|
|
||||||
class MessageRepositoryTest {
|
class MessageRepositoryTest {
|
||||||
@ -44,7 +43,7 @@ class MessageRepositoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `throw error when message is not in the db`() {
|
fun `throw error when message is not in the db`() {
|
||||||
val testMessage = Message(1, 1, 1, "", 1, "", "", "", now(), 1, false, 1, 1, false, false)
|
val testMessage = getMessageEntity(1, "", false)
|
||||||
`when`(local.getMessageWithAttachment(student, testMessage)).thenReturn(Single.error(EmptyResultSetException("No message in database")))
|
`when`(local.getMessageWithAttachment(student, testMessage)).thenReturn(Single.error(EmptyResultSetException("No message in database")))
|
||||||
|
|
||||||
val message = repo.getMessage(student, testMessage)
|
val message = repo.getMessage(student, testMessage)
|
||||||
@ -55,7 +54,7 @@ class MessageRepositoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get message when content already in db`() {
|
fun `get message when content already in db`() {
|
||||||
val testMessage = Message(1, 1, 123, "", 1, "", "", "Test", now(), 1, false, 1, 1, false, false)
|
val testMessage = getMessageEntity(123, "Test", false)
|
||||||
val messageWithAttachment = MessageWithAttachment(testMessage, emptyList())
|
val messageWithAttachment = MessageWithAttachment(testMessage, emptyList())
|
||||||
|
|
||||||
`when`(local.getMessageWithAttachment(student, testMessage)).thenReturn(Single.just(messageWithAttachment))
|
`when`(local.getMessageWithAttachment(student, testMessage)).thenReturn(Single.just(messageWithAttachment))
|
||||||
@ -67,7 +66,7 @@ class MessageRepositoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get message when content in db is empty`() {
|
fun `get message when content in db is empty`() {
|
||||||
val testMessage = Message(1, 1, 123, "", 1, "", "", "", now(), 1, true, 1, 1, false, false)
|
val testMessage = getMessageEntity(123, "", true)
|
||||||
val testMessageWithContent = testMessage.copy(content = "Test")
|
val testMessageWithContent = testMessage.copy(content = "Test")
|
||||||
|
|
||||||
val mWa = MessageWithAttachment(testMessage, emptyList())
|
val mWa = MessageWithAttachment(testMessage, emptyList())
|
||||||
@ -86,7 +85,7 @@ class MessageRepositoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get message when content in db is empty and there is no internet connection`() {
|
fun `get message when content in db is empty and there is no internet connection`() {
|
||||||
val testMessage = Message(1, 1, 123, "", 1, "", "", "", now(), 1, false, 1, 1, false, false)
|
val testMessage = getMessageEntity(123, "", false)
|
||||||
val messageWithAttachment = MessageWithAttachment(testMessage, emptyList())
|
val messageWithAttachment = MessageWithAttachment(testMessage, emptyList())
|
||||||
|
|
||||||
testObservingStrategy.isInternetConnection = false
|
testObservingStrategy.isInternetConnection = false
|
||||||
@ -100,7 +99,7 @@ class MessageRepositoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get message when content in db is empty, unread and there is no internet connection`() {
|
fun `get message when content in db is empty, unread and there is no internet connection`() {
|
||||||
val testMessage = Message(1, 1, 123, "", 1, "", "", "", now(), 1, true, 1, 1, false, false)
|
val testMessage = getMessageEntity(123, "", true)
|
||||||
val messageWithAttachment = MessageWithAttachment(testMessage, emptyList())
|
val messageWithAttachment = MessageWithAttachment(testMessage, emptyList())
|
||||||
|
|
||||||
testObservingStrategy.isInternetConnection = false
|
testObservingStrategy.isInternetConnection = false
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.72'
|
ext.kotlin_version = '1.3.72'
|
||||||
ext.about_libraries = '8.1.6'
|
ext.about_libraries = '8.2.0'
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
@ -13,7 +13,7 @@ buildscript {
|
|||||||
classpath 'com.google.gms:google-services:4.3.3'
|
classpath 'com.google.gms:google-services:4.3.3'
|
||||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.1.1'
|
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.1.1'
|
||||||
classpath "com.github.triplet.gradle:play-publisher:2.7.5"
|
classpath "com.github.triplet.gradle:play-publisher:2.7.5"
|
||||||
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.8"
|
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.0"
|
||||||
classpath "gradle.plugin.com.star-zero.gradle:githook:1.2.0"
|
classpath "gradle.plugin.com.star-zero.gradle:githook:1.2.0"
|
||||||
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${about_libraries}"
|
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${about_libraries}"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user