Posts redesign wip
This commit is contained in:
parent
d6bcc9c156
commit
20799ef1a8
|
@ -69,6 +69,7 @@ dependencies {
|
|||
implementation 'me.grishka.litex:dynamicanimation:1.1.0-alpha03'
|
||||
implementation 'me.grishka.litex:viewpager:1.0.0'
|
||||
implementation 'me.grishka.litex:viewpager2:1.0.0'
|
||||
implementation 'me.grishka.litex:palette:1.0.0'
|
||||
implementation 'me.grishka.appkit:appkit:1.2.7'
|
||||
implementation 'com.google.code.gson:gson:2.8.9'
|
||||
implementation 'org.jsoup:jsoup:1.14.3'
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.joinmastodon.android.ui.text.HtmlParser;
|
|||
import org.parceler.Parcels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -57,6 +56,7 @@ public class AudioPlayerService extends Service{
|
|||
private static HashSet<Callback> callbacks=new HashSet<>();
|
||||
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener=this::onAudioFocusChanged;
|
||||
private boolean resumeAfterAudioFocusGain;
|
||||
private boolean isBuffering=true;
|
||||
|
||||
private BroadcastReceiver receiver=new BroadcastReceiver(){
|
||||
@Override
|
||||
|
@ -176,6 +176,7 @@ public class AudioPlayerService extends Service{
|
|||
player.setOnErrorListener(this::onPlayerError);
|
||||
player.setOnCompletionListener(this::onPlayerCompletion);
|
||||
player.setOnSeekCompleteListener(this::onPlayerSeekCompleted);
|
||||
player.setOnInfoListener(this::onPlayerInfo);
|
||||
try{
|
||||
player.setDataSource(this, Uri.parse(attachment.url));
|
||||
player.prepareAsync();
|
||||
|
@ -187,7 +188,9 @@ public class AudioPlayerService extends Service{
|
|||
}
|
||||
|
||||
private void onPlayerPrepared(MediaPlayer mp){
|
||||
Log.i(TAG, "onPlayerPrepared");
|
||||
playerReady=true;
|
||||
isBuffering=false;
|
||||
player.start();
|
||||
updateSessionState(false);
|
||||
}
|
||||
|
@ -205,6 +208,21 @@ public class AudioPlayerService extends Service{
|
|||
stopSelf();
|
||||
}
|
||||
|
||||
private boolean onPlayerInfo(MediaPlayer mp, int what, int extra){
|
||||
switch(what){
|
||||
case MediaPlayer.MEDIA_INFO_BUFFERING_START -> {
|
||||
isBuffering=true;
|
||||
updateSessionState(false);
|
||||
}
|
||||
case MediaPlayer.MEDIA_INFO_BUFFERING_END -> {
|
||||
isBuffering=false;
|
||||
updateSessionState(false);
|
||||
}
|
||||
default -> Log.i(TAG, "onPlayerInfo() called with: mp = ["+mp+"], what = ["+what+"], extra = ["+extra+"]");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onAudioFocusChanged(int change){
|
||||
switch(change){
|
||||
case AudioManager.AUDIOFOCUS_LOSS -> {
|
||||
|
@ -232,12 +250,16 @@ public class AudioPlayerService extends Service{
|
|||
|
||||
private void updateSessionState(boolean removeNotification){
|
||||
session.setPlaybackState(new PlaybackState.Builder()
|
||||
.setState(player.isPlaying() ? PlaybackState.STATE_PLAYING : PlaybackState.STATE_PAUSED, player.getCurrentPosition(), 1f)
|
||||
.setState(switch(getPlayState()){
|
||||
case PLAYING -> PlaybackState.STATE_PLAYING;
|
||||
case PAUSED -> PlaybackState.STATE_PAUSED;
|
||||
case BUFFERING -> PlaybackState.STATE_BUFFERING;
|
||||
}, player.getCurrentPosition(), 1f)
|
||||
.setActions(PlaybackState.ACTION_STOP | PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_SEEK_TO)
|
||||
.build());
|
||||
updateNotification(!player.isPlaying(), removeNotification);
|
||||
for(Callback cb:callbacks)
|
||||
cb.onPlayStateChanged(attachment.id, player.isPlaying(), player.getCurrentPosition());
|
||||
cb.onPlayStateChanged(attachment.id, getPlayState(), player.getCurrentPosition());
|
||||
}
|
||||
|
||||
private void updateNotification(boolean dismissable, boolean removeNotification){
|
||||
|
@ -310,6 +332,12 @@ public class AudioPlayerService extends Service{
|
|||
return attachment.id;
|
||||
}
|
||||
|
||||
public PlayState getPlayState(){
|
||||
if(isBuffering)
|
||||
return PlayState.BUFFERING;
|
||||
return player.isPlaying() ? PlayState.PLAYING : PlayState.PAUSED;
|
||||
}
|
||||
|
||||
public static void registerCallback(Callback cb){
|
||||
callbacks.add(cb);
|
||||
}
|
||||
|
@ -333,7 +361,13 @@ public class AudioPlayerService extends Service{
|
|||
}
|
||||
|
||||
public interface Callback{
|
||||
void onPlayStateChanged(String attachmentID, boolean playing, int position);
|
||||
void onPlayStateChanged(String attachmentID, PlayState state, int position);
|
||||
void onPlaybackStopped(String attachmentID);
|
||||
}
|
||||
|
||||
public enum PlayState{
|
||||
PLAYING,
|
||||
PAUSED,
|
||||
BUFFERING
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem;
|
|||
import org.joinmastodon.android.ui.displayitems.MediaGridStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.PollFooterStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.PollOptionStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.SpoilerStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
||||
|
@ -48,6 +49,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -405,25 +407,26 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
.exec(accountID);
|
||||
}
|
||||
|
||||
public void onRevealSpoilerClick(TextStatusDisplayItem.Holder holder){
|
||||
public void onRevealSpoilerClick(SpoilerStatusDisplayItem.Holder holder){
|
||||
Status status=holder.getItem().status;
|
||||
revealSpoiler(status, holder.getItemID());
|
||||
toggleSpoiler(status, holder.getItemID());
|
||||
}
|
||||
|
||||
public void onRevealSpoilerClick(MediaGridStatusDisplayItem.Holder holder){
|
||||
Status status=holder.getItem().status;
|
||||
revealSpoiler(status, holder.getItemID());
|
||||
}
|
||||
protected void toggleSpoiler(Status status, String itemID){
|
||||
status.spoilerRevealed=!status.spoilerRevealed;
|
||||
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
|
||||
if(spoiler!=null)
|
||||
spoiler.rebind();
|
||||
SpoilerStatusDisplayItem spoilerItem=Objects.requireNonNull(findItemOfType(itemID, SpoilerStatusDisplayItem.class));
|
||||
|
||||
protected void revealSpoiler(Status status, String itemID){
|
||||
status.spoilerRevealed=true;
|
||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
||||
if(text!=null)
|
||||
adapter.notifyItemChanged(text.getAbsoluteAdapterPosition()-getMainAdapterOffset());
|
||||
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
|
||||
if(header!=null)
|
||||
header.rebind();
|
||||
updateImagesSpoilerState(status, itemID);
|
||||
int index=displayItems.indexOf(spoilerItem);
|
||||
if(status.spoilerRevealed){
|
||||
displayItems.addAll(index+1, spoilerItem.contentItems);
|
||||
adapter.notifyItemRangeInserted(index+1, spoilerItem.contentItems.size());
|
||||
}else{
|
||||
displayItems.subList(index+1, index+1+spoilerItem.contentItems.size()).clear();
|
||||
adapter.notifyItemRangeRemoved(index+1, spoilerItem.contentItems.size());
|
||||
}
|
||||
}
|
||||
|
||||
public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder){
|
||||
|
|
|
@ -327,8 +327,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
|
||||
spoilerEdit=view.findViewById(R.id.content_warning);
|
||||
LayerDrawable spoilerBg=(LayerDrawable) spoilerEdit.getBackground().mutate();
|
||||
spoilerBg.setDrawableByLayerId(R.id.left_drawable, new SpoilerStripesDrawable());
|
||||
spoilerBg.setDrawableByLayerId(R.id.right_drawable, new SpoilerStripesDrawable());
|
||||
spoilerBg.setDrawableByLayerId(R.id.left_drawable, new SpoilerStripesDrawable(false));
|
||||
spoilerBg.setDrawableByLayerId(R.id.right_drawable, new SpoilerStripesDrawable(false));
|
||||
spoilerEdit.setBackground(spoilerBg);
|
||||
if((savedInstanceState!=null && savedInstanceState.getBoolean("hasSpoiler", false)) || hasSpoiler){
|
||||
hasSpoiler=true;
|
||||
|
|
|
@ -336,6 +336,8 @@ public class OnboardingFollowSuggestionsFragment extends BaseRecyclerFragment<Pa
|
|||
}
|
||||
|
||||
private void setActionProgressVisible(boolean visible){
|
||||
if(visible)
|
||||
actionProgress.setIndeterminateTintList(actionButton.getTextColors());
|
||||
actionButton.setTextVisible(!visible);
|
||||
actionProgress.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
actionButton.setClickable(!visible);
|
||||
|
|
|
@ -127,6 +127,7 @@ public class Attachment extends BaseModel{
|
|||
public PointF focus;
|
||||
public SizeMetadata original;
|
||||
public SizeMetadata small;
|
||||
public ColorsMetadata colors;
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
|
@ -138,6 +139,7 @@ public class Attachment extends BaseModel{
|
|||
", focus="+focus+
|
||||
", original="+original+
|
||||
", small="+small+
|
||||
", colors="+colors+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -161,4 +163,20 @@ public class Attachment extends BaseModel{
|
|||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@Parcel
|
||||
public static class ColorsMetadata{
|
||||
public String background;
|
||||
public String foreground;
|
||||
public String accent;
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "ColorsMetadata{"+
|
||||
"background='"+background+'\''+
|
||||
", foreground='"+foreground+'\''+
|
||||
", accent='"+accent+'\''+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,12 @@ public class OutlineProviders{
|
|||
outline.setAlpha(view.getAlpha());
|
||||
}
|
||||
};
|
||||
public static final ViewOutlineProvider OVAL=new ViewOutlineProvider(){
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline){
|
||||
outline.setOval(0, 0, view.getWidth(), view.getHeight());
|
||||
}
|
||||
};
|
||||
|
||||
public static ViewOutlineProvider roundedRect(int dp){
|
||||
ViewOutlineProvider provider=roundedRects.get(dp);
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -13,16 +23,27 @@ import org.joinmastodon.android.R;
|
|||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.drawables.AudioAttachmentBackgroundDrawable;
|
||||
import org.joinmastodon.android.ui.drawables.SeekBarThumbDrawable;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import androidx.palette.graphics.Palette;
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class AudioStatusDisplayItem extends StatusDisplayItem{
|
||||
public final Status status;
|
||||
public final Attachment attachment;
|
||||
private final ImageLoaderRequest imageRequest;
|
||||
|
||||
public AudioStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status, Attachment attachment){
|
||||
super(parentID, parentFragment);
|
||||
this.status=status;
|
||||
this.attachment=attachment;
|
||||
imageRequest=new UrlImageLoaderRequest(TextUtils.isEmpty(attachment.previewUrl) ? status.account.avatarStatic : attachment.previewUrl, V.dp(100), V.dp(100));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,25 +51,38 @@ public class AudioStatusDisplayItem extends StatusDisplayItem{
|
|||
return Type.AUDIO;
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<AudioStatusDisplayItem> implements AudioPlayerService.Callback{
|
||||
private final ImageButton playPauseBtn;
|
||||
@Override
|
||||
public int getImageCount(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageLoaderRequest getImageRequest(int index){
|
||||
return imageRequest;
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<AudioStatusDisplayItem> implements AudioPlayerService.Callback, ImageLoaderViewHolder{
|
||||
private final ImageButton playPauseBtn, forwardBtn, rewindBtn;
|
||||
private final TextView time;
|
||||
private final SeekBar seekBar;
|
||||
private final ImageView image;
|
||||
private final FrameLayout content;
|
||||
private final AudioAttachmentBackgroundDrawable bgDrawable;
|
||||
|
||||
private int lastKnownPosition;
|
||||
private long lastKnownPositionTime;
|
||||
private boolean playing;
|
||||
private int lastRemainingSeconds=-1;
|
||||
private boolean seekbarBeingDragged;
|
||||
private int lastPosSeconds=-1;
|
||||
private AudioPlayerService.PlayState state;
|
||||
|
||||
private Runnable positionUpdater=this::updatePosition;
|
||||
private final Runnable positionUpdater=this::updatePosition;
|
||||
|
||||
public Holder(Context context, ViewGroup parent){
|
||||
super(context, R.layout.display_item_audio, parent);
|
||||
playPauseBtn=findViewById(R.id.play_pause_btn);
|
||||
time=findViewById(R.id.time);
|
||||
seekBar=findViewById(R.id.seekbar);
|
||||
seekBar.setThumb(new SeekBarThumbDrawable(context));
|
||||
image=findViewById(R.id.image);
|
||||
content=findViewById(R.id.content);
|
||||
forwardBtn=findViewById(R.id.forward_btn);
|
||||
rewindBtn=findViewById(R.id.rewind_btn);
|
||||
playPauseBtn.setOnClickListener(this::onPlayPauseClick);
|
||||
itemView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener(){
|
||||
@Override
|
||||
|
@ -61,76 +95,71 @@ public class AudioStatusDisplayItem extends StatusDisplayItem{
|
|||
AudioPlayerService.unregisterCallback(Holder.this);
|
||||
}
|
||||
});
|
||||
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
|
||||
if(fromUser){
|
||||
int seconds=(int)(seekBar.getProgress()/10000.0*item.attachment.getDuration());
|
||||
time.setText(formatDuration(seconds));
|
||||
}
|
||||
}
|
||||
forwardBtn.setOnClickListener(this::onSeekButtonClick);
|
||||
rewindBtn.setOnClickListener(this::onSeekButtonClick);
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar){
|
||||
seekbarBeingDragged=true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar){
|
||||
AudioPlayerService service=AudioPlayerService.getInstance();
|
||||
if(service!=null && service.getAttachmentID().equals(item.attachment.id)){
|
||||
service.seekTo((int)(seekBar.getProgress()/10000.0*item.attachment.getDuration()*1000.0));
|
||||
}
|
||||
seekbarBeingDragged=false;
|
||||
if(playing)
|
||||
itemView.postOnAnimation(positionUpdater);
|
||||
}
|
||||
});
|
||||
image.setOutlineProvider(OutlineProviders.OVAL);
|
||||
image.setClipToOutline(true);
|
||||
content.setBackground(bgDrawable=new AudioAttachmentBackgroundDrawable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(AudioStatusDisplayItem item){
|
||||
int seconds=(int)item.attachment.getDuration();
|
||||
String duration=formatDuration(seconds);
|
||||
// Some fonts (not Roboto) have different-width digits. 0 is supposedly the widest.
|
||||
time.getLayoutParams().width=(int)Math.ceil(Math.max(time.getPaint().measureText("-"+duration),
|
||||
time.getPaint().measureText("-"+duration.replaceAll("\\d", "0"))));
|
||||
time.setText(duration);
|
||||
AudioPlayerService service=AudioPlayerService.getInstance();
|
||||
if(service!=null && service.getAttachmentID().equals(item.attachment.id)){
|
||||
seekBar.setEnabled(true);
|
||||
onPlayStateChanged(item.attachment.id, service.isPlaying(), service.getPosition());
|
||||
forwardBtn.setVisibility(View.VISIBLE);
|
||||
rewindBtn.setVisibility(View.VISIBLE);
|
||||
onPlayStateChanged(item.attachment.id, service.getPlayState(), service.getPosition());
|
||||
actuallyUpdatePosition();
|
||||
}else{
|
||||
seekBar.setEnabled(false);
|
||||
state=null;
|
||||
time.setText(duration);
|
||||
forwardBtn.setVisibility(View.INVISIBLE);
|
||||
rewindBtn.setVisibility(View.INVISIBLE);
|
||||
setPlayButtonPlaying(false, false);
|
||||
}
|
||||
|
||||
int mainColor;
|
||||
if(item.attachment.meta!=null && item.attachment.meta.colors!=null){
|
||||
try{
|
||||
mainColor=Color.parseColor(item.attachment.meta.colors.background);
|
||||
}catch(IllegalArgumentException x){
|
||||
mainColor=0xff808080;
|
||||
}
|
||||
}else{
|
||||
mainColor=0xff808080;
|
||||
}
|
||||
updateColors(mainColor);
|
||||
}
|
||||
|
||||
private void onPlayPauseClick(View v){
|
||||
AudioPlayerService service=AudioPlayerService.getInstance();
|
||||
if(service!=null && service.getAttachmentID().equals(item.attachment.id)){
|
||||
if(playing)
|
||||
if(state!=AudioPlayerService.PlayState.PAUSED)
|
||||
service.pause(true);
|
||||
else
|
||||
service.play();
|
||||
}else{
|
||||
AudioPlayerService.start(v.getContext(), item.status, item.attachment);
|
||||
onPlayStateChanged(item.attachment.id, true, 0);
|
||||
seekBar.setEnabled(true);
|
||||
onPlayStateChanged(item.attachment.id, AudioPlayerService.PlayState.BUFFERING, 0);
|
||||
forwardBtn.setVisibility(View.VISIBLE);
|
||||
rewindBtn.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayStateChanged(String attachmentID, boolean playing, int position){
|
||||
public void onPlayStateChanged(String attachmentID, AudioPlayerService.PlayState state, int position){
|
||||
if(attachmentID.equals(item.attachment.id)){
|
||||
this.lastKnownPosition=position;
|
||||
lastKnownPositionTime=SystemClock.uptimeMillis();
|
||||
this.playing=playing;
|
||||
playPauseBtn.setImageResource(playing ? R.drawable.ic_fluent_pause_circle_24_filled : R.drawable.ic_fluent_play_circle_24_filled);
|
||||
if(!playing){
|
||||
lastRemainingSeconds=-1;
|
||||
time.setText(formatDuration((int) item.attachment.getDuration()));
|
||||
}else{
|
||||
this.state=state;
|
||||
setPlayButtonPlaying(state!=AudioPlayerService.PlayState.PAUSED, true);
|
||||
if(state==AudioPlayerService.PlayState.PLAYING){
|
||||
itemView.postOnAnimation(positionUpdater);
|
||||
}else if(state==AudioPlayerService.PlayState.BUFFERING){
|
||||
actuallyUpdatePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,14 +167,15 @@ public class AudioStatusDisplayItem extends StatusDisplayItem{
|
|||
@Override
|
||||
public void onPlaybackStopped(String attachmentID){
|
||||
if(attachmentID.equals(item.attachment.id)){
|
||||
playing=false;
|
||||
playPauseBtn.setImageResource(R.drawable.ic_fluent_play_circle_24_filled);
|
||||
seekBar.setProgress(0);
|
||||
seekBar.setEnabled(false);
|
||||
state=null;
|
||||
setPlayButtonPlaying(false, true);
|
||||
forwardBtn.setVisibility(View.INVISIBLE);
|
||||
rewindBtn.setVisibility(View.INVISIBLE);
|
||||
time.setText(formatDuration((int)item.attachment.getDuration()));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private String formatDuration(int seconds){
|
||||
if(seconds>=3600)
|
||||
return String.format("%d:%02d:%02d", seconds/3600, seconds%3600/60, seconds%60);
|
||||
|
@ -154,16 +184,79 @@ public class AudioStatusDisplayItem extends StatusDisplayItem{
|
|||
}
|
||||
|
||||
private void updatePosition(){
|
||||
if(!playing || seekbarBeingDragged)
|
||||
if(state!=AudioPlayerService.PlayState.PLAYING)
|
||||
return;
|
||||
double pos=lastKnownPosition/1000.0+(SystemClock.uptimeMillis()-lastKnownPositionTime)/1000.0;
|
||||
seekBar.setProgress((int)Math.round(pos/item.attachment.getDuration()*10000.0));
|
||||
actuallyUpdatePosition();
|
||||
itemView.postOnAnimation(positionUpdater);
|
||||
int remainingSeconds=(int)(item.attachment.getDuration()-pos);
|
||||
if(remainingSeconds!=lastRemainingSeconds){
|
||||
lastRemainingSeconds=remainingSeconds;
|
||||
time.setText("-"+formatDuration(remainingSeconds));
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private void actuallyUpdatePosition(){
|
||||
double pos=lastKnownPosition/1000.0;
|
||||
if(state==AudioPlayerService.PlayState.PLAYING)
|
||||
pos+=(SystemClock.uptimeMillis()-lastKnownPositionTime)/1000.0;
|
||||
int posSeconds=(int)pos;
|
||||
if(posSeconds!=lastPosSeconds){
|
||||
lastPosSeconds=posSeconds;
|
||||
time.setText(formatDuration(posSeconds)+"/"+formatDuration((int)item.attachment.getDuration()));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateColors(int mainColor){
|
||||
float[] hsv={0, 0, 0};
|
||||
float[] hsv2={0, 0, 0};
|
||||
Color.colorToHSV(mainColor, hsv);
|
||||
boolean isGray=hsv[1]<0.2f;
|
||||
boolean isDarkTheme=UiUtils.isDarkTheme();
|
||||
hsv2[0]=hsv[0];
|
||||
hsv2[1]=isGray ? hsv[1] : (isDarkTheme ? 0.6f : 0.4f);
|
||||
hsv2[2]=isDarkTheme ? 0.3f : 0.75f;
|
||||
int bgColor=Color.HSVToColor(hsv2);
|
||||
hsv2[1]=isGray ? hsv[1] : (isDarkTheme ? 0.3f : 0.6f);
|
||||
hsv2[2]=isDarkTheme ? 0.6f : 0.4f;
|
||||
bgDrawable.setColors(bgColor, Color.HSVToColor(128, hsv2));
|
||||
|
||||
hsv2[1]=isGray ? hsv[1] : 0.1f;
|
||||
hsv2[2]=1;
|
||||
int controlsColor=Color.HSVToColor(hsv2);
|
||||
time.setTextColor(controlsColor);
|
||||
forwardBtn.setColorFilter(controlsColor);
|
||||
rewindBtn.setColorFilter(controlsColor);
|
||||
}
|
||||
|
||||
private void setPlayButtonPlaying(boolean playing, boolean animated){
|
||||
playPauseBtn.setImageResource(playing ? R.drawable.ic_pause_48px : R.drawable.ic_play_arrow_48px);
|
||||
playPauseBtn.setContentDescription(item.parentFragment.getString(playing ? R.string.pause : R.string.play));
|
||||
if(playing)
|
||||
bgDrawable.startAnimation();
|
||||
else
|
||||
bgDrawable.stopAnimation(animated);
|
||||
}
|
||||
|
||||
private void onSeekButtonClick(View v){
|
||||
int seekAmount=v.getId()==R.id.forward_btn ? 10_000 : -5_000;
|
||||
AudioPlayerService service=AudioPlayerService.getInstance();
|
||||
if(service!=null && service.getAttachmentID().equals(item.attachment.id)){
|
||||
int newPos=Math.min(Math.max(0, service.getPosition()+seekAmount), (int)(item.attachment.getDuration()*1000));
|
||||
service.seekTo(newPos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(int index, Drawable image){
|
||||
this.image.setImageDrawable(image);
|
||||
if((item.attachment.meta==null || item.attachment.meta.colors==null) && image instanceof BitmapDrawable bd){
|
||||
Bitmap bitmap=bd.getBitmap();
|
||||
if(Build.VERSION.SDK_INT>=26 && bitmap.getConfig()==Bitmap.Config.HARDWARE)
|
||||
bitmap=bitmap.copy(Bitmap.Config.ARGB_8888, false);
|
||||
int color=Palette.from(bitmap).maximumColorCount(1).generate().getDominantColor(0xff808080);
|
||||
updateColors(color);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearImage(int index){
|
||||
setImage(index, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.joinmastodon.android.ui.displayitems;
|
|||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
@ -45,6 +47,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||
public static class Holder extends StatusDisplayItem.Holder<FooterStatusDisplayItem>{
|
||||
private final TextView reply, boost, favorite;
|
||||
private final ImageView share;
|
||||
private final ColorStateList buttonColors;
|
||||
|
||||
private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){
|
||||
@Override
|
||||
|
@ -61,6 +64,27 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||
boost=findViewById(R.id.boost);
|
||||
favorite=findViewById(R.id.favorite);
|
||||
share=findViewById(R.id.share);
|
||||
|
||||
float[] hsb={0, 0, 0};
|
||||
Color.colorToHSV(UiUtils.getThemeColor(activity, R.attr.colorM3Primary), hsb);
|
||||
hsb[1]+=0.1f;
|
||||
hsb[2]+=0.16f;
|
||||
|
||||
buttonColors=new ColorStateList(new int[][]{
|
||||
{android.R.attr.state_selected},
|
||||
{android.R.attr.state_enabled},
|
||||
{}
|
||||
}, new int[]{
|
||||
Color.HSVToColor(hsb),
|
||||
UiUtils.getThemeColor(activity, R.attr.colorM3OnSurfaceVariant),
|
||||
UiUtils.getThemeColor(activity, R.attr.colorM3OnSurfaceVariant) & 0x80FFFFFF
|
||||
});
|
||||
|
||||
boost.setTextColor(buttonColors);
|
||||
boost.setCompoundDrawableTintList(buttonColors);
|
||||
favorite.setTextColor(buttonColors);
|
||||
favorite.setCompoundDrawableTintList(buttonColors);
|
||||
|
||||
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N){
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(reply);
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(boost);
|
||||
|
@ -94,7 +118,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||
private void bindButton(TextView btn, long count){
|
||||
if(count>0 && !item.hideCounts){
|
||||
btn.setText(UiUtils.abbreviateNumber(count));
|
||||
btn.setCompoundDrawablePadding(V.dp(8));
|
||||
btn.setCompoundDrawablePadding(V.dp(6));
|
||||
}else{
|
||||
btn.setText("");
|
||||
btn.setCompoundDrawablePadding(0);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.graphics.Outline;
|
||||
|
@ -32,6 +33,7 @@ import org.joinmastodon.android.model.Account;
|
|||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Relationship;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
@ -105,33 +107,23 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView name, username, timestamp, extraText;
|
||||
private final ImageView avatar, more, visibility;
|
||||
private final TextView name, timeAndUsername, extraText;
|
||||
private final ImageView avatar, more;
|
||||
private final PopupMenu optionsMenu;
|
||||
private Relationship relationship;
|
||||
private APIRequest<?> currentRelationshipRequest;
|
||||
|
||||
private static final ViewOutlineProvider roundCornersOutline=new ViewOutlineProvider(){
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline){
|
||||
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), V.dp(12));
|
||||
}
|
||||
};
|
||||
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
super(activity, R.layout.display_item_header, parent);
|
||||
name=findViewById(R.id.name);
|
||||
username=findViewById(R.id.username);
|
||||
timestamp=findViewById(R.id.timestamp);
|
||||
timeAndUsername=findViewById(R.id.time_and_username);
|
||||
avatar=findViewById(R.id.avatar);
|
||||
more=findViewById(R.id.more);
|
||||
visibility=findViewById(R.id.visibility);
|
||||
extraText=findViewById(R.id.extra_text);
|
||||
avatar.setOnClickListener(this::onAvaClick);
|
||||
avatar.setOutlineProvider(roundCornersOutline);
|
||||
avatar.setOutlineProvider(OutlineProviders.roundedRect(10));
|
||||
avatar.setClipToOutline(true);
|
||||
more.setOnClickListener(this::onMoreClick);
|
||||
visibility.setOnClickListener(v->item.parentFragment.onVisibilityIconClick(this));
|
||||
|
||||
optionsMenu=new PopupMenu(activity, more);
|
||||
optionsMenu.inflate(R.menu.post);
|
||||
|
@ -200,22 +192,17 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||
});
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void onBind(HeaderStatusDisplayItem item){
|
||||
name.setText(item.parsedName);
|
||||
username.setText('@'+item.user.acct);
|
||||
String time;
|
||||
if(item.status==null || item.status.editedAt==null)
|
||||
timestamp.setText(UiUtils.formatRelativeTimestamp(itemView.getContext(), item.createdAt));
|
||||
time=UiUtils.formatRelativeTimestamp(itemView.getContext(), item.createdAt);
|
||||
else
|
||||
timestamp.setText(item.parentFragment.getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(itemView.getContext(), item.status.editedAt)));
|
||||
visibility.setVisibility(item.hasVisibilityToggle && !item.inset ? View.VISIBLE : View.GONE);
|
||||
if(item.hasVisibilityToggle){
|
||||
visibility.setImageResource(item.status.spoilerRevealed ? R.drawable.ic_visibility_off : R.drawable.ic_visibility);
|
||||
visibility.setContentDescription(item.parentFragment.getString(item.status.spoilerRevealed ? R.string.hide_content : R.string.reveal_content));
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
|
||||
visibility.setTooltipText(visibility.getContentDescription());
|
||||
}
|
||||
}
|
||||
time=item.parentFragment.getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(itemView.getContext(), item.status.editedAt));
|
||||
|
||||
timeAndUsername.setText(time+" · @"+item.user.acct);
|
||||
itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), item.needBottomPadding ? V.dp(16) : 0);
|
||||
if(TextUtils.isEmpty(item.extraText)){
|
||||
extraText.setVisibility(View.GONE);
|
||||
|
|
|
@ -31,6 +31,7 @@ import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
|||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
||||
private static final String TAG="MediaGridDisplayItem";
|
||||
|
@ -97,6 +98,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
|||
wrapper=(FrameLayout)itemView;
|
||||
layout=new MediaGridLayout(activity);
|
||||
wrapper.addView(layout);
|
||||
wrapper.setPadding(0, 0, 0, V.dp(8));
|
||||
|
||||
activity.getLayoutInflater().inflate(R.layout.overlay_image_alt_text, wrapper);
|
||||
altTextWrapper=findViewById(R.id.alt_text_wrapper);
|
||||
|
@ -105,6 +107,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
|||
altTextClose=findViewById(R.id.alt_text_close);
|
||||
altText=findViewById(R.id.alt_text);
|
||||
altTextClose.setOnClickListener(this::onAltTextCloseClick);
|
||||
wrapper.setClipToPadding(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -158,11 +161,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
|||
|
||||
private void onViewClick(View v){
|
||||
int index=(Integer)v.getTag();
|
||||
if(!item.status.spoilerRevealed){
|
||||
item.parentFragment.onRevealSpoilerClick(this);
|
||||
}else if(item.parentFragment instanceof PhotoViewerHost){
|
||||
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, index, this);
|
||||
}
|
||||
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, index, this);
|
||||
}
|
||||
|
||||
private void onAltTextClick(View v){
|
||||
|
|
|
@ -37,9 +37,11 @@ public class PollFooterStatusDisplayItem extends StatusDisplayItem{
|
|||
|
||||
@Override
|
||||
public void onBind(PollFooterStatusDisplayItem item){
|
||||
String text=item.parentFragment.getResources().getQuantityString(R.plurals.x_voters, item.poll.votersCount, item.poll.votersCount);
|
||||
String text=item.parentFragment.getResources().getQuantityString(R.plurals.x_votes, item.poll.votesCount, item.poll.votesCount);
|
||||
if(item.poll.expiresAt!=null && !item.poll.isExpired()){
|
||||
text+=" · "+UiUtils.formatTimeLeft(itemView.getContext(), item.poll.expiresAt);
|
||||
if(item.poll.multiple)
|
||||
text+=" · "+item.parentFragment.getString(R.string.poll_multiple_choice);
|
||||
}else if(item.poll.isExpired()){
|
||||
text+=" · "+item.parentFragment.getString(R.string.poll_closed);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.widget.TextView;
|
|||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Poll;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
|
||||
|
@ -25,11 +26,13 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
|||
private boolean showResults;
|
||||
private float votesFraction; // 0..1
|
||||
private boolean isMostVoted;
|
||||
private final int optionIndex;
|
||||
public final Poll poll;
|
||||
|
||||
public PollOptionStatusDisplayItem(String parentID, Poll poll, Poll.Option option, BaseStatusListFragment parentFragment){
|
||||
public PollOptionStatusDisplayItem(String parentID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment){
|
||||
super(parentID, parentFragment);
|
||||
this.option=option;
|
||||
this.optionIndex=optionIndex;
|
||||
option=poll.options.get(optionIndex);
|
||||
this.poll=poll;
|
||||
text=HtmlParser.parseCustomEmoji(option.title, poll.emojis);
|
||||
emojiHelper.setText(text);
|
||||
|
@ -61,23 +64,24 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
|||
|
||||
public static class Holder extends StatusDisplayItem.Holder<PollOptionStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView text, percent;
|
||||
private final View icon, button;
|
||||
private final View check, button;
|
||||
private final Drawable progressBg;
|
||||
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
super(activity, R.layout.display_item_poll_option, parent);
|
||||
text=findViewById(R.id.text);
|
||||
percent=findViewById(R.id.percent);
|
||||
icon=findViewById(R.id.icon);
|
||||
check=findViewById(R.id.checkbox);
|
||||
button=findViewById(R.id.button);
|
||||
progressBg=activity.getResources().getDrawable(R.drawable.bg_poll_option_voted, activity.getTheme()).mutate();
|
||||
itemView.setOnClickListener(this::onButtonClick);
|
||||
button.setOutlineProvider(OutlineProviders.roundedRect(20));
|
||||
button.setClipToOutline(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(PollOptionStatusDisplayItem item){
|
||||
text.setText(item.text);
|
||||
icon.setVisibility(item.showResults ? View.GONE : View.VISIBLE);
|
||||
percent.setVisibility(item.showResults ? View.VISIBLE : View.GONE);
|
||||
itemView.setClickable(!item.showResults);
|
||||
if(item.showResults){
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
|
||||
public class SpoilerStatusDisplayItem extends StatusDisplayItem{
|
||||
public final Status status;
|
||||
public final ArrayList<StatusDisplayItem> contentItems=new ArrayList<>();
|
||||
private final CharSequence parsedTitle;
|
||||
private final CustomEmojiHelper emojiHelper;
|
||||
|
||||
public SpoilerStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status){
|
||||
super(parentID, parentFragment);
|
||||
this.status=status;
|
||||
parsedTitle=HtmlParser.parseCustomEmoji(status.spoilerText, status.emojis);
|
||||
emojiHelper=new CustomEmojiHelper();
|
||||
emojiHelper.setText(parsedTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageCount(){
|
||||
return emojiHelper.getImageCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageLoaderRequest getImageRequest(int index){
|
||||
return emojiHelper.getImageRequest(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(){
|
||||
return Type.SPOILER;
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<SpoilerStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView title, action;
|
||||
private final View button;
|
||||
|
||||
public Holder(Context context, ViewGroup parent){
|
||||
super(context, R.layout.display_item_spoiler, parent);
|
||||
title=findViewById(R.id.spoiler_title);
|
||||
action=findViewById(R.id.spoiler_action);
|
||||
button=findViewById(R.id.spoiler_button);
|
||||
|
||||
button.setOutlineProvider(OutlineProviders.roundedRect(8));
|
||||
button.setClipToOutline(true);
|
||||
LayerDrawable spoilerBg=(LayerDrawable) button.getBackground().mutate();
|
||||
spoilerBg.setDrawableByLayerId(R.id.left_drawable, new SpoilerStripesDrawable(true));
|
||||
spoilerBg.setDrawableByLayerId(R.id.right_drawable, new SpoilerStripesDrawable(false));
|
||||
button.setBackground(spoilerBg);
|
||||
button.setOnClickListener(v->item.parentFragment.onRevealSpoilerClick(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(SpoilerStatusDisplayItem item){
|
||||
title.setText(item.parsedTitle);
|
||||
action.setText(item.status.spoilerRevealed ? R.string.spoiler_hide : R.string.spoiler_show);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(int index, Drawable image){
|
||||
item.emojiHelper.setImageDrawable(index, image);
|
||||
title.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearImage(int index){
|
||||
setImage(index, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -64,6 +64,7 @@ public abstract class StatusDisplayItem{
|
|||
case GAP -> new GapStatusDisplayItem.Holder(activity, parent);
|
||||
case EXTENDED_FOOTER -> new ExtendedFooterStatusDisplayItem.Holder(activity, parent);
|
||||
case MEDIA_GRID -> new MediaGridStatusDisplayItem.Holder(activity, parent);
|
||||
case SPOILER -> new SpoilerStatusDisplayItem.Holder(activity, parent);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -72,32 +73,43 @@ public abstract class StatusDisplayItem{
|
|||
ArrayList<StatusDisplayItem> items=new ArrayList<>();
|
||||
Status statusForContent=status.getContentStatus();
|
||||
if(status.reblog!=null){
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.user_boosted, status.account.displayName), status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20_filled));
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.user_boosted, status.account.displayName), status.account.emojis, R.drawable.ic_repeat_20px));
|
||||
}else if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId)){
|
||||
Account account=Objects.requireNonNull(knownAccounts.get(status.inReplyToAccountId));
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.in_reply_to, account.displayName), account.emojis, R.drawable.ic_fluent_arrow_reply_20_filled));
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.in_reply_to, account.displayName), account.emojis, R.drawable.ic_reply_20px));
|
||||
}
|
||||
HeaderStatusDisplayItem header;
|
||||
items.add(header=new HeaderStatusDisplayItem(parentID, statusForContent.account, statusForContent.createdAt, fragment, accountID, statusForContent, null));
|
||||
|
||||
ArrayList<StatusDisplayItem> contentItems;
|
||||
if(!TextUtils.isEmpty(statusForContent.spoilerText)){
|
||||
SpoilerStatusDisplayItem spoilerItem=new SpoilerStatusDisplayItem(parentID, fragment, statusForContent);
|
||||
items.add(spoilerItem);
|
||||
contentItems=spoilerItem.contentItems;
|
||||
}else{
|
||||
contentItems=items;
|
||||
}
|
||||
|
||||
if(!TextUtils.isEmpty(statusForContent.content))
|
||||
items.add(new TextStatusDisplayItem(parentID, HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID), fragment, statusForContent));
|
||||
contentItems.add(new TextStatusDisplayItem(parentID, HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID), fragment, statusForContent));
|
||||
else
|
||||
header.needBottomPadding=true;
|
||||
|
||||
List<Attachment> imageAttachments=statusForContent.mediaAttachments.stream().filter(att->att.type.isImage()).collect(Collectors.toList());
|
||||
if(!imageAttachments.isEmpty()){
|
||||
PhotoLayoutHelper.TiledLayoutResult layout=PhotoLayoutHelper.processThumbs(imageAttachments);
|
||||
items.add(new MediaGridStatusDisplayItem(parentID, fragment, layout, imageAttachments, statusForContent));
|
||||
contentItems.add(new MediaGridStatusDisplayItem(parentID, fragment, layout, imageAttachments, statusForContent));
|
||||
}
|
||||
for(Attachment att:statusForContent.mediaAttachments){
|
||||
if(att.type==Attachment.Type.AUDIO){
|
||||
items.add(new AudioStatusDisplayItem(parentID, fragment, statusForContent, att));
|
||||
contentItems.add(new AudioStatusDisplayItem(parentID, fragment, statusForContent, att));
|
||||
}
|
||||
}
|
||||
if(statusForContent.poll!=null){
|
||||
buildPollItems(parentID, fragment, statusForContent.poll, items);
|
||||
buildPollItems(parentID, fragment, statusForContent.poll, contentItems);
|
||||
}
|
||||
if(statusForContent.card!=null && statusForContent.mediaAttachments.isEmpty() && TextUtils.isEmpty(statusForContent.spoilerText)){
|
||||
items.add(new LinkCardStatusDisplayItem(parentID, fragment, statusForContent));
|
||||
contentItems.add(new LinkCardStatusDisplayItem(parentID, fragment, statusForContent));
|
||||
}
|
||||
if(addFooter){
|
||||
items.add(new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID));
|
||||
|
@ -109,12 +121,20 @@ public abstract class StatusDisplayItem{
|
|||
item.inset=inset;
|
||||
item.index=i++;
|
||||
}
|
||||
if(items!=contentItems){
|
||||
for(StatusDisplayItem item:contentItems){
|
||||
item.inset=inset;
|
||||
item.index=i++;
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){
|
||||
int i=0;
|
||||
for(Poll.Option opt:poll.options){
|
||||
items.add(new PollOptionStatusDisplayItem(parentID, poll, opt, fragment));
|
||||
items.add(new PollOptionStatusDisplayItem(parentID, poll, i, fragment));
|
||||
i++;
|
||||
}
|
||||
items.add(new PollFooterStatusDisplayItem(parentID, fragment, poll));
|
||||
}
|
||||
|
@ -133,7 +153,8 @@ public abstract class StatusDisplayItem{
|
|||
HASHTAG,
|
||||
GAP,
|
||||
EXTENDED_FOOTER,
|
||||
MEDIA_GRID
|
||||
MEDIA_GRID,
|
||||
SPOILER
|
||||
}
|
||||
|
||||
public static abstract class Holder<T extends StatusDisplayItem> extends BindableViewHolder<T> implements UsableRecyclerView.DisableableClickable{
|
||||
|
|
|
@ -3,15 +3,11 @@ package org.joinmastodon.android.ui.displayitems;
|
|||
import android.app.Activity;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
import org.joinmastodon.android.ui.views.LinkedTextView;
|
||||
|
||||
|
@ -21,8 +17,7 @@ import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
|||
|
||||
public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||
private CharSequence text;
|
||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper(), spoilerEmojiHelper;
|
||||
private CharSequence parsedSpoilerText;
|
||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
||||
public boolean textSelectable;
|
||||
public final Status status;
|
||||
|
||||
|
@ -31,11 +26,6 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||
this.text=text;
|
||||
this.status=status;
|
||||
emojiHelper.setText(text);
|
||||
if(!TextUtils.isEmpty(status.spoilerText)){
|
||||
parsedSpoilerText=HtmlParser.parseCustomEmoji(status.spoilerText, status.emojis);
|
||||
spoilerEmojiHelper=new CustomEmojiHelper();
|
||||
spoilerEmojiHelper.setText(parsedSpoilerText);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,29 +35,20 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||
|
||||
@Override
|
||||
public int getImageCount(){
|
||||
if(spoilerEmojiHelper!=null && !status.spoilerRevealed)
|
||||
return spoilerEmojiHelper.getImageCount();
|
||||
return emojiHelper.getImageCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageLoaderRequest getImageRequest(int index){
|
||||
if(spoilerEmojiHelper!=null && !status.spoilerRevealed)
|
||||
return spoilerEmojiHelper.getImageRequest(index);
|
||||
return emojiHelper.getImageRequest(index);
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<TextStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final LinkedTextView text;
|
||||
private final TextView spoilerTitle;
|
||||
private final View spoilerOverlay;
|
||||
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
super(activity, R.layout.display_item_text, parent);
|
||||
text=findViewById(R.id.text);
|
||||
spoilerTitle=findViewById(R.id.spoiler_title);
|
||||
spoilerOverlay=findViewById(R.id.spoiler_overlay);
|
||||
itemView.setOnClickListener(v->item.parentFragment.onRevealSpoilerClick(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,29 +56,13 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||
text.setText(item.text);
|
||||
text.setTextIsSelectable(item.textSelectable);
|
||||
text.setInvalidateOnEveryFrame(false);
|
||||
if(!TextUtils.isEmpty(item.status.spoilerText)){
|
||||
spoilerTitle.setText(item.parsedSpoilerText);
|
||||
if(item.status.spoilerRevealed){
|
||||
spoilerOverlay.setVisibility(View.GONE);
|
||||
text.setVisibility(View.VISIBLE);
|
||||
itemView.setClickable(false);
|
||||
}else{
|
||||
spoilerOverlay.setVisibility(View.VISIBLE);
|
||||
text.setVisibility(View.INVISIBLE);
|
||||
itemView.setClickable(true);
|
||||
}
|
||||
}else{
|
||||
spoilerOverlay.setVisibility(View.GONE);
|
||||
text.setVisibility(View.VISIBLE);
|
||||
itemView.setClickable(false);
|
||||
}
|
||||
itemView.setClickable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(int index, Drawable image){
|
||||
getEmojiHelper().setImageDrawable(index, image);
|
||||
text.invalidate();
|
||||
spoilerTitle.invalidate();
|
||||
if(image instanceof Animatable){
|
||||
((Animatable) image).start();
|
||||
if(image instanceof MovieDrawable)
|
||||
|
@ -112,7 +77,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||
}
|
||||
|
||||
private CustomEmojiHelper getEmojiHelper(){
|
||||
return item.spoilerEmojiHelper!=null && !item.status.spoilerRevealed ? item.spoilerEmojiHelper : item.emojiHelper;
|
||||
return item.emojiHelper;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
package org.joinmastodon.android.ui.drawables;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class AudioAttachmentBackgroundDrawable extends Drawable{
|
||||
private int bgColor, wavesColor;
|
||||
private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private long[] animationStartTimes={0, 0};
|
||||
private boolean animationRunning;
|
||||
private Runnable[] restartRunnables={()->restartAnimation(0), ()->restartAnimation(1)};
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas){
|
||||
Rect bounds=getBounds();
|
||||
paint.setColor(bgColor);
|
||||
canvas.drawRect(bounds, paint);
|
||||
|
||||
float initialRadius=V.dp(48);
|
||||
float finalRadius=bounds.width()/2f;
|
||||
long time=SystemClock.uptimeMillis();
|
||||
boolean animationsStillRunning=false;
|
||||
|
||||
for(int i=0;i<animationStartTimes.length;i++){
|
||||
long t=time-animationStartTimes[i];
|
||||
if(t<0)
|
||||
continue;
|
||||
float fraction=t/3000f;
|
||||
if(fraction>1)
|
||||
continue;
|
||||
fraction=CubicBezierInterpolator.EASE_OUT.getInterpolation(fraction);
|
||||
paint.setColor(wavesColor);
|
||||
paint.setAlpha(Math.round(paint.getAlpha()*(1f-fraction)));
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), initialRadius+(finalRadius-initialRadius)*fraction, paint);
|
||||
animationsStillRunning=true;
|
||||
}
|
||||
|
||||
if(animationsStillRunning){
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(){
|
||||
return PixelFormat.OPAQUE;
|
||||
}
|
||||
|
||||
public void setColors(int bg, int waves){
|
||||
bgColor=bg;
|
||||
wavesColor=waves;
|
||||
}
|
||||
|
||||
public void startAnimation(){
|
||||
if(animationRunning)
|
||||
return;
|
||||
|
||||
long time=SystemClock.uptimeMillis();
|
||||
animationStartTimes[0]=time;
|
||||
scheduleSelf(restartRunnables[0], time+3000);
|
||||
scheduleSelf(restartRunnables[1], time+1500);
|
||||
animationRunning=true;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
public void stopAnimation(boolean gracefully){
|
||||
if(!animationRunning)
|
||||
return;
|
||||
|
||||
animationRunning=false;
|
||||
for(Runnable r:restartRunnables)
|
||||
unscheduleSelf(r);
|
||||
if(!gracefully){
|
||||
animationStartTimes[0]=animationStartTimes[1]=0;
|
||||
}
|
||||
}
|
||||
|
||||
private void restartAnimation(int index){
|
||||
long time=SystemClock.uptimeMillis();
|
||||
animationStartTimes[index]=time;
|
||||
if(animationRunning)
|
||||
scheduleSelf(restartRunnables[index], time+3000);
|
||||
}
|
||||
}
|
|
@ -14,11 +14,16 @@ import androidx.annotation.Nullable;
|
|||
|
||||
public class SpoilerStripesDrawable extends Drawable{
|
||||
private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private boolean flipped;
|
||||
|
||||
public SpoilerStripesDrawable(){
|
||||
private static final float X1=-0.860365f;
|
||||
private static final float X2=10.6078f;
|
||||
|
||||
public SpoilerStripesDrawable(boolean flipped){
|
||||
paint.setColor(0xff000000);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(3);
|
||||
this.flipped=flipped;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,7 +39,7 @@ public class SpoilerStripesDrawable extends Drawable{
|
|||
float y1=6.80133f;
|
||||
float y2=-1.22874f;
|
||||
while(y2<height){
|
||||
canvas.drawLine(-0.860365f, y1, 10.6078f, y2, paint);
|
||||
canvas.drawLine(flipped ? X2 : X1, y1, flipped ? X1 : X2, y2, paint);
|
||||
y1+=8.03007f;
|
||||
y2+=8.03007f;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ public class LinkSpan extends CharacterStyle {
|
|||
@Override
|
||||
public void updateDrawState(TextPaint tp) {
|
||||
tp.setColor(color=tp.linkColor);
|
||||
tp.setUnderlineText(true);
|
||||
}
|
||||
|
||||
public void onClick(Context context){
|
||||
|
|
|
@ -24,6 +24,7 @@ public class FrameLayoutThatOnlyMeasuresFirstChild extends FrameLayout{
|
|||
return;
|
||||
View child0=getChildAt(0);
|
||||
measureChild(child0, widthMeasureSpec, heightMeasureSpec);
|
||||
super.onMeasure(child0.getMeasuredWidth() | MeasureSpec.EXACTLY, child0.getMeasuredHeight() | MeasureSpec.EXACTLY);
|
||||
int vpad=getPaddingTop()+getPaddingBottom();
|
||||
super.onMeasure(child0.getMeasuredWidth() | MeasureSpec.EXACTLY, (child0.getMeasuredHeight()+vpad) | MeasureSpec.EXACTLY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/highlight_over_dark">
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="#80000000"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="#ff000000"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -2,8 +2,14 @@
|
|||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="?android:colorBackground"/>
|
||||
<corners android:radius="10dp"/>
|
||||
<stroke android:width="1dp" android:color="?colorM3Outline"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/mask">
|
||||
<shape>
|
||||
<solid android:color="#000"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="?android:colorBackground"/>
|
||||
<corners android:radius="10dp"/>
|
||||
</shape>
|
||||
<scale android:scaleGravity="start|fill_vertical" android:scaleWidth="100%">
|
||||
<shape>
|
||||
<solid android:color="?colorM3SecondaryContainer"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</scale>
|
||||
</item>
|
||||
<item>
|
||||
<clip android:clipOrientation="horizontal" android:gravity="start">
|
||||
<shape>
|
||||
<solid android:color="@color/poll_option_progress"/>
|
||||
<corners android:radius="10dp"/>
|
||||
</shape>
|
||||
</clip>
|
||||
<shape>
|
||||
<stroke android:width="1dp" android:color="?colorM3Outline"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="#000"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<color android:color="?colorM3SecondaryContainer"/>
|
||||
</item>
|
||||
<item android:gravity="left" android:width="5dp">
|
||||
<shape>
|
||||
<gradient android:type="linear" android:angle="270" android:startColor="#FEC84B" android:endColor="#F79009"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@+id/left_drawable" android:width="5dp" android:gravity="left">
|
||||
<color android:color="#0f0"/>
|
||||
</item>
|
||||
<item android:gravity="right" android:width="5dp">
|
||||
<shape>
|
||||
<gradient android:type="linear" android:angle="270" android:startColor="#FEC84B" android:endColor="#F79009"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@+id/right_drawable" android:width="5dp" android:gravity="right">
|
||||
<color android:color="#0f0"/>
|
||||
</item>
|
||||
<item>
|
||||
<ripple android:color="?android:colorControlHighlight">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape>
|
||||
<solid android:color="#000"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M8.229,14.062 L4.708,10.521 5.75,9.479 8.229,11.938 14.25,5.938 15.292,7Z"/>
|
||||
</vector>
|
|
@ -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="M18,32.5V21.9H15.3V19.45H20.5V32.5ZM25.35,32.5Q24.4,32.5 23.775,31.875Q23.15,31.25 23.15,30.3V21.65Q23.15,20.7 23.775,20.075Q24.4,19.45 25.35,19.45H29.5Q30.45,19.45 31.075,20.075Q31.7,20.7 31.7,21.65V30.3Q31.7,31.25 31.075,31.875Q30.45,32.5 29.5,32.5ZM25.65,30H29.2Q29.2,30 29.2,30Q29.2,30 29.2,30V21.9Q29.2,21.9 29.2,21.9Q29.2,21.9 29.2,21.9H25.65Q25.65,21.9 25.65,21.9Q25.65,21.9 25.65,21.9V30Q25.65,30 25.65,30Q25.65,30 25.65,30ZM24,44Q20.25,44 16.975,42.6Q13.7,41.2 11.25,38.75Q8.8,36.3 7.4,33.025Q6,29.75 6,26Q6,22.25 7.4,18.975Q8.8,15.7 11.25,13.25Q13.7,10.8 16.975,9.4Q20.25,8 24,8H25.05L21.15,4.1L23.2,2.05L30.55,9.4L23.2,16.75L21.15,14.7L24.85,11H24Q17.75,11 13.375,15.375Q9,19.75 9,26Q9,32.25 13.375,36.625Q17.75,41 24,41Q30.25,41 34.625,36.625Q39,32.25 39,26H42Q42,29.75 40.6,33.025Q39.2,36.3 36.75,38.75Q34.3,41.2 31.025,42.6Q27.75,44 24,44Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M10,16Q9.375,16 8.938,15.562Q8.5,15.125 8.5,14.5Q8.5,13.875 8.938,13.438Q9.375,13 10,13Q10.625,13 11.062,13.438Q11.5,13.875 11.5,14.5Q11.5,15.125 11.062,15.562Q10.625,16 10,16ZM10,11.5Q9.375,11.5 8.938,11.062Q8.5,10.625 8.5,10Q8.5,9.375 8.938,8.938Q9.375,8.5 10,8.5Q10.625,8.5 11.062,8.938Q11.5,9.375 11.5,10Q11.5,10.625 11.062,11.062Q10.625,11.5 10,11.5ZM10,7Q9.375,7 8.938,6.562Q8.5,6.125 8.5,5.5Q8.5,4.875 8.938,4.438Q9.375,4 10,4Q10.625,4 11.062,4.438Q11.5,4.875 11.5,5.5Q11.5,6.125 11.062,6.562Q10.625,7 10,7Z"/>
|
||||
</vector>
|
|
@ -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="M28.25,38V10H36V38ZM12,38V10H19.75V38Z"/>
|
||||
</vector>
|
|
@ -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="M16,37.85V9.85L38,23.85ZM19,23.85ZM19,32.4 L32.45,23.85 19,15.3Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="true" android:drawable="@drawable/ic_check_20px"/>
|
||||
</selector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M5.875,18.333 L2.5,14.958 5.792,11.667 7.042,12.917 5.875,14.083H14.083V10.833H15.833V15.833H5.875L7.125,17.083ZM4.167,9.167V4.167H14.125L12.875,2.917L14.125,1.667L17.5,5.042L14.188,8.354L12.938,7.104L14.125,5.917H5.917V9.167Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_repeat_wght700grad200fill1_20px" android:state_selected="true"/>
|
||||
<item android:drawable="@drawable/ic_repeat_20px"/>
|
||||
</selector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M5.812,18.792 L2.042,15.021 5.729,11.354 7.354,12.979 6.417,13.875H13.896V10.604H16.188V16.167H6.417L7.438,17.167ZM3.833,9.375V3.812H13.583L12.562,2.812L14.188,1.188L17.958,4.958L14.25,8.667L12.625,7.042L13.583,6.104H6.125V9.375Z"/>
|
||||
</vector>
|
|
@ -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="M24,44Q20.25,44 16.975,42.6Q13.7,41.2 11.25,38.75Q8.8,36.3 7.4,33.025Q6,29.75 6,26H9Q9,32.25 13.375,36.625Q17.75,41 24,41Q30.25,41 34.625,36.625Q39,32.25 39,26Q39,19.75 34.75,15.375Q30.5,11 24.25,11H23.15L26.8,14.65L24.7,16.75L17.35,9.4L24.7,2.05L26.75,4.1L22.85,8H24Q27.75,8 31.025,9.4Q34.3,10.8 36.75,13.25Q39.2,15.7 40.6,18.975Q42,22.25 42,26Q42,29.75 40.6,33.025Q39.2,36.3 36.75,38.75Q34.3,41.2 31.025,42.6Q27.75,44 24,44ZM19,32.5V30H25.35V27.2H19V19.45H27.8V21.9H21.5V24.75H26.1Q26.8,24.75 27.3,25.25Q27.8,25.75 27.8,26.45V30.8Q27.8,31.5 27.3,32Q26.8,32.5 26.1,32.5Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M15.5,15.625V12.625Q15.5,11.583 14.771,10.854Q14.042,10.125 13,10.125H5.875L8.438,12.688L7.375,13.75L3,9.375L7.375,5L8.438,6.062L5.875,8.625H13Q14.667,8.625 15.833,9.792Q17,10.958 17,12.625V15.625Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M14.958,18.333Q13.896,18.333 13.167,17.594Q12.438,16.854 12.438,15.792Q12.438,15.646 12.458,15.5Q12.479,15.354 12.521,15.229L6.75,11.896Q6.396,12.208 5.958,12.385Q5.521,12.562 5.042,12.562Q3.979,12.562 3.24,11.823Q2.5,11.083 2.5,10.021Q2.5,8.958 3.24,8.219Q3.979,7.479 5.042,7.479Q5.521,7.479 5.958,7.646Q6.396,7.812 6.75,8.125L12.521,4.792Q12.479,4.667 12.448,4.521Q12.417,4.375 12.417,4.229Q12.417,3.167 13.156,2.427Q13.896,1.688 14.958,1.688Q16.021,1.688 16.76,2.427Q17.5,3.167 17.5,4.229Q17.5,5.292 16.76,6.031Q16.021,6.771 14.958,6.771Q14.479,6.771 14.052,6.594Q13.625,6.417 13.271,6.104L7.5,9.438Q7.542,9.562 7.562,9.719Q7.583,9.875 7.583,10.021Q7.583,10.146 7.562,10.302Q7.542,10.458 7.5,10.583L13.271,13.917Q13.625,13.604 14.052,13.427Q14.479,13.25 14.958,13.25Q16.021,13.25 16.76,13.99Q17.5,14.729 17.5,15.792Q17.5,16.854 16.76,17.594Q16.021,18.333 14.958,18.333ZM14.958,5.021Q15.292,5.021 15.521,4.792Q15.75,4.562 15.75,4.229Q15.75,3.896 15.521,3.667Q15.292,3.438 14.958,3.438Q14.625,3.438 14.396,3.667Q14.167,3.896 14.167,4.229Q14.167,4.562 14.396,4.792Q14.625,5.021 14.958,5.021ZM5.042,10.812Q5.375,10.812 5.604,10.583Q5.833,10.354 5.833,10.021Q5.833,9.688 5.604,9.458Q5.375,9.229 5.042,9.229Q4.708,9.229 4.479,9.458Q4.25,9.688 4.25,10.021Q4.25,10.354 4.479,10.583Q4.708,10.812 5.042,10.812ZM14.958,16.583Q15.292,16.583 15.521,16.354Q15.75,16.125 15.75,15.792Q15.75,15.458 15.521,15.229Q15.292,15 14.958,15Q14.625,15 14.396,15.229Q14.167,15.458 14.167,15.792Q14.167,16.125 14.396,16.354Q14.625,16.583 14.958,16.583ZM14.958,4.229Q14.958,4.229 14.958,4.229Q14.958,4.229 14.958,4.229Q14.958,4.229 14.958,4.229Q14.958,4.229 14.958,4.229Q14.958,4.229 14.958,4.229Q14.958,4.229 14.958,4.229Q14.958,4.229 14.958,4.229Q14.958,4.229 14.958,4.229ZM5.042,10.021Q5.042,10.021 5.042,10.021Q5.042,10.021 5.042,10.021Q5.042,10.021 5.042,10.021Q5.042,10.021 5.042,10.021Q5.042,10.021 5.042,10.021Q5.042,10.021 5.042,10.021Q5.042,10.021 5.042,10.021Q5.042,10.021 5.042,10.021ZM14.958,15.792Q14.958,15.792 14.958,15.792Q14.958,15.792 14.958,15.792Q14.958,15.792 14.958,15.792Q14.958,15.792 14.958,15.792Q14.958,15.792 14.958,15.792Q14.958,15.792 14.958,15.792Q14.958,15.792 14.958,15.792Q14.958,15.792 14.958,15.792Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M7.333,14.896 L10,13.312 12.688,14.896 11.979,11.896 14.292,9.917 11.229,9.646 10,6.792 8.771,9.646 5.708,9.917 8.042,11.896ZM5.062,18 L6.375,12.458 2,8.729 7.75,8.229 10,3 12.25,8.25 18,8.729 13.625,12.458 14.938,18 10,15.062ZM10,11.062Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_star_wght700grad200fill1_20px" android:state_selected="true"/>
|
||||
<item android:drawable="@drawable/ic_star_20px"/>
|
||||
</selector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3.958,19.708 L6.25,12.292 0.125,7.792H7.583L10,0.062L12.417,7.792H19.875L13.75,12.292L16.062,19.708L10.021,15.104Z"/>
|
||||
</vector>
|
|
@ -3,52 +3,60 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="-8dp"
|
||||
android:layout_marginBottom="-8dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:background="?buttonBackground"
|
||||
android:outlineProvider="background"
|
||||
android:elevation="2dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/play_pause_btn"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:tint="?colorButtonText"
|
||||
android:src="@drawable/ic_fluent_play_circle_24_filled"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:progressDrawable="@drawable/seekbar_progress"
|
||||
android:max="10000"
|
||||
android:splitTrack="false"/>
|
||||
android:layout_height="188dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/m3_label_medium"
|
||||
android:layout_height="20dp"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textColor="?colorButtonText"
|
||||
android:gravity="end"
|
||||
android:gravity="center_vertical"
|
||||
android:singleLine="true"
|
||||
android:fontFeatureSettings="'tnum'"
|
||||
tools:text="1:23"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:layout_gravity="center"
|
||||
android:importantForAccessibility="no"
|
||||
tools:src="#0f0"/>
|
||||
|
||||
</LinearLayout>
|
||||
<ImageButton
|
||||
android:id="@+id/play_pause_btn"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:background="@drawable/bg_audio_play_button"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_play_arrow_48px"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/forward_btn"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_forward_10_48px"
|
||||
android:background="@drawable/bg_round_ripple"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/rewind_btn"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_replay_5_48px"
|
||||
android:background="@drawable/bg_round_ripple"/>
|
||||
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
|
@ -3,25 +3,30 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:paddingLeft="20dp"
|
||||
android:paddingRight="20dp">
|
||||
android:layout_height="42dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/reply_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="56dp">
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:background="?android:actionBarItemBackground"
|
||||
android:minWidth="34dp">
|
||||
<TextView
|
||||
android:id="@+id/reply"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:drawableStart="@drawable/ic_fluent_chat_multiple_24_regular"
|
||||
android:drawablePadding="8dp"
|
||||
android:drawableTint="?android:textColorSecondary"
|
||||
android:drawableStart="@drawable/ic_reply_20px"
|
||||
android:drawablePadding="6dp"
|
||||
android:drawableTint="?colorM3OnSurfaceVariant"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textAppearance="@style/m3_label_medium"
|
||||
tools:text="123"/>
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -34,18 +39,21 @@
|
|||
android:id="@+id/boost_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="56dp">
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:background="?android:actionBarItemBackground"
|
||||
android:minWidth="34dp">
|
||||
<TextView
|
||||
android:id="@+id/boost"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:drawableStart="@drawable/ic_boost"
|
||||
android:drawablePadding="8dp"
|
||||
android:drawableTint="@color/boost_icon"
|
||||
android:textColor="@color/boost_icon"
|
||||
android:drawableStart="@drawable/ic_repeat_selector"
|
||||
android:drawablePadding="6dp"
|
||||
android:drawableTint="?colorM3OnSurfaceVariant"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textAppearance="@style/m3_label_medium"
|
||||
tools:text="123"/>
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -58,18 +66,21 @@
|
|||
android:id="@+id/favorite_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="56dp">
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:background="?android:actionBarItemBackground"
|
||||
android:minWidth="34dp">
|
||||
<TextView
|
||||
android:id="@+id/favorite"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:drawableStart="@drawable/ic_fluent_star_24_selector"
|
||||
android:drawablePadding="8dp"
|
||||
android:drawableTint="@color/favorite_icon"
|
||||
android:textColor="@color/favorite_icon"
|
||||
android:drawableStart="@drawable/ic_star_selector"
|
||||
android:drawablePadding="6dp"
|
||||
android:drawableTint="?colorM3OnSurfaceVariant"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textAppearance="@style/m3_label_medium"
|
||||
tools:text="123"/>
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -82,14 +93,17 @@
|
|||
android:id="@+id/share_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="56dp">
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:background="?android:actionBarItemBackground"
|
||||
android:minWidth="34dp">
|
||||
<ImageView
|
||||
android:id="@+id/share"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_fluent_share_24_regular"
|
||||
android:tint="?android:textColorSecondary"
|
||||
android:src="@drawable/ic_share_20px"
|
||||
android:tint="?colorM3OnSurfaceVariant"
|
||||
android:gravity="center_vertical"/>
|
||||
</FrameLayout>
|
||||
|
||||
|
|
|
@ -13,30 +13,22 @@
|
|||
android:layout_height="24dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="-2dp"
|
||||
android:layout_marginEnd="-2dp"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:scaleType="center"
|
||||
android:tint="?android:textColorSecondary"
|
||||
android:tint="?colorM3OnSurfaceVariant"
|
||||
android:contentDescription="@string/more_options"
|
||||
android:src="@drawable/ic_post_more" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/visibility"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@id/more"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:scaleType="center"
|
||||
android:tint="?android:textColorSecondary"
|
||||
android:src="@drawable/ic_visibility" />
|
||||
android:src="@drawable/ic_more_vert_20px" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="46dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginEnd="12dp" />
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||
android:id="@+id/name_wrap"
|
||||
|
@ -53,7 +45,8 @@
|
|||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
android:gravity="start|center_vertical"
|
||||
tools:text="Eugen" />
|
||||
|
||||
<TextView
|
||||
|
@ -66,46 +59,22 @@
|
|||
android:textAppearance="@style/m3_title_medium"
|
||||
android:fontFamily="sans-serif"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="boosted your cat picture" />
|
||||
|
||||
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>
|
||||
|
||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||
<TextView
|
||||
android:id="@+id/time_and_username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:layout_below="@id/name_wrap"
|
||||
android:layout_toEndOf="@id/avatar"
|
||||
android:layout_toStartOf="@id/visibility"
|
||||
android:layoutDirection="locale"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
tools:text="\@Gargron" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/separator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:text="·"
|
||||
android:textAppearance="@style/m3_title_small" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timestamp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
android:singleLine="true"
|
||||
tools:text="3h" />
|
||||
|
||||
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
tools:text="9h ago · \@Gargron@mastodon.social"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -17,8 +17,8 @@
|
|||
android:layout_width="40dp"
|
||||
android:layout_height="22dp"
|
||||
android:layout_gravity="start|bottom"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:importantForAccessibility="no"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
@ -8,20 +9,24 @@
|
|||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textColor="?android:textColorPrimary" />
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
tools:text="fdsafdsafsdafds"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/vote_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:enabled="false"
|
||||
style="@style/Widget.Mastodon.M3.Button.Filled"
|
||||
android:text="@string/action_vote"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -5,53 +5,60 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:outlineProvider="background"
|
||||
android:elevation="2dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/bg_poll_option_clickable"
|
||||
android:duplicateParentState="true"
|
||||
android:layoutDirection="locale">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:duplicateParentState="true"
|
||||
android:tint="?colorDarkIcon"
|
||||
android:src="@drawable/ic_poll_option_button"/>
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textColor="?colorM3Primary"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:paddingEnd="26dp"
|
||||
tools:text="scream into void jsfdklfjdalskfjdsalkfjdsalkfjdsalkfdjsalkfdsajlk"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="-26dp"
|
||||
android:tint="?colorM3OnSecondaryContainer"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_poll_check" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/percent"
|
||||
android:layout_width="46dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textColor="?colorM3OnSecondaryContainer"
|
||||
android:visibility="gone"
|
||||
android:gravity="end"
|
||||
tools:visibility="visible"
|
||||
tools:text="00.0%"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
tools:text="scream into void"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -2,7 +2,6 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="-6dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="16dp">
|
||||
|
@ -11,9 +10,10 @@
|
|||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
android:drawableStart="@drawable/ic_fluent_arrow_repeat_all_20_filled"
|
||||
android:drawableTint="?android:textColorSecondary"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:drawableStart="@drawable/ic_repeat_20px"
|
||||
android:drawableTint="?colorM3OnSurfaceVariant"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:drawablePadding="6dp"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"/>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/spoiler_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/bg_spoiler"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/spoiler_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:textColor="?colorM3OnSecondaryContainer"
|
||||
tools:text="Spoilery stuff"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/spoiler_action"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:singleLine="true"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="?colorM3Primary"
|
||||
tools:text="Re-hide"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -5,38 +5,15 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="12dp">
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<org.joinmastodon.android.ui.views.LinkedTextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
android:textAppearance="@style/m3_body_large"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/spoiler_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/spoiler_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="@style/m3_title_large"
|
||||
tools:text="CW title"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/tap_to_reveal"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -5,8 +5,8 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|bottom"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:importantForAccessibility="noHideDescendants"
|
||||
|
|
|
@ -103,9 +103,9 @@
|
|||
<item quantity="one">%d day left</item>
|
||||
<item quantity="other">%d days left</item>
|
||||
</plurals>
|
||||
<plurals name="x_voters">
|
||||
<item quantity="one">%,d voter</item>
|
||||
<item quantity="other">%,d voters</item>
|
||||
<plurals name="x_votes">
|
||||
<item quantity="one">%,d vote</item>
|
||||
<item quantity="other">%,d votes</item>
|
||||
</plurals>
|
||||
<string name="poll_closed">Closed</string>
|
||||
<string name="confirm_mute_title">Mute Account</string>
|
||||
|
@ -438,4 +438,7 @@
|
|||
<!-- %1$s is server domain, %2$s is email domain. You can reorder these placeholders to fit your language better. -->
|
||||
<string name="signup_email_domain_blocked">%1$s doesn\'t allow signups from %2$s. Try a different one or <a>pick a different server</a>.</string>
|
||||
<string name="signup_username_taken">This username is taken.</string>
|
||||
<string name="spoiler_show">Show anyway</string>
|
||||
<string name="spoiler_hide">Re-hide</string>
|
||||
<string name="poll_multiple_choice">Choose one or more</string>
|
||||
</resources>
|
|
@ -4,7 +4,6 @@
|
|||
<!-- needed to disable scrim on API 29+ -->
|
||||
<item name="android:enforceNavigationBarContrast" tools:ignore="NewApi">false</item>
|
||||
<item name="android:enforceStatusBarContrast" tools:ignore="NewApi">false</item>
|
||||
<item name="appkitBackDrawable">@drawable/ic_fluent_arrow_left_24_regular</item>
|
||||
<item name="android:splitMotionEvents">false</item>
|
||||
<item name="android:windowBackground">?colorWindowBackground</item>
|
||||
<item name="android:editTextStyle">@style/Widget.Mastodon.EditText</item>
|
||||
|
@ -23,7 +22,6 @@
|
|||
<item name="colorBackgroundLight">@color/gray_50</item>
|
||||
<item name="colorBackgroundLightest">@color/gray_25</item>
|
||||
<item name="colorDarkIcon">@color/gray_900</item>
|
||||
<item name="colorWindowBackground">@color/white</item>
|
||||
<item name="android:statusBarColor">@color/gray_50</item>
|
||||
<item name="android:navigationBarColor">@color/navigation_bar_bg</item>
|
||||
<item name="android:actionBarTheme">@style/Theme.Mastodon.Toolbar</item>
|
||||
|
@ -70,13 +68,14 @@
|
|||
<item name="colorM3OnError">#FFF</item>
|
||||
<item name="colorM3ErrorContainer">#F9DEDC</item>
|
||||
<item name="colorM3OnErrorContainer">#410E0B</item>
|
||||
|
||||
<item name="colorWindowBackground">?colorM3Background</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Mastodon.Dark" parent="Theme.AppKit">
|
||||
<!-- needed to disable scrim on API 29+ -->
|
||||
<item name="android:enforceNavigationBarContrast" tools:ignore="NewApi">false</item>
|
||||
<item name="android:enforceStatusBarContrast" tools:ignore="NewApi">false</item>
|
||||
<item name="appkitBackDrawable">@drawable/ic_fluent_arrow_left_24_regular</item>
|
||||
<item name="android:splitMotionEvents">false</item>
|
||||
<item name="android:windowBackground">?colorWindowBackground</item>
|
||||
<item name="android:editTextStyle">@style/Widget.Mastodon.EditText</item>
|
||||
|
|
Loading…
Reference in New Issue