Skip to content

Commit

Permalink
refactor:optimize the architecture of the network module
Browse files Browse the repository at this point in the history
  • Loading branch information
I-Info committed Oct 29, 2023
1 parent 0f0ae2b commit 321c98d
Show file tree
Hide file tree
Showing 29 changed files with 99 additions and 240 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,30 @@
IJH app for Android, a **work in progress** currently.

# Features

- [ ] All features supported by **WeJH**.
- [ ] Notifications.
- [ ] More...

# Architecture
The app follows the [official architecture guidance](https://developer.android.com/topic/architecture).

- data
The app follows
the [official architecture guidance](https://developer.android.com/topic/architecture).

![module.png](https://s2.loli.net/2023/10/29/EUNtaGgBVqdfvJz.png)

- data (repository -> data source)
- network (Retrofit/OkHttp)
- datastore (Protobuf)
- database (Room)
- UI

## UI
UI is built with [Jetpack Compose](https://developer.android.com/jetpack/compose) and

UI is built with [Jetpack Compose](https://developer.android.com/jetpack/compose) and
[Material Design 3](https://m3.material.io).

- Theme: IJH app uses the Dynamic color theme as possible, and provides a default theme for fallbacks.
- Theme: IJH app uses the Dynamic color theme as possible, and provides a default theme for
fallbacks.

## Dependency injection
IJH app uses DI(Dependency injection) between layers and uses [Hilt](https://developer.android.com/training/dependency-injection/hilt-android)
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/kotlin/com/zjutjh/ijh/ui/model/TermDayState.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.zjutjh.ijh.ui.model

import com.zjutjh.ijh.model.CampusInfo
import com.zjutjh.ijh.model.Term
import com.zjutjh.ijh.model.WeJhInfo
import java.time.DayOfWeek
import java.time.LocalDate

Expand Down Expand Up @@ -29,7 +29,7 @@ class TermDayState(
}
}

fun WeJhInfo.toTermDayState(): TermDayState {
fun CampusInfo.toTermDayState(): TermDayState {
val date = LocalDate.now()
val duration = date.toEpochDay() - termStartDate.toEpochDay()
val week: Long = duration / 7L + 1L
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package com.zjutjh.ijh.ui.viewmodel
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.zjutjh.ijh.data.CampusInfoRepository
import com.zjutjh.ijh.data.CourseRepository
import com.zjutjh.ijh.data.WeJhInfoRepository
import com.zjutjh.ijh.data.WeJhUserRepository
import com.zjutjh.ijh.model.Course
import com.zjutjh.ijh.model.Term
Expand Down Expand Up @@ -37,7 +37,7 @@ import javax.inject.Inject

@HiltViewModel
class CourseCalendarViewModel @Inject constructor(
weJhInfoRepository: WeJhInfoRepository,
campusInfoRepository: CampusInfoRepository,
weJhUserRepository: WeJhUserRepository,
private val courseRepository: CourseRepository,
) : ViewModel() {
Expand All @@ -53,7 +53,7 @@ class CourseCalendarViewModel @Inject constructor(
)

@OptIn(ExperimentalCoroutinesApi::class)
private val localTermDayState = weJhInfoRepository.infoStream
private val localTermDayState = campusInfoRepository.infoStream
.mapLatest {
it?.toTermDayState()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package com.zjutjh.ijh.ui.viewmodel
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.zjutjh.ijh.data.CampusInfoRepository
import com.zjutjh.ijh.data.CourseRepository
import com.zjutjh.ijh.data.WeJhInfoRepository
import com.zjutjh.ijh.data.WeJhUserRepository
import com.zjutjh.ijh.model.Course
import com.zjutjh.ijh.model.Session
Expand All @@ -26,7 +26,7 @@ import kotlin.time.toKotlinDuration
class HomeViewModel @Inject constructor(
weJhUserRepository: WeJhUserRepository,
private val courseRepository: CourseRepository,
private val weJhInfoRepository: WeJhInfoRepository,
private val campusInfoRepository: CampusInfoRepository,
) : ViewModel() {

private val timerFlow: Flow<Unit> = flow {
Expand Down Expand Up @@ -66,7 +66,7 @@ class HomeViewModel @Inject constructor(
private val termLocalRefreshChannel: MutableStateFlow<Unit> = MutableStateFlow(Unit)

@OptIn(ExperimentalCoroutinesApi::class)
val termDayState: StateFlow<LoadResult<TermDayState?>> = weJhInfoRepository.infoStream
val termDayState: StateFlow<LoadResult<TermDayState?>> = campusInfoRepository.infoStream
.combine(termLocalRefreshChannel) { t1, _ -> t1 }
.mapLatest {
it?.toTermDayState()
Expand Down Expand Up @@ -155,7 +155,7 @@ class HomeViewModel @Inject constructor(
}

private suspend fun refreshTerm(): Pair<Int, Term>? {
runCatching { weJhInfoRepository.sync() }
runCatching { campusInfoRepository.sync() }
.fold({
Log.i("Home", "Sync WeJhInfo succeed.")
return it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class ScheduleWidget : GlanceAppWidget() {
val entryPoint =
EntryPointAccessors.fromApplication<ScheduleWidgetReceiver.Repositories>(context)

val dayStateFlow = entryPoint.weJhInfoRepository.infoStream
val dayStateFlow = entryPoint.campusInfoRepository.infoStream
.map { it?.toTermDayState() }
val coursesFlow = dayStateFlow.flatMapLatest {
it ?: return@flatMapLatest flowOf(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.zjutjh.ijh.data.CampusInfoRepository
import com.zjutjh.ijh.data.CourseRepository
import com.zjutjh.ijh.data.WeJhInfoRepository
import com.zjutjh.ijh.work.ScheduleWidgetUpdater
import com.zjutjh.ijh.work.enqueueWidgetRefresh
import dagger.hilt.EntryPoint
Expand All @@ -25,7 +25,7 @@ class ScheduleWidgetReceiver : GlanceAppWidgetReceiver() {
@InstallIn(SingletonComponent::class)
interface Repositories {
val courseRepository: CourseRepository
val weJhInfoRepository: WeJhInfoRepository
val campusInfoRepository: CampusInfoRepository
}

override val glanceAppWidget = ScheduleWidget()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class ScheduleWidgetUpdater(

override suspend fun doWork(): Result {
val result = try {
val info = entryPoint.weJhInfoRepository.sync()
val info = entryPoint.campusInfoRepository.sync()
entryPoint.courseRepository.sync(info.first, info.second)

Log.i("ScheduleWidget", "Synced.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.time.LocalDate
import java.time.ZonedDateTime

@Stable
data class WeJhInfo(
data class CampusInfo(
val term: Term,
val year: Int,
val termStartDate: LocalDate,
Expand Down
11 changes: 11 additions & 0 deletions core/data/src/main/kotlin/com/zjutjh/ijh/data/BalanceRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.zjutjh.ijh.data

interface BalanceRepository {

/**
* Get balance directly from network, because the non-realtime data is useless
*
* @return balance (Unit: CNY) in string
*/
suspend fun getBalance(): String
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.zjutjh.ijh.data

import com.zjutjh.ijh.model.CampusInfo
import com.zjutjh.ijh.model.Term
import com.zjutjh.ijh.model.WeJhInfo
import kotlinx.coroutines.flow.Flow

interface WeJhInfoRepository {
val infoStream: Flow<WeJhInfo?>
interface CampusInfoRepository {
val infoStream: Flow<CampusInfo?>

/**
* Sync WeJhInfo from network to local
* Sync campus info from network to local
* @return Pair(year, term)
*/
suspend fun sync(): Pair<Int, Term>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.zjutjh.ijh.data.di

import com.zjutjh.ijh.data.CampusInfoRepository
import com.zjutjh.ijh.data.CourseRepository
import com.zjutjh.ijh.data.WeJhInfoRepository
import com.zjutjh.ijh.data.WeJhUserRepository
import com.zjutjh.ijh.data.impl.CampusInfoRepositoryImpl
import com.zjutjh.ijh.data.impl.CourseRepositoryImpl
import com.zjutjh.ijh.data.impl.WeJhInfoRepositoryImpl
import com.zjutjh.ijh.data.impl.WeJhUserRepositoryImpl
import dagger.Binds
import dagger.Module
Expand All @@ -22,5 +22,5 @@ interface DataModule {
fun bindWeJhUserRepository(impl: WeJhUserRepositoryImpl): WeJhUserRepository

@Binds
fun bindWeJhInfoRepository(impl: WeJhInfoRepositoryImpl): WeJhInfoRepository
fun bindWeJhInfoRepository(impl: CampusInfoRepositoryImpl): CampusInfoRepository
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package com.zjutjh.ijh.data.impl

import com.zjutjh.ijh.data.WeJhInfoRepository
import com.zjutjh.ijh.data.CampusInfoRepository
import com.zjutjh.ijh.datastore.WeJhPreferenceDataSource
import com.zjutjh.ijh.datastore.converter.asExternalModel
import com.zjutjh.ijh.datastore.model.infoOrNull
import com.zjutjh.ijh.model.CampusInfo
import com.zjutjh.ijh.model.Term
import com.zjutjh.ijh.model.WeJhInfo
import com.zjutjh.ijh.network.WeJhSystemDataSource
import com.zjutjh.ijh.network.CampusInfoNetworkDataSource
import com.zjutjh.ijh.network.model.asExternalModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class WeJhInfoRepositoryImpl @Inject constructor(
private val network: WeJhSystemDataSource,
class CampusInfoRepositoryImpl @Inject constructor(
private val network: CampusInfoNetworkDataSource,
private val local: WeJhPreferenceDataSource
) : WeJhInfoRepository {
) : CampusInfoRepository {

override val infoStream: Flow<WeJhInfo?> = local.data.map { it.infoOrNull?.asExternalModel() }
override val infoStream: Flow<CampusInfo?> = local.data.map { it.infoOrNull?.asExternalModel() }

override suspend fun sync(): Pair<Int, Term> {
val weJhInfo = network.getInfo().asExternalModel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.zjutjh.ijh.datastore.WeJhPreferenceDataSource
import com.zjutjh.ijh.datastore.converter.toZonedDateTime
import com.zjutjh.ijh.model.Course
import com.zjutjh.ijh.model.Term
import com.zjutjh.ijh.network.ZfDataSource
import com.zjutjh.ijh.network.CourseNetworkDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
Expand All @@ -23,7 +23,7 @@ import javax.inject.Singleton
*/
@Singleton
class CourseRepositoryImpl @Inject constructor(
private val zfDataSource: ZfDataSource,
private val networkDataSource: CourseNetworkDataSource,
private val localPreference: WeJhPreferenceDataSource,
private val dao: CourseDao,
) : CourseRepository {
Expand Down Expand Up @@ -52,7 +52,7 @@ class CourseRepositoryImpl @Inject constructor(
override suspend fun sync(year: Int, term: Term) {
val old = dao.getCourses(year, term).first()

val classTable = zfDataSource.getClassTable(year.toString(), term.value).lessonsTable
val classTable = networkDataSource.getZfClassTable(year.toString(), term.value).lessonsTable
if (!classTable.isNullOrEmpty()) {
val new = classTable.map { it.asLocalModel(year, term) }

Expand Down
Loading

0 comments on commit 321c98d

Please sign in to comment.