Fix weak reference to account destroyed in background

This commit is contained in:
Thomas 2022-06-19 17:26:39 +02:00
parent eaf9ac87af
commit 5d2f7c3475
22 changed files with 403 additions and 365 deletions

View file

@ -108,6 +108,7 @@ import app.fedilab.android.client.entities.api.Instance;
import app.fedilab.android.client.entities.api.MastodonList;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.client.entities.app.BottomMenu;
import app.fedilab.android.client.entities.app.Pinned;
import app.fedilab.android.client.entities.app.PinnedTimeline;
@ -142,7 +143,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
public static boolean show_boosts, show_replies, show_art_nsfw;
public static String regex_home, regex_local, regex_public;
Fragment currentFragment;
private Account account;
private BaseAccount account;
private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding;
private Pinned pinned;
@ -242,7 +243,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
instanceIntent = extras.getString(Helper.PREF_INSTANCE);
if (extras.getInt(Helper.INTENT_ACTION) == Helper.NOTIFICATION_INTENT) {
try {
Account account = new Account(BaseMainActivity.this).getUniqAccount(userIdIntent, instanceIntent);
BaseAccount account = new Account(BaseMainActivity.this).getUniqAccount(userIdIntent, instanceIntent);
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(BaseMainActivity.this);
headerMenuOpen = false;
Toasty.info(BaseMainActivity.this, getString(R.string.toast_account_changed, "@" + account.mastodon_account.acct + "@" + account.instance), Toasty.LENGTH_LONG).show();
@ -379,7 +380,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
headerMainBinding.ownerAccounts.setImageResource(R.drawable.ic_baseline_arrow_drop_up_24);
new Thread(() -> {
try {
List<Account> accounts = new Account(BaseMainActivity.this).getAll();
List<BaseAccount> accounts = new Account(BaseMainActivity.this).getAll();
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
binding.navView.getMenu().clear();
@ -390,7 +391,7 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
SubMenu currentSubmenu = null;
String lastInstance = "";
if (accounts != null) {
for (final Account account : accounts) {
for (final BaseAccount account : accounts) {
if (!currentToken.equalsIgnoreCase(account.token)) {
if (!lastInstance.trim().equalsIgnoreCase(account.instance.trim())) {
lastInstance = account.instance.toUpperCase();
@ -682,12 +683,11 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
.observe(BaseMainActivity.this, account1 -> {
//Initialize static var
getCurrentAccount(BaseMainActivity.this);
//Set the Mastodon account
Helper.setMastodonAccount(account1);
new Thread(() -> {
try {
//Update account in db
new Account(BaseMainActivity.this).insertOrUpdate(getCurrentAccount(BaseMainActivity.this));
getCurrentAccount(BaseMainActivity.this);
} catch (DBException e) {
e.printStackTrace();
}

View file

@ -75,7 +75,7 @@ public class MainApplication extends MultiDexApplication {
super.attachBaseContext(base);
MultiDex.install(MainApplication.this);
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(MainApplication.this);
boolean send_crash_reports = sharedpreferences.getBoolean(getString(R.string.SET_SEND_CRASH_REPORTS), false);
boolean send_crash_reports = sharedpreferences.getBoolean(getString(R.string.SET_SEND_CRASH_REPORTS), true);
if (send_crash_reports) {
ACRA.init(this, new CoreConfigurationBuilder()
//core configuration:

View file

@ -70,6 +70,7 @@ import app.fedilab.android.client.entities.api.Mention;
import app.fedilab.android.client.entities.api.ScheduledStatus;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.client.entities.app.StatusDraft;
import app.fedilab.android.databinding.ActivityPaginationBinding;
import app.fedilab.android.databinding.PopupContactBinding;
@ -122,7 +123,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
}
};
private ActivityPaginationBinding binding;
private Account account;
private BaseAccount account;
private String instance, token;
private Uri photoFileUri;
private ScheduledStatus scheduledStatus;

View file

@ -104,7 +104,7 @@ public class Status implements Serializable, Cloneable {
public transient boolean isFocused = false;
public transient boolean setCursorToEnd = false;
public transient int cursorPosition = 0;
public transient boolean submitted = false;
@NonNull
public Object clone() throws CloneNotSupportedException {
return super.clone();

View file

@ -20,7 +20,6 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.ArrayList;
@ -37,36 +36,10 @@ import app.fedilab.android.sqlite.Sqlite;
* Accounts details are serialized and can be for different softwares
* The type of the software is stored in api field
*/
public class Account implements Serializable {
public class Account extends BaseAccount implements Serializable {
private final SQLiteDatabase db;
@SerializedName("user_id")
public String user_id;
@SerializedName("instance")
public String instance;
@SerializedName("api")
public API api;
@SerializedName("software")
public String software;
@SerializedName("token")
public String token;
@SerializedName("refresh_token")
public String refresh_token;
@SerializedName("token_validity")
public long token_validity;
@SerializedName("client_id")
public String client_id;
@SerializedName("client_secret")
public String client_secret;
@SerializedName("created_at")
public Date created_at;
@SerializedName("updated_at")
public Date updated_at;
@SerializedName("mastodon_account")
public app.fedilab.android.client.entities.api.Account mastodon_account;
@SerializedName("admin")
public boolean admin;
private transient Context context;
@ -81,9 +54,9 @@ public class Account implements Serializable {
}
/**
* Serialized a Mastodon Account class
* Serialized a Mastodon BaseAccount class
*
* @param mastodon_account {@link app.fedilab.android.client.entities.api.Account} to serialize
* @param mastodon_account {@link BaseAccount} to serialize
* @return String serialized account
*/
public static String mastodonAccountToStringStorage(app.fedilab.android.client.entities.api.Account mastodon_account) {
@ -96,7 +69,7 @@ public class Account implements Serializable {
}
/**
* Unserialized a Mastodon Account
* Unserialized a Mastodon BaseAccount
*
* @param serializedAccount String serialized account
* @return {@link app.fedilab.android.client.entities.api.Account}
@ -111,11 +84,11 @@ public class Account implements Serializable {
}
/**
* Returns all Account in db
* Returns all BaseAccount in db
*
* @return Account List<Account>
* @return BaseAccount List<BaseAccount>
*/
public List<Account> getPushNotificationAccounts() {
public List<BaseAccount> getPushNotificationAccounts() {
try {
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, "(" + Sqlite.COL_API + " = 'MASTODON' OR " + Sqlite.COL_API + " = 'PLEROMA' OR " + Sqlite.COL_API + " = 'FRIENDICA') AND " + Sqlite.COL_TOKEN + " IS NOT NULL", null, null, null, Sqlite.COL_INSTANCE + " ASC", null);
@ -128,11 +101,11 @@ public class Account implements Serializable {
/**
* Insert or update a user
*
* @param account {@link Account}
* @param account {@link BaseAccount}
* @return long - db id
* @throws DBException exception with database
*/
public long insertOrUpdate(Account account) throws DBException {
public long insertOrUpdate(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -149,11 +122,11 @@ public class Account implements Serializable {
/**
* Insert an account in db
*
* @param account {@link Account}
* @param account {@link BaseAccount}
* @return long - db id
* @throws DBException exception with database
*/
private long insertAccount(Account account) throws DBException {
private long insertAccount(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -185,11 +158,11 @@ public class Account implements Serializable {
/**
* Update an account in db
*
* @param account {@link Account}
* @param account {@link BaseAccount}
* @return long - db id
* @throws DBException exception with database
*/
private long updateAccount(Account account) throws DBException {
private long updateAccount(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -223,11 +196,11 @@ public class Account implements Serializable {
/**
* Check if a user exists in db
*
* @param account Account {@link Account}
* @param account BaseAccount {@link BaseAccount}
* @return boolean - user exists
* @throws DBException Exception
*/
public boolean accountExist(Account account) throws DBException {
public boolean accountExist(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -240,13 +213,13 @@ public class Account implements Serializable {
}
/**
* Returns an Account by userId and instance
* Returns an BaseAccount by userId and instance
*
* @param userId String
* @param instance String
* @return Account {@link Account}
* @return BaseAccount {@link BaseAccount}
*/
public Account getUniqAccount(String userId, String instance) throws DBException {
public BaseAccount getUniqAccount(String userId, String instance) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -259,12 +232,12 @@ public class Account implements Serializable {
}
/**
* Returns an Account by token
* Returns an BaseAccount by token
*
* @param token String
* @return Account {@link Account}
* @return BaseAccount {@link BaseAccount}
*/
public Account getAccountByToken(String token) throws DBException {
public BaseAccount getAccountByToken(String token) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -277,11 +250,11 @@ public class Account implements Serializable {
}
/**
* Returns authenticated Account
* Returns authenticated BaseAccount
*
* @return Account {@link Account}
* @return BaseAccount {@link BaseAccount}
*/
public Account getConnectedAccount() throws DBException {
public BaseAccount getConnectedAccount() throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -297,9 +270,9 @@ public class Account implements Serializable {
/**
* Returns all accounts that allows cross-account actions
*
* @return Account List<{@link Account}>
* @return BaseAccount List<{@link BaseAccount}>
*/
public List<Account> getCrossAccounts() throws DBException {
public List<BaseAccount> getCrossAccounts() throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -314,9 +287,9 @@ public class Account implements Serializable {
/**
* Returns all accounts
*
* @return Account List<{@link Account}>
* @return BaseAccount List<{@link BaseAccount}>
*/
public List<Account> getAll() throws DBException {
public List<BaseAccount> getAll() throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -331,9 +304,9 @@ public class Account implements Serializable {
/**
* Returns last used account
*
* @return Account {@link Account}
* @return BaseAccount {@link BaseAccount}
*/
public Account getLastUsedAccount() throws DBException {
public BaseAccount getLastUsedAccount() throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -348,10 +321,10 @@ public class Account implements Serializable {
/**
* Remove an account from db
*
* @param account {@link Account}
* @param account {@link BaseAccount}
* @return int
*/
public int removeUser(Account account) throws DBException {
public int removeUser(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -360,15 +333,15 @@ public class Account implements Serializable {
}
private List<Account> cursorToListUser(Cursor c) {
private List<BaseAccount> cursorToListUser(Cursor c) {
//No element found
if (c.getCount() == 0) {
c.close();
return null;
}
List<Account> accountList = new ArrayList<>();
List<BaseAccount> accountList = new ArrayList<>();
while (c.moveToNext()) {
Account account = convertCursorToAccount(c);
BaseAccount account = convertCursorToAccount(c);
//We don't add in the list the current connected account
if (!account.token.equalsIgnoreCase(BaseMainActivity.currentToken)) {
accountList.add(account);
@ -379,15 +352,15 @@ public class Account implements Serializable {
return accountList;
}
private List<Account> cursorToListUserWithOwner(Cursor c) {
private List<BaseAccount> cursorToListUserWithOwner(Cursor c) {
//No element found
if (c.getCount() == 0) {
c.close();
return null;
}
List<Account> accountList = new ArrayList<>();
List<BaseAccount> accountList = new ArrayList<>();
while (c.moveToNext()) {
Account account = convertCursorToAccount(c);
BaseAccount account = convertCursorToAccount(c);
//We don't add in the list the current connected account
accountList.add(account);
}
@ -397,11 +370,11 @@ public class Account implements Serializable {
}
/***
* Method to hydrate an Account from database
* Method to hydrate an BaseAccount from database
* @param c Cursor
* @return Account {@link Account}
* @return BaseAccount {@link BaseAccount}
*/
private Account cursorToUser(Cursor c) {
private BaseAccount cursorToUser(Cursor c) {
//No element found
if (c.getCount() == 0) {
c.close();
@ -410,7 +383,7 @@ public class Account implements Serializable {
//Take the first element
c.moveToFirst();
//New user
Account account = convertCursorToAccount(c);
BaseAccount account = convertCursorToAccount(c);
//Close the cursor
c.close();
return account;
@ -420,10 +393,10 @@ public class Account implements Serializable {
* Read cursor and hydrate without closing it
*
* @param c - Cursor
* @return Account
* @return BaseAccount
*/
private Account convertCursorToAccount(Cursor c) {
Account account = new Account();
private BaseAccount convertCursorToAccount(Cursor c) {
BaseAccount account = new BaseAccount();
account.user_id = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_USER_ID));
account.client_id = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_APP_CLIENT_ID));
account.client_secret = c.getString(c.getColumnIndexOrThrow(Sqlite.COL_APP_CLIENT_SECRET));

View file

@ -0,0 +1,57 @@
package app.fedilab.android.client.entities.app;
/* Copyright 2022 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.Date;
/**
* Class that manages Accounts from database
* Accounts details are serialized and can be for different softwares
* The type of the software is stored in api field
*/
public class BaseAccount implements Serializable {
@SerializedName("user_id")
public String user_id;
@SerializedName("instance")
public String instance;
@SerializedName("api")
public Account.API api;
@SerializedName("software")
public String software;
@SerializedName("token")
public String token;
@SerializedName("refresh_token")
public String refresh_token;
@SerializedName("token_validity")
public long token_validity;
@SerializedName("client_id")
public String client_id;
@SerializedName("client_secret")
public String client_secret;
@SerializedName("created_at")
public Date created_at;
@SerializedName("updated_at")
public Date updated_at;
@SerializedName("mastodon_account")
public app.fedilab.android.client.entities.api.Account mastodon_account;
@SerializedName("admin")
public boolean admin;
}

View file

@ -118,7 +118,7 @@ public class BottomMenu implements Serializable {
return bottomMenu.bottom_menu.get(position).item_menu_type;
}
public BottomMenu hydrate(Account account, BottomNavigationView bottomNavigationView) {
public BottomMenu hydrate(BaseAccount account, BottomNavigationView bottomNavigationView) {
bottomNavigationView.getMenu().clear();
BottomMenu bottomMenu = null;
try {
@ -237,7 +237,7 @@ public class BottomMenu implements Serializable {
* @param account Account
* @return BottomMenu - {@link BottomMenu}
*/
public BottomMenu getAllBottomMenu(Account account) throws DBException {
public BottomMenu getAllBottomMenu(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -256,7 +256,7 @@ public class BottomMenu implements Serializable {
* @param account Account
* @return BottomMenu - {@link BottomMenu}
*/
public BottomMenu getBottomMenu(Account account) throws DBException {
public BottomMenu getBottomMenu(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}

View file

@ -149,7 +149,7 @@ public class Pinned implements Serializable {
* @param account Account
* @return Pinned - {@link Pinned}
*/
public Pinned getPinned(Account account) throws DBException {
public Pinned getPinned(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -178,7 +178,7 @@ public class Pinned implements Serializable {
* @param account Account
* @return Pinned - {@link Pinned}
*/
public Pinned getAllPinned(Account account) throws DBException {
public Pinned getAllPinned(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}

View file

@ -165,6 +165,7 @@ public class QuickLoad {
* @return long - db id
* @throws DBException exception with database
*/
@SuppressWarnings("UnusedReturnValue")
public long deleteForAllAccount() throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
@ -184,7 +185,8 @@ public class QuickLoad {
* @return long - db id
* @throws DBException exception with database
*/
public long deleteForAccount(Account account) throws DBException {
@SuppressWarnings("UnusedReturnValue")
public long deleteForAccount(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -202,11 +204,11 @@ public class QuickLoad {
/**
* Update a status in quickload
*
* @param account {@link Account}
* @param account {@link BaseAccount}
* @param newStatus - Status
* @throws DBException exception with database
*/
public void updateStatus(Account account, Status newStatus) throws DBException {
public void updateStatus(BaseAccount account, Status newStatus) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -279,7 +281,7 @@ public class QuickLoad {
* @param id - String id of the status
* @throws DBException exception with database
*/
public void deleteStatus(Account account, String id) throws DBException {
public void deleteStatus(BaseAccount account, String id) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -375,7 +377,7 @@ public class QuickLoad {
* @param ident - the name for pinned timeline
* @return SavedValues
*/
public QuickLoad getSavedValue(Account account, Timeline.TimeLineEnum timeLineType, String ident) {
public QuickLoad getSavedValue(BaseAccount account, Timeline.TimeLineEnum timeLineType, String ident) {
if (cannotBeStored(timeLineType)) {
return null;
}
@ -455,7 +457,7 @@ public class QuickLoad {
* @return Statuses
* @throws DBException - throws a db exception
*/
private QuickLoad get(String slug, Account account) throws DBException {
private QuickLoad get(String slug, BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}

View file

@ -169,7 +169,7 @@ public class ScheduledBoost implements Serializable {
* @param account Account
* @return List<ScheduledBoost> - List of {@link ScheduledBoost}
*/
public List<ScheduledBoost> getScheduled(Account account) throws DBException {
public List<ScheduledBoost> getScheduled(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}

View file

@ -238,7 +238,7 @@ public class StatusCache {
* @return long - db id
* @throws DBException exception with database
*/
public long deleteForAccount(Account account) throws DBException {
public long deleteForAccount(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}

View file

@ -278,7 +278,7 @@ public class StatusDraft implements Serializable {
* @param account Account
* @return List<StatusDraft> - List of {@link StatusDraft}
*/
public List<StatusDraft> geStatusDraftList(Account account) throws DBException {
public List<StatusDraft> geStatusDraftList(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
@ -297,7 +297,7 @@ public class StatusDraft implements Serializable {
* @param account Account
* @return List<StatusDraft> - List of {@link StatusDraft}
*/
public List<StatusDraft> geStatusDraftScheduledList(Account account) throws DBException {
public List<StatusDraft> geStatusDraftScheduledList(BaseAccount account) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}

View file

@ -40,6 +40,7 @@ import app.fedilab.android.client.endpoints.MastodonSearchService;
import app.fedilab.android.client.entities.api.Results;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.exception.DBException;
import app.fedilab.android.ui.drawer.AccountsSearchAdapter;
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
@ -67,14 +68,14 @@ public class CrossActionHelper {
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
new Thread(() -> {
try {
List<Account> accounts = new Account(context).getCrossAccounts();
List<BaseAccount> accounts = new Account(context).getCrossAccounts();
if (accounts.size() == 1) {
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> fetchRemote(context, actionType, accounts.get(0), targetedAccount, targetedStatus);
mainHandler.post(myRunnable);
} else {
List<app.fedilab.android.client.entities.api.Account> accountList = new ArrayList<>();
for (Account account : accounts) {
for (BaseAccount account : accounts) {
accountList.add(account.mastodon_account);
}
Handler mainHandler = new Handler(Looper.getMainLooper());
@ -82,9 +83,9 @@ public class CrossActionHelper {
AlertDialog.Builder builderSingle = new AlertDialog.Builder(context, Helper.dialogStyle());
builderSingle.setTitle(context.getString(R.string.choose_accounts));
final AccountsSearchAdapter accountsSearchAdapter = new AccountsSearchAdapter(context, accountList);
final Account[] accountArray = new Account[accounts.size()];
final BaseAccount[] accountArray = new Account[accounts.size()];
int i = 0;
for (Account account : accounts) {
for (BaseAccount account : accounts) {
accountArray[i] = account;
i++;
}
@ -92,7 +93,7 @@ public class CrossActionHelper {
builderSingle.setAdapter(accountsSearchAdapter, (dialog, which) -> {
boolean confirmFav = sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_VALIDATION_FAV), false);
boolean confirmBoost = sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_VALIDATION), true);
Account selectedAccount = accountArray[which];
BaseAccount selectedAccount = accountArray[which];
if ((actionType == TypeOfCrossAction.REBLOG_ACTION && confirmBoost) || (actionType == TypeOfCrossAction.FAVOURITE_ACTION && confirmFav)) {
AlertDialog.Builder alt_bld = new AlertDialog.Builder(context, Helper.dialogStyle());
if (actionType == TypeOfCrossAction.REBLOG_ACTION) {
@ -127,7 +128,7 @@ public class CrossActionHelper {
/**
* Fetch and federate the remote account or status
*/
private static void fetchRemote(@NonNull Context context, @NonNull TypeOfCrossAction actionType, @NonNull Account ownerAccount, app.fedilab.android.client.entities.api.Account targetedAccount, Status targetedStatus) {
private static void fetchRemote(@NonNull Context context, @NonNull TypeOfCrossAction actionType, @NonNull BaseAccount ownerAccount, app.fedilab.android.client.entities.api.Account targetedAccount, Status targetedStatus) {
SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get("crossactions", SearchVM.class);
if (targetedAccount != null) {
@ -165,7 +166,7 @@ public class CrossActionHelper {
/**
* Do action when status or account has been fetched
*/
private static void applyAction(@NonNull Context context, @NonNull TypeOfCrossAction actionType, @NonNull Account ownerAccount, app.fedilab.android.client.entities.api.Account targetedAccount, Status targetedStatus) {
private static void applyAction(@NonNull Context context, @NonNull TypeOfCrossAction actionType, @NonNull BaseAccount ownerAccount, app.fedilab.android.client.entities.api.Account targetedAccount, Status targetedStatus) {
AccountsVM accountsVM = null;
StatusesVM statusesVM = null;
@ -263,7 +264,7 @@ public class CrossActionHelper {
/**
* Fetch and federate the remote status
*/
public static void fetchRemoteStatus(@NonNull Context context, @NonNull Account ownerAccount, String url, Callback callback) {
public static void fetchRemoteStatus(@NonNull Context context, @NonNull BaseAccount ownerAccount, String url, Callback callback) {
MastodonSearchService mastodonSearchService = init(context, MainActivity.currentInstance);
new Thread(() -> {
Call<Results> resultsCall = mastodonSearchService.search(ownerAccount.token, url, null, "statuses", false, true, false, 0, null, null, 1);
@ -306,7 +307,7 @@ public class CrossActionHelper {
/**
* Fetch and federate the remote status
*/
public static void fetchRemoteAccount(@NonNull Context context, @NonNull Account ownerAccount, app.fedilab.android.client.entities.api.Account targetedAccount, Callback callback) {
public static void fetchRemoteAccount(@NonNull Context context, @NonNull BaseAccount ownerAccount, app.fedilab.android.client.entities.api.Account targetedAccount, Callback callback) {
MastodonSearchService mastodonSearchService = init(context, MainActivity.currentInstance);

View file

@ -132,6 +132,7 @@ import app.fedilab.android.activities.WebviewActivity;
import app.fedilab.android.broadcastreceiver.ToastMessage;
import app.fedilab.android.client.entities.api.Attachment;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.client.entities.app.QuickLoad;
import app.fedilab.android.client.entities.app.StatusCache;
import app.fedilab.android.exception.DBException;
@ -593,68 +594,7 @@ public class Helper {
return date;
}
/**
* Log out the authenticated user by removing its token
*
* @param activity Activity
* @param account {@link Account}
* @throws DBException Exception
*/
public static void removeAccount(Activity activity, Account account) throws DBException {
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
//Current user
String userId = sharedpreferences.getString(PREF_USER_ID, null);
String instance = sharedpreferences.getString(PREF_USER_INSTANCE, null);
Account accountDB = new Account(activity);
boolean accountRemovedIsLogged = false;
//Remove the current account
if (account == null) {
account = accountDB.getUniqAccount(userId, instance);
accountRemovedIsLogged = true;
}
if (account != null) {
Account finalAccount = account;
OauthVM oauthVM = new ViewModelProvider((ViewModelStoreOwner) activity).get(OauthVM.class);
//Revoke the token
oauthVM.revokeToken(account.instance, account.token, account.client_id, account.client_secret);
//Revoke token and remove user
new Thread(() -> {
try {
accountDB.removeUser(finalAccount);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
}
//If the account removed is not the logged one, no need to log out the current user
if (!accountRemovedIsLogged) {
return;
}
//Log out the current user
Account newAccount = accountDB.getLastUsedAccount();
SharedPreferences.Editor editor = sharedpreferences.edit();
if (newAccount == null) {
editor.putString(PREF_USER_TOKEN, null);
editor.putString(PREF_USER_INSTANCE, null);
editor.putString(PREF_USER_ID, null);
editor.apply();
Intent loginActivity = new Intent(activity, LoginActivity.class);
activity.startActivity(loginActivity);
activity.finish();
} else {
editor.putString(PREF_USER_TOKEN, newAccount.token);
editor.putString(PREF_USER_INSTANCE, newAccount.instance);
editor.putString(PREF_USER_ID, newAccount.user_id);
BaseMainActivity.currentUserID = newAccount.user_id;
BaseMainActivity.currentToken = newAccount.token;
BaseMainActivity.currentInstance = newAccount.instance;
editor.apply();
Intent changeAccount = new Intent(activity, MainActivity.class);
changeAccount.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
activity.startActivity(changeAccount);
}
}
private static BaseAccount currentAccount;
/**
* Converts dp to pixel
@ -910,31 +850,66 @@ public class Helper {
}
/**
* Load a profile picture for the account
* Log out the authenticated user by removing its token
*
* @param view ImageView - the view where the image will be loaded
* @param account - {@link Account}
* @param activity Activity
* @param account {@link Account}
* @throws DBException Exception
*/
public static void loadPP(ImageView view, Account account) {
Context context = view.getContext();
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
boolean disableGif = sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_GIF), false);
String targetedUrl = disableGif ? account.mastodon_account.avatar_static : account.mastodon_account.avatar;
if (disableGif || (!targetedUrl.endsWith(".gif"))) {
Glide.with(view.getContext())
.asDrawable()
.load(targetedUrl)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(view);
} else {
Glide.with(view.getContext())
.asGif()
.load(targetedUrl)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(view);
public static void removeAccount(Activity activity, BaseAccount account) throws DBException {
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
//Current user
String userId = sharedpreferences.getString(PREF_USER_ID, null);
String instance = sharedpreferences.getString(PREF_USER_INSTANCE, null);
Account accountDB = new Account(activity);
boolean accountRemovedIsLogged = false;
//Remove the current account
if (account == null) {
account = accountDB.getUniqAccount(userId, instance);
accountRemovedIsLogged = true;
}
if (account != null) {
BaseAccount finalAccount = account;
OauthVM oauthVM = new ViewModelProvider((ViewModelStoreOwner) activity).get(OauthVM.class);
//Revoke the token
oauthVM.revokeToken(account.instance, account.token, account.client_id, account.client_secret);
//Revoke token and remove user
new Thread(() -> {
try {
accountDB.removeUser(finalAccount);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
}
//If the account removed is not the logged one, no need to log out the current user
if (!accountRemovedIsLogged) {
return;
}
//Log out the current user
BaseAccount newAccount = accountDB.getLastUsedAccount();
SharedPreferences.Editor editor = sharedpreferences.edit();
if (newAccount == null) {
editor.putString(PREF_USER_TOKEN, null);
editor.putString(PREF_USER_INSTANCE, null);
editor.putString(PREF_USER_ID, null);
editor.apply();
Intent loginActivity = new Intent(activity, LoginActivity.class);
activity.startActivity(loginActivity);
activity.finish();
} else {
editor.putString(PREF_USER_TOKEN, newAccount.token);
editor.putString(PREF_USER_INSTANCE, newAccount.instance);
editor.putString(PREF_USER_ID, newAccount.user_id);
BaseMainActivity.currentUserID = newAccount.user_id;
BaseMainActivity.currentToken = newAccount.token;
BaseMainActivity.currentInstance = newAccount.instance;
editor.apply();
Intent changeAccount = new Intent(activity, MainActivity.class);
changeAccount.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
activity.startActivity(changeAccount);
}
}
/**
@ -1045,154 +1020,31 @@ public class Helper {
}
/**
* Sends notification with intent
* Load a profile picture for the account
*
* @param context Context
* @param intent Intent associated to the notifcation
* @param icon Bitmap profile picture
* @param title String title of the notification
* @param message String message for the notification
* @param view ImageView - the view where the image will be loaded
* @param account - {@link Account}
*/
@SuppressLint("UnspecifiedImmutableFlag")
public static void notify_user(Context context, int notificationId, Account account, Intent intent, Bitmap icon, NotifType notifType, String title, String message) {
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
// prepare intent which is triggered if the user click on the notification
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
int requestCode = (int) System.currentTimeMillis();
PendingIntent pIntent;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
pIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);
public static void loadPP(ImageView view, BaseAccount account) {
Context context = view.getContext();
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
boolean disableGif = sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_GIF), false);
String targetedUrl = disableGif ? account.mastodon_account.avatar_static : account.mastodon_account.avatar;
if (disableGif || (!targetedUrl.endsWith(".gif"))) {
Glide.with(view.getContext())
.asDrawable()
.load(targetedUrl)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(view);
} else {
pIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
Glide.with(view.getContext())
.asGif()
.load(targetedUrl)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(view);
}
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// build notification
String channelId;
String channelTitle;
switch (notifType) {
case FAV:
channelId = "channel_favourite";
channelTitle = context.getString(R.string.channel_notif_fav);
break;
case FOLLLOW:
channelId = "channel_follow";
channelTitle = context.getString(R.string.channel_notif_follow);
break;
case MENTION:
channelId = "channel_mention";
channelTitle = context.getString(R.string.channel_notif_mention);
break;
case POLL:
channelId = "channel_poll";
channelTitle = context.getString(R.string.channel_notif_poll);
break;
case BACKUP:
channelId = "channel_backup";
channelTitle = context.getString(R.string.channel_notif_backup);
break;
case STORE:
channelId = "channel_store";
channelTitle = context.getString(R.string.channel_notif_media);
break;
case TOOT:
channelId = "channel_status";
channelTitle = context.getString(R.string.channel_notif_status);
break;
default:
channelId = "channel_boost";
channelTitle = context.getString(R.string.channel_notif_boost);
}
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_notification).setTicker(message)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true);
if (notifType == NotifType.MENTION) {
if (message.length() > 500) {
message = message.substring(0, 499) + "";
}
notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
}
notificationBuilder.setGroup(account.mastodon_account.acct + "@" + account.instance)
.setContentIntent(pIntent)
.setContentText(message);
int ledColour = Color.BLUE;
int prefColor;
try {
prefColor = sharedpreferences.getInt(context.getString(R.string.SET_LED_COLOUR_VAL), LED_COLOUR);
} catch (ClassCastException e) {
prefColor = Integer.parseInt(sharedpreferences.getString(context.getString(R.string.SET_LED_COLOUR_VAL), String.valueOf(LED_COLOUR)));
}
switch (prefColor) {
case 0: // BLUE
ledColour = Color.BLUE;
break;
case 1: // CYAN
ledColour = Color.CYAN;
break;
case 2: // MAGENTA
ledColour = Color.MAGENTA;
break;
case 3: // GREEN
ledColour = Color.GREEN;
break;
case 4: // RED
ledColour = Color.RED;
break;
case 5: // YELLOW
ledColour = Color.YELLOW;
break;
case 6: // WHITE
ledColour = Color.WHITE;
break;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel;
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_SILENT), false)) {
channel = new NotificationChannel(channelId, channelTitle, NotificationManager.IMPORTANCE_LOW);
channel.setSound(null, null);
channel.setVibrationPattern(new long[]{500, 500, 500});
channel.enableVibration(true);
channel.setLightColor(ledColour);
} else {
channel = new NotificationChannel(channelId, channelTitle, NotificationManager.IMPORTANCE_DEFAULT);
String soundUri = sharedpreferences.getString(context.getString(R.string.SET_NOTIF_SOUND), ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.boop);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setSound(Uri.parse(soundUri), audioAttributes);
}
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(channel);
} else {
if (sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_SILENT), false)) {
notificationBuilder.setVibrate(new long[]{500, 500, 500});
} else {
String soundUri = sharedpreferences.getString(context.getString(R.string.SET_NOTIF_SOUND), ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.boop);
notificationBuilder.setSound(Uri.parse(soundUri));
}
notificationBuilder.setLights(ledColour, 500, 1000);
}
notificationBuilder.setContentTitle(title);
notificationBuilder.setLargeIcon(icon);
notificationManager.notify(notificationId, notificationBuilder.build());
Notification summaryNotification =
new NotificationCompat.Builder(context, channelId)
.setContentTitle(title)
.setContentText(channelTitle)
.setContentIntent(pIntent)
.setLargeIcon(icon)
.setSmallIcon(R.drawable.ic_notification)
.setGroup(account.mastodon_account.acct + "@" + account.instance)
.setGroupSummary(true)
.build();
notificationManager.notify(notificationId, summaryNotification);
}
/**
@ -1547,7 +1399,156 @@ public class Helper {
void onAttachmentCopied(Attachment attachment);
}
private static WeakReference<Account> currentAccount;
/**
* Sends notification with intent
*
* @param context Context
* @param intent Intent associated to the notifcation
* @param icon Bitmap profile picture
* @param title String title of the notification
* @param message String message for the notification
*/
@SuppressLint("UnspecifiedImmutableFlag")
public static void notify_user(Context context, int notificationId, BaseAccount account, Intent intent, Bitmap icon, NotifType notifType, String title, String message) {
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
// prepare intent which is triggered if the user click on the notification
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
int requestCode = (int) System.currentTimeMillis();
PendingIntent pIntent;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
pIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);
} else {
pIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
}
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP);
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// build notification
String channelId;
String channelTitle;
switch (notifType) {
case FAV:
channelId = "channel_favourite";
channelTitle = context.getString(R.string.channel_notif_fav);
break;
case FOLLLOW:
channelId = "channel_follow";
channelTitle = context.getString(R.string.channel_notif_follow);
break;
case MENTION:
channelId = "channel_mention";
channelTitle = context.getString(R.string.channel_notif_mention);
break;
case POLL:
channelId = "channel_poll";
channelTitle = context.getString(R.string.channel_notif_poll);
break;
case BACKUP:
channelId = "channel_backup";
channelTitle = context.getString(R.string.channel_notif_backup);
break;
case STORE:
channelId = "channel_store";
channelTitle = context.getString(R.string.channel_notif_media);
break;
case TOOT:
channelId = "channel_status";
channelTitle = context.getString(R.string.channel_notif_status);
break;
default:
channelId = "channel_boost";
channelTitle = context.getString(R.string.channel_notif_boost);
}
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_notification).setTicker(message)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true);
if (notifType == NotifType.MENTION) {
if (message.length() > 500) {
message = message.substring(0, 499) + "";
}
notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
}
notificationBuilder.setGroup(account.mastodon_account.acct + "@" + account.instance)
.setContentIntent(pIntent)
.setContentText(message);
int ledColour = Color.BLUE;
int prefColor;
try {
prefColor = sharedpreferences.getInt(context.getString(R.string.SET_LED_COLOUR_VAL), LED_COLOUR);
} catch (ClassCastException e) {
prefColor = Integer.parseInt(sharedpreferences.getString(context.getString(R.string.SET_LED_COLOUR_VAL), String.valueOf(LED_COLOUR)));
}
switch (prefColor) {
case 0: // BLUE
ledColour = Color.BLUE;
break;
case 1: // CYAN
ledColour = Color.CYAN;
break;
case 2: // MAGENTA
ledColour = Color.MAGENTA;
break;
case 3: // GREEN
ledColour = Color.GREEN;
break;
case 4: // RED
ledColour = Color.RED;
break;
case 5: // YELLOW
ledColour = Color.YELLOW;
break;
case 6: // WHITE
ledColour = Color.WHITE;
break;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel;
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_SILENT), false)) {
channel = new NotificationChannel(channelId, channelTitle, NotificationManager.IMPORTANCE_LOW);
channel.setSound(null, null);
channel.setVibrationPattern(new long[]{500, 500, 500});
channel.enableVibration(true);
channel.setLightColor(ledColour);
} else {
channel = new NotificationChannel(channelId, channelTitle, NotificationManager.IMPORTANCE_DEFAULT);
String soundUri = sharedpreferences.getString(context.getString(R.string.SET_NOTIF_SOUND), ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.boop);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setSound(Uri.parse(soundUri), audioAttributes);
}
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(channel);
} else {
if (sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_SILENT), false)) {
notificationBuilder.setVibrate(new long[]{500, 500, 500});
} else {
String soundUri = sharedpreferences.getString(context.getString(R.string.SET_NOTIF_SOUND), ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.boop);
notificationBuilder.setSound(Uri.parse(soundUri));
}
notificationBuilder.setLights(ledColour, 500, 1000);
}
notificationBuilder.setContentTitle(title);
notificationBuilder.setLargeIcon(icon);
notificationManager.notify(notificationId, notificationBuilder.build());
Notification summaryNotification =
new NotificationCompat.Builder(context, channelId)
.setContentTitle(title)
.setContentText(channelTitle)
.setContentIntent(pIntent)
.setLargeIcon(icon)
.setSmallIcon(R.drawable.ic_notification)
.setGroup(account.mastodon_account.acct + "@" + account.instance)
.setGroupSummary(true)
.build();
notificationManager.notify(notificationId, summaryNotification);
}
public static void transfertIfExist(Context context) {
@ -1614,23 +1615,15 @@ public class Helper {
return "@fedilab_fetch_more_" + uuid;
}
public static void setMastodonAccount(app.fedilab.android.client.entities.api.Account mastodon_account) {
if (currentAccount != null) {
currentAccount.get().mastodon_account = mastodon_account;
}
}
public static Account getCurrentAccount(Context context) {
if (currentAccount == null || currentAccount.get() == null || currentAccount.get().mastodon_account == null) {
public static BaseAccount getCurrentAccount(Context context) {
if (currentAccount == null) {
try {
Account account = new Account(context).getUniqAccount(MainActivity.currentUserID, MainActivity.currentInstance);
currentAccount = new WeakReference<>(account);
currentAccount.get().mastodon_account = account.mastodon_account;
currentAccount = new Account(context).getUniqAccount(MainActivity.currentUserID, MainActivity.currentInstance);
} catch (DBException e) {
e.printStackTrace();
}
}
return currentAccount.get();
return currentAccount;
}
public static class CacheTask {

View file

@ -53,6 +53,7 @@ import app.fedilab.android.client.endpoints.MastodonNotificationsService;
import app.fedilab.android.client.entities.api.Notification;
import app.fedilab.android.client.entities.api.Notifications;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.exception.DBException;
import okhttp3.OkHttpClient;
import retrofit2.Call;
@ -70,7 +71,7 @@ public class NotificationsHelper {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context);
String[] slugArray = slug.split("@");
Account accountDb = new Account(context).getUniqAccount(slugArray[0], slugArray[1]);
BaseAccount accountDb = new Account(context).getUniqAccount(slugArray[0], slugArray[1]);
if (accountDb == null) {
return;
}
@ -147,7 +148,7 @@ public class NotificationsHelper {
return retrofit.create(MastodonNotificationsService.class);
}
public static void onRetrieveNotifications(Context context, Notifications newNotifications, final Account account) {
public static void onRetrieveNotifications(Context context, Notifications newNotifications, final BaseAccount account) {
List<Notification> notificationsReceived = newNotifications.notifications;
if (notificationsReceived == null || notificationsReceived.size() == 0 || account == null)
return;

View file

@ -38,6 +38,7 @@ import java.util.concurrent.TimeUnit;
import app.fedilab.android.R;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.jobs.NotificationsWorker;
public class PushHelper {
@ -49,7 +50,7 @@ public class PushHelper {
switch (typeOfNotification) {
case "PUSH_NOTIFICATIONS":
new Thread(() -> {
List<Account> accounts = new Account(context).getPushNotificationAccounts();
List<BaseAccount> accounts = new Account(context).getPushNotificationAccounts();
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> {
List<String> distributors = UnifiedPush.getDistributors(context, new ArrayList<>());
@ -84,8 +85,8 @@ public class PushHelper {
break;
case "REPEAT_NOTIFICATIONS":
new Thread(() -> {
List<Account> accounts = new Account(context).getPushNotificationAccounts();
for (Account account : accounts) {
List<BaseAccount> accounts = new Account(context).getPushNotificationAccounts();
for (BaseAccount account : accounts) {
((Activity) context).runOnUiThread(() -> {
UnifiedPush.unregisterApp(context, account.user_id + "@" + account.instance);
});
@ -98,8 +99,8 @@ public class PushHelper {
case "NO_NOTIFICATIONS":
WorkManager.getInstance(context).cancelAllWorkByTag(Helper.WORKER_REFRESH_NOTIFICATION);
new Thread(() -> {
List<Account> accounts = new Account(context).getPushNotificationAccounts();
for (Account account : accounts) {
List<BaseAccount> accounts = new Account(context).getPushNotificationAccounts();
for (BaseAccount account : accounts) {
((Activity) context).runOnUiThread(() -> {
UnifiedPush.unregisterApp(context, account.user_id + "@" + account.instance);
});
@ -110,7 +111,7 @@ public class PushHelper {
}
private static void registerAppWithDialog(Context context, List<Account> accounts) {
private static void registerAppWithDialog(Context context, List<BaseAccount> accounts) {
if (accounts == null) {
return;
}
@ -119,7 +120,7 @@ public class PushHelper {
if (distributors.size() == 1) {
UnifiedPush.saveDistributor(context, distributors.get(0));
}
for (Account account : accounts) {
for (BaseAccount account : accounts) {
UnifiedPush.registerApp(context, account.user_id + "@" + account.instance, new ArrayList<>(), "");
}
return;
@ -131,7 +132,7 @@ public class PushHelper {
alert.setSingleChoiceItems(distributorsStr, -1, (dialog, item) -> {
String distributor = distributorsStr[item];
UnifiedPush.saveDistributor(context, distributor);
for (Account account : accounts) {
for (BaseAccount account : accounts) {
UnifiedPush.registerApp(context, account.user_id + "@" + account.instance, new ArrayList<>(), "");
}
dialog.dismiss();

View file

@ -35,6 +35,7 @@ import app.fedilab.android.R;
import app.fedilab.android.client.endpoints.MastodonNotificationsService;
import app.fedilab.android.client.entities.api.PushSubscription;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.exception.DBException;
import okhttp3.OkHttpClient;
import retrofit2.Call;
@ -79,7 +80,7 @@ public class PushNotifications {
ECDH finalEcdh = ecdh;
new Thread(() -> {
String[] slugArray = slug.split("@");
Account accountDb = null;
BaseAccount accountDb = null;
try {
accountDb = new Account(context).getUniqAccount(slugArray[0], slugArray[1]);
} catch (DBException e) {

View file

@ -45,6 +45,7 @@ import app.fedilab.android.client.entities.api.Poll;
import app.fedilab.android.client.entities.api.ScheduledStatus;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.client.entities.app.PostState;
import app.fedilab.android.client.entities.app.StatusDraft;
import app.fedilab.android.exception.DBException;
@ -141,7 +142,7 @@ public class PostMessageService extends IntentService {
}
if (watermarkText == null) {
try {
Account account = new Account(context).getAccountByToken(dataPost.token);
BaseAccount account = new Account(context).getAccountByToken(dataPost.token);
watermarkText = account.mastodon_account.username + "@" + account.instance;
} catch (DBException e) {
e.printStackTrace();

View file

@ -91,7 +91,7 @@ import app.fedilab.android.client.entities.api.Mention;
import app.fedilab.android.client.entities.api.Poll;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.api.Tag;
import app.fedilab.android.client.entities.app.Account;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.client.entities.app.StatusDraft;
import app.fedilab.android.databinding.ComposeAttachmentItemBinding;
import app.fedilab.android.databinding.ComposePollBinding;
@ -122,7 +122,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
"..--..", ".-.-.-", ".----.",};
private final List<Status> statusList;
private final int TYPE_NORMAL = 0;
private final Account account;
private final BaseAccount account;
private final String visibility;
private final app.fedilab.android.client.entities.api.Account mentionedAccount;
public ManageDrafts manageDrafts;
@ -130,7 +130,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
private Context context;
private AlertDialog alertDialogEmoji;
public ComposeAdapter(List<Status> statusList, int statusCount, Account account, app.fedilab.android.client.entities.api.Account mentionedAccount, String visibility) {
public ComposeAdapter(List<Status> statusList, int statusCount, BaseAccount account, app.fedilab.android.client.entities.api.Account mentionedAccount, String visibility) {
this.statusList = statusList;
this.statusCount = statusCount;
this.account = account;
@ -1210,8 +1210,13 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
} else {
ImageViewCompat.setImageTintList(holder.binding.buttonPoll, null);
}
holder.binding.buttonPost.setEnabled(!statusDraft.submitted);
holder.binding.buttonPost.setOnClickListener(v -> manageDrafts.onSubmit(prepareDraft(statusList, this, account.instance, account.user_id)));
holder.binding.buttonPost.setOnClickListener(v -> {
statusDraft.submitted = true;
notifyItemChanged(position);
manageDrafts.onSubmit(prepareDraft(statusList, this, account.instance, account.user_id));
});
}
}

View file

@ -44,6 +44,7 @@ import app.fedilab.android.client.entities.api.Poll;
import app.fedilab.android.client.entities.api.ScheduledStatus;
import app.fedilab.android.client.entities.api.ScheduledStatuses;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.client.entities.app.QuickLoad;
import app.fedilab.android.client.entities.app.StatusCache;
import app.fedilab.android.exception.DBException;
@ -322,7 +323,7 @@ public class StatusesVM extends AndroidViewModel {
}
//The status must also be deleted in cache
try {
app.fedilab.android.client.entities.app.Account account = new app.fedilab.android.client.entities.app.Account(getApplication().getApplicationContext()).getAccountByToken(token);
BaseAccount account = new app.fedilab.android.client.entities.app.Account(getApplication().getApplicationContext()).getAccountByToken(token);
new StatusCache(getApplication().getApplicationContext()).deleteStatus(id, account.instance);
new QuickLoad(getApplication().getApplicationContext()).deleteStatus(account, id);
} catch (DBException e) {

View file

@ -40,6 +40,7 @@ import app.fedilab.android.client.entities.api.MastodonList;
import app.fedilab.android.client.entities.api.Pagination;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.api.Statuses;
import app.fedilab.android.client.entities.app.BaseAccount;
import app.fedilab.android.client.entities.app.StatusCache;
import app.fedilab.android.client.entities.app.StatusDraft;
import app.fedilab.android.exception.DBException;
@ -286,7 +287,7 @@ public class TimelinesVM extends AndroidViewModel {
* @param account app.fedilab.android.client.entities.app.Account
* @return LiveData<ist < StatusDraft>>
*/
public LiveData<List<StatusDraft>> getDrafts(app.fedilab.android.client.entities.app.Account account) {
public LiveData<List<StatusDraft>> getDrafts(BaseAccount account) {
statusDraftListMutableLiveData = new MutableLiveData<>();
new Thread(() -> {
List<StatusDraft> statusCacheDAO = null;

View file

@ -27,7 +27,7 @@
app:title="@string/embedded_browser" />
<SwitchPreferenceCompat
app:defaultValue="false"
app:defaultValue="true"
app:iconSpaceReserved="false"
app:key="@string/SET_SEND_CRASH_REPORTS"
app:singleLineTitle="false"