Featured tab in profiles
This commit is contained in:
parent
09ffda2605
commit
955b9a4b2b
|
@ -0,0 +1,14 @@
|
||||||
|
package org.joinmastodon.android.api.requests.accounts;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
|
import org.joinmastodon.android.model.Hashtag;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GetAccountFeaturedHashtags extends MastodonAPIRequest<List<Hashtag>>{
|
||||||
|
public GetAccountFeaturedHashtags(String id){
|
||||||
|
super(HttpMethod.GET, "/accounts/"+id+"/featured_tags", new TypeToken<>(){});
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ public class GetAccountStatuses extends MastodonAPIRequest<List<Status>>{
|
||||||
addQueryParameter("exclude_reblogs", "true");
|
addQueryParameter("exclude_reblogs", "true");
|
||||||
}
|
}
|
||||||
case OWN_POSTS_AND_REPLIES -> addQueryParameter("exclude_reblogs", "true");
|
case OWN_POSTS_AND_REPLIES -> addQueryParameter("exclude_reblogs", "true");
|
||||||
|
case PINNED -> addQueryParameter("pinned", "true");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ public class GetAccountStatuses extends MastodonAPIRequest<List<Status>>{
|
||||||
INCLUDE_REPLIES,
|
INCLUDE_REPLIES,
|
||||||
MEDIA,
|
MEDIA,
|
||||||
NO_REBLOGS,
|
NO_REBLOGS,
|
||||||
OWN_POSTS_AND_REPLIES
|
OWN_POSTS_AND_REPLIES,
|
||||||
|
PINNED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.joinmastodon.android.fragments;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.model.Account;
|
||||||
|
import org.joinmastodon.android.model.Hashtag;
|
||||||
|
import org.joinmastodon.android.ui.displayitems.HashtagStatusDisplayItem;
|
||||||
|
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
public class FeaturedHashtagsListFragment extends BaseStatusListFragment<Hashtag>{
|
||||||
|
private Account account;
|
||||||
|
private String accountID;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
accountID=getArguments().getString("account");
|
||||||
|
account=Parcels.unwrap(getArguments().getParcelable("profileAccount"));
|
||||||
|
onDataLoaded(getArguments().getParcelableArrayList("hashtags").stream().map(p->(Hashtag)Parcels.unwrap(p)).collect(Collectors.toList()), false);
|
||||||
|
setTitle(R.string.featured_hashtags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<StatusDisplayItem> buildDisplayItems(Hashtag s){
|
||||||
|
return Collections.singletonList(new HashtagStatusDisplayItem(s.name, this, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addAccountToKnown(Hashtag s){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemClick(String id){
|
||||||
|
UiUtils.openHashtagTimeline(getActivity(), accountID, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doLoadData(int offset, int count){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawDivider(View child, View bottomSibling, RecyclerView.ViewHolder holder, RecyclerView.ViewHolder siblingHolder, RecyclerView parent, Canvas c, Paint paint){
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package org.joinmastodon.android.fragments;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses;
|
||||||
|
import org.joinmastodon.android.model.Account;
|
||||||
|
import org.joinmastodon.android.model.Status;
|
||||||
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import me.grishka.appkit.api.SimpleCallback;
|
||||||
|
|
||||||
|
public class PinnedPostsListFragment extends StatusListFragment{
|
||||||
|
private Account account;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
account=Parcels.unwrap(getArguments().getParcelable("profileAccount"));
|
||||||
|
setTitle(R.string.pinned_posts);
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doLoadData(int offset, int count){
|
||||||
|
new GetAccountStatuses(account.id, null, null, 100, GetAccountStatuses.Filter.PINNED)
|
||||||
|
.setCallback(new SimpleCallback<>(this){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Status> result){
|
||||||
|
onDataLoaded(result, false);
|
||||||
|
}
|
||||||
|
}).exec(accountID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
package org.joinmastodon.android.fragments;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.requests.accounts.GetAccountFeaturedHashtags;
|
||||||
|
import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses;
|
||||||
|
import org.joinmastodon.android.model.Account;
|
||||||
|
import org.joinmastodon.android.model.Hashtag;
|
||||||
|
import org.joinmastodon.android.model.SearchResult;
|
||||||
|
import org.joinmastodon.android.model.Status;
|
||||||
|
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
|
||||||
|
import org.joinmastodon.android.ui.displayitems.HashtagStatusDisplayItem;
|
||||||
|
import org.joinmastodon.android.ui.displayitems.SectionHeaderStatusDisplayItem;
|
||||||
|
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import me.grishka.appkit.Nav;
|
||||||
|
import me.grishka.appkit.api.SimpleCallback;
|
||||||
|
|
||||||
|
public class ProfileFeaturedFragment extends BaseStatusListFragment<SearchResult>{
|
||||||
|
private Account profileAccount;
|
||||||
|
private List<Hashtag> featuredTags;
|
||||||
|
// private List<Account> endorsedAccounts;
|
||||||
|
private List<Status> pinnedStatuses;
|
||||||
|
private boolean tagsLoaded, statusesLoaded;
|
||||||
|
|
||||||
|
public ProfileFeaturedFragment(){
|
||||||
|
setListLayoutId(R.layout.recycler_fragment_no_refresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
profileAccount=Parcels.unwrap(getArguments().getParcelable("profileAccount"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<StatusDisplayItem> buildDisplayItems(SearchResult s){
|
||||||
|
ArrayList<StatusDisplayItem> items=switch(s.type){
|
||||||
|
case ACCOUNT -> new ArrayList<>(Collections.singletonList(new AccountStatusDisplayItem(s.id, this, s.account)));
|
||||||
|
case HASHTAG -> new ArrayList<>(Collections.singletonList(new HashtagStatusDisplayItem(s.id, this, s.hashtag)));
|
||||||
|
case STATUS -> StatusDisplayItem.buildItems(this, s.status, accountID, s, knownAccounts, false, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
if(s.firstInSection){
|
||||||
|
items.add(0, new SectionHeaderStatusDisplayItem(this, getString(switch(s.type){
|
||||||
|
case ACCOUNT -> R.string.profile_endorsed_accounts;
|
||||||
|
case HASHTAG -> R.string.hashtags;
|
||||||
|
case STATUS -> R.string.posts;
|
||||||
|
}), getString(R.string.view_all), switch(s.type){
|
||||||
|
case ACCOUNT -> (Runnable)this::showAllEndorsedAccounts;
|
||||||
|
case HASHTAG -> (Runnable)this::showAllFeaturedHashtags;
|
||||||
|
case STATUS -> (Runnable)this::showAllPinnedPosts;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addAccountToKnown(SearchResult s){
|
||||||
|
Account acc=switch(s.type){
|
||||||
|
case ACCOUNT -> s.account;
|
||||||
|
case STATUS -> s.status.account;
|
||||||
|
case HASHTAG -> null;
|
||||||
|
};
|
||||||
|
if(acc!=null && !knownAccounts.containsKey(acc.id))
|
||||||
|
knownAccounts.put(acc.id, acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemClick(String id){
|
||||||
|
SearchResult res=getResultByID(id);
|
||||||
|
if(res==null)
|
||||||
|
return;
|
||||||
|
switch(res.type){
|
||||||
|
case ACCOUNT -> {
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
args.putParcelable("profileAccount", Parcels.wrap(res.account));
|
||||||
|
Nav.go(getActivity(), ProfileFragment.class, args);
|
||||||
|
}
|
||||||
|
case HASHTAG -> UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag.name);
|
||||||
|
case STATUS -> {
|
||||||
|
Status status=res.status.getContentStatus();
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
args.putParcelable("status", Parcels.wrap(status));
|
||||||
|
if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId))
|
||||||
|
args.putParcelable("inReplyToAccount", Parcels.wrap(knownAccounts.get(status.inReplyToAccountId)));
|
||||||
|
Nav.go(getActivity(), ThreadFragment.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doLoadData(int offset, int count){
|
||||||
|
if(!statusesLoaded){
|
||||||
|
new GetAccountStatuses(profileAccount.id, null, null, 1, GetAccountStatuses.Filter.PINNED)
|
||||||
|
.setCallback(new SimpleCallback<>(this){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Status> result){
|
||||||
|
pinnedStatuses=result;
|
||||||
|
statusesLoaded=true;
|
||||||
|
onOneApiRequestCompleted();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec(accountID);
|
||||||
|
}
|
||||||
|
if(!tagsLoaded){
|
||||||
|
new GetAccountFeaturedHashtags(profileAccount.id)
|
||||||
|
.setCallback(new SimpleCallback<>(this){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Hashtag> result){
|
||||||
|
featuredTags=result;
|
||||||
|
tagsLoaded=true;
|
||||||
|
onOneApiRequestCompleted();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec(accountID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onShown(){
|
||||||
|
super.onShown();
|
||||||
|
if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading)
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRefresh(){
|
||||||
|
statusesLoaded=false;
|
||||||
|
tagsLoaded=false;
|
||||||
|
super.onRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onOneApiRequestCompleted(){
|
||||||
|
if(tagsLoaded && statusesLoaded){
|
||||||
|
ArrayList<SearchResult> results=new ArrayList<>();
|
||||||
|
if(!pinnedStatuses.isEmpty()){
|
||||||
|
SearchResult res=new SearchResult(pinnedStatuses.get(0));
|
||||||
|
res.firstInSection=true;
|
||||||
|
results.add(res);
|
||||||
|
}
|
||||||
|
for(int i=0;i<Math.min(3, featuredTags.size());i++){
|
||||||
|
SearchResult res=new SearchResult(featuredTags.get(i));
|
||||||
|
res.firstInSection=(i==0);
|
||||||
|
results.add(res);
|
||||||
|
}
|
||||||
|
onDataLoaded(results, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SearchResult getResultByID(String id){
|
||||||
|
for(SearchResult s:data){
|
||||||
|
if(s.id.equals(id)){
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawDivider(View child, View bottomSibling, RecyclerView.ViewHolder holder, RecyclerView.ViewHolder siblingHolder, RecyclerView parent, Canvas c, Paint paint){
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAllPinnedPosts(){
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
args.putParcelable("profileAccount", Parcels.wrap(profileAccount));
|
||||||
|
Nav.go(getActivity(), PinnedPostsListFragment.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAllFeaturedHashtags(){
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
ArrayList<Parcelable> tags=featuredTags.stream().map(Parcels::wrap).collect(Collectors.toCollection(ArrayList::new));
|
||||||
|
args.putParcelableArrayList("hashtags", tags);
|
||||||
|
Nav.go(getActivity(), FeaturedHashtagsListFragment.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAllEndorsedAccounts(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import android.graphics.drawable.LayerDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Parcelable;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.style.ImageSpan;
|
import android.text.style.ImageSpan;
|
||||||
|
@ -111,7 +112,8 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
private ProgressBarButton actionButton;
|
private ProgressBarButton actionButton;
|
||||||
private ViewPager2 pager;
|
private ViewPager2 pager;
|
||||||
private NestedRecyclerScrollView scrollView;
|
private NestedRecyclerScrollView scrollView;
|
||||||
private AccountTimelineFragment postsFragment, postsWithRepliesFragment, mediaFragment;
|
private ProfileFeaturedFragment featuredFragment;
|
||||||
|
private AccountTimelineFragment timelineFragment;
|
||||||
private ProfileAboutFragment aboutFragment;
|
private ProfileAboutFragment aboutFragment;
|
||||||
private TabLayout tabbar;
|
private TabLayout tabbar;
|
||||||
private SwipeRefreshLayout refreshLayout;
|
private SwipeRefreshLayout refreshLayout;
|
||||||
|
@ -216,14 +218,13 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tabViews=new FrameLayout[4];
|
tabViews=new FrameLayout[3];
|
||||||
for(int i=0;i<tabViews.length;i++){
|
for(int i=0;i<tabViews.length;i++){
|
||||||
FrameLayout tabView=new FrameLayout(getActivity());
|
FrameLayout tabView=new FrameLayout(getActivity());
|
||||||
tabView.setId(switch(i){
|
tabView.setId(switch(i){
|
||||||
case 0 -> R.id.profile_posts;
|
case 0 -> R.id.profile_featured;
|
||||||
case 1 -> R.id.profile_posts_with_replies;
|
case 1 -> R.id.profile_timeline;
|
||||||
case 2 -> R.id.profile_media;
|
case 2 -> R.id.profile_about;
|
||||||
case 3 -> R.id.profile_about;
|
|
||||||
default -> throw new IllegalStateException("Unexpected value: "+i);
|
default -> throw new IllegalStateException("Unexpected value: "+i);
|
||||||
});
|
});
|
||||||
tabView.setVisibility(View.GONE);
|
tabView.setVisibility(View.GONE);
|
||||||
|
@ -245,10 +246,9 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
@Override
|
@Override
|
||||||
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position){
|
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position){
|
||||||
tab.setText(switch(position){
|
tab.setText(switch(position){
|
||||||
case 0 -> R.string.posts;
|
case 0 -> R.string.profile_featured;
|
||||||
case 1 -> R.string.posts_and_replies;
|
case 1 -> R.string.profile_timeline;
|
||||||
case 2 -> R.string.media;
|
case 2 -> R.string.profile_about;
|
||||||
case 3 -> R.string.profile_about;
|
|
||||||
default -> throw new IllegalStateException();
|
default -> throw new IllegalStateException();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -312,12 +312,10 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
if(refreshing){
|
if(refreshing){
|
||||||
refreshing=false;
|
refreshing=false;
|
||||||
refreshLayout.setRefreshing(false);
|
refreshLayout.setRefreshing(false);
|
||||||
if(postsFragment.loaded)
|
if(timelineFragment.loaded)
|
||||||
postsFragment.onRefresh();
|
timelineFragment.onRefresh();
|
||||||
if(postsWithRepliesFragment.loaded)
|
if(featuredFragment.loaded)
|
||||||
postsWithRepliesFragment.onRefresh();
|
featuredFragment.onRefresh();
|
||||||
if(mediaFragment.loaded)
|
|
||||||
mediaFragment.onRefresh();
|
|
||||||
}
|
}
|
||||||
V.setVisibilityAnimated(fab, View.VISIBLE);
|
V.setVisibilityAnimated(fab, View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
@ -337,10 +335,14 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
public void dataLoaded(){
|
public void dataLoaded(){
|
||||||
if(getActivity()==null)
|
if(getActivity()==null)
|
||||||
return;
|
return;
|
||||||
if(postsFragment==null){
|
if(featuredFragment==null){
|
||||||
postsFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.DEFAULT, true);
|
featuredFragment=new ProfileFeaturedFragment();
|
||||||
postsWithRepliesFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.INCLUDE_REPLIES, false);
|
Bundle args=new Bundle();
|
||||||
mediaFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.MEDIA, false);
|
args.putString("account", accountID);
|
||||||
|
args.putParcelable("profileAccount", Parcels.wrap(account));
|
||||||
|
args.putBoolean("__is_tab", true);
|
||||||
|
featuredFragment.setArguments(args);
|
||||||
|
timelineFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.DEFAULT, true);
|
||||||
aboutFragment=new ProfileAboutFragment();
|
aboutFragment=new ProfileAboutFragment();
|
||||||
aboutFragment.setFields(fields);
|
aboutFragment.setFields(fields);
|
||||||
}
|
}
|
||||||
|
@ -397,11 +399,6 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView(){
|
|
||||||
super.onDestroyView();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfigurationChanged(Configuration newConfig){
|
public void onConfigurationChanged(Configuration newConfig){
|
||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
|
@ -425,10 +422,9 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyChildWindowInsets(){
|
private void applyChildWindowInsets(){
|
||||||
if(postsFragment!=null && postsFragment.isAdded() && childInsets!=null){
|
if(timelineFragment!=null && timelineFragment.isAdded() && childInsets!=null){
|
||||||
postsFragment.onApplyWindowInsets(childInsets);
|
timelineFragment.onApplyWindowInsets(childInsets);
|
||||||
postsWithRepliesFragment.onApplyWindowInsets(childInsets);
|
featuredFragment.onApplyWindowInsets(childInsets);
|
||||||
mediaFragment.onApplyWindowInsets(childInsets);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,10 +689,9 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
|
|
||||||
private Fragment getFragmentForPage(int page){
|
private Fragment getFragmentForPage(int page){
|
||||||
return switch(page){
|
return switch(page){
|
||||||
case 0 -> postsFragment;
|
case 0 -> featuredFragment;
|
||||||
case 1 -> postsWithRepliesFragment;
|
case 1 -> timelineFragment;
|
||||||
case 2 -> mediaFragment;
|
case 2 -> aboutFragment;
|
||||||
case 3 -> aboutFragment;
|
|
||||||
default -> throw new IllegalStateException();
|
default -> throw new IllegalStateException();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -759,7 +754,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
pager.setUserInputEnabled(false);
|
pager.setUserInputEnabled(false);
|
||||||
actionButton.setText(R.string.save_changes);
|
actionButton.setText(R.string.save_changes);
|
||||||
pager.setCurrentItem(3);
|
pager.setCurrentItem(2);
|
||||||
for(int i=0;i<3;i++){
|
for(int i=0;i<3;i++){
|
||||||
tabbar.getTabAt(i).view.setEnabled(false);
|
tabbar.getTabAt(i).view.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
@ -1001,7 +996,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount(){
|
public int getItemCount(){
|
||||||
return loaded ? 4 : 0;
|
return loaded ? 3 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,12 +6,13 @@ import org.parceler.Parcel;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Parcel
|
@Parcel
|
||||||
public class Hashtag extends BaseModel{
|
public class Hashtag extends BaseModel implements DisplayItemsParent{
|
||||||
@RequiredField
|
@RequiredField
|
||||||
public String name;
|
public String name;
|
||||||
@RequiredField
|
@RequiredField
|
||||||
public String url;
|
public String url;
|
||||||
public List<History> history;
|
public List<History> history;
|
||||||
|
public int statusesCount;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
|
@ -19,6 +20,12 @@ public class Hashtag extends BaseModel{
|
||||||
"name='"+name+'\''+
|
"name='"+name+'\''+
|
||||||
", url='"+url+'\''+
|
", url='"+url+'\''+
|
||||||
", history="+history+
|
", history="+history+
|
||||||
|
", statusesCount="+statusesCount+
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID(){
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ public class SearchResult extends BaseModel implements DisplayItemsParent{
|
||||||
public Type type;
|
public Type type;
|
||||||
|
|
||||||
public transient String id;
|
public transient String id;
|
||||||
|
public transient boolean firstInSection;
|
||||||
|
|
||||||
public SearchResult(){}
|
public SearchResult(){}
|
||||||
|
|
||||||
|
|
|
@ -37,12 +37,15 @@ public class HashtagStatusDisplayItem extends StatusDisplayItem{
|
||||||
public void onBind(HashtagStatusDisplayItem _item){
|
public void onBind(HashtagStatusDisplayItem _item){
|
||||||
Hashtag item=_item.tag;
|
Hashtag item=_item.tag;
|
||||||
title.setText('#'+item.name);
|
title.setText('#'+item.name);
|
||||||
int numPeople=item.history.get(0).accounts;
|
if(item.history!=null && !item.history.isEmpty()){
|
||||||
if(item.history.size()>1)
|
int numPeople=item.history.get(0).accounts;
|
||||||
numPeople+=item.history.get(1).accounts;
|
if(item.history.size()>1)
|
||||||
subtitle.setText(_item.parentFragment.getResources().getQuantityString(R.plurals.x_people_talking, numPeople, numPeople));
|
numPeople+=item.history.get(1).accounts;
|
||||||
chart.setData(item.history);
|
subtitle.setText(itemView.getResources().getQuantityString(R.plurals.x_people_talking, numPeople, numPeople));
|
||||||
|
chart.setData(item.history);
|
||||||
|
}else{
|
||||||
|
subtitle.setText(itemView.getResources().getQuantityString(R.plurals.x_posts, item.statusesCount, item.statusesCount));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package org.joinmastodon.android.ui.displayitems;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
|
|
||||||
|
public class SectionHeaderStatusDisplayItem extends StatusDisplayItem{
|
||||||
|
public final String title, buttonText;
|
||||||
|
public final Runnable onButtonClick;
|
||||||
|
|
||||||
|
public SectionHeaderStatusDisplayItem(BaseStatusListFragment parentFragment, String title, String buttonText, Runnable onButtonClick){
|
||||||
|
super("", parentFragment);
|
||||||
|
this.title=title;
|
||||||
|
this.buttonText=buttonText;
|
||||||
|
this.onButtonClick=onButtonClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType(){
|
||||||
|
return Type.SECTION_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Holder extends StatusDisplayItem.Holder<SectionHeaderStatusDisplayItem>{
|
||||||
|
private final TextView title;
|
||||||
|
private final Button actionBtn;
|
||||||
|
|
||||||
|
public Holder(Context context, ViewGroup parent){
|
||||||
|
super(context, R.layout.display_item_section_header, parent);
|
||||||
|
title=findViewById(R.id.title);
|
||||||
|
actionBtn=findViewById(R.id.action_btn);
|
||||||
|
actionBtn.setOnClickListener(v->item.onButtonClick.run());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(SectionHeaderStatusDisplayItem item){
|
||||||
|
title.setText(item.title);
|
||||||
|
if(item.onButtonClick!=null){
|
||||||
|
actionBtn.setVisibility(View.VISIBLE);
|
||||||
|
actionBtn.setText(item.buttonText);
|
||||||
|
}else{
|
||||||
|
actionBtn.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,6 +65,7 @@ public abstract class StatusDisplayItem{
|
||||||
case EXTENDED_FOOTER -> new ExtendedFooterStatusDisplayItem.Holder(activity, parent);
|
case EXTENDED_FOOTER -> new ExtendedFooterStatusDisplayItem.Holder(activity, parent);
|
||||||
case MEDIA_GRID -> new MediaGridStatusDisplayItem.Holder(activity, parent);
|
case MEDIA_GRID -> new MediaGridStatusDisplayItem.Holder(activity, parent);
|
||||||
case SPOILER -> new SpoilerStatusDisplayItem.Holder(activity, parent);
|
case SPOILER -> new SpoilerStatusDisplayItem.Holder(activity, parent);
|
||||||
|
case SECTION_HEADER -> new SectionHeaderStatusDisplayItem.Holder(activity, parent);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +155,8 @@ public abstract class StatusDisplayItem{
|
||||||
GAP,
|
GAP,
|
||||||
EXTENDED_FOOTER,
|
EXTENDED_FOOTER,
|
||||||
MEDIA_GRID,
|
MEDIA_GRID,
|
||||||
SPOILER
|
SPOILER,
|
||||||
|
SECTION_HEADER
|
||||||
}
|
}
|
||||||
|
|
||||||
public static abstract class Holder<T extends StatusDisplayItem> extends BindableViewHolder<T> implements UsableRecyclerView.DisableableClickable{
|
public static abstract class Holder<T extends StatusDisplayItem> extends BindableViewHolder<T> implements UsableRecyclerView.DisableableClickable{
|
||||||
|
|
|
@ -14,12 +14,12 @@ import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.CustomViewHelper;
|
||||||
|
|
||||||
public class HashtagChartView extends View{
|
public class HashtagChartView extends View implements CustomViewHelper{
|
||||||
private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
|
private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
private Path strokePath=new Path(), fillPath=new Path();
|
private Path strokePath=new Path(), fillPath=new Path();
|
||||||
private CornerPathEffect pathEffect=new CornerPathEffect(V.dp(3));
|
private final CornerPathEffect pathEffect=new CornerPathEffect(dp(3));
|
||||||
private float[] relativeOffsets=new float[7];
|
private float[] relativeOffsets=new float[7];
|
||||||
|
|
||||||
public HashtagChartView(Context context){
|
public HashtagChartView(Context context){
|
||||||
|
@ -32,7 +32,7 @@ public class HashtagChartView extends View{
|
||||||
|
|
||||||
public HashtagChartView(Context context, AttributeSet attrs, int defStyle){
|
public HashtagChartView(Context context, AttributeSet attrs, int defStyle){
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
paint.setStrokeWidth(V.dp(1.71f));
|
paint.setStrokeWidth(dp(1.71f));
|
||||||
paint.setStrokeCap(Paint.Cap.ROUND);
|
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
paint.setStrokeJoin(Paint.Join.ROUND);
|
paint.setStrokeJoin(Paint.Join.ROUND);
|
||||||
}
|
}
|
||||||
|
@ -57,20 +57,20 @@ public class HashtagChartView extends View{
|
||||||
return;
|
return;
|
||||||
strokePath.rewind();
|
strokePath.rewind();
|
||||||
fillPath.rewind();
|
fillPath.rewind();
|
||||||
float step=(getWidth()-V.dp(2))/(float)(relativeOffsets.length-1);
|
float step=(getWidth()-dp(2))/(float)(relativeOffsets.length-1);
|
||||||
float maxH=getHeight()-V.dp(2);
|
float maxH=getHeight()-dp(2);
|
||||||
float x=getWidth()-V.dp(1);
|
float x=getWidth()-dp(1);
|
||||||
strokePath.moveTo(x, maxH-maxH*relativeOffsets[0]+V.dp(1));
|
strokePath.moveTo(x, maxH-maxH*relativeOffsets[0]+dp(1));
|
||||||
fillPath.moveTo(getWidth(), getHeight()-V.dp(1));
|
fillPath.moveTo(getWidth(), getHeight()-dp(1));
|
||||||
fillPath.lineTo(x, maxH-maxH*relativeOffsets[0]+V.dp(1));
|
fillPath.lineTo(x, maxH-maxH*relativeOffsets[0]+dp(1));
|
||||||
for(int i=1;i<relativeOffsets.length;i++){
|
for(int i=1;i<relativeOffsets.length;i++){
|
||||||
float offset=relativeOffsets[i];
|
float offset=relativeOffsets[i];
|
||||||
x-=step;
|
x-=step;
|
||||||
float y=maxH-maxH*offset+V.dp(1);
|
float y=maxH-maxH*offset+dp(1);
|
||||||
strokePath.lineTo(x, y);
|
strokePath.lineTo(x, y);
|
||||||
fillPath.lineTo(x, y);
|
fillPath.lineTo(x, y);
|
||||||
}
|
}
|
||||||
fillPath.lineTo(V.dp(1), getHeight()-V.dp(1));
|
fillPath.lineTo(dp(1), getHeight()-dp(1));
|
||||||
fillPath.close();
|
fillPath.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,11 +83,11 @@ public class HashtagChartView extends View{
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas){
|
protected void onDraw(Canvas canvas){
|
||||||
paint.setStyle(Paint.Style.FILL);
|
paint.setStyle(Paint.Style.FILL);
|
||||||
paint.setColor(UiUtils.getThemeColor(getContext(), R.attr.colorAccentLightest));
|
paint.setColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3PrimaryInverse));
|
||||||
paint.setPathEffect(null);
|
paint.setPathEffect(null);
|
||||||
canvas.drawPath(fillPath, paint);
|
canvas.drawPath(fillPath, paint);
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
paint.setColor(UiUtils.getThemeColor(getContext(), android.R.attr.colorAccent));
|
paint.setColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3Primary));
|
||||||
paint.setPathEffect(pathEffect);
|
paint.setPathEffect(pathEffect);
|
||||||
canvas.drawPath(strokePath, paint);
|
canvas.drawPath(strokePath, paint);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,7 @@ public class NestedRecyclerScrollView extends CustomScrollView{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
|
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
|
||||||
final RecyclerView rv = (RecyclerView) target;
|
if(target instanceof RecyclerView rv && ((dy < 0 && isScrolledToTop(rv)) || (dy > 0 && !isScrolledToBottom()))){
|
||||||
if ((dy < 0 && isScrolledToTop(rv)) || (dy > 0 && !isScrolledToBottom())) {
|
|
||||||
scrollBy(0, dy);
|
scrollBy(0, dy);
|
||||||
consumed[1] = dy;
|
consumed[1] = dy;
|
||||||
return;
|
return;
|
||||||
|
@ -37,8 +36,7 @@ public class NestedRecyclerScrollView extends CustomScrollView{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onNestedPreFling(View target, float velX, float velY) {
|
public boolean onNestedPreFling(View target, float velX, float velY) {
|
||||||
final RecyclerView rv = (RecyclerView) target;
|
if (target instanceof RecyclerView rv && ((velY < 0 && isScrolledToTop(rv)) || (velY > 0 && !isScrolledToBottom()))){
|
||||||
if ((velY < 0 && isScrolledToTop(rv)) || (velY > 0 && !isScrolledToBottom())) {
|
|
||||||
fling((int) velY);
|
fling((int) velY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textAppearance="@style/m3_title_medium"
|
||||||
|
android:textColor="?colorM3OnSurface"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
tools:text="Section Header"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/action_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="-8dp"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="?colorM3Primary"
|
||||||
|
android:background="@drawable/bg_button_borderless_rounded"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
tools:text="Action"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -2,11 +2,7 @@
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:paddingRight="16dp"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingBottom="8dp">
|
|
||||||
|
|
||||||
<org.joinmastodon.android.ui.views.LinkedTextView
|
<org.joinmastodon.android.ui.views.LinkedTextView
|
||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
|
@ -14,6 +10,10 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textColor="?colorM3OnSurface"
|
android:textColor="?colorM3OnSurface"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
android:textAppearance="@style/m3_body_large"/>
|
android:textAppearance="@style/m3_body_large"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -215,11 +215,11 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginEnd="4dp"
|
android:layout_marginEnd="4dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:fontFamily="sans-serif-black"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textColor="?colorM3OnSurfaceVariant"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:textSize="14dp"
|
android:textSize="14dp"
|
||||||
android:textStyle="bold"
|
|
||||||
tools:text="123" />
|
tools:text="123" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
|
@ -2,39 +2,43 @@
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="64dp"
|
android:layout_height="72dp"
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="16dp"
|
android:paddingRight="16dp"
|
||||||
android:paddingTop="12dp">
|
android:paddingTop="14dp">
|
||||||
|
|
||||||
<org.joinmastodon.android.ui.views.HashtagChartView
|
<org.joinmastodon.android.ui.views.HashtagChartView
|
||||||
android:id="@+id/chart"
|
android:id="@+id/chart"
|
||||||
android:layout_width="64dp"
|
android:layout_width="66dp"
|
||||||
android:layout_height="32dp"
|
android:layout_height="36dp"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:layout_marginEnd="7dp"
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
android:layout_alignParentEnd="true"/>
|
android:layout_alignParentEnd="true"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="24dp"
|
||||||
android:layout_toStartOf="@id/chart"
|
android:layout_toStartOf="@id/chart"
|
||||||
android:textAppearance="@style/m3_title_medium"
|
android:textAppearance="@style/m3_body_large"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textColor="?colorM3OnSurface"
|
||||||
tools:text="#mastodev"/>
|
tools:text="#mastodev"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/subtitle"
|
android:id="@+id/subtitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="20dp"
|
||||||
android:layout_below="@id/title"
|
android:layout_below="@id/title"
|
||||||
android:layout_toStartOf="@id/chart"
|
android:layout_toStartOf="@id/chart"
|
||||||
android:textAppearance="@style/m3_body_medium"
|
android:textAppearance="@style/m3_body_medium"
|
||||||
android:textColor="?android:textColorSecondary"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical"
|
||||||
tools:text="over 9000 people talking"/>
|
tools:text="over 9000 people talking"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
|
@ -41,6 +41,7 @@
|
||||||
<attr name="colorM3OnError" format="color"/>
|
<attr name="colorM3OnError" format="color"/>
|
||||||
<attr name="colorM3ErrorContainer" format="color"/>
|
<attr name="colorM3ErrorContainer" format="color"/>
|
||||||
<attr name="colorM3OnErrorContainer" format="color"/>
|
<attr name="colorM3OnErrorContainer" format="color"/>
|
||||||
|
<attr name="colorM3PrimaryInverse" format="color"/>
|
||||||
|
|
||||||
<attr name="primaryLargeButtonStyle" format="reference"/>
|
<attr name="primaryLargeButtonStyle" format="reference"/>
|
||||||
<attr name="secondaryLargeButtonStyle" format="reference"/>
|
<attr name="secondaryLargeButtonStyle" format="reference"/>
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
<resources>
|
<resources>
|
||||||
<item name="header" type="id"/>
|
<item name="header" type="id"/>
|
||||||
|
|
||||||
<item name="profile_posts" type="id"/>
|
<item name="profile_featured" type="id"/>
|
||||||
<item name="profile_posts_with_replies" type="id"/>
|
<item name="profile_timeline" type="id"/>
|
||||||
<item name="profile_media" type="id"/>
|
|
||||||
<item name="profile_about" type="id"/>
|
<item name="profile_about" type="id"/>
|
||||||
|
|
||||||
<item name="discover_posts" type="id"/>
|
<item name="discover_posts" type="id"/>
|
||||||
|
|
|
@ -442,4 +442,10 @@
|
||||||
<string name="spoiler_hide">Re-hide</string>
|
<string name="spoiler_hide">Re-hide</string>
|
||||||
<string name="poll_multiple_choice">Choose one or more</string>
|
<string name="poll_multiple_choice">Choose one or more</string>
|
||||||
<string name="save_changes">Save changes</string>
|
<string name="save_changes">Save changes</string>
|
||||||
|
<string name="profile_featured">Featured</string>
|
||||||
|
<string name="profile_timeline">Timeline</string>
|
||||||
|
<string name="view_all">View all</string>
|
||||||
|
<string name="profile_endorsed_accounts">Accounts</string>
|
||||||
|
<string name="pinned_posts">Pinned posts</string>
|
||||||
|
<string name="featured_hashtags">Featured hashtags</string>
|
||||||
</resources>
|
</resources>
|
|
@ -65,6 +65,7 @@
|
||||||
<item name="colorM3OnError">#FFF</item>
|
<item name="colorM3OnError">#FFF</item>
|
||||||
<item name="colorM3ErrorContainer">#F9DEDC</item>
|
<item name="colorM3ErrorContainer">#F9DEDC</item>
|
||||||
<item name="colorM3OnErrorContainer">#410E0B</item>
|
<item name="colorM3OnErrorContainer">#410E0B</item>
|
||||||
|
<item name="colorM3PrimaryInverse">@color/m3_sys_dark_primary</item>
|
||||||
|
|
||||||
<item name="colorWindowBackground">?colorM3Background</item>
|
<item name="colorWindowBackground">?colorM3Background</item>
|
||||||
<item name="android:statusBarColor">?colorM3Background</item>
|
<item name="android:statusBarColor">?colorM3Background</item>
|
||||||
|
@ -139,6 +140,7 @@
|
||||||
<item name="colorM3OnError">#601410</item>
|
<item name="colorM3OnError">#601410</item>
|
||||||
<item name="colorM3ErrorContainer">#8C1D18</item>
|
<item name="colorM3ErrorContainer">#8C1D18</item>
|
||||||
<item name="colorM3OnErrorContainer">#F9DEDC</item>
|
<item name="colorM3OnErrorContainer">#F9DEDC</item>
|
||||||
|
<item name="colorM3PrimaryInverse">@color/m3_sys_light_primary</item>
|
||||||
|
|
||||||
<item name="colorWindowBackground">?colorM3Background</item>
|
<item name="colorWindowBackground">?colorM3Background</item>
|
||||||
<item name="android:statusBarColor">?colorM3Background</item>
|
<item name="android:statusBarColor">?colorM3Background</item>
|
||||||
|
|
Loading…
Reference in New Issue