blob: 8512ed17c5093a79434bd5eba6c2a44f224822a3 (
plain) (
blame)
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
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.model
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager
import java.util.Locale
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.utils.GameHelper
import org.yuzu.yuzu_emu.utils.GameMetadata
class GamesViewModel : ViewModel() {
val games: StateFlow<List<Game>> get() = _games
private val _games = MutableStateFlow(emptyList<Game>())
val searchedGames: StateFlow<List<Game>> get() = _searchedGames
private val _searchedGames = MutableStateFlow(emptyList<Game>())
val isReloading: StateFlow<Boolean> get() = _isReloading
private val _isReloading = MutableStateFlow(false)
val shouldSwapData: StateFlow<Boolean> get() = _shouldSwapData
private val _shouldSwapData = MutableStateFlow(false)
val shouldScrollToTop: StateFlow<Boolean> get() = _shouldScrollToTop
private val _shouldScrollToTop = MutableStateFlow(false)
val searchFocused: StateFlow<Boolean> get() = _searchFocused
private val _searchFocused = MutableStateFlow(false)
init {
// Ensure keys are loaded so that ROM metadata can be decrypted.
NativeLibrary.reloadKeys()
// Retrieve list of cached games
val storedGames = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
.getStringSet(GameHelper.KEY_GAMES, emptySet())
viewModelScope.launch {
withContext(Dispatchers.IO) {
if (storedGames!!.isNotEmpty()) {
val deserializedGames = mutableSetOf<Game>()
storedGames.forEach {
val game: Game
try {
game = Json.decodeFromString(it)
} catch (e: Exception) {
// We don't care about any errors related to parsing the game cache
return@forEach
}
val gameExists =
DocumentFile.fromSingleUri(
YuzuApplication.appContext,
Uri.parse(game.path)
)?.exists()
if (gameExists == true) {
deserializedGames.add(game)
}
}
setGames(deserializedGames.toList())
}
reloadGames(false)
}
}
}
fun setGames(games: List<Game>) {
val sortedList = games.sortedWith(
compareBy(
{ it.title.lowercase(Locale.getDefault()) },
{ it.path }
)
)
_games.value = sortedList
}
fun setSearchedGames(games: List<Game>) {
_searchedGames.value = games
}
fun setShouldSwapData(shouldSwap: Boolean) {
_shouldSwapData.value = shouldSwap
}
fun setShouldScrollToTop(shouldScroll: Boolean) {
_shouldScrollToTop.value = shouldScroll
}
fun setSearchFocused(searchFocused: Boolean) {
_searchFocused.value = searchFocused
}
fun reloadGames(directoryChanged: Boolean) {
if (isReloading.value) {
return
}
_isReloading.value = true
viewModelScope.launch {
withContext(Dispatchers.IO) {
GameMetadata.resetMetadata()
setGames(GameHelper.getGames())
_isReloading.value = false
if (directoryChanged) {
setShouldSwapData(true)
}
}
}
}
}
|