v0.2.8: Site & Keyword Reordering Support & Slim Bottom Bar Margins

This commit is contained in:
2026-08-20 23:53:24 +00:00
parent 48e81598b4
commit 7ae5f713d6
@@ -5,7 +5,9 @@ import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore import androidx.datastore.preferences.preferencesDataStore
import com.hotdeal.alarm.domain.model.SiteType
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@@ -13,28 +15,91 @@ import kotlinx.coroutines.flow.map
* 앱 설정 저장 (DataStore) * 앱 설정 저장 (DataStore)
*/ */
class AppSettings(private val context: Context) { class AppSettings(private val context: Context) {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "app_settings") private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "app_settings")
companion object { companion object {
private val POLLING_INTERVAL_KEY = intPreferencesKey("polling_interval_minutes") private val POLLING_INTERVAL_KEY = intPreferencesKey("polling_interval_minutes")
private val SITE_ORDER_KEY = stringPreferencesKey("site_order_list")
private val KEYWORD_ORDER_KEY = stringPreferencesKey("keyword_order_list")
private const val DEFAULT_INTERVAL = 2 private const val DEFAULT_INTERVAL = 2
} }
/** /**
* 폴 주기 (분) * 폴 주기 (분)
*/ */
val pollingInterval: Flow<Int> = context.dataStore.data val pollingInterval: Flow<Int> = context.dataStore.data
.map { preferences -> .map { preferences ->
preferences[POLLING_INTERVAL_KEY] ?: DEFAULT_INTERVAL preferences[POLLING_INTERVAL_KEY] ?: DEFAULT_INTERVAL
} }
/** /**
* 폴 주기 설정 저장 * 폴 주기 설정 저장
*/ */
suspend fun setPollingInterval(minutes: Int) { suspend fun setPollingInterval(minutes: Int) {
context.dataStore.edit { preferences -> context.dataStore.edit { preferences ->
preferences[POLLING_INTERVAL_KEY] = minutes preferences[POLLING_INTERVAL_KEY] = minutes
} }
} }
/**
* 사이트 표시 순서 목록
*/
val siteOrder: Flow<List<SiteType>> = context.dataStore.data
.map { preferences ->
val savedStr = preferences[SITE_ORDER_KEY]
if (savedStr.isNullOrBlank()) {
SiteType.entries
} else {
val savedNames = savedStr.split(",")
val ordered = mutableListOf<SiteType>()
savedNames.forEach { name ->
try {
ordered.add(SiteType.valueOf(name.trim()))
} catch (e: Exception) {
// ignore invalid
}
}
// 누락된 신규 사이트가 있으면 끝에 추가
SiteType.entries.forEach { site ->
if (site !in ordered) {
ordered.add(site)
}
}
ordered
}
}
/**
* 사이트 표시 순서 저장
*/
suspend fun setSiteOrder(order: List<SiteType>) {
val str = order.joinToString(",") { it.name }
context.dataStore.edit { preferences ->
preferences[SITE_ORDER_KEY] = str
}
}
/**
* 키워드 ID 표시 순서 목록
*/
val keywordOrder: Flow<List<Long>> = context.dataStore.data
.map { preferences ->
val savedStr = preferences[KEYWORD_ORDER_KEY]
if (savedStr.isNullOrBlank()) {
emptyList()
} else {
savedStr.split(",").mapNotNull { it.trim().toLongOrNull() }
}
}
/**
* 키워드 ID 표시 순서 저장
*/
suspend fun setKeywordOrder(order: List<Long>) {
val str = order.joinToString(",") { it.toString() }
context.dataStore.edit { preferences ->
preferences[KEYWORD_ORDER_KEY] = str
}
}
} }