forked from github/wulkanowy-mirror
Add replying to messages (#263)
This commit is contained in:
parent
824ed3f282
commit
ba76453e45
@ -77,7 +77,7 @@ play {
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation('com.github.wulkanowy:api:29d24ca1ff') { exclude module: "threetenbp" }
|
||||
implementation('com.github.wulkanowy:api:a8d05df1ab') { exclude module: "threetenbp" }
|
||||
|
||||
implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
implementation "androidx.appcompat:appcompat:1.0.2"
|
||||
@ -107,7 +107,7 @@ dependencies {
|
||||
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
|
||||
implementation 'com.ncapdevi:frag-nav:3.1.0'
|
||||
|
||||
implementation "com.hootsuite.android:nachos:1.1.1"
|
||||
implementation 'com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f'
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:971640b29d'
|
||||
|
||||
implementation 'com.github.pwittchen:reactivenetwork-rx2:3.0.2'
|
||||
|
@ -21,7 +21,8 @@ class GradeLocalTest {
|
||||
|
||||
@Before
|
||||
fun createDb() {
|
||||
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java).build()
|
||||
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||
.build()
|
||||
gradeLocal = GradeLocal(testDb.gradeDao)
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.api.toDate
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy
|
||||
@ -22,7 +20,6 @@ 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.of
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import kotlin.test.assertFalse
|
||||
|
@ -39,7 +39,7 @@ class GradeStatisticsLocalTest {
|
||||
))
|
||||
|
||||
val stats = gradeStatisticsLocal.getGradesStatistics(
|
||||
Semester(2, 2, "", 1, 2, true, 1 ,1), false,
|
||||
Semester(2, 2, "", 1, 2, true, 1, 1), false,
|
||||
"Matematyka"
|
||||
).blockingGet()
|
||||
assertEquals(1, stats.size)
|
||||
|
@ -39,7 +39,18 @@
|
||||
android:name=".ui.modules.main.MainActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/main_title"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/WulkanowyTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".ui.modules.message.send.SendMessageActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/send_message_title"
|
||||
android:parentActivityName=".ui.modules.main.MainActivity"
|
||||
android:theme="@style/WulkanowyTheme.NoActionBar">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".ui.modules.main.MainActivity" />
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".services.widgets.TimetableWidgetService"
|
||||
|
@ -40,6 +40,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.db.entities.Subject
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.data.db.migrations.Migration10
|
||||
import io.github.wulkanowy.data.db.migrations.Migration2
|
||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||
@ -47,6 +48,7 @@ import io.github.wulkanowy.data.db.migrations.Migration5
|
||||
import io.github.wulkanowy.data.db.migrations.Migration6
|
||||
import io.github.wulkanowy.data.db.migrations.Migration7
|
||||
import io.github.wulkanowy.data.db.migrations.Migration8
|
||||
import io.github.wulkanowy.data.db.migrations.Migration9
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -77,7 +79,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 8
|
||||
const val VERSION_SCHEMA = 10
|
||||
|
||||
fun newInstance(context: Context): AppDatabase {
|
||||
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
||||
@ -91,7 +93,9 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration5(),
|
||||
Migration6(),
|
||||
Migration7(),
|
||||
Migration8()
|
||||
Migration8(),
|
||||
Migration9(),
|
||||
Migration10()
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
@ -18,6 +18,6 @@ interface GradeSummaryDao {
|
||||
@Delete
|
||||
fun deleteAll(gradesSummary: List<GradeSummary>)
|
||||
|
||||
@Query("SELECT * FROM grades_summary WHERE student_id = :studentId AND semester_id = :semesterId")
|
||||
@Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId")
|
||||
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradeSummary>>
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ interface MessagesDao {
|
||||
@Update
|
||||
fun updateAll(messages: List<Message>)
|
||||
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC")
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
|
||||
fun loadAll(studentId: Int, folder: Int): Maybe<List<Message>>
|
||||
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND real_id = :id")
|
||||
|
@ -4,7 +4,7 @@ import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "Grades_Summary")
|
||||
@Entity(tableName = "GradesSummary")
|
||||
data class GradeSummary(
|
||||
|
||||
@ColumnInfo(name = "semester_id")
|
||||
|
@ -24,9 +24,6 @@ data class Message(
|
||||
@ColumnInfo(name = "sender_id")
|
||||
val senderId: Int,
|
||||
|
||||
@ColumnInfo(name = "recipient_id")
|
||||
val recipientId: Int,
|
||||
|
||||
@ColumnInfo(name = "recipient_name")
|
||||
val recipient: String,
|
||||
|
||||
@ -39,8 +36,10 @@ data class Message(
|
||||
|
||||
var unread: Boolean,
|
||||
|
||||
@ColumnInfo(name = "unread_by")
|
||||
val unreadBy: Int,
|
||||
|
||||
@ColumnInfo(name = "read_by")
|
||||
val readBy: Int,
|
||||
|
||||
val removed: Boolean
|
||||
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration10 : Migration(9, 10) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary")
|
||||
}
|
||||
}
|
@ -6,11 +6,13 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
class Migration2 : Migration(1, 2) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE LuckyNumbers (" +
|
||||
"id INTEGER NOT NULL PRIMARY KEY, " +
|
||||
"is_notified INTEGER NOT NULL, " +
|
||||
"student_id INTEGER NOT NULL, " +
|
||||
"date INTEGER NOT NULL, " +
|
||||
"lucky_number INTEGER NOT NULL)")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS LuckyNumbers (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
is_notified INTEGER NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
date INTEGER NOT NULL,
|
||||
lucky_number INTEGER NOT NULL)
|
||||
""")
|
||||
}
|
||||
}
|
||||
|
@ -6,18 +6,20 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
class Migration3 : Migration(2, 3) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE CompletedLesson (" +
|
||||
"id INTEGER NOT NULL PRIMARY KEY, " +
|
||||
"student_id INTEGER NOT NULL, " +
|
||||
"diary_id INTEGER NOT NULL, " +
|
||||
"date INTEGER NOT NULL, " +
|
||||
"number INTEGER NOT NULL, " +
|
||||
"subject TEXT NOT NULL, " +
|
||||
"topic TEXT NOT NULL, " +
|
||||
"teacher TEXT NOT NULL, " +
|
||||
"teacher_symbol TEXT NOT NULL, " +
|
||||
"substitution TEXT NOT NULL, " +
|
||||
"absence TEXT NOT NULL, " +
|
||||
"resources TEXT NOT NULL)")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS CompletedLesson (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
diary_id INTEGER NOT NULL,
|
||||
date INTEGER NOT NULL,
|
||||
number INTEGER NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
topic TEXT NOT NULL,
|
||||
teacher TEXT NOT NULL,
|
||||
teacher_symbol TEXT NOT NULL,
|
||||
substitution TEXT NOT NULL,
|
||||
absence TEXT NOT NULL,
|
||||
resources TEXT NOT NULL)
|
||||
""")
|
||||
}
|
||||
}
|
||||
|
@ -6,24 +6,26 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
class Migration4 : Migration(3, 4) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS `Messages`")
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `Messages` (" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
|
||||
"`is_notified` INTEGER NOT NULL," +
|
||||
"`content` TEXT," +
|
||||
"`student_id` INTEGER NOT NULL," +
|
||||
"`real_id` INTEGER NOT NULL," +
|
||||
"`message_id` INTEGER NOT NULL," +
|
||||
"`sender_name` TEXT NOT NULL," +
|
||||
"`sender_id` INTEGER NOT NULL," +
|
||||
"`recipient_id` INTEGER NOT NULL," +
|
||||
"`recipient_name` TEXT NOT NULL," +
|
||||
"`subject` TEXT NOT NULL," +
|
||||
"`date` INTEGER NOT NULL," +
|
||||
"`folder_id` INTEGER NOT NULL," +
|
||||
"`unread` INTEGER NOT NULL," +
|
||||
"`unreadBy` INTEGER NOT NULL," +
|
||||
"`readBy` INTEGER NOT NULL," +
|
||||
"`removed` INTEGER NOT NULL)")
|
||||
database.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS Messages (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
is_notified INTEGER NOT NULL,
|
||||
content TEXT,
|
||||
student_id INTEGER NOT NULL,
|
||||
real_id INTEGER NOT NULL,
|
||||
message_id INTEGER NOT NULL,
|
||||
sender_name TEXT NOT NULL,
|
||||
sender_id INTEGER NOT NULL,
|
||||
recipient_id INTEGER NOT NULL,
|
||||
recipient_name TEXT NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
date INTEGER NOT NULL,
|
||||
folder_id INTEGER NOT NULL,
|
||||
unread INTEGER NOT NULL,
|
||||
unreadBy INTEGER NOT NULL,
|
||||
readBy INTEGER NOT NULL,
|
||||
removed INTEGER NOT NULL)
|
||||
""")
|
||||
}
|
||||
}
|
||||
|
@ -8,17 +8,19 @@ import org.threeten.bp.ZoneOffset
|
||||
class Migration5 : Migration(4, 5) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN `registration_date` INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("UPDATE Students SET `registration_date` = '${now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()}'")
|
||||
database.execSQL("DROP TABLE IF EXISTS `Notes`")
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `Notes` (" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
|
||||
"`is_read` INTEGER NOT NULL," +
|
||||
"`is_notified` INTEGER NOT NULL," +
|
||||
"`student_id` INTEGER NOT NULL," +
|
||||
"`date` INTEGER NOT NULL," +
|
||||
"`teacher` TEXT NOT NULL," +
|
||||
"`category` TEXT NOT NULL," +
|
||||
"`content` TEXT NOT NULL)")
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL")
|
||||
database.execSQL("UPDATE Students SET registration_date = '${now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()}'")
|
||||
database.execSQL("DROP TABLE IF EXISTS Notes")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS Notes (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
is_read INTEGER NOT NULL,
|
||||
is_notified INTEGER NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
date INTEGER NOT NULL,
|
||||
teacher TEXT NOT NULL,
|
||||
category TEXT NOT NULL,
|
||||
content TEXT NOT NULL)
|
||||
""")
|
||||
}
|
||||
}
|
||||
|
@ -6,25 +6,29 @@ 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 IF NOT EXISTS ReportingUnits (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
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("""
|
||||
CREATE TABLE IF NOT EXISTS Recipients (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
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")
|
||||
|
@ -6,13 +6,15 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
class Migration7 : Migration(6, 7) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `GradesStatistics` (" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
|
||||
"`student_id` INTEGER NOT NULL," +
|
||||
"`semester_id` INTEGER NOT NULL," +
|
||||
"`subject` TEXT NOT NULL," +
|
||||
"`grade` INTEGER NOT NULL," +
|
||||
"`amount` INTEGER NOT NULL," +
|
||||
"`is_semester` INTEGER NOT NULL)")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS GradesStatistics (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
semester_id INTEGER NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
grade INTEGER NOT NULL,
|
||||
amount INTEGER NOT NULL,
|
||||
is_semester INTEGER NOT NULL)
|
||||
""")
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
class Migration8 : Migration(7, 8) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE `Timetable` ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL")
|
||||
database.execSQL("ALTER TABLE `Timetable` ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL")
|
||||
database.execSQL("ALTER TABLE `Timetable` ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL")
|
||||
database.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL")
|
||||
database.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL")
|
||||
database.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL")
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration9 : Migration(8, 9) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS Messages (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
real_id INTEGER NOT NULL,
|
||||
message_id INTEGER NOT NULL,
|
||||
sender_name TEXT NOT NULL,
|
||||
sender_id INTEGER NOT NULL,
|
||||
recipient_name TEXT NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
date INTEGER NOT NULL,
|
||||
folder_id INTEGER NOT NULL,
|
||||
unread INTEGER NOT NULL,
|
||||
unread_by INTEGER NOT NULL,
|
||||
read_by INTEGER NOT NULL,
|
||||
removed INTEGER NOT NULL,
|
||||
is_notified INTEGER NOT NULL,
|
||||
content TEXT)
|
||||
""")
|
||||
}
|
||||
}
|
@ -27,7 +27,8 @@ class GradeRepository @Inject constructor(
|
||||
}.flatMap { newGrades ->
|
||||
local.getGrades(semester).toSingle(emptyList())
|
||||
.doOnSuccess { oldGrades ->
|
||||
val notifyBreakDate = oldGrades.maxBy { it.date }?.date ?: student.registrationDate.toLocalDate()
|
||||
val notifyBreakDate = oldGrades.maxBy { it.date }?.date
|
||||
?: student.registrationDate.toLocalDate()
|
||||
local.deleteGrades(oldGrades - newGrades)
|
||||
local.saveGrades((newGrades - oldGrades)
|
||||
.onEach {
|
||||
|
@ -20,6 +20,7 @@ class HomeworkLocal @Inject constructor(private val homeworkDb: HomeworkDao) {
|
||||
}
|
||||
|
||||
fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Homework>> {
|
||||
return homeworkDb.loadAll(semester.semesterId, semester.studentId, startDate, endDate).filter { it.isNotEmpty() }
|
||||
return homeworkDb.loadAll(semester.semesterId, semester.studentId, startDate, endDate)
|
||||
.filter { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ class MessageRemote @Inject constructor(private val api: Api) {
|
||||
sender = it.sender.orEmpty(),
|
||||
senderId = it.senderId ?: 0,
|
||||
recipient = it.recipient.orEmpty(),
|
||||
recipientId = 0,
|
||||
subject = it.subject.trim(),
|
||||
date = it.date?.toLocalDateTime() ?: now(),
|
||||
folderId = it.folderId,
|
||||
|
@ -83,6 +83,10 @@ class MessageRepository @Inject constructor(
|
||||
}
|
||||
|
||||
fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Single<SentMessage> {
|
||||
return remote.sendMessage(subject, content, recipients)
|
||||
return ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.sendMessage(subject, content, recipients)
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,6 @@ class PreferencesRepository @Inject constructor(
|
||||
val currentTheme: Int
|
||||
get() = sharedPref.getString(currentThemeKey, "1")?.toIntOrNull() ?: 1
|
||||
|
||||
val gradePlusModifier: Double
|
||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_plus), "0.0")?.toDoubleOrNull() ?: 0.0
|
||||
|
||||
val gradeMinusModifier: Double
|
||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_minus), "0.0")?.toDoubleOrNull() ?: 0.0
|
||||
|
||||
val gradeColorTheme: String
|
||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_color_scheme), "vulcan") ?: "vulcan"
|
||||
|
||||
@ -51,4 +45,14 @@ class PreferencesRepository @Inject constructor(
|
||||
val isDebugNotificationEnableKey: String = context.getString(R.string.pref_key_notification_debug)
|
||||
val isDebugNotificationEnable: Boolean
|
||||
get() = sharedPref.getBoolean(isDebugNotificationEnableKey, false)
|
||||
|
||||
val gradePlusModifier: Double
|
||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_plus), "0.0")?.toDouble() ?: 0.0
|
||||
|
||||
val gradeMinusModifier: Double
|
||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_minus), "0.0")?.toDouble()
|
||||
?: 0.0
|
||||
|
||||
val fillMessageContent: Boolean
|
||||
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_fill_message_content), true)
|
||||
}
|
||||
|
@ -1,30 +1,41 @@
|
||||
package io.github.wulkanowy.data.repositories.recipient
|
||||
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
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
|
||||
import io.github.wulkanowy.api.messages.Recipient as ApiRecipient
|
||||
|
||||
@Singleton
|
||||
class RecipientRemote @Inject constructor(private val api: Api) {
|
||||
|
||||
fun getRecipients(role: Int, unit: ReportingUnit): Single<List<Recipient>> {
|
||||
return api.getRecipients(role, unit.realId)
|
||||
return api.getRecipients(unit.realId, role)
|
||||
.map { recipients ->
|
||||
recipients.map {
|
||||
Recipient(
|
||||
recipients.map { it.toRecipient() }
|
||||
}
|
||||
}
|
||||
|
||||
fun getMessageRecipients(message: Message): Single<List<Recipient>> {
|
||||
return api.getMessageRecipients(message.messageId, message.senderId)
|
||||
.map { recipients ->
|
||||
recipients.map { it.toRecipient() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun ApiRecipient.toRecipient(): Recipient {
|
||||
return Recipient(
|
||||
studentId = api.studentId,
|
||||
name = it.name,
|
||||
realName = it.name,
|
||||
realId = it.id,
|
||||
hash = it.hash,
|
||||
loginId = it.loginId,
|
||||
role = it.role,
|
||||
unitId = it.reportingUnitId ?: 0
|
||||
realId = id,
|
||||
realName = name,
|
||||
name = shortName,
|
||||
hash = hash,
|
||||
loginId = loginId,
|
||||
role = role,
|
||||
unitId = reportingUnitId ?: 0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ 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.Message
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
@ -39,4 +40,13 @@ class RecipientRepository @Inject constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getMessageRecipients(student: Student, message: Message): Single<List<Recipient>> {
|
||||
return Single.just(apiHelper.initApi(student))
|
||||
.flatMap { ReactiveNetwork.checkInternetConnectivity(settings) }
|
||||
.flatMap {
|
||||
if (it) remote.getMessageRecipients(message)
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginModule
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainModule
|
||||
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
||||
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
||||
import io.github.wulkanowy.ui.widgets.timetable.TimetableWidgetProvider
|
||||
|
||||
@ -15,7 +16,7 @@ import io.github.wulkanowy.ui.widgets.timetable.TimetableWidgetProvider
|
||||
internal abstract class BuilderModule {
|
||||
|
||||
@PerActivity
|
||||
@ContributesAndroidInjector()
|
||||
@ContributesAndroidInjector
|
||||
abstract fun bindSplashActivity(): SplashActivity
|
||||
|
||||
@PerActivity
|
||||
@ -26,6 +27,9 @@ internal abstract class BuilderModule {
|
||||
@ContributesAndroidInjector(modules = [MainModule::class])
|
||||
abstract fun bindMainActivity(): MainActivity
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun bindMessageSendActivity(): SendMessageActivity
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun bindTimetableWidgetService(): TimetableWidgetService
|
||||
|
||||
|
@ -20,7 +20,6 @@ import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
|
||||
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
||||
import io.github.wulkanowy.ui.modules.message.MessageModule
|
||||
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.note.NoteFragment
|
||||
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
|
||||
@ -97,10 +96,6 @@ abstract class MainModule {
|
||||
@ContributesAndroidInjector
|
||||
abstract fun bindCompletedLessonsFragment(): CompletedLessonsFragment
|
||||
|
||||
@PerFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun bindSendMessageFragment(): SendMessageFragment
|
||||
|
||||
@PerFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun bindAccountDialog(): AccountDialog
|
||||
|
@ -12,9 +12,8 @@ import io.github.wulkanowy.data.repositories.message.MessageFolder.SENT
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
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.message.send.SendMessageFragment
|
||||
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
||||
import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment
|
||||
import io.github.wulkanowy.utils.setOnSelectPageListener
|
||||
import kotlinx.android.synthetic.main.fragment_message.*
|
||||
@ -85,7 +84,7 @@ class MessageFragment : BaseFragment(), MessageView, MainView.TitledView {
|
||||
}
|
||||
|
||||
override fun openSendMessage() {
|
||||
(activity as? MainActivity)?.pushView(SendMessageFragment.newInstance())
|
||||
context?.let { it.startActivity(SendMessageActivity.getStartIntent(it)) }
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -1,20 +1,31 @@
|
||||
package io.github.wulkanowy.ui.modules.message.preview
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
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.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
||||
import kotlinx.android.synthetic.main.fragment_message_preview.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
class MessagePreviewFragment : BaseSessionFragment(), MessagePreviewView, MainView.TitledView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: MessagePreviewPresenter
|
||||
|
||||
private var menuReplyButton: MenuItem? = null
|
||||
|
||||
override val titleStringId: Int
|
||||
get() = R.string.message_title
|
||||
|
||||
@ -31,42 +42,66 @@ class MessagePreviewFragment : BaseSessionFragment(), MessagePreviewView, MainVi
|
||||
}
|
||||
}
|
||||
|
||||
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_message_preview, container, false)
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
messageContainer = message
|
||||
messageContainer = messagePreviewContainer
|
||||
presenter.onAttachView(this, (savedInstanceState ?: arguments)?.getInt(MESSAGE_ID_KEY) ?: 0)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
|
||||
inflater?.inflate(R.menu.action_menu_message_preview, menu)
|
||||
menuReplyButton = menu?.findItem(R.id.messagePreviewMenuReply)
|
||||
presenter.onCreateOptionsMenu()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||
return if (item?.itemId == R.id.messagePreviewMenuReply) presenter.onReply()
|
||||
else false
|
||||
}
|
||||
|
||||
override fun setSubject(subject: String) {
|
||||
messageSubject.text = subject
|
||||
messagePreviewSubject.text = subject
|
||||
}
|
||||
|
||||
override fun setRecipient(recipient: String?) {
|
||||
messageAuthor.text = getString(R.string.message_to, recipient)
|
||||
override fun setRecipient(recipient: String) {
|
||||
messagePreviewAuthor.text = "${getString(R.string.message_to)} $recipient"
|
||||
}
|
||||
|
||||
override fun setSender(sender: String?) {
|
||||
messageAuthor.text = getString(R.string.message_from, sender)
|
||||
override fun setSender(sender: String) {
|
||||
messagePreviewAuthor.text = "${getString(R.string.message_from)} $sender"
|
||||
}
|
||||
|
||||
override fun setDate(date: String?) {
|
||||
messageDate.text = getString(R.string.message_date, date)
|
||||
override fun setDate(date: String) {
|
||||
messagePreviewDate.text = getString(R.string.message_date, date)
|
||||
}
|
||||
|
||||
override fun setContent(content: String?) {
|
||||
messageContent.text = content
|
||||
override fun setContent(content: String) {
|
||||
messagePreviewContent.text = content
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
messageProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
messagePreviewProgress.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showReplyButton(show: Boolean) {
|
||||
menuReplyButton?.isVisible = show
|
||||
}
|
||||
|
||||
override fun showMessageError() {
|
||||
messageError.visibility = View.VISIBLE
|
||||
messagePreviewError.visibility = VISIBLE
|
||||
}
|
||||
|
||||
override fun openMessageReply(message: Message?) {
|
||||
context?.let { it.startActivity(SendMessageActivity.getStartIntent(it, message)) }
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.wulkanowy.ui.modules.message.preview
|
||||
|
||||
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
@ -21,6 +22,8 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
|
||||
var messageId: Int = 0
|
||||
|
||||
private var replyMessage: Message? = null
|
||||
|
||||
fun onAttachView(view: MessagePreviewView, id: Int) {
|
||||
super.onAttachView(view)
|
||||
loadData(id)
|
||||
@ -38,11 +41,13 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
.doFinally { view?.showProgress(false) }
|
||||
.subscribe({ message ->
|
||||
Timber.i("Loading message $id preview result: Success ")
|
||||
replyMessage = message
|
||||
view?.run {
|
||||
message.let {
|
||||
setSubject(if (it.subject.isNotBlank()) it.subject else noSubjectString)
|
||||
setDate(it.date.toFormattedString("yyyy-MM-dd HH:mm:ss"))
|
||||
setContent(it.content)
|
||||
setContent(it.content.orEmpty())
|
||||
showReplyButton(true)
|
||||
|
||||
if (it.recipient.isNotBlank()) setRecipient(it.recipient)
|
||||
else setSender(it.sender)
|
||||
@ -56,4 +61,15 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun onReply(): Boolean {
|
||||
return if (replyMessage != null) {
|
||||
view?.openMessageReply(replyMessage)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
fun onCreateOptionsMenu() {
|
||||
view?.showReplyButton(replyMessage != null)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.message.preview
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||
|
||||
interface MessagePreviewView : BaseSessionView {
|
||||
@ -8,15 +9,19 @@ interface MessagePreviewView : BaseSessionView {
|
||||
|
||||
fun setSubject(subject: String)
|
||||
|
||||
fun setRecipient(recipient: String?)
|
||||
fun setRecipient(recipient: String)
|
||||
|
||||
fun setSender(sender: String?)
|
||||
fun setSender(sender: String)
|
||||
|
||||
fun setDate(date: String?)
|
||||
fun setDate(date: String)
|
||||
|
||||
fun setContent(content: String?)
|
||||
fun setContent(content: String)
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
fun showReplyButton(show: Boolean)
|
||||
|
||||
fun showMessageError()
|
||||
|
||||
fun openMessageReply(message: Message?)
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package io.github.wulkanowy.ui.modules.message.send
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import com.pchmn.materialchips.model.ChipInterface
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
|
||||
class RecipientChip(var recipient: Recipient) : ChipInterface {
|
||||
|
||||
override fun getAvatarDrawable(): Drawable? = null
|
||||
|
||||
override fun getAvatarUri(): Uri? = null
|
||||
|
||||
override fun getId(): Any = recipient.id
|
||||
|
||||
override fun getLabel(): String = recipient.name
|
||||
|
||||
override fun getInfo(): String {
|
||||
return recipient.realName.run {
|
||||
substringBeforeLast("-").let { sub ->
|
||||
when {
|
||||
(sub == this) -> this
|
||||
(sub.indexOf('(') != -1) -> indexOf("(").let { substring(if (it != -1) it else 0) }
|
||||
(sub.indexOf('[') != -1) -> indexOf("[").let { substring(if (it != -1) it else 0) }
|
||||
else -> substringAfter('-')
|
||||
}
|
||||
}.trim()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package io.github.wulkanowy.ui.modules.message.send
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.widget.Toast
|
||||
import android.widget.Toast.LENGTH_LONG
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.utils.hideSoftInput
|
||||
import io.github.wulkanowy.utils.showSoftInput
|
||||
import kotlinx.android.synthetic.main.activity_send_message.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class SendMessageActivity : BaseActivity(), SendMessageView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: SendMessagePresenter
|
||||
|
||||
companion object {
|
||||
private const val EXTRA_MESSAGE = "EXTRA_MESSAGE"
|
||||
|
||||
fun getStartIntent(context: Context) = Intent(context, SendMessageActivity::class.java)
|
||||
|
||||
fun getStartIntent(context: Context, message: Message?): Intent {
|
||||
return getStartIntent(context).putExtra(EXTRA_MESSAGE, message)
|
||||
}
|
||||
}
|
||||
|
||||
override val formRecipientsData: List<Recipient>
|
||||
get() = (sendMessageRecipientsInput.selectedChipList).map { (it as RecipientChip).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.message_required_recipients)
|
||||
|
||||
override val messageContentMinLength: String
|
||||
get() = getString(R.string.message_content_min_length)
|
||||
|
||||
override val messageSuccess: String
|
||||
get() = getString(R.string.message_send_successful)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_send_message)
|
||||
setSupportActionBar(sendMessageToolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
messageContainer = sendMessageContainer
|
||||
|
||||
presenter.onAttachView(this, intent.getSerializableExtra(EXTRA_MESSAGE) as? Message)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.action_menu_send_message, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
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>) {
|
||||
sendMessageRecipientsInput.filterableList = recipients.map { RecipientChip(it) }
|
||||
}
|
||||
|
||||
override fun setSelectedRecipients(recipients: List<Recipient>) {
|
||||
recipients.map { sendMessageRecipientsInput.addChip(RecipientChip(it)) }
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
sendMessageProgress.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
sendMessageContent.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
sendMessageEmpty.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showActionBar(show: Boolean) {
|
||||
supportActionBar?.apply { if (show) show() else hide() }
|
||||
}
|
||||
|
||||
override fun setSubject(subject: String) {
|
||||
sendMessageSubjectInput.setText(subject)
|
||||
}
|
||||
|
||||
override fun setContent(content: String) {
|
||||
sendMessageContentInput.setText(content)
|
||||
}
|
||||
|
||||
override fun showMessage(text: String) {
|
||||
Toast.makeText(this, text, LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun showSoftInput(show: Boolean) {
|
||||
if (show) showSoftInput() else hideSoftInput()
|
||||
}
|
||||
|
||||
override fun popView() {
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
presenter.onDetachView()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
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()
|
||||
}
|
||||
}
|
@ -1,50 +1,77 @@
|
||||
package io.github.wulkanowy.ui.modules.message.send
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
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.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.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
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.Completable
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class SendMessagePresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
private val errorHandler: ErrorHandler,
|
||||
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 preferencesRepository: PreferencesRepository,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<SendMessageView>(errorHandler) {
|
||||
) : BasePresenter<SendMessageView>(errorHandler) {
|
||||
|
||||
private lateinit var reportingUnit: ReportingUnit
|
||||
|
||||
override fun onAttachView(view: SendMessageView) {
|
||||
fun onAttachView(view: SendMessageView, message: Message?) {
|
||||
super.onAttachView(view)
|
||||
Timber.i("Send message view is attached")
|
||||
view.run {
|
||||
initView()
|
||||
showBottomNav(false)
|
||||
loadData(message)
|
||||
view.apply {
|
||||
message?.let {
|
||||
setSubject("RE: ${message.subject}")
|
||||
if (preferencesRepository.fillMessageContent) {
|
||||
setContent(when (message.sender.isNotEmpty()) {
|
||||
true -> "\n\nOd: ${message.sender}\n"
|
||||
false -> "\n\nDo: ${message.recipient}\n"
|
||||
} + "Data: ${message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${message.content}")
|
||||
}
|
||||
}
|
||||
}
|
||||
loadRecipients()
|
||||
}
|
||||
|
||||
private fun loadRecipients() {
|
||||
private fun loadData(message: Message?) {
|
||||
var reportingUnit: ReportingUnit? = null
|
||||
var recipients: List<Recipient> = emptyList()
|
||||
var selectedRecipient: List<Recipient> = emptyList()
|
||||
|
||||
Timber.i("Loading recipients started")
|
||||
disposable.add(studentRepository.getCurrentStudent()
|
||||
.flatMapMaybe { student ->
|
||||
semesterRepository.getCurrentSemester(student)
|
||||
.flatMapMaybe { reportingUnitRepository.getReportingUnit(student, it.unitId) }
|
||||
.flatMap { semesterRepository.getCurrentSemester(it).map { semester -> it to semester } }
|
||||
.flatMapCompletable { (student, semester) ->
|
||||
reportingUnitRepository.getReportingUnit(student, semester.unitId)
|
||||
.doOnSuccess { reportingUnit = it }
|
||||
.flatMap { recipientRepository.getRecipients(student, 2, it).toMaybe() }
|
||||
.doOnSuccess {
|
||||
Timber.i("Loading recipients result: Success, fetched %d recipients", it.size)
|
||||
recipients = it
|
||||
}
|
||||
.flatMapCompletable {
|
||||
if (message == null) Completable.complete()
|
||||
else recipientRepository.getMessageRecipients(student, message)
|
||||
.doOnSuccess {
|
||||
Timber.i("Loaded message recipients to reply result: Success, fetched %d recipients", it.size)
|
||||
selectedRecipient = it
|
||||
}
|
||||
.ignoreElement()
|
||||
}
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
@ -54,28 +81,24 @@ class SendMessagePresenter @Inject constructor(
|
||||
showContent(false)
|
||||
}
|
||||
}
|
||||
.doFinally {
|
||||
view?.run {
|
||||
showProgress(false)
|
||||
}
|
||||
}
|
||||
.doFinally { view?.run { showProgress(false) } }
|
||||
.subscribe({
|
||||
Timber.i("Loading recipients result: Success, fetched %s recipients", it.size.toString())
|
||||
view?.apply {
|
||||
setReportingUnit(reportingUnit)
|
||||
setRecipients(it)
|
||||
refreshRecipientsAdapter()
|
||||
if (reportingUnit !== null) {
|
||||
reportingUnit?.let { setReportingUnit(it) }
|
||||
setRecipients(recipients)
|
||||
if (selectedRecipient.isNotEmpty()) setSelectedRecipients(selectedRecipient)
|
||||
showContent(true)
|
||||
} else {
|
||||
Timber.e("Loading recipients result: Can't find the reporting unit")
|
||||
view?.showEmpty(true)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
Timber.i("Loading recipients result: An exception occurred")
|
||||
Timber.e("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>) {
|
||||
@ -85,14 +108,12 @@ class SendMessagePresenter @Inject constructor(
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.run {
|
||||
hideSoftInput()
|
||||
showSoftInput(false)
|
||||
showContent(false)
|
||||
showProgress(true)
|
||||
showActionBar(false)
|
||||
}
|
||||
}
|
||||
.doFinally {
|
||||
view?.showProgress(false)
|
||||
}
|
||||
.subscribe({
|
||||
Timber.i("Sending message result: Success")
|
||||
analytics.logEvent("send_message", "recipients" to recipients.size)
|
||||
@ -102,16 +123,16 @@ class SendMessagePresenter @Inject constructor(
|
||||
}
|
||||
}, {
|
||||
Timber.i("Sending message result: An exception occurred")
|
||||
view?.showContent(true)
|
||||
view?.run {
|
||||
showContent(true)
|
||||
showProgress(false)
|
||||
showActionBar(true)
|
||||
}
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fun onTypingRecipients() {
|
||||
view?.refreshRecipientsAdapter()
|
||||
}
|
||||
|
||||
fun onSend(): Boolean {
|
||||
view?.run {
|
||||
when {
|
||||
@ -129,9 +150,4 @@ class SendMessagePresenter @Inject constructor(
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onDetachView() {
|
||||
view?.showBottomNav(true)
|
||||
super.onDetachView()
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ 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
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface SendMessageView : BaseSessionView {
|
||||
interface SendMessageView : BaseView {
|
||||
|
||||
val formRecipientsData: List<Recipient>
|
||||
|
||||
@ -18,13 +18,11 @@ interface SendMessageView : BaseSessionView {
|
||||
|
||||
val messageSuccess: String
|
||||
|
||||
fun initView()
|
||||
|
||||
fun setReportingUnit(unit: ReportingUnit)
|
||||
|
||||
fun setRecipients(recipients: List<Recipient>)
|
||||
|
||||
fun refreshRecipientsAdapter()
|
||||
fun setSelectedRecipients(recipients: List<Recipient>)
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
@ -32,9 +30,13 @@ interface SendMessageView : BaseSessionView {
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
fun showActionBar(show: Boolean)
|
||||
|
||||
fun setSubject(subject: String)
|
||||
|
||||
fun setContent(content: String)
|
||||
|
||||
fun showSoftInput(show: Boolean)
|
||||
|
||||
fun popView()
|
||||
|
||||
fun hideSoftInput()
|
||||
|
||||
fun showBottomNav(show: Boolean)
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ class MessageTabFragment : BaseSessionFragment(), MessageTabView, MessageView.Me
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
messageContainer = messageTabRecycler
|
||||
presenter.onAttachView(this, MessageFolder.valueOf(
|
||||
(savedInstanceState ?: arguments)?.getString(MessageTabFragment.MESSAGE_TAB_FOLDER_ID) ?: ""
|
||||
(savedInstanceState ?: arguments)?.getString(MessageTabFragment.MESSAGE_TAB_FOLDER_ID).orEmpty()
|
||||
))
|
||||
}
|
||||
|
||||
|
10
app/src/main/res/drawable/ic_message_reply_24dp.xml
Normal file
10
app/src/main/res/drawable/ic_message_reply_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="M10,9V5l-7,7 7,7v-4.1c5,0 8.5,1.6 11,5.1 -1,-5 -4,-10 -11,-11z" />
|
||||
</vector>
|
@ -3,13 +3,28 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/sendMessageContainer"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/sendMessageAppBarContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/WulkanowyTheme.ActionBar"
|
||||
app:elevation="0dp">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/sendMessageToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/sendMessageContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/sendMessageAppBarContainer"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
@ -22,14 +37,14 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/send_message_from"
|
||||
android:text="@string/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:layout_height="30dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:enabled="false"
|
||||
android:textColor="?android:attr/textColorPrimaryNoDisable"
|
||||
@ -43,32 +58,32 @@
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="58dp"
|
||||
android:paddingStart="14dp"
|
||||
android:paddingLeft="14dp"
|
||||
android:paddingTop="14dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingRight="0dp"
|
||||
android:paddingBottom="14dp">
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/send_message_to"
|
||||
android:text="@string/message_to"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<com.hootsuite.nachos.NachoTextView
|
||||
android:id="@+id/sendMessageRecipientInput"
|
||||
<com.pchmn.materialchips.ChipsInput
|
||||
android:id="@+id/sendMessageRecipientsInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="@android:color/transparent"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/chipTextColor"
|
||||
app:chipBackground="?attr/chipBackgroundColor" />
|
||||
app:horizontalScroll="true"
|
||||
tools:layout_height="30dp">
|
||||
|
||||
</com.pchmn.materialchips.ChipsInput>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
@ -79,9 +94,9 @@
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
android:id="@+id/sendMessageSubjectInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="66dp"
|
||||
android:layout_height="58dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:hint="@string/send_message_subject"
|
||||
android:hint="@string/message_subject"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:padding="14dp" />
|
||||
@ -97,7 +112,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:gravity="top|start"
|
||||
android:hint="@string/send_message_content"
|
||||
android:hint="@string/message_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:paddingStart="14dp"
|
||||
android:paddingLeft="14dp"
|
||||
@ -107,9 +122,10 @@
|
||||
android:singleLine="false" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/sendMessageAppBarContainer">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/sendMessageEmpty"
|
||||
@ -141,5 +157,5 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</FrameLayout>
|
||||
</RelativeLayout>
|
@ -1,22 +1,22 @@
|
||||
<FrameLayout 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:id="@+id/messagePreviewContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ScrollView
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messageSubject"
|
||||
android:id="@+id/messagePreviewSubject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="15dp"
|
||||
@ -25,7 +25,7 @@
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messageAuthor"
|
||||
android:id="@+id/messagePreviewAuthor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
@ -34,7 +34,7 @@
|
||||
tools:text="@tools:sample/full_names" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messageDate"
|
||||
android:id="@+id/messagePreviewDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="15dp"
|
||||
@ -43,7 +43,7 @@
|
||||
tools:text="@tools:sample/date/ddmmyy" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/messageContent"
|
||||
android:id="@+id/messagePreviewContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
@ -51,11 +51,10 @@
|
||||
android:textIsSelectable="true"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/messageError"
|
||||
android:id="@+id/messagePreviewError"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
@ -82,7 +81,7 @@
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/messageProgress"
|
||||
android:id="@+id/messagePreviewProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
10
app/src/main/res/menu/action_menu_message_preview.xml
Normal file
10
app/src/main/res/menu/action_menu_message_preview.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/messagePreviewMenuReply"
|
||||
android:icon="@drawable/ic_message_reply_24dp"
|
||||
android:orderInCategory="1"
|
||||
android:title="@string/message_reply"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
@ -7,9 +7,12 @@
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||
<item name="bottomNavBackground">@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>
|
||||
<item name="chip_backgroundColor">@color/chip_backgroundColor_inverse</item>
|
||||
<item name="chip_labelColor">@color/chip_labelColor_inverse</item>
|
||||
<item name="chip_detailed_backgroundColor">@color/chip_backgroundColor_inverse</item>
|
||||
<item name="filterable_list_backgroundColor">@color/filterable_list_backgroundColor_inverse</item>
|
||||
<item name="filterable_list_textColor">@color/filterable_list_textColor_inverse</item>
|
||||
|
||||
<!--AboutLibraries specific values-->
|
||||
<item name="about_libraries_window_background">@color/about_libraries_window_background_dark</item>
|
||||
|
@ -13,6 +13,7 @@
|
||||
<string name="more_title">Więcej</string>
|
||||
<string name="about_title">O aplikacji</string>
|
||||
<string name="message_title">Wiadomości</string>
|
||||
<string name="send_message_title">Nowa wiadomość</string>
|
||||
<string name="note_title">Uwagi i osiągnięcia</string>
|
||||
<string name="homework_title">Zadania domowe</string>
|
||||
<string name="account_title">Wybierz konto</string>
|
||||
@ -135,9 +136,15 @@
|
||||
<string name="message_no_subject">(brak tematu)</string>
|
||||
<string name="message_no_items">Brak wiadomości</string>
|
||||
<string name="message_preview_error">Wystąpił błąd podczas pobierania treści wiadomości</string>
|
||||
<string name="message_from">Od: %s</string>
|
||||
<string name="message_to">Do: %s</string>
|
||||
<string name="message_from">Od:</string>
|
||||
<string name="message_to">Do:</string>
|
||||
<string name="message_date">Data: %s</string>
|
||||
<string name="message_reply">Odpowiedz</string>
|
||||
<string name="message_subject">Temat</string>
|
||||
<string name="message_content">Treść</string>
|
||||
<string name="message_send_successful">Wiadomość wysłana pomyślnie</string>
|
||||
<string name="message_required_recipients">Musisz wybrać co najmniej 1 adresata</string>
|
||||
<string name="message_content_min_length">Treść wiadomości musi zawierać co najmniej 3 znaki</string>
|
||||
<plurals name="message_number_item">
|
||||
<item quantity="one">%d wiadomość</item>
|
||||
<item quantity="few">%d wiadomości</item>
|
||||
@ -154,16 +161,6 @@
|
||||
<item quantity="many">Dostałeś %1$d wiadomości</item>
|
||||
</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>
|
||||
|
||||
|
||||
<!--Note-->
|
||||
<string name="note_no_items">Brak informacji o uwagach</string>
|
||||
@ -241,8 +238,6 @@
|
||||
<string name="pref_view_summary">Pokazuj podsumowanie w ocenach</string>
|
||||
<string name="pref_view_present">Pokazuj obecność we frekwencji</string>
|
||||
<string name="pref_view_theme_dark">Ciemny motyw (Beta)</string>
|
||||
<string name="pref_view_grade_modifier_plus">Wartość plusa</string>
|
||||
<string name="pref_view_grade_modifier_minus">Wartość minusa</string>
|
||||
<string name="pref_view_expand_grade">Rozwiń oceny</string>
|
||||
<string name="pref_grade_color_scheme">Schemat kolorów ocen</string>
|
||||
|
||||
@ -256,6 +251,11 @@
|
||||
<string name="pref_services_interval">Interwał aktualizacji</string>
|
||||
<string name="pref_services_wifi">Tylko WiFi</string>
|
||||
|
||||
<string name="pref_other_header">Inne</string>
|
||||
<string name="pref_other_grade_modifier_plus">Wartość plusa</string>
|
||||
<string name="pref_other_grade_modifier_minus">Wartość minusa</string>
|
||||
<string name="pref_other_fill_message_content">Odpowiadaj z historią wiadomości</string>
|
||||
|
||||
|
||||
<!--Notification Channels-->
|
||||
<string name="channel_new_entries">Nowe wpisy w dzienniku</string>
|
||||
|
@ -32,8 +32,11 @@
|
||||
<color name="bottom_nav_background">#303030</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="chip_backgroundColor_inverse">#595959</color>
|
||||
<color name="chip_labelColor_inverse">#fefefe</color>
|
||||
<color name="chip_detailed_backgroundColor">#fefefe</color>
|
||||
<color name="filterable_list_backgroundColor_inverse">#393939</color>
|
||||
<color name="filterable_list_textColor_inverse">#fefefe</color>
|
||||
|
||||
<color name="divider">#cccccc</color>
|
||||
<color name="divider_inverse">#777777</color>
|
||||
|
@ -3,8 +3,6 @@
|
||||
<string name="pref_key_start_menu">start_menu</string>
|
||||
<string name="pref_key_attendance_present">attendance_present</string>
|
||||
<string name="pref_key_theme">theme</string>
|
||||
<string name="pref_key_grade_modifier_plus">grade_modifier_plus</string>
|
||||
<string name="pref_key_grade_modifier_minus">grade_modifier_minus</string>
|
||||
<string name="pref_key_grade_color_scheme">grade_color_scheme</string>
|
||||
<string name="pref_key_expand_grade">expand_grade</string>
|
||||
<string name="pref_key_services_enable">services_enable</string>
|
||||
@ -12,4 +10,7 @@
|
||||
<string name="pref_key_services_wifi_only">services_disable_wifi_only</string>
|
||||
<string name="pref_key_notifications_enable">notifications_enable</string>
|
||||
<string name="pref_key_notification_debug">notification_debug</string>
|
||||
<string name="pref_key_grade_modifier_plus">grade_modifier_plus</string>
|
||||
<string name="pref_key_grade_modifier_minus">grade_modifier_minus</string>
|
||||
<string name="pref_key_fill_message_content">fill_message_content</string>
|
||||
</resources>
|
||||
|
@ -13,6 +13,7 @@
|
||||
<string name="more_title">More</string>
|
||||
<string name="about_title">About</string>
|
||||
<string name="message_title">Messages</string>
|
||||
<string name="send_message_title">New message</string>
|
||||
<string name="note_title">Notes and achievements</string>
|
||||
<string name="homework_title">Homework</string>
|
||||
<string name="account_title">Choose account</string>
|
||||
@ -129,9 +130,15 @@
|
||||
<string name="message_no_subject">(no subject)</string>
|
||||
<string name="message_no_items">No messages</string>
|
||||
<string name="message_preview_error">An error occurred while downloading message content</string>
|
||||
<string name="message_from">From: %s</string>
|
||||
<string name="message_to">To: %s</string>
|
||||
<string name="message_from">From:</string>
|
||||
<string name="message_to">To:</string>
|
||||
<string name="message_date">Date: %s</string>
|
||||
<string name="message_reply">Reply</string>
|
||||
<string name="message_subject">Subject</string>
|
||||
<string name="message_content">Content</string>
|
||||
<string name="message_send_successful">Message sent successfully</string>
|
||||
<string name="message_required_recipients">You need to choose at least 1 recipient</string>
|
||||
<string name="message_content_min_length">The message content must be at least 3 characters</string>
|
||||
<plurals name="message_number_item">
|
||||
<item quantity="one">%d message</item>
|
||||
<item quantity="other">%d messages</item>
|
||||
@ -145,16 +152,6 @@
|
||||
<item quantity="other">You received %1$d messages</item>
|
||||
</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>
|
||||
|
||||
|
||||
<!--Note-->
|
||||
<string name="note_no_items">No info about notes</string>
|
||||
@ -226,8 +223,6 @@
|
||||
<string name="pref_view_summary">Show the summary in the grades</string>
|
||||
<string name="pref_view_present">Show presence in attendance</string>
|
||||
<string name="pref_view_theme_dark">Dark theme (Beta)</string>
|
||||
<string name="pref_view_grade_modifier_plus">Value of the plus</string>
|
||||
<string name="pref_view_grade_modifier_minus">Value of the minus</string>
|
||||
<string name="pref_view_expand_grade">Expand grades</string>
|
||||
<string name="pref_grade_color_scheme">Grades color scheme</string>
|
||||
|
||||
@ -241,6 +236,11 @@
|
||||
<string name="pref_services_interval">Updates interval</string>
|
||||
<string name="pref_services_wifi">Wi-Fi only</string>
|
||||
|
||||
<string name="pref_other_header">Other</string>
|
||||
<string name="pref_other_grade_modifier_plus">Value of the plus</string>
|
||||
<string name="pref_other_grade_modifier_minus">Value of the minus</string>
|
||||
<string name="pref_other_fill_message_content">Reply with message history</string>
|
||||
|
||||
|
||||
<!--Notification Channels-->
|
||||
<string name="channel_new_entries">New entries in register</string>
|
||||
|
@ -14,9 +14,8 @@
|
||||
<item name="subtitleTextColor">@android:color/primary_text_dark</item>
|
||||
<item name="android:colorBackground">@android:color/white</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>
|
||||
<item name="chip_detailed_backgroundColor">@color/chip_detailed_backgroundColor</item>
|
||||
|
||||
<!-- AboutLibraries specific values -->
|
||||
<item name="about_libraries_window_background">@color/about_libraries_window_background</item>
|
||||
|
@ -38,22 +38,6 @@
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_grade_color_scheme"
|
||||
app:iconSpaceReserved="false" />
|
||||
<ListPreference
|
||||
android:defaultValue="0.0"
|
||||
android:entries="@array/grade_modifier_entries"
|
||||
android:entryValues="@array/grade_modifier_value"
|
||||
android:key="@string/pref_key_grade_modifier_plus"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_view_grade_modifier_plus"
|
||||
app:iconSpaceReserved="false" />
|
||||
<ListPreference
|
||||
android:defaultValue="0.0"
|
||||
android:entries="@array/grade_modifier_entries"
|
||||
android:entryValues="@array/grade_modifier_value"
|
||||
android:key="@string/pref_key_grade_modifier_minus"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_view_grade_modifier_minus"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/pref_services_header"
|
||||
@ -94,4 +78,29 @@
|
||||
android:title="@string/pref_notify_debug_switch"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/pref_other_header"
|
||||
app:iconSpaceReserved="false">
|
||||
<ListPreference
|
||||
android:defaultValue="0.0"
|
||||
android:entries="@array/grade_modifier_entries"
|
||||
android:entryValues="@array/grade_modifier_value"
|
||||
android:key="@string/pref_key_grade_modifier_plus"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_other_grade_modifier_plus"
|
||||
app:iconSpaceReserved="false" />
|
||||
<ListPreference
|
||||
android:defaultValue="0.0"
|
||||
android:entries="@array/grade_modifier_entries"
|
||||
android:entryValues="@array/grade_modifier_value"
|
||||
android:key="@string/pref_key_grade_modifier_minus"
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_other_grade_modifier_minus"
|
||||
app:iconSpaceReserved="false" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="@string/pref_key_fill_message_content"
|
||||
android:title="@string/pref_other_fill_message_content"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
@ -0,0 +1,20 @@
|
||||
package io.github.wulkanowy.ui.modules.message.send
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class TestRecipientChip {
|
||||
|
||||
@Test
|
||||
fun testRecipientChipInfo() {
|
||||
assertEquals("Uczeń", getRecipientChip("Kowalski Jan - Uczeń").info)
|
||||
assertEquals("(JK) - pracownik [Fake123456]", getRecipientChip("Kowalski Jan (JK) - pracownik [Fake123456]").info)
|
||||
assertEquals("[KK] - pracownik (Fake123456)", getRecipientChip("Kowalska Karolina [KK] - pracownik (Fake123456)").info)
|
||||
assertEquals("(BK) - Nauczyciel [Fake123456]", getRecipientChip("Kowal-Mazur Barbara (BK) - Nauczyciel [Fake123456]").info)
|
||||
}
|
||||
|
||||
private fun getRecipientChip(realName: String): RecipientChip {
|
||||
return RecipientChip(Recipient(0, "", "", realName, 0, 0, 0, ""))
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user