|
|
|
|
@@ -2,21 +2,18 @@ package org.joinmastodon.android.ui;
|
|
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint;
|
|
|
|
|
import android.app.Activity;
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.app.ProgressDialog;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.content.res.ColorStateList;
|
|
|
|
|
import android.graphics.drawable.Animatable;
|
|
|
|
|
import android.graphics.drawable.ColorDrawable;
|
|
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
|
|
import android.os.Build;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
|
import android.view.WindowInsets;
|
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
import android.widget.ImageButton;
|
|
|
|
|
import android.widget.ImageView;
|
|
|
|
|
import android.widget.PopupMenu;
|
|
|
|
|
import android.widget.RadioButton;
|
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
|
|
|
|
import org.joinmastodon.android.GlobalUserPreferences;
|
|
|
|
|
@@ -25,14 +22,18 @@ import org.joinmastodon.android.R;
|
|
|
|
|
import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken;
|
|
|
|
|
import org.joinmastodon.android.api.session.AccountSession;
|
|
|
|
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
|
|
|
|
import org.joinmastodon.android.fragments.HomeFragment;
|
|
|
|
|
import org.joinmastodon.android.fragments.SplashFragment;
|
|
|
|
|
import org.joinmastodon.android.model.Account;
|
|
|
|
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.DrawableRes;
|
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
|
import androidx.annotation.StringRes;
|
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
|
|
|
import me.grishka.appkit.Nav;
|
|
|
|
|
import me.grishka.appkit.api.Callback;
|
|
|
|
|
@@ -52,13 +53,15 @@ import me.grishka.appkit.views.UsableRecyclerView;
|
|
|
|
|
|
|
|
|
|
public class AccountSwitcherSheet extends BottomSheet{
|
|
|
|
|
private final Activity activity;
|
|
|
|
|
private final HomeFragment fragment;
|
|
|
|
|
private UsableRecyclerView list;
|
|
|
|
|
private List<WrappedAccount> accounts;
|
|
|
|
|
private ListImageLoaderWrapper imgLoader;
|
|
|
|
|
|
|
|
|
|
public AccountSwitcherSheet(@NonNull Activity activity){
|
|
|
|
|
public AccountSwitcherSheet(@NonNull Activity activity, @Nullable HomeFragment fragment){
|
|
|
|
|
super(activity);
|
|
|
|
|
this.activity=activity;
|
|
|
|
|
this.fragment=fragment;
|
|
|
|
|
|
|
|
|
|
accounts=AccountSessionManager.getInstance().getLoggedInAccounts().stream().map(WrappedAccount::new).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
@@ -70,41 +73,42 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|
|
|
|
MergeRecyclerAdapter adapter=new MergeRecyclerAdapter();
|
|
|
|
|
View handle=new View(activity);
|
|
|
|
|
handle.setBackgroundResource(R.drawable.bg_bottom_sheet_handle);
|
|
|
|
|
handle.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(36)));
|
|
|
|
|
adapter.addAdapter(new SingleViewRecyclerAdapter(handle));
|
|
|
|
|
adapter.addAdapter(new AccountsAdapter());
|
|
|
|
|
AccountViewHolder holder=new AccountViewHolder();
|
|
|
|
|
holder.more.setVisibility(View.GONE);
|
|
|
|
|
holder.currentIcon.setVisibility(View.GONE);
|
|
|
|
|
holder.name.setText(R.string.add_account);
|
|
|
|
|
holder.avatar.setScaleType(ImageView.ScaleType.CENTER);
|
|
|
|
|
holder.avatar.setImageResource(R.drawable.ic_fluent_add_circle_24_filled);
|
|
|
|
|
holder.avatar.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(activity, android.R.attr.textColorPrimary)));
|
|
|
|
|
adapter.addAdapter(new ClickableSingleViewRecyclerAdapter(holder.itemView, ()->{
|
|
|
|
|
adapter.addAdapter(new ClickableSingleViewRecyclerAdapter(makeSimpleListItem(R.string.add_account, R.drawable.ic_add_24px), ()->{
|
|
|
|
|
Nav.go(activity, SplashFragment.class, null);
|
|
|
|
|
dismiss();
|
|
|
|
|
}));
|
|
|
|
|
adapter.addAdapter(new ClickableSingleViewRecyclerAdapter(makeSimpleListItem(R.string.log_out_all_accounts, R.drawable.ic_logout_24px), this::confirmLogOutAll));
|
|
|
|
|
|
|
|
|
|
list.setAdapter(adapter);
|
|
|
|
|
DividerItemDecoration divider=new DividerItemDecoration(activity, R.attr.colorPollVoted, .5f, 72, 16, DividerItemDecoration.NOT_FIRST);
|
|
|
|
|
divider.setDrawBelowLastItem(true);
|
|
|
|
|
list.addItemDecoration(divider);
|
|
|
|
|
|
|
|
|
|
FrameLayout content=new FrameLayout(activity);
|
|
|
|
|
content.setBackgroundResource(R.drawable.bg_bottom_sheet);
|
|
|
|
|
content.addView(list);
|
|
|
|
|
setContentView(content);
|
|
|
|
|
setNavigationBarBackground(new ColorDrawable(UiUtils.getThemeColor(activity, R.attr.colorWindowBackground)), !UiUtils.isDarkTheme());
|
|
|
|
|
setNavigationBarBackground(new ColorDrawable(UiUtils.alphaBlendColors(UiUtils.getThemeColor(activity, R.attr.colorM3Surface),
|
|
|
|
|
UiUtils.getThemeColor(activity, R.attr.colorM3Primary), 0.05f)), !UiUtils.isDarkTheme());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void confirmLogOut(String accountID){
|
|
|
|
|
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
|
|
|
|
new M3AlertDialogBuilder(activity)
|
|
|
|
|
.setTitle(R.string.log_out)
|
|
|
|
|
.setMessage(R.string.confirm_log_out)
|
|
|
|
|
.setMessage(activity.getString(R.string.confirm_log_out, session.getFullUsername()))
|
|
|
|
|
.setPositiveButton(R.string.log_out, (dialog, which) -> logOut(accountID))
|
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
|
.show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void confirmLogOutAll(){
|
|
|
|
|
new M3AlertDialogBuilder(activity)
|
|
|
|
|
.setMessage(R.string.confirm_log_out_all_accounts)
|
|
|
|
|
.setPositiveButton(R.string.log_out, (dialog, which) -> logOutAll())
|
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
|
.show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void logOut(String accountID){
|
|
|
|
|
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
|
|
|
|
new RevokeOauthToken(session.app.clientId, session.app.clientSecret, session.token.accessToken)
|
|
|
|
|
@@ -123,6 +127,41 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|
|
|
|
.exec(accountID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void logOutAll(){
|
|
|
|
|
final ProgressDialog progress=new ProgressDialog(activity);
|
|
|
|
|
progress.setMessage(activity.getString(R.string.loading));
|
|
|
|
|
progress.setCancelable(false);
|
|
|
|
|
progress.show();
|
|
|
|
|
ArrayList<AccountSession> sessions=new ArrayList<>(AccountSessionManager.getInstance().getLoggedInAccounts());
|
|
|
|
|
for(AccountSession session:sessions){
|
|
|
|
|
new RevokeOauthToken(session.app.clientId, session.app.clientSecret, session.token.accessToken)
|
|
|
|
|
.setCallback(new Callback<>(){
|
|
|
|
|
@Override
|
|
|
|
|
public void onSuccess(Object result){
|
|
|
|
|
AccountSessionManager.getInstance().removeAccount(session.getID());
|
|
|
|
|
sessions.remove(session);
|
|
|
|
|
if(sessions.isEmpty()){
|
|
|
|
|
progress.dismiss();
|
|
|
|
|
Nav.goClearingStack(activity, SplashFragment.class, null);
|
|
|
|
|
dismiss();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onError(ErrorResponse error){
|
|
|
|
|
AccountSessionManager.getInstance().removeAccount(session.getID());
|
|
|
|
|
sessions.remove(session);
|
|
|
|
|
if(sessions.isEmpty()){
|
|
|
|
|
progress.dismiss();
|
|
|
|
|
Nav.goClearingStack(activity, SplashFragment.class, null);
|
|
|
|
|
dismiss();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.exec(session.getID());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onLoggedOut(String accountID){
|
|
|
|
|
AccountSessionManager.getInstance().removeAccount(accountID);
|
|
|
|
|
dismiss();
|
|
|
|
|
@@ -143,6 +182,13 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private View makeSimpleListItem(@StringRes int title, @DrawableRes int icon){
|
|
|
|
|
TextView tv=(TextView) activity.getLayoutInflater().inflate(R.layout.item_text_with_icon, list, false);
|
|
|
|
|
tv.setText(title);
|
|
|
|
|
tv.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, 0, 0, 0);
|
|
|
|
|
return tv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class AccountsAdapter extends UsableRecyclerView.Adapter<AccountViewHolder> implements ImageLoaderRecyclerAdapter{
|
|
|
|
|
public AccountsAdapter(){
|
|
|
|
|
super(imgLoader);
|
|
|
|
|
@@ -176,45 +222,27 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class AccountViewHolder extends BindableViewHolder<AccountSession> implements ImageLoaderViewHolder, UsableRecyclerView.Clickable{
|
|
|
|
|
private final TextView name;
|
|
|
|
|
private class AccountViewHolder extends BindableViewHolder<AccountSession> implements ImageLoaderViewHolder, UsableRecyclerView.Clickable, UsableRecyclerView.LongClickable{
|
|
|
|
|
private final TextView name, username;
|
|
|
|
|
private final ImageView avatar;
|
|
|
|
|
private final ImageButton more;
|
|
|
|
|
private final View currentIcon;
|
|
|
|
|
private final PopupMenu menu;
|
|
|
|
|
private final RadioButton radioButton;
|
|
|
|
|
|
|
|
|
|
public AccountViewHolder(){
|
|
|
|
|
super(activity, R.layout.item_account_switcher, list);
|
|
|
|
|
name=findViewById(R.id.name);
|
|
|
|
|
username=findViewById(R.id.username);
|
|
|
|
|
radioButton=findViewById(R.id.radiobtn);
|
|
|
|
|
avatar=findViewById(R.id.avatar);
|
|
|
|
|
more=findViewById(R.id.more);
|
|
|
|
|
currentIcon=findViewById(R.id.current);
|
|
|
|
|
|
|
|
|
|
avatar.setOutlineProvider(OutlineProviders.roundedRect(12));
|
|
|
|
|
avatar.setOutlineProvider(OutlineProviders.roundedRect(OutlineProviders.RADIUS_MEDIUM));
|
|
|
|
|
avatar.setClipToOutline(true);
|
|
|
|
|
|
|
|
|
|
menu=new PopupMenu(activity, more);
|
|
|
|
|
menu.inflate(R.menu.account_switcher);
|
|
|
|
|
menu.setOnMenuItemClickListener(item1 -> {
|
|
|
|
|
confirmLogOut(item.getID());
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
more.setOnClickListener(v->menu.show());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
|
|
@Override
|
|
|
|
|
public void onBind(AccountSession item){
|
|
|
|
|
name.setText("@"+item.self.username+"@"+item.domain);
|
|
|
|
|
if(AccountSessionManager.getInstance().getLastActiveAccountID().equals(item.getID())){
|
|
|
|
|
more.setVisibility(View.GONE);
|
|
|
|
|
currentIcon.setVisibility(View.VISIBLE);
|
|
|
|
|
}else{
|
|
|
|
|
more.setVisibility(View.VISIBLE);
|
|
|
|
|
currentIcon.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
menu.getMenu().findItem(R.id.log_out).setTitle(activity.getString(R.string.log_out_account, "@"+item.self.username));
|
|
|
|
|
UiUtils.enablePopupMenuIcons(activity, menu);
|
|
|
|
|
name.setText(item.self.displayName);
|
|
|
|
|
username.setText(item.getFullUsername());
|
|
|
|
|
radioButton.setChecked(AccountSessionManager.getInstance().getLastActiveAccountID().equals(item.getID()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@@ -231,10 +259,23 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onClick(){
|
|
|
|
|
if(AccountSessionManager.getInstance().getLastActiveAccountID().equals(item.getID())){
|
|
|
|
|
dismiss();
|
|
|
|
|
if(fragment!=null){
|
|
|
|
|
fragment.setCurrentTab(R.id.tab_profile);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
AccountSessionManager.getInstance().setLastActiveAccountID(item.getID());
|
|
|
|
|
activity.finish();
|
|
|
|
|
activity.startActivity(new Intent(activity, MainActivity.class));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onLongClick(){
|
|
|
|
|
confirmLogOut(item.getID());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static class WrappedAccount{
|
|
|
|
|
|