Skip to content

Commit

Permalink
Promote standalone mode out of beta
Browse files Browse the repository at this point in the history
  • Loading branch information
bubelov committed May 28, 2022
1 parent b248b06 commit dda9c02
Show file tree
Hide file tree
Showing 47 changed files with 132 additions and 345 deletions.
1 change: 0 additions & 1 deletion app/build.gradle.kts
Expand Up @@ -120,7 +120,6 @@ dependencies {
implementation("com.squareup.sqldelight:coroutines-extensions:$sqlDelightVer")
implementation("com.squareup.sqldelight:android-driver:$sqlDelightVer")

implementation("com.github.nextcloud:Android-SingleSignOn:0.6.1")
implementation("com.google.android.material:material:1.6.0")
implementation("com.squareup.picasso:picasso:2.71828")
implementation("io.insert-koin:koin-android:3.2.0")
Expand Down
44 changes: 7 additions & 37 deletions app/src/main/kotlin/api/NewsApiSwitcher.kt
Expand Up @@ -4,18 +4,13 @@ import android.content.Context
import api.miniflux.MinifluxApiAdapter
import api.miniflux.MinifluxApiBuilder
import api.nextcloud.DirectNextcloudNewsApiBuilder
import api.nextcloud.NextcloudNewsApi
import api.nextcloud.NextcloudNewsApiAdapter
import api.standalone.StandaloneNewsApi
import com.google.gson.GsonBuilder
import com.nextcloud.android.sso.api.NextcloudAPI
import com.nextcloud.android.sso.helper.SingleAccountHelper
import common.ConfRepository
import db.Database
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import org.koin.core.annotation.Single
import retrofit2.NextcloudRetrofitApiBuilder

@Single
class NewsApiSwitcher(
Expand All @@ -25,41 +20,16 @@ class NewsApiSwitcher(
private val context: Context,
) {

fun switch(authType: String) {
when (authType) {
ConfRepository.AUTH_TYPE_NEXTCLOUD_APP -> switchToAppBasedNextcloudApi()
ConfRepository.AUTH_TYPE_NEXTCLOUD_DIRECT -> switchToDirectNextcloudApi()
ConfRepository.AUTH_TYPE_MINIFLUX -> switchToMinifluxApi()
ConfRepository.AUTH_TYPE_STANDALONE -> switchToStandaloneApi()
else -> throw Exception("Unknown auth type: $authType")
fun switch(backend: String) {
when (backend) {
ConfRepository.BACKEND_STANDALONE -> switchToStandaloneApi()
ConfRepository.BACKEND_MINIFLUX -> switchToMinifluxApi()
ConfRepository.BACKEND_NEXTCLOUD -> switchToNextcloudApi()
else -> throw Exception("Unknown backend: $backend")
}
}

private fun switchToAppBasedNextcloudApi() {
val account = SingleAccountHelper.getCurrentSingleSignOnAccount(context)

val callback: NextcloudAPI.ApiConnectedListener =
object : NextcloudAPI.ApiConnectedListener {
override fun onConnected() {}
override fun onError(e: Exception) {}
}

val nextcloudApi = NextcloudAPI(
context,
account,
GsonBuilder().create(),
callback
)

val nextcloudNewsApi = NextcloudRetrofitApiBuilder(
nextcloudApi,
"/index.php/apps/news/api/v1-2/"
).create(NextcloudNewsApi::class.java)

wrapper.api = NextcloudNewsApiAdapter(nextcloudNewsApi)
}

private fun switchToDirectNextcloudApi(): Unit = runBlocking {
private fun switchToNextcloudApi(): Unit = runBlocking {
val conf = confRepo.select().first()

wrapper.api = NextcloudNewsApiAdapter(
Expand Down
46 changes: 10 additions & 36 deletions app/src/main/kotlin/auth/AccountsRepository.kt
Expand Up @@ -2,17 +2,13 @@ package auth

import android.content.Context
import co.appreactor.news.R
import com.nextcloud.android.sso.exceptions.SSOException
import com.nextcloud.android.sso.helper.SingleAccountHelper
import com.squareup.sqldelight.runtime.coroutines.asFlow
import com.squareup.sqldelight.runtime.coroutines.mapToOneOrNull
import common.ConfRepository
import db.Conf
import db.Database
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import org.koin.core.annotation.Single

@Single
Expand All @@ -33,46 +29,24 @@ class AccountsRepository(
}

private fun Conf.accountTitle(): String {
return when (authType) {
ConfRepository.AUTH_TYPE_NEXTCLOUD_APP,
ConfRepository.AUTH_TYPE_NEXTCLOUD_DIRECT -> {
resources.getString(R.string.nextcloud)
}
ConfRepository.AUTH_TYPE_MINIFLUX -> {
resources.getString(R.string.miniflux)
}
ConfRepository.AUTH_TYPE_STANDALONE -> {
resources.getString(R.string.standalone_mode_no_beta)
}
return when (backend) {
ConfRepository.BACKEND_STANDALONE -> resources.getString(R.string.standalone_mode)
ConfRepository.BACKEND_MINIFLUX -> resources.getString(R.string.miniflux)
ConfRepository.BACKEND_NEXTCLOUD -> resources.getString(R.string.nextcloud)
else -> ""
}
}

private suspend fun Conf.accountSubtitle(): String {
return when (authType) {
ConfRepository.AUTH_TYPE_NEXTCLOUD_APP,
ConfRepository.AUTH_TYPE_NEXTCLOUD_DIRECT -> {
if (nextcloudServerUrl.isNotBlank()) {
val username = nextcloudServerUsername
"$username@${nextcloudServerUrl.replace("https://", "")}"
} else {
try {
val account = withContext(Dispatchers.Default) {
SingleAccountHelper.getCurrentSingleSignOnAccount(context)
}

account.name
} catch (e: SSOException) {
"unknown"
}
}
}
ConfRepository.AUTH_TYPE_MINIFLUX -> {
return when (backend) {
ConfRepository.BACKEND_STANDALONE -> ""
ConfRepository.BACKEND_MINIFLUX -> {
val username = minifluxServerUsername
"$username@${minifluxServerUrl.replace("https://", "")}"
}
ConfRepository.AUTH_TYPE_STANDALONE -> {
resources.getString(R.string.beta)
ConfRepository.BACKEND_NEXTCLOUD -> {
val username = nextcloudServerUsername
"$username@${nextcloudServerUrl.replace("https://", "")}"
}
else -> ""
}
Expand Down
98 changes: 19 additions & 79 deletions app/src/main/kotlin/auth/AuthFragment.kt
Expand Up @@ -6,16 +6,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import co.appreactor.news.R
import co.appreactor.news.databinding.FragmentAuthBinding
import com.nextcloud.android.sso.AccountImporter
import com.nextcloud.android.sso.exceptions.SSOException
import com.nextcloud.android.sso.helper.SingleAccountHelper
import com.nextcloud.android.sso.model.SingleSignOnAccount
import com.nextcloud.android.sso.ui.UiExceptionManager
import common.AppFragment
import common.ConfRepository
import common.app
Expand All @@ -36,11 +30,11 @@ class AuthFragment : AppFragment(
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View? {
val conf = runBlocking { model.selectConf().first() }

return if (conf.authType.isBlank()) {
return if (conf.backend.isBlank()) {
_binding = FragmentAuthBinding.inflate(inflater, container, false)
binding.root
} else {
Expand All @@ -60,24 +54,25 @@ class AuthFragment : AppFragment(

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.initButtons()
}

binding.loginWithMiniflux.setOnClickListener {
findNavController().navigate(R.id.action_authFragment_to_minifluxAuthFragment)
}

binding.loginWithNextcloudApp.setOnClickListener {
showAccountPicker()
}
override fun onResume() {
super.onResume()
(binding.icon.drawable as? Animatable)?.start()
}

binding.loginWithNextcloudServer.setOnClickListener {
findNavController().navigate(R.id.action_authFragment_to_directAuthFragment)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

binding.standaloneMode.setOnClickListener {
private fun FragmentAuthBinding.initButtons() {
useStandaloneBackend.setOnClickListener {
lifecycleScope.launchWhenResumed {
model.upsertConf(
model.selectConf().first().copy(
authType = ConfRepository.AUTH_TYPE_STANDALONE,
backend = ConfRepository.BACKEND_STANDALONE,
syncOnStartup = false,
backgroundSyncIntervalMillis = TimeUnit.HOURS.toMillis(12),
initialSyncCompleted = true,
Expand All @@ -89,68 +84,13 @@ class AuthFragment : AppFragment(
findNavController().navigate(R.id.action_authFragment_to_entriesFragment)
}
}
}

override fun onResume() {
super.onResume()
(binding.icon.drawable as? Animatable)?.start()
}

@Deprecated("Deprecated in Java")
@Suppress("DEPRECATION")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)

when (resultCode) {
AppCompatActivity.RESULT_CANCELED -> setButtonsEnabled(true)

else -> {
AccountImporter.onActivityResult(
requestCode,
resultCode,
data,
this
) { onNextcloudAccountAccessGranted(it) }
}
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

private fun onNextcloudAccountAccessGranted(account: SingleSignOnAccount) {
SingleAccountHelper.setCurrentAccount(context, account.name)

runBlocking {
val conf = model.selectConf().first()
model.upsertConf(conf.copy(authType = ConfRepository.AUTH_TYPE_NEXTCLOUD_APP))
useMinifluxBackend.setOnClickListener {
findNavController().navigate(R.id.action_authFragment_to_minifluxAuthFragment)
}

app().setupBackgroundSync(override = true)

findNavController().navigate(R.id.action_authFragment_to_entriesFragment)
}

private fun showAccountPicker() {
setButtonsEnabled(false)

try {
AccountImporter.pickNewAccount(this)
} catch (e: Exception) {
if (e is SSOException) {
UiExceptionManager.showDialogForException(context, e)
}

setButtonsEnabled(true)
useNextcloudBackend.setOnClickListener {
findNavController().navigate(R.id.action_authFragment_to_nextcloudAuthFragment)
}
}

private fun setButtonsEnabled(enabled: Boolean) {
binding.loginWithMiniflux.isEnabled = enabled
binding.loginWithNextcloudApp.isEnabled = enabled
binding.loginWithNextcloudServer.isEnabled = enabled
binding.standaloneMode.isEnabled = enabled
}
}
2 changes: 1 addition & 1 deletion app/src/main/kotlin/auth/AuthViewModel.kt
Expand Up @@ -16,6 +16,6 @@ class AuthViewModel(

suspend fun upsertConf(conf: Conf) {
confRepo.upsert(conf)
newsApiSwitcher.switch(conf.authType)
newsApiSwitcher.switch(conf.backend)
}
}
2 changes: 1 addition & 1 deletion app/src/main/kotlin/auth/MinifluxAuthFragment.kt
Expand Up @@ -83,7 +83,7 @@ class MinifluxAuthFragment : AppFragment() {
binding.trustSelfSignedCerts.isChecked,
)

model.setAuthType(ConfRepository.AUTH_TYPE_MINIFLUX)
model.setBackend(ConfRepository.BACKEND_MINIFLUX)

app().setupBackgroundSync(override = true)

Expand Down
6 changes: 3 additions & 3 deletions app/src/main/kotlin/auth/MinifluxAuthViewModel.kt
Expand Up @@ -47,9 +47,9 @@ class MinifluxAuthViewModel(
confRepo.upsert(newConf)
}

suspend fun setAuthType(newAuthType: String) {
val newConf = confRepo.select().first().copy(authType = newAuthType)
suspend fun setBackend(newBackend: String) {
val newConf = confRepo.select().first().copy(backend = newBackend)
confRepo.upsert(newConf)
apiSwitcher.switch(newAuthType)
apiSwitcher.switch(newBackend)
}
}
2 changes: 1 addition & 1 deletion app/src/main/kotlin/auth/NextcloudAuthFragment.kt
Expand Up @@ -83,7 +83,7 @@ class NextcloudAuthFragment : AppFragment() {
binding.trustSelfSignedCerts.isChecked,
)

model.setAuthType(ConfRepository.AUTH_TYPE_NEXTCLOUD_DIRECT)
model.setBackend(ConfRepository.BACKEND_NEXTCLOUD)

app().setupBackgroundSync(override = true)

Expand Down
6 changes: 3 additions & 3 deletions app/src/main/kotlin/auth/NextcloudAuthModel.kt
Expand Up @@ -58,9 +58,9 @@ class NextcloudAuthModel(
confRepo.upsert(newConf)
}

suspend fun setAuthType(newAuthType: String) {
val newConf = confRepo.select().first().copy(authType = newAuthType)
suspend fun setBackend(newBackend: String) {
val newConf = confRepo.select().first().copy(backend = newBackend)
confRepo.upsert(newConf)
nextcloudApiSwitcher.switch(newAuthType)
nextcloudApiSwitcher.switch(newBackend)
}
}
6 changes: 3 additions & 3 deletions app/src/main/kotlin/common/App.kt
Expand Up @@ -65,10 +65,10 @@ class App : Application() {
}

runBlocking {
val authType = get<ConfRepository>().select().first().authType
val backend = get<ConfRepository>().select().first().backend

if (authType.isNotBlank()) {
get<NewsApiSwitcher>().switch(authType)
if (backend.isNotBlank()) {
get<NewsApiSwitcher>().switch(backend)
setupBackgroundSync(override = false)
}
}
Expand Down
9 changes: 4 additions & 5 deletions app/src/main/kotlin/common/ConfRepository.kt
Expand Up @@ -25,16 +25,15 @@ class ConfRepository(
}

companion object {
const val AUTH_TYPE_NEXTCLOUD_APP = "nextcloud_app"
const val AUTH_TYPE_NEXTCLOUD_DIRECT = "nextcloud_direct"
const val AUTH_TYPE_MINIFLUX = "miniflux"
const val AUTH_TYPE_STANDALONE = "standalone"
const val BACKEND_STANDALONE = "standalone"
const val BACKEND_MINIFLUX = "miniflux"
const val BACKEND_NEXTCLOUD = "nextcloud"

const val SORT_ORDER_ASCENDING = "ascending"
const val SORT_ORDER_DESCENDING = "descending"

val DEFAULT_CONF = Conf(
authType = "",
backend = "",
nextcloudServerUrl = "",
nextcloudServerTrustSelfSignedCerts = false,
nextcloudServerUsername = "",
Expand Down

0 comments on commit dda9c02

Please sign in to comment.