這篇寫完就還剩五篇,今天來完成 HackMD 的 API 串接部份
val hackmdApiKey: Flow<String> = context.dataStore.data
    .map { preferences ->
        preferences[Keys.hackmdApiKey] ?: ""
    }
suspend fun setHackmdApiKey(apiKey: String) {
    context.dataStore.edit { preferences ->
        preferences[Keys.hackmdApiKey] = apiKey
    }
}
suspend fun clearHackmdApiKey() {
    context.dataStore.edit { preferences ->
        preferences.remove(Keys.hackmdApiKey)
    }
}        
class GetHackmdApiKeyUseCase @Inject constructor(
    private val repository: UserPreferencesRepository
) {
    operator fun invoke(): Flow<String> {
        return repository.hackmdApiKey
    }
}
class SaveHackmdApiKeyUseCase @Inject constructor(
    private val repository: UserPreferencesRepository
) {
    suspend operator fun invoke(apiKey: String) {
        repository.setHackmdApiKey(apiKey)
    }
}
class ClearHackmdApiKeyUseCase @Inject constructor(
    private val repository: UserPreferencesRepository
) {
    suspend operator fun invoke() {
        repository.clearHackmdApiKey()
    }
}
val uiState: StateFlow<SettingsUiState> = combine(
    getSettingsUseCase(),
    getHackmdApiKeyUseCase()
) { settings, apiKey ->
    SettingsUiState(
        settings = settings,
        hackmdApiKey = apiKey,
        isLoading = false
    )
}.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5000),
    initialValue = SettingsUiState(isLoading = true)
)
fun onHackmdApiKeyChanged(apiKey: String) {
    viewModelScope.launch {
        saveHackmdApiKeyUseCase(apiKey)
    }
}
fun onClearHackmdApiKey() {
    viewModelScope.launch {
        clearHackmdApiKeyUseCase()
    }
}    
Spacer(modifier = Modifier.height(16.dp))
// HackMD Section
Text(
    text = "HackMD 整合",
    style = MaterialTheme.typography.titleLarge
)
Button(onClick = { uriHandler.openUri("https://hackmd.io/") }) {
    Text("前往 HackMD 官網")
}
Button(onClick = { uriHandler.openUri("https://hackmd.io/@docs/issue-revoke-api-token-zh") }) {
    Text("如何取得 Token?")
}
val isApiKeySet = uiState.hackmdApiKey.isNotBlank()
TextField(
    value = uiState.hackmdApiKey,
    onValueChange = onApiKeyChanged,
    label = { Text("HackMD API Token") },
    modifier = Modifier.fillMaxWidth(),
    readOnly = isApiKeySet,
    visualTransformation = if (isApiKeySet) PasswordVisualTransformation() else VisualTransformation.None,
    trailingIcon = {
        if (isApiKeySet) {
            IconButton(onClick = onClearApiKey) {
                Icon(
                    imageVector = Icons.Default.Clear,
                    contentDescription = "清除 API Token"
                )
            }
        }
    }
)