forked from github/wulkanowy-mirror
Add sending messages (#232)
This commit is contained in:
parent
5ba12cf8c6
commit
c72c301039
@ -72,8 +72,7 @@ play {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
implementation('com.github.wulkanowy:api:46f09bdf34') { exclude module: "threetenbp" }
|
||||||
implementation('com.github.wulkanowy:api:0a4317f651') { exclude module: "threetenbp" }
|
|
||||||
|
|
||||||
implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||||
implementation "androidx.appcompat:appcompat:1.0.2"
|
implementation "androidx.appcompat:appcompat:1.0.2"
|
||||||
@ -125,6 +124,8 @@ dependencies {
|
|||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
||||||
androidTestImplementation 'org.mockito:mockito-android:2.23.4'
|
androidTestImplementation 'org.mockito:mockito-android:2.23.4'
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
|
|
||||||
|
implementation "com.hootsuite.android:nachos:1.1.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
@ -41,7 +41,7 @@ class AttendanceLocalTest {
|
|||||||
))
|
))
|
||||||
|
|
||||||
val attendance = attendanceLocal
|
val attendance = attendanceLocal
|
||||||
.getAttendance(Semester(1, 2, "", 1, 3, true),
|
.getAttendance(Semester(1, 2, "", 1, 3, true, 1, 1),
|
||||||
LocalDate.of(2018, 9, 10),
|
LocalDate.of(2018, 9, 10),
|
||||||
LocalDate.of(2018, 9, 14)
|
LocalDate.of(2018, 9, 14)
|
||||||
)
|
)
|
||||||
|
@ -42,7 +42,7 @@ class CompletedLessonsLocalTest {
|
|||||||
))
|
))
|
||||||
|
|
||||||
val completed = completedLessonsLocal
|
val completed = completedLessonsLocal
|
||||||
.getCompletedLessons(Semester(1, 2, "", 1, 3, true),
|
.getCompletedLessons(Semester(1, 2, "", 1, 3, true, 1, 1),
|
||||||
LocalDate.of(2018, 9, 10),
|
LocalDate.of(2018, 9, 10),
|
||||||
LocalDate.of(2018, 9, 14)
|
LocalDate.of(2018, 9, 14)
|
||||||
)
|
)
|
||||||
|
@ -41,7 +41,7 @@ class ExamLocalTest {
|
|||||||
))
|
))
|
||||||
|
|
||||||
val exams = examLocal
|
val exams = examLocal
|
||||||
.getExams(Semester(1, 2, "", 1, 3, true),
|
.getExams(Semester(1, 2, "", 1, 3, true, 1, 1),
|
||||||
LocalDate.of(2018, 9, 10),
|
LocalDate.of(2018, 9, 10),
|
||||||
LocalDate.of(2018, 9, 14)
|
LocalDate.of(2018, 9, 14)
|
||||||
)
|
)
|
||||||
|
@ -37,7 +37,7 @@ class LuckyNumberLocalTest {
|
|||||||
fun saveAndReadTest() {
|
fun saveAndReadTest() {
|
||||||
luckyNumberLocal.saveLuckyNumber(LuckyNumber(1, LocalDate.of(2019, 1, 20), 14))
|
luckyNumberLocal.saveLuckyNumber(LuckyNumber(1, LocalDate.of(2019, 1, 20), 14))
|
||||||
|
|
||||||
val luckyNumber = luckyNumberLocal.getLuckyNumber(Semester(1, 1, "", 1, 3, true),
|
val luckyNumber = luckyNumberLocal.getLuckyNumber(Semester(1, 1, "", 1, 3, true, 1, 1),
|
||||||
LocalDate.of(2019, 1, 20)
|
LocalDate.of(2019, 1, 20)
|
||||||
).blockingGet()
|
).blockingGet()
|
||||||
|
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.local
|
||||||
|
|
||||||
|
import androidx.room.Room
|
||||||
|
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.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.data.repositories.recipient.RecipientLocal
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.threeten.bp.LocalDateTime
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class RecipientLocalTest {
|
||||||
|
|
||||||
|
private lateinit var recipientLocal: RecipientLocal
|
||||||
|
|
||||||
|
private lateinit var testDb: AppDatabase
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun createDb() {
|
||||||
|
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||||
|
.build()
|
||||||
|
recipientLocal = RecipientLocal(testDb.recipientDao)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun closeDb() {
|
||||||
|
testDb.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun saveAndReadTest() {
|
||||||
|
recipientLocal.saveRecipients(listOf(
|
||||||
|
Recipient(1, "2rPracownik", "Kowalski Jan", "Kowalski Jan [KJ] - Pracownik (Fake123456)", 3, 4, 2, "hash"),
|
||||||
|
Recipient(1, "3rPracownik", "Kowalska Karolina", "Kowalska Karolina [KK] - Pracownik (Fake123456)", 4, 4, 2, "hash"),
|
||||||
|
Recipient(1, "4rPracownik", "Krupa Stanisław", "Krupa Stanisław [KS] - Uczeń (Fake123456)", 5, 4, 1, "hash")
|
||||||
|
))
|
||||||
|
|
||||||
|
val recipients = recipientLocal.getRecipients(
|
||||||
|
Student("fakelog.cf", "AUTO", "", "", "", 1, "", "", "", true, LocalDateTime.now()),
|
||||||
|
2,
|
||||||
|
ReportingUnit(1, 4, "", 0, "", emptyList())
|
||||||
|
).blockingGet()
|
||||||
|
|
||||||
|
assertEquals(2, recipients.size)
|
||||||
|
assertEquals(1, recipients[0].studentId)
|
||||||
|
assertEquals("3rPracownik", recipients[1].realId)
|
||||||
|
assertEquals("Kowalski Jan", recipients[0].name)
|
||||||
|
assertEquals("Kowalska Karolina [KK] - Pracownik (Fake123456)", recipients[1].realName)
|
||||||
|
assertEquals(3, recipients[0].loginId)
|
||||||
|
assertEquals(4, recipients[1].unitId)
|
||||||
|
assertEquals(2, recipients[0].role)
|
||||||
|
assertEquals("hash", recipients[1].hash)
|
||||||
|
}
|
||||||
|
}
|
@ -45,7 +45,7 @@ class TimetableLocalTest {
|
|||||||
))
|
))
|
||||||
|
|
||||||
val exams = timetableDb.getTimetable(
|
val exams = timetableDb.getTimetable(
|
||||||
Semester(1, 2, "", 1, 1, true),
|
Semester(1, 2, "", 1, 1, true, 1, 1),
|
||||||
LocalDate.of(2018, 9, 10),
|
LocalDate.of(2018, 9, 10),
|
||||||
LocalDate.of(2018, 9, 14)
|
LocalDate.of(2018, 9, 14)
|
||||||
).blockingGet()
|
).blockingGet()
|
||||||
|
@ -121,4 +121,12 @@ internal class RepositoryModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideCompletedLessonsDao(database: AppDatabase) = database.completedLessonsDao
|
fun provideCompletedLessonsDao(database: AppDatabase) = database.completedLessonsDao
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideRecipientDao(database: AppDatabase) = database.recipientDao
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ import io.github.wulkanowy.data.db.dao.HomeworkDao
|
|||||||
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
||||||
import io.github.wulkanowy.data.db.dao.MessagesDao
|
import io.github.wulkanowy.data.db.dao.MessagesDao
|
||||||
import io.github.wulkanowy.data.db.dao.NoteDao
|
import io.github.wulkanowy.data.db.dao.NoteDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.RecipientDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
||||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||||
import io.github.wulkanowy.data.db.dao.SubjectDao
|
import io.github.wulkanowy.data.db.dao.SubjectDao
|
||||||
@ -30,6 +32,8 @@ import io.github.wulkanowy.data.db.entities.Homework
|
|||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.github.wulkanowy.data.db.entities.Note
|
import io.github.wulkanowy.data.db.entities.Note
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
@ -38,6 +42,7 @@ import io.github.wulkanowy.data.db.migrations.Migration2
|
|||||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration6
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -56,7 +61,9 @@ import javax.inject.Singleton
|
|||||||
Homework::class,
|
Homework::class,
|
||||||
Subject::class,
|
Subject::class,
|
||||||
LuckyNumber::class,
|
LuckyNumber::class,
|
||||||
CompletedLesson::class
|
CompletedLesson::class,
|
||||||
|
ReportingUnit::class,
|
||||||
|
Recipient::class
|
||||||
],
|
],
|
||||||
version = AppDatabase.VERSION_SCHEMA,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
@ -65,7 +72,7 @@ import javax.inject.Singleton
|
|||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 5
|
const val VERSION_SCHEMA = 6
|
||||||
|
|
||||||
fun newInstance(context: Context): AppDatabase {
|
fun newInstance(context: Context): AppDatabase {
|
||||||
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
||||||
@ -76,7 +83,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
Migration2(),
|
Migration2(),
|
||||||
Migration3(),
|
Migration3(),
|
||||||
Migration4(),
|
Migration4(),
|
||||||
Migration5()
|
Migration5(),
|
||||||
|
Migration6()
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
@ -109,4 +117,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
abstract val luckyNumberDao: LuckyNumberDao
|
abstract val luckyNumberDao: LuckyNumberDao
|
||||||
|
|
||||||
abstract val completedLessonsDao: CompletedLessonsDao
|
abstract val completedLessonsDao: CompletedLessonsDao
|
||||||
|
|
||||||
|
abstract val reportingUnitDao: ReportingUnitDao
|
||||||
|
|
||||||
|
abstract val recipientDao: RecipientDao
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import org.threeten.bp.LocalDateTime
|
|||||||
import org.threeten.bp.Month
|
import org.threeten.bp.Month
|
||||||
import org.threeten.bp.ZoneOffset
|
import org.threeten.bp.ZoneOffset
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
class Converters {
|
class Converters {
|
||||||
|
|
||||||
@ -36,4 +38,14 @@ class Converters {
|
|||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun intToMonth(value: Int?) = value?.let { Month.of(it) }
|
fun intToMonth(value: Int?) = value?.let { Month.of(it) }
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun intListToGson(list: List<Int>): String {
|
||||||
|
return Gson().toJson(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun gsonToIntList(value: String): List<Int> {
|
||||||
|
return Gson().fromJson(value, object : TypeToken<List<Int>>() {}.type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Dao
|
||||||
|
interface RecipientDao {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insertAll(messages: List<Recipient>)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun deleteAll(messages: List<Recipient>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId")
|
||||||
|
fun load(studentId: Int, role: Int, unitId: Int): Maybe<List<Recipient>>
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Dao
|
||||||
|
interface ReportingUnitDao {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insertAll(reportingUnits: List<ReportingUnit>)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun deleteAll(reportingUnits: List<ReportingUnit>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
|
||||||
|
fun load(studentId: Int): Maybe<List<ReportingUnit>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId AND real_id = :unitId")
|
||||||
|
fun loadOne(studentId: Int, unitId: Int): Maybe<ReportingUnit>
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
@Entity(tableName = "Recipients")
|
||||||
|
data class Recipient(
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
val studentId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "real_id")
|
||||||
|
val realId: String,
|
||||||
|
|
||||||
|
val name: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "real_name")
|
||||||
|
val realName: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "login_id")
|
||||||
|
val loginId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "unit_id")
|
||||||
|
val unitId: Int,
|
||||||
|
|
||||||
|
val role: Int,
|
||||||
|
|
||||||
|
val hash: String
|
||||||
|
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0
|
||||||
|
|
||||||
|
override fun toString() = name
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
@Entity(tableName = "ReportingUnits")
|
||||||
|
data class ReportingUnit(
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
val studentId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "real_id")
|
||||||
|
val realId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "short")
|
||||||
|
val shortName: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "sender_id")
|
||||||
|
val senderId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "sender_name")
|
||||||
|
val senderName: String,
|
||||||
|
|
||||||
|
val roles: List<Int>
|
||||||
|
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0
|
||||||
|
}
|
@ -24,7 +24,13 @@ data class Semester(
|
|||||||
val semesterName: Int,
|
val semesterName: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "is_current")
|
@ColumnInfo(name = "is_current")
|
||||||
val isCurrent: Boolean
|
val isCurrent: Boolean,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "class_id")
|
||||||
|
val classId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "unit_id")
|
||||||
|
val unitId: Int
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package io.github.wulkanowy.data.db.migrations
|
||||||
|
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
|
||||||
|
class Migration6 : Migration(5, 6) {
|
||||||
|
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("CREATE TABLE ReportingUnits (" +
|
||||||
|
"id INTEGER NOT NULL PRIMARY KEY," +
|
||||||
|
"student_id INTEGER NOT NULL," +
|
||||||
|
"real_id INTEGER NOT NULL," +
|
||||||
|
"short TEXT NOT NULL," +
|
||||||
|
"sender_id INTEGER NOT NULL," +
|
||||||
|
"sender_name TEXT NOT NULL," +
|
||||||
|
"roles TEXT NOT NULL)")
|
||||||
|
|
||||||
|
database.execSQL("CREATE TABLE Recipients (" +
|
||||||
|
"id INTEGER NOT NULL PRIMARY KEY," +
|
||||||
|
"student_id INTEGER NOT NULL," +
|
||||||
|
"real_id TEXT NOT NULL," +
|
||||||
|
"name TEXT NOT NULL," +
|
||||||
|
"real_name TEXT NOT NULL," +
|
||||||
|
"login_id INTEGER NOT NULL," +
|
||||||
|
"unit_id INTEGER NOT NULL," +
|
||||||
|
"role INTEGER NOT NULL," +
|
||||||
|
"hash TEXT NOT NULL)")
|
||||||
|
|
||||||
|
database.execSQL("DELETE FROM Semesters WHERE 1")
|
||||||
|
database.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
|
||||||
|
database.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL")
|
||||||
|
}
|
||||||
|
}
|
@ -2,13 +2,16 @@ package io.github.wulkanowy.data.repositories.message
|
|||||||
|
|
||||||
import io.github.wulkanowy.api.Api
|
import io.github.wulkanowy.api.Api
|
||||||
import io.github.wulkanowy.api.messages.Folder
|
import io.github.wulkanowy.api.messages.Folder
|
||||||
|
import io.github.wulkanowy.api.messages.SentMessage
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import io.github.wulkanowy.utils.toLocalDateTime
|
import io.github.wulkanowy.utils.toLocalDateTime
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import org.threeten.bp.LocalDateTime.now
|
import org.threeten.bp.LocalDateTime.now
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
import io.github.wulkanowy.api.messages.Message as ApiMessage
|
import io.github.wulkanowy.api.messages.Message as ApiMessage
|
||||||
|
import io.github.wulkanowy.api.messages.Recipient as ApiRecipient
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class MessageRemote @Inject constructor(private val api: Api) {
|
class MessageRemote @Inject constructor(private val api: Api) {
|
||||||
@ -39,4 +42,21 @@ class MessageRemote @Inject constructor(private val api: Api) {
|
|||||||
fun getMessagesContent(message: Message, markAsRead: Boolean = false): Single<String> {
|
fun getMessagesContent(message: Message, markAsRead: Boolean = false): Single<String> {
|
||||||
return api.getMessageContent(message.messageId, message.folderId, markAsRead, message.realId)
|
return api.getMessageContent(message.messageId, message.folderId, markAsRead, message.realId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Single<SentMessage> {
|
||||||
|
return api.sendMessage(
|
||||||
|
subject = subject,
|
||||||
|
content = content,
|
||||||
|
recipients = recipients.map {
|
||||||
|
ApiRecipient(
|
||||||
|
id = it.realId,
|
||||||
|
realName = it.realName,
|
||||||
|
loginId = it.loginId,
|
||||||
|
reportingUnitId = it.unitId,
|
||||||
|
role = it.role,
|
||||||
|
hash = it.hash
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ package io.github.wulkanowy.data.repositories.message
|
|||||||
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import io.github.wulkanowy.api.messages.SentMessage
|
||||||
import io.github.wulkanowy.data.ApiHelper
|
import io.github.wulkanowy.data.ApiHelper
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
@ -82,4 +84,8 @@ class MessageRepository @Inject constructor(
|
|||||||
fun updateMessages(messages: List<Message>): Completable {
|
fun updateMessages(messages: List<Message>): Completable {
|
||||||
return Completable.fromCallable { local.updateMessages(messages) }
|
return Completable.fromCallable { local.updateMessages(messages) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Single<SentMessage> {
|
||||||
|
return remote.sendMessage(subject, content, recipients)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.recipient
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.RecipientDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@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() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveRecipients(recipients: List<Recipient>) {
|
||||||
|
return recipientDb.insertAll(recipients)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteRecipients(recipients: List<Recipient>) {
|
||||||
|
recipientDb.deleteAll(recipients)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.recipient
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.reactivex.Single
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class RecipientRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
|
fun getRecipients(role: Int, unit: ReportingUnit): Single<List<Recipient>> {
|
||||||
|
return api.getRecipients(role, unit.realId)
|
||||||
|
.map { recipients ->
|
||||||
|
recipients.map {
|
||||||
|
Recipient(
|
||||||
|
studentId = api.studentId,
|
||||||
|
name = it.name,
|
||||||
|
realName = it.realName,
|
||||||
|
realId = it.id,
|
||||||
|
hash = it.hash,
|
||||||
|
loginId = it.loginId,
|
||||||
|
role = it.role,
|
||||||
|
unitId = it.reportingUnitId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.recipient
|
||||||
|
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import io.github.wulkanowy.data.ApiHelper
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.reactivex.Single
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class RecipientRepository @Inject constructor(
|
||||||
|
private val settings: InternetObservingSettings,
|
||||||
|
private val local: RecipientLocal,
|
||||||
|
private val remote: RecipientRemote,
|
||||||
|
private val apiHelper: ApiHelper
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getRecipients(student: Student, role: Int, unit: ReportingUnit, forceRefresh: Boolean = false): Single<List<Recipient>> {
|
||||||
|
return Single.just(apiHelper.initApi(student))
|
||||||
|
.flatMap { _ ->
|
||||||
|
local.getRecipients(student, role, unit).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||||
|
.flatMap {
|
||||||
|
if (it) remote.getRecipients(role, unit)
|
||||||
|
else Single.error(UnknownHostException())
|
||||||
|
}.flatMap { new ->
|
||||||
|
local.getRecipients(student, role, unit).toSingle(emptyList())
|
||||||
|
.doOnSuccess { old ->
|
||||||
|
local.deleteRecipients(old - new)
|
||||||
|
local.saveRecipients(new - old)
|
||||||
|
}
|
||||||
|
}.flatMap {
|
||||||
|
local.getRecipients(student, role, unit).toSingle(emptyList())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.reportingunit
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: ReportingUnitDao) {
|
||||||
|
|
||||||
|
fun getReportingUnits(student: Student): Maybe<List<ReportingUnit>> {
|
||||||
|
return reportingUnitDb.load(student.studentId).filter { !it.isEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getReportingUnit(student: Student, unitId: Int): Maybe<ReportingUnit> {
|
||||||
|
return reportingUnitDb.loadOne(student.studentId, unitId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveReportingUnits(reportingUnits: List<ReportingUnit>) {
|
||||||
|
return reportingUnitDb.insertAll(reportingUnits)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteReportingUnits(reportingUnits: List<ReportingUnit>) {
|
||||||
|
reportingUnitDb.deleteAll(reportingUnits)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.reportingunit
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.reactivex.Single
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class ReportingUnitRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
|
fun getReportingUnits(): Single<List<ReportingUnit>> {
|
||||||
|
return api.getReportingUnits().map {
|
||||||
|
it.map { unit ->
|
||||||
|
ReportingUnit(
|
||||||
|
studentId = api.studentId,
|
||||||
|
realId = unit.id,
|
||||||
|
roles = unit.roles,
|
||||||
|
senderId = unit.senderId,
|
||||||
|
senderName = unit.senderName,
|
||||||
|
shortName = unit.short
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.reportingunit
|
||||||
|
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import io.github.wulkanowy.data.ApiHelper
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import io.reactivex.Single
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class ReportingUnitRepository @Inject constructor(
|
||||||
|
private val settings: InternetObservingSettings,
|
||||||
|
private val local: ReportingUnitLocal,
|
||||||
|
private val remote: ReportingUnitRemote,
|
||||||
|
private val apiHelper: ApiHelper
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getReportingUnits(student: Student, forceRefresh: Boolean = false): Single<List<ReportingUnit>> {
|
||||||
|
return Single.just(apiHelper.initApi(student))
|
||||||
|
.flatMap { _ ->
|
||||||
|
local.getReportingUnits(student).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||||
|
.flatMap {
|
||||||
|
if (it) remote.getReportingUnits()
|
||||||
|
else Single.error(UnknownHostException())
|
||||||
|
}.flatMap { new ->
|
||||||
|
local.getReportingUnits(student).toSingle(emptyList())
|
||||||
|
.doOnSuccess { old ->
|
||||||
|
local.deleteReportingUnits(old - new)
|
||||||
|
local.saveReportingUnits(new - old)
|
||||||
|
}
|
||||||
|
}.flatMap { local.getReportingUnits(student).toSingle(emptyList()) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getReportingUnit(student: Student, unitId: Int): Maybe<ReportingUnit> {
|
||||||
|
return Maybe.just(apiHelper.initApi(student))
|
||||||
|
.flatMap { _ ->
|
||||||
|
local.getReportingUnit(student, unitId)
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||||
|
.flatMap {
|
||||||
|
if (it) getReportingUnits(student, true)
|
||||||
|
else Single.error(UnknownHostException())
|
||||||
|
}.flatMapMaybe {
|
||||||
|
local.getReportingUnit(student, unitId)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,9 @@ class SemesterRemote @Inject constructor(private val api: Api) {
|
|||||||
diaryName = semester.diaryName,
|
diaryName = semester.diaryName,
|
||||||
semesterId = semester.semesterId,
|
semesterId = semester.semesterId,
|
||||||
semesterName = semester.semesterNumber,
|
semesterName = semester.semesterNumber,
|
||||||
isCurrent = semester.current
|
isCurrent = semester.current,
|
||||||
|
classId = semester.classId,
|
||||||
|
unitId = semester.unitId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ import io.github.wulkanowy.data.repositories.message.MessageRepository
|
|||||||
import io.github.wulkanowy.data.repositories.message.MessageRepository.MessageFolder.RECEIVED
|
import io.github.wulkanowy.data.repositories.message.MessageRepository.MessageFolder.RECEIVED
|
||||||
import io.github.wulkanowy.data.repositories.note.NoteRepository
|
import io.github.wulkanowy.data.repositories.note.NoteRepository
|
||||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.recipient.RecipientRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.reportingunit.ReportingUnitRepository
|
||||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.data.repositories.timetable.TimetableRepository
|
import io.github.wulkanowy.data.repositories.timetable.TimetableRepository
|
||||||
@ -26,6 +28,7 @@ import io.github.wulkanowy.utils.isHolidays
|
|||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
|
import io.reactivex.Single
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -69,6 +72,12 @@ class SyncWorker : SimpleJobService() {
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var completedLessons: CompletedLessonsRepository
|
lateinit var completedLessons: CompletedLessonsRepository
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var reportingUnitRepository: ReportingUnitRepository
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var recipientRepository: RecipientRepository
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var prefRepository: PreferencesRepository
|
lateinit var prefRepository: PreferencesRepository
|
||||||
|
|
||||||
@ -98,21 +107,24 @@ class SyncWorker : SimpleJobService() {
|
|||||||
disposable.add(student.isStudentSaved()
|
disposable.add(student.isStudentSaved()
|
||||||
.flatMapMaybe { if (it) student.getCurrentStudent().toMaybe() else Maybe.empty() }
|
.flatMapMaybe { if (it) student.getCurrentStudent().toMaybe() else Maybe.empty() }
|
||||||
.flatMap { semester.getCurrentSemester(it, true).map { semester -> semester to it }.toMaybe() }
|
.flatMap { semester.getCurrentSemester(it, true).map { semester -> semester to it }.toMaybe() }
|
||||||
.flatMapCompletable {
|
.flatMapCompletable { c ->
|
||||||
Completable.merge(
|
Completable.merge(
|
||||||
listOf(
|
listOf(
|
||||||
gradesDetails.getGrades(it.second, it.first, true, notify).ignoreElement(),
|
gradesDetails.getGrades(c.second, c.first, true, notify).ignoreElement(),
|
||||||
gradesSummary.getGradesSummary(it.first, true).ignoreElement(),
|
gradesSummary.getGradesSummary(c.first, true).ignoreElement(),
|
||||||
attendance.getAttendance(it.first, start, end, true).ignoreElement(),
|
attendance.getAttendance(c.first, start, end, true).ignoreElement(),
|
||||||
exam.getExams(it.first, start, end, true).ignoreElement(),
|
exam.getExams(c.first, start, end, true).ignoreElement(),
|
||||||
timetable.getTimetable(it.first, start, end, true).ignoreElement(),
|
timetable.getTimetable(c.first, start, end, true).ignoreElement(),
|
||||||
message.getMessages(it.second, RECEIVED, true, notify).ignoreElement(),
|
message.getMessages(c.second, RECEIVED, true, notify).ignoreElement(),
|
||||||
note.getNotes(it.second, it.first, true, notify).ignoreElement(),
|
note.getNotes(c.second, c.first, true, notify).ignoreElement(),
|
||||||
homework.getHomework(it.first, LocalDate.now(), true).ignoreElement(),
|
homework.getHomework(c.first, LocalDate.now(), true).ignoreElement(),
|
||||||
homework.getHomework(it.first, LocalDate.now().plusDays(1), true).ignoreElement(),
|
homework.getHomework(c.first, LocalDate.now().plusDays(1), true).ignoreElement(),
|
||||||
luckyNumber.getLuckyNumber(it.first, true, notify).ignoreElement(),
|
luckyNumber.getLuckyNumber(c.first, true, notify).ignoreElement(),
|
||||||
completedLessons.getCompletedLessons(it.first, start, end, true).ignoreElement()
|
completedLessons.getCompletedLessons(c.first, start, end, true).ignoreElement()
|
||||||
)
|
) + reportingUnitRepository.getReportingUnits(c.second, true)
|
||||||
|
.flatMapPublisher { reportingUnits ->
|
||||||
|
Single.merge(reportingUnits.map { recipientRepository.getRecipients(c.second, 2, it, true) })
|
||||||
|
}.ignoreElements()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.subscribe({}, { error = it }))
|
.subscribe({}, { error = it }))
|
||||||
|
@ -20,6 +20,7 @@ import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
|
|||||||
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
||||||
import io.github.wulkanowy.ui.modules.message.MessageModule
|
import io.github.wulkanowy.ui.modules.message.MessageModule
|
||||||
import io.github.wulkanowy.ui.modules.message.preview.MessagePreviewFragment
|
import io.github.wulkanowy.ui.modules.message.preview.MessagePreviewFragment
|
||||||
|
import io.github.wulkanowy.ui.modules.message.send.SendMessageFragment
|
||||||
import io.github.wulkanowy.ui.modules.more.MoreFragment
|
import io.github.wulkanowy.ui.modules.more.MoreFragment
|
||||||
import io.github.wulkanowy.ui.modules.note.NoteFragment
|
import io.github.wulkanowy.ui.modules.note.NoteFragment
|
||||||
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
|
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
|
||||||
@ -94,9 +95,13 @@ abstract class MainModule {
|
|||||||
|
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract fun bindAccountDialog(): AccountDialog
|
abstract fun bindCompletedLessonsFragment(): CompletedLessonsFragment
|
||||||
|
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract fun bindCompletedLessonsFragment(): CompletedLessonsFragment
|
abstract fun bindSendMessageFragment(): SendMessageFragment
|
||||||
|
|
||||||
|
@PerFragment
|
||||||
|
@ContributesAndroidInjector
|
||||||
|
abstract fun bindAccountDialog(): AccountDialog
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,9 @@ import io.github.wulkanowy.data.repositories.message.MessageRepository.MessageFo
|
|||||||
import io.github.wulkanowy.data.repositories.message.MessageRepository.MessageFolder.TRASHED
|
import io.github.wulkanowy.data.repositories.message.MessageRepository.MessageFolder.TRASHED
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
||||||
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
|
import io.github.wulkanowy.ui.modules.message.send.SendMessageFragment
|
||||||
import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment
|
import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment
|
||||||
import io.github.wulkanowy.utils.setOnSelectPageListener
|
import io.github.wulkanowy.utils.setOnSelectPageListener
|
||||||
import kotlinx.android.synthetic.main.fragment_message.*
|
import kotlinx.android.synthetic.main.fragment_message.*
|
||||||
@ -61,6 +63,8 @@ class MessageFragment : BaseFragment(), MessageView, MainView.TitledView {
|
|||||||
setOnSelectPageListener { presenter.onPageSelected(it) }
|
setOnSelectPageListener { presenter.onPageSelected(it) }
|
||||||
}
|
}
|
||||||
messageTabLayout.setupWithViewPager(messageViewPager)
|
messageTabLayout.setupWithViewPager(messageViewPager)
|
||||||
|
|
||||||
|
openSendMessageButton.setOnClickListener { presenter.onSendMessageButtonClicked() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showContent(show: Boolean) {
|
override fun showContent(show: Boolean) {
|
||||||
@ -80,6 +84,10 @@ class MessageFragment : BaseFragment(), MessageView, MainView.TitledView {
|
|||||||
(pagerAdapter.getFragmentInstance(index) as? MessageView.MessageChildView)?.onParentLoadData(forceRefresh)
|
(pagerAdapter.getFragmentInstance(index) as? MessageView.MessageChildView)?.onParentLoadData(forceRefresh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openSendMessage() {
|
||||||
|
(activity as? MainActivity)?.pushView(SendMessageFragment.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
presenter.onDetachView()
|
presenter.onDetachView()
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
@ -42,4 +42,8 @@ class MessagePresenter @Inject constructor(
|
|||||||
showProgress(false)
|
showProgress(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onSendMessageButtonClicked() {
|
||||||
|
view?.openSendMessage()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ interface MessageView : BaseView {
|
|||||||
|
|
||||||
fun notifyChildLoadData(index: Int, forceRefresh: Boolean)
|
fun notifyChildLoadData(index: Int, forceRefresh: Boolean)
|
||||||
|
|
||||||
|
fun openSendMessage()
|
||||||
|
|
||||||
interface MessageChildView {
|
interface MessageChildView {
|
||||||
|
|
||||||
fun onParentLoadData(forceRefresh: Boolean)
|
fun onParentLoadData(forceRefresh: Boolean)
|
||||||
|
@ -0,0 +1,154 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.message.send
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.hootsuite.nachos.ChipConfiguration
|
||||||
|
import com.hootsuite.nachos.chip.ChipSpan
|
||||||
|
import com.hootsuite.nachos.chip.ChipSpanChipCreator
|
||||||
|
import com.hootsuite.nachos.tokenizer.SpanChipTokenizer
|
||||||
|
import io.github.wulkanowy.R
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||||
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
|
import io.github.wulkanowy.utils.hideSoftInput
|
||||||
|
import io.github.wulkanowy.utils.setOnTextChangedListener
|
||||||
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
|
import kotlinx.android.synthetic.main.fragment_send_message.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SendMessageFragment : BaseSessionFragment(), SendMessageView, MainView.TitledView {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var presenter: SendMessagePresenter
|
||||||
|
|
||||||
|
private var recipients: List<Recipient> = emptyList()
|
||||||
|
|
||||||
|
private lateinit var recipientsAdapter: ArrayAdapter<Recipient>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance() = SendMessageFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val titleStringId: Int
|
||||||
|
get() = R.string.send_message_title
|
||||||
|
|
||||||
|
override val formRecipientsData: List<Recipient>
|
||||||
|
get() = sendMessageRecipientInput.allChips.map { it.data as Recipient }
|
||||||
|
|
||||||
|
override val formSubjectValue: String
|
||||||
|
get() = sendMessageSubjectInput.text.toString()
|
||||||
|
|
||||||
|
override val formContentValue: String
|
||||||
|
get() = sendMessageContentInput.text.toString()
|
||||||
|
|
||||||
|
override val messageRequiredRecipients: String
|
||||||
|
get() = getString(R.string.send_message_required_recipients)
|
||||||
|
|
||||||
|
override val messageContentMinLength: String
|
||||||
|
get() = getString(R.string.send_message_content_min_length)
|
||||||
|
|
||||||
|
override val messageSuccess: String
|
||||||
|
get() = getString(R.string.send_message_successful)
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.fragment_send_message, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
presenter.onAttachView(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initView() {
|
||||||
|
context?.let {
|
||||||
|
sendMessageRecipientInput.chipTokenizer = SpanChipTokenizer<ChipSpan>(it, object : ChipSpanChipCreator() {
|
||||||
|
override fun createChip(context: Context, text: CharSequence, data: Any?): ChipSpan {
|
||||||
|
return ChipSpan(context, text, ContextCompat.getDrawable(context, R.drawable.ic_all_account_24dp), data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun configureChip(chip: ChipSpan, chipConfiguration: ChipConfiguration) {
|
||||||
|
super.configureChip(chip, chipConfiguration)
|
||||||
|
chip.setShowIconOnLeft(true)
|
||||||
|
}
|
||||||
|
}, ChipSpan::class.java)
|
||||||
|
recipientsAdapter = ArrayAdapter(it, android.R.layout.simple_dropdown_item_1line)
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessageRecipientInput.setAdapter(recipientsAdapter)
|
||||||
|
sendMessageRecipientInput.setOnTextChangedListener { presenter.onTypingRecipients() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
|
||||||
|
inflater?.inflate(R.menu.action_menu_send_message, menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||||
|
return if (item?.itemId == R.id.sendMessageMenuSend) presenter.onSend()
|
||||||
|
else false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setReportingUnit(unit: ReportingUnit) {
|
||||||
|
sendMessageFromTextView.setText(unit.senderName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setRecipients(recipients: List<Recipient>) {
|
||||||
|
this.recipients = recipients
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refreshRecipientsAdapter() {
|
||||||
|
recipientsAdapter.run {
|
||||||
|
clear()
|
||||||
|
addAll(recipients - sendMessageRecipientInput.allChips.map { it.data as Recipient })
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showProgress(show: Boolean) {
|
||||||
|
sendMessageProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showContent(show: Boolean) {
|
||||||
|
sendMessageContent.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showEmpty(show: Boolean) {
|
||||||
|
sendMessageEmpty.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popView() {
|
||||||
|
(activity as? MainActivity)?.popView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hideSoftInput() {
|
||||||
|
activity?.hideSoftInput()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showBottomNav(show: Boolean) {
|
||||||
|
(activity as? MainActivity)?.mainBottomNav?.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showMessage(text: String) {
|
||||||
|
Toast.makeText(context, text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
presenter.onDetachView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,137 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.message.send
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.recipient.RecipientRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.reportingunit.ReportingUnitRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
|
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||||
|
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||||
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SendMessagePresenter @Inject constructor(
|
||||||
|
private val errorHandler: SessionErrorHandler,
|
||||||
|
private val schedulers: SchedulersProvider,
|
||||||
|
private val studentRepository: StudentRepository,
|
||||||
|
private val semesterRepository: SemesterRepository,
|
||||||
|
private val messageRepository: MessageRepository,
|
||||||
|
private val reportingUnitRepository: ReportingUnitRepository,
|
||||||
|
private val recipientRepository: RecipientRepository,
|
||||||
|
private val analytics: FirebaseAnalyticsHelper
|
||||||
|
) : BaseSessionPresenter<SendMessageView>(errorHandler) {
|
||||||
|
|
||||||
|
private lateinit var reportingUnit: ReportingUnit
|
||||||
|
|
||||||
|
override fun onAttachView(view: SendMessageView) {
|
||||||
|
Timber.i("Send message view is attached")
|
||||||
|
super.onAttachView(view)
|
||||||
|
view.run {
|
||||||
|
initView()
|
||||||
|
showBottomNav(false)
|
||||||
|
}
|
||||||
|
loadRecipients()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadRecipients() {
|
||||||
|
Timber.i("Loading recipients started")
|
||||||
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
|
.flatMapMaybe { student ->
|
||||||
|
semesterRepository.getCurrentSemester(student)
|
||||||
|
.flatMapMaybe { reportingUnitRepository.getReportingUnit(student, it.unitId) }
|
||||||
|
.doOnSuccess { reportingUnit = it }
|
||||||
|
.flatMap { recipientRepository.getRecipients(student, 2, it).toMaybe() }
|
||||||
|
}
|
||||||
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
|
.observeOn(schedulers.mainThread)
|
||||||
|
.doOnSubscribe {
|
||||||
|
view?.run {
|
||||||
|
showProgress(true)
|
||||||
|
showContent(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.doFinally {
|
||||||
|
view?.run {
|
||||||
|
showProgress(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.subscribe({
|
||||||
|
view?.apply {
|
||||||
|
setReportingUnit(reportingUnit)
|
||||||
|
setRecipients(it)
|
||||||
|
refreshRecipientsAdapter()
|
||||||
|
showContent(true)
|
||||||
|
}
|
||||||
|
Timber.i("Loading recipients result: Success, fetched %s recipients", it.size.toString())
|
||||||
|
}, {
|
||||||
|
Timber.i("Loading recipients result: An exception occurred")
|
||||||
|
view?.showContent(true)
|
||||||
|
errorHandler.dispatch(it)
|
||||||
|
}, {
|
||||||
|
Timber.i("Loading recipients result: Can't find the reporting unit")
|
||||||
|
view?.showEmpty(true)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendMessage(subject: String, content: String, recipients: List<Recipient>) {
|
||||||
|
Timber.i("Sending message started")
|
||||||
|
disposable.add(messageRepository.sendMessage(subject, content, recipients)
|
||||||
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
|
.observeOn(schedulers.mainThread)
|
||||||
|
.doOnSubscribe {
|
||||||
|
view?.run {
|
||||||
|
hideSoftInput()
|
||||||
|
showContent(false)
|
||||||
|
showProgress(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.doFinally {
|
||||||
|
view?.showProgress(false)
|
||||||
|
}
|
||||||
|
.subscribe({
|
||||||
|
Timber.i("Sending message result: Success")
|
||||||
|
analytics.logEvent("send_message", "recipients" to recipients.size)
|
||||||
|
view?.run {
|
||||||
|
showMessage(messageSuccess)
|
||||||
|
popView()
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
Timber.i("Sending message result: An exception occurred")
|
||||||
|
view?.showContent(true)
|
||||||
|
errorHandler.dispatch(it)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onTypingRecipients() {
|
||||||
|
view?.refreshRecipientsAdapter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSend(): Boolean {
|
||||||
|
view?.run {
|
||||||
|
when {
|
||||||
|
formRecipientsData.isEmpty() -> showMessage(messageRequiredRecipients)
|
||||||
|
formContentValue.length < 3 -> showMessage(messageContentMinLength)
|
||||||
|
else -> {
|
||||||
|
sendMessage(
|
||||||
|
subject = formSubjectValue,
|
||||||
|
content = formContentValue,
|
||||||
|
recipients = formRecipientsData
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachView() {
|
||||||
|
view?.showBottomNav(true)
|
||||||
|
super.onDetachView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.message.send
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||||
|
|
||||||
|
interface SendMessageView : BaseSessionView {
|
||||||
|
|
||||||
|
val formRecipientsData: List<Recipient>
|
||||||
|
|
||||||
|
val formSubjectValue: String
|
||||||
|
|
||||||
|
val formContentValue: String
|
||||||
|
|
||||||
|
val messageRequiredRecipients: String
|
||||||
|
|
||||||
|
val messageContentMinLength: String
|
||||||
|
|
||||||
|
val messageSuccess: String
|
||||||
|
|
||||||
|
fun initView()
|
||||||
|
|
||||||
|
fun setReportingUnit(unit: ReportingUnit)
|
||||||
|
|
||||||
|
fun setRecipients(recipients: List<Recipient>)
|
||||||
|
|
||||||
|
fun refreshRecipientsAdapter()
|
||||||
|
|
||||||
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
fun popView()
|
||||||
|
|
||||||
|
fun hideSoftInput()
|
||||||
|
|
||||||
|
fun showBottomNav(show: Boolean)
|
||||||
|
}
|
10
app/src/main/res/drawable/ic_menu_send_message_24dp.xml
Normal file
10
app/src/main/res/drawable/ic_menu_send_message_24dp.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.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z" />
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_send_message_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_send_message_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z" />
|
||||||
|
</vector>
|
@ -24,10 +24,22 @@
|
|||||||
android:layout_marginTop="48dp"
|
android:layout_marginTop="48dp"
|
||||||
android:visibility="invisible" />
|
android:visibility="invisible" />
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/openSendMessageButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:tint="#FFFFFF"
|
||||||
|
app:srcCompat="@drawable/ic_send_message_24dp" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/messageProgress"
|
android:id="@+id/messageProgress"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:indeterminate="true" />
|
android:indeterminate="true" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
145
app/src/main/res/layout/fragment_send_message.xml
Normal file
145
app/src/main/res/layout/fragment_send_message.xml
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/sendMessageContent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="14dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:text="@string/send_message_from"
|
||||||
|
android:textColor="@android:color/darker_gray"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText
|
||||||
|
android:id="@+id/sendMessageFromTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="38dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:enabled="false"
|
||||||
|
android:textColor="?android:attr/textColorPrimaryNoDisable"
|
||||||
|
tools:text="Jan Kowalski" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/dividerColor" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="14dp"
|
||||||
|
android:paddingLeft="14dp"
|
||||||
|
android:paddingTop="14dp"
|
||||||
|
android:paddingEnd="0dp"
|
||||||
|
android:paddingRight="0dp"
|
||||||
|
android:paddingBottom="14dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:text="@string/send_message_to"
|
||||||
|
android:textColor="@android:color/darker_gray"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<com.hootsuite.nachos.NachoTextView
|
||||||
|
android:id="@+id/sendMessageRecipientInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:inputType="text"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="?attr/chipTextColor"
|
||||||
|
app:chipBackground="?attr/chipBackgroundColor" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/dividerColor" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText
|
||||||
|
android:id="@+id/sendMessageSubjectInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="66dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:hint="@string/send_message_subject"
|
||||||
|
android:inputType="text"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:padding="14dp" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/dividerColor" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText
|
||||||
|
android:id="@+id/sendMessageContentInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:gravity="top|start"
|
||||||
|
android:hint="@string/send_message_content"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:paddingStart="14dp"
|
||||||
|
android:paddingLeft="14dp"
|
||||||
|
android:paddingTop="18dp"
|
||||||
|
android:paddingEnd="14dp"
|
||||||
|
android:paddingRight="14dp"
|
||||||
|
android:singleLine="false" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/sendMessageEmpty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:minWidth="100dp"
|
||||||
|
android:minHeight="100dp"
|
||||||
|
app:srcCompat="@drawable/ic_more_messages_24dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:text="@string/error_unknown"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/sendMessageProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
</RelativeLayout>
|
10
app/src/main/res/menu/action_menu_send_message.xml
Normal file
10
app/src/main/res/menu/action_menu_send_message.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/sendMessageMenuSend"
|
||||||
|
android:icon="@drawable/ic_menu_send_message_24dp"
|
||||||
|
android:orderInCategory="1"
|
||||||
|
android:title="@string/send_message_title"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
</menu>
|
@ -7,6 +7,9 @@
|
|||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
<item name="bottomNavBackground">@color/bottom_nav_background</item>
|
<item name="bottomNavBackground">@color/bottom_nav_background</item>
|
||||||
<item name="android:navigationBarColor" tools:targetApi="21">@color/bottom_nav_background</item>
|
<item name="android:navigationBarColor" tools:targetApi="21">@color/bottom_nav_background</item>
|
||||||
|
<item name="chipBackgroundColor">@color/chip_material_background_inverse</item>
|
||||||
|
<item name="chipTextColor">@color/chip_default_text_color_inverse</item>
|
||||||
|
<item name="dividerColor">@color/divider_inverse</item>
|
||||||
|
|
||||||
<!--AboutLibraries specific values-->
|
<!--AboutLibraries specific values-->
|
||||||
<item name="about_libraries_window_background">@color/about_libraries_window_background_dark</item>
|
<item name="about_libraries_window_background">@color/about_libraries_window_background_dark</item>
|
||||||
|
@ -168,6 +168,16 @@
|
|||||||
<item quantity="many">Dostałeś %1$d wiadomości</item>
|
<item quantity="many">Dostałeś %1$d wiadomości</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
|
<!--Send message-->
|
||||||
|
<string name="send_message_title">Wyślij</string>
|
||||||
|
<string name="send_message_from">Od:</string>
|
||||||
|
<string name="send_message_to">Do:</string>
|
||||||
|
<string name="send_message_subject">Temat</string>
|
||||||
|
<string name="send_message_content">Treść</string>
|
||||||
|
<string name="send_message_successful">Wiadomość wysłana pomyślnie</string>
|
||||||
|
<string name="send_message_required_recipients">Musisz wybrać co najmniej 1 adresata</string>
|
||||||
|
<string name="send_message_content_min_length">Treść wiadomości musi zawierać co najmniej 3 znaki</string>
|
||||||
|
|
||||||
<!--About-->
|
<!--About-->
|
||||||
<string name="about_source_code">Kod źródłowy</string>
|
<string name="about_source_code">Kod źródłowy</string>
|
||||||
<string name="about_feedback">Zgłoś błąd</string>
|
<string name="about_feedback">Zgłoś błąd</string>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<attr name="bottomNavBackground" format="reference" />
|
<attr name="bottomNavBackground" format="reference" />
|
||||||
|
<attr name="dividerColor" format="reference" />
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -16,4 +16,10 @@
|
|||||||
|
|
||||||
<color name="bottom_nav_background">#303030</color>
|
<color name="bottom_nav_background">#303030</color>
|
||||||
<color name="bottom_nav_background_inverse">#ffffff</color>
|
<color name="bottom_nav_background_inverse">#ffffff</color>
|
||||||
|
|
||||||
|
<color name="chip_material_background_inverse">#595959</color>
|
||||||
|
<color name="chip_default_text_color_inverse">#fefefe</color>
|
||||||
|
|
||||||
|
<color name="divider">#cccccc</color>
|
||||||
|
<color name="divider_inverse">#777777</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -155,6 +155,16 @@
|
|||||||
<item quantity="other">You received %1$d messages</item>
|
<item quantity="other">You received %1$d messages</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
|
<!--Send message-->
|
||||||
|
<string name="send_message_title">Send</string>
|
||||||
|
<string name="send_message_from">From:</string>
|
||||||
|
<string name="send_message_to">To:</string>
|
||||||
|
<string name="send_message_subject">Subject</string>
|
||||||
|
<string name="send_message_content">Content</string>
|
||||||
|
<string name="send_message_successful">Message sent successfully</string>
|
||||||
|
<string name="send_message_required_recipients">You need to choose at least 1 recipient</string>
|
||||||
|
<string name="send_message_content_min_length">The message content must be at least 3 characters</string>
|
||||||
|
|
||||||
<!--About-->
|
<!--About-->
|
||||||
<string name="about_source_code">Source code</string>
|
<string name="about_source_code">Source code</string>
|
||||||
<string name="about_feedback">Report a bug</string>
|
<string name="about_feedback">Report a bug</string>
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
<item name="subtitleTextColor">@android:color/primary_text_dark</item>
|
<item name="subtitleTextColor">@android:color/primary_text_dark</item>
|
||||||
<item name="android:colorBackground">@android:color/white</item>
|
<item name="android:colorBackground">@android:color/white</item>
|
||||||
<item name="bottomNavBackground">@color/bottom_nav_background_inverse</item>
|
<item name="bottomNavBackground">@color/bottom_nav_background_inverse</item>
|
||||||
|
<item name="chipBackgroundColor">@color/chip_material_background</item>
|
||||||
|
<item name="chipTextColor">@color/chip_default_text_color</item>
|
||||||
|
<item name="dividerColor">@color/divider</item>
|
||||||
|
|
||||||
<!-- AboutLibraries specific values -->
|
<!-- AboutLibraries specific values -->
|
||||||
<item name="about_libraries_window_background">@color/about_libraries_window_background</item>
|
<item name="about_libraries_window_background">@color/about_libraries_window_background</item>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user