Skip to content

Commit 2f8ca79

Browse files
committed
migrate config from json5 to json
1 parent d4cebfb commit 2f8ca79

File tree

12 files changed

+239
-113
lines changed

12 files changed

+239
-113
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ kotlin {
9696
implementation("io.github.pdvrieze.xmlutil:serialization:_")
9797
// implementation("com.ryanharter.kotlinx.serialization:kotlinx-serialization-xml:_")
9898
implementation("io.github.xn32:json5k:_")
99+
implementation( "com.akuleshov7:ktoml-core:_")
99100

100101
implementation("com.github.doyaaaaaken:kotlin-csv-jvm:_")
101102

src/desktopMain/kotlin/Config.kt

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import androidx.compose.runtime.Immutable
2+
import com.akuleshov7.ktoml.Toml
3+
import com.akuleshov7.ktoml.TomlInputConfig
4+
import com.akuleshov7.ktoml.annotations.TomlMultiline
25
import io.github.oshai.kotlinlogging.KotlinLogging
36
import io.github.xn32.json5k.Json5
47
import io.github.xn32.json5k.SerialComment
@@ -13,12 +16,18 @@ import kotlinx.coroutines.flow.launchIn
1316
import kotlinx.coroutines.flow.onEach
1417
import kotlinx.coroutines.flow.sample
1518
import kotlinx.coroutines.plus
19+
import kotlinx.serialization.ExperimentalSerializationApi
20+
import kotlinx.serialization.SerialName
1621
import kotlinx.serialization.Serializable
22+
import kotlinx.serialization.json.Json
23+
import kotlinx.serialization.json.JsonNames
1724
import nestdrop.deck.Deck
1825
import nestdrop.deck.applyConfig
1926
import nestdrop.deck.configFlow
2027
import utils.LOOM
2128
import tags.PresetPlaylist
29+
import tags.Term
30+
import tags.TermDouble
2231
import ui.screens.customSearches
2332
import utils.prettyPrint
2433
import kotlin.time.Duration.Companion.seconds
@@ -47,8 +56,23 @@ data class Config(
4756
val deck4: DeckConfig = DeckConfig(
4857
triggerTime = 0.25f + 0.125f
4958
),
50-
val presetPlaylists: List<PresetPlaylist> = emptyList()
51-
)
59+
@TomlMultiline
60+
@SerialName("presetPlaylists")
61+
@Deprecated("to be removed") val presetPlaylistsOld: List<PresetPlaylistDouble> = emptyList(),
62+
val playlists: Map<String, List<Term>> = emptyMap()
63+
) {
64+
val presetPlaylists by lazy {
65+
playlists.entries.map {
66+
PresetPlaylist(it.key, it.value)
67+
}
68+
}
69+
70+
@Serializable
71+
data class PresetPlaylistDouble(
72+
val label: String,
73+
val terms: List<TermDouble>
74+
)
75+
}
5276

5377
@Immutable
5478
@Serializable
@@ -72,10 +96,13 @@ data class DeckConfig(
7296
) {
7397
@Immutable
7498
@Serializable
75-
data class SearchConfig(
99+
data class SearchConfig @OptIn(ExperimentalSerializationApi::class) constructor(
76100
val autoChange: Boolean = false,
77-
val name: String? = null,
101+
@JsonNames("name", "label")
102+
val label: String? = null,
103+
// val enabledFragments: Set<String> = emptySet(),
78104
)
105+
79106
@Immutable
80107
@Serializable
81108
data class PresetQueue(
@@ -118,6 +145,7 @@ data class DeckConfig(
118145
val autoChange: Boolean = false,
119146
val index: Int = -1,
120147
val name: String? = null,
148+
@TomlMultiline
121149
val toggles: Set<String> = emptySet(),
122150
)
123151

@@ -142,15 +170,28 @@ data class DeckConfig(
142170
val autoChange: Boolean = false,
143171
val blendMode: Boolean = false,
144172
val index: Int = -1,
173+
@TomlMultiline
145174
val toggles: Set<Int> = emptySet(),
146175
)
147176
}
148177

149178
val config = MutableStateFlow(Config())
150179

151-
//val json = Json {
180+
private val json = Json {
181+
allowComments = true
182+
prettyPrint = true
183+
allowTrailingComma = true
184+
encodeDefaults = true
185+
useAlternativeNames = true
186+
isLenient = true
187+
// this.explicitNulls = false
152188
// namingStrategy = JsonNamingStrategy.SnakeCase
153-
//}
189+
}
190+
val toml = Toml(
191+
inputConfig = TomlInputConfig(
192+
allowEmptyToml = false
193+
)
194+
)
154195
val json5 = Json5 {
155196
prettyPrint = true
156197
encodeDefaults = true
@@ -175,16 +216,36 @@ suspend fun Deck.updateConfig(deckConfig: DeckConfig) {
175216
@OptIn(FlowPreview::class)
176217
suspend fun loadConfig() {
177218
logger.info { "load config" }
178-
if (configFile.exists()) {
219+
val newConfigValue = if (configFile.exists()) {
179220
logger.info { "loading: $configFile" }
180221
// configFile.readText()
181-
config.value = json5.decodeFromString(
222+
json.decodeFromString(
182223
Config.serializer(),
183224
configFile.readText(),
184225
)
226+
} else if (configFileJson5.exists()) {
227+
logger.info { "loading: $configFileJson5" }
228+
// configFile.readText()
229+
json.decodeFromString(
230+
Config.serializer(),
231+
configFileJson5.readText(),
232+
)
185233
} else {
234+
logger.info { "does not exist: $configFile $configFileJson5" }
235+
null
236+
}
186237

187-
logger.info { "does not exist: $configFile" }
238+
if (newConfigValue != null) {
239+
config.value = newConfigValue.let { c ->
240+
if (c.playlists.isEmpty()) {
241+
c.copy(
242+
playlists = c.presetPlaylistsOld.associate { it.label to it.terms.map { it.toTerm() } },
243+
presetPlaylistsOld = emptyList()
244+
)
245+
} else {
246+
c
247+
}
248+
}
188249
}
189250

190251
config
@@ -229,14 +290,17 @@ suspend fun loadConfig() {
229290

230291
customSearches.onEach { searches ->
231292
updateConfig {
232-
copy(presetPlaylists = searches)
293+
copy(playlists = searches.associate { it.label to it.terms })
233294
}
234295
}.launchIn(configScope)
235296
}
236297

237298
fun saveConfig(config: Config) {
238299
configFile.parentFile.mkdirs()
239300
configFile.writeText(
240-
json5.encodeToString(Config.serializer(), config)
301+
json.encodeToString(Config.serializer(), config)
302+
)
303+
configFileToml.writeText(
304+
toml.encodeToString(Config.serializer(), config)
241305
)
242306
}

src/desktopMain/kotlin/locations.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ val configFolder = dotenv["NESTCTRL_CONFIG_FOLDER"]?.parsePath() ?: userHome.res
99
val tagsFolder = configFolder.resolve("tags").also {
1010
logger.info { "tags folder: $it" }
1111
}
12-
val configFile = configFolder.resolve("config.json5").also {
12+
val configFile = configFolder.resolve("config.json").also {
1313
logger.info { "config file: $it" }
1414
}
15+
val configFileJson5 = configFolder.resolve("config.json5").also {
16+
logger.info { "config file json5: $it" }
17+
}
18+
val configFileToml = configFolder.resolve("config.toml").also {
19+
logger.info { "config file toml: $it" }
20+
}
1521
val queueFolder = configFolder.resolve("queues").also {
1622
logger.info { "queue folder: $it" }
1723
}

src/desktopMain/kotlin/nestdrop/deck/Deck.kt

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ import presetsFolder
5050
import presetsMap
5151
import queueFolder
5252
import tags.PresetPlaylist
53+
import tags.nestdropQueueSearches
5354
import tags.pickItemToGenerate
5455
import tags.presetTagsMapping
56+
import ui.screens.customSearches
5557
import utils.className
5658
import utils.runningHistory
5759
import utils.runningHistoryNotNull
@@ -355,7 +357,12 @@ class Deck(
355357
}
356358

357359
@Immutable
358-
inner class Search : MutableStateFlow<PresetPlaylist?> by MutableStateFlow(null) {
360+
inner class Search {
361+
362+
val label = MutableStateFlow<String?>(null)
363+
// val enabledFragments = MutableStateFlow<Set<String>>(emptySet())
364+
private val currentMutable = MutableStateFlow<PresetPlaylist?>(null)
365+
val current = currentMutable.asStateFlow()
359366

360367
val autoChange = MutableStateFlow(false)
361368

@@ -364,7 +371,7 @@ class Deck(
364371
logger.info { "skip disabled $deckName" }
365372
return
366373
}
367-
search.value?.let { search ->
374+
current.value?.let { search ->
368375

369376
val presets = presetsMap.value
370377
val presetTags = presetTagsMapping.value
@@ -403,7 +410,36 @@ class Deck(
403410
}
404411

405412
fun startFlows() {
406-
search.filterNotNull()
413+
combine(
414+
customSearches,
415+
nestdropQueueSearches,
416+
label
417+
) { customSearches, queueSearches, label ->
418+
customSearches.firstOrNull { it.label == label }
419+
?: queueSearches.firstOrNull { it.label == label }
420+
}
421+
.onEach {
422+
currentMutable.value = it
423+
}
424+
.launchIn(flowScope)
425+
426+
// combine(
427+
// customSearches,
428+
// nestdropQueueSearches,
429+
// enabledFragments
430+
// ) { customSearches, queueSearches, enabledFragments ->
431+
// val terms = customSearches.filter { it.label in enabledFragments }.flatMap { it.terms } + queueSearches.filter { it.label in enabledFragments }.flatMap { it.terms }
432+
// PresetPlaylist(
433+
// label = "dynamic",
434+
// terms = terms
435+
// )
436+
// }
437+
// .onEach {
438+
// currentMutable.value = it
439+
// }
440+
// .launchIn(flowScope)
441+
442+
current.filterNotNull()
407443
.distinctUntilChanged()
408444
.onEach { search ->
409445
val presets = presetsMap.value
@@ -425,7 +461,7 @@ class Deck(
425461
}
426462
folder.listFiles()?.forEach { it.deleteRecursively() }
427463

428-
filtered.mapValues { it.value.roundToInt() }.forEach { (location, weight) ->
464+
filtered.mapValues { it.value }.forEach { (location, weight) ->
429465
val presetFile = presetsFolder.resolve(location.path)
430466
val previewFile = presetsFolder.resolve(location.previewPath)
431467
if (weight == 1) {
@@ -439,7 +475,8 @@ class Deck(
439475
}
440476
} else {
441477
repeat(weight) { i ->
442-
val targetFolder = folder.resolve(location.path).parentFile!!
478+
val targetFolder = folder
479+
.resolve(location.path).parentFile!!
443480
.resolve("${location.name}_$i")
444481
targetFolder.mkdirs()
445482
targetFolder.resolve(presetFile.name).also {
@@ -451,6 +488,22 @@ class Deck(
451488
}
452489
}
453490
}
491+
if(filtered.isEmpty()) {
492+
presets.values.filter {
493+
it.categoryPath.last() == "! Transition"
494+
}.forEach { location ->
495+
val presetFile = presetsFolder.resolve(location.path)
496+
val previewFile = presetsFolder.resolve(location.previewPath)
497+
val targetFolder = folder.resolve(location.path).parentFile!!
498+
targetFolder.mkdirs()
499+
targetFolder.resolve(presetFile.name).also {
500+
presetFile.copyTo(it)
501+
}
502+
targetFolder.resolve(previewFile.name).also {
503+
previewFile.copyTo(it)
504+
}
505+
}
506+
}
454507
nestdropPortSend(
455508
OSCMessage("/Queue/<${folder.name}>/Refresh", 1)
456509
)

0 commit comments

Comments
 (0)