That fuck shit the fascists are using
at master 285 lines 10 kB view raw
1package org.tm.archive.components; 2 3import android.content.Context; 4import android.content.res.TypedArray; 5import android.graphics.Canvas; 6import android.graphics.Color; 7import android.os.Bundle; 8import android.os.Parcelable; 9import android.util.AttributeSet; 10import android.view.View; 11import android.view.ViewGroup; 12import android.widget.FrameLayout; 13import android.widget.TextView; 14 15import androidx.annotation.NonNull; 16import androidx.annotation.Nullable; 17import androidx.annotation.StringRes; 18 19import com.bumptech.glide.RequestManager; 20 21import org.signal.ringrtc.CallLinkRootKey; 22import org.tm.archive.R; 23import org.tm.archive.calls.links.CallLinks; 24import org.tm.archive.conversation.colors.AvatarColorHash; 25import org.tm.archive.linkpreview.LinkPreview; 26import org.tm.archive.linkpreview.LinkPreviewRepository; 27import org.tm.archive.mms.ImageSlide; 28import org.tm.archive.mms.SlidesClickedListener; 29import org.tm.archive.recipients.Recipient; 30import org.tm.archive.util.Util; 31import org.tm.archive.util.ViewUtil; 32import org.tm.archive.util.views.Stub; 33 34import java.text.DateFormat; 35import java.text.SimpleDateFormat; 36import java.util.Locale; 37 38import okhttp3.HttpUrl; 39 40/** 41 * The view shown in the compose box or conversation that represents the state of the link preview. 42 */ 43public class LinkPreviewView extends FrameLayout { 44 45 private static final String STATE_ROOT = "linkPreviewView.state.root"; 46 private static final String STATE_STATE = "linkPreviewView.state.state"; 47 48 private static final int TYPE_CONVERSATION = 0; 49 private static final int TYPE_COMPOSE = 1; 50 51 private ViewGroup container; 52 private Stub<OutlinedThumbnailView> thumbnail; 53 private TextView title; 54 private TextView description; 55 private TextView site; 56 private View divider; 57 private View closeButton; 58 private View spinner; 59 private TextView noPreview; 60 61 private int type; 62 private int defaultRadius; 63 private CornerMask cornerMask; 64 private CloseClickedListener closeClickedListener; 65 private LinkPreviewViewThumbnailState thumbnailState = new LinkPreviewViewThumbnailState(); 66 67 public LinkPreviewView(Context context) { 68 super(context); 69 init(null); 70 } 71 72 public LinkPreviewView(Context context, @Nullable AttributeSet attrs) { 73 super(context, attrs); 74 init(attrs); 75 } 76 77 private void init(@Nullable AttributeSet attrs) { 78 inflate(getContext(), R.layout.link_preview, this); 79 80 container = findViewById(R.id.linkpreview_container); 81 thumbnail = new Stub<>(findViewById(R.id.linkpreview_thumbnail)); 82 title = findViewById(R.id.linkpreview_title); 83 description = findViewById(R.id.linkpreview_description); 84 site = findViewById(R.id.linkpreview_site); 85 divider = findViewById(R.id.linkpreview_divider); 86 spinner = findViewById(R.id.linkpreview_progress_wheel); 87 closeButton = findViewById(R.id.linkpreview_close); 88 noPreview = findViewById(R.id.linkpreview_no_preview); 89 defaultRadius = getResources().getDimensionPixelSize(R.dimen.thumbnail_default_radius); 90 cornerMask = new CornerMask(this); 91 92 if (attrs != null) { 93 TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.LinkPreviewView, 0, 0); 94 type = typedArray.getInt(R.styleable.LinkPreviewView_linkpreview_type, 0); 95 typedArray.recycle(); 96 } 97 98 if (type == TYPE_COMPOSE) { 99 container.setBackgroundColor(Color.TRANSPARENT); 100 container.setPadding(0, 0, 0, 0); 101 divider.setVisibility(VISIBLE); 102 closeButton.setVisibility(VISIBLE); 103 title.setMaxLines(2); 104 description.setMaxLines(2); 105 106 closeButton.setOnClickListener(v -> { 107 if (closeClickedListener != null) { 108 closeClickedListener.onCloseClicked(); 109 } 110 }); 111 } 112 113 setWillNotDraw(false); 114 } 115 116 @Override 117 protected @NonNull Parcelable onSaveInstanceState() { 118 Parcelable root = super.onSaveInstanceState(); 119 Bundle bundle = new Bundle(); 120 121 bundle.putParcelable(STATE_ROOT, root); 122 bundle.putParcelable(STATE_STATE, thumbnailState); 123 124 return bundle; 125 } 126 127 @Override 128 protected void onRestoreInstanceState(Parcelable state) { 129 if (state instanceof Bundle) { 130 Parcelable root = ((Bundle) state).getParcelable(STATE_ROOT); 131 thumbnailState = ((Bundle) state).getParcelable(STATE_STATE); 132 133 thumbnailState.applyState(thumbnail); 134 super.onRestoreInstanceState(root); 135 } else { 136 super.onRestoreInstanceState(state); 137 } 138 } 139 140 @Override 141 protected void dispatchDraw(Canvas canvas) { 142 super.dispatchDraw(canvas); 143 if (type == TYPE_COMPOSE) return; 144 145 cornerMask.mask(canvas); 146 } 147 148 public void setLoading() { 149 title.setVisibility(GONE); 150 site.setVisibility(GONE); 151 description.setVisibility(GONE); 152 thumbnail.setVisibility(GONE); 153 spinner.setVisibility(VISIBLE); 154 noPreview.setVisibility(INVISIBLE); 155 } 156 157 public void setNoPreview(@Nullable LinkPreviewRepository.Error customError) { 158 title.setVisibility(GONE); 159 site.setVisibility(GONE); 160 thumbnail.setVisibility(GONE); 161 spinner.setVisibility(GONE); 162 noPreview.setVisibility(VISIBLE); 163 noPreview.setText(getLinkPreviewErrorString(customError)); 164 } 165 166 public void setLinkPreview(@NonNull RequestManager requestManager, @NonNull LinkPreview linkPreview, boolean showThumbnail) { 167 setLinkPreview(requestManager, linkPreview, showThumbnail, true, false); 168 } 169 170 public void setLinkPreview(@NonNull RequestManager requestManager, @NonNull LinkPreview linkPreview, boolean showThumbnail, boolean showDescription, boolean scheduleMessageMode) { 171 spinner.setVisibility(GONE); 172 noPreview.setVisibility(GONE); 173 174 CallLinkRootKey callLinkRootKey = CallLinks.parseUrl(linkPreview.getUrl()); 175 if (!Util.isEmpty(linkPreview.getTitle())) { 176 title.setText(linkPreview.getTitle()); 177 title.setVisibility(VISIBLE); 178 } else if (callLinkRootKey != null) { 179 title.setText(R.string.Recipient_signal_call); 180 title.setVisibility(VISIBLE); 181 } else { 182 title.setVisibility(GONE); 183 } 184 185 if (showDescription && !Util.isEmpty(linkPreview.getDescription())) { 186 description.setText(linkPreview.getDescription()); 187 description.setVisibility(VISIBLE); 188 } else if (callLinkRootKey != null) { 189 description.setText(R.string.LinkPreviewView__use_this_link_to_join_a_signal_call); 190 description.setVisibility(VISIBLE); 191 } else { 192 description.setVisibility(GONE); 193 } 194 195 String domain = null; 196 197 if (!Util.isEmpty(linkPreview.getUrl())) { 198 HttpUrl url = HttpUrl.parse(linkPreview.getUrl()); 199 if (url != null) { 200 domain = url.topPrivateDomain(); 201 } 202 } 203 204 if (domain != null && linkPreview.getDate() > 0) { 205 site.setText(getContext().getString(R.string.LinkPreviewView_domain_date, domain, formatDate(linkPreview.getDate()))); 206 site.setVisibility(VISIBLE); 207 } else if (domain != null) { 208 site.setText(domain); 209 site.setVisibility(VISIBLE); 210 } else if (linkPreview.getDate() > 0) { 211 site.setText(formatDate(linkPreview.getDate())); 212 site.setVisibility(VISIBLE); 213 } else { 214 site.setVisibility(GONE); 215 } 216 217 if (showThumbnail && linkPreview.getThumbnail().isPresent()) { 218 thumbnail.setVisibility(VISIBLE); 219 thumbnailState.applyState(thumbnail); 220 thumbnail.get().setImageResource(requestManager, new ImageSlide(linkPreview.getThumbnail().get()), type == TYPE_CONVERSATION && !scheduleMessageMode, false); 221 thumbnail.get().showSecondaryText(false); 222 } else if (callLinkRootKey != null) { 223 thumbnail.setVisibility(VISIBLE); 224 thumbnailState.applyState(thumbnail); 225 thumbnail.get().setImageDrawable( 226 requestManager, 227 Recipient.DEFAULT_FALLBACK_PHOTO_PROVIDER 228 .getPhotoForCallLink() 229 .asDrawable(getContext(), 230 AvatarColorHash.forCallLink(callLinkRootKey.getKeyBytes())) 231 ); 232 thumbnail.get().showSecondaryText(false); 233 } else { 234 thumbnail.setVisibility(GONE); 235 } 236 } 237 238 public void setCorners(int topStart, int topEnd) { 239 if (ViewUtil.isRtl(this)) { 240 cornerMask.setRadii(topEnd, topStart, 0, 0); 241 thumbnailState = thumbnailState.copy( 242 defaultRadius, 243 topEnd, 244 defaultRadius, 245 defaultRadius, 246 thumbnailState.getDownloadListener() 247 ); 248 thumbnailState.applyState(thumbnail); 249 } else { 250 cornerMask.setRadii(topStart, topEnd, 0, 0); 251 thumbnailState.copy( 252 topStart, 253 defaultRadius, 254 defaultRadius, 255 defaultRadius, 256 thumbnailState.getDownloadListener() 257 ); 258 thumbnailState.applyState(thumbnail); 259 } 260 postInvalidate(); 261 } 262 263 public void setCloseClickedListener(@Nullable CloseClickedListener closeClickedListener) { 264 this.closeClickedListener = closeClickedListener; 265 } 266 267 public void setDownloadClickedListener(SlidesClickedListener listener) { 268 thumbnailState = thumbnailState.withDownloadListener(listener); 269 thumbnailState.applyState(thumbnail); 270 } 271 272 private @StringRes static int getLinkPreviewErrorString(@Nullable LinkPreviewRepository.Error customError) { 273 return customError == LinkPreviewRepository.Error.GROUP_LINK_INACTIVE ? R.string.LinkPreviewView_this_group_link_is_not_active 274 : R.string.LinkPreviewView_no_link_preview_available; 275 } 276 277 private static String formatDate(long date) { 278 DateFormat dateFormat = new SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()); 279 return dateFormat.format(date); 280 } 281 282 public interface CloseClickedListener { 283 void onCloseClicked(); 284 } 285}