forked from github/wulkanowy-mirror
Merge branch 'release/0.19.0'
This commit is contained in:
.travis.yml
app
build.gradle
build.gradleschemas
src
androidTest
java
io
github
wulkanowy
data
db
migrations
repositories
fdroid
java
io
github
wulkanowy
utils
main
assets
java
io
github
wulkanowy
data
services
sync
ui
modules
about
logviewer
account
attendance
grade
message
preview
tab
timetable
completed
utils
play
release-notes
pl-PL
res
drawable
layout
menu
values-de
values-pl
values-ru
values-uk
values
test
java
io
github
wulkanowy
@ -14,7 +14,7 @@ cache:
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- 0.18.3
|
||||
- 0.19.0
|
||||
|
||||
android:
|
||||
licenses:
|
||||
|
@ -17,8 +17,8 @@ android {
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 29
|
||||
versionCode 62
|
||||
versionName "0.18.3"
|
||||
versionCode 63
|
||||
versionName "0.19.0"
|
||||
multiDexEnabled true
|
||||
resValue "string", "app_name", "Wulkanowy"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
@ -77,8 +77,8 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
viewBinding {
|
||||
enabled = true
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
@ -124,14 +124,14 @@ configurations.all {
|
||||
}
|
||||
|
||||
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 "androidx.core:core-ktx:1.2.0"
|
||||
implementation "androidx.activity:activity-ktx:1.1.0"
|
||||
implementation "androidx.appcompat:appcompat:1.2.0-rc01"
|
||||
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.multidex:multidex:2.0.1"
|
||||
|
||||
@ -142,7 +142,7 @@ dependencies {
|
||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout: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 "me.zhanghai.android.materialprogressbar:library:1.6.1"
|
||||
|
||||
@ -180,12 +180,13 @@ dependencies {
|
||||
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
||||
implementation "io.coil-kt:coil:0.11.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-ktx:19.0.7"
|
||||
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'
|
||||
|
||||
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')"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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)
|
||||
}
|
||||
|
||||
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
|
||||
assertTrue { it.single { it.second }.second }
|
||||
assertEquals(1970, it[0].first.schoolYear)
|
||||
assertEquals(of(1970, 1, 1), it[0].first.end)
|
||||
assertEquals(of(1970, 1, 1), it[0].first.start)
|
||||
assertFalse(it[0].second)
|
||||
assertFalse(it[1].second)
|
||||
assertFalse(it[2].second)
|
||||
assertTrue(it[3].second)
|
||||
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let { semesters ->
|
||||
assertTrue { semesters.single { it.second }.second }
|
||||
assertEquals(1970, semesters[0].first.schoolYear)
|
||||
assertEquals(of(1970, 1, 1), semesters[0].first.end)
|
||||
assertEquals(of(1970, 1, 1), semesters[0].first.start)
|
||||
assertFalse(semesters[0].second)
|
||||
assertFalse(semesters[1].second)
|
||||
assertFalse(semesters[2].second)
|
||||
assertTrue(semesters[3].second)
|
||||
}
|
||||
|
||||
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
|
||||
assertTrue { it.single { it.second }.second }
|
||||
assertFalse(it[0].second)
|
||||
assertFalse(it[1].second)
|
||||
assertFalse(it[2].second)
|
||||
assertTrue(it[3].second)
|
||||
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let { semesters ->
|
||||
assertTrue { semesters.single { it.second }.second }
|
||||
assertFalse(semesters[0].second)
|
||||
assertFalse(semesters[1].second)
|
||||
assertFalse(semesters[2].second)
|
||||
assertTrue(semesters[3].second)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import org.threeten.bp.LocalDate.of
|
||||
import kotlin.test.assertEquals
|
||||
@ -35,9 +36,18 @@ class AttendanceLocalTest {
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
attendanceLocal.saveAttendance(listOf(
|
||||
Attendance(1, 2, 3, of(2018, 9, 10), 0, "", "", false, false, false, false, false, false, false, SentExcuseStatus.ACCEPTED.name),
|
||||
Attendance(1, 2, 3, of(2018, 9, 14), 0, "", "", false, false, false, false, false, false, false, SentExcuseStatus.WAITING.name),
|
||||
Attendance(1, 2, 3, of(2018, 9, 17), 0, "", "", false, false, false, false, false, false, false, SentExcuseStatus.ACCEPTED.name)
|
||||
getAttendanceEntity(
|
||||
of(2018, 9, 10),
|
||||
SentExcuseStatus.ACCEPTED
|
||||
),
|
||||
getAttendanceEntity(
|
||||
of(2018, 9, 14),
|
||||
SentExcuseStatus.WAITING
|
||||
),
|
||||
getAttendanceEntity(
|
||||
of(2018, 9, 17),
|
||||
SentExcuseStatus.ACCEPTED
|
||||
)
|
||||
))
|
||||
|
||||
val attendance = attendanceLocal
|
||||
@ -50,4 +60,25 @@ class AttendanceLocalTest {
|
||||
assertEquals(attendance[0].date, of(2018, 9, 10))
|
||||
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
|
||||
)
|
||||
}
|
||||
|
1
app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt
1
app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt
@ -5,7 +5,6 @@ import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
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 org.junit.After
|
||||
import org.junit.Before
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.content.Context
|
||||
import timber.log.Timber
|
||||
|
||||
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 (image error) Size: 13 KiB |
@ -1,17 +1,15 @@
|
||||
package io.github.wulkanowy.data
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.AssetManager
|
||||
import android.content.res.Resources
|
||||
import androidx.core.content.getSystemService
|
||||
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.ChuckerInterceptor
|
||||
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.Provides
|
||||
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.Migration24
|
||||
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.Migration4
|
||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||
@ -110,7 +111,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 25
|
||||
const val VERSION_SCHEMA = 26
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
||||
return arrayOf(
|
||||
@ -137,7 +138,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration22(),
|
||||
Migration23(),
|
||||
Migration24(),
|
||||
Migration25()
|
||||
Migration25(),
|
||||
Migration26()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDateTime
|
||||
|
||||
@Entity(tableName = "GradesSummary")
|
||||
data class GradeSummary(
|
||||
@ -36,4 +37,16 @@ data class GradeSummary(
|
||||
) {
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
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
|
||||
class AppCreatorRepository @Inject constructor(private val assets: AssetManager) {
|
||||
fun getAppCreators(): Single<List<Contributor>> {
|
||||
return Single.fromCallable<List<Contributor>> {
|
||||
return Single.fromCallable {
|
||||
Gson().fromJson(
|
||||
assets.open("contributors.json").bufferedReader().use { it.readText() },
|
||||
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>> {
|
||||
return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
||||
.filter { !it.isEmpty() }
|
||||
.filter { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
fun saveExams(exams: List<Exam>) {
|
||||
|
@ -27,6 +27,10 @@ class GradeLocal @Inject constructor(
|
||||
gradeDb.updateAll(grades)
|
||||
}
|
||||
|
||||
fun updateGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
gradeSummaryDb.updateAll(gradesSummary)
|
||||
}
|
||||
|
||||
fun getGradesDetails(semester: Semester): Maybe<List<Grade>> {
|
||||
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.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -43,7 +44,31 @@ class GradeRepository @Inject constructor(
|
||||
local.getGradesSummary(semester).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
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 {
|
||||
@ -63,6 +88,14 @@ class GradeRepository @Inject constructor(
|
||||
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 {
|
||||
return Completable.fromCallable { local.updateGrades(listOf(grade)) }
|
||||
}
|
||||
@ -70,4 +103,8 @@ class GradeRepository @Inject constructor(
|
||||
fun updateGrades(grades: List<Grade>): Completable {
|
||||
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) {
|
||||
|
||||
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> {
|
||||
|
@ -11,7 +11,7 @@ import javax.inject.Singleton
|
||||
class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: ReportingUnitDao) {
|
||||
|
||||
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> {
|
||||
|
@ -14,7 +14,7 @@ class StudentRemote @Inject constructor(private val sdk: Sdk) {
|
||||
private fun mapStudents(students: List<SdkStudent>, email: String, password: String): List<Student> {
|
||||
return students.map { student ->
|
||||
Student(
|
||||
email = email,
|
||||
email = email.ifBlank { student.email },
|
||||
password = password,
|
||||
isParent = student.isParent,
|
||||
symbol = student.symbol,
|
||||
|
@ -9,7 +9,7 @@ import javax.inject.Inject
|
||||
class GradeStatisticsWork @Inject constructor(private val gradeStatisticsRepository: GradeStatisticsRepository) : Work {
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import androidx.core.app.NotificationCompat.PRIORITY_HIGH
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import io.github.wulkanowy.R
|
||||
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.Student
|
||||
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||
@ -30,17 +31,21 @@ class GradeWork @Inject constructor(
|
||||
|
||||
override fun create(student: Student, semester: Semester): Completable {
|
||||
return gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable)
|
||||
.flatMap { gradeRepository.getNotNotifiedGrades(semester) }
|
||||
.flatMapCompletable {
|
||||
if (it.isNotEmpty()) notify(it)
|
||||
.ignoreElement()
|
||||
.concatWith(Completable.concatArray(gradeRepository.getNotNotifiedGrades(semester).flatMapCompletable {
|
||||
if (it.isNotEmpty()) notifyDetails(it)
|
||||
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>) {
|
||||
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), 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))
|
||||
private fun getNotificationBuilder(): NotificationCompat.Builder {
|
||||
return NotificationCompat.Builder(context, NewGradesChannel.CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_stat_grade)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(PRIORITY_HIGH)
|
||||
@ -49,6 +54,12 @@ class GradeWork @Inject constructor(
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(context, MainView.Section.GRADE.id,
|
||||
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 {
|
||||
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
|
||||
grades.forEach { addLine("${it.subject}: ${it.entry}") }
|
||||
@ -57,4 +68,30 @@ class GradeWork @Inject constructor(
|
||||
.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()
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Loading logs files result: ${it.joinToString { it.name }}")
|
||||
view?.shareLogs(it)
|
||||
.subscribe({ files ->
|
||||
Timber.i("Loading logs files result: ${files.joinToString { it.name }}")
|
||||
view?.shareLogs(files)
|
||||
}, {
|
||||
Timber.i("Loading logs files result: An exception occurred")
|
||||
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.graphics.PorterDuff
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.databinding.HeaderAccountBinding
|
||||
import io.github.wulkanowy.databinding.ItemAccountBinding
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
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 = {}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
|
||||
ItemAccountBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
)
|
||||
override fun getItemViewType(position: Int) = items[position].viewType.id
|
||||
|
||||
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")
|
||||
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
|
||||
val student = items[position]
|
||||
|
||||
with(holder.binding) {
|
||||
private fun bindItemViewHolder(binding: ItemAccountBinding, student: Student) {
|
||||
with(binding) {
|
||||
accountItemName.text = "${student.studentName} ${student.className}"
|
||||
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) {
|
||||
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)
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import android.widget.Toast.LENGTH_LONG
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.databinding.DialogAccountBinding
|
||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||
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) {
|
||||
items = data
|
||||
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() {
|
||||
Timber.i("Loading account data started")
|
||||
disposable.add(studentRepository.getSavedStudents(false)
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.map { createAccountItems(it) }
|
||||
.subscribe({
|
||||
Timber.i("Loading account result: Success")
|
||||
view?.updateData(it)
|
||||
|
@ -1,13 +1,12 @@
|
||||
package io.github.wulkanowy.ui.modules.account
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface AccountView : BaseView {
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<Student>)
|
||||
fun updateData(data: List<AccountItem<*>>)
|
||||
|
||||
fun dismissView()
|
||||
|
||||
|
@ -20,7 +20,6 @@ import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import org.threeten.bp.LocalDate.ofEpochDay
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import javax.inject.Inject
|
||||
|
||||
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> {
|
||||
if (isNotEmpty() && size == grades.size) return this
|
||||
if (isNotEmpty() && size > grades.size) return this
|
||||
|
||||
return grades.mapIndexed { i, (subject, details) ->
|
||||
singleOrNull { it.subject == subject }?.let { return@mapIndexed it }
|
||||
|
@ -63,7 +63,7 @@ class MessagePreviewAdapter @Inject constructor() :
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun bindMessage(holder: MessageViewHolder, message: Message) {
|
||||
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"))
|
||||
messagePreviewContent.text = message.content
|
||||
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
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.print.PrintAttributes
|
||||
import android.print.PrintManager
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
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 io.github.wulkanowy.R
|
||||
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.message.MessageFragment
|
||||
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
|
||||
|
||||
class MessagePreviewFragment :
|
||||
@ -29,18 +39,31 @@ class MessagePreviewFragment :
|
||||
@Inject
|
||||
lateinit var previewAdapter: MessagePreviewAdapter
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
private var menuReplyButton: MenuItem? = null
|
||||
|
||||
private var menuForwardButton: MenuItem? = null
|
||||
|
||||
private var menuDeleteButton: MenuItem? = null
|
||||
|
||||
private var menuShareButton: MenuItem? = null
|
||||
|
||||
private var menuPrintButton: MenuItem? = null
|
||||
|
||||
override val titleStringId: Int
|
||||
get() = R.string.message_title
|
||||
|
||||
override val deleteMessageSuccessString: String
|
||||
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 {
|
||||
const val MESSAGE_ID_KEY = "message_id"
|
||||
|
||||
@ -77,6 +100,8 @@ class MessagePreviewFragment :
|
||||
menuReplyButton = menu.findItem(R.id.messagePreviewMenuReply)
|
||||
menuForwardButton = menu.findItem(R.id.messagePreviewMenuForward)
|
||||
menuDeleteButton = menu.findItem(R.id.messagePreviewMenuDelete)
|
||||
menuShareButton = menu.findItem(R.id.messagePreviewMenuShare)
|
||||
menuPrintButton = menu.findItem(R.id.messagePreviewMenuPrint)
|
||||
presenter.onCreateOptionsMenu()
|
||||
}
|
||||
|
||||
@ -85,6 +110,8 @@ class MessagePreviewFragment :
|
||||
R.id.messagePreviewMenuReply -> presenter.onReply()
|
||||
R.id.messagePreviewMenuForward -> presenter.onForward()
|
||||
R.id.messagePreviewMenuDelete -> presenter.onMessageDelete()
|
||||
R.id.messagePreviewMenuShare -> presenter.onShare()
|
||||
R.id.messagePreviewMenuPrint -> presenter.onPrint()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@ -108,6 +135,8 @@ class MessagePreviewFragment :
|
||||
menuReplyButton?.isVisible = show
|
||||
menuForwardButton?.isVisible = show
|
||||
menuDeleteButton?.isVisible = show
|
||||
menuShareButton?.isVisible = show
|
||||
menuPrintButton?.isVisible = show && appInfo.systemVersion >= Build.VERSION_CODES.LOLLIPOP
|
||||
}
|
||||
|
||||
override fun setDeletedOptionsLabels() {
|
||||
@ -138,6 +167,38 @@ class MessagePreviewFragment :
|
||||
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() {
|
||||
(activity as MainActivity).popView()
|
||||
}
|
||||
|
@ -1,12 +1,17 @@
|
||||
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.MessageAttachment
|
||||
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -15,11 +20,14 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val messageRepository: MessageRepository,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
private val analytics: FirebaseAnalyticsHelper,
|
||||
private var appInfo: AppInfo
|
||||
) : BasePresenter<MessagePreviewView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
var message: Message? = null
|
||||
|
||||
var attachments: List<MessageAttachment>? = null
|
||||
|
||||
private lateinit var lastError: Throwable
|
||||
|
||||
private var retryCallback: () -> Unit = {}
|
||||
@ -56,6 +64,7 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
.subscribe({ message ->
|
||||
Timber.i("Loading message ${message.message.messageId} preview result: Success ")
|
||||
this@MessagePreviewPresenter.message = message.message
|
||||
this@MessagePreviewPresenter.attachments = message.attachments
|
||||
view?.apply {
|
||||
setMessageWithAttachment(message)
|
||||
initOptions()
|
||||
@ -87,6 +96,60 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
} 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() {
|
||||
message?.let { message ->
|
||||
disposable.add(studentRepository.getCurrentStudent()
|
||||
|
@ -1,5 +1,7 @@
|
||||
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.MessageWithAttachment
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
@ -8,6 +10,10 @@ interface MessagePreviewView : BaseView {
|
||||
|
||||
val deleteMessageSuccessString: String
|
||||
|
||||
val messageNoSubjectString: String
|
||||
|
||||
val printHTML: String
|
||||
|
||||
fun initView()
|
||||
|
||||
fun setMessageWithAttachment(item: MessageWithAttachment)
|
||||
@ -34,5 +40,10 @@ interface MessagePreviewView : BaseView {
|
||||
|
||||
fun openMessageForward(message: Message?)
|
||||
|
||||
fun shareText(text: String, subject: String)
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
fun printDocument(html: String, jobName: String)
|
||||
|
||||
fun popView()
|
||||
}
|
||||
|
@ -4,10 +4,9 @@ import android.graphics.Typeface
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
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.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder
|
||||
@ -20,39 +19,23 @@ class MessageTabAdapter @Inject constructor() :
|
||||
|
||||
var onClickListener: (Message, position: Int) -> Unit = { _, _ -> }
|
||||
|
||||
private val items = SortedList(Message::class.java, object :
|
||||
SortedListAdapterCallback<Message>(this) {
|
||||
private var items = mutableListOf<Message>()
|
||||
|
||||
override fun compare(item1: Message, item2: Message): Int {
|
||||
return item2.date.compareTo(item1.date)
|
||||
}
|
||||
|
||||
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 setDataItems(data: List<Message>) {
|
||||
val diffResult = DiffUtil.calculateDiff(MessageTabDiffUtil(items, data))
|
||||
items = data.toMutableList()
|
||||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
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(
|
||||
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)
|
||||
|
||||
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>) {
|
||||
tabAdapter.replaceAll(data)
|
||||
tabAdapter.setDataItems(data)
|
||||
}
|
||||
|
||||
override fun updateItem(item: Message, position: Int) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
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.repositories.message.MessageFolder
|
||||
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.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||
import timber.log.Timber
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.pow
|
||||
|
||||
class MessageTabPresenter @Inject constructor(
|
||||
schedulers: SchedulersProvider,
|
||||
@ -31,9 +35,12 @@ class MessageTabPresenter @Inject constructor(
|
||||
|
||||
private var messages = emptyList<Message>()
|
||||
|
||||
private val searchQuery = PublishSubject.create<String>()
|
||||
|
||||
fun onAttachView(view: MessageTabView, folder: MessageFolder) {
|
||||
super.onAttachView(view)
|
||||
view.initView()
|
||||
initializeSearchStream()
|
||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||
this.folder = folder
|
||||
}
|
||||
@ -76,38 +83,35 @@ class MessageTabPresenter @Inject constructor(
|
||||
|
||||
private fun loadData(forceRefresh: Boolean) {
|
||||
Timber.i("Loading $folder message data started")
|
||||
disposable.apply {
|
||||
clear()
|
||||
add(studentRepository.getCurrentStudent()
|
||||
.flatMap { student ->
|
||||
semesterRepository.getCurrentSemester(student)
|
||||
.flatMap { messageRepository.getMessages(student, it, folder, forceRefresh) }
|
||||
disposable.add(studentRepository.getCurrentStudent()
|
||||
.flatMap { student ->
|
||||
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)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
notifyParentDataLoaded()
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
Timber.i("Loading $folder message result: Success")
|
||||
messages = it
|
||||
onSearchQueryTextChange(lastSearchQuery)
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
Timber.i("Loading $folder message result: Success")
|
||||
messages = it
|
||||
view?.updateData(getFilteredData(lastSearchQuery))
|
||||
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) {
|
||||
@ -121,25 +125,36 @@ class MessageTabPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
fun onSearchQueryTextChange(query: String) {
|
||||
lastSearchQuery = query
|
||||
if (query != searchQuery.toString())
|
||||
searchQuery.onNext(query)
|
||||
}
|
||||
|
||||
val lowerCaseQuery = query.toLowerCase()
|
||||
val filteredList = mutableListOf<Message>()
|
||||
messages.forEach {
|
||||
if (lowerCaseQuery in it.subject.toLowerCase() ||
|
||||
lowerCaseQuery in it.sender.toLowerCase() ||
|
||||
lowerCaseQuery in it.recipient.toLowerCase() ||
|
||||
lowerCaseQuery in it.date.toFormattedString()
|
||||
) {
|
||||
filteredList.add(it)
|
||||
private fun initializeSearchStream() {
|
||||
disposable.add(searchQuery
|
||||
.debounce(250, TimeUnit.MILLISECONDS)
|
||||
.map { query ->
|
||||
lastSearchQuery = query
|
||||
getFilteredData(query)
|
||||
}
|
||||
.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>) {
|
||||
@ -151,4 +166,42 @@ class MessageTabPresenter @Inject constructor(
|
||||
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.onFeatureDisabled = {
|
||||
this.view?.showFeatureDisabled()
|
||||
this.view?.showEmpty(true);
|
||||
this.view?.showEmpty(true)
|
||||
Timber.i("Completed lessons feature disabled by school")
|
||||
}
|
||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
|
@ -71,4 +71,17 @@ fun Context.openDialer(phone: String) {
|
||||
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
|
||||
|
@ -52,4 +52,4 @@ class LifecycleAwareVariableActivity<T : Any> : ReadWriteProperty<AppCompatActiv
|
||||
@Suppress("unused")
|
||||
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
|
||||
privateKey = student.privateKey
|
||||
|
||||
emptyCookieJarInterceptor = true
|
||||
|
||||
Timber.d("Sdk in ${student.loginMode} mode reinitialized")
|
||||
|
||||
return this
|
||||
|
@ -1,6 +1,8 @@
|
||||
Wersja 0.18.3
|
||||
- poprawiliśmy liczenie średniej i dodaliśmy nowy sposób jej liczenia w ustawieniach
|
||||
- naprawiliśmy usuwanie wiadomości
|
||||
- naprawiliśmy wysyłanie wiadomości na Lubelskim Portalu Oświatowym
|
||||
Wersja 0.19.0
|
||||
- naprawiliśmy pokazywanie brakujących przedmiotów na liście podsumowania ocen
|
||||
- ulepszyliśmy wygląd menadżera kont
|
||||
- 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
|
||||
|
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_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
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"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/accountDialogTitle"
|
||||
android:overScrollMode="never"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/item_account" />
|
||||
android:orientation="vertical">
|
||||
|
||||
<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_below="@id/accountDialogRecycler"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/account_add_new"
|
||||
android:textColor="?android:textColorPrimary" />
|
||||
<TextView
|
||||
android:id="@+id/accountDialogTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
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" />
|
||||
|
||||
<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_below="@id/accountDialogRecycler"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/account_logout" />
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/accountDialogRecycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_weight="1"
|
||||
android:overScrollMode="never"
|
||||
tools:itemCount="3"
|
||||
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>
|
||||
|
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:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:paddingVertical="8dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
tools:context=".ui.modules.account.AccountAdapter">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/accountItemImage"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_all_account"
|
||||
@ -27,7 +24,7 @@
|
||||
android:id="@+id/accountItemName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textSize="16sp"
|
||||
@ -40,7 +37,7 @@
|
||||
android:id="@+id/accountItemSchool"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="3dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
@ -50,4 +47,21 @@
|
||||
app:layout_constraintStart_toEndOf="@id/accountItemImage"
|
||||
app:layout_constraintTop_toBottomOf="@id/accountItemName"
|
||||
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>
|
||||
|
@ -22,4 +22,18 @@
|
||||
android:title="@string/message_delete"
|
||||
app:iconTint="@color/material_on_surface_emphasis_medium"
|
||||
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>
|
||||
|
@ -36,8 +36,8 @@
|
||||
</string-array>
|
||||
<string-array name="grade_average_mode_entries">
|
||||
<item>Durchschnittsnote für das 2. Semester</item>
|
||||
<item>Average of grades from both semesters</item>
|
||||
<item>Durchschnitt der Bewertungen für das ganze Jahr</item>
|
||||
<item>Durchschnitt der Noten aus beiden Semestern</item>
|
||||
<item>Durchschnitt der Noten aus dem ganzen Jahr</item>
|
||||
</string-array>
|
||||
<string-array name="timetable_show_whole_class_entries">
|
||||
<item>Nicht zeigen</item>
|
||||
|
@ -103,10 +103,26 @@
|
||||
<item quantity="one">Neue Note</item>
|
||||
<item quantity="other">Neue Noten</item>
|
||||
</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">
|
||||
<item quantity="one">Du hast %1$d Note bekommen</item>
|
||||
<item quantity="other">Du hast %1$d Noten bekommen</item>
|
||||
</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-->
|
||||
<string name="timetable_lesson">Lektion</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_delete_forever">Dauerhaft löschen</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_content">Inhalt</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_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">Die heutige Glücksnummer ist: </string>
|
||||
<string name="lucky_number_notify_new_item">Die heutige Glücksnummer ist: %d</string>
|
||||
<!--Mobile devices-->
|
||||
<string name="mobile_devices_title">Mobile 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_confirm">Wollen Sie sich von einem aktiven Studenten abmelden?</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-->
|
||||
<string name="about_version">Version der App</string>
|
||||
<string name="about_contributor">Mitarbeiter</string>
|
||||
@ -270,8 +292,8 @@
|
||||
<string name="logviewer_share">Logs teilen</string>
|
||||
<string name="logviewer_refresh">Aktualisieren</string>
|
||||
<!--Error dialog-->
|
||||
<string name="dialog_error_check_update">Check for updates</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">Auf Updates prüfen</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-->
|
||||
<string name="all_content">Inhalt</string>
|
||||
<string name="all_retry">Wiederhol</string>
|
||||
@ -289,7 +311,7 @@
|
||||
<string name="all_prev">Zurück</string>
|
||||
<string name="all_next">Nächste</string>
|
||||
<string name="all_search">Suchen</string>
|
||||
<string name="all_search_hint">Suchen...</string>
|
||||
<string name="all_search_hint">Suchen…</string>
|
||||
<!--Timetable Widget-->
|
||||
<string name="widget_timetable_no_items">Keine Lektionen</string>
|
||||
<string name="widget_timetable_theme_title">Thema wählen</string>
|
||||
|
@ -107,12 +107,36 @@
|
||||
<item quantity="many">Nowe oceny</item>
|
||||
<item quantity="other">Nowe oceny</item>
|
||||
</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">
|
||||
<item quantity="one">Masz %1$d nową ocenę</item>
|
||||
<item quantity="few">Masz %1$d nowe oceny</item>
|
||||
<item quantity="many">Masz %1$d nowych ocen</item>
|
||||
<item quantity="other">Masz %1$d nowych ocen</item>
|
||||
</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-->
|
||||
<string name="timetable_lesson">Lekcja</string>
|
||||
<string name="timetable_room">Sala</string>
|
||||
@ -180,6 +204,8 @@
|
||||
<string name="message_move_to_bin">Przenieś do kosza</string>
|
||||
<string name="message_delete_forever">Usuń trwale</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_content">Treść</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_confirm">Czy chcesz wylogować aktualnego 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-->
|
||||
<string name="about_version">Wersja aplikacji</string>
|
||||
<string name="about_contributor">Twórcy</string>
|
||||
@ -309,7 +339,7 @@
|
||||
<string name="all_prev">Poprzedni</string>
|
||||
<string name="all_next">Następny</string>
|
||||
<string name="all_search">Szukaj</string>
|
||||
<string name="all_search_hint">Szukaj...</string>
|
||||
<string name="all_search_hint">Szukaj…</string>
|
||||
<!--Timetable Widget-->
|
||||
<string name="widget_timetable_no_items">Brak lekcji</string>
|
||||
<string name="widget_timetable_theme_title">Wybierz motyw</string>
|
||||
|
@ -37,7 +37,7 @@
|
||||
<string-array name="grade_average_mode_entries">
|
||||
<item>Средняя оценка со 2 семестра</item>
|
||||
<item>Average of grades from both semesters</item>
|
||||
<item>Средняя оценка с целого года</item>
|
||||
<item>Average of grades from the whole year</item>
|
||||
</string-array>
|
||||
<string-array name="timetable_show_whole_class_entries">
|
||||
<item>Не показывать</item>
|
||||
|
@ -107,12 +107,36 @@
|
||||
<item quantity="many">Новые оценки</item>
|
||||
<item quantity="other">Новые оценки</item>
|
||||
</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">
|
||||
<item quantity="one">Вы получили %1$d оценку</item>
|
||||
<item quantity="few">Вы получили %1$d оценки</item>
|
||||
<item quantity="many">Вы получили %1$d оценок</item>
|
||||
<item quantity="other">Вы получили %1$d оценок</item>
|
||||
</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-->
|
||||
<string name="timetable_lesson">Урок</string>
|
||||
<string name="timetable_room">Аудитория</string>
|
||||
@ -180,6 +204,8 @@
|
||||
<string name="message_move_to_bin">Перенести в корзину</string>
|
||||
<string name="message_delete_forever">Удалить навсегда</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_content">Текст</string>
|
||||
<string name="message_send_successful">Сообщение успешно отправлено</string>
|
||||
@ -265,6 +291,10 @@
|
||||
<string name="account_logout">Выйти</string>
|
||||
<string name="account_confirm">Вы точно хотите выйти из данного аккаунта?</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-->
|
||||
<string name="about_version">Версия приложения</string>
|
||||
<string name="about_contributor">Разработчики</string>
|
||||
@ -309,7 +339,7 @@
|
||||
<string name="all_prev">Предыдущий</string>
|
||||
<string name="all_next">Следующий</string>
|
||||
<string name="all_search">Поиск</string>
|
||||
<string name="all_search_hint">Поиск...</string>
|
||||
<string name="all_search_hint">Поиск…</string>
|
||||
<!--Timetable Widget-->
|
||||
<string name="widget_timetable_no_items">Нет уроков</string>
|
||||
<string name="widget_timetable_theme_title">Выбрать тему</string>
|
||||
|
@ -37,7 +37,7 @@
|
||||
<string-array name="grade_average_mode_entries">
|
||||
<item>Середня оцінка з 2 семестру</item>
|
||||
<item>Average of grades from both semesters</item>
|
||||
<item>Середня оцінка за весь рік</item>
|
||||
<item>Average of grades from the whole year</item>
|
||||
</string-array>
|
||||
<string-array name="timetable_show_whole_class_entries">
|
||||
<item>Не показувати</item>
|
||||
|
@ -107,12 +107,36 @@
|
||||
<item quantity="many">Нові оцінки</item>
|
||||
<item quantity="other">Нові оцінки</item>
|
||||
</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">
|
||||
<item quantity="one">Ви отримали %1$d оцінку</item>
|
||||
<item quantity="few">Ви отримали %1$d оцінки</item>
|
||||
<item quantity="many">Ви отримали %1$d оцінок</item>
|
||||
<item quantity="other">Ви отримали %1$d оцінок</item>
|
||||
</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-->
|
||||
<string name="timetable_lesson">Урок</string>
|
||||
<string name="timetable_room">Аудиторія</string>
|
||||
@ -180,6 +204,8 @@
|
||||
<string name="message_move_to_bin">Перемістити у кошик</string>
|
||||
<string name="message_delete_forever">Видалити назавжди</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_content">Зміст</string>
|
||||
<string name="message_send_successful">Повідомлення було успішно відправлено</string>
|
||||
@ -265,6 +291,10 @@
|
||||
<string name="account_logout">Вийти</string>
|
||||
<string name="account_confirm">Ви впевнені, що хочете вийти з цього аккаунту?</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-->
|
||||
<string name="about_version">Версія додатка</string>
|
||||
<string name="about_contributor">Розробники</string>
|
||||
@ -309,7 +339,7 @@
|
||||
<string name="all_prev">Попередній</string>
|
||||
<string name="all_next">Наступний</string>
|
||||
<string name="all_search">Пошук</string>
|
||||
<string name="all_search_hint">Пошук...</string>
|
||||
<string name="all_search_hint">Пошук…</string>
|
||||
<!--Timetable Widget-->
|
||||
<string name="widget_timetable_no_items">Брак уроків</string>
|
||||
<string name="widget_timetable_theme_title">Увібрати тему</string>
|
||||
|
@ -113,10 +113,26 @@
|
||||
<item quantity="one">New grade</item>
|
||||
<item quantity="other">New grades</item>
|
||||
</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">
|
||||
<item quantity="one">You received %1$d grade</item>
|
||||
<item quantity="other">You received %1$d grades</item>
|
||||
</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-->
|
||||
@ -194,6 +210,8 @@
|
||||
<string name="message_move_to_bin">Move to trash</string>
|
||||
<string name="message_delete_forever">Delete permanently</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_content">Content</string>
|
||||
<string name="message_send_successful">Message sent successfully</string>
|
||||
@ -282,6 +300,10 @@
|
||||
<string name="account_logout">Logout</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_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-->
|
||||
@ -339,7 +361,7 @@
|
||||
<string name="all_prev">Prev</string>
|
||||
<string name="all_next">Next</string>
|
||||
<string name="all_search">Search</string>
|
||||
<string name="all_search_hint">Search...</string>
|
||||
<string name="all_search_hint">Search…</string>
|
||||
|
||||
|
||||
<!--Timetable Widget-->
|
||||
|
@ -1,5 +1,6 @@
|
||||
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.Student
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
@ -72,3 +73,25 @@ fun getTimetableEntity(
|
||||
teacher = "",
|
||||
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 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.Student
|
||||
import io.github.wulkanowy.data.repositories.UnitTestInternetObservingStrategy
|
||||
import io.github.wulkanowy.getMessageEntity
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.observers.TestObserver
|
||||
import org.junit.Assert.assertEquals
|
||||
@ -15,7 +15,6 @@ import org.mockito.Mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.threeten.bp.LocalDateTime.now
|
||||
import java.net.UnknownHostException
|
||||
|
||||
class MessageRepositoryTest {
|
||||
@ -44,7 +43,7 @@ class MessageRepositoryTest {
|
||||
|
||||
@Test
|
||||
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")))
|
||||
|
||||
val message = repo.getMessage(student, testMessage)
|
||||
@ -55,7 +54,7 @@ class MessageRepositoryTest {
|
||||
|
||||
@Test
|
||||
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())
|
||||
|
||||
`when`(local.getMessageWithAttachment(student, testMessage)).thenReturn(Single.just(messageWithAttachment))
|
||||
@ -67,7 +66,7 @@ class MessageRepositoryTest {
|
||||
|
||||
@Test
|
||||
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 mWa = MessageWithAttachment(testMessage, emptyList())
|
||||
@ -86,7 +85,7 @@ class MessageRepositoryTest {
|
||||
|
||||
@Test
|
||||
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())
|
||||
|
||||
testObservingStrategy.isInternetConnection = false
|
||||
@ -100,7 +99,7 @@ class MessageRepositoryTest {
|
||||
|
||||
@Test
|
||||
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())
|
||||
|
||||
testObservingStrategy.isInternetConnection = false
|
||||
|
@ -1,6 +1,6 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.72'
|
||||
ext.about_libraries = '8.1.6'
|
||||
ext.about_libraries = '8.2.0'
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
@ -13,7 +13,7 @@ buildscript {
|
||||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.1.1'
|
||||
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 "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${about_libraries}"
|
||||
}
|
||||
|
Reference in New Issue
Block a user