397 lines
13 KiB
Java
397 lines
13 KiB
Java
/*
|
|
* Copyright (c) 2022 Proton AG
|
|
*
|
|
* This file is part of Proton Mail.
|
|
*
|
|
* Proton Mail 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.
|
|
*
|
|
* Proton Mail 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 Proton Mail. If not, see https://www.gnu.org/licenses/.
|
|
*/
|
|
package ch.protonmail.android.activities;
|
|
|
|
import static ch.protonmail.android.worker.FetchUserWorkerKt.FETCH_USER_INFO_WORKER_NAME;
|
|
import static ch.protonmail.android.worker.FetchUserWorkerKt.FETCH_USER_INFO_WORKER_RESULT;
|
|
|
|
import android.app.AlertDialog;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.os.Bundle;
|
|
import android.text.method.LinkMovementMethod;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.widget.Button;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.LayoutRes;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.appcompat.app.AppCompatDelegate;
|
|
import androidx.appcompat.widget.Toolbar;
|
|
import androidx.work.WorkManager;
|
|
|
|
import com.birbit.android.jobqueue.JobManager;
|
|
import com.google.android.material.snackbar.Snackbar;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import butterknife.BindView;
|
|
import butterknife.ButterKnife;
|
|
import ch.protonmail.android.R;
|
|
import ch.protonmail.android.adapters.swipe.SwipeProcessor;
|
|
import ch.protonmail.android.api.NetworkConfigurator;
|
|
import ch.protonmail.android.api.ProtonMailApiManager;
|
|
import ch.protonmail.android.api.models.MailSettings;
|
|
import ch.protonmail.android.api.models.User;
|
|
import ch.protonmail.android.bl.Html5Handler;
|
|
import ch.protonmail.android.bl.HtmlDivHandler;
|
|
import ch.protonmail.android.bl.HtmlProcessor;
|
|
import ch.protonmail.android.bl.XHtmlHandler;
|
|
import ch.protonmail.android.core.BigContentHolder;
|
|
import ch.protonmail.android.core.NetworkResults;
|
|
import ch.protonmail.android.core.ProtonMailApplication;
|
|
import ch.protonmail.android.core.QueueNetworkUtil;
|
|
import ch.protonmail.android.core.UserManager;
|
|
import ch.protonmail.android.feature.account.AccountStateManager;
|
|
import ch.protonmail.android.jobs.organizations.GetOrganizationJob;
|
|
import ch.protonmail.android.utils.CustomLocale;
|
|
import ch.protonmail.android.utils.INetworkConfiguratorCallback;
|
|
import ch.protonmail.android.worker.FetchMailSettingsWorker;
|
|
import ch.protonmail.android.worker.FetchUserWorker;
|
|
import dagger.hilt.android.AndroidEntryPoint;
|
|
import me.proton.core.humanverification.presentation.HumanVerificationOrchestrator;
|
|
import timber.log.Timber;
|
|
|
|
@AndroidEntryPoint
|
|
public abstract class BaseActivity extends AppCompatActivity implements INetworkConfiguratorCallback {
|
|
|
|
public static final String EXTRA_IN_APP = "extra_in_app";
|
|
private static final int NO_LAYOUT_ID = -1;
|
|
|
|
private ProtonMailApplication app;
|
|
|
|
@Deprecated // Doesn't make sense for this to be injected nor be used to sub-classes, as it can
|
|
// be retrieved directly from the application context
|
|
@Inject
|
|
protected ProtonMailApplication mApp;
|
|
@Inject
|
|
protected ProtonMailApiManager mApi;
|
|
@Inject
|
|
protected NetworkConfigurator networkConfigurator;
|
|
@Inject
|
|
@Deprecated // TODO this should not be used by sub-classes, they should get it injected
|
|
// directly, as are aiming to remove this base class
|
|
protected UserManager mUserManager;
|
|
@Inject
|
|
protected AccountStateManager accountStateManager;
|
|
@Inject
|
|
protected HumanVerificationOrchestrator humanVerificationOrchestrator;
|
|
@Inject
|
|
protected JobManager mJobManager;
|
|
@Inject
|
|
protected QueueNetworkUtil mNetworkUtil;
|
|
@Inject
|
|
protected SwipeProcessor mSwipeProcessor;
|
|
@Inject
|
|
protected HtmlProcessor mHtmlProcessor;
|
|
@Inject
|
|
protected BigContentHolder mBigContentHolder;
|
|
@Inject
|
|
protected NetworkResults mNetworkResults;
|
|
@Inject
|
|
protected WorkManager workManager;
|
|
@Inject
|
|
protected FetchUserWorker.Enqueuer fetchUserInfoWorkerEnqueuer;
|
|
@Inject
|
|
protected FetchMailSettingsWorker.Enqueuer fetchMailSettingsWorkerEnqueuer;
|
|
|
|
@Nullable
|
|
@BindView(R.id.toolbar)
|
|
protected Toolbar mToolbar;
|
|
@Nullable
|
|
@BindView(R.id.layout_no_connectivity_info)
|
|
protected View mConnectivitySnackLayout;
|
|
@Nullable
|
|
@BindView(R.id.screenProtectorView)
|
|
protected View mScreenProtectorLayout;
|
|
|
|
private BroadcastReceiver mLangReceiver = null;
|
|
private String mCurrentLocale;
|
|
protected Snackbar mRequestTimeoutSnack;
|
|
|
|
private AlertDialog alertDelinquency;
|
|
|
|
/**
|
|
* Optional id for the layout
|
|
*
|
|
* @return the id of the layout to inflate, or {@link #NO_LAYOUT_ID} if
|
|
* {@link #getRootView()} is used
|
|
*/
|
|
@LayoutRes
|
|
protected int getLayoutId() {
|
|
return NO_LAYOUT_ID;
|
|
}
|
|
|
|
/**
|
|
* Optional View to set as content
|
|
*
|
|
* @return the {@link View} to set as content or {@code null} if {@link #getLayoutId()} is used
|
|
*/
|
|
@Nullable
|
|
protected View getRootView() {
|
|
return null;
|
|
}
|
|
|
|
protected boolean isDohOngoing = false;
|
|
protected boolean autoRetry = true;
|
|
|
|
static {
|
|
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
|
}
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
app = (ProtonMailApplication) getApplication();
|
|
super.onCreate(savedInstanceState);
|
|
app.setAppInBackground(false);
|
|
if (savedInstanceState != null) {
|
|
mCurrentLocale = savedInstanceState.getString("curr_loc");
|
|
if (mCurrentLocale != null && !mCurrentLocale.equals(getResources().getConfiguration().locale.toString())) {
|
|
}
|
|
}
|
|
mCurrentLocale = app.getCurrentLocale();
|
|
buildHtmlProcessor();
|
|
|
|
int layoutId = getLayoutId();
|
|
View rootView = getRootView();
|
|
if (layoutId != NO_LAYOUT_ID) {
|
|
setContentView(layoutId);
|
|
} else if (rootView != null) {
|
|
setContentView(rootView);
|
|
}
|
|
|
|
ButterKnife.bind(this);
|
|
if (mToolbar != null) {
|
|
setSupportActionBar(mToolbar);
|
|
}
|
|
|
|
humanVerificationOrchestrator.register(this, false);
|
|
accountStateManager.setHumanVerificationOrchestrator(humanVerificationOrchestrator);
|
|
accountStateManager.observeHVStateWithExternalLifecycle(getLifecycle());
|
|
}
|
|
|
|
@Override
|
|
protected void onDestroy() {
|
|
humanVerificationOrchestrator.unregister(this);
|
|
super.onDestroy();
|
|
}
|
|
|
|
@Override
|
|
protected void onNewIntent(Intent intent) {
|
|
super.onNewIntent(intent);
|
|
}
|
|
|
|
@Override
|
|
protected void onRestart() {
|
|
super.onRestart();
|
|
}
|
|
|
|
protected boolean isPreventingScreenshots() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
protected void onResume() {
|
|
super.onResume();
|
|
|
|
User user = mUserManager.getCurrentLegacyUser();
|
|
|
|
app.setAppInBackground(false);
|
|
networkConfigurator.setNetworkConfiguratorCallback(this);
|
|
|
|
accountStateManager.setHumanVerificationOrchestrator(humanVerificationOrchestrator);
|
|
}
|
|
|
|
@Override
|
|
protected void onPause() {
|
|
app.setAppInBackground(true);
|
|
networkConfigurator.removeNetworkConfiguratorCallback();
|
|
super.onPause();
|
|
}
|
|
|
|
@Override
|
|
protected void onSaveInstanceState(Bundle outState) {
|
|
outState.putString("curr_loc", mCurrentLocale);
|
|
super.onSaveInstanceState(outState);
|
|
}
|
|
|
|
protected boolean isAutoShowRemoteImages() {
|
|
MailSettings mailSettings = mUserManager.getCurrentUserMailSettingsBlocking();
|
|
if (mailSettings != null)
|
|
return mailSettings.getShowImagesFrom().includesRemote();
|
|
else
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
protected void onStart() {
|
|
super.onStart();
|
|
app.setAppInBackground(false);
|
|
app.setCurrentActivity(this);
|
|
getWindow().getDecorView().postDelayed(this::deactivateScreenProtector, 500);
|
|
}
|
|
|
|
@Override
|
|
protected void onStop() {
|
|
super.onStop();
|
|
|
|
if (!(this instanceof AddAttachmentsActivity)) {
|
|
activateScreenProtector();
|
|
}
|
|
}
|
|
|
|
private void deactivateScreenProtector() {
|
|
if (mScreenProtectorLayout != null) {
|
|
mScreenProtectorLayout.setVisibility(View.GONE);
|
|
}
|
|
}
|
|
|
|
private void activateScreenProtector() {
|
|
User currentUser = mUserManager.getCurrentLegacyUser();
|
|
if (currentUser != null && currentUser.isUsePin()) {
|
|
if (mScreenProtectorLayout != null) {
|
|
mScreenProtectorLayout.setVisibility(View.VISIBLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void checkDelinquency() {
|
|
ch.protonmail.android.domain.entity.user.User user = mUserManager.getCurrentUser();
|
|
if (user == null) return;
|
|
boolean areMailRoutesAccessible = user.getDelinquent().getMailRoutesAccessible();
|
|
if (!areMailRoutesAccessible && (alertDelinquency == null || !alertDelinquency.isShowing())) {
|
|
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
LayoutInflater inflater = this.getLayoutInflater();
|
|
View dialogView = inflater.inflate(R.layout.layout_delinquency_dialog, null, false);
|
|
TextView subtitle = dialogView.findViewById(R.id.subtitle);
|
|
subtitle.setMovementMethod(LinkMovementMethod.getInstance());
|
|
Button btnClose = dialogView.findViewById(R.id.close_app);
|
|
Button btnCheckAgain = dialogView.findViewById(R.id.recheck);
|
|
Button btnLogout = dialogView.findViewById(R.id.logout);
|
|
|
|
btnLogout.setOnClickListener(v -> {
|
|
accountStateManager.signOutPrimary().invokeOnCompletion(throwable -> {
|
|
finish();
|
|
return null;
|
|
});
|
|
});
|
|
btnClose.setOnClickListener(v -> finish());
|
|
btnCheckAgain.setOnClickListener(v -> {
|
|
// TODO: Remove fetchUserInfoWorkerEnqueuer, not adapted for this usage.
|
|
fetchUserInfoWorkerEnqueuer.invoke(user.getId());
|
|
workManager.getWorkInfosForUniqueWorkLiveData(FETCH_USER_INFO_WORKER_NAME)
|
|
.observe(this, workInfo -> {
|
|
boolean isDelinquent = workInfo.get(0).getOutputData().getBoolean(FETCH_USER_INFO_WORKER_RESULT, true);
|
|
if (!isDelinquent && alertDelinquency != null && alertDelinquency.isShowing()) {
|
|
alertDelinquency.dismiss();
|
|
}
|
|
});
|
|
});
|
|
builder.setView(dialogView);
|
|
alertDelinquency = builder.create();
|
|
alertDelinquency.setCanceledOnTouchOutside(false);
|
|
alertDelinquency.setCancelable(false);
|
|
if (!isFinishing()) {
|
|
alertDelinquency.show();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void showRequestTimeoutSnack() {
|
|
mRequestTimeoutSnack = Snackbar.make(mConnectivitySnackLayout, getString(R.string.request_timeout), Snackbar.LENGTH_LONG);
|
|
View view = mRequestTimeoutSnack.getView();
|
|
TextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text);
|
|
tv.setTextColor(this.getColor(R.color.text_inverted));
|
|
mRequestTimeoutSnack.show();
|
|
}
|
|
|
|
protected void fetchOrganizationData() {
|
|
User user = mUserManager.getCurrentLegacyUser();
|
|
if (user != null && user.isPaidUser()) {
|
|
GetOrganizationJob getOrganizationJob = new GetOrganizationJob();
|
|
mJobManager.addJobInBackground(getOrganizationJob);
|
|
} else {
|
|
app.setOrganization(null);
|
|
}
|
|
}
|
|
|
|
protected BroadcastReceiver setupLangReceiver() {
|
|
if (mLangReceiver == null) {
|
|
mLangReceiver = new BroadcastReceiver() {
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
// noop
|
|
}
|
|
};
|
|
|
|
IntentFilter filter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
|
|
registerReceiver(mLangReceiver, filter);
|
|
}
|
|
|
|
return mLangReceiver;
|
|
}
|
|
|
|
@Override
|
|
protected void attachBaseContext(Context base) {
|
|
super.attachBaseContext(CustomLocale.INSTANCE.apply(base));
|
|
}
|
|
|
|
private void buildHtmlProcessor() {
|
|
mHtmlProcessor.addHandler(new HtmlDivHandler());
|
|
mHtmlProcessor.addHandler(new Html5Handler());
|
|
mHtmlProcessor.addHandler(new XHtmlHandler());
|
|
}
|
|
|
|
@Override
|
|
public void onApiProvidersChanged() {
|
|
networkConfigurator.refreshDomainsAsync();
|
|
}
|
|
|
|
@Override
|
|
public void startDohSignal() {
|
|
isDohOngoing = true;
|
|
Timber.d("BaseActivity: startDohSignal");
|
|
}
|
|
|
|
@Override
|
|
public void stopDohSignal() {
|
|
isDohOngoing = false;
|
|
Timber.d("BaseActivity: stopDohSignal");
|
|
}
|
|
|
|
@Override
|
|
public void onDohFailed() {
|
|
Timber.d("BaseActivity: Doh All alternative proxies failed");
|
|
}
|
|
|
|
@Override
|
|
public void startAutoRetry() {
|
|
autoRetry = true;
|
|
}
|
|
|
|
@Override
|
|
public void stopAutoRetry() {
|
|
autoRetry = false;
|
|
}
|
|
}
|