-
-
Notifications
You must be signed in to change notification settings - Fork 79
/
Copy pathMemosViewModel.kt
132 lines (115 loc) · 4.59 KB
/
MemosViewModel.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package me.mudkip.moememos.viewmodel
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.skydoves.sandwich.ApiResponse
import com.skydoves.sandwich.suspendOnSuccess
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.mudkip.moememos.data.model.DailyUsageStat
import me.mudkip.moememos.data.model.Memo
import me.mudkip.moememos.data.model.MemoVisibility
import me.mudkip.moememos.data.model.Resource
import me.mudkip.moememos.data.service.AccountService
import me.mudkip.moememos.data.service.MemoService
import me.mudkip.moememos.ext.string
import me.mudkip.moememos.ext.suspendOnErrorMessage
import java.time.LocalDate
import java.time.OffsetDateTime
import javax.inject.Inject
@HiltViewModel
class MemosViewModel @Inject constructor(
private val memoService: MemoService,
private val accountService: AccountService
) : ViewModel() {
var memos = mutableStateListOf<Memo>()
private set
var tags = mutableStateListOf<String>()
private set
var errorMessage: String? by mutableStateOf(null)
private set
var matrix by mutableStateOf(DailyUsageStat.initialMatrix)
private set
var host: String? by mutableStateOf(null)
private set
init {
snapshotFlow { memos.toList() }
.onEach { matrix = calculateMatrix() }
.launchIn(viewModelScope)
}
fun loadMemos() = viewModelScope.launch {
memoService.repository.listMemos().suspendOnSuccess {
memos.clear()
memos.addAll(data)
errorMessage = null
loadHost()
}.suspendOnErrorMessage {
errorMessage = it
}
}
fun loadTags() = viewModelScope.launch {
memoService.repository.listTags().suspendOnSuccess {
tags.clear()
tags.addAll(data)
}
}
suspend fun loadHost() = withContext(viewModelScope.coroutineContext) {
accountService.currentAccount.collect { currentAccount ->
val currentHost = currentAccount?.toUserData()?.memosV1?.host ?: let {
currentAccount?.toUserData()?.memosV0?.host
}
host = currentHost
}
}
suspend fun deleteTag(name: String) = withContext(viewModelScope.coroutineContext) {
memoService.repository.deleteTag(name).suspendOnSuccess {
tags.remove(name)
}
}
suspend fun updateMemoPinned(memoIdentifier: String, pinned: Boolean) = withContext(viewModelScope.coroutineContext) {
memoService.repository.updateMemo(memoIdentifier, pinned = pinned).suspendOnSuccess {
updateMemo(data)
}
}
suspend fun editMemo(memoIdentifier: String, content: String, resourceList: List<Resource>?, visibility: MemoVisibility): ApiResponse<Memo> = withContext(viewModelScope.coroutineContext) {
memoService.repository.updateMemo(memoIdentifier, content, resourceList, visibility).suspendOnSuccess {
updateMemo(data)
}
}
suspend fun archiveMemo(memoIdentifier: String) = withContext(viewModelScope.coroutineContext) {
memoService.repository.archiveMemo(memoIdentifier).suspendOnSuccess {
memos.removeIf { it.identifier == memoIdentifier }
}
}
suspend fun deleteMemo(memoIdentifier: String) = withContext(viewModelScope.coroutineContext) {
memoService.repository.deleteMemo(memoIdentifier).suspendOnSuccess {
memos.removeIf { it.identifier == memoIdentifier }
}
}
private fun updateMemo(memo: Memo) {
val index = memos.indexOfFirst { it.identifier == memo.identifier }
if (index != -1) {
memos[index] = memo
}
}
private fun calculateMatrix(): List<DailyUsageStat> {
val countMap = HashMap<LocalDate, Int>()
for (memo in memos) {
val date = memo.date.atZone(OffsetDateTime.now().offset).toLocalDate()
countMap[date] = (countMap[date] ?: 0) + 1
}
return DailyUsageStat.initialMatrix.map {
it.copy(count = countMap[it.date] ?: 0)
}
}
}
val LocalMemos =
compositionLocalOf<MemosViewModel> { error(me.mudkip.moememos.R.string.memos_view_model_not_found.string) }