commit
23f82197c6
|
@ -0,0 +1,16 @@
|
||||||
|
package org.joinmastodon.android.api.requests.instance;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
|
import org.joinmastodon.android.model.DomainBlock;
|
||||||
|
import org.joinmastodon.android.model.ExtendedDescription;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GetDomainBlocks extends MastodonAPIRequest<List<DomainBlock>>{
|
||||||
|
public GetDomainBlocks(){
|
||||||
|
super(HttpMethod.GET, "/instance/domain_blocks", new TypeToken<>(){});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.joinmastodon.android.api.requests.instance;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
|
import org.joinmastodon.android.model.ExtendedDescription;
|
||||||
|
import org.joinmastodon.android.model.Instance;
|
||||||
|
|
||||||
|
public class GetExtendedDescription extends MastodonAPIRequest<ExtendedDescription>{
|
||||||
|
public GetExtendedDescription(){
|
||||||
|
super(HttpMethod.GET, "/instance/extended_description", ExtendedDescription.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.joinmastodon.android.api.requests.instance;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
|
import org.joinmastodon.android.model.WeeklyActivity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GetWeeklyActivity extends MastodonAPIRequest<List<WeeklyActivity>>{
|
||||||
|
public GetWeeklyActivity(){
|
||||||
|
super(HttpMethod.GET, "/instance/activity", new TypeToken<>(){});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
package org.joinmastodon.android.fragments;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowInsets;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.requests.instance.GetDomainBlocks;
|
||||||
|
import org.joinmastodon.android.fragments.onboarding.GoogleMadeMeAddThisFragment;
|
||||||
|
import org.joinmastodon.android.model.DomainBlock;
|
||||||
|
import org.joinmastodon.android.model.Instance;
|
||||||
|
import org.joinmastodon.android.model.Severity;
|
||||||
|
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||||
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.joinmastodon.android.utils.ElevationOnScrollListener;
|
||||||
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import me.grishka.appkit.Nav;
|
||||||
|
import me.grishka.appkit.api.SimpleCallback;
|
||||||
|
import me.grishka.appkit.fragments.LoaderFragment;
|
||||||
|
import me.grishka.appkit.fragments.ToolbarFragment;
|
||||||
|
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.FragmentRootLinearLayout;
|
||||||
|
import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
|
|
||||||
|
public class InstanceBlockListFragment extends LoaderFragment {
|
||||||
|
private UsableRecyclerView list;
|
||||||
|
private MergeRecyclerAdapter adapter;
|
||||||
|
private View buttonBar;
|
||||||
|
private Instance instance;
|
||||||
|
private ElevationOnScrollListener onScrollListener;
|
||||||
|
|
||||||
|
private List<DomainBlock> domainBlocks;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setRetainInstance(true);
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity){
|
||||||
|
super.onAttach(activity);
|
||||||
|
setNavigationBarColor(UiUtils.getThemeColor(activity, R.attr.colorWindowBackground));
|
||||||
|
instance=Parcels.unwrap(getArguments().getParcelable("instance"));
|
||||||
|
setTitle(R.string.mo_instance_info_moderated_servers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
|
||||||
|
View view=inflater.inflate(R.layout.fragment_onboarding_rules, container, false);
|
||||||
|
|
||||||
|
list=view.findViewById(R.id.list);
|
||||||
|
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
|
|
||||||
|
adapter=new MergeRecyclerAdapter();
|
||||||
|
adapter.addAdapter(new ItemsAdapter());
|
||||||
|
list.setAdapter(adapter);
|
||||||
|
list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorM3SurfaceVariant, 1, 0, 0, DividerItemDecoration.NOT_FIRST));
|
||||||
|
|
||||||
|
buttonBar=view.findViewById(R.id.button_bar);
|
||||||
|
|
||||||
|
view.findViewById(R.id.btn_back).setOnClickListener(v->Nav.finish(this));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doLoadData() {
|
||||||
|
currentRequest= new GetDomainBlocks().setCallback(new SimpleCallback<>(this) {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<DomainBlock> result) {
|
||||||
|
domainBlocks=result;
|
||||||
|
dataLoaded();
|
||||||
|
}
|
||||||
|
}).execNoAuth(instance.uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
||||||
|
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
||||||
|
list.addOnScrollListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onUpdateToolbar(){
|
||||||
|
super.onUpdateToolbar();
|
||||||
|
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
|
||||||
|
getToolbar().setElevation(0);
|
||||||
|
if(onScrollListener!=null){
|
||||||
|
onScrollListener.setViews(buttonBar, getToolbar());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplyWindowInsets(WindowInsets insets){
|
||||||
|
if(Build.VERSION.SDK_INT>=27){
|
||||||
|
int inset=insets.getSystemWindowInsetBottom();
|
||||||
|
buttonBar.setPadding(0, 0, 0, inset>0 ? Math.max(inset, V.dp(36)) : 0);
|
||||||
|
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), 0));
|
||||||
|
}else{
|
||||||
|
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRefresh(){
|
||||||
|
doLoadData();
|
||||||
|
}
|
||||||
|
private class ItemsAdapter extends RecyclerView.Adapter<ItemViewHolder>{
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||||
|
return new ItemViewHolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ItemViewHolder holder, int position){
|
||||||
|
holder.bind(domainBlocks.get(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount(){
|
||||||
|
return domainBlocks.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ItemViewHolder extends BindableViewHolder<DomainBlock>{
|
||||||
|
private final TextView instanceUri, reason;
|
||||||
|
private final ImageView severity;
|
||||||
|
|
||||||
|
public ItemViewHolder(){
|
||||||
|
super(getActivity(), R.layout.item_server_block, list);
|
||||||
|
instanceUri=findViewById(R.id.instance);
|
||||||
|
reason=findViewById(R.id.reason);
|
||||||
|
severity=findViewById(R.id.severity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
@Override
|
||||||
|
public void onBind(DomainBlock item){
|
||||||
|
instanceUri.setText(item.domain);
|
||||||
|
reason.setText(item.comment);
|
||||||
|
switch (item.severity) {
|
||||||
|
case SILENCE -> {
|
||||||
|
severity.setImageDrawable(getContext().getDrawable(R.drawable.ic_fluent_speaker_mute_28_regular));
|
||||||
|
severity.setContentDescription(getContext().getString(R.string.mo_severity_silence));
|
||||||
|
}
|
||||||
|
case SUSPEND -> {
|
||||||
|
severity.setImageDrawable(getContext().getDrawable(R.drawable.ic_fluent_shield_prohibited_28_regular));
|
||||||
|
severity.setContentDescription(getContext().getString(R.string.mo_severity_suspend));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
severity.setTooltipText(severity.getContentDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,437 @@
|
||||||
|
package org.joinmastodon.android.fragments;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Outline;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewOutlineProvider;
|
||||||
|
import android.view.WindowInsets;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.DomainManager;
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.requests.instance.GetExtendedDescription;
|
||||||
|
import org.joinmastodon.android.api.requests.instance.GetInstance;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
|
import org.joinmastodon.android.fragments.onboarding.InstanceRulesFragment;
|
||||||
|
import org.joinmastodon.android.model.Account;
|
||||||
|
import org.joinmastodon.android.model.AccountField;
|
||||||
|
import org.joinmastodon.android.model.Attachment;
|
||||||
|
import org.joinmastodon.android.model.ExtendedDescription;
|
||||||
|
import org.joinmastodon.android.model.Instance;
|
||||||
|
import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||||
|
import org.joinmastodon.android.ui.SingleImagePhotoViewerListener;
|
||||||
|
import org.joinmastodon.android.ui.drawables.CoverOverlayGradientDrawable;
|
||||||
|
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
||||||
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.joinmastodon.android.ui.views.CoverImageView;
|
||||||
|
import org.joinmastodon.android.ui.views.LinkedTextView;
|
||||||
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import me.grishka.appkit.Nav;
|
||||||
|
import me.grishka.appkit.api.SimpleCallback;
|
||||||
|
import me.grishka.appkit.fragments.LoaderFragment;
|
||||||
|
import me.grishka.appkit.imageloader.ListImageLoaderWrapper;
|
||||||
|
import me.grishka.appkit.imageloader.RecyclerViewDelegate;
|
||||||
|
import me.grishka.appkit.imageloader.ViewImageLoader;
|
||||||
|
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||||
|
import me.grishka.appkit.utils.BindableViewHolder;
|
||||||
|
import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
|
|
||||||
|
public class InstanceInfoFragment extends LoaderFragment {
|
||||||
|
|
||||||
|
private Instance instance;
|
||||||
|
private String extendedDescription;
|
||||||
|
private CoverImageView cover;
|
||||||
|
private TextView uri, description, readMore;
|
||||||
|
private SwipeRefreshLayout refreshLayout;
|
||||||
|
private final CoverOverlayGradientDrawable coverGradient=new CoverOverlayGradientDrawable();
|
||||||
|
private LinearLayout textWrap;
|
||||||
|
|
||||||
|
private ScrollView scrollView, textScrollView;
|
||||||
|
private float titleTransY;
|
||||||
|
|
||||||
|
private String accountID;
|
||||||
|
private Account account;
|
||||||
|
private String targetDomain;
|
||||||
|
private final ArrayList<AccountField> fields=new ArrayList<>();
|
||||||
|
|
||||||
|
private boolean refreshing;
|
||||||
|
private boolean isExpanded = false;
|
||||||
|
|
||||||
|
public UsableRecyclerView list;
|
||||||
|
private List<AccountField> metadataListData=Collections.emptyList();
|
||||||
|
private MetadataAdapter adapter;
|
||||||
|
private ListImageLoaderWrapper imgLoader;
|
||||||
|
|
||||||
|
private float textMaxHeight, textCollapsedHeight;
|
||||||
|
private LinearLayout.LayoutParams collapseParams, wrapParams;
|
||||||
|
|
||||||
|
public InstanceInfoFragment(){
|
||||||
|
super(R.layout.loader_fragment_overlay_toolbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
|
||||||
|
setRetainInstance(true);
|
||||||
|
|
||||||
|
accountID=getArguments().getString("account");
|
||||||
|
account= AccountSessionManager.getInstance().getAccount(accountID).self;
|
||||||
|
targetDomain=getArguments().getString("instanceDomain");
|
||||||
|
loadData();
|
||||||
|
loadExtendedDescription();
|
||||||
|
DomainManager.getInstance().setCurrentDomain(targetDomain + "/about");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity){
|
||||||
|
super.onAttach(activity);
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
|
||||||
|
View content=inflater.inflate(R.layout.fragment_instance_info, container, false);
|
||||||
|
|
||||||
|
refreshLayout=content.findViewById(R.id.refresh_layout);
|
||||||
|
scrollView=content.findViewById(R.id.scroll_view);
|
||||||
|
cover=content.findViewById(R.id.cover);
|
||||||
|
uri =content.findViewById(R.id.uri);
|
||||||
|
description=content.findViewById(R.id.description);
|
||||||
|
list=content.findViewById(R.id.metadata);
|
||||||
|
textScrollView=content.findViewById(R.id.text_scroll_view);
|
||||||
|
textWrap=content.findViewById(R.id.text_wrap);
|
||||||
|
readMore=content.findViewById(R.id.read_more);
|
||||||
|
textMaxHeight=getActivity().getResources().getDimension(R.dimen.description_max_height);
|
||||||
|
textCollapsedHeight=getActivity().getResources().getDimension(R.dimen.description_collapsed_height);
|
||||||
|
collapseParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) textCollapsedHeight);
|
||||||
|
wrapParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
|
||||||
|
cover.setForeground(coverGradient);
|
||||||
|
cover.setOnClickListener(this::onCoverClick);
|
||||||
|
readMore.setOnClickListener(this::onReadMoreClick);
|
||||||
|
refreshLayout.setOnRefreshListener(this);
|
||||||
|
|
||||||
|
|
||||||
|
if(loaded){
|
||||||
|
bindViews();
|
||||||
|
dataLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
list.setItemAnimator(new BetterItemAnimator());
|
||||||
|
list.setDrawSelectorOnTop(true);
|
||||||
|
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
|
imgLoader=new ListImageLoaderWrapper(getActivity(), list, new RecyclerViewDelegate(list), null);
|
||||||
|
list.setAdapter(adapter=new MetadataAdapter());
|
||||||
|
list.setClipToPadding(false);
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doLoadData(){
|
||||||
|
currentRequest=new GetInstance()
|
||||||
|
.setCallback(new SimpleCallback<>(this){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Instance result){
|
||||||
|
if (getActivity() == null) return;
|
||||||
|
instance = result;
|
||||||
|
bindViews();
|
||||||
|
dataLoaded();
|
||||||
|
if(refreshing) {
|
||||||
|
refreshing = false;
|
||||||
|
refreshLayout.setRefreshing(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.execNoAuth(targetDomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadExtendedDescription() {
|
||||||
|
new GetExtendedDescription()
|
||||||
|
.setCallback(new SimpleCallback<>(this){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ExtendedDescription result){
|
||||||
|
if (getActivity() == null || result == null || TextUtils.isEmpty(result.content)) return;
|
||||||
|
extendedDescription = result.content;
|
||||||
|
updateDescription();
|
||||||
|
collapseDescription();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.execNoAuth(targetDomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDescription() {
|
||||||
|
if (instance == null || description == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
description.setText(HtmlParser.parse(TextUtils.isEmpty(extendedDescription) ?
|
||||||
|
TextUtils.isEmpty(instance.description) ? instance.shortDescription : instance.description
|
||||||
|
: extendedDescription,
|
||||||
|
account.emojis, Collections.emptyList(), Collections.emptyList(), accountID));
|
||||||
|
|
||||||
|
description.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(textWrap.getWidth(), View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRefresh(){
|
||||||
|
if(refreshing)
|
||||||
|
return;
|
||||||
|
refreshing=true;
|
||||||
|
doLoadData();
|
||||||
|
loadExtendedDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dataLoaded(){
|
||||||
|
if(getActivity()==null)
|
||||||
|
return;
|
||||||
|
setFields(fields);
|
||||||
|
super.dataLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
updateToolbar();
|
||||||
|
titleTransY=getToolbar().getLayoutParams().height;
|
||||||
|
if(toolbarTitleView!=null){
|
||||||
|
toolbarTitleView.setTranslationY(titleTransY);
|
||||||
|
toolbarSubtitleView.setTranslationY(titleTransY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(Configuration newConfig){
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
updateToolbar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplyWindowInsets(WindowInsets insets){
|
||||||
|
int statusBarHeight = insets.getSystemWindowInsetTop();
|
||||||
|
if(contentView!=null){
|
||||||
|
((ViewGroup.MarginLayoutParams) getToolbar().getLayoutParams()).topMargin= statusBarHeight;
|
||||||
|
}
|
||||||
|
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), 0, insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void bindViews(){
|
||||||
|
ViewImageLoader.load(cover, null, new UrlImageLoaderRequest(instance.thumbnail, 1000, 1000));
|
||||||
|
uri.setText(instance.title);
|
||||||
|
setTitle(instance.title);
|
||||||
|
|
||||||
|
updateDescription();
|
||||||
|
collapseDescription();
|
||||||
|
|
||||||
|
fields.clear();
|
||||||
|
|
||||||
|
|
||||||
|
if (instance.contactAccount != null) {
|
||||||
|
AccountField admin = new AccountField();
|
||||||
|
admin.parsedName=admin.name=getContext().getString(R.string.mo_instance_admin);
|
||||||
|
admin.parsedValue=buildLinkText(instance.contactAccount.url, instance.contactAccount.getDisplayUsername() + "@" + instance.uri);
|
||||||
|
fields.add(admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance.email != null) {
|
||||||
|
AccountField contact = new AccountField();
|
||||||
|
contact.parsedName=getContext().getString(R.string.mo_instance_contact);
|
||||||
|
contact.parsedValue=buildLinkText("mailto:" + instance.email, instance.email);
|
||||||
|
fields.add(contact);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance.stats != null) {
|
||||||
|
AccountField activeUsers = new AccountField();
|
||||||
|
activeUsers.parsedName=getContext().getString(R.string.mo_instance_users);
|
||||||
|
activeUsers.parsedValue= NumberFormat.getInstance().format(instance.stats.userCount);
|
||||||
|
fields.add(activeUsers);
|
||||||
|
|
||||||
|
AccountField statusCount = new AccountField();
|
||||||
|
statusCount.parsedName=getContext().getString(R.string.mo_instance_status);
|
||||||
|
statusCount.parsedValue= NumberFormat.getInstance().format(instance.stats.statusCount);
|
||||||
|
fields.add(statusCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountField registration = new AccountField();
|
||||||
|
registration.parsedName=getContext().getString(R.string.mo_instance_registration);
|
||||||
|
registration.parsedValue=getContext().getString(instance.registrations ? instance.approvalRequired ? R.string.mo_instance_registration_approval : R.string.mo_instance_registration_open : R.string.instance_signup_closed);
|
||||||
|
fields.add(registration);
|
||||||
|
|
||||||
|
setFields(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpannableStringBuilder buildLinkText(String link, String text) {
|
||||||
|
String value = "<span class=\"h-card\"><a href=" + link + " class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">" + text + "</a></span>";
|
||||||
|
return HtmlParser.parse(value, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collapseDescription() {
|
||||||
|
textScrollView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
description.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(textWrap.getWidth(), View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
|
||||||
|
|
||||||
|
readMore.setText(isExpanded ? R.string.sk_collapse : R.string.sk_expand);
|
||||||
|
description.post(() -> {
|
||||||
|
boolean tooBig = description.getMeasuredHeight() > textMaxHeight;
|
||||||
|
readMore.setVisibility(tooBig ? View.VISIBLE : View.GONE);
|
||||||
|
textScrollView.setLayoutParams(tooBig && !isExpanded ? collapseParams : wrapParams);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateToolbar(){
|
||||||
|
getToolbar().setBackgroundColor(0);
|
||||||
|
if(toolbarTitleView!=null){
|
||||||
|
toolbarTitleView.setTranslationY(titleTransY);
|
||||||
|
toolbarSubtitleView.setTranslationY(titleTransY);
|
||||||
|
}
|
||||||
|
getToolbar().setOnClickListener(v->scrollToTop());
|
||||||
|
getToolbar().setNavigationContentDescription(R.string.back);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scrollToTop(){
|
||||||
|
scrollView.smoothScrollTo(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
|
||||||
|
inflater.inflate(R.menu.instance_info, menu);
|
||||||
|
UiUtils.enableOptionsMenuIcons(getActivity(), menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item){
|
||||||
|
int id=item.getItemId();
|
||||||
|
if (id==R.id.open_timeline) {
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
args.putString("domain", instance.uri);
|
||||||
|
Nav.go(getActivity(), CustomLocalTimelineFragment.class, args);
|
||||||
|
}else if (id==R.id.rules) {
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putParcelable("instance", Parcels.wrap(instance));
|
||||||
|
Nav.go(getActivity(), InstanceRulesFragment.class, args);
|
||||||
|
} else if (id==R.id.moderated_servers) {
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putParcelable("instance", Parcels.wrap(instance));
|
||||||
|
Nav.go(getActivity(), InstanceBlockListFragment.class, args);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean wantsLightStatusBar(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected int getToolbarResource(){
|
||||||
|
return R.layout.profile_toolbar;
|
||||||
|
}
|
||||||
|
private void onReadMoreClick(View view) {
|
||||||
|
isExpanded = !isExpanded;
|
||||||
|
bindViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void onCoverClick(View v){
|
||||||
|
Drawable drawable=cover.getDrawable();
|
||||||
|
if(drawable==null || drawable instanceof ColorDrawable)
|
||||||
|
return;
|
||||||
|
new PhotoViewer(getActivity(), Attachment.createFakeAttachments(instance.thumbnail, drawable), 0,
|
||||||
|
new SingleImagePhotoViewerListener(cover, cover, null, this, () -> {
|
||||||
|
}, () -> drawable, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFields(ArrayList<AccountField> fields){
|
||||||
|
metadataListData=fields;
|
||||||
|
if (adapter != null) adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MetadataAdapter extends UsableRecyclerView.Adapter<BaseViewHolder> {
|
||||||
|
public MetadataAdapter(){
|
||||||
|
super(imgLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||||
|
return new AboutViewHolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(BaseViewHolder holder, int position){
|
||||||
|
holder.bind(metadataListData.get(position));
|
||||||
|
super.onBindViewHolder(holder, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount(){
|
||||||
|
return metadataListData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class BaseViewHolder extends BindableViewHolder<AccountField> {
|
||||||
|
public BaseViewHolder(int layout){
|
||||||
|
super(getActivity(), layout, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AboutViewHolder extends BaseViewHolder {
|
||||||
|
private final TextView title;
|
||||||
|
private final LinkedTextView value;
|
||||||
|
|
||||||
|
public AboutViewHolder(){
|
||||||
|
super(R.layout.item_profile_about);
|
||||||
|
title=findViewById(R.id.title);
|
||||||
|
value=findViewById(R.id.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(AccountField item){
|
||||||
|
title.setText(item.parsedName);
|
||||||
|
value.setText(item.parsedValue);
|
||||||
|
value.setTextColor(UiUtils.getThemeColor(getActivity(), android.R.attr.textColorPrimary));
|
||||||
|
value.setLinkTextColor(UiUtils.getThemeColor(getActivity(), android.R.attr.colorAccent));
|
||||||
|
value.setCompoundDrawables(null, null, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import android.os.Bundle;
|
||||||
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;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
@ -382,6 +383,16 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
followersBtn.setOnClickListener(this::onFollowersOrFollowingClick);
|
followersBtn.setOnClickListener(this::onFollowersOrFollowingClick);
|
||||||
followingBtn.setOnClickListener(this::onFollowersOrFollowingClick);
|
followingBtn.setOnClickListener(this::onFollowersOrFollowingClick);
|
||||||
|
|
||||||
|
|
||||||
|
//this currently takes up the whole username
|
||||||
|
//in the future it might need to be change to only the instance uri
|
||||||
|
username.setOnClickListener(v -> {
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
args.putString("instanceDomain", Uri.parse(account.url).getHost());
|
||||||
|
Nav.go(getActivity(), InstanceInfoFragment.class, args);
|
||||||
|
});
|
||||||
|
|
||||||
username.setOnLongClickListener(v->{
|
username.setOnLongClickListener(v->{
|
||||||
String usernameString=account.acct;
|
String usernameString=account.acct;
|
||||||
if(!usernameString.contains("@")){
|
if(!usernameString.contains("@")){
|
||||||
|
@ -1132,16 +1143,6 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Attachment> createFakeAttachments(String url, Drawable drawable){
|
|
||||||
Attachment att=new Attachment();
|
|
||||||
att.type=Attachment.Type.IMAGE;
|
|
||||||
att.url=url;
|
|
||||||
att.meta=new Attachment.Metadata();
|
|
||||||
att.meta.width=drawable.getIntrinsicWidth();
|
|
||||||
att.meta.height=drawable.getIntrinsicHeight();
|
|
||||||
return Collections.singletonList(att);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onNotifyButtonClick(View v) {
|
private void onNotifyButtonClick(View v) {
|
||||||
UiUtils.performToggleAccountNotifications(getActivity(), account, accountID, relationship, actionButton, this::setNotifyProgressVisible, this::updateRelationship);
|
UiUtils.performToggleAccountNotifications(getActivity(), account, accountID, relationship, actionButton, this::setNotifyProgressVisible, this::updateRelationship);
|
||||||
}
|
}
|
||||||
|
@ -1154,7 +1155,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
if(ava==null)
|
if(ava==null)
|
||||||
return;
|
return;
|
||||||
int radius=V.dp(25);
|
int radius=V.dp(25);
|
||||||
currentPhotoViewer=new PhotoViewer(getActivity(), createFakeAttachments(account.avatar, ava), 0,
|
currentPhotoViewer=new PhotoViewer(getActivity(), Attachment.createFakeAttachments(account.avatar, ava), 0,
|
||||||
new SingleImagePhotoViewerListener(avatar, avatarBorder, new int[]{radius, radius, radius, radius}, this, ()->currentPhotoViewer=null, ()->ava, null, null));
|
new SingleImagePhotoViewerListener(avatar, avatarBorder, new int[]{radius, radius, radius, radius}, this, ()->currentPhotoViewer=null, ()->ava, null, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1166,7 +1167,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
Drawable drawable=cover.getDrawable();
|
Drawable drawable=cover.getDrawable();
|
||||||
if(drawable==null || drawable instanceof ColorDrawable)
|
if(drawable==null || drawable instanceof ColorDrawable)
|
||||||
return;
|
return;
|
||||||
currentPhotoViewer=new PhotoViewer(getActivity(), createFakeAttachments(account.header, drawable), 0,
|
currentPhotoViewer=new PhotoViewer(getActivity(), Attachment.createFakeAttachments(account.header, drawable), 0,
|
||||||
new SingleImagePhotoViewerListener(cover, cover, null, this, ()->currentPhotoViewer=null, ()->drawable, ()->avatarBorder.setTranslationZ(2), ()->avatarBorder.setTranslationZ(0)));
|
new SingleImagePhotoViewerListener(cover, cover, null, this, ()->currentPhotoViewer=null, ()->drawable, ()->avatarBorder.setTranslationZ(2), ()->avatarBorder.setTranslationZ(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ import org.parceler.Parcel;
|
||||||
import org.parceler.ParcelConstructor;
|
import org.parceler.ParcelConstructor;
|
||||||
import org.parceler.ParcelProperty;
|
import org.parceler.ParcelProperty;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Parcel
|
@Parcel
|
||||||
|
@ -44,6 +46,16 @@ public class Attachment extends BaseModel{
|
||||||
blurhashPlaceholder=new BlurHashDrawable(placeholder, getWidth(), getHeight());
|
blurhashPlaceholder=new BlurHashDrawable(placeholder, getWidth(), getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static List<Attachment> createFakeAttachments(String url, Drawable drawable){
|
||||||
|
Attachment att=new Attachment();
|
||||||
|
att.type=Attachment.Type.IMAGE;
|
||||||
|
att.url=url;
|
||||||
|
att.meta=new Attachment.Metadata();
|
||||||
|
att.meta.width=drawable.getIntrinsicWidth();
|
||||||
|
att.meta.height=drawable.getIntrinsicHeight();
|
||||||
|
return Collections.singletonList(att);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getWidth(){
|
public int getWidth(){
|
||||||
if(meta==null)
|
if(meta==null)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.RequiredField;
|
||||||
|
import org.parceler.Parcel;
|
||||||
|
|
||||||
|
@Parcel
|
||||||
|
public class DomainBlock extends BaseModel {
|
||||||
|
@RequiredField
|
||||||
|
public String domain;
|
||||||
|
@RequiredField
|
||||||
|
public String digest;
|
||||||
|
@RequiredField
|
||||||
|
public Severity severity;
|
||||||
|
public String comment;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DomainBlock{" +
|
||||||
|
"domain='" + domain + '\'' +
|
||||||
|
", digest='" + digest + '\'' +
|
||||||
|
", severity='" + severity + '\'' +
|
||||||
|
", comment='" + comment + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.RequiredField;
|
||||||
|
import org.parceler.Parcel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Parcel
|
||||||
|
public class ExtendedDescription extends BaseModel{
|
||||||
|
@RequiredField
|
||||||
|
public String content;
|
||||||
|
public String updatedAt;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ExtendedDescription{" +
|
||||||
|
"content='" + content + '\'' +
|
||||||
|
", updatedAt='" + updatedAt + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import org.parceler.Parcel;
|
||||||
|
|
||||||
|
public enum Severity {
|
||||||
|
@SerializedName("silence")
|
||||||
|
SILENCE,
|
||||||
|
@SerializedName("suspend")
|
||||||
|
SUSPEND
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.RequiredField;
|
||||||
|
import org.parceler.Parcel;
|
||||||
|
|
||||||
|
@Parcel
|
||||||
|
public class WeeklyActivity extends BaseModel {
|
||||||
|
@RequiredField
|
||||||
|
public String week;
|
||||||
|
@RequiredField
|
||||||
|
public int statuses;
|
||||||
|
@RequiredField
|
||||||
|
public int logins;
|
||||||
|
@RequiredField
|
||||||
|
public int registrations;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "WeeklyActivity{" +
|
||||||
|
"week=" + week +
|
||||||
|
", statuses=" + statuses +
|
||||||
|
", logins=" + logins +
|
||||||
|
", registrations=" + registrations +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -920,6 +920,8 @@ public class UiUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add icons to the menu.
|
||||||
|
/// Passing in items will be colored to be visible on the background.
|
||||||
public static void enableOptionsMenuIcons(Context context, Menu menu, @IdRes int... asAction) {
|
public static void enableOptionsMenuIcons(Context context, Menu menu, @IdRes int... asAction) {
|
||||||
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
|
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<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="M13.25,14.5C13.25,15.052 12.802,15.5 12.25,15.5C11.698,15.5 11.25,15.052 11.25,14.5C11.25,13.948 11.698,13.5 12.25,13.5C12.802,13.5 13.25,13.948 13.25,14.5ZM11.5,6.75L11.5,11.75C11.5,12.164 11.836,12.5 12.25,12.5C12.664,12.5 13,12.164 13,11.75V6.75C13,6.336 12.664,6 12.25,6C11.836,6 11.5,6.336 11.5,6.75ZM4,4.5C4,3.119 5.119,2 6.5,2H18C19.381,2 20.5,3.119 20.5,4.5V18.75C20.5,19.164 20.164,19.5 19.75,19.5H5.5C5.5,20.052 5.948,20.5 6.5,20.5H19.75C20.164,20.5 20.5,20.836 20.5,21.25C20.5,21.664 20.164,22 19.75,22H6.5C5.119,22 4,20.881 4,19.5V4.5ZM19,18V4.5C19,3.948 18.552,3.5 18,3.5H6.5C5.948,3.5 5.5,3.948 5.5,4.5V18H19Z"
|
||||||
|
android:fillColor="@color/fluent_default_icon_tint"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="28dp" android:height="28dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path android:pathData="M3.75 5C3.336 5 3 5.336 3 5.75V11c0 5.001 2.958 8.676 8.725 10.948 0.177 0.07 0.373 0.07 0.55 0 0.144-0.057 0.286-0.114 0.426-0.173-0.659-0.475-1.225-1.071-1.667-1.756C6.64 17.962 4.5 14.975 4.5 11V6.478c2.577-0.152 5.08-1.09 7.5-2.8 2.42 1.71 4.923 2.648 7.5 2.8v4.254c0.54 0.282 1.037 0.638 1.475 1.054C20.992 11.528 21 11.266 21 11V5.75C21 5.336 20.664 5 20.25 5c-2.663 0-5.258-0.944-7.8-2.85-0.267-0.2-0.633-0.2-0.9 0C9.008 4.056 6.413 5 3.75 5zM16.5 22c3.038 0 5.5-2.462 5.5-5.5S19.538 11 16.5 11 11 13.462 11 16.5s2.462 5.5 5.5 5.5zm-3.309-3.252c-0.436-0.64-0.691-1.415-0.691-2.248 0-2.21 1.79-4 4-4 0.834 0 1.608 0.255 2.248 0.691l-5.557 5.557zm1.06 1.06l5.558-5.556c0.436 0.64 0.691 1.414 0.691 2.248 0 2.21-1.79 4-4 4-0.834 0-1.607-0.255-2.248-0.691z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<me.grishka.appkit.views.RecursiveSwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/refresh_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@id/scroll_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false">
|
||||||
|
|
||||||
|
<org.joinmastodon.android.ui.views.CoverImageView
|
||||||
|
android:id="@+id/cover"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:background="?profileHeaderBackground"
|
||||||
|
android:contentDescription="@string/profile_header"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/text_wrap"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/cover"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/uri"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textAppearance="@style/m3_headline_small"
|
||||||
|
tools:text="floss.social" />
|
||||||
|
|
||||||
|
|
||||||
|
<org.joinmastodon.android.ui.views.UntouchableScrollView
|
||||||
|
android:id="@+id/text_scroll_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fadingEdgeLength="36dp"
|
||||||
|
android:requiresFadingEdge="vertical"
|
||||||
|
android:scrollbars="none">
|
||||||
|
|
||||||
|
<org.joinmastodon.android.ui.views.LinkedTextView
|
||||||
|
android:id="@+id/description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:textAppearance="@style/m3_body_large"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
</org.joinmastodon.android.ui.views.UntouchableScrollView>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/read_more"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:background="@drawable/bg_text_button"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
|
android:text="@string/sk_expand"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textAppearance="@style/m3_label_medium"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/border_top"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0.5dp"
|
||||||
|
android:layout_below="@id/text_wrap"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:background="?attr/colorPollVoted" />
|
||||||
|
|
||||||
|
<me.grishka.appkit.views.UsableRecyclerView
|
||||||
|
android:id="@+id/metadata"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/border_top"
|
||||||
|
android:background="?colorBackgroundLightest"
|
||||||
|
android:paddingTop="4dp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</me.grishka.appkit.views.RecursiveSwipeRefreshLayout>
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?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="wrap_content"
|
||||||
|
android:paddingTop="12dp"
|
||||||
|
android:paddingEnd="24dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="6dip"
|
||||||
|
android:layout_marginTop="6dip"
|
||||||
|
android:layout_marginBottom="6dip"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<TextView android:id="@+id/instance"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:fadingEdge="horizontal" />
|
||||||
|
|
||||||
|
<TextView android:id="@+id/reason"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/instance"
|
||||||
|
android:layout_alignStart="@id/instance"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:maxLines="4" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/severity"
|
||||||
|
android:src="@drawable/ic_fluent_speaker_mute_28_regular"
|
||||||
|
android:contentDescription="@string/mo_severity_silence"
|
||||||
|
android:minHeight="32dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@+id/open_timeline" android:title="@string/mo_instance_info_open_timeline" android:icon="@drawable/ic_fluent_timeline_24_regular"/>
|
||||||
|
<item android:id="@+id/rules" android:title="@string/instance_rules_title" android:icon="@drawable/ic_fluent_task_list_ltr_24_regular"/>
|
||||||
|
<item android:id="@+id/moderated_servers" android:title="@string/mo_instance_info_moderated_servers" android:icon="@drawable/ic_fluent_book_exclamation_mark_24_regular"/>
|
||||||
|
</menu>
|
|
@ -3,4 +3,6 @@
|
||||||
<dimen name="text_max_height">220dp</dimen>
|
<dimen name="text_max_height">220dp</dimen>
|
||||||
<dimen name="text_collapsed_height">145dp</dimen>
|
<dimen name="text_collapsed_height">145dp</dimen>
|
||||||
<dimen name="layout_max_width">450dp</dimen>
|
<dimen name="layout_max_width">450dp</dimen>
|
||||||
|
<dimen name="description_max_height">1000dp</dimen>
|
||||||
|
<dimen name="description_collapsed_height">445dp</dimen>
|
||||||
</resources>
|
</resources>
|
|
@ -57,4 +57,16 @@
|
||||||
<string name="mo_mention_reblogger_automatically">Automatically mention account who reblogged the post in replies</string>
|
<string name="mo_mention_reblogger_automatically">Automatically mention account who reblogged the post in replies</string>
|
||||||
<string name="mo_confirm_unfollow_title">Unfollow Account</string>
|
<string name="mo_confirm_unfollow_title">Unfollow Account</string>
|
||||||
<string name="mo_confirm_unfollow">Confirm to unfollow %s</string>
|
<string name="mo_confirm_unfollow">Confirm to unfollow %s</string>
|
||||||
|
|
||||||
|
<string name="mo_instance_admin">Administered by</string>
|
||||||
|
<string name="mo_instance_contact">Contact</string>
|
||||||
|
<string name="mo_instance_users">Users</string>
|
||||||
|
<string name="mo_instance_status">Status</string>
|
||||||
|
<string name="mo_instance_registration">Registration</string>
|
||||||
|
<string name="mo_instance_registration_open">Open</string>
|
||||||
|
<string name="mo_instance_registration_approval">Approval required</string>
|
||||||
|
<string name="mo_instance_info_open_timeline">Local timeline</string>
|
||||||
|
<string name="mo_instance_info_moderated_servers">Moderated servers</string>
|
||||||
|
<string name="mo_severity_silence">Silenced</string>
|
||||||
|
<string name="mo_severity_suspend">Blocked</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue