mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-02-21 19:54:44 +01:00
Refactor grade module (#156)
This commit is contained in:
parent
357b2350cb
commit
f2b7c0e781
@ -1,15 +1,15 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-kapt'// sync warning probably caused by bug https://issuetracker.google.com/issues/74537216, fix in AS 3.2
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
apply plugin: 'kotlin-android-extensions'
|
||||||
apply plugin: 'io.fabric'
|
apply plugin: 'io.fabric'
|
||||||
|
apply plugin: 'com.github.triplet.play'
|
||||||
apply from: 'jacoco.gradle'
|
apply from: 'jacoco.gradle'
|
||||||
apply from: 'sonarqube.gradle'
|
apply from: 'sonarqube.gradle'
|
||||||
apply plugin: 'com.github.triplet.play'
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
buildToolsVersion '28.0.2'
|
buildToolsVersion '28.0.3'
|
||||||
|
|
||||||
playAccountConfigs {
|
playAccountConfigs {
|
||||||
defaultAccountConfig {
|
defaultAccountConfig {
|
||||||
@ -75,13 +75,15 @@ dependencies {
|
|||||||
implementation('com.github.wulkanowy:api:07201a4') {
|
implementation('com.github.wulkanowy:api:07201a4') {
|
||||||
exclude module: "threetenbp"
|
exclude module: "threetenbp"
|
||||||
}
|
}
|
||||||
|
|
||||||
implementation "com.android.support:support-v4:$supportVersion"
|
implementation "com.android.support:support-v4:$supportVersion"
|
||||||
|
implementation "com.android.support:appcompat-v7:$supportVersion"
|
||||||
implementation "com.android.support:design:$supportVersion"
|
implementation "com.android.support:design:$supportVersion"
|
||||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||||
implementation "com.android.support:preference-v14:$supportVersion"
|
implementation "com.android.support:preference-v14:$supportVersion"
|
||||||
implementation 'com.android.support:multidex:1.0.3'
|
implementation 'com.android.support:multidex:1.0.3'
|
||||||
|
|
||||||
implementation "com.google.android.gms:play-services-oss-licenses:16.0.0"
|
implementation "com.google.android.gms:play-services-oss-licenses:16.0.1"
|
||||||
implementation "com.firebase:firebase-jobdispatcher:0.8.5"
|
implementation "com.firebase:firebase-jobdispatcher:0.8.5"
|
||||||
|
|
||||||
implementation "com.google.dagger:dagger-android-support:2.17"
|
implementation "com.google.dagger:dagger-android-support:2.17"
|
||||||
@ -92,7 +94,7 @@ dependencies {
|
|||||||
implementation "android.arch.persistence.room:rxjava2:1.1.1"
|
implementation "android.arch.persistence.room:rxjava2:1.1.1"
|
||||||
kapt "android.arch.persistence.room:compiler:1.1.1"
|
kapt "android.arch.persistence.room:compiler:1.1.1"
|
||||||
|
|
||||||
implementation "eu.davidea:flexible-adapter:5.0.5"
|
implementation "eu.davidea:flexible-adapter:5.0.6"
|
||||||
implementation "eu.davidea:flexible-adapter-ui:1.0.0-b5"
|
implementation "eu.davidea:flexible-adapter-ui:1.0.0-b5"
|
||||||
implementation "com.aurelhubert:ahbottomnavigation:2.2.0"
|
implementation "com.aurelhubert:ahbottomnavigation:2.2.0"
|
||||||
implementation 'com.ncapdevi:frag-nav:3.0.0-RC3'
|
implementation 'com.ncapdevi:frag-nav:3.0.0-RC3'
|
||||||
@ -101,8 +103,6 @@ dependencies {
|
|||||||
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
|
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
|
||||||
implementation "io.reactivex.rxjava2:rxjava:2.2.1"
|
implementation "io.reactivex.rxjava2:rxjava:2.2.1"
|
||||||
|
|
||||||
implementation "org.apache.commons:commons-lang3:3.8"
|
|
||||||
implementation "org.apache.commons:commons-collections4:4.2"
|
|
||||||
implementation "com.jakewharton.threetenabp:threetenabp:1.1.0"
|
implementation "com.jakewharton.threetenabp:threetenabp:1.1.0"
|
||||||
|
|
||||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
implementation "com.jakewharton.timber:timber:4.7.1"
|
||||||
|
@ -34,13 +34,13 @@ class AttendanceLocalTest {
|
|||||||
@Test
|
@Test
|
||||||
fun saveAndReadTest() {
|
fun saveAndReadTest() {
|
||||||
attendanceLocal.saveAttendance(listOf(
|
attendanceLocal.saveAttendance(listOf(
|
||||||
Attendance(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 10)),
|
Attendance(0, "1", "2", LocalDate.of(2018, 9, 10), 0, "", ""),
|
||||||
Attendance(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 14)),
|
Attendance(0, "1", "2", LocalDate.of(2018, 9, 14), 0, "", ""),
|
||||||
Attendance(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 17)) // in next week
|
Attendance(0, "1", "2", LocalDate.of(2018, 9, 17), 0, "", "")
|
||||||
))
|
))
|
||||||
|
|
||||||
val attendance = attendanceLocal
|
val attendance = attendanceLocal
|
||||||
.getAttendance(Semester(studentId = "1", diaryId = "2", semesterId = "3"),
|
.getAttendance(Semester(1, "1", "2", "", "3", 1),
|
||||||
LocalDate.of(2018, 9, 10),
|
LocalDate.of(2018, 9, 10),
|
||||||
LocalDate.of(2018, 9, 14)
|
LocalDate.of(2018, 9, 14)
|
||||||
)
|
)
|
||||||
|
@ -34,13 +34,13 @@ class ExamLocalTest {
|
|||||||
@Test
|
@Test
|
||||||
fun saveAndReadTest() {
|
fun saveAndReadTest() {
|
||||||
examLocal.saveExams(listOf(
|
examLocal.saveExams(listOf(
|
||||||
Exam(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 10)),
|
Exam(0, "1", "2", LocalDate.of(2018, 9, 10), LocalDate.now(), "", "", "", "", "", ""),
|
||||||
Exam(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 14)),
|
Exam(0, "1", "2", LocalDate.of(2018, 9, 14), LocalDate.now(), "", "", "", "", "", ""),
|
||||||
Exam(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 17)) // in next week
|
Exam(0, "1", "2", LocalDate.of(2018, 9, 17), LocalDate.now(), "", "", "", "", "", "")
|
||||||
))
|
))
|
||||||
|
|
||||||
val exams = examLocal
|
val exams = examLocal
|
||||||
.getExams(Semester(studentId = "1", diaryId = "2", semesterId = "3"),
|
.getExams(Semester(1, "1", "2", "", "3", 1),
|
||||||
LocalDate.of(2018, 9, 10),
|
LocalDate.of(2018, 9, 10),
|
||||||
LocalDate.of(2018, 9, 14)
|
LocalDate.of(2018, 9, 14)
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,7 @@ import kotlin.test.assertEquals
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class SessionLocalTest {
|
class SessionLocalTest {
|
||||||
|
|
||||||
private lateinit var studentLocal: SessionLocal
|
private lateinit var sessionLocal: SessionLocal
|
||||||
|
|
||||||
private lateinit var testDb: AppDatabase
|
private lateinit var testDb: AppDatabase
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ class SessionLocalTest {
|
|||||||
testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
|
testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
|
||||||
.build()
|
.build()
|
||||||
sharedHelper = SharedPrefHelper(context.getSharedPreferences("TEST", Context.MODE_PRIVATE))
|
sharedHelper = SharedPrefHelper(context.getSharedPreferences("TEST", Context.MODE_PRIVATE))
|
||||||
studentLocal = SessionLocal(testDb.studentDao(), testDb.semesterDao(), sharedHelper, context)
|
sessionLocal = SessionLocal(testDb.studentDao(), testDb.semesterDao(), sharedHelper, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -38,12 +38,12 @@ class SessionLocalTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun saveAndReadTest() {
|
fun saveAndReadTest() {
|
||||||
studentLocal.saveStudent(Student(email = "test", password = "test123", schoolId = "23")).blockingAwait()
|
sessionLocal.saveStudent(Student(email = "test", password = "test123", schoolId = "23")).blockingAwait()
|
||||||
assert(sharedHelper.getLong(SessionLocal.LAST_USER_KEY, 0) == 1L)
|
assert(sharedHelper.getLong(SessionLocal.LAST_USER_KEY, 0) == 1L)
|
||||||
|
|
||||||
assert(studentLocal.isSessionSaved)
|
assert(sessionLocal.isSessionSaved)
|
||||||
|
|
||||||
val student = studentLocal.getLastStudent().blockingGet()
|
val student = sessionLocal.getLastStudent().blockingGet()
|
||||||
assertEquals("23", student.schoolId)
|
assertEquals("23", student.schoolId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
package="io.github.wulkanowy"
|
package="io.github.wulkanowy"
|
||||||
android:installLocation="internalOnly">
|
android:installLocation="internalOnly">
|
||||||
|
|
||||||
@ -15,13 +14,11 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:theme="@style/WulkanowyTheme"
|
android:theme="@style/WulkanowyTheme"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true">
|
||||||
tools:targetApi="m">
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.splash.SplashActivity"
|
android:name=".ui.splash.SplashActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:screenOrientation="portrait"
|
||||||
android:noHistory="true"
|
android:theme="@style/WulkanowyTheme.SplashScreen">
|
||||||
android:theme="@style/WulkanowyTheme.SplashTheme">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
@ -32,39 +29,13 @@
|
|||||||
android:name=".ui.login.LoginActivity"
|
android:name=".ui.login.LoginActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:label="@string/login_title"
|
android:label="@string/login_title"
|
||||||
android:theme="@style/WulkanowyTheme.DarkActionBar"
|
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.main.MainActivity"
|
android:name=".ui.main.MainActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:label="@string/main_title"
|
android:label="@string/main_title"
|
||||||
android:launchMode="singleTop" />
|
android:launchMode="singleTop"
|
||||||
<activity
|
android:theme="@style/WulkanowyTheme.NoActionBar" />
|
||||||
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
|
|
||||||
android:theme="@style/WulkanowyTheme.DarkActionBar" />
|
|
||||||
<activity
|
|
||||||
android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
|
|
||||||
android:theme="@style/WulkanowyTheme.DarkActionBar" />
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".services.jobs.SyncJob"
|
|
||||||
android:exported="false">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
|
|
||||||
</intent-filter>
|
|
||||||
</service>
|
|
||||||
<service
|
|
||||||
android:name=".services.widgets.TimetableWidgetServices"
|
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
|
||||||
|
|
||||||
<receiver android:name=".ui.widgets.TimetableWidgetProvider">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
|
||||||
</intent-filter>
|
|
||||||
<meta-data
|
|
||||||
android:name="android.appwidget.provider"
|
|
||||||
android:resource="@xml/provider_widget_timetable" />
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.fabric.ApiKey"
|
android:name="io.fabric.ApiKey"
|
||||||
|
@ -9,9 +9,12 @@ import com.jakewharton.threetenabp.AndroidThreeTen
|
|||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import dagger.android.support.DaggerApplication
|
import dagger.android.support.DaggerApplication
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.utils.Log
|
||||||
import io.fabric.sdk.android.Fabric
|
import io.fabric.sdk.android.Fabric
|
||||||
|
import io.github.wulkanowy.BuildConfig.DEBUG
|
||||||
import io.github.wulkanowy.di.DaggerAppComponent
|
import io.github.wulkanowy.di.DaggerAppComponent
|
||||||
import io.github.wulkanowy.utils.LoggerUtils
|
import io.github.wulkanowy.utils.CrashlyticsTree
|
||||||
|
import io.github.wulkanowy.utils.DebugLogTree
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class WulkanowyApp : DaggerApplication() {
|
class WulkanowyApp : DaggerApplication() {
|
||||||
@ -24,31 +27,27 @@ class WulkanowyApp : DaggerApplication() {
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
AndroidThreeTen.init(this)
|
AndroidThreeTen.init(this)
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
enableDebugLog()
|
|
||||||
}
|
|
||||||
initializeFabric()
|
initializeFabric()
|
||||||
|
if (DEBUG) enableDebugLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun enableDebugLog() {
|
private fun enableDebugLog() {
|
||||||
FlexibleAdapter.enableLogs(eu.davidea.flexibleadapter.utils.Log.Level.DEBUG)
|
Timber.plant(DebugLogTree)
|
||||||
Timber.plant(LoggerUtils.DebugLogTree())
|
FlexibleAdapter.enableLogs(Log.Level.DEBUG)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initializeFabric() {
|
private fun initializeFabric() {
|
||||||
Fabric.with(Fabric.Builder(this)
|
Fabric.with(Fabric.Builder(this)
|
||||||
.kits(
|
.kits(Crashlytics.Builder()
|
||||||
Crashlytics.Builder()
|
.core(CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
|
||||||
.core(CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
|
.build(),
|
||||||
.build(),
|
Answers())
|
||||||
Answers()
|
|
||||||
)
|
|
||||||
.debuggable(BuildConfig.DEBUG)
|
.debuggable(BuildConfig.DEBUG)
|
||||||
.build())
|
.build())
|
||||||
Timber.plant(LoggerUtils.CrashlyticsTree())
|
Timber.plant(CrashlyticsTree)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applicationInjector(): AndroidInjector<out DaggerApplication> =
|
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
|
||||||
DaggerAppComponent.builder().create(this)
|
return DaggerAppComponent.builder().create(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
package io.github.wulkanowy.data
|
package io.github.wulkanowy.data
|
||||||
|
|
||||||
import android.arch.persistence.room.Room
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.support.v7.preference.PreferenceManager
|
import android.support.v7.preference.PreferenceManager
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.SocketInternetObservingStrategy
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import io.github.wulkanowy.api.Api
|
import io.github.wulkanowy.api.Api
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.utils.DATABASE_NAME
|
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@ -18,7 +17,10 @@ internal class RepositoryModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideInternetObservingSettings(): InternetObservingSettings {
|
fun provideInternetObservingSettings(): InternetObservingSettings {
|
||||||
return InternetObservingSettings.create()
|
return InternetObservingSettings
|
||||||
|
.strategy(SocketInternetObservingStrategy())
|
||||||
|
.host("www.google.com")
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -27,10 +29,7 @@ internal class RepositoryModule {
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideDatabase(context: Context): AppDatabase {
|
fun provideDatabase(context: Context) = AppDatabase.newInstance(context)
|
||||||
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun provideErrorHandler(context: Context) = ErrorHandler(context.resources)
|
fun provideErrorHandler(context: Context) = ErrorHandler(context.resources)
|
||||||
@ -49,6 +48,14 @@ internal class RepositoryModule {
|
|||||||
@Provides
|
@Provides
|
||||||
fun provideSemesterDao(database: AppDatabase) = database.semesterDao()
|
fun provideSemesterDao(database: AppDatabase) = database.semesterDao()
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideGradeDao(database: AppDatabase) = database.gradeDao()
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideGradeSummaryDao(database: AppDatabase) = database.gradeSummaryDao()
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideExamDao(database: AppDatabase) = database.examsDao()
|
fun provideExamDao(database: AppDatabase) = database.examsDao()
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
package io.github.wulkanowy.data.db
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import android.arch.persistence.room.Database
|
import android.arch.persistence.room.Database
|
||||||
|
import android.arch.persistence.room.Room
|
||||||
import android.arch.persistence.room.RoomDatabase
|
import android.arch.persistence.room.RoomDatabase
|
||||||
import android.arch.persistence.room.TypeConverters
|
import android.arch.persistence.room.TypeConverters
|
||||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
import android.content.Context
|
||||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
import io.github.wulkanowy.data.db.dao.*
|
||||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
import io.github.wulkanowy.data.db.entities.*
|
||||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -19,7 +15,9 @@ import javax.inject.Singleton
|
|||||||
Student::class,
|
Student::class,
|
||||||
Semester::class,
|
Semester::class,
|
||||||
Exam::class,
|
Exam::class,
|
||||||
Attendance::class
|
Attendance::class,
|
||||||
|
Grade::class,
|
||||||
|
GradeSummary::class
|
||||||
],
|
],
|
||||||
version = 1,
|
version = 1,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
@ -27,6 +25,13 @@ import javax.inject.Singleton
|
|||||||
@TypeConverters(Converters::class)
|
@TypeConverters(Converters::class)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance(context: Context): AppDatabase {
|
||||||
|
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abstract fun studentDao(): StudentDao
|
abstract fun studentDao(): StudentDao
|
||||||
|
|
||||||
abstract fun semesterDao(): SemesterDao
|
abstract fun semesterDao(): SemesterDao
|
||||||
@ -34,4 +39,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
abstract fun examsDao(): ExamDao
|
abstract fun examsDao(): ExamDao
|
||||||
|
|
||||||
abstract fun attendanceDao(): AttendanceDao
|
abstract fun attendanceDao(): AttendanceDao
|
||||||
|
|
||||||
|
abstract fun gradeDao(): GradeDao
|
||||||
|
|
||||||
|
abstract fun gradeSummaryDao(): GradeSummaryDao
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import android.arch.persistence.room.*
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface GradeDao {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insertAll(grades: List<Grade>)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(grade: Grade)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun deleteAll(grades: List<Grade>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
|
||||||
|
fun getGrades(semesterId: String, studentId: String): Maybe<List<Grade>>
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import android.arch.persistence.room.Dao
|
||||||
|
import android.arch.persistence.room.Insert
|
||||||
|
import android.arch.persistence.room.OnConflictStrategy.REPLACE
|
||||||
|
import android.arch.persistence.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface GradeSummaryDao {
|
||||||
|
|
||||||
|
@Insert(onConflict = REPLACE)
|
||||||
|
fun insertAll(gradesSummary: List<GradeSummary>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM grades_summary WHERE student_id = :studentId AND semester_id = :semesterId")
|
||||||
|
fun getGradesSummary(semesterId: String, studentId: String): Maybe<List<GradeSummary>>
|
||||||
|
}
|
@ -13,18 +13,18 @@ data class Attendance(
|
|||||||
var id: Long = 0,
|
var id: Long = 0,
|
||||||
|
|
||||||
@ColumnInfo(name = "student_id")
|
@ColumnInfo(name = "student_id")
|
||||||
var studentId: String = "",
|
var studentId: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "diary_id")
|
@ColumnInfo(name = "diary_id")
|
||||||
var diaryId: String = "",
|
var diaryId: String,
|
||||||
|
|
||||||
var date: LocalDate,
|
var date: LocalDate,
|
||||||
|
|
||||||
var number: Int = 0,
|
var number: Int,
|
||||||
|
|
||||||
var subject: String = "",
|
var subject: String,
|
||||||
|
|
||||||
var name: String = "",
|
var name: String,
|
||||||
|
|
||||||
var presence: Boolean = false,
|
var presence: Boolean = false,
|
||||||
|
|
||||||
|
@ -13,26 +13,26 @@ data class Exam(
|
|||||||
var id: Long = 0,
|
var id: Long = 0,
|
||||||
|
|
||||||
@ColumnInfo(name = "student_id")
|
@ColumnInfo(name = "student_id")
|
||||||
var studentId: String = "",
|
var studentId: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "diary_id")
|
@ColumnInfo(name = "diary_id")
|
||||||
var diaryId: String = "",
|
var diaryId: String,
|
||||||
|
|
||||||
var date: LocalDate,
|
var date: LocalDate,
|
||||||
|
|
||||||
@ColumnInfo(name = "entry_date")
|
@ColumnInfo(name = "entry_date")
|
||||||
var entryDate: LocalDate = LocalDate.now(),
|
var entryDate: LocalDate = LocalDate.now(),
|
||||||
|
|
||||||
var subject: String = "",
|
var subject: String,
|
||||||
|
|
||||||
var group: String = "",
|
var group: String,
|
||||||
|
|
||||||
var type: String = "",
|
var type: String,
|
||||||
|
|
||||||
var description: String = "",
|
var description: String,
|
||||||
|
|
||||||
var teacher: String = "",
|
var teacher: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "teacher_symbol")
|
@ColumnInfo(name = "teacher_symbol")
|
||||||
var teacherSymbol: String = ""
|
var teacherSymbol: String
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
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 java.io.Serializable
|
||||||
|
|
||||||
|
@Entity(tableName = "Grades")
|
||||||
|
data class Grade(
|
||||||
|
|
||||||
|
@ColumnInfo(name = "semester_id")
|
||||||
|
var semesterId: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
var studentId: String,
|
||||||
|
|
||||||
|
var subject: String,
|
||||||
|
|
||||||
|
var entry: String,
|
||||||
|
|
||||||
|
var value: Int,
|
||||||
|
|
||||||
|
var modifier: Double,
|
||||||
|
|
||||||
|
var comment: String,
|
||||||
|
|
||||||
|
var color: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "grade_symbol")
|
||||||
|
var gradeSymbol: String,
|
||||||
|
|
||||||
|
var description: String,
|
||||||
|
|
||||||
|
var weight: String,
|
||||||
|
|
||||||
|
var weightValue: Int,
|
||||||
|
|
||||||
|
var date: LocalDate,
|
||||||
|
|
||||||
|
var teacher: String
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0
|
||||||
|
|
||||||
|
@ColumnInfo(name = "is_new")
|
||||||
|
var isNew: Boolean = false
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import android.arch.persistence.room.ColumnInfo
|
||||||
|
import android.arch.persistence.room.Entity
|
||||||
|
import android.arch.persistence.room.Index
|
||||||
|
import android.arch.persistence.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "Grades_Summary",
|
||||||
|
indices = [Index(value = ["semester_id", "student_id", "subject"], unique = true)])
|
||||||
|
data class GradeSummary(
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "semester_id")
|
||||||
|
var semesterId: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
var studentId: String,
|
||||||
|
|
||||||
|
var subject: String,
|
||||||
|
|
||||||
|
var predictedGrade: String,
|
||||||
|
|
||||||
|
var finalGrade: String
|
||||||
|
)
|
@ -19,13 +19,13 @@ data class Semester(
|
|||||||
var diaryId: String,
|
var diaryId: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "diary_name")
|
@ColumnInfo(name = "diary_name")
|
||||||
var diaryName: String = "",
|
var diaryName: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "semester_id")
|
@ColumnInfo(name = "semester_id")
|
||||||
var semesterId: String,
|
var semesterId: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "semester_name")
|
@ColumnInfo(name = "semester_name")
|
||||||
var semesterName: Int = 0,
|
var semesterName: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "is_current")
|
@ColumnInfo(name = "is_current")
|
||||||
var current: Boolean = false
|
var current: Boolean = false
|
||||||
|
@ -6,7 +6,7 @@ import io.github.wulkanowy.data.db.entities.Attendance
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.repositories.local.AttendanceLocal
|
import io.github.wulkanowy.data.repositories.local.AttendanceLocal
|
||||||
import io.github.wulkanowy.data.repositories.remote.AttendanceRemote
|
import io.github.wulkanowy.data.repositories.remote.AttendanceRemote
|
||||||
import io.github.wulkanowy.utils.extension.getWeekFirstDayAlwaysCurrent
|
import io.github.wulkanowy.utils.weekFirstDayAlwaysCurrent
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import org.threeten.bp.DayOfWeek
|
import org.threeten.bp.DayOfWeek
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
@ -21,7 +21,7 @@ class AttendanceRepository @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false): Single<List<Attendance>> {
|
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false): Single<List<Attendance>> {
|
||||||
val start = startDate.getWeekFirstDayAlwaysCurrent()
|
val start = startDate.weekFirstDayAlwaysCurrent
|
||||||
val end = endDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
|
val end = endDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
|
||||||
|
|
||||||
return local.getAttendance(semester, start, end).filter { !forceRefresh }
|
return local.getAttendance(semester, start, end).filter { !forceRefresh }
|
||||||
|
@ -6,8 +6,7 @@ import io.github.wulkanowy.data.db.entities.Exam
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.repositories.local.ExamLocal
|
import io.github.wulkanowy.data.repositories.local.ExamLocal
|
||||||
import io.github.wulkanowy.data.repositories.remote.ExamRemote
|
import io.github.wulkanowy.data.repositories.remote.ExamRemote
|
||||||
import io.github.wulkanowy.utils.extension.getWeekFirstDayAlwaysCurrent
|
import io.github.wulkanowy.utils.weekFirstDayAlwaysCurrent
|
||||||
import io.github.wulkanowy.utils.extension.toDate
|
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import org.threeten.bp.DayOfWeek
|
import org.threeten.bp.DayOfWeek
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
@ -24,7 +23,7 @@ class ExamRepository @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false): Single<List<Exam>> {
|
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false): Single<List<Exam>> {
|
||||||
val start = startDate.getWeekFirstDayAlwaysCurrent()
|
val start = startDate.weekFirstDayAlwaysCurrent
|
||||||
val end = endDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
|
val end = endDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
|
||||||
|
|
||||||
return local.getExams(semester, start, end).filter { !forceRefresh }
|
return local.getExams(semester, start, end).filter { !forceRefresh }
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
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.Grade
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.repositories.local.GradeLocal
|
||||||
|
import io.github.wulkanowy.data.repositories.remote.GradeRemote
|
||||||
|
import io.reactivex.Completable
|
||||||
|
import io.reactivex.Single
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class GradeRepository @Inject constructor(
|
||||||
|
private val settings: InternetObservingSettings,
|
||||||
|
private val local: GradeLocal,
|
||||||
|
private val remote: GradeRemote
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getGrades(semester: Semester, forceRefresh: Boolean = false): Single<List<Grade>> {
|
||||||
|
return local.getGrades(semester).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||||
|
.flatMap {
|
||||||
|
if (it) remote.getGrades(semester)
|
||||||
|
else Single.error(UnknownHostException())
|
||||||
|
}.flatMap { newGrades ->
|
||||||
|
local.getGrades(semester).toSingle(emptyList())
|
||||||
|
.doOnSuccess { oldGrades ->
|
||||||
|
local.deleteGrades(oldGrades - newGrades)
|
||||||
|
local.saveGrades((newGrades - oldGrades)
|
||||||
|
.onEach { if (oldGrades.isNotEmpty()) it.isNew = true })
|
||||||
|
}
|
||||||
|
}.flatMap { local.getGrades(semester).toSingle(emptyList()) })
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateGrade(grade: Grade): Completable {
|
||||||
|
return local.updateGrade(grade)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
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.GradeSummary
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.repositories.local.GradeSummaryLocal
|
||||||
|
import io.github.wulkanowy.data.repositories.remote.GradeSummaryRemote
|
||||||
|
import io.reactivex.Single
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class GradeSummaryRepository @Inject constructor(
|
||||||
|
private val settings: InternetObservingSettings,
|
||||||
|
private val local: GradeSummaryLocal,
|
||||||
|
private val remote: GradeSummaryRemote
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getGradesSummary(semester: Semester, forceRefresh: Boolean = false): Single<List<GradeSummary>> {
|
||||||
|
return local.getGradesSummary(semester).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||||
|
.flatMap {
|
||||||
|
if (it) remote.getGradeSummary(semester)
|
||||||
|
else Single.error(UnknownHostException())
|
||||||
|
}
|
||||||
|
).doOnSuccess { local.saveGradesSummary(it) }
|
||||||
|
}
|
||||||
|
}
|
@ -42,9 +42,8 @@ class SessionRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun saveStudent(student: Student): Completable {
|
fun saveStudent(student: Student): Completable {
|
||||||
return remote.getSemesters(student).flatMapCompletable {
|
return remote.getSemesters(student).flatMapCompletable { local.saveSemesters(it) }
|
||||||
local.saveSemesters(it)
|
.concatWith(local.saveStudent(student))
|
||||||
}.concatWith(local.saveStudent(student))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearCache() {
|
fun clearCache() {
|
||||||
|
@ -3,11 +3,8 @@ package io.github.wulkanowy.data.repositories.local
|
|||||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.utils.extension.toDate
|
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import org.threeten.bp.DayOfWeek
|
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import org.threeten.bp.temporal.TemporalAdjusters
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.local
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradeDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.reactivex.Completable
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class GradeLocal @Inject constructor(private val gradeDb: GradeDao) {
|
||||||
|
|
||||||
|
fun getGrades(semester: Semester): Maybe<List<Grade>> {
|
||||||
|
return gradeDb.getGrades(semester.semesterId, semester.studentId).filter { !it.isEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveGrades(grades: List<Grade>) {
|
||||||
|
gradeDb.insertAll(grades)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateGrade(grade: Grade): Completable {
|
||||||
|
return Completable.fromCallable { gradeDb.update(grade) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteGrades(grades: List<Grade>) {
|
||||||
|
gradeDb.deleteAll(grades)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.local
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class GradeSummaryLocal @Inject constructor(private val gradeSummaryDb: GradeSummaryDao) {
|
||||||
|
|
||||||
|
fun getGradesSummary(semester: Semester): Maybe<List<GradeSummary>> {
|
||||||
|
return gradeSummaryDb.getGradesSummary(semester.semesterId, semester.studentId)
|
||||||
|
.filter { !it.isEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||||
|
gradeSummaryDb.insertAll(gradesSummary)
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.repositories.remote
|
|||||||
import io.github.wulkanowy.api.Api
|
import io.github.wulkanowy.api.Api
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.utils.extension.toLocalDate
|
import io.github.wulkanowy.utils.toLocalDate
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.repositories.remote
|
|||||||
import io.github.wulkanowy.api.Api
|
import io.github.wulkanowy.api.Api
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.utils.extension.toLocalDate
|
import io.github.wulkanowy.utils.toLocalDate
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.remote
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.utils.toLocalDate
|
||||||
|
import io.reactivex.Single
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class GradeRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
|
fun getGrades(semester: Semester): Single<List<Grade>> {
|
||||||
|
return Single.just(api.run {
|
||||||
|
if (diaryId != semester.diaryId) {
|
||||||
|
diaryId = semester.diaryId
|
||||||
|
notifyDataChanged()
|
||||||
|
}
|
||||||
|
}).flatMap { api.getGrades(semester.semesterId.toInt()) }
|
||||||
|
.map { grades ->
|
||||||
|
grades.map {
|
||||||
|
Grade(
|
||||||
|
semesterId = semester.semesterId,
|
||||||
|
studentId = semester.studentId,
|
||||||
|
subject = it.subject,
|
||||||
|
entry = it.entry,
|
||||||
|
value = it.value,
|
||||||
|
modifier = it.modifier.toDouble(),
|
||||||
|
comment = it.comment,
|
||||||
|
color = it.color,
|
||||||
|
gradeSymbol = it.symbol,
|
||||||
|
description = it.description,
|
||||||
|
weight = it.weight,
|
||||||
|
weightValue = it.weightValue,
|
||||||
|
date = it.date.toLocalDate(),
|
||||||
|
teacher = it.teacher
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.remote
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.reactivex.Single
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class GradeSummaryRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
|
fun getGradeSummary(semester: Semester): Single<List<GradeSummary>> {
|
||||||
|
return Single.just(api.run {
|
||||||
|
if (diaryId != semester.diaryId) {
|
||||||
|
diaryId = semester.diaryId
|
||||||
|
notifyDataChanged()
|
||||||
|
}
|
||||||
|
}).flatMap { api.getGradesSummary(semester.semesterId.toInt()) }
|
||||||
|
.map { gradesSummary ->
|
||||||
|
gradesSummary.map {
|
||||||
|
GradeSummary(
|
||||||
|
semesterId = semester.semesterId,
|
||||||
|
studentId = semester.studentId,
|
||||||
|
subject = it.name,
|
||||||
|
predictedGrade = it.predicted,
|
||||||
|
finalGrade = it.final
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,13 +8,16 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
|||||||
import io.github.wulkanowy.WulkanowyApp
|
import io.github.wulkanowy.WulkanowyApp
|
||||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
import io.github.wulkanowy.utils.schedulers.SchedulersProvider
|
import io.github.wulkanowy.utils.schedulers.SchedulersProvider
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
internal class AppModule {
|
internal class AppModule {
|
||||||
|
|
||||||
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideContext(app: WulkanowyApp): Context = app
|
fun provideContext(app: WulkanowyApp): Context = app
|
||||||
|
|
||||||
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideSchedulers(): SchedulersManager = SchedulersProvider()
|
fun provideSchedulers(): SchedulersManager = SchedulersProvider()
|
||||||
|
|
||||||
|
@ -6,11 +6,10 @@ import android.support.design.widget.Snackbar.LENGTH_LONG
|
|||||||
import android.support.v7.app.AppCompatDelegate
|
import android.support.v7.app.AppCompatDelegate
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import dagger.android.support.DaggerAppCompatActivity
|
import dagger.android.support.DaggerAppCompatActivity
|
||||||
import io.github.wulkanowy.R
|
|
||||||
|
|
||||||
abstract class BaseActivity : DaggerAppCompatActivity(), BaseView {
|
abstract class BaseActivity : DaggerAppCompatActivity(), BaseView {
|
||||||
|
|
||||||
protected lateinit var messageView: View
|
protected lateinit var messageContainer: View
|
||||||
|
|
||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -18,12 +17,7 @@ abstract class BaseActivity : DaggerAppCompatActivity(), BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun showMessage(text: String) {
|
override fun showMessage(text: String) {
|
||||||
Snackbar.make(messageView, text, LENGTH_LONG).show()
|
Snackbar.make(messageContainer, text, LENGTH_LONG).show()
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoNetworkMessage() {
|
|
||||||
showMessage(getString(R.string.all_no_internet))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
@ -1,24 +1,10 @@
|
|||||||
package io.github.wulkanowy.ui.base
|
package io.github.wulkanowy.ui.base
|
||||||
|
|
||||||
import android.support.annotation.StringRes
|
|
||||||
|
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
|
||||||
abstract class BaseFragment : DaggerFragment(), BaseView {
|
abstract class BaseFragment : DaggerFragment(), BaseView {
|
||||||
|
|
||||||
fun setTitle(title: String) {
|
|
||||||
activity?.title = title
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showMessage(text: String) {
|
override fun showMessage(text: String) {
|
||||||
(activity as BaseActivity?)?.showMessage(text)
|
(activity as BaseActivity?)?.showMessage(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showMessage(@StringRes stringId: Int) {
|
|
||||||
showMessage(getString(stringId))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoNetworkMessage() {
|
|
||||||
(activity as BaseActivity?)?.showNoNetworkMessage()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,28 +3,30 @@ package io.github.wulkanowy.ui.base
|
|||||||
import android.support.v4.app.Fragment
|
import android.support.v4.app.Fragment
|
||||||
import android.support.v4.app.FragmentManager
|
import android.support.v4.app.FragmentManager
|
||||||
import android.support.v4.app.FragmentStatePagerAdapter
|
import android.support.v4.app.FragmentStatePagerAdapter
|
||||||
|
import android.view.ViewGroup
|
||||||
|
|
||||||
class BasePagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
|
class BasePagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
|
||||||
|
|
||||||
private val fragmentList = mutableListOf<Fragment>()
|
val fragments = mutableMapOf<String?, Fragment>()
|
||||||
|
|
||||||
private val titleList = mutableListOf<String>()
|
val registeredFragments = mutableMapOf<Int, Fragment>()
|
||||||
|
|
||||||
fun addFragment(fragment: Fragment, title: String) {
|
override fun getItem(position: Int) = fragments.values.elementAt(position)
|
||||||
fragmentList.add(fragment)
|
|
||||||
titleList.add(title)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addFragments(vararg fragments: Fragment) {
|
override fun getCount() = fragments.size
|
||||||
fragmentList.addAll(fragments)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItem(position: Int): Fragment = fragmentList[position]
|
|
||||||
|
|
||||||
override fun getCount(): Int = fragmentList.size
|
|
||||||
|
|
||||||
override fun getPageTitle(position: Int): CharSequence? {
|
override fun getPageTitle(position: Int): CharSequence? {
|
||||||
return if (!titleList.isEmpty() && titleList.size == fragmentList.size) titleList[position]
|
return fragments.keys.elementAtOrNull(position)
|
||||||
else null
|
}
|
||||||
|
|
||||||
|
override fun instantiateItem(container: ViewGroup, position: Int): Any {
|
||||||
|
return super.instantiateItem(container, position).also {
|
||||||
|
registeredFragments[position] = it as Fragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun destroyItem(container: ViewGroup, position: Int, fragment: Any) {
|
||||||
|
registeredFragments.remove(position)
|
||||||
|
super.destroyItem(container, position, fragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,4 @@ package io.github.wulkanowy.ui.base
|
|||||||
interface BaseView {
|
interface BaseView {
|
||||||
|
|
||||||
fun showMessage(text: String)
|
fun showMessage(text: String)
|
||||||
|
|
||||||
fun showNoNetworkMessage()
|
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,9 @@ import io.github.wulkanowy.ui.base.BaseActivity
|
|||||||
import io.github.wulkanowy.ui.base.BasePagerAdapter
|
import io.github.wulkanowy.ui.base.BasePagerAdapter
|
||||||
import io.github.wulkanowy.ui.login.form.LoginFormFragment
|
import io.github.wulkanowy.ui.login.form.LoginFormFragment
|
||||||
import io.github.wulkanowy.ui.login.options.LoginOptionsFragment
|
import io.github.wulkanowy.ui.login.options.LoginOptionsFragment
|
||||||
import io.github.wulkanowy.utils.extension.setOnSelectPageListener
|
import io.github.wulkanowy.utils.setOnSelectPageListener
|
||||||
import kotlinx.android.synthetic.main.activity_login.*
|
import kotlinx.android.synthetic.main.activity_login.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Named
|
|
||||||
|
|
||||||
class LoginActivity : BaseActivity(), LoginView, LoginSwitchListener {
|
class LoginActivity : BaseActivity(), LoginView, LoginSwitchListener {
|
||||||
|
|
||||||
@ -19,7 +18,6 @@ class LoginActivity : BaseActivity(), LoginView, LoginSwitchListener {
|
|||||||
lateinit var presenter: LoginPresenter
|
lateinit var presenter: LoginPresenter
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@field:Named("Login")
|
|
||||||
lateinit var loginAdapter: BasePagerAdapter
|
lateinit var loginAdapter: BasePagerAdapter
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -30,7 +28,7 @@ class LoginActivity : BaseActivity(), LoginView, LoginSwitchListener {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_login)
|
setContentView(R.layout.activity_login)
|
||||||
presenter.attachView(this)
|
presenter.attachView(this)
|
||||||
messageView = loginContainer
|
messageContainer = loginContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
@ -38,7 +36,10 @@ class LoginActivity : BaseActivity(), LoginView, LoginSwitchListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initAdapter() {
|
override fun initAdapter() {
|
||||||
loginAdapter.addFragments(LoginFormFragment(), LoginOptionsFragment())
|
loginAdapter.fragments.putAll(mapOf(
|
||||||
|
"1" to LoginFormFragment.newInstance(),
|
||||||
|
"2" to LoginOptionsFragment.newInstance()
|
||||||
|
))
|
||||||
loginViewpager.run {
|
loginViewpager.run {
|
||||||
adapter = loginAdapter
|
adapter = loginAdapter
|
||||||
setOnSelectPageListener { presenter.onPageSelected(it) }
|
setOnSelectPageListener { presenter.onPageSelected(it) }
|
||||||
@ -61,7 +62,7 @@ class LoginActivity : BaseActivity(), LoginView, LoginSwitchListener {
|
|||||||
(loginAdapter.getItem(index) as LoginOptionsFragment).loadData()
|
(loginAdapter.getItem(index) as LoginOptionsFragment).loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun currentViewPosition(): Int = loginViewpager.currentItem
|
override fun currentViewPosition() = loginViewpager.currentItem
|
||||||
|
|
||||||
public override fun onDestroy() {
|
public override fun onDestroy() {
|
||||||
presenter.detachView()
|
presenter.detachView()
|
||||||
|
@ -9,8 +9,6 @@ import io.github.wulkanowy.di.scopes.PerFragment
|
|||||||
import io.github.wulkanowy.ui.base.BasePagerAdapter
|
import io.github.wulkanowy.ui.base.BasePagerAdapter
|
||||||
import io.github.wulkanowy.ui.login.form.LoginFormFragment
|
import io.github.wulkanowy.ui.login.form.LoginFormFragment
|
||||||
import io.github.wulkanowy.ui.login.options.LoginOptionsFragment
|
import io.github.wulkanowy.ui.login.options.LoginOptionsFragment
|
||||||
import io.github.wulkanowy.ui.login.options.LoginOptionsModule
|
|
||||||
import javax.inject.Named
|
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
internal abstract class LoginModule {
|
internal abstract class LoginModule {
|
||||||
@ -19,8 +17,8 @@ internal abstract class LoginModule {
|
|||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@PerActivity
|
||||||
@Provides
|
@Provides
|
||||||
@Named("Login")
|
|
||||||
fun provideLoginAdapter(activity: LoginActivity) = BasePagerAdapter(activity.supportFragmentManager)
|
fun provideLoginAdapter(activity: LoginActivity) = BasePagerAdapter(activity.supportFragmentManager)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ -34,6 +32,6 @@ internal abstract class LoginModule {
|
|||||||
abstract fun bindLoginFormFragment(): LoginFormFragment
|
abstract fun bindLoginFormFragment(): LoginFormFragment
|
||||||
|
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@ContributesAndroidInjector(modules = [LoginOptionsModule::class])
|
@ContributesAndroidInjector()
|
||||||
abstract fun bindLoginOptionsFragment(): LoginOptionsFragment
|
abstract fun bindLoginOptionsFragment(): LoginOptionsFragment
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ import android.widget.ArrayAdapter
|
|||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.login.LoginSwitchListener
|
import io.github.wulkanowy.ui.login.LoginSwitchListener
|
||||||
import io.github.wulkanowy.utils.extension.hideSoftInput
|
import io.github.wulkanowy.utils.hideSoftInput
|
||||||
import io.github.wulkanowy.utils.extension.showSoftInput
|
import io.github.wulkanowy.utils.showSoftInput
|
||||||
import kotlinx.android.synthetic.main.fragment_login_form.*
|
import kotlinx.android.synthetic.main.fragment_login_form.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -21,6 +21,10 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: LoginFormPresenter
|
lateinit var presenter: LoginFormPresenter
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance() = LoginFormFragment()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
return inflater.inflate(R.layout.fragment_login_form, container, false)
|
return inflater.inflate(R.layout.fragment_login_form, container, false)
|
||||||
}
|
}
|
||||||
@ -132,8 +136,8 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
|||||||
loginFormProgressContainer.visibility = if (show) VISIBLE else GONE
|
loginFormProgressContainer.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroyView() {
|
||||||
super.onDestroy()
|
super.onDestroyView()
|
||||||
presenter.detachView()
|
presenter.detachView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.login.form
|
|||||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.login.LoginErrorHandler
|
import io.github.wulkanowy.ui.login.LoginErrorHandler
|
||||||
import io.github.wulkanowy.utils.DEFAULT_SYMBOL
|
|
||||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -83,6 +82,6 @@ class LoginFormPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun normalizeSymbol(symbol: String): String {
|
private fun normalizeSymbol(symbol: String): String {
|
||||||
return if (symbol.isEmpty()) DEFAULT_SYMBOL else symbol
|
return if (symbol.isEmpty()) "Default" else symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
|||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.main.MainActivity
|
import io.github.wulkanowy.ui.main.MainActivity
|
||||||
import io.github.wulkanowy.utils.extension.setOnItemClickListener
|
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||||
import kotlinx.android.synthetic.main.fragment_login_options.*
|
import kotlinx.android.synthetic.main.fragment_login_options.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package io.github.wulkanowy.ui.login.options
|
|
||||||
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
|
||||||
import io.github.wulkanowy.di.scopes.PerFragment
|
|
||||||
|
|
||||||
@Module
|
|
||||||
internal class LoginOptionsModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@PerFragment
|
|
||||||
fun provideLoginOptionsAdapter() = FlexibleAdapter<LoginOptionsItem>(null)
|
|
||||||
}
|
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.main
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.Fragment
|
|
||||||
import android.support.v4.content.ContextCompat
|
import android.support.v4.content.ContextCompat
|
||||||
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation
|
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation
|
||||||
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem
|
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem
|
||||||
@ -16,10 +15,12 @@ import io.github.wulkanowy.ui.main.exam.ExamFragment
|
|||||||
import io.github.wulkanowy.ui.main.grade.GradeFragment
|
import io.github.wulkanowy.ui.main.grade.GradeFragment
|
||||||
import io.github.wulkanowy.ui.main.more.MoreFragment
|
import io.github.wulkanowy.ui.main.more.MoreFragment
|
||||||
import io.github.wulkanowy.ui.main.timetable.TimetableFragment
|
import io.github.wulkanowy.ui.main.timetable.TimetableFragment
|
||||||
|
import io.github.wulkanowy.utils.setOnTabTransactionListener
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MainActivity : BaseActivity(), MainView, FragNavController.TransactionListener {
|
class MainActivity : BaseActivity(), MainView {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: MainPresenter
|
lateinit var presenter: MainPresenter
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ class MainActivity : BaseActivity(), MainView, FragNavController.TransactionList
|
|||||||
lateinit var navController: FragNavController
|
lateinit var navController: FragNavController
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val DEFAULT_TAB = 0
|
const val DEFAULT_TAB = 2
|
||||||
|
|
||||||
fun getStartIntent(context: Context) = Intent(context, MainActivity::class.java)
|
fun getStartIntent(context: Context) = Intent(context, MainActivity::class.java)
|
||||||
}
|
}
|
||||||
@ -35,27 +36,19 @@ class MainActivity : BaseActivity(), MainView, FragNavController.TransactionList
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
messageView = mainContainer
|
setSupportActionBar(mainToolbar)
|
||||||
|
messageContainer = mainFragmentContainer
|
||||||
|
|
||||||
presenter.attachView(this)
|
presenter.attachView(this)
|
||||||
navController.initialize(DEFAULT_TAB, savedInstanceState)
|
navController.initialize(DEFAULT_TAB, savedInstanceState)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initFragmentController() {
|
override fun onStart() {
|
||||||
navController.run {
|
super.onStart()
|
||||||
rootFragments = listOf(
|
presenter.onStartView()
|
||||||
GradeFragment.newInstance(),
|
|
||||||
AttendanceFragment.newInstance(),
|
|
||||||
ExamFragment.newInstance(),
|
|
||||||
TimetableFragment.newInstance(),
|
|
||||||
MoreFragment.newInstance()
|
|
||||||
)
|
|
||||||
fragmentHideStrategy = DETACH_ON_NAVIGATE_HIDE_ON_SWITCH
|
|
||||||
createEager = true
|
|
||||||
transactionListener = this@MainActivity
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initBottomNav() {
|
override fun initView() {
|
||||||
mainBottomNav.run {
|
mainBottomNav.run {
|
||||||
addItems(mutableListOf(
|
addItems(mutableListOf(
|
||||||
AHBottomNavigationItem(R.string.grade_title, R.drawable.ic_menu_main_grade_26dp, 0),
|
AHBottomNavigationItem(R.string.grade_title, R.drawable.ic_menu_main_grade_26dp, 0),
|
||||||
@ -69,39 +62,63 @@ class MainActivity : BaseActivity(), MainView, FragNavController.TransactionList
|
|||||||
titleState = AHBottomNavigation.TitleState.ALWAYS_SHOW
|
titleState = AHBottomNavigation.TitleState.ALWAYS_SHOW
|
||||||
currentItem = DEFAULT_TAB
|
currentItem = DEFAULT_TAB
|
||||||
isBehaviorTranslationEnabled = false
|
isBehaviorTranslationEnabled = false
|
||||||
setOnTabSelectedListener { position, _ ->
|
setTitleTextSizeInSp(10f, 10f)
|
||||||
presenter.onTabSelected(position)
|
|
||||||
|
setOnTabSelectedListener { position, wasSelected ->
|
||||||
|
presenter.onTabSelected(position, wasSelected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
navController.run {
|
||||||
|
setOnTabTransactionListener { presenter.onMenuViewChange(it) }
|
||||||
|
fragmentHideStrategy = DETACH_ON_NAVIGATE_HIDE_ON_SWITCH
|
||||||
|
rootFragments = listOf(
|
||||||
|
GradeFragment.newInstance(),
|
||||||
|
AttendanceFragment.newInstance(),
|
||||||
|
ExamFragment.newInstance(),
|
||||||
|
TimetableFragment.newInstance(),
|
||||||
|
MoreFragment.newInstance()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFragmentTransaction(fragment: Fragment?, transactionType: FragNavController.TransactionType) {}
|
override fun switchMenuView(position: Int) {
|
||||||
|
|
||||||
override fun onTabTransaction(fragment: Fragment?, index: Int) {
|
|
||||||
presenter.onMenuFragmentChange(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun switchMenuFragment(position: Int) {
|
|
||||||
navController.switchTab(position)
|
navController.switchTab(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setViewTitle(title: String) {
|
override fun setViewTitle(title: String) {
|
||||||
setTitle(title)
|
supportActionBar?.title = title
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun defaultTitle(): String = getString(R.string.main_title)
|
override fun expandActionBar(show: Boolean) {
|
||||||
|
mainAppBarContainer.setExpanded(show, true)
|
||||||
|
}
|
||||||
|
|
||||||
override fun mapOfTitles(): Map<Int, String> {
|
override fun viewTitle(index: Int): String {
|
||||||
return mapOf(0 to R.string.grade_title,
|
return getString(listOf(R.string.grade_title,
|
||||||
1 to R.string.attendance_title,
|
R.string.attendance_title,
|
||||||
2 to R.string.exam_title,
|
R.string.exam_title,
|
||||||
3 to R.string.timetable_title,
|
R.string.timetable_title,
|
||||||
4 to R.string.more_title
|
R.string.more_title)[index])
|
||||||
).mapValues { getString(it.value) }
|
}
|
||||||
|
|
||||||
|
override fun currentMenuIndex() = navController.currentStackIndex
|
||||||
|
|
||||||
|
override fun notifyMenuViewReselected() {
|
||||||
|
(navController.currentFrag as? MainView.MenuFragmentView)?.onFragmentReselected()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBackPressed() {
|
||||||
|
navController.apply { if (isRootFragment) super.onBackPressed() else popFragment() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle?) {
|
override fun onSaveInstanceState(outState: Bundle?) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
navController.onSaveInstanceState(outState)
|
navController.onSaveInstanceState(outState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
presenter.detachView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import io.github.wulkanowy.di.scopes.PerFragment
|
|||||||
import io.github.wulkanowy.ui.main.attendance.AttendanceFragment
|
import io.github.wulkanowy.ui.main.attendance.AttendanceFragment
|
||||||
import io.github.wulkanowy.ui.main.exam.ExamFragment
|
import io.github.wulkanowy.ui.main.exam.ExamFragment
|
||||||
import io.github.wulkanowy.ui.main.grade.GradeFragment
|
import io.github.wulkanowy.ui.main.grade.GradeFragment
|
||||||
|
import io.github.wulkanowy.ui.main.grade.GradeModule
|
||||||
import io.github.wulkanowy.ui.main.more.MoreFragment
|
import io.github.wulkanowy.ui.main.more.MoreFragment
|
||||||
import io.github.wulkanowy.ui.main.timetable.TimetableFragment
|
import io.github.wulkanowy.ui.main.timetable.TimetableFragment
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ abstract class MainModule {
|
|||||||
abstract fun bindExamFragment(): ExamFragment
|
abstract fun bindExamFragment(): ExamFragment
|
||||||
|
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector(modules = [GradeModule::class])
|
||||||
abstract fun bindGradeFragment(): GradeFragment
|
abstract fun bindGradeFragment(): GradeFragment
|
||||||
|
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@ -47,4 +48,3 @@ abstract class MainModule {
|
|||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract fun bindTimetableFragment(): TimetableFragment
|
abstract fun bindTimetableFragment(): TimetableFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,21 +9,27 @@ class MainPresenter @Inject constructor(errorHandler: ErrorHandler)
|
|||||||
|
|
||||||
override fun attachView(view: MainView) {
|
override fun attachView(view: MainView) {
|
||||||
super.attachView(view)
|
super.attachView(view)
|
||||||
view.run {
|
view.initView()
|
||||||
initFragmentController()
|
|
||||||
initBottomNav()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onTabSelected(position: Int): Boolean {
|
fun onStartView() {
|
||||||
view?.switchMenuFragment(position)
|
view?.run { setViewTitle(viewTitle(currentMenuIndex())) }
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onMenuFragmentChange(position: Int) {
|
fun onMenuViewChange(index: Int) {
|
||||||
view?.run {
|
view?.run { setViewTitle(viewTitle(index)) }
|
||||||
setViewTitle(mapOfTitles()[position] ?: defaultTitle())
|
}
|
||||||
}
|
|
||||||
|
fun onTabSelected(index: Int, wasSelected: Boolean): Boolean {
|
||||||
|
return view?.run {
|
||||||
|
expandActionBar(true)
|
||||||
|
if (wasSelected) {
|
||||||
|
notifyMenuViewReselected()
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
switchMenuView(index)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
} == true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,15 +4,22 @@ import io.github.wulkanowy.ui.base.BaseView
|
|||||||
|
|
||||||
interface MainView : BaseView {
|
interface MainView : BaseView {
|
||||||
|
|
||||||
fun initFragmentController()
|
fun initView()
|
||||||
|
|
||||||
fun initBottomNav()
|
fun switchMenuView(position: Int)
|
||||||
|
|
||||||
fun switchMenuFragment(position: Int)
|
|
||||||
|
|
||||||
fun setViewTitle(title: String)
|
fun setViewTitle(title: String)
|
||||||
|
|
||||||
fun defaultTitle(): String
|
fun expandActionBar(show: Boolean)
|
||||||
|
|
||||||
fun mapOfTitles(): Map<Int, String>
|
fun viewTitle(index: Int): String
|
||||||
}
|
|
||||||
|
fun currentMenuIndex(): Int
|
||||||
|
|
||||||
|
fun notifyMenuViewReselected()
|
||||||
|
|
||||||
|
interface MenuFragmentView {
|
||||||
|
|
||||||
|
fun onFragmentReselected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.utils.extension.toFormat
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import kotlinx.android.synthetic.main.dialog_attendance.*
|
import kotlinx.android.synthetic.main.dialog_attendance.*
|
||||||
|
|
||||||
class AttendanceDialog : DialogFragment() {
|
class AttendanceDialog : DialogFragment() {
|
||||||
@ -42,7 +42,7 @@ class AttendanceDialog : DialogFragment() {
|
|||||||
|
|
||||||
attendanceDialogSubject.text = attendance.subject
|
attendanceDialogSubject.text = attendance.subject
|
||||||
attendanceDialogDescription.text = attendance.name
|
attendanceDialogDescription.text = attendance.name
|
||||||
attendanceDialogDate.text = attendance.date.toFormat()
|
attendanceDialogDate.text = attendance.date.toFormattedString()
|
||||||
attendanceDialogNumber.text = attendance.number.toString()
|
attendanceDialogNumber.text = attendance.number.toString()
|
||||||
attendanceDialogClose.setOnClickListener { dismiss() }
|
attendanceDialogClose.setOnClickListener { dismiss() }
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
|||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.utils.extension.setOnItemClickListener
|
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||||
import kotlinx.android.synthetic.main.fragment_attendance.*
|
import kotlinx.android.synthetic.main.fragment_attendance.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.repositories.AttendanceRepository
|
import io.github.wulkanowy.data.repositories.AttendanceRepository
|
||||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.utils.extension.*
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -19,7 +19,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
private val sessionRepository: SessionRepository
|
private val sessionRepository: SessionRepository
|
||||||
) : BasePresenter<AttendanceView>(errorHandler) {
|
) : BasePresenter<AttendanceView>(errorHandler) {
|
||||||
|
|
||||||
var currentDate: LocalDate = LocalDate.now().getNearSchoolDayPrevOnWeekEnd()
|
var currentDate: LocalDate = LocalDate.now().nearSchoolDayPrevOnWeekEnd
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override fun attachView(view: AttendanceView) {
|
override fun attachView(view: AttendanceView) {
|
||||||
@ -27,13 +27,14 @@ class AttendancePresenter @Inject constructor(
|
|||||||
view.initView()
|
view.initView()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadAttendanceForPreviousDay() = loadData(currentDate.getPreviousWorkDay().toEpochDay())
|
fun loadAttendanceForPreviousDay() = loadData(currentDate.previousWorkDay.toEpochDay())
|
||||||
|
|
||||||
fun loadAttendanceForNextDay() = loadData(currentDate.getNextWorkDay().toEpochDay())
|
fun loadAttendanceForNextDay() = loadData(currentDate.nextWorkDay.toEpochDay())
|
||||||
|
|
||||||
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
||||||
this.currentDate = LocalDate.ofEpochDay(date ?: currentDate.getNearSchoolDayPrevOnWeekEnd().toEpochDay())
|
this.currentDate = LocalDate.ofEpochDay(date
|
||||||
if (currentDate.isHolidays()) return
|
?: currentDate.nearSchoolDayPrevOnWeekEnd.toEpochDay())
|
||||||
|
if (currentDate.isHolidays) return
|
||||||
|
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
disposable.add(sessionRepository.getSemesters()
|
disposable.add(sessionRepository.getSemesters()
|
||||||
@ -50,9 +51,9 @@ class AttendancePresenter @Inject constructor(
|
|||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
clearData()
|
clearData()
|
||||||
}
|
}
|
||||||
showPreButton(!currentDate.minusDays(1).isHolidays())
|
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||||
showNextButton(!currentDate.plusDays(1).isHolidays())
|
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||||
updateNavigationDay(currentDate.toFormat("EEEE \n dd.MM.YYYY").capitalize())
|
updateNavigationDay(currentDate.toFormattedString("EEEE \n dd.MM.YYYY").capitalize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.doFinally {
|
.doFinally {
|
||||||
|
@ -7,7 +7,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.utils.extension.toFormat
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import kotlinx.android.synthetic.main.dialog_exam.*
|
import kotlinx.android.synthetic.main.dialog_exam.*
|
||||||
|
|
||||||
class ExamDialog : DialogFragment() {
|
class ExamDialog : DialogFragment() {
|
||||||
@ -43,7 +43,7 @@ class ExamDialog : DialogFragment() {
|
|||||||
examDialogSubjectValue.text = exam.subject
|
examDialogSubjectValue.text = exam.subject
|
||||||
examDialogTypeValue.text = exam.type
|
examDialogTypeValue.text = exam.type
|
||||||
examDialogTeacherValue.text = exam.teacher
|
examDialogTeacherValue.text = exam.teacher
|
||||||
examDialogDateValue.text = exam.entryDate.toFormat()
|
examDialogDateValue.text = exam.entryDate.toFormattedString()
|
||||||
examDialogDescriptionValue.text = exam.description
|
examDialogDescriptionValue.text = exam.description
|
||||||
|
|
||||||
examDialogClose.setOnClickListener { dismiss() }
|
examDialogClose.setOnClickListener { dismiss() }
|
||||||
|
@ -11,7 +11,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
|||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.utils.extension.setOnItemClickListener
|
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||||
import kotlinx.android.synthetic.main.fragment_exam.*
|
import kotlinx.android.synthetic.main.fragment_exam.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
|||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.ExpandableViewHolder
|
import eu.davidea.viewholders.ExpandableViewHolder
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.utils.extension.getWeekDayName
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import io.github.wulkanowy.utils.extension.toFormat
|
import io.github.wulkanowy.utils.weekDayName
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
import kotlinx.android.synthetic.main.header_exam.*
|
import kotlinx.android.synthetic.main.header_exam.*
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
@ -40,8 +40,8 @@ class ExamHeader : AbstractHeaderItem<ExamHeader.ViewHolder>() {
|
|||||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder,
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder,
|
||||||
position: Int, payloads: MutableList<Any>?) {
|
position: Int, payloads: MutableList<Any>?) {
|
||||||
holder.run {
|
holder.run {
|
||||||
examHeaderDay.text = date.getWeekDayName().capitalize()
|
examHeaderDay.text = date.weekDayName.capitalize()
|
||||||
examHeaderDate.text = date.toFormat()
|
examHeaderDate.text = date.toFormattedString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.repositories.ExamRepository
|
import io.github.wulkanowy.data.repositories.ExamRepository
|
||||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.utils.extension.getWeekFirstDayNextOnWeekEnd
|
import io.github.wulkanowy.utils.isHolidays
|
||||||
import io.github.wulkanowy.utils.extension.isHolidays
|
|
||||||
import io.github.wulkanowy.utils.extension.toFormat
|
|
||||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
import io.github.wulkanowy.utils.weekFirstDayNextOnWeekEnd
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ class ExamPresenter @Inject constructor(
|
|||||||
private val sessionRepository: SessionRepository
|
private val sessionRepository: SessionRepository
|
||||||
) : BasePresenter<ExamView>(errorHandler) {
|
) : BasePresenter<ExamView>(errorHandler) {
|
||||||
|
|
||||||
var currentDate: LocalDate = LocalDate.now().getWeekFirstDayNextOnWeekEnd()
|
var currentDate: LocalDate = LocalDate.now().weekFirstDayNextOnWeekEnd
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override fun attachView(view: ExamView) {
|
override fun attachView(view: ExamView) {
|
||||||
@ -34,8 +34,9 @@ class ExamPresenter @Inject constructor(
|
|||||||
fun loadExamsForNextWeek() = loadData(currentDate.plusDays(7).toEpochDay())
|
fun loadExamsForNextWeek() = loadData(currentDate.plusDays(7).toEpochDay())
|
||||||
|
|
||||||
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
||||||
this.currentDate = LocalDate.ofEpochDay(date ?: currentDate.getWeekFirstDayNextOnWeekEnd().toEpochDay())
|
this.currentDate = LocalDate.ofEpochDay(date
|
||||||
if (currentDate.isHolidays()) return
|
?: currentDate.weekFirstDayNextOnWeekEnd.toEpochDay())
|
||||||
|
if (currentDate.isHolidays) return
|
||||||
|
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
disposable.add(sessionRepository.getSemesters()
|
disposable.add(sessionRepository.getSemesters()
|
||||||
@ -51,9 +52,10 @@ class ExamPresenter @Inject constructor(
|
|||||||
showProgress(!forceRefresh)
|
showProgress(!forceRefresh)
|
||||||
if (!forceRefresh) showEmpty(false)
|
if (!forceRefresh) showEmpty(false)
|
||||||
showContent(null == date && forceRefresh)
|
showContent(null == date && forceRefresh)
|
||||||
showPreButton(!currentDate.minusDays(7).isHolidays())
|
showPreButton(!currentDate.minusDays(7).isHolidays)
|
||||||
showNextButton(!currentDate.plusDays(7).isHolidays())
|
showNextButton(!currentDate.plusDays(7).isHolidays)
|
||||||
updateNavigationWeek("${currentDate.toFormat("dd.MM")}-${currentDate.plusDays(4).toFormat("dd.MM")}")
|
updateNavigationWeek(currentDate.toFormattedString("dd.MM") +
|
||||||
|
"-${currentDate.plusDays(4).toFormattedString("dd.MM")}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.doAfterSuccess {
|
.doAfterSuccess {
|
||||||
|
@ -1,19 +1,120 @@
|
|||||||
package io.github.wulkanowy.ui.main.grade
|
package io.github.wulkanowy.ui.main.grade
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.support.v7.app.AlertDialog
|
||||||
import android.view.View
|
import android.view.*
|
||||||
import android.view.ViewGroup
|
import android.view.View.INVISIBLE
|
||||||
|
import android.view.View.VISIBLE
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
|
import io.github.wulkanowy.ui.base.BasePagerAdapter
|
||||||
|
import io.github.wulkanowy.ui.main.MainView
|
||||||
|
import io.github.wulkanowy.ui.main.grade.details.GradeDetailsFragment
|
||||||
|
import io.github.wulkanowy.ui.main.grade.summary.GradeSummaryFragment
|
||||||
|
import io.github.wulkanowy.utils.setOnSelectPageListener
|
||||||
|
import kotlinx.android.synthetic.main.fragment_grade.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class GradeFragment : BaseFragment() {
|
class GradeFragment : BaseFragment(), GradeView, MainView.MenuFragmentView {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var presenter: GradePresenter
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var pagerAdapter: BasePagerAdapter
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = GradeFragment()
|
fun newInstance() = GradeFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
return inflater.inflate(R.layout.fragment_grade, container, false)
|
return inflater.inflate(R.layout.fragment_grade, container, false)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
presenter.attachView(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
|
||||||
|
inflater?.inflate(R.menu.action_menu_grade, menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initView() {
|
||||||
|
pagerAdapter.fragments.putAll(mapOf(
|
||||||
|
getString(R.string.all_details) to GradeDetailsFragment.newInstance(),
|
||||||
|
getString(R.string.grade_menu_summary) to GradeSummaryFragment.newInstance()
|
||||||
|
))
|
||||||
|
gradeViewPager.run {
|
||||||
|
adapter = pagerAdapter
|
||||||
|
setOnSelectPageListener { presenter.onPageSelected(it) }
|
||||||
|
}
|
||||||
|
gradeTabLayout.setupWithViewPager(gradeViewPager)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||||
|
return if (item?.itemId == R.id.gradeMenuSemester) presenter.onSemesterSwitch()
|
||||||
|
else false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFragmentReselected() {
|
||||||
|
presenter.onViewReselected()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showContent(show: Boolean) {
|
||||||
|
gradeViewPager.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
|
gradeTabLayout.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showProgress(show: Boolean) {
|
||||||
|
gradeProgress.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showSemesterDialog(selectedIndex: Int) {
|
||||||
|
arrayOf(getString(R.string.grade_semester, 1),
|
||||||
|
getString(R.string.grade_semester, 2)).also { array ->
|
||||||
|
context?.let {
|
||||||
|
AlertDialog.Builder(it)
|
||||||
|
.setSingleChoiceItems(array, selectedIndex) { dialog, which ->
|
||||||
|
presenter.onSemesterSelected(which)
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
.setTitle(R.string.grade_switch_semester)
|
||||||
|
.setNegativeButton(R.string.all_cancel) { dialog, _ -> dialog.dismiss() }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun currentPageIndex() = gradeViewPager.currentItem
|
||||||
|
|
||||||
|
fun onChildRefresh() {
|
||||||
|
presenter.onChildViewRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onChildFragmentLoaded(semesterId: String) {
|
||||||
|
presenter.onChildViewLoaded(semesterId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun notifyChildLoadData(index: Int, semesterId: String, forceRefresh: Boolean) {
|
||||||
|
(childFragmentManager.fragments[index] as GradeView.GradeChildView).onParentLoadData(semesterId, forceRefresh)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun notifyChildParentReselected(index: Int) {
|
||||||
|
(pagerAdapter.registeredFragments[index] as? GradeView.GradeChildView)?.onParentReselected()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun notifyChildSemesterChange(index: Int) {
|
||||||
|
(pagerAdapter.registeredFragments[index] as? GradeView.GradeChildView)?.onParentChangeSemester()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
presenter.detachView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade
|
||||||
|
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.android.ContributesAndroidInjector
|
||||||
|
import io.github.wulkanowy.di.scopes.PerChildFragment
|
||||||
|
import io.github.wulkanowy.di.scopes.PerFragment
|
||||||
|
import io.github.wulkanowy.ui.base.BasePagerAdapter
|
||||||
|
import io.github.wulkanowy.ui.main.grade.details.GradeDetailsFragment
|
||||||
|
import io.github.wulkanowy.ui.main.grade.summary.GradeSummaryFragment
|
||||||
|
|
||||||
|
@Module
|
||||||
|
abstract class GradeModule {
|
||||||
|
|
||||||
|
@Module
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@PerFragment
|
||||||
|
@Provides
|
||||||
|
fun provideGradePagerAdapter(fragment: GradeFragment) = BasePagerAdapter(fragment.childFragmentManager)
|
||||||
|
}
|
||||||
|
|
||||||
|
@PerChildFragment
|
||||||
|
@ContributesAndroidInjector()
|
||||||
|
abstract fun bindGradeDetailsFragment(): GradeDetailsFragment
|
||||||
|
|
||||||
|
@PerChildFragment
|
||||||
|
@ContributesAndroidInjector
|
||||||
|
abstract fun binGradeSummaryFragment(): GradeSummaryFragment
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.ErrorHandler
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||||
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
|
import io.reactivex.Completable
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class GradePresenter @Inject constructor(
|
||||||
|
private val errorHandler: ErrorHandler,
|
||||||
|
private val schedulers: SchedulersManager,
|
||||||
|
private val sessionRepository: SessionRepository) : BasePresenter<GradeView>(errorHandler) {
|
||||||
|
|
||||||
|
private var semesters = emptyList<Semester>()
|
||||||
|
|
||||||
|
private var selectedIndex = 0
|
||||||
|
|
||||||
|
private val loadedSemesterId = mutableMapOf<Int, String>()
|
||||||
|
|
||||||
|
override fun attachView(view: GradeView) {
|
||||||
|
super.attachView(view)
|
||||||
|
disposable.add(Completable.timer(150, TimeUnit.MILLISECONDS, schedulers.mainThread())
|
||||||
|
.subscribe {
|
||||||
|
view.initView()
|
||||||
|
loadData()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onViewReselected() {
|
||||||
|
view?.run { notifyChildParentReselected(currentPageIndex()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSemesterSwitch(): Boolean {
|
||||||
|
if (semesters.isNotEmpty()) view?.showSemesterDialog(selectedIndex)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSemesterSelected(index: Int) {
|
||||||
|
if (selectedIndex != index) {
|
||||||
|
selectedIndex = index
|
||||||
|
loadedSemesterId.clear()
|
||||||
|
view?.let {
|
||||||
|
notifyChildrenSemesterChange()
|
||||||
|
loadChild(it.currentPageIndex())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onChildViewRefresh() {
|
||||||
|
view?.let { loadChild(it.currentPageIndex(), forceRefresh = true) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onChildViewLoaded(semesterId: String) {
|
||||||
|
view?.apply {
|
||||||
|
showContent(true)
|
||||||
|
showProgress(false)
|
||||||
|
loadedSemesterId[currentPageIndex()] = semesterId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onPageSelected(index: Int) {
|
||||||
|
loadChild(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadData() {
|
||||||
|
disposable.add(sessionRepository.getSemesters()
|
||||||
|
.map {
|
||||||
|
it.first { item -> item.current }.also { current ->
|
||||||
|
selectedIndex = current.semesterName - 1
|
||||||
|
semesters = it.filter { semester -> semester.diaryId == current.diaryId }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.subscribeOn(schedulers.backgroundThread())
|
||||||
|
.observeOn(schedulers.mainThread())
|
||||||
|
.subscribe({ _ ->
|
||||||
|
view?.let { loadChild(it.currentPageIndex()) }
|
||||||
|
}) { errorHandler.proceed(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadChild(index: Int, forceRefresh: Boolean = false) {
|
||||||
|
semesters.first { it.semesterName == selectedIndex + 1 }.semesterId.also {
|
||||||
|
if (forceRefresh || loadedSemesterId[index] != it) {
|
||||||
|
view?.notifyChildLoadData(index, it, forceRefresh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun notifyChildrenSemesterChange() {
|
||||||
|
for (i in 0..1) view?.notifyChildSemesterChange(i)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade
|
||||||
|
|
||||||
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
|
||||||
|
interface GradeView : BaseView {
|
||||||
|
|
||||||
|
fun initView()
|
||||||
|
|
||||||
|
fun currentPageIndex(): Int
|
||||||
|
|
||||||
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
|
fun showSemesterDialog(selectedIndex: Int)
|
||||||
|
|
||||||
|
fun notifyChildLoadData(index: Int, semesterId: String, forceRefresh: Boolean)
|
||||||
|
|
||||||
|
fun notifyChildParentReselected(index: Int)
|
||||||
|
|
||||||
|
fun notifyChildSemesterChange(index: Int)
|
||||||
|
|
||||||
|
interface GradeChildView {
|
||||||
|
|
||||||
|
fun onParentChangeSemester()
|
||||||
|
|
||||||
|
fun onParentLoadData(semesterId: String, forceRefresh: Boolean)
|
||||||
|
|
||||||
|
fun onParentReselected()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.details
|
||||||
|
|
||||||
|
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.Grade
|
||||||
|
import io.github.wulkanowy.utils.colorStringId
|
||||||
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
import io.github.wulkanowy.utils.valueColor
|
||||||
|
import kotlinx.android.synthetic.main.dialog_grade.*
|
||||||
|
|
||||||
|
|
||||||
|
class GradeDetailsDialog : DialogFragment() {
|
||||||
|
|
||||||
|
private lateinit var grade: Grade
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ARGUMENT_KEY = "Item"
|
||||||
|
|
||||||
|
fun newInstance(grade: Grade): GradeDetailsDialog {
|
||||||
|
return GradeDetailsDialog().apply {
|
||||||
|
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, grade) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
arguments?.run {
|
||||||
|
grade = getSerializable(ARGUMENT_KEY) as Grade
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.dialog_grade, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
gradeDialogSubject.text = grade.subject
|
||||||
|
gradeDialogWeightValue.text = grade.weight
|
||||||
|
gradeDialogDateValue.text = grade.date.toFormattedString()
|
||||||
|
gradeDialogColorValue.text = getString(grade.colorStringId)
|
||||||
|
|
||||||
|
gradeDialogCommentValue.apply {
|
||||||
|
if (grade.comment.isEmpty()) {
|
||||||
|
visibility = GONE
|
||||||
|
gradeDialogComment.visibility = GONE
|
||||||
|
} else text = grade.comment
|
||||||
|
}
|
||||||
|
|
||||||
|
gradeDialogValue.run {
|
||||||
|
text = grade.entry
|
||||||
|
setBackgroundResource(grade.valueColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
gradeDialogTeacherValue.text = if (grade.teacher.isEmpty()) {
|
||||||
|
getString(R.string.all_no_data)
|
||||||
|
} else grade.teacher
|
||||||
|
|
||||||
|
gradeDialogDescriptionValue.text = grade.run {
|
||||||
|
when {
|
||||||
|
description.isEmpty() && gradeSymbol.isNotEmpty() -> gradeSymbol
|
||||||
|
description.isEmpty() && gradeSymbol.isEmpty() -> getString(R.string.all_no_description)
|
||||||
|
gradeSymbol.isNotEmpty() && description.isNotEmpty() -> "$gradeSymbol - $description"
|
||||||
|
else -> description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gradeDialogClose.setOnClickListener { dismiss() }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.details
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
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 eu.davidea.flexibleadapter.items.IExpandable
|
||||||
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
import io.github.wulkanowy.R
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
|
import io.github.wulkanowy.ui.main.grade.GradeFragment
|
||||||
|
import io.github.wulkanowy.ui.main.grade.GradeView
|
||||||
|
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||||
|
import kotlinx.android.synthetic.main.fragment_grade_details.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeChildView {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var presenter: GradeDetailsPresenter
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var gradeDetailsAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance() = GradeDetailsFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.fragment_grade_details, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
presenter.attachView(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initView() {
|
||||||
|
gradeDetailsAdapter.run {
|
||||||
|
isAutoCollapseOnExpand = true
|
||||||
|
isAutoScrollOnExpand = true
|
||||||
|
setOnItemClickListener { presenter.onGradeItemSelected(getItem(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
gradeDetailsRecycler.run {
|
||||||
|
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||||
|
adapter = gradeDetailsAdapter
|
||||||
|
}
|
||||||
|
gradeDetailsSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateData(data: List<GradeDetailsHeader>) {
|
||||||
|
gradeDetailsAdapter.updateDataSet(data, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateItem(item: AbstractFlexibleItem<*>) {
|
||||||
|
gradeDetailsAdapter.updateItem(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearView() {
|
||||||
|
gradeDetailsAdapter.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resetView() {
|
||||||
|
gradeDetailsAdapter.apply {
|
||||||
|
smoothScrollToPosition(0)
|
||||||
|
collapseAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getHeaderOfItem(item: AbstractFlexibleItem<*>): IExpandable<*, out IFlexible<*>>? {
|
||||||
|
return gradeDetailsAdapter.getExpandableOf(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isViewEmpty() = gradeDetailsAdapter.isEmpty
|
||||||
|
|
||||||
|
override fun showProgress(show: Boolean) {
|
||||||
|
gradeDetailsProgress.visibility = if (show) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showContent(show: Boolean) {
|
||||||
|
gradeDetailsRecycler.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showEmpty(show: Boolean) {
|
||||||
|
gradeDetailsEmpty.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showRefresh(show: Boolean) {
|
||||||
|
gradeDetailsSwipe.isRefreshing = show
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showGradeDialog(grade: Grade) {
|
||||||
|
GradeDetailsDialog.newInstance(grade).show(fragmentManager, grade.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onParentLoadData(semesterId: String, forceRefresh: Boolean) {
|
||||||
|
presenter.loadData(semesterId, forceRefresh)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onParentReselected() {
|
||||||
|
presenter.onParentViewReselected()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onParentChangeSemester() {
|
||||||
|
presenter.onParentChangeSemester()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun notifyParentDataLoaded(semesterId: String) {
|
||||||
|
(parentFragment as? GradeFragment)?.onChildFragmentLoaded(semesterId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun notifyParentRefresh() {
|
||||||
|
(parentFragment as? GradeFragment)?.onChildRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun emptyAverageString(): String = getString(R.string.grade_no_average)
|
||||||
|
|
||||||
|
override fun averageString(): String = getString(R.string.grade_average)
|
||||||
|
|
||||||
|
override fun gradeNumberString(number: Int): String = resources.getQuantityString(R.plurals.grade_number_item, number, number)
|
||||||
|
|
||||||
|
override fun weightString(): String = getString(R.string.grade_weight)
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
presenter.detachView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.details
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.GONE
|
||||||
|
import android.view.View.VISIBLE
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractExpandableItem
|
||||||
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
import eu.davidea.viewholders.ExpandableViewHolder
|
||||||
|
import io.github.wulkanowy.R
|
||||||
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.header_grade_details.*
|
||||||
|
|
||||||
|
class GradeDetailsHeader(
|
||||||
|
private val subject: String,
|
||||||
|
private val number: String,
|
||||||
|
private val average: String,
|
||||||
|
var newGrades: Int)
|
||||||
|
: AbstractExpandableItem<GradeDetailsHeader.ViewHolder, GradeDetailsItem>() {
|
||||||
|
|
||||||
|
override fun getLayoutRes() = R.layout.header_grade_details
|
||||||
|
|
||||||
|
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?): ViewHolder {
|
||||||
|
return ViewHolder(view, adapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder,
|
||||||
|
position: Int, payloads: MutableList<Any>?) {
|
||||||
|
holder.run {
|
||||||
|
gradeHeaderSubject.text = subject
|
||||||
|
gradeHeaderAverage.text = average
|
||||||
|
gradeHeaderNumber.text = number
|
||||||
|
gradeHeaderPredicted.visibility = GONE
|
||||||
|
gradeHeaderFinal.visibility = GONE
|
||||||
|
|
||||||
|
gradeHeaderNote.visibility = if (newGrades > 0) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as GradeDetailsHeader
|
||||||
|
|
||||||
|
if (subject != other.subject) return false
|
||||||
|
if (number != other.number) return false
|
||||||
|
if (average != other.average) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = subject.hashCode()
|
||||||
|
result = 31 * result + number.hashCode()
|
||||||
|
result = 31 * result + average.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?) : ExpandableViewHolder(view, adapter),
|
||||||
|
LayoutContainer {
|
||||||
|
|
||||||
|
init {
|
||||||
|
contentView.setOnClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldNotifyParentOnClick() = true
|
||||||
|
|
||||||
|
override val containerView: View
|
||||||
|
get() = contentView
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.details
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
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.Grade
|
||||||
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.item_grade_details.*
|
||||||
|
|
||||||
|
class GradeDetailsItem(val grade: Grade, private val weightString: String, private val valueColor: Int)
|
||||||
|
: AbstractFlexibleItem<GradeDetailsItem.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun getLayoutRes() = R.layout.item_grade_details
|
||||||
|
|
||||||
|
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>): ViewHolder {
|
||||||
|
return ViewHolder(view, adapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder,
|
||||||
|
position: Int, payloads: MutableList<Any>?) {
|
||||||
|
holder.run {
|
||||||
|
gradeItemValue.run {
|
||||||
|
text = grade.entry
|
||||||
|
setBackgroundResource(valueColor)
|
||||||
|
}
|
||||||
|
gradeItemDescription.text = if (grade.description.isNotEmpty()) grade.description else grade.gradeSymbol
|
||||||
|
gradeItemDate.text = grade.date.toFormattedString()
|
||||||
|
gradeItemWeight.text = "$weightString: ${grade.weight}"
|
||||||
|
gradeItemNote.visibility = if (grade.isNew) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as GradeDetailsItem
|
||||||
|
|
||||||
|
if (grade != other.grade) return false
|
||||||
|
if (weightString != other.weightString) return false
|
||||||
|
if (valueColor != other.valueColor) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = grade.hashCode()
|
||||||
|
result = 31 * result + weightString.hashCode()
|
||||||
|
result = 31 * result + valueColor
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter),
|
||||||
|
LayoutContainer {
|
||||||
|
|
||||||
|
override val containerView: View
|
||||||
|
get() = contentView
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.details
|
||||||
|
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
import io.github.wulkanowy.data.ErrorHandler
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.data.repositories.GradeRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||||
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
|
import io.github.wulkanowy.utils.calcAverage
|
||||||
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
|
import io.github.wulkanowy.utils.valueColor
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class GradeDetailsPresenter @Inject constructor(
|
||||||
|
private val errorHandler: ErrorHandler,
|
||||||
|
private val schedulers: SchedulersManager,
|
||||||
|
private val gradeRepository: GradeRepository,
|
||||||
|
private val sessionRepository: SessionRepository) : BasePresenter<GradeDetailsView>(errorHandler) {
|
||||||
|
|
||||||
|
override fun attachView(view: GradeDetailsView) {
|
||||||
|
super.attachView(view)
|
||||||
|
view.initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadData(semesterId: String, forceRefresh: Boolean) {
|
||||||
|
disposable.add(sessionRepository.getSemesters()
|
||||||
|
.flatMap { gradeRepository.getGrades(it.first { item -> item.semesterId == semesterId }, forceRefresh) }
|
||||||
|
.map { createGradeItems(it.groupBy { grade -> grade.subject }.toSortedMap()) }
|
||||||
|
.subscribeOn(schedulers.backgroundThread())
|
||||||
|
.observeOn(schedulers.mainThread())
|
||||||
|
.doFinally {
|
||||||
|
view?.run {
|
||||||
|
showRefresh(false)
|
||||||
|
showProgress(false)
|
||||||
|
notifyParentDataLoaded(semesterId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.subscribe({
|
||||||
|
view?.run {
|
||||||
|
showEmpty(it.isEmpty())
|
||||||
|
showContent(it.isNotEmpty())
|
||||||
|
updateData(it)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
view?.run { showEmpty(isViewEmpty()) }
|
||||||
|
errorHandler.proceed(it)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onGradeItemSelected(item: AbstractFlexibleItem<*>?) {
|
||||||
|
if (item is GradeDetailsItem) {
|
||||||
|
view?.apply {
|
||||||
|
showGradeDialog(item.grade)
|
||||||
|
if (item.grade.isNew) {
|
||||||
|
item.grade.isNew = false
|
||||||
|
updateItem(item)
|
||||||
|
getHeaderOfItem(item)?.let { header ->
|
||||||
|
if (header is GradeDetailsHeader) {
|
||||||
|
header.newGrades--
|
||||||
|
updateItem(header)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateGrade(item.grade)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSwipeRefresh() {
|
||||||
|
view?.notifyParentRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onParentViewReselected() {
|
||||||
|
view?.run {
|
||||||
|
if (!isViewEmpty()) resetView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onParentChangeSemester() {
|
||||||
|
view?.run {
|
||||||
|
showProgress(true)
|
||||||
|
showRefresh(false)
|
||||||
|
showContent(false)
|
||||||
|
showEmpty(false)
|
||||||
|
clearView()
|
||||||
|
}
|
||||||
|
disposable.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGradeItems(items: Map<String, List<Grade>>): List<GradeDetailsHeader> {
|
||||||
|
return items.map {
|
||||||
|
it.value.calcAverage().let { average ->
|
||||||
|
GradeDetailsHeader(
|
||||||
|
subject = it.key,
|
||||||
|
average = formatAverage(average),
|
||||||
|
number = view?.gradeNumberString(it.value.size).orEmpty(),
|
||||||
|
newGrades = it.value.filter { grade -> grade.isNew }.size
|
||||||
|
).apply {
|
||||||
|
subItems = it.value.map { item ->
|
||||||
|
GradeDetailsItem(
|
||||||
|
grade = item,
|
||||||
|
weightString = view?.weightString().orEmpty(),
|
||||||
|
valueColor = item.valueColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatAverage(average: Double): String {
|
||||||
|
return view?.run {
|
||||||
|
if (average == 0.0) emptyAverageString()
|
||||||
|
else averageString().format(average)
|
||||||
|
}.orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateGrade(grade: Grade) {
|
||||||
|
disposable.add(gradeRepository.updateGrade(grade)
|
||||||
|
.subscribeOn(schedulers.backgroundThread())
|
||||||
|
.observeOn(schedulers.mainThread())
|
||||||
|
.subscribe({}) { error -> errorHandler.proceed(error) })
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.details
|
||||||
|
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
import eu.davidea.flexibleadapter.items.IExpandable
|
||||||
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
|
||||||
|
interface GradeDetailsView : BaseView {
|
||||||
|
|
||||||
|
fun initView()
|
||||||
|
|
||||||
|
fun updateData(data: List<GradeDetailsHeader>)
|
||||||
|
|
||||||
|
fun updateItem(item: AbstractFlexibleItem<*>)
|
||||||
|
|
||||||
|
fun getHeaderOfItem(item: AbstractFlexibleItem<*>): IExpandable<*, out IFlexible<*>>?
|
||||||
|
|
||||||
|
fun resetView()
|
||||||
|
|
||||||
|
fun clearView()
|
||||||
|
|
||||||
|
fun isViewEmpty(): Boolean
|
||||||
|
|
||||||
|
fun showGradeDialog(grade: Grade)
|
||||||
|
|
||||||
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
|
fun showRefresh(show: Boolean)
|
||||||
|
|
||||||
|
fun emptyAverageString(): String
|
||||||
|
|
||||||
|
fun averageString(): String
|
||||||
|
|
||||||
|
fun gradeNumberString(number: Int): String
|
||||||
|
|
||||||
|
fun weightString(): String
|
||||||
|
|
||||||
|
fun notifyParentDataLoaded(semesterId: String)
|
||||||
|
|
||||||
|
fun notifyParentRefresh()
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.summary
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
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.ui.base.BaseFragment
|
||||||
|
import io.github.wulkanowy.ui.main.grade.GradeFragment
|
||||||
|
import io.github.wulkanowy.ui.main.grade.GradeView
|
||||||
|
import kotlinx.android.synthetic.main.fragment_grade_summary.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class GradeSummaryFragment : BaseFragment(), GradeSummaryView, GradeView.GradeChildView {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var presenter: GradeSummaryPresenter
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var gradeSummaryAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance() = GradeSummaryFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.fragment_grade_summary, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
presenter.attachView(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initView() {
|
||||||
|
gradeSummaryAdapter.setDisplayHeadersAtStartUp(true)
|
||||||
|
|
||||||
|
gradeSummaryRecycler.run {
|
||||||
|
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||||
|
adapter = gradeSummaryAdapter
|
||||||
|
}
|
||||||
|
gradeSummarySwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDataSet(data: List<GradeSummaryItem>, header: GradeSummaryScrollableHeader) {
|
||||||
|
gradeSummaryAdapter.apply {
|
||||||
|
updateDataSet(data, true)
|
||||||
|
removeAllScrollableHeaders()
|
||||||
|
addScrollableHeader(header)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearView() {
|
||||||
|
gradeSummaryAdapter.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resetView() {
|
||||||
|
gradeSummaryAdapter.smoothScrollToPosition(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isViewEmpty() = gradeSummaryAdapter.isEmpty
|
||||||
|
|
||||||
|
override fun showContent(show: Boolean) {
|
||||||
|
gradeSummaryRecycler.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showEmpty(show: Boolean) {
|
||||||
|
gradeSummaryEmpty.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showProgress(show: Boolean) {
|
||||||
|
gradeSummaryProgress.visibility = if (show) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showRefresh(show: Boolean) {
|
||||||
|
gradeSummarySwipe.isRefreshing = show
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onParentLoadData(semesterId: String, forceRefresh: Boolean) {
|
||||||
|
presenter.loadData(semesterId, forceRefresh)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onParentReselected() {
|
||||||
|
presenter.onParentViewReselected()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onParentChangeSemester() {
|
||||||
|
presenter.onParentChangeSemester()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun notifyParentDataLoaded(semesterId: String) {
|
||||||
|
(parentFragment as? GradeFragment)?.onChildFragmentLoaded(semesterId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun notifyParentRefresh() {
|
||||||
|
(parentFragment as? GradeFragment)?.onChildRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun predictedString() = getString(R.string.grade_summary_predicted_grade)
|
||||||
|
|
||||||
|
override fun finalString() = getString(R.string.grade_summary_final_grade)
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
presenter.detachView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.summary
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
||||||
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
|
import io.github.wulkanowy.R
|
||||||
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.header_grade_summary.*
|
||||||
|
|
||||||
|
class GradeSummaryHeader(private val name: String, private val average: String) : AbstractHeaderItem<GradeSummaryHeader.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun getLayoutRes() = R.layout.header_grade_summary
|
||||||
|
|
||||||
|
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?): ViewHolder {
|
||||||
|
return ViewHolder(view, adapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder?,
|
||||||
|
position: Int, payloads: MutableList<Any>?) {
|
||||||
|
holder?.run {
|
||||||
|
gradeSummaryHeaderName.text = name
|
||||||
|
gradeSummaryHeaderAverage.text = average
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as GradeSummaryHeader
|
||||||
|
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (average != other.average) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = name.hashCode()
|
||||||
|
result = 31 * result + average.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?) :
|
||||||
|
FlexibleViewHolder(view, adapter), LayoutContainer {
|
||||||
|
|
||||||
|
override val containerView: View?
|
||||||
|
get() = contentView
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.summary
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
||||||
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
|
import io.github.wulkanowy.R
|
||||||
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.item_grade_summary.*
|
||||||
|
|
||||||
|
class GradeSummaryItem(header: GradeSummaryHeader, private val grade: String, private val title: String)
|
||||||
|
: AbstractSectionableItem<GradeSummaryItem.ViewHolder, GradeSummaryHeader>(header) {
|
||||||
|
|
||||||
|
override fun getLayoutRes() = R.layout.item_grade_summary
|
||||||
|
|
||||||
|
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?): ViewHolder {
|
||||||
|
return ViewHolder(view, adapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder?,
|
||||||
|
position: Int, payloads: MutableList<Any>?) {
|
||||||
|
holder?.run {
|
||||||
|
gradeSummaryItemGrade.text = grade
|
||||||
|
gradeSummaryItemTitle.text = title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as GradeSummaryItem
|
||||||
|
|
||||||
|
if (grade != other.grade) return false
|
||||||
|
if (title != other.title) return false
|
||||||
|
if (header != other.header) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = header.hashCode()
|
||||||
|
result = 31 * result + grade.hashCode()
|
||||||
|
result = 31 * result + title.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?)
|
||||||
|
: FlexibleViewHolder(view, adapter), LayoutContainer {
|
||||||
|
|
||||||
|
override val containerView: View?
|
||||||
|
get() = contentView
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.summary
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.ErrorHandler
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
|
import io.github.wulkanowy.data.repositories.GradeRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.GradeSummaryRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||||
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
|
import io.github.wulkanowy.utils.calcAverage
|
||||||
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
|
import java.lang.String.format
|
||||||
|
import java.util.Locale.FRANCE
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class GradeSummaryPresenter @Inject constructor(
|
||||||
|
private val errorHandler: ErrorHandler,
|
||||||
|
private val gradeSummaryRepository: GradeSummaryRepository,
|
||||||
|
private val gradeRepository: GradeRepository,
|
||||||
|
private val sessionRepository: SessionRepository,
|
||||||
|
private val schedulers: SchedulersManager)
|
||||||
|
: BasePresenter<GradeSummaryView>(errorHandler) {
|
||||||
|
|
||||||
|
override fun attachView(view: GradeSummaryView) {
|
||||||
|
super.attachView(view)
|
||||||
|
view.initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadData(semesterId: String, forceRefresh: Boolean) {
|
||||||
|
disposable.add(sessionRepository.getSemesters()
|
||||||
|
.map { semester -> semester.first { it.semesterId == semesterId } }
|
||||||
|
.flatMap {
|
||||||
|
gradeSummaryRepository.getGradesSummary(it, forceRefresh)
|
||||||
|
.flatMap { gradesSummary ->
|
||||||
|
gradeRepository.getGrades(it, forceRefresh)
|
||||||
|
.map { grades ->
|
||||||
|
grades.groupBy { grade -> grade.subject }
|
||||||
|
.mapValues { entry -> entry.value.calcAverage() }
|
||||||
|
.filterValues { value -> value != 0.0 }
|
||||||
|
.let { averages ->
|
||||||
|
createGradeSummaryItems(gradesSummary, averages) to
|
||||||
|
GradeSummaryScrollableHeader(
|
||||||
|
formatAverage(gradesSummary.calcAverage()),
|
||||||
|
formatAverage(averages.values.average())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.subscribeOn(schedulers.backgroundThread())
|
||||||
|
.observeOn(schedulers.mainThread())
|
||||||
|
.doFinally {
|
||||||
|
view?.run {
|
||||||
|
showRefresh(false)
|
||||||
|
showProgress(false)
|
||||||
|
notifyParentDataLoaded(semesterId)
|
||||||
|
}
|
||||||
|
}.subscribe({
|
||||||
|
view?.run {
|
||||||
|
showEmpty(it.first.isEmpty())
|
||||||
|
showContent(it.first.isNotEmpty())
|
||||||
|
updateDataSet(it.first, it.second)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
view?.run { showEmpty(isViewEmpty()) }
|
||||||
|
errorHandler.proceed(it)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSwipeRefresh() {
|
||||||
|
view?.notifyParentRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onParentViewReselected() {
|
||||||
|
view?.run {
|
||||||
|
if (!isViewEmpty()) resetView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onParentChangeSemester() {
|
||||||
|
view?.run {
|
||||||
|
showProgress(true)
|
||||||
|
showRefresh(false)
|
||||||
|
showContent(false)
|
||||||
|
showEmpty(false)
|
||||||
|
clearView()
|
||||||
|
}
|
||||||
|
disposable.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGradeSummaryItems(gradesSummary: List<GradeSummary>, averages: Map<String, Double>)
|
||||||
|
: List<GradeSummaryItem> {
|
||||||
|
return gradesSummary.filter { !checkEmpty(it, averages) }
|
||||||
|
.flatMap { gradeSummary ->
|
||||||
|
GradeSummaryHeader(
|
||||||
|
name = gradeSummary.subject,
|
||||||
|
average = formatAverage(averages.getOrElse(gradeSummary.subject) { 0.0 }, "")
|
||||||
|
).let {
|
||||||
|
listOf(GradeSummaryItem(
|
||||||
|
header = it,
|
||||||
|
title = view?.predictedString().orEmpty(),
|
||||||
|
grade = gradeSummary.predictedGrade
|
||||||
|
), GradeSummaryItem(
|
||||||
|
header = it,
|
||||||
|
title = view?.finalString().orEmpty(),
|
||||||
|
grade = gradeSummary.finalGrade
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkEmpty(gradeSummary: GradeSummary, averages: Map<String, Double>): Boolean {
|
||||||
|
return gradeSummary.run {
|
||||||
|
finalGrade.isEmpty() && predictedGrade.isEmpty() && averages[subject] == null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatAverage(average: Double, defaultValue: String = "-- --"): String {
|
||||||
|
return if (average == 0.0 || average.isNaN()) defaultValue
|
||||||
|
else format(FRANCE, "%.2f", average)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.summary
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
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 kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.scrollable_header_grade_summary.*
|
||||||
|
|
||||||
|
class GradeSummaryScrollableHeader(private val finalAverage: String, private val calculatedAverage: String)
|
||||||
|
: AbstractFlexibleItem<GradeSummaryScrollableHeader.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun getLayoutRes() = R.layout.scrollable_header_grade_summary
|
||||||
|
|
||||||
|
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?): ViewHolder {
|
||||||
|
return ViewHolder(view, adapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder?,
|
||||||
|
position: Int, payloads: MutableList<Any>?) {
|
||||||
|
holder?.apply {
|
||||||
|
gradeSummaryScrollableHeaderFinal.text = finalAverage
|
||||||
|
gradeSummaryScrollableHeaderCalculated.text = calculatedAverage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as GradeSummaryScrollableHeader
|
||||||
|
|
||||||
|
if (calculatedAverage != other.calculatedAverage) return false
|
||||||
|
if (finalAverage != other.finalAverage) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = calculatedAverage.hashCode()
|
||||||
|
result = 31 * result + finalAverage.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?) : FlexibleViewHolder(view, adapter),
|
||||||
|
LayoutContainer {
|
||||||
|
|
||||||
|
override val containerView: View?
|
||||||
|
get() = contentView
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.grade.summary
|
||||||
|
|
||||||
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
|
||||||
|
interface GradeSummaryView : BaseView {
|
||||||
|
|
||||||
|
fun initView()
|
||||||
|
|
||||||
|
fun updateDataSet(data: List<GradeSummaryItem>, header: GradeSummaryScrollableHeader)
|
||||||
|
|
||||||
|
fun resetView()
|
||||||
|
|
||||||
|
fun clearView()
|
||||||
|
|
||||||
|
fun isViewEmpty(): Boolean
|
||||||
|
|
||||||
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
|
fun showRefresh(show: Boolean)
|
||||||
|
|
||||||
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
fun predictedString(): String
|
||||||
|
|
||||||
|
fun finalString(): String
|
||||||
|
|
||||||
|
fun notifyParentDataLoaded(semesterId: String)
|
||||||
|
|
||||||
|
fun notifyParentRefresh()
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package io.github.wulkanowy.utils.extension
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context.INPUT_METHOD_SERVICE
|
import android.content.Context.INPUT_METHOD_SERVICE
|
@ -1,40 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils;
|
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.AnimatorListenerAdapter;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
public final class AnimationUtils {
|
|
||||||
|
|
||||||
public static void slideDown(final View view) {
|
|
||||||
view.setVisibility(View.VISIBLE);
|
|
||||||
view.setAlpha(0.f);
|
|
||||||
|
|
||||||
view.setTranslationY(-(view.getHeight() / 2));
|
|
||||||
view.animate()
|
|
||||||
.translationY(0)
|
|
||||||
.alpha(1.f)
|
|
||||||
.setListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
view.setVisibility(View.VISIBLE);
|
|
||||||
view.setAlpha(1.f);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void slideUp(final View view) {
|
|
||||||
view.animate()
|
|
||||||
.translationY(-(view.getHeight() / 2))
|
|
||||||
.alpha(0.f)
|
|
||||||
.setListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
// superfluous restoration
|
|
||||||
view.setVisibility(View.GONE);
|
|
||||||
view.setAlpha(1.f);
|
|
||||||
view.setTranslationY(0.f);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
const val APP_NAME = "Wulkanowy"
|
|
||||||
|
|
||||||
const val DATABASE_NAME = "wulkanowy_db"
|
|
||||||
|
|
||||||
const val DEFAULT_SYMBOL = "Default"
|
|
||||||
|
|
||||||
const val DATE_PATTERN = "yyyy-MM-dd"
|
|
||||||
|
|
||||||
const val REPO_URL = "https://github.com/wulkanowy/wulkanowy"
|
|
@ -1,44 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.support.annotation.AttrRes;
|
|
||||||
import android.support.annotation.ColorInt;
|
|
||||||
|
|
||||||
import io.github.wulkanowy.R;
|
|
||||||
|
|
||||||
public final class CommonUtils {
|
|
||||||
|
|
||||||
private CommonUtils() {
|
|
||||||
throw new IllegalStateException("Utility class");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int colorHexToColorName(String hexColor) {
|
|
||||||
switch (hexColor) {
|
|
||||||
case "000000":
|
|
||||||
return R.string.all_black;
|
|
||||||
|
|
||||||
case "F04C4C":
|
|
||||||
return R.string.all_red;
|
|
||||||
|
|
||||||
case "20A4F7":
|
|
||||||
return R.string.all_blue;
|
|
||||||
|
|
||||||
case "6ECD07":
|
|
||||||
return R.string.all_green;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return R.string.all_empty_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
public static int getThemeAttrColor(Context context, @AttrRes int colorAttr) {
|
|
||||||
final TypedArray array = context.obtainStyledAttributes(null, new int[]{colorAttr});
|
|
||||||
try {
|
|
||||||
return array.getColor(0, 0);
|
|
||||||
} finally {
|
|
||||||
array.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils;
|
|
||||||
|
|
||||||
import com.crashlytics.android.answers.Answers;
|
|
||||||
import com.crashlytics.android.answers.CustomEvent;
|
|
||||||
import com.crashlytics.android.answers.LoginEvent;
|
|
||||||
import com.crashlytics.android.answers.SignUpEvent;
|
|
||||||
|
|
||||||
public final class FabricUtils {
|
|
||||||
|
|
||||||
private FabricUtils() {
|
|
||||||
throw new IllegalStateException("Utility class");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void logLogin(String method, boolean result) {
|
|
||||||
Answers.getInstance().logLogin(new LoginEvent()
|
|
||||||
.putMethod(method)
|
|
||||||
.putSuccess(result)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void logRegister(boolean result, String symbol, String message) {
|
|
||||||
Answers.getInstance().logSignUp(new SignUpEvent()
|
|
||||||
.putMethod("Login activity")
|
|
||||||
.putSuccess(result)
|
|
||||||
.putCustomAttribute("symbol", symbol)
|
|
||||||
.putCustomAttribute("message", message)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void logRefresh(String name, boolean result, String date) {
|
|
||||||
Answers.getInstance().logCustom(
|
|
||||||
new CustomEvent(name + " refresh")
|
|
||||||
.putCustomAttribute("Success", result ? "true" : "false")
|
|
||||||
.putCustomAttribute("Date", date)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,10 @@
|
|||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
|
||||||
|
inline fun FlexibleAdapter<*>.setOnItemClickListener(crossinline listener: (position: Int) -> Unit) {
|
||||||
|
addListener(FlexibleAdapter.OnItemClickListener { _, position ->
|
||||||
|
listener(position)
|
||||||
|
true
|
||||||
|
})
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import android.support.v4.app.Fragment
|
||||||
|
import com.ncapdevi.fragnav.FragNavController
|
||||||
|
|
||||||
|
inline fun FragNavController.setOnTabTransactionListener(crossinline listener: (index: Int) -> Unit) {
|
||||||
|
transactionListener = object : FragNavController.TransactionListener {
|
||||||
|
override fun onFragmentTransaction(fragment: Fragment?, transactionType: FragNavController.TransactionType) {}
|
||||||
|
override fun onTabTransaction(fragment: Fragment?, index: Int) {
|
||||||
|
listener(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import io.github.wulkanowy.R
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
|
|
||||||
|
fun List<Grade>.calcAverage(): Double {
|
||||||
|
var counter = 0.0
|
||||||
|
var denominator = 0.0
|
||||||
|
|
||||||
|
forEach {
|
||||||
|
counter += (it.value + it.modifier) * it.weightValue
|
||||||
|
denominator += it.weightValue
|
||||||
|
}
|
||||||
|
return if (denominator != 0.0) counter / denominator else 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("calcSummaryAverage")
|
||||||
|
fun List<GradeSummary>.calcAverage(): Double {
|
||||||
|
return asSequence().mapNotNull {
|
||||||
|
if (it.finalGrade.matches("[0-6]".toRegex())) it.finalGrade.toDouble() else null
|
||||||
|
}.average()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline val Grade.valueColor: Int
|
||||||
|
get() {
|
||||||
|
return when (value) {
|
||||||
|
6 -> R.color.grade_six
|
||||||
|
5 -> R.color.grade_five
|
||||||
|
4 -> R.color.grade_four
|
||||||
|
3 -> R.color.grade_three
|
||||||
|
2 -> R.color.grade_two
|
||||||
|
1 -> R.color.grade_one
|
||||||
|
else -> R.color.grade_default
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline val Grade.colorStringId: Int
|
||||||
|
get() {
|
||||||
|
return when (color) {
|
||||||
|
"000000" -> R.string.all_black
|
||||||
|
"F04C4C" -> R.string.all_red
|
||||||
|
"20A4F7" -> R.string.all_blue
|
||||||
|
"6ECD07" -> R.string.all_green
|
||||||
|
else -> R.string.all_empty_color
|
||||||
|
}
|
||||||
|
}
|
@ -1,166 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils;
|
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public final class GradeUtils {
|
|
||||||
|
|
||||||
private final static Pattern validGradePattern = Pattern.compile("^(\\++|-|--|=)?[0-6](\\++|-|--|=)?$");
|
|
||||||
private final static Pattern simpleGradeValuePattern = Pattern.compile("([0-6])");
|
|
||||||
|
|
||||||
private GradeUtils() {
|
|
||||||
throw new IllegalStateException("Utility class");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*public static float calculateWeightedAverage(List<Grade> gradeList) {
|
|
||||||
|
|
||||||
float counter = 0f;
|
|
||||||
float denominator = 0f;
|
|
||||||
|
|
||||||
for (Grade grade : gradeList) {
|
|
||||||
int weight = getWeightValue(grade.getWeight());
|
|
||||||
float value = getWeightedGradeValue(grade.getValue());
|
|
||||||
|
|
||||||
if (value != -1.0f) {
|
|
||||||
counter += value * weight;
|
|
||||||
denominator += weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counter == 0f) {
|
|
||||||
return -1.0f;
|
|
||||||
}
|
|
||||||
return counter / denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float calculateSubjectsAverage(List<Subject> subjectList, boolean usePredicted) {
|
|
||||||
return calculateSubjectsAverage(subjectList, usePredicted, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float calculateDetailedSubjectsAverage(List<Subject> subjectList) {
|
|
||||||
return calculateSubjectsAverage(subjectList, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getValueColor(String value) {
|
|
||||||
Matcher m1 = validGradePattern.matcher(value);
|
|
||||||
if (!m1.find()) {
|
|
||||||
return R.color.grade_default;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher m2 = simpleGradeValuePattern.matcher(m1.group());
|
|
||||||
if (!m2.find()) {
|
|
||||||
return R.color.grade_default;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (Integer.parseInt(m2.group())) {
|
|
||||||
case 6:
|
|
||||||
return R.color.grade_six;
|
|
||||||
case 5:
|
|
||||||
return R.color.grade_five;
|
|
||||||
case 4:
|
|
||||||
return R.color.grade_four;
|
|
||||||
case 3:
|
|
||||||
return R.color.grade_three;
|
|
||||||
case 2:
|
|
||||||
return R.color.grade_two;
|
|
||||||
case 1:
|
|
||||||
return R.color.grade_one;
|
|
||||||
default:
|
|
||||||
return R.color.grade_default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float calculateSubjectsAverage(List<Subject> subjectList, boolean usePredicted, boolean useSubjectsAverages) {
|
|
||||||
float counter = 0f;
|
|
||||||
float denominator = 0f;
|
|
||||||
|
|
||||||
for (Subject subject : subjectList) {
|
|
||||||
float value;
|
|
||||||
|
|
||||||
if (useSubjectsAverages) {
|
|
||||||
value = calculateWeightedAverage(subject.getGradeList());
|
|
||||||
} else {
|
|
||||||
value = getGradeValue(usePredicted ? subject.getPredictedRating() : subject.getFinalRating());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value != -1.0f) {
|
|
||||||
counter += Math.round(value);
|
|
||||||
denominator++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counter == 0) {
|
|
||||||
return -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return counter / denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float getGradeValue(String grade) {
|
|
||||||
if (validGradePattern.matcher(grade).matches()) {
|
|
||||||
return getWeightedGradeValue(grade);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getVerbalGradeValue(grade);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float getVerbalGradeValue(String grade) {
|
|
||||||
switch (grade) {
|
|
||||||
case "celujący":
|
|
||||||
return 6f;
|
|
||||||
case "bardzo dobry":
|
|
||||||
return 5f;
|
|
||||||
case "dobry":
|
|
||||||
return 4f;
|
|
||||||
case "dostateczny":
|
|
||||||
return 3f;
|
|
||||||
case "dopuszczający":
|
|
||||||
return 2f;
|
|
||||||
case "niedostateczny":
|
|
||||||
return 1f;
|
|
||||||
default:
|
|
||||||
return -1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getShortGradeValue(String grade) {
|
|
||||||
switch (grade) {
|
|
||||||
case "celujący":
|
|
||||||
return "6";
|
|
||||||
case "bardzo dobry":
|
|
||||||
return "5";
|
|
||||||
case "dobry":
|
|
||||||
return "4";
|
|
||||||
case "dostateczny":
|
|
||||||
return "3";
|
|
||||||
case "dopuszczający":
|
|
||||||
return "2";
|
|
||||||
case "niedostateczny":
|
|
||||||
return "1";
|
|
||||||
default:
|
|
||||||
return grade;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float getWeightedGradeValue(String value) {
|
|
||||||
if (validGradePattern.matcher(value).matches()) {
|
|
||||||
if (value.matches("[-][0-6]") || value.matches("[0-6][-]")) {
|
|
||||||
String replacedValue = value.replaceAll("[-]", "");
|
|
||||||
return Float.valueOf(replacedValue) - 0.33f;
|
|
||||||
} else if (value.matches("[+][0-6]") || value.matches("[0-6][+]")) {
|
|
||||||
String replacedValue = value.replaceAll("[+]", "");
|
|
||||||
return Float.valueOf((replacedValue)) + 0.33f;
|
|
||||||
} else if (value.matches("[-|=]{1,2}[0-6]") || value.matches("[0-6][-|=]{1,2}")) {
|
|
||||||
String replacedValue = value.replaceAll("[-|=]{1,2}", "");
|
|
||||||
return Float.valueOf((replacedValue)) - 0.5f;
|
|
||||||
} else {
|
|
||||||
return Float.valueOf(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getWeightValue(String weightOfGrade) {
|
|
||||||
return Integer.valueOf(weightOfGrade.substring(0, weightOfGrade.length() - 3));
|
|
||||||
}*/
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils;
|
|
||||||
|
|
||||||
import android.os.Build;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.crashlytics.android.Crashlytics;
|
|
||||||
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
public final class LoggerUtils {
|
|
||||||
|
|
||||||
public static class CrashlyticsTree extends Timber.Tree {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void log(int priority, @Nullable String tag, @Nullable String message, @Nullable Throwable t) {
|
|
||||||
Crashlytics.setInt("priority", priority);
|
|
||||||
Crashlytics.setString("tag", tag);
|
|
||||||
|
|
||||||
if (t == null) {
|
|
||||||
Crashlytics.log(message);
|
|
||||||
} else {
|
|
||||||
Crashlytics.setString("message", message);
|
|
||||||
Crashlytics.logException(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DebugLogTree extends Timber.DebugTree {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void log(int priority, String tag, @NonNull String message, Throwable t) {
|
|
||||||
if ("HUAWEI".equals(Build.MANUFACTURER) || "samsung".equals(Build.MANUFACTURER)) {
|
|
||||||
if (priority == Log.VERBOSE || priority == Log.DEBUG || priority == Log.INFO) {
|
|
||||||
priority = Log.ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.log(priority, AppConstantKt.APP_NAME, message, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String createStackElementTag(@NonNull StackTraceElement element) {
|
|
||||||
return super.createStackElementTag(element) + " - " + element.getLineNumber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
27
app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt
Normal file
27
app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import com.crashlytics.android.Crashlytics
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
object CrashlyticsTree : Timber.Tree() {
|
||||||
|
|
||||||
|
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||||
|
Crashlytics.setInt("priority", priority)
|
||||||
|
Crashlytics.setString("tag", tag)
|
||||||
|
|
||||||
|
if (t == null) {
|
||||||
|
Crashlytics.log(message)
|
||||||
|
} else {
|
||||||
|
Crashlytics.setString("message", message)
|
||||||
|
Crashlytics.logException(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object DebugLogTree : Timber.DebugTree() {
|
||||||
|
|
||||||
|
override fun createStackElementTag(element: StackTraceElement): String? {
|
||||||
|
return super.createStackElementTag(element) + " - ${element.lineNumber}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
87
app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt
Normal file
87
app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import org.threeten.bp.DayOfWeek.*
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import org.threeten.bp.format.DateTimeFormatter
|
||||||
|
import org.threeten.bp.format.DateTimeFormatter.ofPattern
|
||||||
|
import org.threeten.bp.temporal.TemporalAdjusters
|
||||||
|
import org.threeten.bp.temporal.TemporalAdjusters.*
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
private const val DATE_PATTERN = "yyyy-MM-dd"
|
||||||
|
|
||||||
|
fun Date.toLocalDate(): LocalDate {
|
||||||
|
return LocalDate.parse(SimpleDateFormat(DATE_PATTERN, Locale.getDefault()).format(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
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(): String = this.toFormattedString(DATE_PATTERN)
|
||||||
|
|
||||||
|
inline val LocalDate.nextWorkDay: LocalDate
|
||||||
|
get() {
|
||||||
|
return when (this.dayOfWeek) {
|
||||||
|
FRIDAY, SATURDAY, SUNDAY -> this.with(next(MONDAY))
|
||||||
|
else -> this.plusDays(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline val LocalDate.previousWorkDay: LocalDate
|
||||||
|
get() {
|
||||||
|
return when (this.dayOfWeek) {
|
||||||
|
SATURDAY, SUNDAY, MONDAY -> this.with(previous(FRIDAY))
|
||||||
|
else -> this.minusDays(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline val LocalDate.nearSchoolDayPrevOnWeekEnd: LocalDate
|
||||||
|
get() {
|
||||||
|
return when (this.dayOfWeek) {
|
||||||
|
SATURDAY, SUNDAY -> this.with(previous(FRIDAY))
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline val LocalDate.nearSchoolDayNextOnWeekEnd: LocalDate
|
||||||
|
get() {
|
||||||
|
return when (this.dayOfWeek) {
|
||||||
|
SATURDAY, SUNDAY -> this.with(next(MONDAY))
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline val LocalDate.weekDayName: String
|
||||||
|
get() = this.format(ofPattern("EEEE", Locale.getDefault()))
|
||||||
|
|
||||||
|
inline val LocalDate.weekFirstDayAlwaysCurrent: LocalDate
|
||||||
|
get() = this.with(TemporalAdjusters.previousOrSame(MONDAY))
|
||||||
|
|
||||||
|
inline val LocalDate.weekFirstDayNextOnWeekEnd: LocalDate
|
||||||
|
get() {
|
||||||
|
return when (this.dayOfWeek) {
|
||||||
|
SATURDAY, SUNDAY -> this.with(next(MONDAY))
|
||||||
|
else -> this.with(previousOrSame(MONDAY))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Dz.U. 2016 poz. 1335](http://prawo.sejm.gov.pl/isap.nsf/DocDetails.xsp?id=WDU20160001335)
|
||||||
|
*/
|
||||||
|
inline val LocalDate.isHolidays: Boolean
|
||||||
|
get() {
|
||||||
|
return LocalDate.of(this.year, 9, 1).run {
|
||||||
|
when (dayOfWeek) {
|
||||||
|
FRIDAY, SATURDAY, SUNDAY -> with(firstInMonth(MONDAY))
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
}.let { firstSchoolDay ->
|
||||||
|
LocalDate.of(this.year, 6, 20)
|
||||||
|
.with(next(FRIDAY))
|
||||||
|
.let { lastSchoolDay -> this.isBefore(firstSchoolDay) && this.isAfter(lastSchoolDay) }
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,12 @@
|
|||||||
package io.github.wulkanowy.utils.extension
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
import android.support.v4.view.ViewPager
|
import android.support.v4.view.ViewPager
|
||||||
|
|
||||||
fun ViewPager.setOnSelectPageListener(selectListener: (position: Int) -> Unit) {
|
inline fun ViewPager.setOnSelectPageListener(crossinline selectListener: (position: Int) -> Unit) {
|
||||||
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
selectListener(position)
|
selectListener(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageScrollStateChanged(state: Int) {}
|
override fun onPageScrollStateChanged(state: Int) {}
|
||||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||||
})
|
})
|
@ -1,15 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils.extension
|
|
||||||
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
|
||||||
|
|
||||||
fun FlexibleAdapter<*>.setOnItemClickListener(listener: (position: Int) -> Unit) {
|
|
||||||
addListener(FlexibleAdapter.OnItemClickListener { _, position ->
|
|
||||||
listener(position)
|
|
||||||
true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun FlexibleAdapter<*>.setOnUpdateListener(listener: (size: Int) -> Unit) {
|
|
||||||
addListener(FlexibleAdapter.OnUpdateListener { listener(it) })
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils.extension
|
|
||||||
|
|
||||||
import io.github.wulkanowy.utils.DATE_PATTERN
|
|
||||||
import org.threeten.bp.*
|
|
||||||
import org.threeten.bp.format.DateTimeFormatter
|
|
||||||
import org.threeten.bp.temporal.TemporalAdjusters
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
fun Date.toLocalDate(): LocalDate = LocalDate.parse(SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(this))
|
|
||||||
|
|
||||||
fun String.toDate(format: String = "yyyy-MM-dd"): LocalDate = LocalDate.parse(this, DateTimeFormatter.ofPattern(format))
|
|
||||||
|
|
||||||
fun LocalDate.toFormat(format: String): String = this.format(DateTimeFormatter.ofPattern(format))
|
|
||||||
|
|
||||||
fun LocalDate.toFormat(): String = this.toFormat(DATE_PATTERN)
|
|
||||||
|
|
||||||
fun LocalDate.getNextWorkDay(): LocalDate {
|
|
||||||
return when(this.dayOfWeek) {
|
|
||||||
DayOfWeek.FRIDAY, DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> this.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
|
|
||||||
else -> this.plusDays(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LocalDate.getPreviousWorkDay(): LocalDate {
|
|
||||||
return when(this.dayOfWeek) {
|
|
||||||
DayOfWeek.SATURDAY, DayOfWeek.SUNDAY, DayOfWeek.MONDAY -> this.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY))
|
|
||||||
else -> this.minusDays(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LocalDate.getNearSchoolDayPrevOnWeekEnd(): LocalDate {
|
|
||||||
return when(this.dayOfWeek) {
|
|
||||||
DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> this.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY))
|
|
||||||
else -> this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LocalDate.getNearSchoolDayNextOnWeekEnd(): LocalDate {
|
|
||||||
return when(this.dayOfWeek) {
|
|
||||||
DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> this.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
|
|
||||||
else -> this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LocalDate.getWeekDayName(): String = this.format(DateTimeFormatter.ofPattern("EEEE", Locale.getDefault()))
|
|
||||||
|
|
||||||
fun LocalDate.getWeekFirstDayAlwaysCurrent(): LocalDate {
|
|
||||||
return this.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LocalDate.getWeekFirstDayNextOnWeekEnd(): LocalDate {
|
|
||||||
return when(this.dayOfWeek) {
|
|
||||||
DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> this.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
|
|
||||||
else -> this.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [Dz.U. 2016 poz. 1335](http://prawo.sejm.gov.pl/isap.nsf/DocDetails.xsp?id=WDU20160001335)
|
|
||||||
*/
|
|
||||||
fun LocalDate.isHolidays(): Boolean = this.isAfter(this.getLastSchoolDay()) && this.isBefore(this.getFirstSchoolDay())
|
|
||||||
|
|
||||||
fun LocalDate.getSchoolYear(): Int = if (this.monthValue <= 8) this.year - 1 else this.year
|
|
||||||
|
|
||||||
fun LocalDate.getFirstSchoolDay(): LocalDate {
|
|
||||||
return LocalDate.of(this.year, 9, 1).run {
|
|
||||||
when (dayOfWeek) {
|
|
||||||
DayOfWeek.FRIDAY, DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY))
|
|
||||||
else -> this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LocalDate.getLastSchoolDay(): LocalDate {
|
|
||||||
return LocalDate
|
|
||||||
.of(this.year, 6, 20)
|
|
||||||
.with(TemporalAdjusters.next(DayOfWeek.FRIDAY))
|
|
||||||
}
|
|
@ -12,7 +12,6 @@ import android.security.keystore.KeyGenParameterSpec
|
|||||||
import android.security.keystore.KeyProperties.*
|
import android.security.keystore.KeyProperties.*
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.Base64.DEFAULT
|
import android.util.Base64.DEFAULT
|
||||||
import org.apache.commons.lang3.StringUtils
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
@ -76,7 +75,7 @@ object Scrambler {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun decrypt(cipherText: String): String {
|
fun decrypt(cipherText: String): String {
|
||||||
if (StringUtils.isEmpty(cipherText)) throw ScramblerException("Text to be encrypted is empty")
|
if (cipherText.isEmpty()) throw ScramblerException("Text to be encrypted is empty")
|
||||||
|
|
||||||
if (SDK_INT < JELLY_BEAN_MR2 || cipherText.length < 250) {
|
if (SDK_INT < JELLY_BEAN_MR2 || cipherText.length < 250) {
|
||||||
return String(Base64.decode(cipherText.toByteArray(KEY_CHARSET), DEFAULT), KEY_CHARSET)
|
return String(Base64.decode(cipherText.toByteArray(KEY_CHARSET), DEFAULT), KEY_CHARSET)
|
||||||
|
BIN
app/src/main/res/drawable-v15/img_splash_logo.png
Normal file
BIN
app/src/main/res/drawable-v15/img_splash_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
@ -1,5 +1,9 @@
|
|||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:opacity="opaque">
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="#FFF" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<bitmap
|
<bitmap
|
||||||
android:gravity="left|right|top|bottom"
|
android:gravity="left|right|top|bottom"
|
BIN
app/src/main/res/drawable-v23/img_splash_logo.png
Normal file
BIN
app/src/main/res/drawable-v23/img_splash_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
12
app/src/main/res/drawable-v23/layer_splash_background.xml
Normal file
12
app/src/main/res/drawable-v23/layer_splash_background.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="#FFF" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:drawable="@drawable/img_splash_logo" />
|
||||||
|
</layer-list>
|
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
Before Width: | Height: | Size: 49 KiB |
BIN
app/src/main/res/drawable/img_timetable_widget_preview.webp
Normal file
BIN
app/src/main/res/drawable/img_timetable_widget_preview.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
@ -1,19 +1,33 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/mainContainer"
|
android:id="@+id/mainContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:orientation="vertical">
|
|
||||||
|
<android.support.design.widget.AppBarLayout
|
||||||
|
android:id="@+id/mainAppBarContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:elevation="0dp">
|
||||||
|
|
||||||
|
<android.support.v7.widget.Toolbar
|
||||||
|
android:id="@+id/mainToolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize" />
|
||||||
|
|
||||||
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/mainFragmentContainer"
|
android:id="@+id/mainFragmentContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1" />
|
android:layout_marginBottom="@dimen/bottom_navigation_height"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||||
|
|
||||||
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
|
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
|
||||||
android:id="@+id/mainBottomNav"
|
android:id="@+id/mainBottomNav"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom" />
|
android:layout_gravity="bottom" />
|
||||||
</LinearLayout>
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
@ -5,45 +5,42 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minWidth="300dp"
|
android:minWidth="300dp">
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="15dp"
|
android:layout_marginTop="15dp"
|
||||||
android:padding="20dp"
|
android:padding="20dp"
|
||||||
tools:ignore="UselessParent">
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_value"
|
android:id="@+id/gradeDialogValue"
|
||||||
android:layout_width="80dp"
|
android:layout_width="80dp"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
|
android:background="@color/grade_default"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textColor="@color/grade_text"
|
android:textColor="@color/grade_text"
|
||||||
android:background="@color/grade_default"
|
|
||||||
android:textSize="30sp" />
|
android:textSize="30sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_subject"
|
android:id="@+id/gradeDialogSubject"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_gravity="start"
|
android:layout_gravity="start"
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:layout_marginEnd="90dp"
|
android:layout_marginEnd="90dp"
|
||||||
android:layout_marginRight="90dp"
|
android:layout_marginRight="90dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:maxLines="5"
|
android:maxLines="5"
|
||||||
android:minHeight="80dp"
|
android:minHeight="80dp"
|
||||||
@ -53,134 +50,157 @@
|
|||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_description"
|
android:id="@+id/gradeDialogDescription"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogSubject"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_subject"
|
android:layout_alignParentLeft="true"
|
||||||
android:text="@string/all_description"
|
android:text="@string/all_description"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_description_value"
|
android:id="@+id/gradeDialogDescriptionValue"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogDescription"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_description"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/all_no_description"
|
android:text="@string/all_no_description"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_weight"
|
android:id="@+id/gradeDialogWeight"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogDescriptionValue"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_description_value"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="@string/grade_weight"
|
android:text="@string/grade_weight"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_weight_value"
|
android:id="@+id/gradeDialogWeightValue"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogWeight"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_weight"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/grade_weight"
|
android:text="@string/grade_weight"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_teacher"
|
android:id="@+id/gradeDialogComment"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogWeightValue"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_weight_value"
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:text="@string/grade_comment"
|
||||||
|
android:textSize="17sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/gradeDialogCommentValue"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/gradeDialogComment"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_marginTop="3dp"
|
||||||
|
android:text="@string/grade_comment"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/gradeDialogTeacher"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/gradeDialogCommentValue"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="@string/all_teacher"
|
android:text="@string/all_teacher"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_teacher_value"
|
android:id="@+id/gradeDialogTeacherValue"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogTeacher"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_teacher"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/all_teacher"
|
android:text="@string/all_teacher"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_color"
|
android:id="@+id/gradeDialogColor"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogTeacherValue"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_teacher_value"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="@string/all_color"
|
android:text="@string/all_color"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_color_value"
|
android:id="@+id/gradeDialogColorValue"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogColor"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_color"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/all_color"
|
android:text="@string/all_color"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_date"
|
android:id="@+id/gradeDialogDate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogColorValue"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_color_value"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="@string/all_date"
|
android:text="@string/all_date"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_dialog_date_value"
|
android:id="@+id/gradeDialogDateValue"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_below="@+id/gradeDialogDate"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/grade_dialog_date"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/all_date"
|
android:text="@string/all_date"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/grade_dialog_close_button"
|
android:id="@+id/gradeDialogClose"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignTop="@+id/gradeDialogDateValue"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignTop="@+id/grade_dialog_date_value"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_marginTop="25dp"
|
android:layout_marginTop="25dp"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:text="@string/all_close"
|
android:text="@string/all_close"
|
||||||
android:textColor="?android:attr/android:textColorSecondary"
|
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
|
android:textColor="?android:attr/android:textColorSecondary"
|
||||||
android:textSize="15sp" />
|
android:textSize="15sp" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -1,174 +1,33 @@
|
|||||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
android:id="@+id/grade_fragment_container"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<TextView
|
<android.support.design.widget.TabLayout
|
||||||
|
android:id="@+id/gradeTabLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/colorPrimary"
|
||||||
|
android:elevation="5dp"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:tabGravity="fill"
|
||||||
|
app:tabIndicatorColor="@android:color/white"
|
||||||
|
app:tabMaxWidth="0dp"
|
||||||
|
app:tabMode="fixed"
|
||||||
|
app:tabTextColor="@android:color/white" />
|
||||||
|
|
||||||
|
<android.support.v4.view.ViewPager
|
||||||
|
android:id="@+id/gradeViewPager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:layout_below="@id/gradeTabLayout"
|
||||||
android:text="Grade" />
|
android:visibility="invisible" />
|
||||||
|
|
||||||
<!--<android.support.v4.widget.SwipeRefreshLayout
|
<ProgressBar
|
||||||
android:id="@+id/grade_fragment_swipe_refresh"
|
android:id="@+id/gradeProgress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
<FrameLayout
|
android:indeterminate="true" />
|
||||||
android:layout_width="match_parent"
|
</RelativeLayout>
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/grade_fragment_details_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
|
||||||
android:id="@+id/grade_fragment_recycler"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<android.support.v4.widget.NestedScrollView
|
|
||||||
android:id="@+id/grade_fragment_summary_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:descendantFocusability="blocksDescendants">
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/grade_fragment_summary_calculated_container"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:layout_toLeftOf="@id/grade_fragment_summary_final_container"
|
|
||||||
android:layout_toStartOf="@id/grade_fragment_summary_final_container">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_fragment_summary_calculated_average_text"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/grades_summary_calculated_average"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_fragment_summary_calculated_average"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/grade_fragment_summary_calculated_average_text"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:text="6,00"
|
|
||||||
android:textSize="21sp" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/grade_fragment_summary_final_container"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:layout_marginRight="10dp"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:layout_marginTop="20dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_fragment_summary_final_average_text"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:gravity="center"
|
|
||||||
android:minLines="2"
|
|
||||||
android:text="@string/grades_summary_final_average"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_fragment_summary_final_average"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/grade_fragment_summary_final_average_text"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:text="6,00"
|
|
||||||
android:textSize="21sp" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/grade_fragment_summary_predicted_container"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:layout_marginRight="10dp"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:layout_toEndOf="@id/grade_fragment_summary_final_container"
|
|
||||||
android:layout_toRightOf="@id/grade_fragment_summary_final_container">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_fragment_summary_predicted_average_text"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:gravity="center"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:text="@string/grades_summary_predicted_average"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_fragment_summary_predicted_average"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/grade_fragment_summary_predicted_average_text"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:text="6,00"
|
|
||||||
android:textSize="21sp" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
|
||||||
android:id="@+id/grade_fragment_summary_recycler"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_below="@id/grade_fragment_summary_calculated_container"
|
|
||||||
android:layout_marginTop="20dp" />
|
|
||||||
</RelativeLayout>
|
|
||||||
</android.support.v4.widget.NestedScrollView>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/grade_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/grade_fragment_no_item_image"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/grade_fragment_no_item_text"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginTop="40dp"
|
|
||||||
android:minHeight="100dp"
|
|
||||||
android:minWidth="100dp"
|
|
||||||
app:srcCompat="@drawable/ic_menu_main_grade_26dp"
|
|
||||||
app:tint="?android:attr/textColorPrimary"
|
|
||||||
tools:ignore="contentDescription" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_fragment_no_item_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="46dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/fragment_no_grades"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
</RelativeLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>-->
|
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
|
50
app/src/main/res/layout/fragment_grade_details.xml
Normal file
50
app/src/main/res/layout/fragment_grade_details.xml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<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:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v4.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/gradeDetailsSwipe"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/gradeDetailsRecycler"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/gradeDetailsProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/gradeDetailsEmpty"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="invisible">
|
||||||
|
|
||||||
|
<android.support.v7.widget.AppCompatImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="100dp"
|
||||||
|
android:minHeight="100dp"
|
||||||
|
app:srcCompat="@drawable/ic_menu_main_grade_26dp"
|
||||||
|
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/grade_no_items"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
50
app/src/main/res/layout/fragment_grade_summary.xml
Normal file
50
app/src/main/res/layout/fragment_grade_summary.xml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<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:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v4.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/gradeSummarySwipe"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/gradeSummaryRecycler"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/gradeSummaryProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/gradeSummaryEmpty"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="invisible">
|
||||||
|
|
||||||
|
<android.support.v7.widget.AppCompatImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="100dp"
|
||||||
|
android:minHeight="100dp"
|
||||||
|
app:srcCompat="@drawable/ic_menu_main_grade_26dp"
|
||||||
|
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/grade_no_items"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
@ -68,7 +68,7 @@
|
|||||||
android:layout_marginBottom="15dp"
|
android:layout_marginBottom="15dp"
|
||||||
android:hint="@string/login_email_hint">
|
android:hint="@string/login_email_hint">
|
||||||
|
|
||||||
<EditText
|
<android.support.design.widget.TextInputEditText
|
||||||
android:id="@+id/loginEmailEdit"
|
android:id="@+id/loginEmailEdit"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -82,7 +82,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/login_password_hint">
|
android:hint="@string/login_password_hint">
|
||||||
|
|
||||||
<EditText
|
<android.support.design.widget.TextInputEditText
|
||||||
android:id="@+id/loginPassEdit"
|
android:id="@+id/loginPassEdit"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/timetable_fragment_container"
|
android:id="@+id/timetable_fragment_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@ -9,22 +9,4 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="Timetable" />
|
android:text="Timetable" />
|
||||||
|
</FrameLayout>
|
||||||
<!--<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<android.support.design.widget.TabLayout
|
|
||||||
android:id="@+id/timetable_fragment_tab_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:tabMinWidth="125dp"
|
|
||||||
app:tabMode="scrollable"/>
|
|
||||||
|
|
||||||
<android.support.v4.view.ViewPager
|
|
||||||
android:id="@+id/timetable_fragment_viewpager"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_below="@id/timetable_fragment_tab_layout" />
|
|
||||||
</RelativeLayout>-->
|
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
android:paddingBottom="16dp"
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
android:paddingRight="16dp"
|
||||||
android:paddingTop="@dimen/activity_vertical_margin">
|
android:paddingTop="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_header_day"
|
android:id="@+id/attendance_header_day"
|
||||||
|
@ -1,56 +1,57 @@
|
|||||||
<RelativeLayout 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:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tool="http://schemas.android.com/tools"
|
xmlns:tool="http://schemas.android.com/tools"
|
||||||
android:id="@+id/grade_header_container"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/ic_all_divider"
|
android:background="@drawable/ic_all_divider"
|
||||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
android:paddingBottom="10dp"
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
android:paddingRight="16dp"
|
||||||
android:paddingTop="@dimen/activity_vertical_margin">
|
android:paddingTop="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_header_subject_text"
|
android:id="@+id/gradeHeaderSubject"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="35dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:layout_marginRight="35dp"
|
android:layout_marginRight="20dp"
|
||||||
|
android:layout_toLeftOf="@id/gradeHeaderNote"
|
||||||
|
android:layout_toStartOf="@id/gradeHeaderNote"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textSize="17sp" />
|
android:textSize="15sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_header_average_text"
|
android:id="@+id/gradeHeaderAverage"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/grade_header_subject_text"
|
android:layout_below="@+id/gradeHeaderSubject"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textColor="?android:attr/android:textColorSecondary"
|
android:textColor="?android:attr/android:textColorSecondary"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_header_number_of_grade_text"
|
android:id="@+id/gradeHeaderNumber"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/grade_header_subject_text"
|
android:layout_below="@id/gradeHeaderSubject"
|
||||||
android:layout_marginLeft="10dp"
|
android:layout_marginLeft="10dp"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:layout_toEndOf="@+id/grade_header_average_text"
|
android:layout_toEndOf="@+id/gradeHeaderAverage"
|
||||||
android:layout_toRightOf="@+id/grade_header_average_text"
|
android:layout_toRightOf="@+id/gradeHeaderAverage"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textColor="?android:attr/android:textColorSecondary"
|
android:textColor="?android:attr/android:textColorSecondary"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_header_predicted_rating_text"
|
android:id="@+id/gradeHeaderPredicted"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/grade_header_average_text"
|
android:layout_below="@id/gradeHeaderAverage"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginRight="10dp"
|
android:layout_marginRight="10dp"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
@ -59,19 +60,19 @@
|
|||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grade_header_final_rating_text"
|
android:id="@+id/gradeHeaderFinal"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/grade_header_average_text"
|
android:layout_below="@id/gradeHeaderAverage"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:layout_toEndOf="@+id/grade_header_predicted_rating_text"
|
android:layout_toEndOf="@+id/gradeHeaderPredicted"
|
||||||
android:layout_toRightOf="@+id/grade_header_predicted_rating_text"
|
android:layout_toRightOf="@+id/gradeHeaderPredicted"
|
||||||
android:text="@string/grade_final"
|
android:text="@string/grade_final"
|
||||||
android:textColor="?android:attr/android:textColorSecondary"
|
android:textColor="?android:attr/android:textColorSecondary"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/grade_header_alert_image"
|
android:id="@+id/gradeHeaderNote"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
@ -9,19 +9,19 @@
|
|||||||
android:paddingTop="7dp">
|
android:paddingTop="7dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grades_summary_header_name"
|
android:id="@+id/gradeSummaryHeaderName"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginEnd="40dp"
|
android:layout_marginEnd="40dp"
|
||||||
android:layout_marginRight="40dp"
|
android:layout_marginRight="40dp"
|
||||||
android:layout_toLeftOf="@id/grades_summary_header_average"
|
android:layout_toLeftOf="@id/gradeSummaryHeaderAverage"
|
||||||
android:layout_toStartOf="@id/grades_summary_header_average"
|
android:layout_toStartOf="@id/gradeSummaryHeaderAverage"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/grades_summary_header_average"
|
android:id="@+id/gradeSummaryHeaderAverage"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
android:paddingBottom="16dp"
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
android:paddingRight="16dp"
|
||||||
android:paddingTop="@dimen/activity_vertical_margin">
|
android:paddingTop="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/timetable_header_day"
|
android:id="@+id/timetable_header_day"
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
<android.support.v7.widget.CardView 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/grade_subitem_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="5dp"
|
|
||||||
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">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_subitem_value"
|
|
||||||
android:layout_width="45dp"
|
|
||||||
android:layout_height="45dp"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:gravity="center"
|
|
||||||
android:maxLength="5"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textColor="@color/grade_text"
|
|
||||||
android:background="@color/grade_default"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_subitem_description"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_marginEnd="40dp"
|
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:layout_marginRight="40dp"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:layout_toEndOf="@+id/grade_subitem_value"
|
|
||||||
android:layout_toRightOf="@+id/grade_subitem_value"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:text="@string/all_description"
|
|
||||||
android:textSize="15sp"
|
|
||||||
tool:ignore="all" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_subitem_date"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignBottom="@+id/grade_subitem_value"
|
|
||||||
android:layout_alignLeft="@+id/grade_subitem_description"
|
|
||||||
android:layout_alignStart="@+id/grade_subitem_description"
|
|
||||||
android:text="@string/all_date"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/grade_subitem_weight"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_toEndOf="@+id/grade_subitem_date"
|
|
||||||
android:layout_toRightOf="@+id/grade_subitem_date"
|
|
||||||
android:layout_alignBottom="@+id/grade_subitem_value"
|
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:text="@string/grade_weight"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/grade_subitem_alert_image"
|
|
||||||
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_all_round_note_24dp"
|
|
||||||
tool:ignore="contentDescription" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
</android.support.v7.widget.CardView>
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user