diff --git a/app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt b/app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt
index 6dad10f2798b..78708498efce 100644
--- a/app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt
+++ b/app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt
@@ -8,10 +8,9 @@ package com.nmc.android.ui
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
-import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
-import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.owncloud.android.AbstractIT
@@ -27,26 +26,13 @@ class LauncherActivityIT : AbstractIT() {
val activityRule = ActivityScenarioRule(LauncherActivity::class.java)
@Test
- fun testSplashScreenWithEmptyTitlesShouldHideTitles() {
- waitForIdleSync()
-
+ fun verifyUIElements() {
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
+ onView(withId(R.id.splashScreenBold)).check(matches(isCompletelyDisplayed()))
+ onView(withId(R.id.splashScreenNormal)).check(matches(isCompletelyDisplayed()))
- onView(withId(R.id.splashScreenBold)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
- onView(withId(R.id.splashScreenNormal)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
- }
-
- @Test
- fun testSplashScreenWithTitlesShouldShowTitles() {
- waitForIdleSync()
- onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
-
- activityRule.scenario.onActivity {
- it.setSplashTitles("Example", "Cloud")
- }
-
- val onePercentArea = ViewMatchers.isDisplayingAtLeast(1)
- onView(withId(R.id.splashScreenBold)).check(matches(onePercentArea))
- onView(withId(R.id.splashScreenNormal)).check(matches(onePercentArea))
+ onView(withId(R.id.splashScreenBold)).check(matches(withText("Magenta")))
+ onView(withId(R.id.splashScreenNormal)).check(matches(withText("CLOUD")))
+ shortSleep()
}
}
diff --git a/app/src/main/java/com/nextcloud/client/account/UserAccountManagerImpl.java b/app/src/main/java/com/nextcloud/client/account/UserAccountManagerImpl.java
index 1554e68e8113..9b46f8a09147 100644
--- a/app/src/main/java/com/nextcloud/client/account/UserAccountManagerImpl.java
+++ b/app/src/main/java/com/nextcloud/client/account/UserAccountManagerImpl.java
@@ -21,6 +21,7 @@
import com.nextcloud.common.NextcloudClient;
import com.nextcloud.utils.extensions.AccountExtensionsKt;
+import com.nmc.android.ui.LauncherActivity;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AuthenticatorActivity;
@@ -397,6 +398,10 @@ private String getAccountType() {
@Override
public void startAccountCreation(final Activity activity) {
+ // NMC-3278 fix
+ // Splash screen should be shown properly before navigating to Login screen
+ if(activity instanceof LauncherActivity) return;
+
Intent intent = new Intent(context, AuthenticatorActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java b/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java
index 42b3ccce6a0c..5645418073cc 100644
--- a/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java
+++ b/app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java
@@ -43,28 +43,21 @@
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
-import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import com.blikoon.qrcodescanner.QrCodeActivity;
-import com.google.android.material.button.MaterialButton;
import com.google.android.material.snackbar.Snackbar;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
import com.nextcloud.android.common.ui.color.ColorUtil;
import com.nextcloud.android.common.ui.theme.utils.ColorRole;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.device.DeviceInfo;
import com.nextcloud.client.di.Injectable;
-import com.nextcloud.client.network.ClientFactory;
import com.nextcloud.client.onboarding.FirstRunActivity;
import com.nextcloud.client.onboarding.OnboardingService;
import com.nextcloud.client.preferences.AppPreferences;
-import com.nextcloud.common.PlainClient;
-import com.nextcloud.operations.PostMethod;
import com.nextcloud.utils.extensions.BundleExtensionsKt;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
@@ -111,8 +104,6 @@
import com.owncloud.android.utils.theme.CapabilityUtils;
import com.owncloud.android.utils.theme.ViewThemeUtils;
-import org.json.JSONObject;
-
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.HashMap;
@@ -120,8 +111,6 @@
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
@@ -137,16 +126,11 @@
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleEventObserver;
-import androidx.lifecycle.ProcessLifecycleOwner;
import de.cotech.hw.fido.WebViewFidoBridge;
import de.cotech.hw.fido.ui.FidoDialogOptions;
import de.cotech.hw.fido2.WebViewWebauthnBridge;
import de.cotech.hw.fido2.ui.WebauthnDialogOptions;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import okhttp3.FormBody;
-import okhttp3.RequestBody;
import static com.owncloud.android.utils.PermissionUtil.PERMISSIONS_CAMERA;
@@ -184,17 +168,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private static final String KEY_USERNAME = "USERNAME";
private static final String KEY_PASSWORD = "PASSWORD";
private static final String KEY_ASYNC_TASK_IN_PROGRESS = "AUTH_IN_PROGRESS";
-
- /**
- * Login Flow v1
- */
- // public static final String WEB_LOGIN = "/index.php/login/flow";
-
- /**
- * Login Flow v2
- */
- public static final String WEB_LOGIN = "/index.php/login/v2";
-
+ public static final String WEB_LOGIN = "/index.php/login/flow";
public static final String PROTOCOL_SUFFIX = "://";
public static final String LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":";
public static final String HTTPS_PROTOCOL = "https://";
@@ -248,9 +222,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
@Inject PassCodeManager passCodeManager;
@Inject ViewThemeUtils.Factory viewThemeUtilsFactory;
@Inject ColorUtil colorUtil;
- @Inject ClientFactory clientFactory;
-
- private String token;
private boolean onlyAdd = false;
@SuppressLint("ResourceAsColor") @ColorInt
@@ -275,7 +246,7 @@ protected void onCreate(Bundle savedInstanceState) {
viewThemeUtils = viewThemeUtilsFactory.withPrimaryAsBackground();
viewThemeUtils.platform.themeStatusBar(this, ColorRole.PRIMARY);
- // WebViewUtil webViewUtil = new WebViewUtil(this);
+ WebViewUtil webViewUtil = new WebViewUtil(this);
Uri data = getIntent().getData();
boolean directLogin = data != null && data.toString().startsWith(getString(R.string.login_data_own_scheme));
@@ -344,8 +315,7 @@ protected void onCreate(Bundle savedInstanceState) {
if (webViewLoginMethod) {
accountSetupWebviewBinding = AccountSetupWebviewBinding.inflate(getLayoutInflater());
setContentView(accountSetupWebviewBinding.getRoot());
- anonymouslyPostLoginRequest(webloginUrl);
- // initWebViewLogin(webloginUrl, false);
+ initWebViewLogin(webloginUrl, false);
} else {
accountSetupBinding = AccountSetupBinding.inflate(getLayoutInflater());
setContentView(accountSetupBinding.getRoot());
@@ -360,18 +330,10 @@ protected void onCreate(Bundle savedInstanceState) {
}
initServerPreFragment(savedInstanceState);
- ProcessLifecycleOwner.get().getLifecycle().addObserver(lifecycleEventObserver);
- // webViewUtil.checkWebViewVersion();
+ webViewUtil.checkWebViewVersion();
}
- private final LifecycleEventObserver lifecycleEventObserver = ((lifecycleOwner, event) -> {
- if (event == Lifecycle.Event.ON_START && token != null) {
- Log_OC.d(TAG, "Start poolLogin");
- poolLogin();
- }
- });
-
private void deleteCookies() {
try {
CookieSyncManager.createInstance(this);
@@ -381,72 +343,11 @@ private void deleteCookies() {
}
}
- private String baseUrl;
-
- /**
- * This function facilitates the login process by anonymously posting a login request to a specified URL.
- * After posting the request, it retrieves the login URL for completing the login flow.
- * The login flow version used is v2.
- *
- * @param url The URL where the login request is to be anonymously posted.
- * This URL should handle the login request and return the login URL.
- * It's typically the entry point for the login process.
- * Example: "..."
- */
- private void anonymouslyPostLoginRequest(String url) {
- baseUrl = url;
-
- Thread thread = new Thread(() -> {
- String response = getResponseOfAnonymouslyPostLoginRequest();
-
- try {
- JsonObject jsonObject = JsonParser.parseString(response).getAsJsonObject();
- String loginUrl = getLoginUrl(jsonObject);
- runOnUiThread(() -> {
- initLoginInfoView();
- launchDefaultWebBrowser(loginUrl);
- });
- token = jsonObject.getAsJsonObject("poll").get("token").getAsString();
- } catch (Throwable t) {
- Log_OC.d(TAG, "Error caught at anonymouslyPostLoginRequest: " + t);
- DisplayUtils.showSnackMessage(this, R.string.authenticator_activity_login_error);
- }
- });
-
- thread.start();
- }
-
- private String getResponseOfAnonymouslyPostLoginRequest() {
- PostMethod post = new PostMethod(baseUrl, false, new FormBody.Builder().build());
- PlainClient client = clientFactory.createPlainClient();
- post.execute(client);
- return post.getResponseBodyAsString();
- }
-
- private String getLoginUrl(JsonObject response) {
- String result = response.get("login").getAsString();
- if (result == null) {
- result = getResources().getString(R.string.webview_login_url);
- }
-
- return result;
- }
-
- private void launchDefaultWebBrowser(String url) {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- }
-
private static String getWebLoginUserAgent() {
return Build.MANUFACTURER.substring(0, 1).toUpperCase(Locale.getDefault()) +
Build.MANUFACTURER.substring(1).toLowerCase(Locale.getDefault()) + " " + Build.MODEL + " (Android)";
}
- /**
- * @Deprecated This function is deprecated. Please use the {@link #anonymouslyPostLoginRequest(String)} method instead, which utilizes the improved login flow v2.
- */
- @Deprecated
@SuppressFBWarnings("ANDROID_WEB_VIEW_JAVASCRIPT")
@SuppressLint("SetJavaScriptEnabled")
private void initWebViewLogin(String baseURL, boolean useGenericUserAgent) {
@@ -806,8 +707,7 @@ protected void onNewIntent(Intent intent) {
if (intent.getBooleanExtra(EXTRA_USE_PROVIDER_AS_WEBLOGIN, false)) {
accountSetupWebviewBinding = AccountSetupWebviewBinding.inflate(getLayoutInflater());
setContentView(accountSetupWebviewBinding.getRoot());
- anonymouslyPostLoginRequest(getString(R.string.provider_registration_server));
- // initWebViewLogin(getString(R.string.provider_registration_server), true);
+ initWebViewLogin(getString(R.string.provider_registration_server), true);
}
}
@@ -1044,16 +944,7 @@ private void onGetServerInfoFinish(RemoteOperationResult result) {
accountSetupWebviewBinding = AccountSetupWebviewBinding.inflate(getLayoutInflater());
setContentView(accountSetupWebviewBinding.getRoot());
-
- if (!isLoginProcessCompleted) {
- if (!isRedirectedToTheDefaultBrowser) {
- anonymouslyPostLoginRequest(mServerInfo.mBaseUrl + WEB_LOGIN);
- isRedirectedToTheDefaultBrowser = true;
- } else {
- initLoginInfoView();
- }
- // initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, false);
- }
+ initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, false);
}
} else {
updateServerStatusIconAndText(result);
@@ -1066,20 +957,6 @@ private void onGetServerInfoFinish(RemoteOperationResult result) {
}
}
- // region LoginInfoView
- private void initLoginInfoView() {
- LinearLayout loginFlowLayout = accountSetupWebviewBinding.loginFlowV2.getRoot();
- MaterialButton cancelButton = accountSetupWebviewBinding.loginFlowV2.cancelButton;
- loginFlowLayout.setVisibility(View.VISIBLE);
-
- cancelButton.setOnClickListener(v -> {
- loginFlowExecutorService.shutdown();
- ProcessLifecycleOwner.get().getLifecycle().removeObserver(lifecycleEventObserver);
- recreate();
- });
- }
- // endregion
-
/**
* Chooses the right icon and text to show to the user for the received operation result.
*
@@ -1321,8 +1198,7 @@ public void onAuthenticatorTaskCallback(RemoteOperationResult result)
} else { // authorization fail due to client side - probably wrong credentials
if (accountSetupWebviewBinding != null) {
- anonymouslyPostLoginRequest(mServerInfo.mBaseUrl + WEB_LOGIN);
- // initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, false);
+ initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, false);
DisplayUtils.showSnackMessage(this,
accountSetupWebviewBinding.loginWebview, R.string.auth_access_failed,
result.getLogMessage());
@@ -1666,71 +1542,6 @@ public void onServiceDisconnected(ComponentName component) {
}
}
- private final ScheduledExecutorService loginFlowExecutorService = Executors.newSingleThreadScheduledExecutor();
- private boolean isLoginProcessCompleted = false;
- private boolean isRedirectedToTheDefaultBrowser = false;
-
- private void poolLogin() {
- loginFlowExecutorService.scheduleWithFixedDelay(() -> {
- if (!isLoginProcessCompleted) {
- performLoginFlowV2();
- }
- }, 0, 30, TimeUnit.SECONDS);
- }
-
- private void performLoginFlowV2() {
- String postRequestUrl = baseUrl + "/poll";
-
- RequestBody requestBody = new FormBody.Builder()
- .add("token", token)
- .build();
-
- PlainClient client = clientFactory.createPlainClient();
- PostMethod post = new PostMethod(postRequestUrl, false, requestBody);
- int status = post.execute(client);
- String response = post.getResponseBodyAsString();
-
- Log_OC.d(TAG, "performLoginFlowV2 status: " + status);
- Log_OC.d(TAG, "performLoginFlowV2 response: " + response);
-
- if (!response.isEmpty()) {
- runOnUiThread(() -> completeLoginFlow(response, status));
- }
- }
-
- private void completeLoginFlow(String response, int status) {
- try {
- JSONObject jsonObject = new JSONObject(response);
-
- String server = jsonObject.getString("server");
- String loginName = jsonObject.getString("loginName");
- String appPassword = jsonObject.getString("appPassword");
-
- LoginUrlInfo loginUrlInfo = new LoginUrlInfo();
- loginUrlInfo.serverAddress = server;
- loginUrlInfo.username = loginName;
- loginUrlInfo.password = appPassword;
-
- isLoginProcessCompleted = (status == 200 && !server.isEmpty() && !loginName.isEmpty() && !appPassword.isEmpty());
-
- if (accountSetupBinding != null) {
- accountSetupBinding.hostUrlInput.setText("");
- }
- mServerInfo.mBaseUrl = AuthenticatorUrlUtils.INSTANCE.normalizeUrlSuffix(loginUrlInfo.serverAddress);
- webViewUser = loginUrlInfo.username;
- webViewPassword = loginUrlInfo.password;
- } catch (Exception e) {
- Log_OC.d(TAG, "Error caught at completeLoginFlow: " + e);
- mServerStatusIcon = R.drawable.ic_alert;
- mServerStatusText = getString(R.string.qr_could_not_be_read);
- showServerStatus();
- }
-
- checkOcServer();
- loginFlowExecutorService.shutdown();
- ProcessLifecycleOwner.get().getLifecycle().removeObserver(lifecycleEventObserver);
- }
-
/**
* Called from SslValidatorDialog when a new server certificate was correctly saved.
*/
diff --git a/app/src/main/res/drawable/ic_magentacloud_splash_logo.xml b/app/src/main/res/drawable/ic_magentacloud_splash_logo.xml
new file mode 100644
index 000000000000..dfc85e1d1b34
--- /dev/null
+++ b/app/src/main/res/drawable/ic_magentacloud_splash_logo.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/account_setup_webview.xml b/app/src/main/res/layout/account_setup_webview.xml
index 583aa20126ea..54c520c617a0 100644
--- a/app/src/main/res/layout/account_setup_webview.xml
+++ b/app/src/main/res/layout/account_setup_webview.xml
@@ -7,31 +7,21 @@
~ SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
-->
+ android:layout_height="match_parent">
-
-
-
-
+ android:indeterminate="true"/>
diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml
index c068a3904a41..8c7f5e91e98c 100644
--- a/app/src/main/res/layout/activity_splash.xml
+++ b/app/src/main/res/layout/activity_splash.xml
@@ -18,11 +18,12 @@
app:layout_constraintBottom_toTopOf="@+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:srcCompat="@drawable/nextcloud_splash_logo" />
+ app:srcCompat="@drawable/ic_magentacloud_splash_logo" />
400dp
24dp
24dp
- 180dp
+ 116dp
20sp
5
0
diff --git a/app/src/main/res/values/setup.xml b/app/src/main/res/values/setup.xml
index 8ac829fd8e0c..c24f81d3ee45 100644
--- a/app/src/main/res/values/setup.xml
+++ b/app/src/main/res/values/setup.xml
@@ -130,8 +130,8 @@
-
-
+ Magenta
+ CLOUD
https://nominatim.openstreetmap.org/