Better account switcher
This commit is contained in:
parent
ec38210dde
commit
8059120136
|
@ -58,7 +58,7 @@ dependencies {
|
||||||
implementation 'me.grishka.litex:dynamicanimation:1.1.0-alpha03'
|
implementation 'me.grishka.litex:dynamicanimation:1.1.0-alpha03'
|
||||||
implementation 'me.grishka.litex:viewpager:1.0.0'
|
implementation 'me.grishka.litex:viewpager:1.0.0'
|
||||||
implementation 'me.grishka.litex:viewpager2:1.0.0'
|
implementation 'me.grishka.litex:viewpager2:1.0.0'
|
||||||
implementation 'me.grishka.appkit:appkit:1.2.3'
|
implementation 'me.grishka.appkit:appkit:1.2.4'
|
||||||
implementation 'com.google.code.gson:gson:2.8.9'
|
implementation 'com.google.code.gson:gson:2.8.9'
|
||||||
implementation 'org.jsoup:jsoup:1.14.3'
|
implementation 'org.jsoup:jsoup:1.14.3'
|
||||||
implementation 'com.squareup:otto:1.3.8'
|
implementation 'com.squareup:otto:1.3.8'
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.app.NotificationManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Outline;
|
import android.graphics.Outline;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -17,6 +18,7 @@ import android.view.WindowInsets;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.joinmastodon.android.MainActivity;
|
import org.joinmastodon.android.MainActivity;
|
||||||
import org.joinmastodon.android.MastodonApp;
|
import org.joinmastodon.android.MastodonApp;
|
||||||
|
@ -28,6 +30,7 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.fragments.discover.DiscoverFragment;
|
import org.joinmastodon.android.fragments.discover.DiscoverFragment;
|
||||||
import org.joinmastodon.android.fragments.discover.SearchFragment;
|
import org.joinmastodon.android.fragments.discover.SearchFragment;
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
|
import org.joinmastodon.android.ui.AccountSwitcherSheet;
|
||||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.joinmastodon.android.ui.views.TabBar;
|
import org.joinmastodon.android.ui.views.TabBar;
|
||||||
|
@ -46,6 +49,7 @@ import me.grishka.appkit.fragments.OnBackPressedListener;
|
||||||
import me.grishka.appkit.imageloader.ViewImageLoader;
|
import me.grishka.appkit.imageloader.ViewImageLoader;
|
||||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
import me.grishka.appkit.views.BottomSheet;
|
||||||
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
||||||
|
|
||||||
public class HomeFragment extends AppKitFragment implements OnBackPressedListener{
|
public class HomeFragment extends AppKitFragment implements OnBackPressedListener{
|
||||||
|
@ -238,21 +242,11 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
|
||||||
|
|
||||||
private boolean onTabLongClick(@IdRes int tab){
|
private boolean onTabLongClick(@IdRes int tab){
|
||||||
if(tab==R.id.tab_profile){
|
if(tab==R.id.tab_profile){
|
||||||
ArrayList<String> options=new ArrayList<>();
|
ArrayList<String> options=new ArrayList<>();
|
||||||
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
|
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
|
||||||
options.add(session.self.displayName+"\n("+session.self.username+"@"+session.domain+")");
|
options.add(session.self.displayName+"\n("+session.self.username+"@"+session.domain+")");
|
||||||
}
|
}
|
||||||
new M3AlertDialogBuilder(getActivity())
|
new AccountSwitcherSheet(getActivity()).show();
|
||||||
.setItems(options.toArray(new String[0]), (dialog, which)->{
|
|
||||||
AccountSession session=AccountSessionManager.getInstance().getLoggedInAccounts().get(which);
|
|
||||||
AccountSessionManager.getInstance().setLastActiveAccountID(session.getID());
|
|
||||||
getActivity().finish();
|
|
||||||
getActivity().startActivity(new Intent(getActivity(), MainActivity.class));
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.add_account, (dialog, which)->{
|
|
||||||
Nav.go(getActivity(), SplashFragment.class, null);
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,247 @@
|
||||||
|
package org.joinmastodon.android.ui;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
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.TextView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.MainActivity;
|
||||||
|
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.SplashFragment;
|
||||||
|
import org.joinmastodon.android.model.Account;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import me.grishka.appkit.Nav;
|
||||||
|
import me.grishka.appkit.api.Callback;
|
||||||
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
|
||||||
|
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||||
|
import me.grishka.appkit.imageloader.ListImageLoaderWrapper;
|
||||||
|
import me.grishka.appkit.imageloader.RecyclerViewDelegate;
|
||||||
|
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||||
|
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||||
|
import me.grishka.appkit.utils.BindableViewHolder;
|
||||||
|
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||||
|
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
import me.grishka.appkit.views.BottomSheet;
|
||||||
|
import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
|
|
||||||
|
public class AccountSwitcherSheet extends BottomSheet{
|
||||||
|
private final Activity activity;
|
||||||
|
private UsableRecyclerView list;
|
||||||
|
private List<WrappedAccount> accounts;
|
||||||
|
private ListImageLoaderWrapper imgLoader;
|
||||||
|
|
||||||
|
public AccountSwitcherSheet(@NonNull Activity activity){
|
||||||
|
super(activity);
|
||||||
|
this.activity=activity;
|
||||||
|
|
||||||
|
accounts=AccountSessionManager.getInstance().getLoggedInAccounts().stream().map(WrappedAccount::new).collect(Collectors.toList());
|
||||||
|
|
||||||
|
list=new UsableRecyclerView(activity);
|
||||||
|
imgLoader=new ListImageLoaderWrapper(activity, list, new RecyclerViewDelegate(list), null);
|
||||||
|
list.setClipToPadding(false);
|
||||||
|
list.setLayoutManager(new LinearLayoutManager(activity));
|
||||||
|
|
||||||
|
MergeRecyclerAdapter adapter=new MergeRecyclerAdapter();
|
||||||
|
View handle=new View(activity);
|
||||||
|
handle.setBackgroundResource(R.drawable.bg_bottom_sheet_handle);
|
||||||
|
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, ()->{
|
||||||
|
Nav.go(activity, SplashFragment.class, null);
|
||||||
|
dismiss();
|
||||||
|
}));
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void confirmLogOut(String accountID){
|
||||||
|
new M3AlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.log_out)
|
||||||
|
.setMessage(R.string.confirm_log_out)
|
||||||
|
.setPositiveButton(R.string.log_out, (dialog, which) -> logOut(accountID))
|
||||||
|
.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)
|
||||||
|
.setCallback(new Callback<>(){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Object result){
|
||||||
|
onLoggedOut(accountID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(ErrorResponse error){
|
||||||
|
onLoggedOut(accountID);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.wrapProgress(activity, R.string.loading, false)
|
||||||
|
.exec(accountID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onLoggedOut(String accountID){
|
||||||
|
AccountSessionManager.getInstance().removeAccount(accountID);
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onWindowInsetsUpdated(WindowInsets insets){
|
||||||
|
if(Build.VERSION.SDK_INT>=29){
|
||||||
|
int tappableBottom=insets.getTappableElementInsets().bottom;
|
||||||
|
int insetBottom=insets.getSystemWindowInsetBottom();
|
||||||
|
if(tappableBottom==0 && insetBottom>0){
|
||||||
|
list.setPadding(0, 0, 0, V.dp(48)-insetBottom);
|
||||||
|
}else{
|
||||||
|
list.setPadding(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AccountsAdapter extends UsableRecyclerView.Adapter<AccountViewHolder> implements ImageLoaderRecyclerAdapter{
|
||||||
|
public AccountsAdapter(){
|
||||||
|
super(imgLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public AccountViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||||
|
return new AccountViewHolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount(){
|
||||||
|
return accounts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(AccountViewHolder holder, int position){
|
||||||
|
holder.bind(accounts.get(position).session);
|
||||||
|
super.onBindViewHolder(holder, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getImageCountForItem(int position){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageLoaderRequest getImageRequest(int position, int image){
|
||||||
|
return accounts.get(position).req;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AccountViewHolder extends BindableViewHolder<AccountSession> implements ImageLoaderViewHolder, UsableRecyclerView.Clickable{
|
||||||
|
private final TextView name;
|
||||||
|
private final ImageView avatar;
|
||||||
|
private final ImageButton more;
|
||||||
|
private final View currentIcon;
|
||||||
|
private final PopupMenu menu;
|
||||||
|
|
||||||
|
public AccountViewHolder(){
|
||||||
|
super(activity, R.layout.item_account_switcher, list);
|
||||||
|
name=findViewById(R.id.name);
|
||||||
|
avatar=findViewById(R.id.avatar);
|
||||||
|
more=findViewById(R.id.more);
|
||||||
|
currentIcon=findViewById(R.id.current);
|
||||||
|
|
||||||
|
avatar.setOutlineProvider(OutlineProviders.roundedRect(12));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setImage(int index, Drawable image){
|
||||||
|
avatar.setImageDrawable(image);
|
||||||
|
if(image instanceof Animatable a)
|
||||||
|
a.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearImage(int index){
|
||||||
|
setImage(index, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(){
|
||||||
|
AccountSessionManager.getInstance().setLastActiveAccountID(item.getID());
|
||||||
|
activity.finish();
|
||||||
|
activity.startActivity(new Intent(activity, MainActivity.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WrappedAccount{
|
||||||
|
public final AccountSession session;
|
||||||
|
public final ImageLoaderRequest req;
|
||||||
|
|
||||||
|
public WrappedAccount(AccountSession session){
|
||||||
|
this.session=session;
|
||||||
|
req=new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? session.self.avatar : session.self.avatarStatic, V.dp(50), V.dp(50));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.joinmastodon.android.ui;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||||
|
import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
|
|
||||||
|
public class ClickableSingleViewRecyclerAdapter extends SingleViewRecyclerAdapter{
|
||||||
|
private final Runnable onClick;
|
||||||
|
|
||||||
|
public ClickableSingleViewRecyclerAdapter(View view, Runnable onClick){
|
||||||
|
super(view);
|
||||||
|
this.onClick=onClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||||
|
return new ClickableViewViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClickableViewViewHolder extends ViewViewHolder implements UsableRecyclerView.Clickable{
|
||||||
|
public ClickableViewViewHolder(@NonNull View itemView){
|
||||||
|
super(itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(){
|
||||||
|
onClick.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration{
|
||||||
private Paint paint=new Paint();
|
private Paint paint=new Paint();
|
||||||
private int paddingStart, paddingEnd;
|
private int paddingStart, paddingEnd;
|
||||||
private Predicate<RecyclerView.ViewHolder> drawDividerPredicate;
|
private Predicate<RecyclerView.ViewHolder> drawDividerPredicate;
|
||||||
|
private boolean drawBelowLastItem;
|
||||||
|
|
||||||
public static final Predicate<RecyclerView.ViewHolder> NOT_FIRST=vh->vh.getAbsoluteAdapterPosition()>0;
|
public static final Predicate<RecyclerView.ViewHolder> NOT_FIRST=vh->vh.getAbsoluteAdapterPosition()>0;
|
||||||
|
|
||||||
|
@ -34,6 +35,10 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration{
|
||||||
this.drawDividerPredicate=drawDividerPredicate;
|
this.drawDividerPredicate=drawDividerPredicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDrawBelowLastItem(boolean drawBelowLastItem){
|
||||||
|
this.drawBelowLastItem=drawBelowLastItem;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
|
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
|
||||||
boolean isRTL=parent.getLayoutDirection()==View.LAYOUT_DIRECTION_RTL;
|
boolean isRTL=parent.getLayoutDirection()==View.LAYOUT_DIRECTION_RTL;
|
||||||
|
@ -43,7 +48,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration{
|
||||||
for(int i=0;i<parent.getChildCount();i++){
|
for(int i=0;i<parent.getChildCount();i++){
|
||||||
View child=parent.getChildAt(i);
|
View child=parent.getChildAt(i);
|
||||||
int pos=parent.getChildAdapterPosition(child);
|
int pos=parent.getChildAdapterPosition(child);
|
||||||
if(pos<totalItems-1 && (drawDividerPredicate==null || drawDividerPredicate.test(parent.getChildViewHolder(child)))){
|
if((drawBelowLastItem || pos<totalItems-1) && (drawDividerPredicate==null || drawDividerPredicate.test(parent.getChildViewHolder(child)))){
|
||||||
float y=Math.round(child.getY()+child.getHeight());
|
float y=Math.round(child.getY()+child.getHeight());
|
||||||
y-=(y-paint.getStrokeWidth()/2f)%1f; // Make sure the line aligns with the pixel grid
|
y-=(y-paint.getStrokeWidth()/2f)%1f; // Make sure the line aligns with the pixel grid
|
||||||
paint.setAlpha(Math.round(255f*child.getAlpha()));
|
paint.setAlpha(Math.round(255f*child.getAlpha()));
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="?colorWindowBackground"/>
|
||||||
|
<corners android:topLeftRadius="12dp" android:topRightRadius="12dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:gravity="center" android:width="36dp" android:height="4dp">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="?android:textColorSecondary"/>
|
||||||
|
<corners android:radius="2dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:height="20dp">
|
||||||
|
<color android:color="#00000000"/>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path android:pathData="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2zm0 5c-0.38 0-0.694 0.282-0.743 0.648L11.25 7.75v3.5h-3.5C7.336 11.25 7 11.586 7 12c0 0.38 0.282 0.694 0.648 0.743L7.75 12.75h3.5v3.5c0 0.414 0.336 0.75 0.75 0.75 0.38 0 0.694-0.282 0.743-0.648l0.007-0.102v-3.5h3.5c0.414 0 0.75-0.336 0.75-0.75 0-0.38-0.282-0.694-0.648-0.743L16.25 11.25h-3.5v-3.5C12.75 7.336 12.414 7 12 7z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path android:pathData="M8.5 16.586l-3.793-3.793c-0.39-0.39-1.024-0.39-1.414 0-0.39 0.39-0.39 1.024 0 1.414l4.5 4.5c0.39 0.39 1.024 0.39 1.414 0l11-11c0.39-0.39 0.39-1.024 0-1.414-0.39-0.39-1.024-0.39-1.414 0L8.5 16.586z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="16dp" android:height="16dp" android:viewportWidth="16" android:viewportHeight="16">
|
||||||
|
<path android:pathData="M4.146 6.354c0.196 0.195 0.512 0.195 0.708 0L8 3.207l3.146 3.147c0.196 0.195 0.512 0.195 0.708 0 0.195-0.196 0.195-0.512 0-0.708l-3.5-3.5c-0.196-0.195-0.512-0.195-0.707 0l-3.5 3.5c-0.196 0.196-0.196 0.512 0 0.708zm0 3.292c0.196-0.195 0.512-0.195 0.708 0L8 12.793l3.146-3.146c0.196-0.196 0.512-0.196 0.708 0 0.195 0.195 0.195 0.511 0 0.707l-3.5 3.5c-0.196 0.195-0.512 0.195-0.707 0l-3.5-3.5c-0.196-0.196-0.196-0.512 0-0.707z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path android:pathData="M12 7.75c-0.966 0-1.75-0.784-1.75-1.75S11.034 4.25 12 4.25 13.75 5.034 13.75 6 12.966 7.75 12 7.75zm0 6c-0.966 0-1.75-0.784-1.75-1.75s0.784-1.75 1.75-1.75 1.75 0.784 1.75 1.75-0.784 1.75-1.75 1.75zM10.25 18c0 0.966 0.784 1.75 1.75 1.75s1.75-0.784 1.75-1.75-0.784-1.75-1.75-1.75-1.75 0.784-1.75 1.75z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="25dp" android:height="24dp" android:viewportWidth="25" android:viewportHeight="24">
|
||||||
|
<path android:pathData="M11.416 17.5c0-1.288 0.375-2.49 1.022-3.5h-7.77c-1.242 0-2.249 1.007-2.249 2.25v0.919c0 0.572 0.179 1.13 0.51 1.596C4.473 20.929 6.996 22 10.417 22c0.931 0 1.796-0.08 2.592-0.238-0.992-1.142-1.592-2.632-1.592-4.263zm-1-15.495c2.761 0 5 2.239 5 5s-2.239 5-5 5c-2.762 0-5-2.239-5-5s2.238-5 5-5zm13 15.495c0 3.038-2.463 5.5-5.5 5.5-3.038 0-5.5-2.462-5.5-5.5 0-3.037 2.462-5.5 5.5-5.5 3.037 0 5.5 2.463 5.5 5.5zm-4.647-2.853c-0.195-0.196-0.511-0.196-0.707 0-0.195 0.195-0.195 0.512 0 0.707L19.71 17h-4.293c-0.276 0-0.5 0.224-0.5 0.5s0.224 0.5 0.5 0.5h4.293l-1.647 1.647c-0.195 0.195-0.195 0.512 0 0.707 0.196 0.195 0.512 0.195 0.707 0l2.5-2.5c0.054-0.053 0.092-0.116 0.117-0.182 0.018-0.05 0.029-0.105 0.03-0.163V17.5c0-0.077-0.018-0.15-0.049-0.215-0.015-0.032-0.034-0.063-0.057-0.092-0.013-0.018-0.028-0.035-0.045-0.05l-2.496-2.496z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:paddingLeft="20dp"
|
||||||
|
android:paddingRight="20dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/avatar"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:importantForAccessibility="no"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/current"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:background="@drawable/ic_fluent_checkmark_24_filled"
|
||||||
|
android:backgroundTint="?android:textColorSecondary"
|
||||||
|
android:contentDescription="@string/current_account"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/more"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/ic_fluent_more_vertical_24_regular"
|
||||||
|
android:tint="?android:textColorSecondary"
|
||||||
|
android:contentDescription="@string/more_options"
|
||||||
|
android:background="?android:selectableItemBackgroundBorderless"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -12,11 +12,11 @@
|
||||||
android:id="@+id/tabbar"
|
android:id="@+id/tabbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:paddingLeft="20dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="20dp">
|
android:paddingRight="16dp">
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/tab_home"
|
android:id="@+id/tab_home"
|
||||||
android:layout_width="52dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:contentDescription="@string/home_timeline"
|
android:contentDescription="@string/home_timeline"
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/tab_search"
|
android:id="@+id/tab_search"
|
||||||
android:layout_width="52dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:contentDescription="@string/search_hint"
|
android:contentDescription="@string/search_hint"
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/tab_notifications"
|
android:id="@+id/tab_notifications"
|
||||||
android:layout_width="52dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:contentDescription="@string/notifications"
|
android:contentDescription="@string/notifications"
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/tab_profile"
|
android:id="@+id/tab_profile"
|
||||||
android:layout_width="52dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:contentDescription="@string/my_profile"
|
android:contentDescription="@string/my_profile"
|
||||||
android:foreground="@drawable/bg_tab_profile"
|
android:foreground="@drawable/bg_tab_profile"
|
||||||
|
@ -73,6 +73,13 @@
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@null"/>
|
android:src="@null"/>
|
||||||
|
<View
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:layout_marginEnd="-4dp"
|
||||||
|
android:backgroundTint="?android:colorPrimary"
|
||||||
|
android:background="@drawable/ic_fluent_chevron_up_down_16_regular"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</org.joinmastodon.android.ui.views.TabBar>
|
</org.joinmastodon.android.ui.views.TabBar>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@+id/log_out" android:title="@string/log_out_account" android:icon="@drawable/ic_fluent_person_arrow_right_24_filled"/>
|
||||||
|
</menu>
|
|
@ -318,4 +318,6 @@
|
||||||
<string name="button_follow_pending">Pending</string>
|
<string name="button_follow_pending">Pending</string>
|
||||||
<string name="follows_you">Follows you</string>
|
<string name="follows_you">Follows you</string>
|
||||||
<string name="manually_approves_followers">Manually approves followers</string>
|
<string name="manually_approves_followers">Manually approves followers</string>
|
||||||
|
<string name="current_account">Current account</string>
|
||||||
|
<string name="log_out_account">Log Out %s</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue