Browse Source
Convert AccountSwitcher dialog to a DialogFragment as the AlertDialog was causing a leak (detected by LeakCanary)
renovate/org.robolectric-robolectric-4.x
Convert AccountSwitcher dialog to a DialogFragment as the AlertDialog was causing a leak (detected by LeakCanary)
renovate/org.robolectric-robolectric-4.x
Ammar Githam
4 years ago
4 changed files with 224 additions and 132 deletions
-
64app/src/main/java/awais/instagrabber/adapters/AccountSwitcherAdapter.java
-
152app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java
-
111app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java
-
29app/src/main/res/layout/dialog_account_switcher.xml
@ -0,0 +1,152 @@ |
|||
package awais.instagrabber.dialogs; |
|||
|
|||
import android.app.Dialog; |
|||
import android.content.Context; |
|||
import android.os.Bundle; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.view.Window; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.annotation.Nullable; |
|||
import androidx.appcompat.app.AlertDialog; |
|||
import androidx.fragment.app.DialogFragment; |
|||
import androidx.fragment.app.FragmentActivity; |
|||
import androidx.recyclerview.widget.LinearLayoutManager; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
|
|||
import awais.instagrabber.R; |
|||
import awais.instagrabber.adapters.AccountSwitcherAdapter; |
|||
import awais.instagrabber.databinding.DialogAccountSwitcherBinding; |
|||
import awais.instagrabber.utils.Constants; |
|||
import awais.instagrabber.utils.CookieUtils; |
|||
import awais.instagrabber.utils.DataBox; |
|||
import awais.instagrabber.utils.TextUtils; |
|||
import awais.instagrabber.utils.Utils; |
|||
|
|||
import static awais.instagrabber.utils.Utils.settingsHelper; |
|||
|
|||
public class AccountSwitcherDialogFragment extends DialogFragment { |
|||
|
|||
private final OnAddAccountClickListener onAddAccountClickListener; |
|||
private DialogAccountSwitcherBinding binding; |
|||
|
|||
private final AccountSwitcherAdapter.OnAccountClickListener accountClickListener = (model, isCurrent) -> { |
|||
if (isCurrent) { |
|||
dismiss(); |
|||
return; |
|||
} |
|||
CookieUtils.setupCookies(model.getCookie()); |
|||
settingsHelper.putString(Constants.COOKIE, model.getCookie()); |
|||
final FragmentActivity activity = getActivity(); |
|||
if (activity != null) activity.recreate(); |
|||
dismiss(); |
|||
}; |
|||
|
|||
private final AccountSwitcherAdapter.OnAccountLongClickListener accountLongClickListener = (model, isCurrent) -> { |
|||
final Context context = getContext(); |
|||
if (context == null) return false; |
|||
if (isCurrent) { |
|||
new AlertDialog.Builder(context) |
|||
.setMessage(R.string.quick_access_cannot_delete_curr) |
|||
.setPositiveButton(R.string.ok, null) |
|||
.show(); |
|||
return true; |
|||
} |
|||
new AlertDialog.Builder(context) |
|||
.setMessage(getString(R.string.quick_access_confirm_delete, model.getUsername())) |
|||
.setPositiveButton(R.string.yes, (dialog, which) -> { |
|||
Utils.dataBox.delUserCookie(model); |
|||
dismiss(); |
|||
}) |
|||
.setNegativeButton(R.string.cancel, null) |
|||
.show(); |
|||
dismiss(); |
|||
return true; |
|||
}; |
|||
|
|||
public AccountSwitcherDialogFragment(final OnAddAccountClickListener onAddAccountClickListener) { |
|||
this.onAddAccountClickListener = onAddAccountClickListener; |
|||
} |
|||
|
|||
@Override |
|||
public View onCreateView(@NonNull final LayoutInflater inflater, |
|||
final ViewGroup container, |
|||
final Bundle savedInstanceState) { |
|||
binding = DialogAccountSwitcherBinding.inflate(inflater, container, false); |
|||
binding.accounts.setLayoutManager(new LinearLayoutManager(getContext())); |
|||
return binding.getRoot(); |
|||
} |
|||
|
|||
@Override |
|||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { |
|||
super.onViewCreated(view, savedInstanceState); |
|||
init(); |
|||
} |
|||
|
|||
@Override |
|||
public void onStart() { |
|||
super.onStart(); |
|||
final Dialog dialog = getDialog(); |
|||
if (dialog == null) return; |
|||
final Window window = dialog.getWindow(); |
|||
if (window == null) return; |
|||
final int height = ViewGroup.LayoutParams.WRAP_CONTENT; |
|||
final int width = (int) (Utils.displayMetrics.widthPixels * 0.8); |
|||
window.setLayout(width, height); |
|||
} |
|||
|
|||
private void init() { |
|||
final AccountSwitcherAdapter adapter = new AccountSwitcherAdapter(accountClickListener, accountLongClickListener); |
|||
binding.accounts.setAdapter(adapter); |
|||
final List<DataBox.CookieModel> allUsers = Utils.dataBox.getAllCookies(); |
|||
if (allUsers == null) return; |
|||
final String cookie = settingsHelper.getString(Constants.COOKIE); |
|||
sortUserList(cookie, allUsers); |
|||
adapter.submitList(allUsers); |
|||
binding.addAccountBtn.setOnClickListener(v -> { |
|||
if (onAddAccountClickListener == null) return; |
|||
onAddAccountClickListener.onAddAccountClick(this); |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Sort the user list by following logic: |
|||
* <ol> |
|||
* <li>Keep currently active account at top. |
|||
* <li>Check if any user does not have a full name. |
|||
* <li>If all have full names, sort by full names. |
|||
* <li>Otherwise, sort by the usernames |
|||
* </ol> |
|||
* |
|||
* @param cookie active cookie |
|||
* @param allUsers list of users |
|||
*/ |
|||
private void sortUserList(final String cookie, final List<DataBox.CookieModel> allUsers) { |
|||
boolean sortByName = true; |
|||
for (final DataBox.CookieModel user : allUsers) { |
|||
if (TextUtils.isEmpty(user.getFullName())) { |
|||
sortByName = false; |
|||
break; |
|||
} |
|||
} |
|||
final boolean finalSortByName = sortByName; |
|||
Collections.sort(allUsers, (o1, o2) -> { |
|||
// keep current account at top |
|||
if (o1.getCookie().equals(cookie)) return -1; |
|||
if (finalSortByName) { |
|||
// sort by full name |
|||
return o1.getFullName().compareTo(o2.getFullName()); |
|||
} |
|||
// otherwise sort by username |
|||
return o1.getUsername().compareTo(o2.getUsername()); |
|||
}); |
|||
} |
|||
|
|||
public interface OnAddAccountClickListener { |
|||
void onAddAccountClick(final AccountSwitcherDialogFragment dialogFragment); |
|||
} |
|||
} |
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto" |
|||
xmlns:tools="http://schemas.android.com/tools" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content"> |
|||
|
|||
<androidx.recyclerview.widget.RecyclerView |
|||
android:id="@+id/accounts" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
app:layout_constraintBottom_toTopOf="@id/add_account_btn" |
|||
app:layout_constraintEnd_toEndOf="parent" |
|||
app:layout_constraintStart_toStartOf="parent" |
|||
app:layout_constraintTop_toTopOf="parent" |
|||
tools:itemCount="5" |
|||
tools:listitem="@layout/pref_account_switcher" /> |
|||
|
|||
<com.google.android.material.button.MaterialButton |
|||
android:id="@+id/add_account_btn" |
|||
style="@style/Widget.MaterialComponents.Button.TextButton" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:text="@string/add_account" |
|||
app:icon="@drawable/ic_add" |
|||
app:layout_constraintBottom_toBottomOf="parent" |
|||
app:layout_constraintStart_toStartOf="parent" |
|||
app:layout_constraintTop_toBottomOf="@id/accounts" /> |
|||
</androidx.constraintlayout.widget.ConstraintLayout> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue