FairEmail/app/src/main/java/eu/faircode/email/ActivityView.java

2666 lines
112 KiB
Java
Raw Normal View History

2018-08-02 13:33:06 +00:00
package eu.faircode.email;
/*
2018-08-14 05:53:24 +00:00
This file is part of FairEmail.
2018-08-02 13:33:06 +00:00
2018-08-14 05:53:24 +00:00
FairEmail is free software: you can redistribute it and/or modify
2018-08-02 13:33:06 +00:00
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.
2018-10-29 10:46:49 +00:00
FairEmail is distributed in the hope that it will be useful,
2018-08-02 13:33:06 +00:00
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
2018-10-29 10:46:49 +00:00
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
2018-08-02 13:33:06 +00:00
2024-01-01 07:50:49 +00:00
Copyright 2018-2024 by Marcel Bokhorst (M66B)
2018-08-02 13:33:06 +00:00
*/
2021-07-31 18:13:58 +00:00
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static androidx.drawerlayout.widget.DrawerLayout.LOCK_MODE_LOCKED_OPEN;
import static androidx.drawerlayout.widget.DrawerLayout.LOCK_MODE_UNLOCKED;
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
2021-07-31 18:13:58 +00:00
2019-08-13 08:27:17 +00:00
import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.app.PendingIntent;
2018-08-02 13:33:06 +00:00
import android.content.BroadcastReceiver;
import android.content.Context;
2018-09-07 11:08:20 +00:00
import android.content.DialogInterface;
2018-08-02 13:33:06 +00:00
import android.content.Intent;
import android.content.IntentFilter;
2018-09-08 10:37:28 +00:00
import android.content.SharedPreferences;
2018-08-02 13:33:06 +00:00
import android.content.res.Configuration;
import android.graphics.Canvas;
2021-08-11 16:37:41 +00:00
import android.graphics.Color;
2019-04-29 09:39:24 +00:00
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
2018-08-06 17:04:24 +00:00
import android.net.Uri;
2018-08-02 13:33:06 +00:00
import android.os.Bundle;
2023-01-08 11:29:30 +00:00
import android.text.Spanned;
2019-08-01 06:38:15 +00:00
import android.text.TextUtils;
2020-06-08 19:32:48 +00:00
import android.util.DisplayMetrics;
2021-08-22 18:12:13 +00:00
import android.util.Pair;
2018-08-02 13:33:06 +00:00
import android.view.LayoutInflater;
2021-08-12 18:00:52 +00:00
import android.view.Menu;
2018-08-02 13:33:06 +00:00
import android.view.MenuItem;
import android.view.View;
2020-01-03 10:32:50 +00:00
import android.view.ViewGroup;
2019-08-16 14:35:33 +00:00
import android.widget.ImageButton;
2020-10-11 10:31:51 +00:00
import android.widget.LinearLayout;
import android.widget.TextView;
2018-08-09 20:45:42 +00:00
import android.widget.Toast;
2018-08-02 13:33:06 +00:00
2022-06-12 07:22:55 +00:00
import androidx.activity.OnBackPressedCallback;
2019-06-30 09:35:03 +00:00
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBarDrawerToggle;
2019-06-30 09:35:03 +00:00
import androidx.appcompat.app.AlertDialog;
2021-08-12 07:51:19 +00:00
import androidx.appcompat.widget.PopupMenu;
2021-08-12 06:12:19 +00:00
import androidx.constraintlayout.widget.Group;
import androidx.core.app.NotificationCompat;
2022-05-10 09:11:37 +00:00
import androidx.core.util.Consumer;
2020-05-25 08:38:10 +00:00
import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Lifecycle;
2022-03-30 14:33:52 +00:00
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.Observer;
2022-03-30 14:33:52 +00:00
import androidx.lifecycle.OnLifecycleEvent;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager;
2019-04-29 09:39:24 +00:00
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
2022-05-10 09:11:37 +00:00
import androidx.window.java.layout.WindowInfoTrackerCallbackAdapter;
import androidx.window.layout.WindowInfoTracker;
import androidx.window.layout.WindowLayoutInfo;
2020-07-25 19:11:06 +00:00
import com.google.android.material.snackbar.Snackbar;
2018-09-08 09:41:05 +00:00
import org.json.JSONArray;
2021-01-03 09:58:51 +00:00
import org.json.JSONException;
2018-09-08 09:41:05 +00:00
import org.json.JSONObject;
2018-08-11 04:41:26 +00:00
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
2018-11-13 15:01:29 +00:00
import java.io.IOException;
2018-11-10 15:50:08 +00:00
import java.io.InputStream;
2018-09-08 09:41:05 +00:00
import java.io.InputStreamReader;
import java.net.URL;
2023-01-08 11:29:30 +00:00
import java.text.DateFormat;
import java.text.SimpleDateFormat;
2018-08-13 18:31:42 +00:00
import java.util.ArrayList;
2018-08-07 18:31:14 +00:00
import java.util.Date;
2018-08-02 13:33:06 +00:00
import java.util.List;
2023-01-08 11:29:30 +00:00
import java.util.Locale;
2021-09-17 17:57:10 +00:00
import java.util.Objects;
2022-04-17 12:29:48 +00:00
import java.util.concurrent.Callable;
2018-08-02 13:33:06 +00:00
2018-09-08 09:41:05 +00:00
import javax.net.ssl.HttpsURLConnection;
2018-08-11 04:41:26 +00:00
2018-09-04 18:51:09 +00:00
public class ActivityView extends ActivityBilling implements FragmentManager.OnBackStackChangedListener {
private String startup;
2021-08-11 16:37:41 +00:00
private boolean nav_expanded;
private boolean nav_pinned;
2021-08-12 07:51:19 +00:00
private boolean nav_options;
2021-08-11 16:37:41 +00:00
private int colorDrawerScrim;
2022-05-10 09:11:37 +00:00
private WindowInfoTrackerCallbackAdapter infoTracker;
2021-08-11 16:37:41 +00:00
private int layoutId;
2018-08-25 11:27:54 +00:00
private View view;
private View content_separator;
private View content_pane;
2021-08-30 09:15:45 +00:00
private TwoStateOwner owner;
2020-01-02 09:37:08 +00:00
private DrawerLayoutEx drawerLayout;
2018-08-02 13:33:06 +00:00
private ActionBarDrawerToggle drawerToggle;
2020-05-25 08:38:10 +00:00
private NestedScrollView drawerContainer;
2021-08-11 07:31:00 +00:00
private ImageButton ibExpanderNav;
2021-08-12 06:12:19 +00:00
private ImageButton ibPin;
2021-08-12 18:00:52 +00:00
private ImageButton ibHide;
2021-08-12 06:12:19 +00:00
private ImageButton ibSettings;
private ImageButton ibFetchMore;
2021-08-13 05:37:56 +00:00
private ImageButton ibForceSync;
2021-09-24 11:36:06 +00:00
2021-08-12 07:51:19 +00:00
private View vSeparatorOptions;
2020-01-30 18:05:30 +00:00
private ImageButton ibExpanderAccount;
2021-09-24 11:36:06 +00:00
private RecyclerView rvAccount;
2019-09-01 16:59:51 +00:00
private ImageButton ibExpanderUnified;
2021-09-24 11:36:06 +00:00
private ImageButton ibExpanderSearch;
private RecyclerView rvSearch;
private View vSeparatorSearch;
2019-07-19 06:27:44 +00:00
private RecyclerView rvUnified;
2021-04-07 17:15:01 +00:00
private ImageButton ibExpanderMenu;
2021-09-24 11:36:06 +00:00
private RecyclerView rvMenu;
2019-09-01 16:59:51 +00:00
private ImageButton ibExpanderExtra;
2021-09-24 11:36:06 +00:00
2019-04-29 09:39:24 +00:00
private RecyclerView rvMenuExtra;
2021-09-24 11:36:06 +00:00
2021-08-12 06:12:19 +00:00
private Group grpOptions;
2018-08-02 13:33:06 +00:00
2021-09-17 09:18:05 +00:00
private AdapterNavAccountFolder adapterNavAccount;
2020-01-23 14:27:26 +00:00
private AdapterNavUnified adapterNavUnified;
2021-09-24 11:36:06 +00:00
private AdapterNavSearch adapterNavSearch;
2020-01-23 14:27:26 +00:00
private AdapterNavMenu adapterNavMenu;
private AdapterNavMenu adapterNavMenuExtra;
private boolean initialized = false;
2019-06-12 16:56:38 +00:00
private boolean exit = false;
2019-07-02 07:05:29 +00:00
private boolean searching = false;
2021-04-04 17:29:57 +00:00
private int lastBackStackCount = 0;
2020-07-25 19:28:26 +00:00
private Snackbar lastSnackbar = null;
2019-06-12 16:56:38 +00:00
2021-05-22 14:54:17 +00:00
static final int PI_UNIFIED = 1;
static final int PI_WHY = 2;
2021-07-31 18:13:58 +00:00
static final int PI_THREAD = 3;
static final int PI_OUTBOX = 4;
2021-07-31 19:29:13 +00:00
static final int PI_UPDATE = 5;
2023-01-08 11:29:30 +00:00
static final int PI_ANNOUNCEMENT = 6;
static final int PI_WIDGET = 7;
static final int PI_POWER = 8;
2018-08-25 18:51:01 +00:00
static final String ACTION_VIEW_FOLDERS = BuildConfig.APPLICATION_ID + ".VIEW_FOLDERS";
2018-08-02 13:33:06 +00:00
static final String ACTION_VIEW_MESSAGES = BuildConfig.APPLICATION_ID + ".VIEW_MESSAGES";
2022-11-28 18:26:37 +00:00
static final String ACTION_SEARCH_ADDRESS = BuildConfig.APPLICATION_ID + ".SEARCH_ADDRESS";
2018-10-15 10:05:42 +00:00
static final String ACTION_VIEW_THREAD = BuildConfig.APPLICATION_ID + ".VIEW_THREAD";
2018-08-02 13:33:06 +00:00
static final String ACTION_EDIT_FOLDER = BuildConfig.APPLICATION_ID + ".EDIT_FOLDER";
2021-03-31 16:28:00 +00:00
static final String ACTION_VIEW_OUTBOX = BuildConfig.APPLICATION_ID + ".VIEW_OUTBOX";
2019-01-18 08:28:07 +00:00
static final String ACTION_EDIT_ANSWERS = BuildConfig.APPLICATION_ID + ".EDIT_ANSWERS";
2018-08-27 09:39:27 +00:00
static final String ACTION_EDIT_ANSWER = BuildConfig.APPLICATION_ID + ".EDIT_ANSWER";
2019-01-18 08:23:53 +00:00
static final String ACTION_EDIT_RULES = BuildConfig.APPLICATION_ID + ".EDIT_RULES";
2019-01-17 13:29:35 +00:00
static final String ACTION_EDIT_RULE = BuildConfig.APPLICATION_ID + ".EDIT_RULE";
2020-05-05 13:17:33 +00:00
static final String ACTION_NEW_MESSAGE = BuildConfig.APPLICATION_ID + ".NEW_MESSAGE";
2018-08-02 13:33:06 +00:00
private static final int UPDATE_TIMEOUT = 15 * 1000; // milliseconds
2019-07-02 07:05:29 +00:00
private static final long EXIT_DELAY = 2500L; // milliseconds
static final long UPDATE_DAILY = (BuildConfig.BETA_RELEASE ? 4 : 12) * 3600 * 1000L; // milliseconds
static final long UPDATE_WEEKLY = 7 * 24 * 3600 * 1000L; // milliseconds
2018-09-08 10:37:28 +00:00
2023-01-08 11:29:30 +00:00
private static final int ANNOUNCEMENT_TIMEOUT = 15 * 1000; // milliseconds
private static final long ANNOUNCEMENT_INTERVAL = 4 * 3600 * 1000L; // milliseconds
2022-03-25 09:48:49 +00:00
private static final int REQUEST_RULES_ACCOUNT = 2001;
private static final int REQUEST_RULES_FOLDER = 2002;
2023-06-18 06:38:22 +00:00
private static final int REQUEST_DEBUG_INFO = 7000;
2022-03-25 09:48:49 +00:00
2018-08-02 13:33:06 +00:00
@Override
2019-08-13 08:27:17 +00:00
@SuppressLint("MissingSuperCall")
2018-08-02 13:33:06 +00:00
protected void onCreate(Bundle savedInstanceState) {
2019-08-13 08:27:17 +00:00
super.onCreate(savedInstanceState, false);
2021-04-04 17:29:57 +00:00
if (savedInstanceState != null) {
Intent intent = savedInstanceState.getParcelable("fair:intent");
if (intent != null)
setIntent(intent);
}
// Workaround stale intents from recent apps screen
boolean recents = (getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0;
if (recents) {
Intent intent = getIntent();
2021-04-04 17:29:57 +00:00
Log.i("Stale intent=" + intent);
intent.setAction(null);
}
2020-05-05 16:12:33 +00:00
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
2021-03-27 20:35:31 +00:00
IntentFilter iff = new IntentFilter();
iff.addAction(ACTION_NEW_MESSAGE);
lbm.registerReceiver(creceiver, iff);
2020-05-05 16:12:33 +00:00
2019-07-02 07:05:29 +00:00
if (savedInstanceState != null)
searching = savedInstanceState.getBoolean("fair:searching");
2021-08-11 16:37:41 +00:00
colorDrawerScrim = Helper.resolveColor(this, R.attr.colorDrawerScrim);
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
startup = prefs.getString("startup", "unified");
nav_expanded = getDrawerExpanded();
2021-08-11 16:37:41 +00:00
nav_pinned = getDrawerPinned();
2021-08-12 07:51:19 +00:00
nav_options = prefs.getBoolean("nav_options", true);
2021-08-16 09:45:44 +00:00
// Fix imported settings from other device
if (nav_expanded && nav_pinned && !canExpandAndPin())
nav_pinned = false;
2022-05-10 09:11:37 +00:00
infoTracker = new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
Configuration config = getResources().getConfiguration();
2021-08-11 16:37:41 +00:00
boolean portrait2 = prefs.getBoolean("portrait2", false);
boolean portrait2c = prefs.getBoolean("portrait2c", false);
int portrait_min_size = prefs.getInt("portrait_min_size", 0);
2021-08-11 16:37:41 +00:00
boolean landscape = prefs.getBoolean("landscape", true);
int landscape_min_size = prefs.getInt("landscape_min_size", 0);
int layout = (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK);
Log.i("Orientation=" + config.orientation + " layout=" + layout +
" portrait rows=" + portrait2 + " cols=" + portrait2c + " min=" + portrait_min_size +
2023-09-12 16:25:35 +00:00
" landscape cols=" + landscape + " min=" + landscape_min_size);
boolean duo = Helper.isSurfaceDuo();
boolean close_pane = prefs.getBoolean("close_pane", !duo);
boolean open_pane = (!close_pane && prefs.getBoolean("open_pane", false));
boolean nav_categories = prefs.getBoolean("nav_categories", false);
// 1=small, 2=normal, 3=large, 4=xlarge
if (layout > 0)
layout--;
if (layout < (config.orientation == ORIENTATION_PORTRAIT ? portrait_min_size : landscape_min_size))
layoutId = R.layout.activity_view_portrait;
else if (config.orientation == ORIENTATION_PORTRAIT && portrait2c)
2021-08-11 16:37:41 +00:00
layoutId = R.layout.activity_view_landscape_split;
2021-08-10 07:23:05 +00:00
else if (config.orientation == ORIENTATION_PORTRAIT || !landscape)
2021-08-11 16:37:41 +00:00
layoutId = (portrait2 ? R.layout.activity_view_portrait_split : R.layout.activity_view_portrait);
2020-11-15 12:34:52 +00:00
else
2021-08-11 16:37:41 +00:00
layoutId = R.layout.activity_view_landscape_split;
view = LayoutInflater.from(this).inflate(layoutId, null);
2018-08-25 11:27:54 +00:00
setContentView(view);
2018-08-02 13:33:06 +00:00
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setCustomView(R.layout.action_bar);
getSupportActionBar().setDisplayShowCustomEnabled(true);
2018-08-02 13:33:06 +00:00
content_separator = findViewById(R.id.content_separator);
content_pane = findViewById(R.id.content_pane);
if (content_pane != null) {
// Special: Surface Duo
if (duo) {
View content_frame = findViewById(R.id.content_frame);
ViewGroup.LayoutParams lparam = content_frame.getLayoutParams();
if (lparam instanceof LinearLayout.LayoutParams) {
((LinearLayout.LayoutParams) lparam).weight = 1; // 50/50
content_frame.setLayoutParams(lparam);
}
// https://docs.microsoft.com/en-us/dual-screen/android/duo-dimensions
2023-04-29 18:39:04 +00:00
int seam = (Helper.isSurfaceDuo2() ? 26 : 34);
content_separator.getLayoutParams().width = Helper.dp2pixels(this, seam);
} else {
int column_width = prefs.getInt("column_width", 67);
ViewGroup.LayoutParams lparam = content_pane.getLayoutParams();
if (lparam instanceof LinearLayout.LayoutParams) {
((LinearLayout.LayoutParams) lparam).weight =
(float) (100 - column_width) / column_width * 2;
content_pane.setLayoutParams(lparam);
}
2020-10-11 10:31:51 +00:00
}
}
2021-08-30 09:15:45 +00:00
owner = new TwoStateOwner(this, "drawer");
2022-03-30 14:33:52 +00:00
owner.getLifecycle().addObserver(new LifecycleObserver() {
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
public void onStateChanged() {
Log.i("Drawer state=" + owner.getLifecycle().getCurrentState());
}
});
2018-08-02 13:33:06 +00:00
drawerLayout = findViewById(R.id.drawer_layout);
2020-01-03 10:32:50 +00:00
final ViewGroup childContent = (ViewGroup) drawerLayout.getChildAt(0);
final ViewGroup childDrawer = (ViewGroup) drawerLayout.getChildAt(1);
2018-08-02 13:33:06 +00:00
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.app_name, R.string.app_name) {
public void onDrawerClosed(View view) {
2020-04-23 19:45:59 +00:00
Log.i("Drawer closed");
2022-04-26 10:13:54 +00:00
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
return;
2020-04-23 10:38:18 +00:00
owner.stop();
2020-01-03 16:33:17 +00:00
drawerLayout.setDrawerLockMode(LOCK_MODE_UNLOCKED);
childContent.setPaddingRelative(0, 0, 0, 0);
2020-04-23 10:38:18 +00:00
2018-08-02 13:33:06 +00:00
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
2020-04-23 10:38:18 +00:00
2020-04-23 19:45:59 +00:00
Log.i("Drawer opened");
2022-04-26 10:13:54 +00:00
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
return;
2020-04-23 10:38:18 +00:00
owner.start();
2021-08-11 16:37:41 +00:00
if (nav_pinned) {
2020-01-03 10:32:50 +00:00
drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_OPEN);
2021-08-11 16:37:41 +00:00
int padding = childDrawer.getLayoutParams().width;
childContent.setPaddingRelative(padding, 0, 0, 0);
2020-01-03 10:32:50 +00:00
}
}
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
2020-04-23 10:38:18 +00:00
2022-03-30 14:33:52 +00:00
if (BuildConfig.DEBUG)
Log.i("Drawer slide=" + slideOffset);
2022-04-26 10:13:54 +00:00
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
return;
2022-03-30 14:33:52 +00:00
2020-04-23 10:38:18 +00:00
if (slideOffset > 0)
owner.start();
else
owner.stop();
2021-08-11 16:37:41 +00:00
if (nav_pinned) {
int padding = Math.round(slideOffset * childDrawer.getLayoutParams().width);
childContent.setPaddingRelative(padding, 0, 0, 0);
}
2018-08-02 13:33:06 +00:00
}
};
drawerLayout.addDrawerListener(drawerToggle);
2019-04-28 18:48:45 +00:00
drawerContainer = findViewById(R.id.drawer_container);
2021-08-12 06:12:19 +00:00
ibExpanderNav = drawerContainer.findViewById(R.id.ibExpanderNav);
ibPin = drawerContainer.findViewById(R.id.ibPin);
2021-08-12 18:00:52 +00:00
ibHide = drawerContainer.findViewById(R.id.ibHide);
2021-08-12 06:12:19 +00:00
ibSettings = drawerContainer.findViewById(R.id.ibSettings);
ibFetchMore = drawerContainer.findViewById(R.id.ibFetchMore);
2021-08-13 05:37:56 +00:00
ibForceSync = drawerContainer.findViewById(R.id.ibForceSync);
2021-08-12 07:51:19 +00:00
vSeparatorOptions = drawerContainer.findViewById(R.id.vSeparatorOptions);
2021-08-12 06:12:19 +00:00
grpOptions = drawerContainer.findViewById(R.id.grpOptions);
2021-09-24 11:36:06 +00:00
2021-08-12 06:12:19 +00:00
ibExpanderAccount = drawerContainer.findViewById(R.id.ibExpanderAccount);
rvAccount = drawerContainer.findViewById(R.id.rvAccount);
2021-09-24 11:36:06 +00:00
2021-08-12 06:12:19 +00:00
ibExpanderUnified = drawerContainer.findViewById(R.id.ibExpanderUnified);
rvUnified = drawerContainer.findViewById(R.id.rvUnified);
2021-09-24 11:36:06 +00:00
ibExpanderSearch = drawerContainer.findViewById(R.id.ibExpanderSearch);
rvSearch = drawerContainer.findViewById(R.id.rvSearch);
vSeparatorSearch = drawerContainer.findViewById(R.id.vSeparatorSearch);
2021-08-12 06:12:19 +00:00
ibExpanderMenu = drawerContainer.findViewById(R.id.ibExpanderMenu);
rvMenu = drawerContainer.findViewById(R.id.rvMenu);
2021-09-24 11:36:06 +00:00
2021-08-12 06:12:19 +00:00
ibExpanderExtra = drawerContainer.findViewById(R.id.ibExpanderExtra);
rvMenuExtra = drawerContainer.findViewById(R.id.rvMenuExtra);
2019-02-26 17:44:15 +00:00
2021-08-11 16:37:41 +00:00
ViewGroup.LayoutParams lparam = drawerContainer.getLayoutParams();
lparam.width = getDrawerWidth();
drawerContainer.setLayoutParams(lparam);
2020-06-09 12:39:36 +00:00
2021-08-12 06:12:19 +00:00
// Navigation expander
ibExpanderNav.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nav_expanded = !nav_expanded;
2021-08-12 16:08:56 +00:00
if (nav_expanded && nav_pinned && !canExpandAndPin()) {
nav_pinned = false;
setDrawerPinned(nav_pinned);
}
setDrawerExpanded(nav_expanded);
2021-08-12 06:12:19 +00:00
}
});
ibExpanderNav.setImageLevel(nav_expanded ? 0 : 1);
// Navigation pinning
2021-08-11 16:37:41 +00:00
ibPin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
nav_pinned = !nav_pinned;
2021-08-12 16:08:56 +00:00
if (nav_pinned && nav_expanded && !canExpandAndPin()) {
nav_expanded = false;
setDrawerExpanded(nav_expanded);
}
setDrawerPinned(nav_pinned);
2021-08-11 16:37:41 +00:00
}
});
ibPin.setImageLevel(nav_pinned ? 1 : 0);
2020-06-08 19:32:48 +00:00
2021-08-12 18:00:52 +00:00
ibHide.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
View dview = LayoutInflater.from(ActivityView.this).inflate(R.layout.dialog_nav_options, null);
new AlertDialog.Builder(ActivityView.this)
.setView(dview)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
prefs.edit().putBoolean("nav_options", false).apply();
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
});
// Navigation settings
2021-08-12 06:12:19 +00:00
ibSettings.setOnClickListener(new View.OnClickListener() {
2021-08-11 07:31:00 +00:00
@Override
public void onClick(View v) {
2021-08-12 07:51:19 +00:00
PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(ActivityView.this, owner, ibSettings);
2021-08-12 18:00:52 +00:00
for (int i = 0; i < FragmentOptions.PAGE_TITLES.length; i++)
popupMenu.getMenu()
.add(Menu.NONE, i, i, FragmentOptions.PAGE_TITLES[i])
.setIcon(FragmentOptions.PAGE_ICONS[i]);
2021-08-12 07:51:19 +00:00
popupMenu.insertIcons(ActivityView.this);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
2021-08-12 18:00:52 +00:00
String tab = FragmentOptions.TAB_LABELS.get(item.getOrder());
startActivity(new Intent(ActivityView.this, ActivitySetup.class)
2022-08-25 05:28:06 +00:00
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
2021-08-12 18:00:52 +00:00
.putExtra("tab", tab));
return true;
2021-08-12 07:51:19 +00:00
}
});
popupMenu.show();
2021-08-11 07:31:00 +00:00
}
});
ibSettings.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
startActivity(new Intent(ActivityView.this, ActivitySetup.class)
2022-08-25 05:28:06 +00:00
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
return true;
}
});
2021-08-13 05:37:56 +00:00
// Fetch more messages
ibFetchMore.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle args = new Bundle();
args.putLong("folder", -1L); // Unified inbox
FragmentDialogSync sync = new FragmentDialogSync();
sync.setArguments(args);
sync.show(getSupportFragmentManager(), "nav:fetch");
}
});
2021-08-13 05:37:56 +00:00
// Force sync
ibForceSync.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ServiceSynchronize.reload(ActivityView.this, null, true, "nav:sync");
2021-08-12 11:38:23 +00:00
ToastEx.makeText(ActivityView.this, R.string.title_force_sync, Toast.LENGTH_LONG).show();
}
});
2021-08-12 07:51:19 +00:00
ibExpanderNav.setVisibility(nav_options ? View.VISIBLE : View.GONE);
grpOptions.setVisibility(nav_expanded && nav_options ? View.VISIBLE : View.GONE);
vSeparatorOptions.setVisibility(nav_options ? View.VISIBLE : View.GONE);
2020-01-30 18:05:30 +00:00
2021-08-12 06:12:19 +00:00
// Accounts
LinearLayoutManager llmAccounts = new LinearLayoutManager(this);
rvAccount.setLayoutManager(llmAccounts);
2021-09-17 09:18:05 +00:00
adapterNavAccount = new AdapterNavAccountFolder(this, this);
2020-01-23 14:27:26 +00:00
rvAccount.setAdapter(adapterNavAccount);
if (nav_categories) {
LayoutInflater inflater = LayoutInflater.from(this);
DividerItemDecoration categoryDecorator = new DividerItemDecoration(this, llmAccounts.getOrientation()) {
@Override
public void onDraw(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
int count = parent.getChildCount();
for (int i = 0; i < count; i++) {
View view = parent.getChildAt(i);
int pos = parent.getChildAdapterPosition(view);
View header = getView(view, parent, pos);
if (header != null) {
canvas.save();
canvas.translate(0, parent.getChildAt(i).getTop() - header.getMeasuredHeight());
header.draw(canvas);
canvas.restore();
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int pos = parent.getChildAdapterPosition(view);
View header = getView(view, parent, pos);
if (header == null)
outRect.setEmpty();
else
outRect.top = header.getMeasuredHeight();
}
private View getView(View view, RecyclerView parent, int pos) {
if (pos == NO_POSITION)
return null;
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
return null;
TupleAccountFolder prev = adapterNavAccount.getItemAtPosition(pos - 1);
TupleAccountFolder account = adapterNavAccount.getItemAtPosition(pos);
if (pos > 0 && prev == null)
return null;
if (account == null)
return null;
if (pos > 0) {
if (Objects.equals(prev.category, account.category))
return null;
} else {
if (account.category == null)
return null;
}
View header = inflater.inflate(R.layout.item_nav_group, parent, false);
TextView tvCategory = header.findViewById(R.id.tvCategory);
tvCategory.setText(account.category);
header.measure(View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());
return header;
}
};
rvAccount.addItemDecoration(categoryDecorator);
}
2020-01-30 18:05:30 +00:00
boolean nav_account = prefs.getBoolean("nav_account", true);
2021-09-17 09:18:05 +00:00
boolean nav_folder = prefs.getBoolean("nav_folder", true);
ibExpanderAccount.setImageLevel(nav_account || nav_folder ? 0 /* less */ : 1 /* more */);
rvAccount.setVisibility(nav_account || nav_folder ? View.VISIBLE : View.GONE);
2020-01-30 18:05:30 +00:00
ibExpanderAccount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
2021-09-17 09:18:05 +00:00
boolean nav_account = prefs.getBoolean("nav_account", true);
boolean nav_folder = prefs.getBoolean("nav_folder", true);
2021-09-23 06:15:03 +00:00
boolean nav_quick = prefs.getBoolean("nav_quick", true);
boolean expanded = (nav_account || nav_folder);
if (expanded && nav_quick && adapterNavAccount.hasFolders())
nav_quick = false;
else {
expanded = !expanded;
if (expanded)
nav_quick = true;
}
2021-09-17 09:18:05 +00:00
prefs.edit()
2021-09-23 06:15:03 +00:00
.putBoolean("nav_account", expanded)
.putBoolean("nav_folder", expanded)
.putBoolean("nav_quick", nav_quick)
2021-09-17 09:18:05 +00:00
.apply();
2021-09-23 06:15:03 +00:00
adapterNavAccount.setFolders(nav_quick);
if (expanded && nav_quick && adapterNavAccount.hasFolders())
ibExpanderAccount.setImageLevel(2 /* unfold less */);
else
ibExpanderAccount.setImageLevel(expanded ? 0 /* less */ : 1 /* more */);
rvAccount.setVisibility(expanded ? View.VISIBLE : View.GONE);
2020-01-30 18:05:30 +00:00
}
});
2019-07-23 05:51:39 +00:00
// Unified system folders
2019-07-19 06:27:44 +00:00
rvUnified.setLayoutManager(new LinearLayoutManager(this));
adapterNavUnified = new AdapterNavUnified(this, this);
2020-01-23 14:27:26 +00:00
rvUnified.setAdapter(adapterNavUnified);
2019-07-19 06:27:44 +00:00
2019-12-16 19:50:25 +00:00
boolean unified_system = prefs.getBoolean("unified_system", true);
2019-09-01 16:59:51 +00:00
ibExpanderUnified.setImageLevel(unified_system ? 0 /* less */ : 1 /* more */);
2020-01-30 18:05:30 +00:00
rvUnified.setVisibility(unified_system ? View.VISIBLE : View.GONE);
2019-07-20 20:22:21 +00:00
2019-09-01 16:59:51 +00:00
ibExpanderUnified.setOnClickListener(new View.OnClickListener() {
2019-07-20 20:22:21 +00:00
@Override
public void onClick(View v) {
2019-12-16 19:50:25 +00:00
boolean unified_system = !prefs.getBoolean("unified_system", true);
2019-07-20 20:22:21 +00:00
prefs.edit().putBoolean("unified_system", unified_system).apply();
2019-09-01 16:59:51 +00:00
ibExpanderUnified.setImageLevel(unified_system ? 0 /* less */ : 1 /* more */);
2020-01-30 18:05:30 +00:00
rvUnified.setVisibility(unified_system ? View.VISIBLE : View.GONE);
2019-07-20 20:22:21 +00:00
}
});
2021-09-24 11:36:06 +00:00
// Menus
rvSearch.setLayoutManager(new LinearLayoutManager(this));
adapterNavSearch = new AdapterNavSearch(this, this, getSupportFragmentManager());
rvSearch.setAdapter(adapterNavSearch);
boolean nav_search = prefs.getBoolean("nav_search", true);
ibExpanderSearch.setImageLevel(nav_search ? 0 /* less */ : 1 /* more */);
ibExpanderSearch.setVisibility(View.GONE);
rvSearch.setVisibility(View.GONE);
vSeparatorSearch.setVisibility(View.GONE);
ibExpanderSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean nav_search = !prefs.getBoolean("nav_search", true);
prefs.edit().putBoolean("nav_search", nav_search).apply();
ibExpanderSearch.setImageLevel(nav_search ? 0 /* less */ : 1 /* more */);
rvSearch.setVisibility(nav_search ? View.VISIBLE : View.GONE);
}
});
2021-04-07 16:42:16 +00:00
// Menus
rvMenu.setLayoutManager(new LinearLayoutManager(this));
adapterNavMenu = new AdapterNavMenu(this, this);
2020-01-23 14:27:26 +00:00
rvMenu.setAdapter(adapterNavMenu);
2018-08-02 13:33:06 +00:00
2021-04-07 17:15:01 +00:00
boolean nav_menu = prefs.getBoolean("nav_menu", true);
ibExpanderMenu.setImageLevel(nav_menu ? 0 /* less */ : 1 /* more */);
rvMenu.setVisibility(nav_menu ? View.VISIBLE : View.GONE);
ibExpanderMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean nav_menu = !prefs.getBoolean("nav_menu", true);
prefs.edit().putBoolean("nav_menu", nav_menu).apply();
ibExpanderMenu.setImageLevel(nav_menu ? 0 /* less */ : 1 /* more */);
rvMenu.setVisibility(nav_menu ? View.VISIBLE : View.GONE);
}
});
2019-07-23 05:51:39 +00:00
// Extra menus
LinearLayoutManager llmMenuExtra = new LinearLayoutManager(this);
rvMenuExtra.setLayoutManager(llmMenuExtra);
adapterNavMenuExtra = new AdapterNavMenu(this, this);
2020-01-23 14:27:26 +00:00
rvMenuExtra.setAdapter(adapterNavMenuExtra);
2018-12-24 10:57:03 +00:00
2019-04-29 09:39:24 +00:00
final Drawable d = getDrawable(R.drawable.divider);
DividerItemDecoration itemDecorator = new DividerItemDecoration(this, llmMenuExtra.getOrientation()) {
2019-04-29 09:39:24 +00:00
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int pos = parent.getChildAdapterPosition(view);
2022-01-06 16:32:56 +00:00
NavMenuItem menu = (adapterNavMenuExtra == null ? null : adapterNavMenuExtra.get(pos));
2019-04-29 10:04:45 +00:00
outRect.set(0, 0, 0, menu != null && menu.isSeparated() ? d.getIntrinsicHeight() : 0);
2019-04-29 09:39:24 +00:00
}
};
itemDecorator.setDrawable(d);
rvMenuExtra.addItemDecoration(itemDecorator);
boolean minimal = prefs.getBoolean("minimal", false);
2019-09-01 16:59:51 +00:00
ibExpanderExtra.setImageLevel(minimal ? 1 /* more */ : 0 /* less */);
2019-04-29 09:39:24 +00:00
rvMenuExtra.setVisibility(minimal ? View.GONE : View.VISIBLE);
2019-09-01 16:59:51 +00:00
ibExpanderExtra.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean minimal = !prefs.getBoolean("minimal", false);
prefs.edit().putBoolean("minimal", minimal).apply();
2019-09-01 16:59:51 +00:00
ibExpanderExtra.setImageLevel(minimal ? 1 /* more */ : 0 /* less */);
2019-04-29 09:39:24 +00:00
rvMenuExtra.setVisibility(minimal ? View.GONE : View.VISIBLE);
2019-07-20 20:22:21 +00:00
if (!minimal)
2023-09-13 05:40:42 +00:00
getMainHandler().post(new RunnableEx("fullScroll") {
2019-07-20 20:22:21 +00:00
@Override
2023-09-13 05:40:42 +00:00
public void delegate() {
2019-07-20 20:22:21 +00:00
drawerContainer.fullScroll(View.FOCUS_DOWN);
}
});
2018-11-13 13:44:57 +00:00
}
});
2018-08-02 13:33:06 +00:00
getSupportFragmentManager().addOnBackStackChangedListener(this);
2022-06-16 07:38:34 +00:00
getOnBackPressedDispatcher().addCallback(this, backPressedCallback);
2022-06-12 07:22:55 +00:00
2020-01-23 14:27:26 +00:00
// Initialize
if (content_pane != null) {
content_separator.setVisibility(duo || open_pane ? View.INVISIBLE : View.GONE);
content_pane.setVisibility(duo || open_pane ? View.INVISIBLE : View.GONE);
2020-01-23 14:27:26 +00:00
}
2023-08-22 21:02:09 +00:00
FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
if (count > 1 && "thread".equals(fm.getBackStackEntryAt(count - 1).getName())) {
Fragment fragment = fm.findFragmentByTag("thread");
2023-10-23 06:23:20 +00:00
if (fragment != null) {
if (fragment.getId() == (content_pane == null ? R.id.content_pane : R.id.content_frame)) {
Log.i("Moving pane=" + (content_pane != null) + " fragment=" + fragment);
fm.popBackStack("thread", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Fragment newFragment = Helper.recreateFragment(fragment, fm);
FragmentTransaction ft = fm.beginTransaction();
ft.replace(content_pane == null ? R.id.content_frame : R.id.content_pane, newFragment, "thread")
.addToBackStack("thread");
ft.commit();
}
2023-08-22 21:02:09 +00:00
if (content_pane != null) {
content_separator.setVisibility(View.VISIBLE);
content_pane.setVisibility(View.VISIBLE);
}
}
}
if (getSupportFragmentManager().getFragments().size() == 0) {
Intent intent = getIntent();
boolean search = (intent != null && intent.hasExtra(Intent.EXTRA_PROCESS_TEXT));
boolean standalone = (intent != null && intent.getBooleanExtra("standalone", false));
2024-02-06 06:21:49 +00:00
boolean unified = (intent != null && "unified".equals(intent.getAction()));
if (!search && !(standalone && !unified))
init();
}
2020-01-23 14:27:26 +00:00
if (savedInstanceState != null)
2020-01-23 14:27:26 +00:00
drawerToggle.setDrawerIndicatorEnabled(savedInstanceState.getBoolean("fair:toggle"));
checkFirst();
2021-03-29 14:18:43 +00:00
checkBanner();
2020-01-23 14:27:26 +00:00
checkCrash();
2020-01-23 15:14:11 +00:00
Shortcuts.update(this, this);
2020-01-23 14:27:26 +00:00
}
public boolean isSplit() {
return (layoutId == R.layout.activity_view_portrait_split ||
layoutId == R.layout.activity_view_landscape_split);
}
2022-06-16 07:38:34 +00:00
@Override
public void onBackPressedFragment() {
backPressedCallback.handleOnBackPressed();
}
private OnBackPressedCallback backPressedCallback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (Helper.isKeyboardVisible(view))
Helper.hideKeyboard(view);
else
onExit();
}
};
2020-01-23 14:27:26 +00:00
private void init() {
Bundle args = new Bundle();
2024-04-13 07:53:00 +00:00
if ("inbox".equals(startup)) {
new SimpleTask<EntityFolder>() {
@Override
protected void onPreExecute(Bundle args) {
initialized = false;
}
2024-04-13 07:53:00 +00:00
@Override
protected EntityFolder onExecute(Context context, Bundle args) throws Throwable {
DB db = DB.getInstance(context);
return db.folder().getFolderPrimary(EntityFolder.INBOX);
}
@Override
protected void onExecuted(Bundle args, EntityFolder inbox) {
FragmentBase fragment = new FragmentMessages();
if (inbox != null) {
2024-04-16 10:35:27 +00:00
args.putString("type", inbox.type);
2024-04-13 07:53:00 +00:00
args.putLong("account", inbox.account);
args.putLong("folder", inbox.id);
}
fragment.setArguments(args);
setFragment(fragment);
checkIntent();
initialized = true;
2024-04-13 07:53:00 +00:00
}
@Override
protected void onException(Bundle args, Throwable ex) {
Log.unexpectedError(getSupportFragmentManager(), ex);
}
}.execute(this, new Bundle(), "primary");
return;
}
2020-01-23 14:27:26 +00:00
FragmentBase fragment;
switch (startup) {
case "accounts":
fragment = new FragmentAccounts();
args.putBoolean("settings", false);
break;
case "folders":
fragment = new FragmentFolders();
args.putBoolean("unified", true);
2020-01-23 14:27:26 +00:00
break;
2020-03-14 13:00:02 +00:00
case "primary":
fragment = new FragmentFolders();
args.putBoolean("primary", true);
2020-03-14 13:00:02 +00:00
break;
2020-01-23 14:27:26 +00:00
default:
fragment = new FragmentMessages();
}
fragment.setArguments(args);
2024-04-13 07:53:00 +00:00
setFragment(fragment);
}
2020-01-23 14:27:26 +00:00
2024-04-13 07:53:00 +00:00
private void setFragment(Fragment fragment) {
2020-01-23 14:27:26 +00:00
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
for (Fragment existing : fm.getFragments())
fragmentTransaction.remove(existing);
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("unified");
fragmentTransaction.commit();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
2021-04-04 17:29:57 +00:00
outState.putParcelable("fair:intent", getIntent());
2022-04-21 08:11:04 +00:00
outState.putBoolean("fair:toggle", drawerToggle == null || drawerToggle.isDrawerIndicatorEnabled());
2020-01-23 14:27:26 +00:00
outState.putBoolean("fair:searching", searching);
super.onSaveInstanceState(outState);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
2019-07-23 05:51:39 +00:00
// Fixed menus
final List<NavMenuItem> menus = new ArrayList<>();
2020-09-28 07:18:56 +00:00
final NavMenuItem navOperations = new NavMenuItem(R.drawable.twotone_dns_24, R.string.menu_operations, new Runnable() {
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onMenuOperations();
}
2022-03-06 13:05:33 +00:00
});
2019-07-09 16:31:36 +00:00
menus.add(navOperations);
2020-09-28 15:15:04 +00:00
menus.add(new NavMenuItem(R.drawable.twotone_list_alt_24, R.string.title_log, new Runnable() {
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onShowLog();
}
2019-07-09 16:31:36 +00:00
}));
2021-05-07 09:14:20 +00:00
menus.add(new NavMenuItem(R.drawable.twotone_text_snippet_24, R.string.menu_answers, new Runnable() {
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onMenuAnswers();
}
}));
2019-03-18 13:35:45 +00:00
2022-04-08 10:34:34 +00:00
menus.add(new NavMenuItem(R.drawable.twotone_filter_alt_24, R.string.menu_rules, new Runnable() {
2022-03-25 09:48:49 +00:00
@Override
public void run() {
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onMenuRulesAccount();
}
}));
2020-09-28 07:18:56 +00:00
menus.add(new NavMenuItem(R.drawable.twotone_settings_24, R.string.menu_setup, new Runnable() {
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onMenuSetup();
}
2022-04-17 12:29:48 +00:00
}, new Callable<Boolean>() {
2021-10-02 06:13:12 +00:00
@Override
2022-04-17 12:29:48 +00:00
public Boolean call() {
2021-10-05 16:13:37 +00:00
if (BuildConfig.DEBUG)
try {
DnsBlockList.clearCache();
ContactInfo.clearCache(ActivityView.this);
2021-10-05 16:13:37 +00:00
ToastEx.makeText(ActivityView.this, R.string.title_completed, Toast.LENGTH_LONG).show();
} catch (Throwable ex) {
Log.unexpectedError(getSupportFragmentManager(), ex);
}
2022-04-17 12:29:48 +00:00
return BuildConfig.DEBUG;
2021-10-02 06:13:12 +00:00
}
}));
2019-03-19 07:01:26 +00:00
2021-08-11 16:37:41 +00:00
adapterNavMenu.set(menus, nav_expanded);
2019-07-23 05:51:39 +00:00
// Collapsible menus
2019-04-29 09:39:24 +00:00
List<NavMenuItem> extra = new ArrayList<>();
2018-08-14 15:57:32 +00:00
2020-09-28 07:18:56 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_help_24, R.string.menu_legend, new Runnable() {
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onMenuLegend();
}
}));
2021-02-10 19:18:14 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_support_24, R.string.menu_faq, new Runnable() {
2019-08-15 05:58:20 +00:00
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
2019-08-15 05:58:20 +00:00
onMenuFAQ();
}
2022-04-17 12:29:48 +00:00
}, new Callable<Boolean>() {
2019-08-15 05:58:20 +00:00
@Override
2022-04-17 12:29:48 +00:00
public Boolean call() {
2023-12-16 12:16:25 +00:00
if (DebugHelper.isAvailable()) {
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onDebugInfo();
return true;
} else
return false;
2019-08-15 05:58:20 +00:00
}
}).setExternal(true));
2020-09-28 07:18:56 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_feedback_24, R.string.menu_issue, new Runnable() {
2020-01-17 10:05:35 +00:00
@Override
public void run() {
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
2020-08-14 06:17:07 +00:00
onMenuIssue();
2020-01-17 10:05:35 +00:00
}
2022-04-17 12:29:48 +00:00
}, new Callable<Boolean>() {
2022-04-17 12:26:38 +00:00
@Override
2022-04-17 12:29:48 +00:00
public Boolean call() {
2022-04-18 06:48:57 +00:00
CoalMine.check();
2022-05-01 11:15:15 +00:00
return BuildConfig.DEBUG;
2022-04-17 12:26:38 +00:00
}
2020-01-17 10:05:35 +00:00
}).setExternal(true));
2020-09-28 07:18:56 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_language_24, R.string.menu_translate, new Runnable() {
2020-06-14 16:34:13 +00:00
@Override
public void run() {
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
2020-08-14 06:17:07 +00:00
onMenuTranslate();
2020-06-14 16:34:13 +00:00
}
}).setExternal(true));
2020-01-16 10:37:27 +00:00
if (Helper.isPlayStoreInstall() && false)
2020-09-28 07:18:56 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_bug_report_24, R.string.menu_test, new Runnable() {
2019-09-30 10:38:24 +00:00
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
2019-09-30 10:38:24 +00:00
onMenuTest();
}
}).setExternal(true));
2021-05-15 15:08:24 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_account_circle_24, R.string.menu_privacy, new Runnable() {
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onMenuPrivacy();
}
2021-06-29 15:49:04 +00:00
}).setExternal(true));
2018-08-13 06:59:05 +00:00
2020-09-28 07:18:56 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_info_24, R.string.menu_about, new Runnable() {
@Override
public void run() {
onMenuAbout();
}
2022-04-17 12:29:48 +00:00
}, new Callable<Boolean>() {
@Override
2022-04-17 12:29:48 +00:00
public Boolean call() {
boolean play = Helper.isPlayStoreInstall();
if (!play) {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
checkUpdate(true);
2023-01-08 11:29:30 +00:00
checkAnnouncements(true);
}
2022-04-17 12:29:48 +00:00
return !play;
}
2021-02-20 13:41:06 +00:00
}).setSeparated().setSubtitle(BuildConfig.VERSION_NAME));
2019-01-14 13:33:16 +00:00
2020-09-28 07:18:56 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_monetization_on_24, R.string.menu_pro, new Runnable() {
2019-08-13 08:27:17 +00:00
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
2019-08-13 08:27:17 +00:00
startActivity(new Intent(ActivityView.this, ActivityBilling.class));
}
2021-07-28 11:52:20 +00:00
}).setExtraIcon(ActivityBilling.isPro(this) ? R.drawable.twotone_check_24 : 0));
2020-06-14 16:34:13 +00:00
if ((Helper.isPlayStoreInstall() || BuildConfig.DEBUG))
2020-09-28 07:18:56 +00:00
extra.add(new NavMenuItem(R.drawable.twotone_star_24, R.string.menu_rate, new Runnable() {
@Override
public void run() {
2020-01-03 10:32:50 +00:00
if (!drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
onMenuRate();
}
2019-08-13 09:33:12 +00:00
}).setExternal(true));
2021-08-11 16:37:41 +00:00
adapterNavMenuExtra.set(extra, nav_expanded);
2019-01-14 19:52:01 +00:00
2019-07-23 05:51:39 +00:00
// Live data
DB db = DB.getInstance(this);
2022-03-06 13:05:33 +00:00
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
2018-10-10 13:45:50 +00:00
db.account().liveAccountFolder(false).observe(owner, new Observer<List<TupleAccountFolder>>() {
@Override
2021-09-17 09:18:05 +00:00
public void onChanged(@Nullable List<TupleAccountFolder> accounts) {
if (accounts == null)
accounts = new ArrayList<>();
2021-09-23 06:15:03 +00:00
boolean nav_account = prefs.getBoolean("nav_account", true);
boolean nav_folder = prefs.getBoolean("nav_folder", true);
boolean nav_quick = prefs.getBoolean("nav_quick", true);
boolean expanded = (nav_account || nav_folder);
adapterNavAccount.set(accounts, nav_expanded, nav_quick);
if (expanded && nav_quick && adapterNavAccount.hasFolders())
ibExpanderAccount.setImageLevel(2 /* unfold less */);
else
ibExpanderAccount.setImageLevel(expanded ? 0 /* less */ : 1 /* more */);
}
});
2018-09-07 11:08:20 +00:00
2020-04-23 10:38:18 +00:00
db.folder().liveUnified().observe(owner, new Observer<List<TupleFolderUnified>>() {
@Override
public void onChanged(List<TupleFolderUnified> folders) {
if (folders == null)
folders = new ArrayList<>();
2021-08-11 16:37:41 +00:00
adapterNavUnified.set(folders, nav_expanded);
}
});
2019-07-19 06:27:44 +00:00
2022-11-26 18:44:58 +00:00
db.search().liveSearches().observe(owner, new Observer<List<EntitySearch>>() {
2021-09-24 11:36:06 +00:00
@Override
2022-11-26 18:44:58 +00:00
public void onChanged(List<EntitySearch> searches) {
if (searches == null)
searches = new ArrayList<>();
adapterNavSearch.set(searches, nav_expanded);
2021-09-24 11:36:06 +00:00
boolean nav_search = prefs.getBoolean("nav_search", true);
2022-11-26 18:44:58 +00:00
ibExpanderSearch.setVisibility(searches.size() > 0 ? View.VISIBLE : View.GONE);
rvSearch.setVisibility(searches.size() > 0 && nav_search ? View.VISIBLE : View.GONE);
vSeparatorSearch.setVisibility(searches.size() > 0 ? View.VISIBLE : View.GONE);
2021-09-24 11:36:06 +00:00
}
});
2020-04-23 10:38:18 +00:00
db.operation().liveStats().observe(owner, new Observer<TupleOperationStats>() {
2022-03-06 11:20:47 +00:00
private Boolean lastWarning = null;
private Integer lastCount = null;
@Override
2019-05-04 20:38:11 +00:00
public void onChanged(TupleOperationStats stats) {
2022-03-06 11:20:47 +00:00
boolean warning = (stats != null && stats.errors != null && stats.errors > 0);
int count = (stats == null ? 0 : stats.pending);
if (Objects.equals(lastWarning, warning) && Objects.equals(lastCount, count))
return;
lastWarning = warning;
lastCount = count;
navOperations.setWarning(warning);
navOperations.setCount(count);
2022-03-06 06:59:58 +00:00
int pos = adapterNavMenu.getPosition(navOperations);
if (pos < 0)
adapterNavMenu.notifyDataSetChanged();
else
adapterNavMenu.notifyItemChanged(pos);
}
});
2020-04-23 19:45:59 +00:00
Log.i("Drawer start");
owner.start();
2021-08-11 16:37:41 +00:00
setupDrawer();
2020-04-23 19:45:59 +00:00
drawerToggle.syncState();
2018-08-02 13:33:06 +00:00
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
2018-10-16 10:20:31 +00:00
setIntent(intent);
2018-08-02 13:33:06 +00:00
}
2022-05-10 09:11:37 +00:00
@Override
protected void onStart() {
super.onStart();
2023-08-10 17:54:42 +00:00
if (!Helper.isPlayStoreInstall())
2022-12-06 15:51:04 +00:00
infoTracker.addWindowLayoutInfoListener(this, Runnable::run, layoutStateChangeCallback);
2022-05-10 09:11:37 +00:00
}
@Override
protected void onStop() {
super.onStop();
2023-08-10 17:54:42 +00:00
if (!Helper.isPlayStoreInstall())
2022-12-06 15:51:04 +00:00
infoTracker.removeWindowLayoutInfoListener(layoutStateChangeCallback);
2022-05-10 09:11:37 +00:00
}
2018-08-02 13:33:06 +00:00
@Override
protected void onResume() {
super.onResume();
2018-08-05 11:40:15 +00:00
2018-08-02 13:33:06 +00:00
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
IntentFilter iff = new IntentFilter();
iff.addAction(ACTION_VIEW_FOLDERS);
2018-08-02 13:33:06 +00:00
iff.addAction(ACTION_VIEW_MESSAGES);
2022-11-28 18:26:37 +00:00
iff.addAction(ACTION_SEARCH_ADDRESS);
2018-10-15 10:05:42 +00:00
iff.addAction(ACTION_VIEW_THREAD);
2018-08-02 13:33:06 +00:00
iff.addAction(ACTION_EDIT_FOLDER);
2021-03-31 16:28:00 +00:00
iff.addAction(ACTION_VIEW_OUTBOX);
2019-01-18 08:28:07 +00:00
iff.addAction(ACTION_EDIT_ANSWERS);
2018-08-27 09:39:27 +00:00
iff.addAction(ACTION_EDIT_ANSWER);
2019-01-18 08:23:53 +00:00
iff.addAction(ACTION_EDIT_RULES);
2019-01-17 13:29:35 +00:00
iff.addAction(ACTION_EDIT_RULE);
2018-08-02 13:33:06 +00:00
lbm.registerReceiver(receiver, iff);
2018-10-16 10:20:31 +00:00
2022-03-30 18:14:54 +00:00
boolean open = drawerLayout.isDrawerOpen(drawerContainer);
Log.i("Drawer resume open=" + open);
if (open)
owner.start();
checkUpdate(false);
2023-01-08 11:29:30 +00:00
checkAnnouncements(false);
if (initialized || !"inbox".equals(startup))
checkIntent();
2018-08-02 13:33:06 +00:00
}
@Override
protected void onPause() {
super.onPause();
2018-08-02 13:33:06 +00:00
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
lbm.unregisterReceiver(receiver);
2022-03-30 18:14:54 +00:00
Log.i("Drawer pause");
owner.stop();
2018-08-02 13:33:06 +00:00
}
2020-05-05 16:12:33 +00:00
@Override
protected void onDestroy() {
2020-05-05 17:20:39 +00:00
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
lbm.unregisterReceiver(creceiver);
2020-05-05 16:12:33 +00:00
super.onDestroy();
2022-05-24 07:34:36 +00:00
infoTracker = null;
2020-05-05 16:12:33 +00:00
}
2022-03-25 09:48:49 +00:00
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
switch (requestCode) {
case REQUEST_RULES_ACCOUNT:
if (resultCode == RESULT_OK && data != null)
onMenuRulesFolder(data.getBundleExtra("args"));
break;
case REQUEST_RULES_FOLDER:
if (resultCode == RESULT_OK && data != null)
onMenuRules(data.getBundleExtra("args"));
break;
2023-06-18 06:38:22 +00:00
case REQUEST_DEBUG_INFO:
if (resultCode == RESULT_OK && data != null)
onDebugInfo(data.getBundleExtra("args"));
break;
2022-03-25 09:48:49 +00:00
}
} catch (Throwable ex) {
Log.e(ex);
}
}
2018-08-02 13:33:06 +00:00
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
2021-08-11 16:37:41 +00:00
nav_pinned = getDrawerPinned();
setupDrawer();
2018-08-02 13:33:06 +00:00
drawerToggle.onConfigurationChanged(newConfig);
}
2021-08-12 07:51:19 +00:00
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
super.onSharedPreferenceChanged(prefs, key);
if ("nav_options".equals(key)) {
nav_options = prefs.getBoolean(key, true);
ibExpanderNav.setVisibility(nav_options ? View.VISIBLE : View.GONE);
grpOptions.setVisibility(nav_expanded && nav_options ? View.VISIBLE : View.GONE);
vSeparatorOptions.setVisibility(nav_options ? View.VISIBLE : View.GONE);
}
}
2021-08-11 16:37:41 +00:00
private void setupDrawer() {
if (nav_pinned) {
drawerLayout.setScrimColor(Color.TRANSPARENT);
drawerLayout.openDrawer(drawerContainer, false);
drawerToggle.onDrawerOpened(drawerContainer);
} else {
drawerLayout.setScrimColor(colorDrawerScrim);
drawerLayout.closeDrawer(drawerContainer, false);
drawerToggle.onDrawerClosed(drawerContainer);
}
}
private boolean getDrawerExpanded() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean legacy = prefs.getBoolean("nav_expanded", true);
return prefs.getBoolean("nav_expanded_" + getOrientation(), legacy);
}
private void setDrawerExpanded(boolean value) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit()
.remove("nav_expanded") // legacy
.putBoolean("nav_expanded_" + getOrientation(), value)
.apply();
2021-08-12 16:08:56 +00:00
ViewGroup.LayoutParams lparam = drawerContainer.getLayoutParams();
lparam.width = getDrawerWidth();
drawerContainer.setLayoutParams(lparam);
ViewGroup childContent = (ViewGroup) drawerLayout.getChildAt(0);
ViewGroup childDrawer = (ViewGroup) drawerLayout.getChildAt(1);
int padding = (nav_pinned ? childDrawer.getLayoutParams().width : 0);
childContent.setPaddingRelative(padding, 0, 0, 0);
grpOptions.setVisibility(nav_expanded ? View.VISIBLE : View.GONE);
ibExpanderNav.setImageLevel(nav_expanded ? 0 : 1);
adapterNavAccount.setExpanded(nav_expanded);
adapterNavUnified.setExpanded(nav_expanded);
adapterNavMenu.setExpanded(nav_expanded);
adapterNavMenuExtra.setExpanded(nav_expanded);
}
2021-08-11 16:37:41 +00:00
private boolean getDrawerPinned() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getResources().getConfiguration();
boolean legacy;
if (config.orientation == ORIENTATION_PORTRAIT)
legacy = prefs.getBoolean("portrait3", false);
else
legacy = prefs.getBoolean("landscape3", true);
return prefs.getBoolean("nav_pinned_" + getOrientation(), legacy);
}
private void setDrawerPinned(boolean value) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit()
.remove("portrait3") // legacy
.remove("landscape3") // legacy
.putBoolean("nav_pinned_" + getOrientation(), value)
.apply();
2021-08-12 16:08:56 +00:00
drawerLayout.setDrawerLockMode(nav_pinned ? LOCK_MODE_LOCKED_OPEN : LOCK_MODE_UNLOCKED);
drawerLayout.setScrimColor(nav_pinned ? Color.TRANSPARENT : colorDrawerScrim);
drawerLayout.openDrawer(drawerContainer, false);
ViewGroup.LayoutParams lparam = drawerContainer.getLayoutParams();
lparam.width = getDrawerWidth();
drawerContainer.setLayoutParams(lparam);
ViewGroup childContent = (ViewGroup) drawerLayout.getChildAt(0);
ViewGroup childDrawer = (ViewGroup) drawerLayout.getChildAt(1);
int padding = (nav_pinned ? childDrawer.getLayoutParams().width : 0);
childContent.setPaddingRelative(padding, 0, 0, 0);
ibPin.setImageLevel(nav_pinned ? 1 : 0);
}
private String getOrientation() {
Configuration config = getResources().getConfiguration();
return (config.orientation == ORIENTATION_PORTRAIT ? "portrait" : "landscape");
2021-08-11 16:37:41 +00:00
}
private int getDrawerWidth() {
if (!nav_expanded)
2021-08-12 16:08:56 +00:00
return Helper.dp2pixels(this, 48); // one icon + padding
if (nav_pinned)
return getDrawerWidthPinned();
else {
2021-12-30 14:33:09 +00:00
int actionBarHeight = Helper.getActionBarHeight(this);
2021-08-12 16:08:56 +00:00
DisplayMetrics dm = getResources().getDisplayMetrics();
2021-08-11 16:37:41 +00:00
int screenWidth = Math.min(dm.widthPixels, dm.heightPixels);
2021-08-12 19:25:59 +00:00
// Screen width 320 - action bar 56 = 264 dp
// Icons 6 x (24 width + 2x6 padding) = 216 dp
int drawerWidth = screenWidth - actionBarHeight;
2021-08-11 16:37:41 +00:00
int dp320 = Helper.dp2pixels(this, 320);
2021-08-12 19:25:59 +00:00
return Math.min(drawerWidth, dp320);
2021-08-11 16:37:41 +00:00
}
}
2021-08-12 16:08:56 +00:00
private int getDrawerWidthPinned() {
int dp300 = Helper.dp2pixels(this, 300);
DisplayMetrics dm = getResources().getDisplayMetrics();
int maxWidth = dm.widthPixels - dp300;
return Math.min(dp300, maxWidth);
}
private boolean canExpandAndPin() {
int dp200 = Helper.dp2pixels(this, 200);
return (getDrawerWidthPinned() >= dp200);
}
2022-06-12 07:22:55 +00:00
private void onExit() {
2020-01-03 10:32:50 +00:00
int count = getSupportFragmentManager().getBackStackEntryCount();
2021-08-11 16:37:41 +00:00
if (!nav_pinned &&
2021-08-11 10:41:33 +00:00
drawerLayout.isDrawerOpen(drawerContainer) &&
2020-01-03 16:33:17 +00:00
(!drawerLayout.isLocked(drawerContainer) || count == 1))
2019-04-28 18:48:45 +00:00
drawerLayout.closeDrawer(drawerContainer);
2019-06-12 16:56:38 +00:00
else {
if (exit || count > 1)
2022-06-12 07:22:55 +00:00
performBack();
else {
2020-10-09 16:31:40 +00:00
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ActivityView.this);
2021-03-25 16:08:25 +00:00
boolean double_back = prefs.getBoolean("double_back", false);
Intent intent = getIntent();
boolean standalone = (intent != null && intent.getBooleanExtra("standalone", false));
if (searching || !double_back || standalone)
2022-06-12 07:22:55 +00:00
performBack();
2019-07-02 07:05:29 +00:00
else {
exit = true;
2022-06-12 07:22:55 +00:00
ToastEx.makeText(ActivityView.this, R.string.app_exit, Toast.LENGTH_SHORT).show();
2020-08-23 15:34:14 +00:00
getMainHandler().postDelayed(new Runnable() {
2019-07-02 07:05:29 +00:00
@Override
public void run() {
exit = false;
}
}, EXIT_DELAY);
}
2019-06-12 16:56:38 +00:00
}
}
2018-08-02 13:33:06 +00:00
}
@Override
2018-08-05 11:40:15 +00:00
public void onBackStackChanged() {
2022-04-28 15:44:33 +00:00
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
return;
2018-08-06 14:40:21 +00:00
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count == 0)
2018-08-05 11:40:15 +00:00
finish();
else {
2023-01-07 10:26:19 +00:00
showActionBar(true);
2021-04-04 17:29:57 +00:00
if (count < lastBackStackCount) {
Intent intent = getIntent();
intent.setAction(null);
Log.i("Reset intent");
}
lastBackStackCount = count;
2020-01-03 10:32:50 +00:00
if (drawerLayout.isDrawerOpen(drawerContainer) &&
!drawerLayout.isLocked(drawerContainer))
2019-04-28 18:48:45 +00:00
drawerLayout.closeDrawer(drawerContainer);
drawerToggle.setDrawerIndicatorEnabled(count == 1);
if (content_pane != null) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean close_pane = prefs.getBoolean("close_pane", !Helper.isSurfaceDuo());
boolean thread = "thread".equals(getSupportFragmentManager().getBackStackEntryAt(count - 1).getName());
2018-11-09 16:16:41 +00:00
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content_pane);
int visibility = (!thread || fragment == null ? (close_pane ? View.GONE : View.INVISIBLE) : View.VISIBLE);
2021-01-25 18:05:58 +00:00
content_separator.setVisibility(visibility);
content_pane.setVisibility(visibility);
2018-11-09 16:16:41 +00:00
}
}
2018-08-02 13:33:06 +00:00
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
2020-01-03 10:32:50 +00:00
if (drawerToggle.onOptionsItemSelected(item)) {
2021-08-12 20:00:00 +00:00
if (nav_pinned)
2022-06-12 07:22:55 +00:00
onExit();
2021-08-12 20:00:00 +00:00
else {
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count == 1 && drawerLayout.isLocked(drawerContainer))
drawerLayout.closeDrawer(drawerContainer);
}
2018-08-02 13:33:06 +00:00
return true;
2020-01-03 10:32:50 +00:00
}
2018-08-02 13:33:06 +00:00
2019-10-04 14:57:40 +00:00
return super.onOptionsItemSelected(item);
2018-08-02 13:33:06 +00:00
}
2021-03-28 17:56:35 +00:00
public void undo(String title, final Bundle args, final SimpleTask<Void> move, final SimpleTask<Void> show) {
2020-07-25 19:11:06 +00:00
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int undo_timeout = prefs.getInt("undo_timeout", 5000);
2021-03-29 07:41:33 +00:00
if (undo_timeout == 0) {
2022-04-16 06:03:29 +00:00
if (move != null) {
2021-03-29 07:41:33 +00:00
move.execute(this, args, "undo:move");
2022-04-16 06:03:29 +00:00
show.cancel(this);
}
2021-03-29 07:41:33 +00:00
} else
2021-03-28 17:56:35 +00:00
undo(undo_timeout, title, args, move, show);
2021-03-27 20:35:31 +00:00
}
2020-07-25 19:11:06 +00:00
2021-12-30 07:02:11 +00:00
private void undo(long undo_timeout, String title, final Bundle args, final SimpleTask move, final SimpleTask show) {
2020-07-25 19:11:06 +00:00
if (drawerLayout == null || drawerLayout.getChildCount() == 0) {
Log.e("Undo: drawer missing");
2022-04-16 06:03:29 +00:00
if (show != null) {
2021-03-28 17:56:35 +00:00
show.execute(this, args, "undo:show");
2022-04-16 06:03:29 +00:00
move.cancel(this);
}
2020-07-25 19:11:06 +00:00
return;
}
final View content = drawerLayout.getChildAt(0);
final Snackbar snackbar = Snackbar.make(content, title, Snackbar.LENGTH_INDEFINITE)
.setGestureInsetBottomIgnored(true);
2023-07-20 20:16:16 +00:00
Helper.setSnackbarLines(snackbar, 7);
2020-12-09 08:35:22 +00:00
2020-07-25 19:28:26 +00:00
lastSnackbar = snackbar;
2020-12-15 08:22:56 +00:00
final Runnable timeout = new Runnable() {
@Override
public void run() {
Log.i("Undo timeout");
snackbar.dismiss();
2022-04-16 06:03:29 +00:00
if (move != null) {
2021-03-28 17:56:35 +00:00
move.execute(ActivityView.this, args, "undo:move");
2022-04-16 06:03:29 +00:00
show.cancel(ActivityView.this);
}
2020-12-15 08:22:56 +00:00
}
};
2020-07-25 19:11:06 +00:00
snackbar.setAction(R.string.title_undo, new View.OnClickListener() {
@Override
public void onClick(View v) {
2020-07-25 19:28:26 +00:00
Log.i("Undo cancel");
2022-01-14 18:07:57 +00:00
content.removeCallbacks(timeout);
2020-07-25 19:28:26 +00:00
snackbar.dismiss();
2022-04-16 06:03:29 +00:00
if (show != null) {
2021-03-28 17:56:35 +00:00
show.execute(ActivityView.this, args, "undo:show");
2022-04-16 06:03:29 +00:00
move.cancel(ActivityView.this);
}
2020-07-25 19:11:06 +00:00
}
});
snackbar.addCallback(new Snackbar.Callback() {
@Override
public void onShown(Snackbar sb) {
ViewGroup.MarginLayoutParams lparam = (ViewGroup.MarginLayoutParams) content.getLayoutParams();
2022-01-14 18:07:57 +00:00
lparam.bottomMargin = snackbar.getView().getHeight();
2020-07-25 19:11:06 +00:00
content.setLayoutParams(lparam);
}
@Override
public void onDismissed(Snackbar transientBottomBar, int event) {
ViewGroup.MarginLayoutParams lparam = (ViewGroup.MarginLayoutParams) content.getLayoutParams();
2022-01-14 18:07:57 +00:00
lparam.bottomMargin = 0;
2020-07-25 19:11:06 +00:00
content.setLayoutParams(lparam);
}
});
2020-12-15 06:59:36 +00:00
2020-07-25 19:11:06 +00:00
snackbar.show();
2022-01-14 18:07:57 +00:00
content.postDelayed(timeout, undo_timeout);
2020-06-21 07:14:52 +00:00
}
private void checkFirst() {
2021-09-18 09:49:01 +00:00
String version = BuildConfig.VERSION_NAME + BuildConfig.REVISION;
2021-09-17 18:41:48 +00:00
2019-06-30 09:35:03 +00:00
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean first = prefs.getBoolean("first", true);
boolean show_changelog = prefs.getBoolean("show_changelog", !BuildConfig.PLAY_STORE_RELEASE);
if (first)
2019-06-30 17:56:23 +00:00
new FragmentDialogFirst().show(getSupportFragmentManager(), "first");
else if (show_changelog) {
2021-11-05 18:12:51 +00:00
// checkFirst: onCreate
// checkIntent: onResume
Intent intent = getIntent();
String action = (intent == null ? null : intent.getAction());
if (action != null &&
2022-07-10 20:21:25 +00:00
(action.startsWith("thread") || action.startsWith("widget")))
2021-11-05 18:12:51 +00:00
return;
2021-09-17 18:41:48 +00:00
String last = prefs.getString("changelog", null);
if (!Objects.equals(version, last) || BuildConfig.DEBUG) {
2021-09-17 17:57:10 +00:00
Bundle args = new Bundle();
args.putString("name", "CHANGELOG.md");
FragmentDialogMarkdown fragment = new FragmentDialogMarkdown();
fragment.setArguments(args);
fragment.show(getSupportFragmentManager(), "changelog");
}
}
2021-09-17 18:41:48 +00:00
2021-09-18 09:49:01 +00:00
prefs.edit().putString("changelog", version).apply();
}
2021-03-29 14:18:43 +00:00
private void checkBanner() {
long now = new Date().getTime();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
long banner_hidden = prefs.getLong("banner_hidden", 0);
if (banner_hidden > 0 && now > banner_hidden)
prefs.edit().remove("banner_hidden").apply();
}
private void checkCrash() {
new SimpleTask<Long>() {
@Override
2018-12-31 07:03:48 +00:00
protected Long onExecute(Context context, Bundle args) throws Throwable {
2023-12-15 11:36:20 +00:00
File file = new File(context.getFilesDir(), DebugHelper.CRASH_LOG_NAME);
if (file.exists()) {
StringBuilder sb = new StringBuilder();
try {
2019-02-22 15:59:23 +00:00
String line;
try (BufferedReader in = new BufferedReader(new FileReader(file))) {
2018-12-24 10:47:21 +00:00
while ((line = in.readLine()) != null)
sb.append(line).append("\r\n");
2018-12-05 12:59:35 +00:00
}
2023-12-15 11:36:20 +00:00
EntityMessage m = DebugHelper.getDebugInfo(context,
"crash", R.string.title_crash_info_remark, null, sb.toString(), null);
return (m == null ? null : m.id);
} finally {
2023-11-16 10:10:34 +00:00
Helper.secureDelete(file);
}
}
return null;
}
@Override
2018-12-31 07:03:48 +00:00
protected void onExecuted(Bundle args, Long id) {
2023-12-15 11:36:20 +00:00
if (id == null)
return;
startActivity(
new Intent(ActivityView.this, ActivityCompose.class)
.putExtra("action", "edit")
.putExtra("id", id));
}
2018-12-01 09:47:08 +00:00
@Override
protected void onException(Bundle args, Throwable ex) {
2019-07-13 06:58:56 +00:00
ToastEx.makeText(ActivityView.this,
2019-12-06 07:50:46 +00:00
Log.formatThrowable(ex, false), Toast.LENGTH_LONG).show();
2018-12-01 09:47:08 +00:00
}
2023-12-15 11:36:20 +00:00
}.execute(this, new Bundle(), DebugHelper.CRASH_LOG_NAME);
}
private void checkUpdate(boolean always) {
if (Helper.isPlayStoreInstall())
return;
if (!Helper.hasValidFingerprint(this) && !(always && BuildConfig.DEBUG))
return;
long now = new Date().getTime();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean updates = prefs.getBoolean("updates", true);
boolean beta = prefs.getBoolean("beta", false) && false;
boolean weekly = prefs.getBoolean("weekly", Helper.hasPlayStore(this));
long last_update_check = prefs.getLong("last_update_check", 0);
if (!always && !updates)
return;
if (!always && last_update_check + (weekly ? UPDATE_WEEKLY : UPDATE_DAILY) > now)
return;
prefs.edit().putLong("last_update_check", now).apply();
Bundle args = new Bundle();
args.putBoolean("always", always);
args.putBoolean("beta", beta);
new SimpleTask<UpdateInfo>() {
@Override
protected UpdateInfo onExecute(Context context, Bundle args) throws Throwable {
boolean beta = args.getBoolean("beta");
2024-01-01 20:18:05 +00:00
if (BuildConfig.DEBUG)
DnsHelper.test(context);
StringBuilder response = new StringBuilder();
HttpsURLConnection urlConnection = null;
try {
URL latest = new URL(beta ? BuildConfig.BITBUCKET_DOWNLOADS_API : BuildConfig.GITHUB_LATEST_API);
urlConnection = (HttpsURLConnection) latest.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(UPDATE_TIMEOUT);
urlConnection.setConnectTimeout(UPDATE_TIMEOUT);
urlConnection.setDoOutput(false);
ConnectionHelper.setUserAgent(context, urlConnection);
urlConnection.connect();
int status = urlConnection.getResponseCode();
InputStream inputStream = (status == HttpsURLConnection.HTTP_OK
? urlConnection.getInputStream() : urlConnection.getErrorStream());
if (inputStream != null) {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = br.readLine()) != null)
response.append(line);
}
if (status == HttpsURLConnection.HTTP_FORBIDDEN) {
// {"message":"API rate limit exceeded for ...","documentation_url":"https://developer.github.com/v3/#rate-limiting"}
JSONObject jmessage = new JSONObject(response.toString());
if (jmessage.has("message"))
throw new IllegalArgumentException(jmessage.getString("message"));
throw new IOException("HTTP " + status + ": " + response);
}
2024-01-06 08:00:20 +00:00
if (status == HttpsURLConnection.HTTP_BAD_GATEWAY)
throw new IOException("HTTP " + status);
if (status != HttpsURLConnection.HTTP_OK)
throw new IOException("HTTP " + status + ": " + response);
JSONObject jroot = new JSONObject(response.toString());
if (beta) {
if (!jroot.has("values"))
throw new IOException("values field missing");
JSONArray jvalues = jroot.getJSONArray("values");
for (int i = 0; i < jvalues.length(); i++) {
JSONObject jitem = jvalues.getJSONObject(i);
if (!jitem.has("links"))
continue;
JSONObject jlinks = jitem.getJSONObject("links");
if (!jlinks.has("self"))
continue;
JSONObject jself = jlinks.getJSONObject("self");
if (!jself.has("href"))
continue;
// .../FairEmail-v1.1995a-play-preview-release.apk
String link = jself.getString("href");
if (!link.endsWith(".apk"))
continue;
int slash = link.lastIndexOf('/');
if (slash < 0)
continue;
String[] c = link.substring(slash + 1).split("-");
if (c.length < 4 ||
!"FairEmail".equals(c[0]) ||
c[1].length() < 8 ||
!"github".equals(c[2]) ||
!"update".equals(c[3]))
continue;
// v1.1995a
Integer version = Helper.parseInt(c[1].substring(3, c[1].length() - 1));
if (version == null)
continue;
char revision = c[1].charAt(c[1].length() - 1);
int v = BuildConfig.VERSION_CODE;
char r = BuildConfig.REVISION.charAt(0);
if (BuildConfig.DEBUG || version > v || (version == v && revision > r)) {
UpdateInfo info = new UpdateInfo();
info.tag_name = c[1];
info.html_url = BuildConfig.BITBUCKET_DOWNLOADS_URI;
info.download_url = link;
return info;
}
}
} else {
if (!jroot.has("tag_name") || jroot.isNull("tag_name"))
throw new IOException("tag_name field missing");
if (!jroot.has("assets") || jroot.isNull("assets"))
throw new IOException("assets section missing");
// Get update info
UpdateInfo info = new UpdateInfo();
info.tag_name = jroot.getString("tag_name");
info.html_url = BuildConfig.GITHUB_LATEST_URI;
// Check if new release
JSONArray jassets = jroot.getJSONArray("assets");
for (int i = 0; i < jassets.length(); i++) {
JSONObject jasset = jassets.getJSONObject(i);
if (jasset.has("name") && !jasset.isNull("name")) {
String name = jasset.getString("name");
if (name.endsWith(".apk") && name.contains("github")) {
info.download_url = jasset.optString("browser_download_url");
Log.i("Latest version=" + info.tag_name);
if (BuildConfig.DEBUG)
return info;
try {
if (Double.parseDouble(info.tag_name) <=
Double.parseDouble(BuildConfig.VERSION_NAME))
return null;
else
return info;
} catch (Throwable ex) {
Log.e(ex);
if (BuildConfig.VERSION_NAME.equals(info.tag_name))
return null;
else
return info;
}
}
}
}
}
return null;
} finally {
if (urlConnection != null)
urlConnection.disconnect();
}
}
@Override
protected void onExecuted(Bundle args, UpdateInfo info) {
boolean always = args.getBoolean("always");
if (info == null) {
if (always)
ToastEx.makeText(ActivityView.this, R.string.title_no_update, Toast.LENGTH_LONG).show();
return;
}
NotificationCompat.Builder builder =
new NotificationCompat.Builder(ActivityView.this, "update")
.setSmallIcon(R.drawable.baseline_get_app_white_24)
.setContentTitle(getString(R.string.title_updated, info.tag_name))
.setContentText(info.html_url)
.setAutoCancel(true)
.setShowWhen(false)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setCategory(NotificationCompat.CATEGORY_REMINDER)
.setVisibility(NotificationCompat.VISIBILITY_SECRET);
Intent update = new Intent(Intent.ACTION_VIEW, Uri.parse(info.html_url))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent piUpdate = PendingIntentCompat.getActivity(
ActivityView.this, PI_UPDATE, update, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(piUpdate);
Intent manage = new Intent(ActivityView.this, ActivitySetup.class)
.setAction("misc")
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
.putExtra("tab", "misc");
PendingIntent piManage = PendingIntentCompat.getActivity(
ActivityView.this, ActivitySetup.PI_MISC, manage, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder actionManage = new NotificationCompat.Action.Builder(
R.drawable.twotone_settings_24,
getString(R.string.title_setup_manage),
piManage);
builder.addAction(actionManage.build());
if (!TextUtils.isEmpty(info.download_url)) {
Intent download = new Intent(Intent.ACTION_VIEW, Uri.parse(info.download_url))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent piDownload = PendingIntentCompat.getActivity(
ActivityView.this, 0, download, 0);
NotificationCompat.Action.Builder actionDownload = new NotificationCompat.Action.Builder(
R.drawable.twotone_cloud_download_24,
getString(R.string.title_download),
piDownload);
builder.addAction(actionDownload.build());
}
try {
NotificationManager nm =
Helper.getSystemService(ActivityView.this, NotificationManager.class);
if (NotificationHelper.areNotificationsEnabled(nm))
nm.notify(NotificationHelper.NOTIFICATION_UPDATE,
builder.build());
} catch (Throwable ex) {
Log.w(ex);
}
}
@Override
protected void onException(Bundle args, Throwable ex) {
2023-12-06 16:06:46 +00:00
if (args.getBoolean("always")) {
boolean report = !(ex instanceof IllegalArgumentException || ex instanceof IOException);
Log.unexpectedError(getSupportFragmentManager(), ex, report);
}
}
}.execute(this, args, "update:check");
}
2023-01-08 11:29:30 +00:00
private void checkAnnouncements(boolean always) {
if (TextUtils.isEmpty(BuildConfig.ANNOUNCEMENT_URI))
return;
long now = new Date().getTime();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean announcements = prefs.getBoolean("announcements", true);
long last_announcement_check = prefs.getLong("last_announcement_check", 0);
if (!always && !announcements)
return;
if (!always && last_announcement_check + ANNOUNCEMENT_INTERVAL > now)
return;
prefs.edit().putLong("last_announcement_check", now).apply();
Bundle args = new Bundle();
args.putBoolean("always", always);
new SimpleTask<List<Announcement>>() {
@Override
protected List<Announcement> onExecute(Context context, Bundle args) throws Throwable {
StringBuilder response = new StringBuilder();
HttpsURLConnection urlConnection = null;
try {
URL latest = new URL(BuildConfig.ANNOUNCEMENT_URI);
urlConnection = (HttpsURLConnection) latest.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(ANNOUNCEMENT_TIMEOUT);
urlConnection.setConnectTimeout(ANNOUNCEMENT_TIMEOUT);
urlConnection.setDoOutput(false);
ConnectionHelper.setUserAgent(context, urlConnection);
urlConnection.connect();
int status = urlConnection.getResponseCode();
InputStream inputStream = (status == HttpsURLConnection.HTTP_OK
? urlConnection.getInputStream() : urlConnection.getErrorStream());
if (inputStream != null) {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = br.readLine()) != null)
response.append(line);
}
if (status != HttpsURLConnection.HTTP_OK)
throw new IOException("HTTP " + status + ": " + response);
DateFormat DTF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
List<Announcement> announcements = new ArrayList<>();
JSONObject jroot = new JSONObject(response.toString());
JSONArray jannouncements = jroot.getJSONArray("Announcements");
for (int i = 0; i < jannouncements.length(); i++) {
JSONObject jannouncement = jannouncements.getJSONObject(i);
String language = Locale.getDefault().getLanguage();
String title = jannouncement.optString("Title." + language);
if (TextUtils.isEmpty(title))
title = jannouncement.getString("Title");
String text = jannouncement.optString("Text." + language);
if (TextUtils.isEmpty(text))
text = jannouncement.getString("Text");
Announcement announcement = new Announcement();
announcement.id = jannouncement.getInt("ID");
announcement.test = jannouncement.optBoolean("Test");
2023-01-18 08:20:03 +00:00
announcement.play = jannouncement.optBoolean("Play", false);
announcement.fdroid = jannouncement.optBoolean("FDroid", true);
2023-01-08 11:29:30 +00:00
announcement.title = title;
announcement.text = HtmlHelper.fromHtml(text, context);
2023-01-18 08:20:03 +00:00
announcement.minVersion = jannouncement.optInt("minVersion", 0);
announcement.maxVersion = jannouncement.optInt("maxVersion", BuildConfig.VERSION_CODE);
2023-01-08 11:29:30 +00:00
if (jannouncement.has("Link"))
announcement.link = Uri.parse(jannouncement.getString("Link"));
announcement.expires = DTF.parse(jannouncement.getString("Expires")
.replace("Z", "+00:00"));
announcements.add(announcement);
}
return announcements;
} finally {
if (urlConnection != null)
urlConnection.disconnect();
}
}
@Override
protected void onExecuted(Bundle args, List<Announcement> announcements) {
boolean always = args.getBoolean("always");
NotificationManager nm =
Helper.getSystemService(ActivityView.this, NotificationManager.class);
if (!NotificationHelper.areNotificationsEnabled(nm))
return;
SharedPreferences.Editor editor = prefs.edit();
for (Announcement announcement : announcements) {
String key = "announcement." + announcement.id;
if (announcement.isExpired()) {
editor.remove(key);
nm.cancel(announcement.id);
} else {
boolean notified = prefs.getBoolean(key, false);
if (notified && !always)
continue;
editor.putBoolean(key, true);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(ActivityView.this, "announcements")
2023-01-09 06:47:01 +00:00
.setSmallIcon(R.drawable.baseline_campaign_white_24)
2023-01-08 11:29:30 +00:00
.setContentTitle(announcement.title)
.setContentText(announcement.text)
.setAutoCancel(true)
.setShowWhen(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
2023-01-09 06:47:01 +00:00
.setCategory(NotificationCompat.CATEGORY_RECOMMENDATION)
2023-01-09 07:01:44 +00:00
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(announcement.text));
2023-01-08 11:29:30 +00:00
if (announcement.link != null) {
2023-01-09 07:07:14 +00:00
Intent link = new Intent(Intent.ACTION_VIEW, announcement.link)
2023-01-08 11:29:30 +00:00
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2023-01-09 07:07:14 +00:00
PendingIntent piLink = PendingIntentCompat.getActivity(
ActivityView.this, PI_ANNOUNCEMENT, link, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(piLink);
2023-01-08 11:29:30 +00:00
}
2023-01-09 06:51:34 +00:00
Intent manage = new Intent(ActivityView.this, ActivitySetup.class)
.setAction("misc")
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
.putExtra("tab", "misc");
PendingIntent piManage = PendingIntentCompat.getActivity(
ActivityView.this, ActivitySetup.PI_MISC, manage, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder actionManage = new NotificationCompat.Action.Builder(
R.drawable.twotone_settings_24,
getString(R.string.title_setup_manage),
piManage);
builder.addAction(actionManage.build());
2023-01-08 11:29:30 +00:00
nm.notify(announcement.id, builder.build());
}
}
editor.apply();
}
@Override
protected void onException(Bundle args, Throwable ex) {
if (args.getBoolean("always"))
Log.unexpectedError(getSupportFragmentManager(), ex);
}
}.execute(this, args, "announcements:check");
}
2019-09-18 08:42:13 +00:00
private void checkIntent() {
Intent intent = getIntent();
2021-02-17 14:41:32 +00:00
Log.i("View intent=" + intent +
" " + TextUtils.join(", ", Log.getExtras(intent.getExtras())));
2019-09-18 08:42:13 +00:00
// Refresh from widget
2019-09-18 08:42:13 +00:00
if (intent.getBooleanExtra("refresh", false)) {
intent.removeExtra("refresh");
2021-03-29 07:18:04 +00:00
int version = intent.getIntExtra("version", 0);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ActivityView.this);
boolean sync_on_launch = prefs.getBoolean("sync_on_launch", false);
if (sync_on_launch || version < 1541)
ServiceUI.sync(this, null);
2019-09-18 08:42:13 +00:00
}
String action = intent.getAction();
if (action != null) {
2019-10-02 09:32:00 +00:00
if (action.startsWith("unified")) {
2019-09-18 08:42:13 +00:00
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getSupportFragmentManager().popBackStack("unified", 0);
2019-10-02 09:32:00 +00:00
if (action.contains(":")) {
Intent clear = new Intent(this, ServiceUI.class)
.setAction(action.replace("unified", "clear"));
startService(clear);
}
} else if (action.startsWith("folders")) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getSupportFragmentManager().popBackStack("unified", 0);
long account = Long.parseLong(action.split(":", 2)[1]);
if (account > 0)
onMenuFolders(account);
2019-11-17 17:08:26 +00:00
} else if (action.startsWith("folder")) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getSupportFragmentManager().popBackStack("unified", 0);
2020-06-15 10:34:25 +00:00
String[] parts = action.split(":");
long folder = Long.parseLong(parts[1]);
if (folder > 0) {
intent.putExtra("folder", folder);
onViewMessages(intent);
}
2020-06-15 10:34:25 +00:00
if (parts.length > 2) {
Intent clear = new Intent(this, ServiceUI.class)
.setAction("clear:" + parts[2]);
startService(clear);
}
2019-11-17 17:08:26 +00:00
2019-09-18 08:42:13 +00:00
} else if ("why".equals(action)) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getSupportFragmentManager().popBackStack("unified", 0);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ActivityView.this);
boolean why = prefs.getBoolean("why", false);
if (!why || BuildConfig.DEBUG) {
prefs.edit().putBoolean("why", true).apply();
Helper.viewFAQ(this, 2);
}
} else if ("outbox".equals(action)) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getSupportFragmentManager().popBackStack("unified", 0);
2019-09-18 08:42:13 +00:00
onMenuOutbox();
} else if (action.startsWith("thread")) {
long id = Long.parseLong(action.split(":", 2)[1]);
long account = intent.getLongExtra("account", -1);
long folder = intent.getLongExtra("folder", -1);
String type = intent.getStringExtra("type");
boolean ignore = intent.getBooleanExtra("ignore", false);
long group = intent.getLongExtra("group", -1L);
if (ignore)
ServiceUI.ignore(this, id, group);
intent.putExtra("id", id);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ActivityView.this);
boolean notify_open_folder = prefs.getBoolean("notify_open_folder", false);
if (account > 0 && folder > 0 && !TextUtils.isEmpty(type) && notify_open_folder) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
if (group >= 0)
getSupportFragmentManager().popBackStack("unified", 0);
else {
getSupportFragmentManager().popBackStack("messages", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Bundle args = new Bundle();
args.putLong("account", account);
args.putLong("folder", folder);
args.putString("type", type);
FragmentMessages fragment = new FragmentMessages();
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("messages");
fragmentTransaction.commit();
}
}
}
2019-09-18 08:42:13 +00:00
onViewThread(intent);
2022-07-10 20:21:25 +00:00
} else if (action.startsWith("widget")) {
2020-09-09 20:51:10 +00:00
long account = intent.getLongExtra("widget_account", -1);
long folder = intent.getLongExtra("widget_folder", -1);
String type = intent.getStringExtra("widget_type");
2020-09-06 07:33:05 +00:00
if (account > 0 && folder > 0 && !TextUtils.isEmpty(type)) {
if (!intent.getBooleanExtra("standalone", false) &&
getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
getSupportFragmentManager().popBackStack("messages", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Bundle args = new Bundle();
args.putLong("account", account);
args.putLong("folder", folder);
2020-09-06 07:33:05 +00:00
args.putString("type", type);
FragmentMessages fragment = new FragmentMessages();
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("messages");
fragmentTransaction.commit();
}
}
2019-09-18 08:42:13 +00:00
onViewThread(intent);
}
2021-05-01 14:36:14 +00:00
intent.setAction(null);
2019-09-18 08:42:13 +00:00
}
if (intent.hasExtra(Intent.EXTRA_PROCESS_TEXT)) {
CharSequence csearch = getIntent().getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT);
String search = (csearch == null ? null : csearch.toString());
if (!TextUtils.isEmpty(search)) {
searching = true;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean fts = prefs.getBoolean("fts", false);
BoundaryCallbackMessages.SearchCriteria criteria = new BoundaryCallbackMessages.SearchCriteria();
criteria.query = search;
criteria.fts = fts;
2019-09-18 08:42:13 +00:00
FragmentMessages.search(
ActivityView.this, ActivityView.this, getSupportFragmentManager(),
-1, -1, false, criteria);
2019-09-18 08:42:13 +00:00
}
intent.removeExtra(Intent.EXTRA_PROCESS_TEXT);
}
}
private void onMenuFolders(long account) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
2018-11-24 16:30:17 +00:00
getSupportFragmentManager().popBackStack("unified", 0);
Bundle args = new Bundle();
args.putLong("account", account);
FragmentFolders fragment = new FragmentFolders();
fragment.setArguments(args);
2018-08-02 13:33:06 +00:00
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("folders");
2018-08-02 13:33:06 +00:00
fragmentTransaction.commit();
}
2019-03-18 13:35:45 +00:00
private void onMenuOutbox() {
Bundle args = new Bundle();
2019-09-11 10:37:50 +00:00
new SimpleTask<EntityFolder>() {
2019-03-18 13:35:45 +00:00
@Override
2019-09-11 10:37:50 +00:00
protected EntityFolder onExecute(Context context, Bundle args) {
2019-03-18 13:35:45 +00:00
DB db = DB.getInstance(context);
EntityFolder outbox = db.folder().getOutbox();
2019-09-11 10:37:50 +00:00
return outbox;
2019-03-18 13:35:45 +00:00
}
@Override
2019-09-11 10:37:50 +00:00
protected void onExecuted(Bundle args, EntityFolder outbox) {
if (outbox == null)
return;
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
2019-03-18 13:35:45 +00:00
getSupportFragmentManager().popBackStack("unified", 0);
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ActivityView.this);
lbm.sendBroadcast(
new Intent(ActivityView.ACTION_VIEW_MESSAGES)
2019-03-25 15:43:56 +00:00
.putExtra("account", -1L)
2019-09-11 10:37:50 +00:00
.putExtra("folder", outbox.id)
.putExtra("type", outbox.type));
2019-03-18 13:35:45 +00:00
}
@Override
protected void onException(Bundle args, Throwable ex) {
2019-12-06 07:50:46 +00:00
Log.unexpectedError(getSupportFragmentManager(), ex);
2019-03-18 13:35:45 +00:00
}
}.execute(this, args, "menu:outbox");
2019-03-18 13:35:45 +00:00
}
2019-04-25 07:02:29 +00:00
private void onMenuOperations() {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
2019-04-25 07:02:29 +00:00
getSupportFragmentManager().popBackStack("operations", FragmentManager.POP_BACK_STACK_INCLUSIVE);
2019-03-15 07:34:31 +00:00
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
2019-04-25 07:02:29 +00:00
fragmentTransaction.replace(R.id.content_frame, new FragmentOperations()).addToBackStack("operations");
fragmentTransaction.commit();
}
2019-04-25 07:02:29 +00:00
private void onMenuAnswers() {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
2019-04-25 07:02:29 +00:00
getSupportFragmentManager().popBackStack("answers", FragmentManager.POP_BACK_STACK_INCLUSIVE);
2019-03-15 07:34:31 +00:00
2018-08-13 06:59:05 +00:00
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
2019-04-25 07:02:29 +00:00
fragmentTransaction.replace(R.id.content_frame, new FragmentAnswers()).addToBackStack("answers");
2018-08-13 06:59:05 +00:00
fragmentTransaction.commit();
}
2022-03-25 09:48:49 +00:00
private void onMenuRulesAccount() {
2022-03-25 17:49:37 +00:00
new SimpleTask<EntityAccount>() {
@Override
protected EntityAccount onExecute(Context context, Bundle args) {
DB db = DB.getInstance(context);
2022-03-25 17:56:28 +00:00
List<EntityAccount> accounts = db.account().getSynchronizingAccounts(null);
2022-03-25 17:49:37 +00:00
if (accounts != null && accounts.size() == 1)
return accounts.get(0);
return null;
}
@Override
protected void onExecuted(Bundle args, EntityAccount account) {
if (account == null) {
FragmentDialogSelectAccount fragment = new FragmentDialogSelectAccount();
fragment.setArguments(new Bundle());
fragment.setTargetActivity(ActivityView.this, REQUEST_RULES_ACCOUNT);
fragment.show(getSupportFragmentManager(), "rules:account");
} else {
args.putLong("account", account.id);
args.putInt("protocol", account.protocol);
args.putString("name", account.name);
onMenuRulesFolder(args);
}
}
@Override
protected void onException(Bundle args, Throwable ex) {
Log.unexpectedError(getSupportFragmentManager(), ex);
}
}.execute(this, new Bundle(), "rules:account");
2022-03-25 09:48:49 +00:00
}
private void onMenuRulesFolder(Bundle args) {
2022-09-06 20:05:55 +00:00
args.putInt("icon", R.drawable.twotone_filter_alt_24);
2023-03-06 19:39:55 +00:00
args.putString("title", getString(R.string.title_select));
2022-03-25 09:48:49 +00:00
args.putLongArray("disabled", new long[0]);
2023-03-27 16:03:32 +00:00
FragmentDialogSelectFolder fragment = new FragmentDialogSelectFolder();
2022-03-25 09:48:49 +00:00
fragment.setArguments(args);
fragment.setTargetActivity(this, REQUEST_RULES_FOLDER);
fragment.show(getSupportFragmentManager(), "rules:folder");
}
private void onMenuRules(Bundle args) {
FragmentRules fragment = new FragmentRules();
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("rules");
fragmentTransaction.commit();
}
2019-01-14 13:20:47 +00:00
private void onMenuSetup() {
2021-08-13 14:39:44 +00:00
startActivity(new Intent(ActivityView.this, ActivitySetup.class)
2022-08-25 05:28:06 +00:00
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
2018-08-06 17:04:24 +00:00
}
2019-01-14 13:20:47 +00:00
private void onMenuLegend() {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
2019-03-15 07:34:31 +00:00
getSupportFragmentManager().popBackStack("legend", FragmentManager.POP_BACK_STACK_INCLUSIVE);
2018-08-26 06:11:06 +00:00
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
2019-01-14 13:20:47 +00:00
fragmentTransaction.replace(R.id.content_frame, new FragmentLegend()).addToBackStack("legend");
2018-08-26 06:11:06 +00:00
fragmentTransaction.commit();
2018-08-25 11:27:54 +00:00
}
private void onMenuTest() {
Helper.view(this, Uri.parse(Helper.TEST_URI), false);
}
2019-01-14 13:20:47 +00:00
private void onMenuFAQ() {
2019-08-15 05:58:20 +00:00
Helper.viewFAQ(this, 0);
2019-01-14 13:20:47 +00:00
}
2020-01-17 10:05:35 +00:00
private void onMenuTranslate() {
2020-08-29 07:31:43 +00:00
Helper.viewFAQ(this, 26);
2020-01-17 10:05:35 +00:00
}
private void onMenuIssue() {
2022-05-15 08:19:48 +00:00
startActivity(Helper.getIntentIssue(this, "View:issue"));
}
2018-08-22 06:20:31 +00:00
private void onMenuPrivacy() {
2021-07-22 14:06:53 +00:00
Helper.view(this, Helper.getPrivacyUri(this), false);
2018-08-22 06:20:31 +00:00
}
private void onMenuAbout() {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
2019-03-15 07:34:31 +00:00
getSupportFragmentManager().popBackStack("about", FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, new FragmentAbout()).addToBackStack("about");
fragmentTransaction.commit();
2018-08-02 17:07:02 +00:00
}
private void onMenuRate() {
2019-08-15 05:58:20 +00:00
new FragmentDialogRate().show(getSupportFragmentManager(), "rate");
}
2018-11-24 16:30:17 +00:00
2018-11-13 15:01:29 +00:00
private void onDebugInfo() {
2023-06-18 06:38:22 +00:00
FragmentDialogDebug fragment = new FragmentDialogDebug();
fragment.setArguments(new Bundle());
fragment.setTargetActivity(this, REQUEST_DEBUG_INFO);
fragment.show(getSupportFragmentManager(), "debug");
}
private void onDebugInfo(Bundle args) {
Log.logBundle(args);
2018-11-13 15:01:29 +00:00
new SimpleTask<Long>() {
2021-06-20 18:58:39 +00:00
@Override
protected void onPreExecute(Bundle args) {
2023-06-18 06:38:22 +00:00
ToastEx.makeText(ActivityView.this, R.string.title_debug_info, Toast.LENGTH_LONG).show();
2021-06-20 18:58:39 +00:00
}
2018-11-13 15:01:29 +00:00
@Override
2021-01-03 09:58:51 +00:00
protected Long onExecute(Context context, Bundle args) throws IOException, JSONException {
2023-09-04 10:00:05 +00:00
boolean send = args.getBoolean("send");
2023-12-15 11:36:20 +00:00
EntityMessage m = DebugHelper.getDebugInfo(context,
"main", R.string.title_debug_info_remark, null, null, args);
if (m == null)
return null;
2023-09-04 10:00:05 +00:00
if (send) {
DB db = DB.getInstance(context);
try {
db.beginTransaction();
2023-12-15 11:36:20 +00:00
EntityMessage draft = db.message().getMessage(m.id);
if (draft != null) {
2023-09-04 13:38:05 +00:00
draft.folder = EntityFolder.getOutbox(context).id;
2023-09-04 10:00:05 +00:00
db.message().updateMessage(draft);
EntityOperation.queue(context, draft, EntityOperation.SEND);
db.setTransactionSuccessful();
2023-09-04 13:38:05 +00:00
args.putBoolean("sent", true);
return null;
2023-09-04 10:00:05 +00:00
}
} finally {
db.endTransaction();
}
}
2023-12-15 11:36:20 +00:00
return m.id;
2018-11-13 15:01:29 +00:00
}
@Override
2018-12-31 07:03:48 +00:00
protected void onExecuted(Bundle args, Long id) {
2023-12-15 11:36:20 +00:00
if (id == null)
return;
2023-09-04 13:38:05 +00:00
boolean sent = args.getBoolean("sent");
if (sent) {
ToastEx.makeText(ActivityView.this, R.string.title_debug_info_send, Toast.LENGTH_LONG).show();
ServiceSend.start(ActivityView.this);
return;
}
2023-09-04 10:00:05 +00:00
if (id == null)
return;
startActivity(new Intent(ActivityView.this, ActivityCompose.class)
.putExtra("action", "edit")
.putExtra("id", id));
2018-11-13 15:01:29 +00:00
}
@Override
protected void onException(Bundle args, Throwable ex) {
2023-12-06 16:06:46 +00:00
boolean report = !(ex instanceof IllegalArgumentException);
Log.unexpectedError(getSupportFragmentManager(), ex, report);
2018-11-13 15:01:29 +00:00
}
2018-12-07 07:40:52 +00:00
2023-06-18 06:38:22 +00:00
}.execute(this, args, "debug:info");
2018-11-13 15:01:29 +00:00
}
private void onShowLog() {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getSupportFragmentManager().popBackStack("logs", FragmentManager.POP_BACK_STACK_INCLUSIVE);
2018-10-10 13:45:50 +00:00
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, new FragmentLogs()).addToBackStack("logs");
fragmentTransaction.commit();
2018-08-17 05:46:22 +00:00
}
2020-05-05 16:12:33 +00:00
private BroadcastReceiver creceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
2021-03-27 20:35:31 +00:00
String action = intent.getAction();
if (ACTION_NEW_MESSAGE.equals(action))
onNewMessage(intent);
2020-05-05 16:12:33 +00:00
}
};
2021-08-22 18:12:13 +00:00
private List<Pair<Long, String>> updatedFolders = new ArrayList<>();
2020-05-05 16:12:33 +00:00
2021-08-22 18:12:13 +00:00
boolean isFolderUpdated(Long folder, String type) {
Pair<Long, String> key = new Pair<>(
folder == null ? -1L : folder,
folder == null ? type : null);
boolean value = updatedFolders.contains(key);
2020-05-05 16:12:33 +00:00
if (value)
2021-08-22 18:12:13 +00:00
updatedFolders.remove(key);
2020-05-05 16:12:33 +00:00
return value;
}
private void onNewMessage(Intent intent) {
long folder = intent.getLongExtra("folder", -1);
2021-08-22 18:12:13 +00:00
String type = intent.getStringExtra("type");
2020-05-05 16:12:33 +00:00
boolean unified = intent.getBooleanExtra("unified", false);
2021-08-22 18:12:13 +00:00
Pair<Long, String> pfolder = new Pair<>(folder, null);
if (!updatedFolders.contains(pfolder))
updatedFolders.add(pfolder);
Pair<Long, String> ptype = new Pair<>(-1L, type);
if (!updatedFolders.contains(ptype))
updatedFolders.add(ptype);
if (unified) {
Pair<Long, String> punified = new Pair<>(-1L, null);
if (!updatedFolders.contains(punified))
updatedFolders.add(punified);
}
2020-05-05 16:12:33 +00:00
}
2019-05-27 10:15:25 +00:00
private BroadcastReceiver receiver = new BroadcastReceiver() {
2018-08-02 13:33:06 +00:00
@Override
public void onReceive(Context context, Intent intent) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
2018-12-12 14:59:34 +00:00
String action = intent.getAction();
if (ACTION_VIEW_FOLDERS.equals(action))
onViewFolders(intent);
else if (ACTION_VIEW_MESSAGES.equals(action))
2018-12-12 14:59:34 +00:00
onViewMessages(intent);
2022-11-28 18:26:37 +00:00
else if (ACTION_SEARCH_ADDRESS.equals(action))
onSearchAddress(intent);
2018-12-12 14:59:34 +00:00
else if (ACTION_VIEW_THREAD.equals(action))
onViewThread(intent);
else if (ACTION_EDIT_FOLDER.equals(action))
onEditFolder(intent);
2021-03-31 16:28:00 +00:00
else if (ACTION_VIEW_OUTBOX.equals(action))
onMenuOutbox();
2019-01-18 08:28:07 +00:00
else if (ACTION_EDIT_ANSWERS.equals(action))
onEditAnswers(intent);
2018-12-12 14:59:34 +00:00
else if (ACTION_EDIT_ANSWER.equals(action))
onEditAnswer(intent);
2019-01-18 08:23:53 +00:00
else if (ACTION_EDIT_RULES.equals(action))
onEditRules(intent);
2019-01-17 13:29:35 +00:00
else if (ACTION_EDIT_RULE.equals(action))
onEditRule(intent);
2018-12-12 14:59:34 +00:00
}
2018-08-25 18:43:13 +00:00
}
};
2018-08-09 20:45:42 +00:00
private void onViewFolders(Intent intent) {
long account = intent.getLongExtra("id", -1);
onMenuFolders(account);
}
2018-08-25 18:43:13 +00:00
private void onViewMessages(Intent intent) {
2022-11-06 20:32:40 +00:00
boolean unified = intent.getBooleanExtra("unified", false);
2021-01-25 18:05:58 +00:00
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
2022-11-06 20:32:40 +00:00
if (unified && "unified".equals(startup)) {
getSupportFragmentManager().popBackStack("unified", 0);
return;
2023-04-17 19:33:39 +00:00
} else {
getSupportFragmentManager().popBackStack("thread", FragmentManager.POP_BACK_STACK_INCLUSIVE);
2022-11-06 20:32:40 +00:00
getSupportFragmentManager().popBackStack("messages", FragmentManager.POP_BACK_STACK_INCLUSIVE);
2023-04-17 19:33:39 +00:00
}
2022-02-19 21:56:19 +00:00
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean foldernav = prefs.getBoolean("foldernav", false);
if (foldernav) {
long account = intent.getLongExtra("account", -1);
if (account > 0) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getSupportFragmentManager().popBackStack("unified", 0);
onMenuFolders(account);
}
}
2018-10-17 09:15:44 +00:00
Bundle args = new Bundle();
2019-07-19 06:27:44 +00:00
args.putString("type", intent.getStringExtra("type"));
2018-10-17 09:15:44 +00:00
args.putLong("account", intent.getLongExtra("account", -1));
args.putLong("folder", intent.getLongExtra("folder", -1));
2018-08-25 18:43:13 +00:00
FragmentMessages fragment = new FragmentMessages();
2018-10-17 09:15:44 +00:00
fragment.setArguments(args);
2018-08-25 18:43:13 +00:00
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
2022-11-06 20:32:40 +00:00
fragmentTransaction.replace(R.id.content_frame, fragment)
.addToBackStack(unified ? "unified" : "messages");
2018-08-25 18:43:13 +00:00
fragmentTransaction.commit();
}
2022-11-28 18:26:37 +00:00
private void onSearchAddress(Intent intent) {
2019-11-16 11:53:36 +00:00
long account = intent.getLongExtra("account", -1);
2019-05-13 12:08:51 +00:00
long folder = intent.getLongExtra("folder", -1);
2019-05-13 13:56:44 +00:00
String query = intent.getStringExtra("query");
2022-11-28 18:26:37 +00:00
boolean sender_only = intent.getBooleanExtra("sender_only", false);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean fts = prefs.getBoolean("fts", false);
BoundaryCallbackMessages.SearchCriteria criteria = new BoundaryCallbackMessages.SearchCriteria();
criteria.query = query;
criteria.fts = fts;
2022-11-28 15:31:04 +00:00
criteria.in_senders = true;
2022-11-28 18:26:37 +00:00
if (sender_only) {
criteria.in_recipients = false;
criteria.in_subject = false;
criteria.in_keywords = false;
criteria.in_message = false;
criteria.in_notes = false;
2023-08-12 13:19:56 +00:00
criteria.in_trash = false;
2022-11-28 18:26:37 +00:00
}
2019-05-13 12:08:51 +00:00
FragmentMessages.search(
this, this, getSupportFragmentManager(),
account, folder, false, criteria);
2019-05-13 12:08:51 +00:00
}
2018-10-15 10:05:42 +00:00
private void onViewThread(Intent intent) {
boolean found = intent.getBooleanExtra("found", false);
2020-07-25 19:28:26 +00:00
if (lastSnackbar != null && lastSnackbar.isShown())
lastSnackbar.dismiss();
2023-09-16 05:56:07 +00:00
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
if (found) {
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments.size() > 0) {
Bundle args = fragments.get(fragments.size() - 1).getArguments();
if (args != null && args.getBoolean("found"))
getSupportFragmentManager().popBackStack();
}
} else
getSupportFragmentManager().popBackStack("thread", FragmentManager.POP_BACK_STACK_INCLUSIVE);
2018-10-15 10:05:42 +00:00
Bundle args = new Bundle();
2018-10-17 09:15:44 +00:00
args.putLong("account", intent.getLongExtra("account", -1));
2020-06-21 06:25:41 +00:00
args.putLong("folder", intent.getLongExtra("folder", -1));
2018-10-17 09:15:44 +00:00
args.putString("thread", intent.getStringExtra("thread"));
args.putLong("id", intent.getLongExtra("id", -1));
2021-07-19 17:59:30 +00:00
args.putInt("lpos", intent.getIntExtra("lpos", -1));
args.putBoolean("filter_archive", intent.getBooleanExtra("filter_archive", true));
args.putBoolean("found", found);
2021-11-12 15:12:54 +00:00
args.putString("searched", intent.getStringExtra("searched"));
2021-04-11 10:07:53 +00:00
args.putBoolean("pinned", intent.getBooleanExtra("pinned", false));
2021-04-14 05:48:44 +00:00
args.putString("msgid", intent.getStringExtra("msgid"));
2018-08-09 20:45:42 +00:00
2018-10-15 10:05:42 +00:00
FragmentMessages fragment = new FragmentMessages();
fragment.setArguments(args);
2018-08-11 05:02:13 +00:00
int pane;
if (content_pane == null)
pane = R.id.content_frame;
else {
pane = R.id.content_pane;
content_separator.setVisibility(View.VISIBLE);
content_pane.setVisibility(View.VISIBLE);
2018-12-22 11:53:07 +00:00
args.putBoolean("pane", true);
}
2018-10-15 10:05:42 +00:00
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
2023-08-22 21:02:09 +00:00
fragmentTransaction.replace(pane, fragment, "thread").addToBackStack("thread");
2018-10-15 10:05:42 +00:00
fragmentTransaction.commit();
}
2018-08-09 20:45:42 +00:00
2018-08-25 18:43:13 +00:00
private void onEditFolder(Intent intent) {
FragmentFolder fragment = new FragmentFolder();
fragment.setArguments(intent.getExtras());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("folder");
fragmentTransaction.commit();
}
2018-08-25 11:27:54 +00:00
2019-01-18 08:28:07 +00:00
private void onEditAnswers(Intent intent) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, new FragmentAnswers()).addToBackStack("answers");
fragmentTransaction.commit();
}
2018-08-27 09:39:27 +00:00
private void onEditAnswer(Intent intent) {
FragmentAnswer fragment = new FragmentAnswer();
fragment.setArguments(intent.getExtras());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("answer");
fragmentTransaction.commit();
}
2019-01-18 08:23:53 +00:00
private void onEditRules(Intent intent) {
FragmentRules fragment = new FragmentRules();
fragment.setArguments(intent.getExtras());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("rules");
fragmentTransaction.commit();
}
2019-01-17 13:29:35 +00:00
private void onEditRule(Intent intent) {
FragmentRule fragment = new FragmentRule();
fragment.setArguments(intent.getExtras());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("rule");
fragmentTransaction.commit();
}
private class UpdateInfo {
String tag_name; // version
String html_url;
String download_url;
}
2023-01-08 11:29:30 +00:00
private class Announcement {
int id;
boolean test;
2023-01-18 08:20:03 +00:00
boolean play;
boolean fdroid;
2023-01-08 11:29:30 +00:00
String title;
Spanned text;
2023-01-18 08:20:03 +00:00
int minVersion;
int maxVersion;
2023-01-08 11:29:30 +00:00
Uri link;
Date expires;
boolean isExpired() {
if (this.test && !BuildConfig.DEBUG)
return true;
2023-01-18 08:20:03 +00:00
if (this.play && !BuildConfig.PLAY_STORE_RELEASE)
return true;
if (this.fdroid && !BuildConfig.FDROID_RELEASE)
return true;
if (this.minVersion > BuildConfig.VERSION_CODE || BuildConfig.VERSION_CODE > this.maxVersion)
return true;
2023-01-08 11:29:30 +00:00
if (expires == null)
return true;
return (expires.getTime() < new Date().getTime());
}
}
2022-05-10 09:11:37 +00:00
private final Consumer<WindowLayoutInfo> layoutStateChangeCallback = new Consumer<WindowLayoutInfo>() {
@Override
public void accept(WindowLayoutInfo info) {
2023-08-10 17:54:42 +00:00
EntityLog.log(ActivityView.this, "Window layout=" + info);
2022-05-10 09:11:37 +00:00
}
};
2018-08-02 13:33:06 +00:00
}