Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "interactive"
}
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@
tools:ignore="UnusedAttribute"
tools:replace="label, icon, theme, name, allowBackup">

<meta-data
android:name="android.content.APP_RESTRICTIONS"
android:resource="@xml/app_restrictions" />

<meta-data
android:name="android.max_aspect"
android:value="10" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ import com.blikoon.qrcodescanner.QrCodeActivity
import com.github.dhaval2404.imagepicker.util.PermissionUtil
import com.google.android.material.snackbar.Snackbar
import com.nextcloud.talk.R
import com.nextcloud.talk.account.data.LoginRepository
import com.nextcloud.talk.account.data.model.LoginCompletion
import com.nextcloud.talk.activities.BaseActivity
import com.nextcloud.talk.account.AccountVerificationActivity
import com.nextcloud.talk.appconfig.AppConfigManager
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
Expand All @@ -44,6 +48,7 @@ import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.CapabilitiesUtil
import com.nextcloud.talk.utils.UriUtils
import com.nextcloud.talk.utils.bundle.BundleKeys
import java.net.HttpURLConnection
import com.nextcloud.talk.utils.bundle.BundleKeys.ADD_ADDITIONAL_ACCOUNT
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
Expand All @@ -69,6 +74,12 @@ class ServerSelectionActivity : BaseActivity() {
@Inject
lateinit var networkMonitor: NetworkMonitor

@Inject
lateinit var appConfigManager: AppConfigManager

@Inject
lateinit var loginRepository: LoginRepository

private var statusQueryDisposable: Disposable? = null

private val onBackPressedCallback = object : OnBackPressedCallback(true) {
Expand All @@ -92,6 +103,21 @@ class ServerSelectionActivity : BaseActivity() {
initSystemBars()

onBackPressedDispatcher.addCallback(this, onBackPressedCallback)

if (savedInstanceState == null) {
val managedBaseUrl = appConfigManager.getServerBaseUrl()
when {
!managedBaseUrl.isNullOrBlank() -> {
binding.serverEntryTextInputEditText.setText(managedBaseUrl)
checkServerAndProceed()
}

!TextUtils.isEmpty(resources!!.getString(R.string.weblogin_url)) -> {
binding.serverEntryTextInputEditText.setText(resources!!.getString(R.string.weblogin_url))
checkServerAndProceed()
}
}
}
}

override fun onResume() {
Expand Down Expand Up @@ -127,10 +153,7 @@ class ServerSelectionActivity : BaseActivity() {
}

binding.serverEntryTextInputEditText.requestFocus()
if (!TextUtils.isEmpty(resources!!.getString(R.string.weblogin_url))) {
binding.serverEntryTextInputEditText.setText(resources!!.getString(R.string.weblogin_url))
checkServerAndProceed()
}

binding.serverEntryTextInputEditText.setOnEditorActionListener { _: TextView?, i: Int, _: KeyEvent? ->
if (i == EditorInfo.IME_ACTION_DONE) {
checkServerAndProceed()
Expand Down Expand Up @@ -349,8 +372,27 @@ class ServerSelectionActivity : BaseActivity() {
}
}
} else {
val baseUrl = queryUrl.replace("/status.php", "")
val managedUsername = appConfigManager.getUsername()
val managedPassword = appConfigManager.getAppPassword()
if (!managedUsername.isNullOrBlank() && !managedPassword.isNullOrBlank()) {
val loginCompletion = LoginCompletion(
HttpURLConnection.HTTP_OK,
baseUrl,
managedUsername,
managedPassword
)
val managedBundle = loginRepository.parseAndLogin(loginCompletion)
if (managedBundle != null) {
val intent = Intent(context, AccountVerificationActivity::class.java)
intent.putExtras(managedBundle)
startActivity(intent)
return@runOnUiThread
}
}

val bundle = Bundle()
bundle.putString(BundleKeys.KEY_BASE_URL, queryUrl.replace("/status.php", ""))
bundle.putString(BundleKeys.KEY_BASE_URL, baseUrl)

val intent = Intent(context, BrowserLoginActivity::class.java)
intent.putExtras(bundle)
Expand Down
37 changes: 37 additions & 0 deletions app/src/main/java/com/nextcloud/talk/appconfig/AppConfigManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.appconfig

import android.content.RestrictionsManager
import android.content.Context
import androidx.annotation.VisibleForTesting
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class AppConfigManager @Inject constructor(private val context: Context) {

fun getServerBaseUrl(): String? = getString(KEY_SERVER_BASE_URL)?.takeIf { it.isNotBlank() }

fun getUsername(): String? = getString(KEY_USERNAME)?.takeIf { it.isNotBlank() }

fun getAppPassword(): String? = getString(KEY_APP_PASSWORD)?.takeIf { it.isNotBlank() }

@VisibleForTesting
internal fun getString(key: String): String? {
val restrictionsManager = context.getSystemService(Context.RESTRICTIONS_SERVICE) as? RestrictionsManager
?: return null
val restrictions = restrictionsManager.applicationRestrictions
return restrictions?.getString(key)
}

companion object {
const val KEY_SERVER_BASE_URL = "nextcloud_url"
const val KEY_USERNAME = "nextcloud_username"
const val KEY_APP_PASSWORD = "nextcloud_password"
}
}
8 changes: 8 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1032,4 +1032,12 @@ How to translate with transifex:
<string name="turn_on_background_blur">Turn on background blur</string>
<string name="turn_off_background_blur">Turn off background blur</string>
<string name="nc_no_account_found">Account not found</string>

<!-- Managed configurations -->
<string name="nc_restriction_server_url_title">Server URL</string>
<string name="nc_restriction_server_url_description">Nextcloud server address that should be used by default.</string>
<string name="nc_restriction_username_title">Username</string>
<string name="nc_restriction_username_description">Username that should be used by default.</string>
<string name="nc_restriction_app_password_title">App password</string>
<string name="nc_restriction_app_password_description">App-specific password or token for the user.</string>
</resources>
29 changes: 29 additions & 0 deletions app/src/main/res/xml/app_restrictions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
<restriction
android:defaultValue=""
android:description="@string/nc_restriction_server_url_description"
android:key="nextcloud_url"
android:restrictionType="string"
android:title="@string/nc_restriction_server_url_title" />

<restriction
android:defaultValue=""
android:description="@string/nc_restriction_username_description"
android:key="nextcloud_username"
android:restrictionType="string"
android:title="@string/nc_restriction_username_title" />

<restriction
android:defaultValue=""
android:description="@string/nc_restriction_app_password_description"
android:key="nextcloud_password"
android:restrictionType="string"
android:title="@string/nc_restriction_app_password_title" />
</restrictions>
Loading