Simple signup

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>

cleanup

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
tobiasKaminsky 2018-05-02 11:25:53 +02:00
parent 342125867d
commit eae43cf464
No known key found for this signature in database
GPG key ID: 0E00D4D47D0C5AF7
31 changed files with 3290 additions and 2791 deletions

View file

@ -91,6 +91,7 @@ android {
testInstrumentationRunnerArgument "TEST_SERVER_URL", "\"$System.env.OCTEST_SERVER_BASE_URL\""
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
versionCode versionMajor * 10000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16"
viewBox="0 0 16 16"
width="16"
version="1.1"
id="svg4"
sodipodi:docname="first_run_files.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8"/>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="835"
id="namedview6"
showgrid="false"
inkscape:pagecheckerboard="true"
inkscape:zoom="14.75"
inkscape:cx="-3.8305085"
inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4"/>
<path
fill="#0082c9"
d="m1.5 2c-0.25 0-0.5 0.25-0.5 0.5v11c0 0.26 0.24 0.5 0.5 0.5h13c0.26 0 0.5-0.241 0.5-0.5v-9c0-0.25-0.25-0.5-0.5-0.5h-6.5l-2-2h-4.5zm8.75 3.5a1.25 1.25 0 0 1 1.25 1.25 1.25 1.25 0 0 1 -1.25 1.25 1.25 1.25 0 0 1 -0.8008 -0.291l-2.4512 1.2265a1.25 1.25 0 0 1 0.002 0.0645 1.25 1.25 0 0 1 -0.0039 0.0645l2.4531 1.2265a1.25 1.25 0 0 1 0.8008 -0.291 1.25 1.25 0 0 1 1.25 1.25 1.25 1.25 0 0 1 -1.25 1.25 1.25 1.25 0 0 1 -1.25 -1.25 1.25 1.25 0 0 1 0.0039 -0.064l-2.4531-1.227a1.25 1.25 0 0 1 -0.8008 0.291 1.25 1.25 0 0 1 -1.25 -1.25 1.25 1.25 0 0 1 1.25 -1.25 1.25 1.25 0 0 1 0.8008 0.291l2.4512-1.2265a1.25 1.25 0 0 1 -0.002 -0.0645 1.25 1.25 0 0 1 1.25 -1.25z"
id="path2"
style="fill:#ffffff;fill-opacity:1"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewbox="0 0 16 16"
height="16"
width="16"
version="1.1"
id="svg4"
sodipodi:docname="first_run_groupware.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8"/>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="835"
id="namedview6"
showgrid="false"
inkscape:pagecheckerboard="true"
inkscape:zoom="14.75"
inkscape:cx="0.54237288"
inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4"/>
<path
fill="#0082c9"
d="m9 1c-1.746 0-3 1.43-3 2.8 0 1.4 0.1 2.4 0.8 3.5 0.224 0.29 0.485 0.35 0.7 0.6 0.135 0.5 0.24 1 0.1 1.5-0.436 0.153-0.85 0.332-1.27 0.5-0.51-0.273-1.1-0.5-1.61-0.7-0.07-0.28-0.02-0.487 0.05-0.75 0.12-0.125 0.23-0.18 0.36-0.3 0.37-0.45 0.39-1.21 0.39-1.75 0-0.8-0.72-1.4-1.5-1.4-0.87 0-1.5 0.72-1.5 1.4h-0.02c0 0.7 0.05 1.2 0.4 1.75 0.1 0.15 0.242 0.175 0.35 0.3 0.0674 0.25 0.121 0.5 0.05 0.75-0.64 0.223-1.244 0.5-1.8 0.8-0.42 0.3-0.233 0.182-0.5 1.15-0.124 0.5 1.3 0.73 2.32 0.81-0.05 0.275-0.12 0.64-0.32 1.34-0.32 1.25 4.353 1.7 6 1.7 2.43 0 6.313-0.456 5.98-1.7-0.52-1.94-0.208-1.71-0.98-2.3-1.09-0.654-2.452-1.167-3.6-1.6-0.15-0.557-0.04-0.97 0.1-1.5 0.235-0.25 0.5-0.36 0.72-0.6 0.69-0.884 0.78-2.424 0.78-3.5 0-1.586-1.43-2.8-3-2.8z"
id="path2"
style="fill:#ffffff;fill-opacity:1"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16mm"
height="16mm"
viewBox="0 0 16 16"
version="1.1"
id="svg829"
inkscape:version="0.92.2 2405546, 2018-03-11"
sodipodi:docname="first_run_talk.svg">
<defs
id="defs823"/>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="-19.200952"
inkscape:cy="38.084396"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:pagecheckerboard="true"
fit-margin-top="2"
fit-margin-left="2"
fit-margin-right="2"
fit-margin-bottom="2"
inkscape:window-width="1600"
inkscape:window-height="835"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"/>
<metadata
id="metadata826">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-15.580506,-164.12649)">
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;stroke-width:0.13229023"
d="m 23.579679,165.51155 a 6.6138496,6.6139445 0 0 0 -6.613756,6.61414 6.6138496,6.6139445 0 0 0 6.613756,6.61394 6.6138496,6.6139445 0 0 0 3.430853,-0.96761 c 0.812866,0.32302 2.633614,1.28133 3.066959,0.86739 0.452829,-0.43245 -0.531627,-2.46778 -0.767642,-3.2241 a 6.6138496,6.6139445 0 0 0 0.88351,-3.28968 6.6138496,6.6139445 0 0 0 -6.613662,-6.61385 z m 7.69e-4,2.51456 a 4.1009972,4.1010914 0 0 1 4.100984,4.10109 4.1009972,4.1010914 0 0 1 -4.100997,4.10081 4.1009972,4.1010914 0 0 1 -4.100997,-4.10081 4.1009972,4.1010914 0 0 1 4.100997,-4.10109 z"
id="path2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -254,6 +254,10 @@
android:configChanges="orientation|screenSize|keyboardHidden"/>
<activity android:name=".ui.activity.WhatsNewActivity"
android:theme="@style/Theme.ownCloud.noActionBar.Login" />
<activity
android:name=".ui.activity.FirstRunActivity"
android:theme="@style/Theme.ownCloud.noActionBar.Login"
android:configChanges="orientation|screenSize"/>
<receiver android:name=".files.BootupBroadcastReceiver" >
<intent-filter>

View file

@ -662,4 +662,9 @@ public class MainApp extends MultiDexApplication {
}
}
}
static public int getLastSeenVersionCode(Context context) {
SharedPreferences pref = android.preference.PreferenceManager.getDefaultSharedPreferences(context);
return pref.getInt(WhatsNewActivity.KEY_LAST_SEEN_VERSION_CODE, 0);
}
}

View file

@ -83,7 +83,6 @@ import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
@ -116,6 +115,7 @@ import com.owncloud.android.operations.GetServerInfoOperation;
import com.owncloud.android.operations.OAuth2GetAccessToken;
import com.owncloud.android.services.OperationsService;
import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
import com.owncloud.android.ui.activity.FirstRunActivity;
import com.owncloud.android.ui.components.CustomEditText;
import com.owncloud.android.ui.dialog.CredentialsDialogFragment;
import com.owncloud.android.ui.dialog.IndeterminateProgressDialog;
@ -146,6 +146,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
public static final String EXTRA_ACTION = "ACTION";
public static final String EXTRA_ACCOUNT = "ACCOUNT";
public static final String EXTRA_USE_PROVIDER_AS_WEBLOGIN = "USE_PROVIDER_AS_WEBLOGIN";
private static final String KEY_AUTH_TOKEN_TYPE = "AUTH_TOKEN_TYPE";
@ -258,6 +259,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
//Log_OC.e(TAG, "onCreate init");
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
FirstRunActivity.runIfNeeded(this);
}
basicTokenType = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType(this));
oauthTokenType = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType(this));
samlTokenType = AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType(this));
@ -265,7 +270,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
// delete cookies for webView
deleteCookies();
// Workaround, for fixing a problem with Android Library Suppor v7 19
// Workaround, for fixing a problem with Android Library Support v7 19
//getWindow().requestFeature(Window.FEATURE_NO_TITLE);
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
@ -291,7 +296,17 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mIsFirstAuthAttempt = savedInstanceState.getBoolean(KEY_AUTH_IS_FIRST_ATTEMPT_TAG);
}
String webloginUrl;
boolean showLegacyLogin;
if (getIntent().getBooleanExtra(EXTRA_USE_PROVIDER_AS_WEBLOGIN, false)) {
webViewLoginMethod = true;
webloginUrl = getString(R.string.provider_registration_server);
showLegacyLogin = false;
} else {
webViewLoginMethod = !TextUtils.isEmpty(getResources().getString(R.string.webview_login_url));
webloginUrl = null;
showLegacyLogin = true;
}
if (webViewLoginMethod) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
@ -328,7 +343,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
} else {
setContentView(R.layout.account_setup_webview);
mLoginWebView = findViewById(R.id.login_webview);
initWebViewLogin(null);
initWebViewLogin(webloginUrl, showLegacyLogin);
}
initServerPreFragment(savedInstanceState);
@ -355,7 +370,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
}
@SuppressLint("SetJavaScriptEnabled")
private void initWebViewLogin(String baseURL) {
private void initWebViewLogin(String baseURL, boolean showLegacyLogin) {
mLoginWebView.setVisibility(View.GONE);
final ProgressBar progressBar = findViewById(R.id.login_webview_progress_bar);
@ -372,7 +387,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
String url;
if (baseURL != null && !baseURL.isEmpty()) {
url = baseURL + WEB_LOGIN;
url = baseURL;
} else {
url = getResources().getString(R.string.webview_login_url);
}
@ -382,6 +397,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
setClient(progressBar);
// show snackbar after 60s to switch back to old login method
if (showLegacyLogin) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
@ -416,7 +432,25 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
}
}).show();
}
}, 60000);
}, 60 * 1000);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mLoginWebView != null && event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (mLoginWebView.canGoBack()) {
mLoginWebView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
private void setClient(ProgressBar progressBar) {
@ -588,18 +622,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mOkButton = findViewById(R.id.buttonOK);
mOkButton.setOnClickListener(v -> onOkClick());
setupWelcomeLink();
setupInstructionMessage();
mTestServerButton.setVisibility(mAction == ACTION_CREATE ? View.VISIBLE : View.GONE);
}
private void setupWelcomeLink() {
Button welcomeLink = findViewById(R.id.welcome_link);
welcomeLink.setVisibility(mAction == ACTION_CREATE &&
getResources().getBoolean(R.bool.show_welcome_link) ? View.VISIBLE : View.GONE);
welcomeLink.setText(getString(R.string.auth_register));
}
private void setupInstructionMessage() {
String instructionsMessageText = calculateInstructionMessageText(mAction, mAuthTokenType);
@ -947,6 +974,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (data != null && data.toString().startsWith(getString(R.string.oauth2_redirect_uri))) {
mNewCapturedUriFromOAuth2Redirection = data;
}
if (intent.getBooleanExtra(EXTRA_USE_PROVIDER_AS_WEBLOGIN, false)) {
webViewLoginMethod = true;
setContentView(R.layout.account_setup_webview);
mLoginWebView = findViewById(R.id.login_webview);
initWebViewLogin(getString(R.string.provider_registration_server), false);
}
}
@ -1097,7 +1131,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private void checkOcServer() {
String uri;
if (mHostUrlInput != null) {
if (mHostUrlInput != null && !mHostUrlInput.getText().toString().isEmpty()) {
uri = mHostUrlInput.getText().toString().trim();
mOkButton.setEnabled(false);
showRefreshButton(false);
@ -1439,7 +1473,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
setContentView(R.layout.account_setup_webview);
mLoginWebView = findViewById(R.id.login_webview);
initWebViewLogin(mServerInfo.mBaseUrl);
initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, true);
} else {
// show old login
setOldLoginVisibility(View.VISIBLE);
@ -1771,7 +1805,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
} else { // authorization fail due to client side - probably wrong credentials
if (webViewLoginMethod) {
mLoginWebView = findViewById(R.id.login_webview);
initWebViewLogin(mServerInfo.mBaseUrl);
initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, true);
DisplayUtils.showSnackMessage(this, mLoginWebView, R.string.auth_access_failed, result.getLogMessage());
} else {
@ -1947,21 +1981,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
}
}
/**
* Starts and activity to open the 'new account' page in the ownCloud web site
*
* @param view 'Account register' button
*/
public void onRegisterClick(View view) {
Intent register = new Intent(
Intent.ACTION_VIEW, Uri.parse(getString(R.string.welcome_link_url))
);
setResult(RESULT_CANCELED);
startActivity(register);
}
/**
* Updates the content and visibility state of the icon and text associated
* to the last check on the ownCloud server.
@ -2051,8 +2070,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mOkButton.performClick();
}
} else if (actionId == EditorInfo.IME_ACTION_NEXT && inputField != null &&
inputField.equals(mHostUrlInput)) {
} else if ((actionId == EditorInfo.IME_ACTION_NEXT || actionId == EditorInfo.IME_NULL)
&& inputField != null && inputField.equals(mHostUrlInput)) {
checkOcServer();
}
return false; // always return false to grant that the software keyboard is hidden anyway

View file

@ -0,0 +1,115 @@
/*
* Nextcloud Android client application
*
* @author Bartosz Przybylski
* Copyright (C) 2015 Bartosz Przybylski
* Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2016 Nextcloud.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.features;
import android.os.Parcel;
import android.os.Parcelable;
import com.owncloud.android.R;
/**
* @author Bartosz Przybylski
* @author Tobias Kaminsky
*/
public class FeatureItem implements Parcelable {
private static final int DO_NOT_SHOW = -1;
private int image;
private int titleText;
private int contentText;
private boolean contentCentered;
private boolean bulletList;
public FeatureItem(int image, int titleText, int contentText, boolean contentCentered, boolean bulletList) {
this.image = image;
this.titleText = titleText;
this.contentText = contentText;
this.contentCentered = contentCentered;
this.bulletList = bulletList;
}
public boolean shouldShowImage() {
return image != DO_NOT_SHOW;
}
public int getImage() {
return image;
}
public boolean shouldShowTitleText() {
return titleText != DO_NOT_SHOW && titleText != R.string.empty;
}
public int getTitleText() {
return titleText;
}
public boolean shouldShowContentText() {
return contentText != DO_NOT_SHOW && contentText != R.string.empty;
}
public int getContentText() {
return contentText;
}
public boolean shouldContentCentered() {
return contentCentered;
}
public boolean shouldShowBulletPointList() {
return bulletList;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(image);
dest.writeInt(titleText);
dest.writeInt(contentText);
dest.writeByte((byte) (contentCentered ? 1 : 0));
dest.writeByte((byte) (bulletList ? 1 : 0));
}
private FeatureItem(Parcel p) {
image = p.readInt();
titleText = p.readInt();
contentText = p.readInt();
contentCentered = p.readByte() == 1;
bulletList = p.readByte() == 1;
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public Object createFromParcel(Parcel source) {
return new FeatureItem(source);
}
@Override
public Object[] newArray(int size) {
return new FeatureItem[size];
}
};
}

View file

@ -1,194 +0,0 @@
/*
* Nextcloud Android client application
*
* @author Bartosz Przybylski
* Copyright (C) 2015 Bartosz Przybylski
* Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2016 Nextcloud.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.features;
import android.os.Parcel;
import android.os.Parcelable;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @author Bartosz Przybylski
*/
public class FeatureList {
private static final boolean SHOW_ON_FIRST_RUN = true;
private static final boolean SHOW_ON_UPGRADE = false;
private static final int VERSION_1_0_0 = 10000099;
private static final int VERSION_3_0_0 = 30000099;
private static final int VERSION_3_3_0 = 30030099;
private static final int BETA_VERSION_0 = 0;
static public List<FeatureItem> get(boolean isMultiAccount) {
List<FeatureItem> featuresList = new ArrayList<>();
// Basic features showed on first install
featuresList.add(new FeatureItem(R.drawable.whats_new_files,
R.string.welcome_feature_1_title, R.string.welcome_feature_1_text,
VERSION_1_0_0, BETA_VERSION_0, SHOW_ON_FIRST_RUN, true, false));
if (isMultiAccount) {
featuresList.add(new FeatureItem(R.drawable.whats_new_accounts,
R.string.welcome_feature_2_title, R.string.welcome_feature_2_text,
VERSION_1_0_0, BETA_VERSION_0, SHOW_ON_FIRST_RUN, true, false));
}
featuresList.add(new FeatureItem(R.drawable.whats_new_auto_upload,
R.string.welcome_feature_3_title, R.string.welcome_feature_3_text,
VERSION_1_0_0, BETA_VERSION_0, SHOW_ON_FIRST_RUN, true, false));
// 3.0.0
featuresList.add(new FeatureItem(R.drawable.whats_new_end_to_end_encryption,
R.string.whats_new_end_to_end_encryption_title, R.string.whats_new_end_to_end_encryption_content,
VERSION_3_0_0, BETA_VERSION_0, SHOW_ON_UPGRADE, false, false));
featuresList.add(new FeatureItem(R.drawable.whats_new_resized_images, R.string.whats_new_resized_images_title,
R.string.whats_new_resized_images_content, VERSION_3_0_0, BETA_VERSION_0, SHOW_ON_UPGRADE,
false, false));
featuresList.add(new FeatureItem(R.drawable.whats_new_ipv6, R.string.whats_new_ipv6_title,
R.string.whats_new_ipv6_content, VERSION_3_0_0,
BETA_VERSION_0, SHOW_ON_UPGRADE, false, false));
// 3.3.0
featuresList.add(new FeatureItem(R.drawable.whats_new_device_credentials,
R.string.whats_new_device_credentials_title, R.string.whats_new_device_credentials_content,
VERSION_3_3_0, BETA_VERSION_0, SHOW_ON_UPGRADE, false, false));
return featuresList;
}
static public FeatureItem[] getFiltered(int lastSeenVersionCode, boolean isFirstRun, boolean isBeta,
boolean isMultiAccount) {
List<FeatureItem> features = new LinkedList<>();
for (FeatureItem item : get(isMultiAccount)) {
final int itemVersionCode = isBeta ? item.getBetaVersionNumber() : item.getVersionCode();
if (isFirstRun && item.shouldShowOnFirstRun()) {
features.add(item);
} else if (!isFirstRun && !item.shouldShowOnFirstRun() &&
MainApp.getVersionCode() >= itemVersionCode &&
lastSeenVersionCode < itemVersionCode) {
features.add(item);
}
}
return features.toArray(new FeatureItem[features.size()]);
}
static public class FeatureItem implements Parcelable {
public static final int DO_NOT_SHOW = -1;
private int image;
private int titleText;
private int contentText;
private int versionCode;
private int betaVersion;
private boolean showOnInitialRun;
private boolean contentCentered;
private boolean bulletList;
public FeatureItem(int image, int titleText, int contentText, int version, int betaVersion) {
this(image, titleText, contentText, version, betaVersion, false, true, true);
}
public FeatureItem(int image, int titleText, int contentText, int version, int betaVersion,
boolean showOnInitialRun) {
this(image, titleText, contentText, version, betaVersion, showOnInitialRun, true, true);
}
public FeatureItem(int image, int titleText, int contentText, int versionCode, int betaVersion,
boolean showOnInitialRun, boolean contentCentered, boolean bulletList) {
this.image = image;
this.titleText = titleText;
this.contentText = contentText;
this.versionCode = versionCode;
this.betaVersion = betaVersion;
this.showOnInitialRun = showOnInitialRun;
this.contentCentered = contentCentered;
this.bulletList = bulletList;
}
public boolean shouldShowImage() { return image != DO_NOT_SHOW; }
public int getImage() { return image; }
public boolean shouldShowTitleText() { return titleText != DO_NOT_SHOW; }
public int getTitleText() { return titleText; }
public boolean shouldShowContentText() { return contentText != DO_NOT_SHOW; }
public int getContentText() { return contentText; }
public int getVersionCode() {
return versionCode;
}
public int getBetaVersionNumber() { return betaVersion; }
public boolean shouldShowOnFirstRun() { return showOnInitialRun; }
public boolean shouldContentCentered() {
return contentCentered;
}
public boolean shouldShowBulletPointList() {
return bulletList;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(image);
dest.writeInt(titleText);
dest.writeInt(contentText);
dest.writeInt(versionCode);
dest.writeInt(betaVersion);
dest.writeByte((byte) (showOnInitialRun ? 1 : 0));
dest.writeByte((byte) (contentCentered ? 1 : 0));
dest.writeByte((byte) (bulletList ? 1 : 0));
}
private FeatureItem(Parcel p) {
image = p.readInt();
titleText = p.readInt();
contentText = p.readInt();
versionCode = p.readInt();
betaVersion = p.readInt();
showOnInitialRun = p.readByte() == 1;
contentCentered = p.readByte() == 1;
bulletList = p.readByte() == 1;
}
public static final Parcelable.Creator CREATOR =
new Parcelable.Creator() {
@Override
public Object createFromParcel(Parcel source) {
return new FeatureItem(source);
}
@Override
public Object[] newArray(int size) {
return new FeatureItem[size];
}
};
}
}

View file

@ -105,7 +105,7 @@ public abstract class BaseActivity extends AppCompatActivity {
/**
* Tries to swap the current ownCloud {@link Account} for other valid and existing.
*
* If no valid ownCloud {@link Account} exists, the the user is requested
* If no valid ownCloud {@link Account} exists, then the user is requested
* to create a new ownCloud {@link Account}.
*
* POSTCONDITION: updates {@link #mAccountWasSet} and {@link #mAccountWasRestored}.

View file

@ -446,7 +446,9 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
UserInfoActivity.openAccountRemovalConfirmationDialog(getAccount(), getFragmentManager(), true);
break;
case R.id.drawer_menu_account_add:
createAccount(false);
Intent firstRunIntent = new Intent(getApplicationContext(), FirstRunActivity.class);
firstRunIntent.putExtra(FirstRunActivity.EXTRA_ALLOW_CLOSE, true);
startActivity(firstRunIntent);
break;
case R.id.drawer_menu_account_manage:
Intent manageAccountsIntent = new Intent(getApplicationContext(), ManageAccountsActivity.class);

View file

@ -0,0 +1,228 @@
/*
* Nextcloud Android client application
*
* @author Bartosz Przybylski
* Copyright (C) 2015 Bartosz Przybylski
* Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2016 Nextcloud.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.ui.activity;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.features.FeatureItem;
import com.owncloud.android.ui.adapter.FeaturesViewAdapter;
import com.owncloud.android.ui.whatsnew.ProgressIndicator;
import com.owncloud.android.utils.DisplayUtils;
/**
* Activity displaying general feature after a fresh install.
*/
public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageChangeListener {
public static final String KEY_LAST_SEEN_VERSION_CODE = "lastSeenVersionCode";
public static final String EXTRA_ALLOW_CLOSE = "ALLOW_CLOSE";
public static final int FIRST_RUN_RESULT_CODE = 199;
private static final String TAG = FirstRunActivity.class.getSimpleName();
private ProgressIndicator mProgress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_run_activity);
boolean isProviderOrOwnInstallationVisible = getResources().getBoolean(R.bool.show_provider_or_own_installation);
setSlideshowSize(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
Button loginButton = findViewById(R.id.login);
loginButton.setBackgroundColor(Color.WHITE);
loginButton.setTextColor(Color.BLACK);
loginButton.setOnClickListener(v -> {
if (getIntent().getBooleanExtra(EXTRA_ALLOW_CLOSE, false)) {
Intent authenticatorActivityIntent = new Intent(this, AuthenticatorActivity.class);
authenticatorActivityIntent.putExtra(AuthenticatorActivity.EXTRA_USE_PROVIDER_AS_WEBLOGIN, false);
startActivityForResult(authenticatorActivityIntent, FIRST_RUN_RESULT_CODE);
} else {
finish();
}
});
Button providerButton = findViewById(R.id.signup);
providerButton.setBackgroundColor(getResources().getColor(R.color.primary_dark));
providerButton.setTextColor(getResources().getColor(R.color.login_text_color));
providerButton.setVisibility(isProviderOrOwnInstallationVisible ? View.VISIBLE : View.GONE);
providerButton.setOnClickListener(v -> {
Intent authenticatorActivityIntent = new Intent(this, AuthenticatorActivity.class);
authenticatorActivityIntent.putExtra(AuthenticatorActivity.EXTRA_USE_PROVIDER_AS_WEBLOGIN, true);
if (getIntent().getBooleanExtra(EXTRA_ALLOW_CLOSE, false)) {
startActivityForResult(authenticatorActivityIntent, FIRST_RUN_RESULT_CODE);
} else {
authenticatorActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(authenticatorActivityIntent);
}
});
TextView hostOwnServerTextView = findViewById(R.id.host_own_server);
hostOwnServerTextView.setTextColor(getResources().getColor(R.color.login_text_color));
hostOwnServerTextView.setVisibility(isProviderOrOwnInstallationVisible ? View.VISIBLE : View.GONE);
mProgress = findViewById(R.id.progressIndicator);
ViewPager mPager = findViewById(R.id.contentPanel);
// Sometimes, accounts are not deleted when you uninstall the application so we'll do it now
if (isFirstRun(this)) {
AccountManager am = (AccountManager) getSystemService(ACCOUNT_SERVICE);
if (am != null) {
for (Account account : AccountUtils.getAccounts(this)) {
am.removeAccount(account, null, null);
}
}
}
FeaturesViewAdapter featuresViewAdapter = new FeaturesViewAdapter(getSupportFragmentManager(),
getFirstRun());
mProgress.setNumberOfSteps(featuresViewAdapter.getCount());
mPager.setAdapter(featuresViewAdapter);
mPager.addOnPageChangeListener(this);
}
private void setSlideshowSize(boolean isLandscape) {
boolean isProviderOrOwnInstallationVisible = getResources().getBoolean(R.bool.show_provider_or_own_installation);
LinearLayout buttonLayout = findViewById(R.id.buttonLayout);
LinearLayout.LayoutParams layoutParams;
buttonLayout.setOrientation(isLandscape ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
LinearLayout bottomLayout = findViewById(R.id.bottomLayout);
if (isProviderOrOwnInstallationVisible) {
layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
} else {
layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
DisplayUtils.convertDpToPixel(isLandscape ? 100f : 150f, this));
}
bottomLayout.setLayoutParams(layoutParams);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
setSlideshowSize(true);
} else {
setSlideshowSize(false);
}
}
@Override
public void onBackPressed() {
onFinish();
if (getIntent().getBooleanExtra(EXTRA_ALLOW_CLOSE, false)) {
super.onBackPressed();
}
}
private void onFinish() {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = pref.edit();
editor.putInt(KEY_LAST_SEEN_VERSION_CODE, MainApp.getVersionCode());
editor.apply();
}
static private boolean isFirstRun(Context context) {
return AccountUtils.getCurrentOwnCloudAccount(context) == null;
}
static public boolean runIfNeeded(Context context) {
if (context instanceof FirstRunActivity) {
return false;
}
if (isFirstRun(context) && context instanceof AuthenticatorActivity) {
context.startActivity(new Intent(context, FirstRunActivity.class));
return true;
} else {
return false;
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// unused but to be implemented due to abstract parent
}
@Override
public void onPageSelected(int position) {
mProgress.animateToStep(position + 1);
}
@Override
public void onPageScrollStateChanged(int state) {
// unused but to be implemented due to abstract parent
}
public void onHostYourOwnServerClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_server_install))));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (FIRST_RUN_RESULT_CODE == requestCode && RESULT_OK == resultCode) {
setAccount(AccountUtils.getCurrentOwnCloudAccount(this));
onAccountSet(false);
Intent i = new Intent(this, FileDisplayActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
public static FeatureItem[] getFirstRun() {
return new FeatureItem[]{
new FeatureItem(R.drawable.logo, R.string.first_run_1_text, R.string.empty, true, false),
new FeatureItem(R.drawable.first_run_files, R.string.first_run_2_text, R.string.empty, true, false),
new FeatureItem(R.drawable.first_run_groupware, R.string.first_run_3_text, R.string.empty, true, false),
new FeatureItem(R.drawable.first_run_talk, R.string.first_run_4_text, R.string.empty, true, false)};
}
}

View file

@ -270,6 +270,13 @@ public class ManageAccountsActivity extends FileActivity
}
@Override
public void showFirstRunActivity() {
Intent firstRunIntent = new Intent(getApplicationContext(), FirstRunActivity.class);
firstRunIntent.putExtra(FirstRunActivity.EXTRA_ALLOW_CLOSE, true);
startActivity(firstRunIntent);
}
// @Override
public void createAccount() {
AccountManager am = AccountManager.get(getApplicationContext());
am.addAccount(MainApp.getAccountType(this),

View file

@ -22,48 +22,30 @@
package com.owncloud.android.ui.activity;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.BulletSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountAuthenticatorActivity;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.features.FeatureList;
import com.owncloud.android.features.FeatureList.FeatureItem;
import com.owncloud.android.features.FeatureItem;
import com.owncloud.android.ui.adapter.FeaturesViewAdapter;
import com.owncloud.android.ui.adapter.FeaturesWebViewAdapter;
import com.owncloud.android.ui.whatsnew.ProgressIndicator;
import com.owncloud.android.utils.ThemeUtils;
/**
* Activity displaying general feature after a fresh install and new features after an update.
* Activity displaying new features after an update.
*/
public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPageChangeListener {
@ -79,22 +61,12 @@ public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPa
super.onCreate(savedInstanceState);
setContentView(R.layout.whats_new_activity);
int fontColor = ThemeUtils.fontColor(this);
int fontColor = getResources().getColor(R.color.login_text_color);
mProgress = findViewById(R.id.progressIndicator);
mPager = findViewById(R.id.contentPanel);
final boolean isBeta = getResources().getBoolean(R.bool.is_beta);
final boolean isMultiAccount = getResources().getBoolean(R.bool.multiaccount_support);
String[] urls = getResources().getStringArray(R.array.whatsnew_urls);
// Sometimes, accounts are not deleted when you uninstall the application so we'll do it now
if (isFirstRun()) {
AccountManager am = (AccountManager) getSystemService(ACCOUNT_SERVICE);
for (Account account : AccountUtils.getAccounts(this)) {
am.removeAccount(account, null, null);
}
}
boolean showWebView = urls.length > 0;
if (showWebView) {
@ -104,20 +76,17 @@ public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPa
mPager.setAdapter(featuresWebViewAdapter);
} else {
FeaturesViewAdapter featuresViewAdapter = new FeaturesViewAdapter(getSupportFragmentManager(),
FeatureList.getFiltered(getLastSeenVersionCode(), isFirstRun(), isBeta, isMultiAccount));
getWhatsNew(this));
mProgress.setNumberOfSteps(featuresViewAdapter.getCount());
mPager.setAdapter(featuresViewAdapter);
}
mPager.addOnPageChangeListener(this);
mForwardFinishButton = findViewById(R.id.forward);
ThemeUtils.colorImageButton(mForwardFinishButton, fontColor);
mForwardFinishButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mForwardFinishButton.setOnClickListener(view -> {
if (mProgress.hasNextStep()) {
mPager.setCurrentItem(mPager.getCurrentItem() + 1, true);
mProgress.animateToStep(mPager.getCurrentItem() + 1);
@ -126,7 +95,6 @@ public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPa
finish();
}
updateNextButtonIfNeeded();
}
});
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
@ -137,20 +105,15 @@ public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPa
mSkipButton = findViewById(R.id.skip);
mSkipButton.setTextColor(fontColor);
mSkipButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mSkipButton.setOnClickListener(view -> {
onFinish();
finish();
}
});
TextView tv = findViewById(R.id.welcomeText);
if (showWebView) {
tv.setText(R.string.app_name);
} else if (isFirstRun()) {
tv.setText(R.string.empty);
} else {
tv.setText(String.format(getString(R.string.whats_new_title), MainApp.getVersionName()));
}
@ -164,7 +127,6 @@ public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPa
super.onBackPressed();
}
private void updateNextButtonIfNeeded() {
if (!mProgress.hasNextStep()) {
mForwardFinishButton.setImageResource(R.drawable.ic_done_white);
@ -182,15 +144,6 @@ public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPa
editor.apply();
}
static public int getLastSeenVersionCode() {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(MainApp.getAppContext());
return pref.getInt(KEY_LAST_SEEN_VERSION_CODE, 0);
}
static private boolean isFirstRun() {
return getLastSeenVersionCode() == 0 && AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext()) == null;
}
static public void runIfNeeded(Context context) {
if (!context.getResources().getBoolean(R.bool.show_whats_new)) {
return;
@ -206,12 +159,7 @@ public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPa
}
static private boolean shouldShow(Context context) {
final boolean isBeta = context.getResources().getBoolean(R.bool.is_beta);
final boolean isMultiAccount = context.getResources().getBoolean(R.bool.multiaccount_support);
return (isFirstRun() && context instanceof AccountAuthenticatorActivity) || (!(isFirstRun() &&
(context instanceof FileDisplayActivity)) && !(context instanceof PassCodeActivity) &&
(FeatureList.getFiltered(getLastSeenVersionCode(), isFirstRun(), isBeta, isMultiAccount).length > 0));
return !(context instanceof PassCodeActivity) && (getWhatsNew(context).length > 0);
}
@Override
@ -230,172 +178,22 @@ public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPa
// unused but to be implemented due to abstract parent
}
private final class FeaturesWebViewAdapter extends FragmentPagerAdapter {
private String[] mWebUrls;
public FeaturesWebViewAdapter(FragmentManager fm, String[] webUrls) {
super(fm);
mWebUrls = webUrls;
static private boolean isFirstRun(Context context) {
return AccountUtils.getCurrentOwnCloudAccount(context) == null;
}
@Override
public Fragment getItem(int position) {
return FeatureWebFragment.newInstance(mWebUrls[position]);
}
static private FeatureItem[] getWhatsNew(Context context) {
int itemVersionCode = 30030000;
@Override
public int getCount() {
return mWebUrls.length;
}
}
int lastSeenVersionCode = MainApp.getLastSeenVersionCode(context);
public static class FeatureWebFragment extends Fragment {
private String mWebUrl;
static public FeatureWebFragment newInstance(String webUrl) {
FeatureWebFragment f = new FeatureWebFragment();
Bundle args = new Bundle();
args.putString("url", webUrl);
f.setArguments(args);
return f;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWebUrl = getArguments() != null ? getArguments().getString("url") : null;
}
@SuppressLint("SetJavaScriptEnabled")
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.whats_new_webview_element, container, false);
WebView webView = v.findViewById(R.id.whatsNewWebView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setAllowFileAccess(false);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl(mWebUrl);
return v;
}
}
private final class FeaturesViewAdapter extends FragmentPagerAdapter {
private FeatureItem[] mFeatures;
public FeaturesViewAdapter(FragmentManager fm, FeatureItem[] features) {
super(fm);
mFeatures = features;
}
@Override
public Fragment getItem(int position) {
return FeatureFragment.newInstance(mFeatures[position]);
}
@Override
public int getCount() {
return mFeatures.length;
}
}
public static class FeatureFragment extends Fragment {
private FeatureItem mItem;
static public FeatureFragment newInstance(FeatureItem item) {
FeatureFragment f = new FeatureFragment();
Bundle args = new Bundle();
args.putParcelable("feature", item);
f.setArguments(args);
return f;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mItem = getArguments() != null ? (FeatureItem) getArguments().getParcelable("feature") : null;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.whats_new_element, container, false);
int fontColor = ThemeUtils.fontColor(getContext());
ImageView iv = v.findViewById(R.id.whatsNewImage);
if (mItem.shouldShowImage()) {
iv.setImageResource(mItem.getImage());
}
TextView titleTextView = v.findViewById(R.id.whatsNewTitle);
if (mItem.shouldShowTitleText()) {
titleTextView.setText(mItem.getTitleText());
titleTextView.setTextColor(fontColor);
}
if (mItem.shouldShowContentText()) {
LinearLayout linearLayout = v.findViewById(R.id.whatsNewTextLayout);
if (mItem.shouldShowBulletPointList()) {
String[] texts = getText(mItem.getContentText()).toString().split("\n");
for (String text : texts) {
TextView textView = generateTextView(text, getContext(),
mItem.shouldContentCentered(), fontColor, true);
linearLayout.addView(textView);
}
if (!isFirstRun(context) && MainApp.getVersionCode() >= itemVersionCode
&& lastSeenVersionCode < itemVersionCode) {
return new FeatureItem[]{(new FeatureItem(R.drawable.whats_new_device_credentials,
R.string.whats_new_device_credentials_title, R.string.whats_new_device_credentials_content,
false, false))};
} else {
TextView textView = generateTextView(getText(mItem.getContentText()).toString(),
getContext(), mItem.shouldContentCentered(), fontColor, false);
linearLayout.addView(textView);
return new FeatureItem[0];
}
}
return v;
}
}
private static TextView generateTextView(String text, Context context,
boolean shouldContentCentered, int fontColor,
boolean showBulletPoints) {
int standardMargin = context.getResources().getDimensionPixelSize(R.dimen.standard_margin);
int doubleMargin = context.getResources()
.getDimensionPixelSize(R.dimen.standard_double_margin);
int zeroMargin = context.getResources().getDimensionPixelSize(R.dimen.zero);
TextView textView = new TextView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(doubleMargin, standardMargin, doubleMargin, zeroMargin);
textView.setTextAppearance(context, R.style.NextcloudTextAppearanceMedium);
textView.setLayoutParams(layoutParams);
if (showBulletPoints) {
BulletSpan bulletSpan = new BulletSpan(standardMargin, fontColor);
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(bulletSpan, 0, spannableString.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
} else {
textView.setText(text);
}
textView.setTextColor(fontColor);
if (!shouldContentCentered) {
textView.setGravity(Gravity.START);
} else {
textView.setGravity(Gravity.CENTER_HORIZONTAL);
}
return textView;
}
}

View file

@ -127,7 +127,7 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
((ImageView) actionView.findViewById(R.id.user_icon)).setImageResource(R.drawable.ic_account_plus);
// bind action listener
actionView.setOnClickListener(v -> mListener.createAccount());
actionView.setOnClickListener(v -> mListener.showFirstRunActivity());
return actionView;
}
@ -184,7 +184,7 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
*/
public interface AccountListAdapterListener {
void createAccount();
void showFirstRunActivity();
}
/**

View file

@ -0,0 +1,28 @@
package com.owncloud.android.ui.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.owncloud.android.features.FeatureItem;
import com.owncloud.android.ui.fragment.FeatureFragment;
public class FeaturesViewAdapter extends FragmentPagerAdapter {
private FeatureItem[] mFeatures;
public FeaturesViewAdapter(FragmentManager fm, FeatureItem[] features) {
super(fm);
mFeatures = features;
}
@Override
public Fragment getItem(int position) {
return FeatureFragment.newInstance(mFeatures[position]);
}
@Override
public int getCount() {
return mFeatures.length;
}
}

View file

@ -0,0 +1,26 @@
package com.owncloud.android.ui.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.owncloud.android.ui.fragment.FeatureWebFragment;
public class FeaturesWebViewAdapter extends FragmentPagerAdapter {
private String[] mWebUrls;
public FeaturesWebViewAdapter(FragmentManager fm, String[] webUrls) {
super(fm);
mWebUrls = webUrls;
}
@Override
public Fragment getItem(int position) {
return FeatureWebFragment.newInstance(mWebUrls[position]);
}
@Override
public int getCount() {
return mWebUrls.length;
}
}

View file

@ -0,0 +1,119 @@
package com.owncloud.android.ui.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.BulletSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.owncloud.android.R;
import com.owncloud.android.features.FeatureItem;
public class FeatureFragment extends Fragment {
private FeatureItem mItem;
static public FeatureFragment newInstance(FeatureItem item) {
FeatureFragment f = new FeatureFragment();
Bundle args = new Bundle();
args.putParcelable("feature", item);
f.setArguments(args);
return f;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mItem = getArguments() != null ? (FeatureItem) getArguments().getParcelable("feature") : null;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.whats_new_element, container, false);
int fontColor = getResources().getColor(R.color.login_text_color);
ImageView iv = v.findViewById(R.id.whatsNewImage);
if (mItem.shouldShowImage()) {
iv.setImageResource(mItem.getImage());
}
TextView titleTextView = v.findViewById(R.id.whatsNewTitle);
if (mItem.shouldShowTitleText()) {
titleTextView.setText(mItem.getTitleText());
titleTextView.setTextColor(fontColor);
titleTextView.setVisibility(View.VISIBLE);
} else {
titleTextView.setVisibility(View.GONE);
}
LinearLayout linearLayout = v.findViewById(R.id.whatsNewTextLayout);
if (mItem.shouldShowContentText()) {
if (mItem.shouldShowBulletPointList()) {
String[] texts = getText(mItem.getContentText()).toString().split("\n");
for (String text : texts) {
TextView textView = generateTextView(text, getContext(),
mItem.shouldContentCentered(), fontColor, true);
linearLayout.addView(textView);
}
} else {
TextView textView = generateTextView(getText(mItem.getContentText()).toString(),
getContext(), mItem.shouldContentCentered(), fontColor, false);
linearLayout.addView(textView);
}
} else {
linearLayout.setVisibility(View.GONE);
}
return v;
}
private TextView generateTextView(String text, Context context,
boolean shouldContentCentered, int fontColor,
boolean showBulletPoints) {
int standardMargin = context.getResources().getDimensionPixelSize(R.dimen.standard_margin);
int doubleMargin = context.getResources()
.getDimensionPixelSize(R.dimen.standard_double_margin);
int zeroMargin = context.getResources().getDimensionPixelSize(R.dimen.zero);
TextView textView = new TextView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(doubleMargin, standardMargin, doubleMargin, zeroMargin);
textView.setTextAppearance(context, R.style.NextcloudTextAppearanceMedium);
textView.setLayoutParams(layoutParams);
if (showBulletPoints) {
BulletSpan bulletSpan = new BulletSpan(standardMargin, fontColor);
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(bulletSpan, 0, spannableString.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
} else {
textView.setText(text);
}
textView.setTextColor(fontColor);
if (!shouldContentCentered) {
textView.setGravity(Gravity.START);
} else {
textView.setGravity(Gravity.CENTER_HORIZONTAL);
}
return textView;
}
}

View file

@ -0,0 +1,49 @@
package com.owncloud.android.ui.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.owncloud.android.R;
public class FeatureWebFragment extends Fragment {
private String mWebUrl;
static public FeatureWebFragment newInstance(String webUrl) {
FeatureWebFragment f = new FeatureWebFragment();
Bundle args = new Bundle();
args.putString("url", webUrl);
f.setArguments(args);
return f;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWebUrl = getArguments() != null ? getArguments().getString("url") : null;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.whats_new_webview_element, container, false);
WebView webView = v.findViewById(R.id.whatsNewWebView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setAllowFileAccess(false);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl(mWebUrl);
return v;
}
}

View file

@ -33,7 +33,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import com.owncloud.android.R;
import com.owncloud.android.utils.ThemeUtils;
/**
* Progress indicator visualizing the actual progress with dots.
@ -65,7 +64,7 @@ public class ProgressIndicator extends FrameLayout {
}
public void setNumberOfSteps(int steps) {
int fontColor = ThemeUtils.fontColor(getContext());
int fontColor = getResources().getColor(R.color.login_text_color);
mNumberOfSteps = steps;
mDotsContainer.removeAllViews();
for (int i = 0; i < steps; ++i) {

View file

@ -50,6 +50,7 @@ import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.StyleSpan;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@ -762,6 +763,13 @@ public class DisplayUtils {
}
}
public static int convertDpToPixel(float dp, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
return (int) (dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
}
static public void showServerOutdatedSnackbar(Activity activity) {
Snackbar.make(activity.findViewById(android.R.id.content),
R.string.outdated_server, Snackbar.LENGTH_INDEFINITE)

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:fillColor="#ffffff"
android:pathData="M1.5,2 C1.25,2,1,2.25,1,2.5 L1,13.5 C1,13.76,1.24,14,1.5,14 L14.5,14 C14.76,14,15,13.759,15,13.5 L15,4.5 C15,4.25,14.75,4,14.5,4 L8,4 L6,2 L1.5,2 Z M10.25,5.5 A1.25,1.25,0,0,1,11.5,6.75 A1.25,1.25,0,0,1,10.25,8 A1.25,1.25,0,0,1,9.4492,7.709 L6.998,8.9355 A1.25,1.25,0,0,1,7,9 A1.25,1.25,0,0,1,6.9961,9.0645 L9.4492,10.291 A1.25,1.25,0,0,1,10.25,10 A1.25,1.25,0,0,1,11.5,11.25 A1.25,1.25,0,0,1,10.25,12.5 A1.25,1.25,0,0,1,9,11.25 A1.25,1.25,0,0,1,9.0039,11.186 L6.5508,9.959 A1.25,1.25,0,0,1,5.75,10.25 A1.25,1.25,0,0,1,4.5,9 A1.25,1.25,0,0,1,5.75,7.75 A1.25,1.25,0,0,1,6.5508,8.041 L9.002,6.8145 A1.25,1.25,0,0,1,9,6.75 A1.25,1.25,0,0,1,10.25,5.5 Z"/>
</vector>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:fillColor="#ffffff"
android:pathData="M9,1 C7.254,1,6,2.43,6,3.8 C6,5.2,6.1,6.2,6.8,7.3 C7.024,7.59,7.285,7.65,7.5,7.9 C7.635,8.4,7.74,8.9,7.6,9.4 C7.164,9.553,6.75,9.732,6.33,9.9 C5.82,9.627,5.23,9.4,4.72,9.2 C4.65,8.92,4.7,8.713,4.77,8.45 C4.89,8.325,5,8.27,5.13,8.15 C5.5,7.7,5.52,6.94,5.52,6.4 C5.52,5.6,4.8,5,4.02,5 C3.15,5,2.52,5.72,2.52,6.4 L2.5,6.4 C2.5,7.1,2.55,7.6,2.9,8.15 C3,8.3,3.142,8.325,3.25,8.45 C3.3174,8.7,3.371,8.95,3.3,9.2 C2.66,9.423,2.056,9.7,1.5,10 C1.08,10.3,1.267,10.182,1,11.15 C0.876,11.65,2.3,11.88,3.32,11.96 C3.27,12.235,3.2,12.6,3,13.3 C2.68,14.55,7.353,15,9,15 C11.43,15,15.313,14.544,14.98,13.3 C14.46,11.36,14.772,11.59,14,11 C12.91,10.346,11.548,9.833,10.4,9.4 C10.25,8.843,10.36,8.43,10.5,7.9 C10.735,7.65,11,7.54,11.22,7.3 C11.91,6.416,12,4.876,12,3.8 C12,2.214,10.57,1,9,1 Z"/>
</vector>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<group
android:translateX="-15.580506"
android:translateY="-164.12649">
<path
android:fillColor="#ffffff"
android:strokeWidth="0.13229023"
android:pathData="M 23.579679,165.51155 a 6.6138496,6.6139445 0 0 0 -6.613756,6.61414 6.6138496,6.6139445 0 0 0 6.613756,6.61394 6.6138496,6.6139445 0 0 0 3.430853,-0.96761 c 0.812866,0.32302 2.633614,1.28133 3.066959,0.86739 0.452829,-0.43245 -0.531627,-2.46778 -0.767642,-3.2241 a 6.6138496,6.6139445 0 0 0 0.88351,-3.28968 6.6138496,6.6139445 0 0 0 -6.613662,-6.61385 z m 0.000769,2.51456 a 4.1009972,4.1010914 0 0 1 4.100984,4.10109 4.1009972,4.1010914 0 0 1 -4.100997,4.10081 4.1009972,4.1010914 0 0 1 -4.100997,-4.10081 4.1009972,4.1010914 0 0 1 4.100997,-4.10109 z"/>
</group>
</vector>

View file

@ -288,26 +288,6 @@
android:text="@string/setup_btn_connect"
android:contentDescription="@string/setup_btn_connect"
android:visibility="gone"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|bottom">
<Button
android:id="@+id/welcome_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@android:color/transparent"
android:onClick="onRegisterClick"
android:paddingTop="@dimen/alternate_half_padding"
android:text="@string/auth_register"
android:textColor="@color/login_text_hint_color"
android:contentDescription="@string/auth_register"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View file

@ -271,25 +271,6 @@
android:text="@string/setup_btn_connect"
android:contentDescription="@string/setup_btn_connect"
android:visibility="gone"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|bottom">
<Button
android:id="@+id/welcome_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:onClick="onRegisterClick"
android:paddingBottom="@dimen/alternate_half_padding"
android:paddingTop="@dimen/alternate_half_padding"
android:text="@string/auth_register"
android:textColor="@color/login_text_hint_color"
android:contentDescription="@string/auth_register"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Nextcloud Android client application
@author Tobias Kaminsky
Copyright (C) 2018 Tobias Kaminsky
Copyright (C) 2018 Nextcloud GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/standard_margin"
android:layout_weight="1"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/contentPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<com.owncloud.android.ui.whatsnew.ProgressIndicator
android:id="@+id/progressIndicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/standard_margin">
</com.owncloud.android.ui.whatsnew.ProgressIndicator>
</LinearLayout>
<LinearLayout
android:id="@+id/bottomLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_weight="0"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:id="@+id/buttonLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_weight="1"
android:maxWidth="500dp"
android:minWidth="300dp"
android:text="@string/login"/>
<Button
android:id="@+id/signup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_weight="1"
android:maxWidth="500dp"
android:minWidth="300dp"
android:text="@string/signup_with_provider"/>
</LinearLayout>
<TextView
android:id="@+id/host_own_server"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:onClick="onHostYourOwnServerClick"
android:text="@string/host_your_own_server"/>
</LinearLayout>
</LinearLayout>

View file

@ -47,8 +47,10 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="@dimen/standard_margin"
android:layout_marginLeft="@dimen/standard_margin"
android:layout_marginRight="@dimen/standard_margin"
android:layout_marginTop="@dimen/standard_double_margin"
android:layout_weight="8"
android:orientation="horizontal"
android:weightSum="3">
@ -86,8 +88,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/arrow_right"
android:contentDescription="@string/forward"/>
android:contentDescription="@string/forward"
android:src="@drawable/arrow_right"/>
</LinearLayout>
</LinearLayout>

View file

@ -20,48 +20,48 @@
License along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:weightSum="100">
<ImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:id="@+id/whatsNewImage"
android:layout_width="200dp"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="@dimen/alternate_margin"
android:layout_weight="50"
android:src="@drawable/whats_new_files"
android:contentDescription="@string/what_s_new_image"/>
android:layout_weight="60"
android:contentDescription="@string/what_s_new_image"
app:srcCompat="@drawable/whats_new_files"/>
<TextView
android:id="@+id/whatsNewTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center"
android:layout_marginBottom="@dimen/standard_half_margin"
android:layout_marginEnd="@dimen/standard_margin"
android:layout_marginLeft="@dimen/standard_margin"
android:layout_marginRight="@dimen/standard_margin"
android:layout_marginStart="@dimen/standard_margin"
android:gravity="center"
android:text="@string/welcome_feature_1_title"
android:textAppearance="@style/NextcloudTextAppearanceHeadline"
android:textColor="@color/white"
android:textStyle="bold"
android:text="@string/welcome_feature_1_title"
android:id="@+id/whatsNewTitle"
android:layout_marginLeft="@dimen/standard_margin"
android:layout_marginStart="@dimen/standard_margin"
android:layout_marginRight="@dimen/standard_margin"
android:layout_marginEnd="@dimen/standard_margin"
android:layout_marginBottom="@dimen/standard_half_margin"
android:layout_gravity="center_horizontal"
android:gravity="center"/>
android:textStyle="bold"/>
<LinearLayout
android:id="@+id/whatsNewTextLayout"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:layout_marginLeft="@dimen/standard_margin"
android:layout_marginStart="@dimen/standard_margin"
android:layout_marginRight="@dimen/standard_margin"
android:layout_gravity="center_horizontal|center"
android:layout_margin="@dimen/standard_margin"
android:layout_marginEnd="@dimen/standard_margin"
android:layout_marginBottom="@dimen/standard_half_margin"
android:layout_marginStart="@dimen/standard_margin"
android:gravity="center"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>

View file

@ -27,8 +27,8 @@
<!-- Can be regular (full input), prefix (subdomain input) and suffix (directory input) -->
<!-- Requires server url to be set -->
<string name="server_input_type">regular</string>
<bool name="show_welcome_link">true</bool>
<string name="welcome_link_url">"https://nextcloud.com/providers"</string>
<bool name="show_provider_or_own_installation">true</bool>
<string name="provider_registration_server">https://www.nextcloud.com/register</string>
<!-- Flags to setup the authentication methods available in the app -->
<string name="auth_method_oauth2">off</string>

View file

@ -797,6 +797,13 @@
<string name="prefs_e2e_mnemonic">E2E mnemonic</string>
<string name="prefs_e2e_no_device_credentials">To show mnemonic please enable device credentials.</string>
<string name="whats_new_device_credentials_title">Use Android\'s device internal protection</string>
<string name="login">Log in</string>
<string name="signup_with_provider">Sign up with provider</string>
<string name="host_your_own_server">Host your own server</string>
<string name="first_run_1_text">Keep your data secure and under your control</string>
<string name="first_run_2_text">Secure collaboration &amp; file exchange</string>
<string name="first_run_3_text">Easy-to-use web mail, calendering &amp; contacts</string>
<string name="first_run_4_text">Screensharing, online meetings &amp; web conferences</string>
<string name="whats_new_device_credentials_content">Use anything like a pattern, password, pin or your fingerprint to keep your data safe.</string>
<string name="restore_button_description">Restore deleted file</string>
<string name="restore">Restore file</string>
@ -810,7 +817,6 @@
<string name="new_media_folder_detected">New %1$s media folder detected.</string>
<string name="new_media_folder_photos">photo</string>
<string name="new_media_folder_videos">video</string>
<string name="outdated_server">The server has reached end of life, please upgrade!</string>
<string name="dismiss">Dismiss</string>
<string name="feedback_no_mail_app">No app available to send mails!</string>