forked from github/wulkanowy-mirror
Refactor timetable module (#160)
This commit is contained in:
parent
f2b7c0e781
commit
5cd8ed88c0
226
.idea/codeStyleSettings.xml
generated
226
.idea/codeStyleSettings.xml
generated
@ -1,226 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectCodeStyleSettingsManager">
|
||||
<option name="PER_PROJECT_SETTINGS">
|
||||
<value>
|
||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||
<value />
|
||||
</option>
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="android" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="com" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="junit" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="net" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="org" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="java" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="javax" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
</value>
|
||||
</option>
|
||||
<option name="RIGHT_MARGIN" value="100" />
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="USE_CUSTOM_SETTINGS" value="true" />
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<Objective-C-extensions>
|
||||
<file>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||
</file>
|
||||
<class>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||
</class>
|
||||
<extensions>
|
||||
<pair source="cpp" header="h" />
|
||||
<pair source="c" header="h" />
|
||||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
<XML>
|
||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||
</XML>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_width</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_height</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_.*</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:width</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:height</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
</value>
|
||||
</option>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</component>
|
||||
</project>
|
@ -72,10 +72,7 @@ ext.supportVersion = "28.0.0"
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation('com.github.wulkanowy:api:07201a4') {
|
||||
exclude module: "threetenbp"
|
||||
}
|
||||
|
||||
implementation('com.github.wulkanowy:api:f54b673') { exclude module: "threetenbp" }
|
||||
implementation "com.android.support:support-v4:$supportVersion"
|
||||
implementation "com.android.support:appcompat-v7:$supportVersion"
|
||||
implementation "com.android.support:design:$supportVersion"
|
||||
|
@ -0,0 +1,51 @@
|
||||
package io.github.wulkanowy.data.repositories.local
|
||||
|
||||
import android.arch.persistence.room.Room
|
||||
import android.support.test.InstrumentationRegistry
|
||||
import android.support.test.runner.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TimetableLocalTest {
|
||||
|
||||
private lateinit var timetableDb: TimetableLocal
|
||||
|
||||
private lateinit var testDb: AppDatabase
|
||||
|
||||
@Before
|
||||
fun createDb() {
|
||||
testDb = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(), AppDatabase::class.java).build()
|
||||
timetableDb = TimetableLocal(testDb.timetableDao())
|
||||
}
|
||||
|
||||
@After
|
||||
fun closeDb() {
|
||||
testDb.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
timetableDb.saveLessons(listOf(
|
||||
Timetable(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 10)),
|
||||
Timetable(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 14)),
|
||||
Timetable(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 17)) // in next week
|
||||
))
|
||||
|
||||
val exams = timetableDb.getLessons(
|
||||
Semester(studentId = "1", diaryId = "2", semesterId = "3", diaryName = "", semesterName = 1),
|
||||
LocalDate.of(2018, 9, 10),
|
||||
LocalDate.of(2018, 9, 14)
|
||||
).blockingGet()
|
||||
assertEquals(2, exams.size)
|
||||
assertEquals(exams[0].date, LocalDate.of(2018, 9, 10))
|
||||
assertEquals(exams[1].date, LocalDate.of(2018, 9, 14))
|
||||
}
|
||||
}
|
@ -63,4 +63,8 @@ internal class RepositoryModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideAttendanceDao(database: AppDatabase) = database.attendanceDao()
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideTimetableDao(database: AppDatabase) = database.timetableDao()
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import javax.inject.Singleton
|
||||
Student::class,
|
||||
Semester::class,
|
||||
Exam::class,
|
||||
Timetable::class,
|
||||
Attendance::class,
|
||||
Grade::class,
|
||||
GradeSummary::class
|
||||
@ -38,6 +39,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun examsDao(): ExamDao
|
||||
|
||||
abstract fun timetableDao(): TimetableDao
|
||||
|
||||
abstract fun attendanceDao(): AttendanceDao
|
||||
|
||||
abstract fun gradeDao(): GradeDao
|
||||
|
@ -7,7 +7,7 @@ import java.util.*
|
||||
class Converters {
|
||||
|
||||
@TypeConverter
|
||||
fun fromTimestamp(value: Long?): LocalDate? = value?.run {
|
||||
fun timestampToDate(value: Long?): LocalDate? = value?.run {
|
||||
DateTimeUtils.toInstant(Date(value)).atZone(ZoneOffset.UTC).toLocalDate()
|
||||
}
|
||||
|
||||
@ -15,4 +15,14 @@ class Converters {
|
||||
fun dateToTimestamp(date: LocalDate?): Long? {
|
||||
return date?.atStartOfDay()?.toInstant(ZoneOffset.UTC)?.toEpochMilli()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun timestampToTime(value: Long?): LocalDateTime? = value?.let {
|
||||
LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun timeToTimestamp(date: LocalDateTime?): Long? {
|
||||
return date?.atZone(ZoneOffset.UTC)?.toInstant()?.toEpochMilli()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import android.arch.persistence.room.Dao
|
||||
import android.arch.persistence.room.Delete
|
||||
import android.arch.persistence.room.Insert
|
||||
import android.arch.persistence.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
|
||||
@Dao
|
||||
interface TimetableDao {
|
||||
|
||||
@Insert
|
||||
fun insertAll(exams: List<Timetable>): List<Long>
|
||||
|
||||
@Delete
|
||||
fun deleteAll(exams: List<Timetable>)
|
||||
|
||||
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||
fun getTimetable(diaryId: String, studentId: String, from: LocalDate, end: LocalDate): Maybe<List<Timetable>>
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package io.github.wulkanowy.data.db.entities
|
||||
|
||||
import android.arch.persistence.room.ColumnInfo
|
||||
import android.arch.persistence.room.Entity
|
||||
import android.arch.persistence.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.io.Serializable
|
||||
|
||||
@Entity(tableName = "Timetable")
|
||||
data class Timetable(
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0,
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
var studentId: String = "",
|
||||
|
||||
@ColumnInfo(name = "diary_id")
|
||||
var diaryId: String = "",
|
||||
|
||||
val number: Int = 0,
|
||||
|
||||
val start: LocalDateTime = LocalDateTime.now(),
|
||||
|
||||
val end: LocalDateTime = LocalDateTime.now(),
|
||||
|
||||
val date: LocalDate,
|
||||
|
||||
val subject: String = "",
|
||||
|
||||
val group: String = "",
|
||||
|
||||
val room: String = "",
|
||||
|
||||
val teacher: String = "",
|
||||
|
||||
val info: String = "",
|
||||
|
||||
val changes: Boolean = false,
|
||||
|
||||
val canceled: Boolean = false
|
||||
) : Serializable
|
@ -13,7 +13,9 @@ import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.temporal.TemporalAdjusters
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AttendanceRepository @Inject constructor(
|
||||
private val settings: InternetObservingSettings,
|
||||
private val local: AttendanceLocal,
|
||||
|
@ -0,0 +1,45 @@
|
||||
package io.github.wulkanowy.data.repositories
|
||||
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.data.repositories.local.TimetableLocal
|
||||
import io.github.wulkanowy.data.repositories.remote.TimetableRemote
|
||||
import io.github.wulkanowy.utils.weekFirstDayAlwaysCurrent
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.DayOfWeek
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.temporal.TemporalAdjusters
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class TimetableRepository @Inject constructor(
|
||||
private val settings: InternetObservingSettings,
|
||||
private val local: TimetableLocal,
|
||||
private val remote: TimetableRemote
|
||||
) {
|
||||
|
||||
fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false): Single<List<Timetable>> {
|
||||
val start = startDate.weekFirstDayAlwaysCurrent
|
||||
val end = endDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
|
||||
|
||||
return local.getLessons(semester, start, end).filter { !forceRefresh }
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
|
||||
if (it) remote.getLessons(semester, start, end)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newLessons ->
|
||||
local.getLessons(semester, start, end).toSingle(emptyList()).map { lessons ->
|
||||
local.deleteLessons(lessons - newLessons)
|
||||
local.saveLessons(newLessons - lessons)
|
||||
newLessons
|
||||
}
|
||||
}).map { list ->
|
||||
list.asSequence().filter {
|
||||
it.date in startDate..endDate
|
||||
}.toList()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package io.github.wulkanowy.data.repositories.local
|
||||
|
||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class TimetableLocal @Inject constructor(private val timetableDb: TimetableDao) {
|
||||
|
||||
fun getLessons(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Timetable>> {
|
||||
return timetableDb.getTimetable(semester.diaryId, semester.studentId, startDate, endDate)
|
||||
.filter { !it.isEmpty() }
|
||||
}
|
||||
|
||||
fun saveLessons(lessons: List<Timetable>) {
|
||||
timetableDb.insertAll(lessons)
|
||||
}
|
||||
|
||||
fun deleteLessons(exams: List<Timetable>) {
|
||||
timetableDb.deleteAll(exams)
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package io.github.wulkanowy.data.repositories.remote
|
||||
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.utils.toLocalDate
|
||||
import io.github.wulkanowy.utils.toLocalDateTime
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class TimetableRemote @Inject constructor(private val api: Api) {
|
||||
|
||||
fun getLessons(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Timetable>> {
|
||||
return Single.just(api.run {
|
||||
if (diaryId != semester.diaryId) {
|
||||
diaryId = semester.diaryId
|
||||
notifyDataChanged()
|
||||
}
|
||||
}).flatMap { api.getTimetable(startDate, endDate) }.map { lessons ->
|
||||
lessons.map {
|
||||
Timetable(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
number = it.number,
|
||||
start = it.start.toLocalDateTime(),
|
||||
end = it.end.toLocalDateTime(),
|
||||
date = it.date.toLocalDate(),
|
||||
subject = it.subject,
|
||||
group = it.group,
|
||||
room = it.room,
|
||||
teacher = it.teacher,
|
||||
info = it.info,
|
||||
changes = it.changes,
|
||||
canceled = it.canceled
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -101,11 +101,6 @@ class AttendanceFragment : BaseFragment(), AttendanceView {
|
||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
||||
}
|
||||
|
||||
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
||||
super.onViewStateRestored(savedInstanceState)
|
||||
presenter.loadData(date = savedInstanceState?.getLong(SAVED_DATE_KEY))
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
presenter.detachView()
|
||||
|
@ -40,7 +40,7 @@ class AttendancePresenter @Inject constructor(
|
||||
disposable.add(sessionRepository.getSemesters()
|
||||
.map { selectSemester(it, -1) }
|
||||
.flatMap { attendanceRepository.getAttendance(it, currentDate, currentDate, forceRefresh) }
|
||||
.map { createTimetableItems(it) }
|
||||
.map { createAttendanceItems(it) }
|
||||
.subscribeOn(schedulers.backgroundThread())
|
||||
.observeOn(schedulers.mainThread())
|
||||
.doOnSubscribe {
|
||||
@ -74,7 +74,7 @@ class AttendancePresenter @Inject constructor(
|
||||
})
|
||||
}
|
||||
|
||||
private fun createTimetableItems(items: List<Attendance>): List<AttendanceItem> {
|
||||
private fun createAttendanceItems(items: List<Attendance>): List<AttendanceItem> {
|
||||
return items.map {
|
||||
AttendanceItem().apply { attendance = it }
|
||||
}
|
||||
|
@ -94,11 +94,6 @@ class ExamFragment : BaseFragment(), ExamView {
|
||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
||||
}
|
||||
|
||||
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
||||
super.onViewStateRestored(savedInstanceState)
|
||||
presenter.loadData(date = savedInstanceState?.getLong(SAVED_DATE_KEY))
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
presenter.detachView()
|
||||
|
@ -2,7 +2,6 @@ package io.github.wulkanowy.ui.main.exam
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import org.threeten.bp.LocalDate
|
||||
|
||||
interface ExamView : BaseView {
|
||||
|
||||
|
@ -14,7 +14,7 @@ class MoreFragment : BaseFragment() {
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_timetable, container, false)
|
||||
return inflater.inflate(R.layout.fragment_attendance, container, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,79 @@
|
||||
package io.github.wulkanowy.ui.main.timetable
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.DialogFragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.ViewGroup
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import kotlinx.android.synthetic.main.dialog_timetable.*
|
||||
|
||||
class TimetableDialog : DialogFragment() {
|
||||
|
||||
private lateinit var lesson: Timetable
|
||||
|
||||
companion object {
|
||||
private const val ARGUMENT_KEY = "Item"
|
||||
|
||||
fun newInstance(exam: Timetable): TimetableDialog {
|
||||
return TimetableDialog().apply {
|
||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogFragmentTheme)
|
||||
arguments?.run {
|
||||
lesson = getSerializable(ARGUMENT_KEY) as Timetable
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
dialog.setTitle(getString(R.string.all_details))
|
||||
return inflater.inflate(R.layout.dialog_timetable, container, false)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
timetableDialogSubject.text = lesson.subject
|
||||
timetableDialogTime.text = "${lesson.start.toFormattedString("HH:mm")} - ${lesson.end.toFormattedString("HH:mm")}"
|
||||
|
||||
lesson.group.let {
|
||||
if (it.isBlank()) {
|
||||
timetableDialogGroupTitle.visibility = GONE
|
||||
timetableDialogGroup.visibility = GONE
|
||||
} else timetableDialogGroup.text = it
|
||||
}
|
||||
|
||||
lesson.room.let {
|
||||
if (it.isBlank()) {
|
||||
timetableDialogRoomTitle.visibility = GONE
|
||||
timetableDialogRoom.visibility = GONE
|
||||
} else timetableDialogRoom.text = it
|
||||
}
|
||||
|
||||
lesson.teacher.let {
|
||||
if (it.isBlank()) {
|
||||
timetableDialogTeacherTitle.visibility = GONE
|
||||
timetableDialogTeacher.visibility = GONE
|
||||
} else timetableDialogTeacher.text = it
|
||||
}
|
||||
|
||||
lesson.info.let {
|
||||
if (it.isBlank()) {
|
||||
timetableDialogChangesTitle.visibility = GONE
|
||||
timetableDialogChanges.visibility = GONE
|
||||
} else timetableDialogChanges.text = it
|
||||
}
|
||||
|
||||
timetableDialogClose.setOnClickListener { dismiss() }
|
||||
}
|
||||
}
|
@ -4,17 +4,105 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_timetable.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class TimetableFragment : BaseFragment() {
|
||||
class TimetableFragment : BaseFragment(), TimetableView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: TimetablePresenter
|
||||
|
||||
@Inject
|
||||
lateinit var timetableAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||
|
||||
companion object {
|
||||
private const val SAVED_DATE_KEY = "CURRENT_DATE"
|
||||
fun newInstance() = TimetableFragment()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_timetable, container, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
presenter.run {
|
||||
attachView(this@TimetableFragment)
|
||||
loadData(date = savedInstanceState?.getLong(SAVED_DATE_KEY))
|
||||
}
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
timetableAdapter.run {
|
||||
isAutoCollapseOnExpand = true
|
||||
isAutoScrollOnExpand = true
|
||||
setOnItemClickListener { presenter.onTimetableItemSelected(getItem(it))}
|
||||
}
|
||||
timetableRecycler.run {
|
||||
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||
adapter = timetableAdapter
|
||||
}
|
||||
timetableSwipe.setOnRefreshListener { presenter.loadData(date = null, forceRefresh = true) }
|
||||
timetablePreviousButton.setOnClickListener { presenter.loadTimetableForPreviousDay() }
|
||||
timetableNextButton.setOnClickListener { presenter.loadTimetableForNextDay() }
|
||||
}
|
||||
|
||||
override fun updateData(data: List<TimetableItem>) {
|
||||
timetableAdapter.updateDataSet(data, true)
|
||||
}
|
||||
|
||||
override fun clearData() {
|
||||
timetableAdapter.clear()
|
||||
}
|
||||
|
||||
override fun updateNavigationDay(date: String) {
|
||||
timetableNavDate.text = date
|
||||
}
|
||||
|
||||
override fun isViewEmpty() = timetableAdapter.isEmpty
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
timetableEmpty.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
timetableProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
timetableRecycler.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun showRefresh(show: Boolean) {
|
||||
timetableSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun showPreButton(show: Boolean) {
|
||||
timetablePreviousButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||
}
|
||||
|
||||
override fun showNextButton(show: Boolean) {
|
||||
timetableNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||
}
|
||||
|
||||
override fun showTimetableDialog(lesson: Timetable) {
|
||||
TimetableDialog.newInstance(lesson).show(fragmentManager, lesson.toString())
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
presenter.detachView()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
package io.github.wulkanowy.ui.main.timetable
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Paint
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.item_timetable.*
|
||||
|
||||
class TimetableItem : AbstractFlexibleItem<TimetableItem.ViewHolder>() {
|
||||
|
||||
lateinit var lesson: Timetable
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>): ViewHolder {
|
||||
return ViewHolder(view, adapter)
|
||||
}
|
||||
|
||||
override fun getLayoutRes(): Int = R.layout.item_timetable
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as TimetableItem
|
||||
|
||||
if (lesson != other.lesson) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return lesson.hashCode()
|
||||
}
|
||||
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder,
|
||||
position: Int, payloads: MutableList<Any>?) {
|
||||
holder.bind(lesson)
|
||||
}
|
||||
|
||||
class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter),
|
||||
LayoutContainer {
|
||||
|
||||
override val containerView: View
|
||||
get() = contentView
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bind(lesson: Timetable) {
|
||||
timetableItemNumber.text = lesson.number.toString()
|
||||
timetableItemSubject.text = lesson.subject
|
||||
timetableItemRoom.text = if (lesson.room.isNotBlank()) "${view.context.getString(R.string.timetable_room)} ${lesson.room}" else ""
|
||||
timetableItemTime.text = "${lesson.start.toFormattedString("HH:mm")} - ${lesson.end.toFormattedString("HH:mm")}"
|
||||
timetableItemAlert.visibility = if (lesson.changes || lesson.canceled) VISIBLE else GONE
|
||||
timetableItemSubject.paintFlags =
|
||||
if (lesson.canceled) timetableItemSubject.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
||||
else timetableItemSubject.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package io.github.wulkanowy.ui.main.timetable
|
||||
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.data.ErrorHandler
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class TimetablePresenter @Inject constructor(
|
||||
private val errorHandler: ErrorHandler,
|
||||
private val schedulers: SchedulersManager,
|
||||
private val timetableRepository: TimetableRepository,
|
||||
private val sessionRepository: SessionRepository
|
||||
) : BasePresenter<TimetableView>(errorHandler) {
|
||||
|
||||
var currentDate: LocalDate = LocalDate.now().nearSchoolDayNextOnWeekEnd
|
||||
private set
|
||||
|
||||
override fun attachView(view: TimetableView) {
|
||||
super.attachView(view)
|
||||
view.initView()
|
||||
}
|
||||
|
||||
fun loadTimetableForPreviousDay() = loadData(currentDate.previousWorkDay.toEpochDay())
|
||||
|
||||
fun loadTimetableForNextDay() = loadData(currentDate.nextWorkDay.toEpochDay())
|
||||
|
||||
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
||||
this.currentDate = LocalDate.ofEpochDay(date ?: currentDate.nearSchoolDayNextOnWeekEnd.toEpochDay())
|
||||
if (currentDate.isHolidays) return
|
||||
|
||||
disposable.clear()
|
||||
disposable.add(sessionRepository.getSemesters()
|
||||
.map { selectSemester(it, -1) }
|
||||
.flatMap { timetableRepository.getTimetable(it, currentDate, currentDate, forceRefresh) }
|
||||
.map { createTimetableItems(it) }
|
||||
.subscribeOn(schedulers.backgroundThread())
|
||||
.observeOn(schedulers.mainThread())
|
||||
.doOnSubscribe {
|
||||
view?.run {
|
||||
showRefresh(forceRefresh)
|
||||
showProgress(!forceRefresh)
|
||||
if (!forceRefresh) clearData()
|
||||
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||
updateNavigationDay(currentDate.toFormattedString("EEEE \n dd.MM.YYYY").capitalize())
|
||||
}
|
||||
}
|
||||
.doFinally {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
view?.run {
|
||||
showEmpty(it.isEmpty())
|
||||
showContent(it.isNotEmpty())
|
||||
updateData(it)
|
||||
}
|
||||
}) {
|
||||
view?.run { showEmpty(isViewEmpty()) }
|
||||
errorHandler.proceed(it)
|
||||
})
|
||||
}
|
||||
|
||||
private fun createTimetableItems(items: List<Timetable>): List<TimetableItem> {
|
||||
return items.map {
|
||||
TimetableItem().apply { lesson = it }
|
||||
}
|
||||
}
|
||||
|
||||
fun onTimetableItemSelected(item: AbstractFlexibleItem<*>?) {
|
||||
if (item is TimetableItem) view?.showTimetableDialog(item.lesson)
|
||||
}
|
||||
|
||||
private fun selectSemester(semesters: List<Semester>, index: Int): Semester {
|
||||
return semesters.single { it.current }.let { currentSemester ->
|
||||
if (index == -1) currentSemester
|
||||
else semesters.single { semester ->
|
||||
semester.run {
|
||||
semesterName - 1 == index && diaryId == currentSemester.diaryId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package io.github.wulkanowy.ui.main.timetable
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface TimetableView : BaseView {
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<TimetableItem>)
|
||||
|
||||
fun updateNavigationDay(date: String)
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showPreButton(show: Boolean)
|
||||
|
||||
fun showNextButton(show: Boolean)
|
||||
|
||||
fun showTimetableDialog(lesson: Timetable)
|
||||
|
||||
fun isViewEmpty(): Boolean
|
||||
fun clearData()
|
||||
}
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.utils
|
||||
|
||||
import org.threeten.bp.DayOfWeek.*
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import org.threeten.bp.format.DateTimeFormatter
|
||||
import org.threeten.bp.format.DateTimeFormatter.ofPattern
|
||||
import org.threeten.bp.temporal.TemporalAdjusters
|
||||
@ -15,13 +16,16 @@ fun Date.toLocalDate(): LocalDate {
|
||||
return LocalDate.parse(SimpleDateFormat(DATE_PATTERN, Locale.getDefault()).format(this))
|
||||
}
|
||||
|
||||
fun Date.toLocalDateTime(): LocalDateTime = LocalDateTime.parse(SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
|
||||
Locale.getDefault()).format(this), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
|
||||
|
||||
fun String.toLocalDate(format: String = DATE_PATTERN): LocalDate {
|
||||
return LocalDate.parse(this, DateTimeFormatter.ofPattern(format))
|
||||
}
|
||||
|
||||
fun LocalDate.toFormattedString(format: String): String = this.format(ofPattern(format))
|
||||
fun LocalDate.toFormattedString(format: String = DATE_PATTERN): String = this.format(ofPattern(format))
|
||||
|
||||
fun LocalDate.toFormattedString(): String = this.toFormattedString(DATE_PATTERN)
|
||||
fun LocalDateTime.toFormattedString(format: String = DATE_PATTERN): String = this.format(DateTimeFormatter.ofPattern(format))
|
||||
|
||||
inline val LocalDate.nextWorkDay: LocalDate
|
||||
get() {
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@ -8,56 +7,21 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="300dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/timetable_dialog_relative_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingLeft="20dp"
|
||||
android:paddingRight="20dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="10dp"
|
||||
tools:ignore="UselessParent">
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_details"
|
||||
android:id="@+id/timetableDialogChangesTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_gravity="start"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="5"
|
||||
android:minHeight="60dp"
|
||||
android:minLines="2"
|
||||
android:paddingTop="10dp"
|
||||
android:text="@string/all_details"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_details"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/timetable_changes"
|
||||
android:textColor="@color/colorPrimary"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_description_value"
|
||||
android:id="@+id/timetableDialogChanges"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_description"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textColor="@color/colorPrimary"
|
||||
@ -65,137 +29,100 @@
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_lesson"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_description_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/timetable_lesson"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_lesson_value"
|
||||
android:id="@+id/timetableDialogSubject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_lesson"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_teacher"
|
||||
android:id="@+id/timetableDialogTeacherTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_lesson_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/all_teacher"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_teacher_value"
|
||||
android:id="@+id/timetableDialogTeacher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_teacher"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_group"
|
||||
android:id="@+id/timetableDialogGroupTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_teacher_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/timetable_group"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_group_value"
|
||||
android:id="@+id/timetableDialogGroup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_group"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_room"
|
||||
android:id="@+id/timetableDialogRoomTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_group_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/timetable_room"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_room_value"
|
||||
android:id="@+id/timetableDialogRoom"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@id/timetable_dialog_room"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_room_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/timetable_time"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_dialog_time_value"
|
||||
android:id="@+id/timetableDialogTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/timetable_dialog_time"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/timetable_dialog_close"
|
||||
android:id="@+id/timetableDialogClose"
|
||||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignTop="@+id/timetable_dialog_time_value"
|
||||
android:layout_marginTop="25dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:focusable="true"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="15dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/all_close"
|
||||
android:textColor="?android:attr/android:textColorSecondary"
|
||||
android:textAllCaps="true"
|
||||
android:textSize="15sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
@ -1,12 +1,99 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/timetable_fragment_container"
|
||||
<LinearLayout 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:layout_alignParentBottom="true">
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/timetableProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true" />
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/timetableSwipe"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/timetableRecycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/timetableEmpty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="Timetable" />
|
||||
</FrameLayout>
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="100dp"
|
||||
android:minWidth="100dp"
|
||||
app:srcCompat="@drawable/ic_menu_main_timetable_24dp"
|
||||
app:tint="?android:attr/textColorPrimary"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/timetable_no_items"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/timetablePreviousButton"
|
||||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="start|center"
|
||||
android:text="@string/prev"
|
||||
android:textAlignment="gravity" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableNavDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/timetableNextButton"
|
||||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="end|center"
|
||||
android:text="@string/next"
|
||||
android:textAlignment="gravity" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -1,73 +0,0 @@
|
||||
<android.support.design.widget.CoordinatorLayout 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/timetable_tab_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="io.github.wulkanowy.ui.main.grades.GradesFragment">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/timetable_tab_fragment_progress_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/timetable_tab_fragment_no_item_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/timetable_tab_fragment_no_item_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/timetable_tab_fragment_no_item_text"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="40dp"
|
||||
android:minHeight="100dp"
|
||||
android:minWidth="100dp"
|
||||
app:srcCompat="@drawable/ic_menu_main_timetable_24dp"
|
||||
app:tint="?android:attr/textColorPrimary"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_tab_fragment_no_item_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="46dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/timetable_no_items"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_tab_fragment_no_item_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/timetable_tab_fragment_no_item_image"
|
||||
android:layout_marginTop="15dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="20sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/timetable_tab_fragment_swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/timetable_tab_fragment_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
@ -1,30 +1,19 @@
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tool="http://schemas.android.com/tools"
|
||||
android:id="@+id/timetable_subItem_cardView"
|
||||
android:id="@+id/timetable_subitem_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="7dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
card_view:cardElevation="0dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="7dp"
|
||||
android:layout_marginEnd="7dp"
|
||||
android:layout_marginLeft="7dp"
|
||||
android:layout_marginRight="7dp"
|
||||
android:layout_marginStart="7dp"
|
||||
android:layout_marginTop="7dp">
|
||||
android:paddingBottom="7dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="7dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_subItem_number_of_lesson"
|
||||
android:id="@+id/timetableItemNumber"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_centerVertical="true"
|
||||
@ -32,10 +21,10 @@
|
||||
android:maxLength="2"
|
||||
android:text="0"
|
||||
android:textSize="32sp"
|
||||
tool:ignore="all"/>
|
||||
tool:ignore="all" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_subItem_lesson"
|
||||
android:id="@+id/timetableItemSubject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
@ -43,52 +32,51 @@
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="40dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@+id/timetable_subItem_number_of_lesson"
|
||||
android:layout_toRightOf="@+id/timetable_subItem_number_of_lesson"
|
||||
android:layout_toEndOf="@+id/timetableItemNumber"
|
||||
android:layout_toRightOf="@+id/timetableItemNumber"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="17sp"
|
||||
tool:ignore="all"/>
|
||||
tool:ignore="RelativeOverlap" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_subItem_time"
|
||||
android:id="@+id/timetableItemTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/timetable_subItem_number_of_lesson"
|
||||
android:layout_alignLeft="@id/timetable_subItem_lesson"
|
||||
android:layout_alignStart="@id/timetable_subItem_lesson"
|
||||
android:layout_alignBottom="@+id/timetableItemNumber"
|
||||
android:layout_alignLeft="@id/timetableItemSubject"
|
||||
android:layout_alignStart="@id/timetableItemSubject"
|
||||
android:maxLines="1"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="?android:attr/android:textColorSecondary"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetable_subItem_room"
|
||||
android:id="@+id/timetableItemRoom"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/timetable_subItem_number_of_lesson"
|
||||
android:layout_alignBottom="@+id/timetableItemNumber"
|
||||
android:layout_marginEnd="40dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="40dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@+id/timetable_subItem_time"
|
||||
android:layout_toRightOf="@+id/timetable_subItem_time"
|
||||
android:layout_toEndOf="@+id/timetableItemTime"
|
||||
android:layout_toRightOf="@+id/timetableItemTime"
|
||||
android:maxLines="1"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="?android:attr/android:textColorSecondary"
|
||||
android:textSize="12sp"
|
||||
tool:ignore="all"/>
|
||||
tool:ignore="RelativeOverlap" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/timetable_subItem_alert_image"
|
||||
android:id="@+id/timetableItemAlert"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="10dp"
|
||||
app:srcCompat="@drawable/ic_timetable_swap_30dp"
|
||||
tool:ignore="contentDescription"/>
|
||||
tool:ignore="contentDescription" />
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.v7.widget.CardView>
|
||||
</RelativeLayout>
|
||||
|
@ -63,11 +63,11 @@
|
||||
|
||||
<!--Timetable-->
|
||||
<string name="timetable_lesson">Lekcja</string>
|
||||
<string name="timetable_room">Sala %s</string>
|
||||
<string name="timetable_room">Sala</string>
|
||||
<string name="timetable_group">Grupa</string>
|
||||
<string name="timetable_time">Godziny</string>
|
||||
<string name="timetable_changes">Zmiany</string>
|
||||
<string name="timetable_no_items">Brak lekcji w tym tygodniu</string>
|
||||
<string name="timetable_no_items">Brak lekcji w tym dniu</string>
|
||||
|
||||
|
||||
<!--Attendance-->
|
||||
|
@ -63,7 +63,7 @@
|
||||
<string name="timetable_group">Group</string>
|
||||
<string name="timetable_time">Hours</string>
|
||||
<string name="timetable_changes">Changes</string>
|
||||
<string name="timetable_no_items">No lesson in this week</string>
|
||||
<string name="timetable_no_items">No lesson in this day</string>
|
||||
|
||||
|
||||
<!--Attendance-->
|
||||
|
@ -0,0 +1,54 @@
|
||||
package io.github.wulkanowy.data.repositories.remote
|
||||
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.api.timetable.Timetable
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.reactivex.Single
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.sql.Date
|
||||
|
||||
class TimetableRemoteTest {
|
||||
|
||||
@MockK
|
||||
private lateinit var mockApi: Api
|
||||
|
||||
@MockK
|
||||
private lateinit var semesterMock: Semester
|
||||
|
||||
@Before
|
||||
fun initApi() {
|
||||
MockKAnnotations.init(this)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getExamsTest() {
|
||||
every { mockApi.getTimetable(
|
||||
LocalDate.of(2018, 9, 10),
|
||||
LocalDate.of(2018, 9, 15)
|
||||
) } returns Single.just(listOf(
|
||||
getTimetable("2018-09-10"),
|
||||
getTimetable("2018-09-17")
|
||||
))
|
||||
|
||||
every { mockApi.diaryId } returns "1"
|
||||
every { semesterMock.studentId } returns "1"
|
||||
every { semesterMock.diaryId } returns "1"
|
||||
|
||||
val timetable = TimetableRemote(mockApi).getLessons(semesterMock,
|
||||
LocalDate.of(2018, 9, 10),
|
||||
LocalDate.of(2018, 9, 15)
|
||||
).blockingGet()
|
||||
assertEquals(2, timetable.size)
|
||||
}
|
||||
|
||||
private fun getTimetable(dateString: String): Timetable {
|
||||
return Timetable(date = Date.valueOf(dateString))
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.utils
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.util.*
|
||||
|
||||
class TimeExtensionTest {
|
||||
@ -18,6 +19,12 @@ class TimeExtensionTest {
|
||||
assertEquals("2018-10.01", LocalDate.of(2018, 10, 1).toFormattedString("yyyy-MM.dd"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toFormat_LocalDateTime() {
|
||||
assertEquals("2018-10-01", LocalDateTime.of(2018, 10, 1, 10, 0, 0).toFormattedString())
|
||||
assertEquals("2018-10-01 10:00:00", LocalDateTime.of(2018, 10, 1, 10, 0, 0).toFormattedString("uuuu-MM-dd HH:mm:ss"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun weekFirstDayAlwaysCurrentTest() {
|
||||
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 2).weekFirstDayAlwaysCurrent)
|
||||
|
@ -10,7 +10,7 @@ buildscript {
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'com.android.tools.build:gradle:3.2.0'
|
||||
classpath "io.fabric.tools:gradle:1.25.4"
|
||||
classpath "io.fabric.tools:gradle:1.26.0"
|
||||
classpath "com.google.gms:oss-licenses:0.9.2"
|
||||
classpath "com.github.triplet.gradle:play-publisher:1.2.2"
|
||||
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2"
|
||||
|
1
gradle/wrapper/gradle-wrapper.properties
vendored
1
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,4 +1,3 @@
|
||||
#Mon Sep 24 22:45:58 CEST 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
Loading…
x
Reference in New Issue
Block a user