Merge pull request #3187 from nextcloud/handleNoApps

Wrapper to start urls/intents if no app is available
This commit is contained in:
Andy Scherzinger 2018-10-29 22:24:59 +01:00 committed by GitHub
commit 831f083153
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 89 additions and 95 deletions

View file

@ -203,7 +203,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private AccountManager mAccountMgr;
private Uri mNewCapturedUriFromOAuth2Redirection;
/// Server PRE-Fragment elements
/// Server PRE-Fragment elements
private CustomEditText mHostUrlInput;
private View mRefreshButton;
private TextView mServerStatusView;
@ -217,7 +217,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private GetServerInfoOperation.ServerInfo mServerInfo = new GetServerInfoOperation.ServerInfo();
/// Authentication PRE-Fragment elements
/// Authentication PRE-Fragment elements
private CheckBox mOAuth2Check;
private TextView mOAuthAuthEndpointText;
private TextView mOAuthTokenEndpointText;
@ -237,7 +237,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private boolean mIsFirstAuthAttempt;
/// Identifier of operation in progress which result shouldn't be lost
/// Identifier of operation in progress which result shouldn't be lost
private long mWaitingForOpId = Long.MAX_VALUE;
private String basicTokenType;
@ -264,7 +264,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (savedInstanceState == null) {
FirstRunActivity.runIfNeeded(this);
}
basicTokenType = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType(this));
oauthTokenType = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType(this));
samlTokenType = AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType(this));
@ -379,7 +379,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mLoginWebView.getSettings().setAllowFileAccess(false);
mLoginWebView.getSettings().setJavaScriptEnabled(true);
mLoginWebView.getSettings().setDomStorageEnabled(true);
if (useGenericUserAgent) {
mLoginWebView.getSettings().setUserAgentString(MainApp.getNextcloudUserAgent());
} else {
@ -1339,7 +1339,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
uri = uriBuilder.build();
Log_OC.d(TAG, "Starting browser to view " + uri.toString());
Intent i = new Intent(Intent.ACTION_VIEW, uri);
startActivity(i);
DisplayUtils.startIntentIfAppAvailable(i, this, R.string.no_browser_available);
}
@ -1371,7 +1372,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (operation instanceof GetServerInfoOperation) {
if (operation.hashCode() == mWaitingForOpId) {
onGetServerInfoFinish(result);
} // else nothing ; only the last check operation is considered;
} // else nothing ; only the last check operation is considered;
// multiple can be started if the user amends a URL quickly
} else if (operation instanceof OAuth2GetAccessToken) {
@ -1456,7 +1457,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
// 1. connection succeeded, and we know if it's SSL or not
// 2. server is installed
// 3. we got the server version
// 4. we got the authentication method required by the server
// 4. we got the authentication method required by the server
mServerInfo = (GetServerInfoOperation.ServerInfo) (result.getData().get(0));
// show outdated warning
@ -1776,7 +1777,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
}
} else if (result.isServerFail() || result.isException()) {
/// server errors or exceptions in authorization take to requiring a new check of
/// server errors or exceptions in authorization take to requiring a new check of
/// the server
mServerIsChecked = true;
mServerIsValid = false;
@ -1837,13 +1838,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (AccountTypeUtils.getAuthTokenTypeAccessToken(accountType).equals(mAuthTokenType)) {
response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);
// the next line is necessary, notifications are calling directly to the
// the next line is necessary, notifications are calling directly to the
// AuthenticatorActivity to update, without AccountManager intervention
mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
} else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(accountType).equals(mAuthTokenType)) {
response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);
// the next line is necessary; by now, notifications are calling directly to the
// the next line is necessary; by now, notifications are calling directly to the
// AuthenticatorActivity to update, without AccountManager intervention
mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
@ -1938,7 +1939,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
}
/// prepare result to return to the Authenticator
// TODO check again what the Authenticator makes with it; probably has the same
// TODO check again what the Authenticator makes with it; probably has the same
// effect as addAccountExplicitly, but it's not well done
final Intent intent = new Intent();
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, accountType);
@ -1947,7 +1948,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (isOAuth || isSaml) {
mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
}
/// add user data to the new account; TODO probably can be done in the last parameter
/// add user data to the new account; TODO probably can be done in the last parameter
// addAccountExplicitly, or in KEY_USERDATA
mAccountMgr.setUserData(mAccount, Constants.KEY_OC_VERSION, mServerInfo.mVersion.getVersion());
mAccountMgr.setUserData(mAccount, Constants.KEY_OC_BASE_URL, mServerInfo.mBaseUrl);
@ -2053,7 +2054,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
/**
* Called when the 'action' button in an IME is pressed ('enter' in software keyboard).
*
*
* Used to trigger the authentication check when the user presses 'enter' after writing the
* password, or to throw the server test when the only field on screen is the URL input field.
*/
@ -2192,7 +2193,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
public void onSavedCertificate() {
Fragment fd = getSupportFragmentManager().findFragmentByTag(SAML_DIALOG_TAG);
if (fd == null) {
// if SAML dialog is not shown,
// if SAML dialog is not shown,
// the SslDialog was shown due to an SSL error in the server check
checkOcServer();
}

View file

@ -545,7 +545,8 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
for (ExternalLink link : externalLinksProvider.getExternalLink(ExternalLinkType.LINK)) {
if (menuItem.getTitle().toString().equalsIgnoreCase(link.name)) {
if (link.redirect) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link.url)));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link.url));
DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available);
} else {
Intent externalWebViewIntent = new Intent(getApplicationContext(), ExternalSiteWebView.class);
externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, link.name);

View file

@ -613,7 +613,7 @@ public abstract class FileActivity extends DrawerActivity
LoadingVersionNumberTask loadTask = new LoadingVersionNumberTask(callback);
loadTask.execute(url);
}
public static void showDevSnackbar(Activity activity, Integer latestVersion, boolean openDirectly) {
Integer currentVersion = -1;
try {
@ -630,7 +630,7 @@ public abstract class FileActivity extends DrawerActivity
String devApkLink = (String) activity.getText(R.string.dev_link) + latestVersion + ".apk";
Uri uriUrl = Uri.parse(devApkLink);
Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
activity.startActivity(intent);
DisplayUtils.startIntentIfAppAvailable(intent, activity, R.string.no_browser_available);
} else {
Snackbar.make(activity.findViewById(android.R.id.content), R.string.dev_version_new_version_available,
Snackbar.LENGTH_LONG)
@ -638,7 +638,7 @@ public abstract class FileActivity extends DrawerActivity
String devApkLink = (String) activity.getText(R.string.dev_link) + latestVersion + ".apk";
Uri uriUrl = Uri.parse(devApkLink);
Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
activity.startActivity(intent);
DisplayUtils.startIntentIfAppAvailable(intent, activity, R.string.no_browser_available);
}).show();
}
} else {

View file

@ -63,7 +63,7 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
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);
@ -181,7 +181,7 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
if (!isProviderOrOwnInstallationVisible) {
return false;
}
if (context instanceof FirstRunActivity) {
return false;
}
@ -210,7 +210,8 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
}
public void onHostYourOwnServerClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_server_install))));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_server_install)));
DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available);
}
@Override
@ -224,7 +225,7 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
DisplayUtils.showSnackMessage(this, R.string.account_creation_failed);
return;
}
setAccount(account);
AccountUtils.setCurrentOwnCloudAccount(this, account.name);
onAccountSet(false);

View file

@ -23,7 +23,6 @@ package com.owncloud.android.ui.activity;
import android.content.Intent;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.widget.AppCompatButton;
import android.text.Html;
@ -33,6 +32,7 @@ import android.view.View;
import android.widget.TextView;
import com.owncloud.android.R;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.ThemeUtils;
/**
@ -94,28 +94,23 @@ public class ParticipateActivity extends FileActivity {
AppCompatButton reportButton = findViewById(R.id.participate_testing_report);
reportButton.getBackground().setColorFilter(ThemeUtils.primaryAccentColor(this), PorterDuff.Mode.SRC_ATOP);
reportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.report_issue_link))));
}
});
reportButton.setOnClickListener(v -> DisplayUtils.startLinkIntent(this, R.string.report_issue_link));
}
public void onGetBetaFDroidClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.fdroid_beta_link))));
DisplayUtils.startLinkIntent(this, R.string.fdroid_beta_link);
}
public void onGetRCFDroidClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.fdroid_link))));
DisplayUtils.startLinkIntent(this, R.string.fdroid_link);
}
public void onGetRCPlayStoreClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.play_store_register_beta))));
DisplayUtils.startLinkIntent(this, R.string.play_store_register_beta);
}
public void onGetBetaApkClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.beta_apk_link))));
DisplayUtils.startLinkIntent(this, R.string.beta_apk_link);
}
@Override

View file

@ -172,7 +172,7 @@ public class Preferences extends PreferenceActivity
// About
setupAboutCategory(accentColor, appVersion);
// Dev
setupDevCategory(accentColor, preferenceScreen);
}
@ -202,10 +202,7 @@ public class Preferences extends PreferenceActivity
Preference pChangelogLink = findPreference("changelog_link");
if (pChangelogLink != null) {
pChangelogLink.setOnPreferenceClickListener(preference -> {
String devChangelogLink = getString(R.string.dev_changelog);
Uri uriUrl = Uri.parse(devChangelogLink);
Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
startActivity(intent);
DisplayUtils.startLinkIntent(this, R.string.dev_changelog);
return true;
});
}
@ -230,14 +227,10 @@ public class Preferences extends PreferenceActivity
boolean licenseEnabled = getResources().getBoolean(R.bool.license_enabled);
Preference licensePreference = findPreference("license");
if (licensePreference != null) {
String licenseUrl = getString(R.string.license_url);
if (licenseEnabled && !licenseUrl.isEmpty()) {
if (licenseEnabled) {
licensePreference.setSummary(R.string.prefs_gpl_v2);
licensePreference.setOnPreferenceClickListener(preference -> {
Uri uriUrl = Uri.parse(licenseUrl);
Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
startActivity(intent);
DisplayUtils.startLinkIntent(this, R.string.license_url);
return true;
});
} else {
@ -258,6 +251,7 @@ public class Preferences extends PreferenceActivity
Intent intent;
if ("application/pdf".equals(mimeType)) {
intent = new Intent(Intent.ACTION_VIEW, privacyUrl);
DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_pdf_app_available);
} else {
intent = new Intent(getApplicationContext(), ExternalSiteWebView.class);
intent.putExtra(ExternalSiteWebView.EXTRA_TITLE,
@ -283,12 +277,9 @@ public class Preferences extends PreferenceActivity
boolean sourcecodeEnabled = getResources().getBoolean(R.bool.sourcecode_enabled);
Preference sourcecodePreference = findPreference("sourcecode");
if (sourcecodePreference != null) {
String sourcecodeUrl = getString(R.string.sourcecode_url);
if (sourcecodeEnabled && !sourcecodeUrl.isEmpty()) {
if (sourcecodeEnabled) {
sourcecodePreference.setOnPreferenceClickListener(preference -> {
Uri uriUrl = Uri.parse(sourcecodeUrl);
Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
startActivity(intent);
DisplayUtils.startLinkIntent(this, R.string.sourcecode_url);
return true;
});
} else {
@ -332,7 +323,7 @@ public class Preferences extends PreferenceActivity
if (!imprintWeb.isEmpty()) {
Uri uriUrl = Uri.parse(imprintWeb);
Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
startActivity(intent);
DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available);
}
//ImprintDialog.newInstance(true).show(preference.get, "IMPRINT_DIALOG");
return true;
@ -460,7 +451,7 @@ public class Preferences extends PreferenceActivity
if (!helpWeb.isEmpty()) {
Uri uriUrl = Uri.parse(helpWeb);
Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
startActivity(intent);
DisplayUtils.startIntentIfAppAvailable(intent, this, R.string.no_browser_available);
}
return true;
});
@ -803,7 +794,7 @@ public class Preferences extends PreferenceActivity
// no f-droid market app or Play store installed --> launch browser for f-droid url
Intent downloadIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("https://f-droid.org/repository/browse/?fdid=at.bitfire.davdroid"));
startActivity(downloadIntent);
DisplayUtils.startIntentIfAppAvailable(downloadIntent, this, R.string.no_browser_available);
DisplayUtils.showSnackMessage(this, R.string.prefs_calendar_contacts_no_store_error);
}
@ -891,7 +882,7 @@ public class Preferences extends PreferenceActivity
builder.show();
}
}
@Override
@NonNull
public MenuInflater getMenuInflater() {

View file

@ -272,7 +272,9 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
}
private void openLink(String link) {
notificationsActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
DisplayUtils.startIntentIfAppAvailable(intent, notificationsActivity, R.string.no_browser_available);
}
@Override

View file

@ -23,9 +23,7 @@ package com.owncloud.android.ui.fragment;
import android.accounts.Account;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
@ -63,6 +61,7 @@ import com.owncloud.android.ui.dialog.SharePasswordDialogFragment;
import com.owncloud.android.ui.fragment.util.FileDetailSharingFragmentHelper;
import com.owncloud.android.ui.fragment.util.SharingMenuHelper;
import com.owncloud.android.utils.ClipboardUtil;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.ThemeUtils;
import java.util.List;
@ -373,11 +372,8 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
public void showNotSupportedByOcMessage() {
if (getView() != null) {
Snackbar.make(getView(), R.string.files_drop_not_supported, Snackbar.LENGTH_LONG)
.setAction(R.string.learn_more, v -> {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(getString(R.string.url_server_install)));
startActivity(i);
})
.setAction(R.string.learn_more, v ->
DisplayUtils.startLinkIntent(requireActivity(), R.string.url_server_install))
.show();
}
}
@ -473,7 +469,7 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
/**
* Get known server capabilities from DB
*
*
* Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
* instance ready to use. If not ready, does nothing.
*/
@ -485,9 +481,9 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
/**
* Get public link from the DB to fill in the "Share link" section in the UI.
*
*
* Takes into account server capabilities before reading database.
*
*
* Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
* instance ready to use. If not ready, does nothing.
*/

View file

@ -25,10 +25,8 @@ package com.owncloud.android.ui.fragment;
import android.accounts.Account;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
@ -62,8 +60,8 @@ import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.ThemeUtils;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Date;
import java.util.List;
/**
* Fragment for Sharing a file with sharees (users or groups) or creating
@ -543,14 +541,8 @@ public class ShareFileFragment extends Fragment implements ShareUserListAdapter.
} else {
// not supported in ownCloud
Snackbar.make(getView(), R.string.files_drop_not_supported, Snackbar.LENGTH_LONG)
.setAction(R.string.learn_more, new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(getString(R.string.url_server_install)));
startActivity(i);
}
})
.setAction(R.string.learn_more, v ->
DisplayUtils.startLinkIntent(requireActivity(), R.string.url_server_install))
.show();
}

View file

@ -765,7 +765,7 @@ public final class DisplayUtils {
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)
@ -773,4 +773,17 @@ public final class DisplayUtils {
})
.show();
}
static public void startLinkIntent(Activity activity, @StringRes int link) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(activity.getString(link)));
DisplayUtils.startIntentIfAppAvailable(intent, activity, R.string.no_browser_available);
}
static public void startIntentIfAppAvailable(Intent intent, Activity activity, @StringRes int error) {
if (intent.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivity(intent);
} else {
DisplayUtils.showSnackMessage(activity, error);
}
}
}

View file

@ -94,16 +94,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/participate_release_candidate_playstore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/white"
android:onClick="onGetRCPlayStoreClick"
android:padding="@dimen/zero"
android:src="@drawable/playstore"
android:contentDescription="@string/participate_rc_play_store"/>
<ImageButton
android:id="@+id/participate_release_candidate_fdroid"
android:layout_width="wrap_content"
@ -114,6 +104,16 @@
android:src="@drawable/fdroid"
android:contentDescription="@string/participate_rc_fdroid"/>
<ImageButton
android:id="@+id/participate_release_candidate_playstore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/white"
android:onClick="onGetRCPlayStoreClick"
android:padding="@dimen/zero"
android:src="@drawable/playstore"
android:contentDescription="@string/participate_rc_play_store"/>
</LinearLayout>
<TextView
@ -204,4 +204,4 @@
android:layout_height="match_parent"
android:layout_gravity="start"/>
</android.support.v4.widget.DrawerLayout>
</android.support.v4.widget.DrawerLayout>

View file

@ -205,7 +205,7 @@
<string name="pass_code_enter_pass_code">Please enter your passcode</string>
<string name="default_credentials_wrong">Incorrect credentials</string>
<string name="credentials_disabled">Credentials disabled</string>
<string name="pass_code_configure_your_pass_code">Enter your passcode</string>
<string name="pass_code_configure_your_pass_code_explanation">The passcode will be requested every time the app is started</string>
<string name="pass_code_reenter_your_pass_code">Please reenter your passcode</string>
@ -214,7 +214,7 @@
<string name="pass_code_wrong">Incorrect passcode</string>
<string name="pass_code_removed">Passcode deleted</string>
<string name="pass_code_stored">Passcode stored</string>
<string name="media_notif_ticker">%1$s music player</string>
<string name="media_state_playing">%1$s (playing)</string>
<string name="media_state_loading">%1$s (loading)</string>
@ -294,10 +294,10 @@
<string name="filedisplay_no_file_selected">No file selected</string>
<string name="activity_chooser_title">Send link to…</string>
<string name="wait_for_tmp_copy_from_private_storage">Copying file from private storage</string>
<string name="oauth_check_onoff">Log in with OAuth 2.0</string>
<string name="oauth_login_connection">Connecting to OAuth 2.0 server…</string>
<string name="ssl_validator_header">The identity of the server could not be verified</string>
<string name="ssl_validator_reason_cert_not_trusted">- The server certificate is not trusted</string>
<string name="ssl_validator_reason_cert_expired">- The server certificate expired</string>
@ -723,7 +723,7 @@
<string name="notification_channel_file_sync_description">Shows file sync progress and results</string>
<string name="notification_channel_file_observer_name">File observer</string>
<string name="notification_channel_file_observer_description">Monitors files for changes</string>
<string name="account_not_found">Account not found!</string>
<string name="screenshot_01_gridView">A safe home for all your data</string>
@ -732,12 +732,12 @@
<string name="screenshot_04_accounts">Connect to different accounts</string>
<string name="screenshot_05_autoUpload">Automatically upload your photos &amp; videos</string>
<string name="screenshot_06_davdroid">Sync calendar &amp; contacts with DAVdroid</string>
<string name="userinfo_no_info_headline">No personal info set</string>
<string name="userinfo_no_info_text">Add name, picture and contact details on your profile page.</string>
<string name="drawer_header_background">Background image of drawer header</string>
<string name="account_icon">Account icon</string>
<string name="end_to_end_encryption_folder_not_empty">This folder is not empty.</string>
<string name="end_to_end_encryption_wrong_password">Error while decrypting. Wrong password?</string>
<string name="end_to_end_encryption_decrypting">Decrypting…</string>
@ -827,5 +827,7 @@
<string name="send_note">Send note to recipient</string>
<string name="note_could_not_sent">Could not send note</string>
<string name="hint_note">Note</string>
<string name="no_browser_available">No app available to handle links</string>
<string name="no_pdf_app_available">No App available to handle PDF</string>
</resources>