parent
a2ea8e76fb
commit
a200701e4c
|
@ -11,6 +11,7 @@ import org.joinmastodon.android.ui.utils.BlurHashDecoder;
|
|||
import org.joinmastodon.android.ui.utils.BlurHashDrawable;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Parcel
|
||||
|
@ -34,11 +35,14 @@ public class Card extends BaseModel{
|
|||
public String embedUrl;
|
||||
public String blurhash;
|
||||
public List<History> history;
|
||||
public Instant publishedAt;
|
||||
|
||||
public transient Drawable blurhashPlaceholder;
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
if(type==null)
|
||||
type=Type.LINK;
|
||||
super.postprocess();
|
||||
if(blurhash!=null){
|
||||
Bitmap placeholder=BlurHashDecoder.decode(blurhash, 16, 16);
|
||||
|
@ -64,6 +68,7 @@ public class Card extends BaseModel{
|
|||
", embedUrl='"+embedUrl+'\''+
|
||||
", blurhash='"+blurhash+'\''+
|
||||
", history="+history+
|
||||
", publishedAt="+publishedAt+
|
||||
'}';
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
@ -13,6 +15,7 @@ import org.joinmastodon.android.R;
|
|||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Card;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.drawables.BlurhashCrossfadeDrawable;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
|
@ -35,7 +38,7 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
|
|||
|
||||
@Override
|
||||
public Type getType(){
|
||||
return Type.CARD;
|
||||
return status.card.type==Card.Type.VIDEO || (status.card.image!=null && status.card.width>status.card.height) ? Type.CARD_LARGE : Type.CARD_COMPACT;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,36 +52,65 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
|
|||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<LinkCardStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView title, description, domain;
|
||||
private final TextView title, description, domain, timestamp;
|
||||
private final ImageView photo;
|
||||
private BlurhashCrossfadeDrawable crossfadeDrawable=new BlurhashCrossfadeDrawable();
|
||||
private boolean didClear;
|
||||
private final View inner;
|
||||
private final boolean isLarge;
|
||||
|
||||
public Holder(Context context, ViewGroup parent){
|
||||
super(context, R.layout.display_item_link_card, parent);
|
||||
public Holder(Context context, ViewGroup parent, boolean isLarge){
|
||||
super(context, isLarge ? R.layout.display_item_link_card : R.layout.display_item_link_card_compact, parent);
|
||||
this.isLarge=isLarge;
|
||||
title=findViewById(R.id.title);
|
||||
description=findViewById(R.id.description);
|
||||
domain=findViewById(R.id.domain);
|
||||
timestamp=findViewById(R.id.timestamp);
|
||||
photo=findViewById(R.id.photo);
|
||||
findViewById(R.id.inner).setOnClickListener(this::onClick);
|
||||
inner=findViewById(R.id.inner);
|
||||
inner.setOnClickListener(this::onClick);
|
||||
inner.setOutlineProvider(OutlineProviders.roundedRect(12));
|
||||
inner.setClipToOutline(true);
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void onBind(LinkCardStatusDisplayItem item){
|
||||
Card card=item.status.card;
|
||||
title.setText(card.title);
|
||||
description.setText(card.description);
|
||||
description.setVisibility(TextUtils.isEmpty(card.description) ? View.GONE : View.VISIBLE);
|
||||
domain.setText(Uri.parse(card.url).getHost());
|
||||
if(description!=null){
|
||||
description.setText(card.description);
|
||||
description.setVisibility(TextUtils.isEmpty(card.description) ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
String cardDomain=Uri.parse(card.url).getHost();
|
||||
if(isLarge && !TextUtils.isEmpty(card.authorName)){
|
||||
domain.setText(itemView.getContext().getString(R.string.article_by_author, card.authorName)+" · "+cardDomain);
|
||||
}else{
|
||||
domain.setText(cardDomain);
|
||||
}
|
||||
if(card.publishedAt!=null){
|
||||
timestamp.setVisibility(View.VISIBLE);
|
||||
timestamp.setText(" · "+UiUtils.formatRelativeTimestamp(itemView.getContext(), card.publishedAt));
|
||||
}else{
|
||||
timestamp.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
photo.setImageDrawable(null);
|
||||
if(item.imgRequest!=null){
|
||||
photo.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
photo.setBackground(null);
|
||||
photo.setImageTintList(null);
|
||||
crossfadeDrawable.setSize(card.width, card.height);
|
||||
crossfadeDrawable.setBlurhashDrawable(card.blurhashPlaceholder);
|
||||
crossfadeDrawable.setCrossfadeAlpha(0f);
|
||||
photo.setImageDrawable(null);
|
||||
photo.setImageDrawable(crossfadeDrawable);
|
||||
didClear=false;
|
||||
}else{
|
||||
photo.setBackgroundColor(UiUtils.getThemeColor(itemView.getContext(), R.attr.colorM3SurfaceVariant));
|
||||
photo.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(itemView.getContext(), R.attr.colorM3Outline)));
|
||||
photo.setScaleType(ImageView.ScaleType.CENTER);
|
||||
photo.setImageResource(R.drawable.ic_feed_48px);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,8 @@ public abstract class StatusDisplayItem{
|
|||
case AUDIO -> new AudioStatusDisplayItem.Holder(activity, parent);
|
||||
case POLL_OPTION -> new PollOptionStatusDisplayItem.Holder(activity, parent);
|
||||
case POLL_FOOTER -> new PollFooterStatusDisplayItem.Holder(activity, parent);
|
||||
case CARD -> new LinkCardStatusDisplayItem.Holder(activity, parent);
|
||||
case CARD_LARGE -> new LinkCardStatusDisplayItem.Holder(activity, parent, true);
|
||||
case CARD_COMPACT -> new LinkCardStatusDisplayItem.Holder(activity, parent, false);
|
||||
case FOOTER -> new FooterStatusDisplayItem.Holder(activity, parent);
|
||||
case ACCOUNT -> new AccountStatusDisplayItem.Holder(new AccountViewHolder(parentFragment, parent, null));
|
||||
case HASHTAG -> new HashtagStatusDisplayItem.Holder(activity, parent);
|
||||
|
@ -208,7 +209,8 @@ public abstract class StatusDisplayItem{
|
|||
AUDIO,
|
||||
POLL_OPTION,
|
||||
POLL_FOOTER,
|
||||
CARD,
|
||||
CARD_LARGE,
|
||||
CARD_COMPACT,
|
||||
FOOTER,
|
||||
ACCOUNT,
|
||||
HASHTAG,
|
||||
|
|
|
@ -87,7 +87,7 @@ public class InsetStatusItemDecoration extends RecyclerView.ItemDecoration{
|
|||
boolean topSiblingInset=pos>0 && displayItems.get(pos-1).inset;
|
||||
boolean bottomSiblingInset=pos<displayItems.size()-1 && displayItems.get(pos+1).inset;
|
||||
StatusDisplayItem.Type type=sdi.getItem().getType();
|
||||
if(type==StatusDisplayItem.Type.CARD || type==StatusDisplayItem.Type.MEDIA_GRID)
|
||||
if(type==StatusDisplayItem.Type.CARD_LARGE || type==StatusDisplayItem.Type.MEDIA_GRID)
|
||||
outRect.left=outRect.right=V.dp(16);
|
||||
else
|
||||
outRect.left=outRect.right=V.dp(8);
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package org.joinmastodon.android.ui.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
|
||||
public class FixedAspectRatioImageView extends ImageView{
|
||||
private float aspectRatio=1;
|
||||
private float aspectRatio;
|
||||
private boolean useHeight;
|
||||
|
||||
public FixedAspectRatioImageView(Context context){
|
||||
|
@ -18,6 +21,10 @@ public class FixedAspectRatioImageView extends ImageView{
|
|||
|
||||
public FixedAspectRatioImageView(Context context, AttributeSet attrs, int defStyle){
|
||||
super(context, attrs, defStyle);
|
||||
TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.FixedAspectRatioImageView);
|
||||
aspectRatio=ta.getFloat(R.styleable.FixedAspectRatioImageView_aspectRatio, 1);
|
||||
useHeight=ta.getBoolean(R.styleable.FixedAspectRatioImageView_useHeight, false);
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/m3_on_surface_overlay">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape>
|
||||
<corners android:radius="11dp"/>
|
||||
<solid android:color="#000"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape>
|
||||
<corners android:radius="11dp"/>
|
||||
<stroke android:color="?colorM3OutlineVariant" android:width="1dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M9,42Q7.8,42 6.9,41.1Q6,40.2 6,39V9Q6,7.8 6.9,6.9Q7.8,6 9,6H32.1L42,15.9V39Q42,40.2 41.1,41.1Q40.2,42 39,42ZM9,39H39Q39,39 39,39Q39,39 39,39V17.55H30.45V9H9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39ZM13.95,33.45H34.05V30.45H13.95ZM13.95,17.55H24V14.55H13.95ZM13.95,25.5H34.05V22.5H13.95ZM9,9V17.55V9V17.55V39Q9,39 9,39Q9,39 9,39Q9,39 9,39Q9,39 9,39V9Q9,9 9,9Q9,9 9,9Z"/>
|
||||
</vector>
|
|
@ -3,54 +3,75 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<org.joinmastodon.android.ui.views.MaxWidthFrameLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/inner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:foreground="?android:selectableItemBackground"
|
||||
android:orientation="vertical"
|
||||
android:foreground="@drawable/fg_link_card"
|
||||
android:padding="1dp"
|
||||
android:maxWidth="400dp">
|
||||
<ImageView
|
||||
<org.joinmastodon.android.ui.views.FixedAspectRatioImageView
|
||||
android:id="@+id/photo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"
|
||||
android:importantForAccessibility="no"
|
||||
app:aspectRatio="1.7777777778"
|
||||
tools:src="#0f0"/>
|
||||
<LinearLayout
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:padding="8dp"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/window_bg_alpha95">
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="Link title"/>
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="Link description"/>
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:maxLines="3"
|
||||
android:ellipsize="end"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="Link title"/>
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="Link description"/>
|
||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="16dp">
|
||||
<TextView
|
||||
android:id="@+id/domain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="example.com"/>
|
||||
</LinearLayout>
|
||||
</org.joinmastodon.android.ui.views.MaxWidthFrameLayout>
|
||||
<TextView
|
||||
android:id="@+id/timestamp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="example.com"/>
|
||||
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/inner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="128dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:foreground="@drawable/fg_link_card"
|
||||
android:padding="1dp"
|
||||
android:maxWidth="400dp">
|
||||
<ImageView
|
||||
android:id="@+id/photo"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="128dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:scaleType="centerCrop"
|
||||
android:importantForAccessibility="no"
|
||||
tools:src="#0f0"/>
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_toStartOf="@id/photo"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:maxLines="3"
|
||||
android:ellipsize="end"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="Link title"/>
|
||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toStartOf="@id/photo"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="16dp">
|
||||
<TextView
|
||||
android:id="@+id/domain"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="example.com"/>
|
||||
<TextView
|
||||
android:id="@+id/timestamp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="example.com"/>
|
||||
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -54,4 +54,9 @@
|
|||
<attr name="android:verticalGap" format="dimension"/>
|
||||
<attr name="android:horizontalGap" format="dimension"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="FixedAspectRatioImageView">
|
||||
<attr name="aspectRatio" format="float"/>
|
||||
<attr name="useHeight" format="boolean"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
|
@ -665,4 +665,5 @@
|
|||
<string name="app_version_copied">Version number copied to clipboard</string>
|
||||
<string name="onboarding_recommendations_intro">You curate your own home feed.
The more people you follow, the more active and interesting it will be.</string>
|
||||
<string name="onboarding_recommendations_title">Personalize your home feed</string>
|
||||
<string name="article_by_author">By %s</string>
|
||||
</resources>
|
|
@ -375,6 +375,7 @@
|
|||
<style name="m3_body_medium">
|
||||
<item name="android:textSize">14dp</item>
|
||||
<item name="android:lineSpacingExtra">4dp</item>
|
||||
<item name="android:lineHeight">20dp</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_body_small">
|
||||
|
@ -386,6 +387,7 @@
|
|||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textSize">16dp</item>
|
||||
<item name="android:lineSpacingExtra">5dp</item>
|
||||
<item name="android:lineHeight">24dp</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_title_small">
|
||||
|
|
Loading…
Reference in New Issue