Posts redesign wip
This commit is contained in:
@@ -69,6 +69,7 @@ dependencies {
|
|||||||
implementation 'me.grishka.litex:dynamicanimation:1.1.0-alpha03'
|
implementation 'me.grishka.litex:dynamicanimation:1.1.0-alpha03'
|
||||||
implementation 'me.grishka.litex:viewpager:1.0.0'
|
implementation 'me.grishka.litex:viewpager:1.0.0'
|
||||||
implementation 'me.grishka.litex:viewpager2: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 'me.grishka.appkit:appkit:1.2.7'
|
||||||
implementation 'com.google.code.gson:gson:2.8.9'
|
implementation 'com.google.code.gson:gson:2.8.9'
|
||||||
implementation 'org.jsoup:jsoup:1.14.3'
|
implementation 'org.jsoup:jsoup:1.14.3'
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import org.joinmastodon.android.ui.text.HtmlParser;
|
|||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -57,6 +56,7 @@ public class AudioPlayerService extends Service{
|
|||||||
private static HashSet<Callback> callbacks=new HashSet<>();
|
private static HashSet<Callback> callbacks=new HashSet<>();
|
||||||
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener=this::onAudioFocusChanged;
|
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener=this::onAudioFocusChanged;
|
||||||
private boolean resumeAfterAudioFocusGain;
|
private boolean resumeAfterAudioFocusGain;
|
||||||
|
private boolean isBuffering=true;
|
||||||
|
|
||||||
private BroadcastReceiver receiver=new BroadcastReceiver(){
|
private BroadcastReceiver receiver=new BroadcastReceiver(){
|
||||||
@Override
|
@Override
|
||||||
@@ -176,6 +176,7 @@ public class AudioPlayerService extends Service{
|
|||||||
player.setOnErrorListener(this::onPlayerError);
|
player.setOnErrorListener(this::onPlayerError);
|
||||||
player.setOnCompletionListener(this::onPlayerCompletion);
|
player.setOnCompletionListener(this::onPlayerCompletion);
|
||||||
player.setOnSeekCompleteListener(this::onPlayerSeekCompleted);
|
player.setOnSeekCompleteListener(this::onPlayerSeekCompleted);
|
||||||
|
player.setOnInfoListener(this::onPlayerInfo);
|
||||||
try{
|
try{
|
||||||
player.setDataSource(this, Uri.parse(attachment.url));
|
player.setDataSource(this, Uri.parse(attachment.url));
|
||||||
player.prepareAsync();
|
player.prepareAsync();
|
||||||
@@ -187,7 +188,9 @@ public class AudioPlayerService extends Service{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onPlayerPrepared(MediaPlayer mp){
|
private void onPlayerPrepared(MediaPlayer mp){
|
||||||
|
Log.i(TAG, "onPlayerPrepared");
|
||||||
playerReady=true;
|
playerReady=true;
|
||||||
|
isBuffering=false;
|
||||||
player.start();
|
player.start();
|
||||||
updateSessionState(false);
|
updateSessionState(false);
|
||||||
}
|
}
|
||||||
@@ -205,6 +208,21 @@ public class AudioPlayerService extends Service{
|
|||||||
stopSelf();
|
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){
|
private void onAudioFocusChanged(int change){
|
||||||
switch(change){
|
switch(change){
|
||||||
case AudioManager.AUDIOFOCUS_LOSS -> {
|
case AudioManager.AUDIOFOCUS_LOSS -> {
|
||||||
@@ -232,12 +250,16 @@ public class AudioPlayerService extends Service{
|
|||||||
|
|
||||||
private void updateSessionState(boolean removeNotification){
|
private void updateSessionState(boolean removeNotification){
|
||||||
session.setPlaybackState(new PlaybackState.Builder()
|
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)
|
.setActions(PlaybackState.ACTION_STOP | PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_SEEK_TO)
|
||||||
.build());
|
.build());
|
||||||
updateNotification(!player.isPlaying(), removeNotification);
|
updateNotification(!player.isPlaying(), removeNotification);
|
||||||
for(Callback cb:callbacks)
|
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){
|
private void updateNotification(boolean dismissable, boolean removeNotification){
|
||||||
@@ -310,6 +332,12 @@ public class AudioPlayerService extends Service{
|
|||||||
return attachment.id;
|
return attachment.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PlayState getPlayState(){
|
||||||
|
if(isBuffering)
|
||||||
|
return PlayState.BUFFERING;
|
||||||
|
return player.isPlaying() ? PlayState.PLAYING : PlayState.PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
public static void registerCallback(Callback cb){
|
public static void registerCallback(Callback cb){
|
||||||
callbacks.add(cb);
|
callbacks.add(cb);
|
||||||
}
|
}
|
||||||
@@ -333,7 +361,13 @@ public class AudioPlayerService extends Service{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface Callback{
|
public interface Callback{
|
||||||
void onPlayStateChanged(String attachmentID, boolean playing, int position);
|
void onPlayStateChanged(String attachmentID, PlayState state, int position);
|
||||||
void onPlaybackStopped(String attachmentID);
|
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.MediaGridStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.PollFooterStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.PollFooterStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.PollOptionStatusDisplayItem;
|
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.StatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
||||||
@@ -48,6 +49,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -405,25 +407,26 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
.exec(accountID);
|
.exec(accountID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onRevealSpoilerClick(TextStatusDisplayItem.Holder holder){
|
public void onRevealSpoilerClick(SpoilerStatusDisplayItem.Holder holder){
|
||||||
Status status=holder.getItem().status;
|
Status status=holder.getItem().status;
|
||||||
revealSpoiler(status, holder.getItemID());
|
toggleSpoiler(status, holder.getItemID());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onRevealSpoilerClick(MediaGridStatusDisplayItem.Holder holder){
|
protected void toggleSpoiler(Status status, String itemID){
|
||||||
Status status=holder.getItem().status;
|
status.spoilerRevealed=!status.spoilerRevealed;
|
||||||
revealSpoiler(status, holder.getItemID());
|
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){
|
int index=displayItems.indexOf(spoilerItem);
|
||||||
status.spoilerRevealed=true;
|
if(status.spoilerRevealed){
|
||||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
displayItems.addAll(index+1, spoilerItem.contentItems);
|
||||||
if(text!=null)
|
adapter.notifyItemRangeInserted(index+1, spoilerItem.contentItems.size());
|
||||||
adapter.notifyItemChanged(text.getAbsoluteAdapterPosition()-getMainAdapterOffset());
|
}else{
|
||||||
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
|
displayItems.subList(index+1, index+1+spoilerItem.contentItems.size()).clear();
|
||||||
if(header!=null)
|
adapter.notifyItemRangeRemoved(index+1, spoilerItem.contentItems.size());
|
||||||
header.rebind();
|
}
|
||||||
updateImagesSpoilerState(status, itemID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder){
|
public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder){
|
||||||
|
|||||||
@@ -327,8 +327,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||||||
|
|
||||||
spoilerEdit=view.findViewById(R.id.content_warning);
|
spoilerEdit=view.findViewById(R.id.content_warning);
|
||||||
LayerDrawable spoilerBg=(LayerDrawable) spoilerEdit.getBackground().mutate();
|
LayerDrawable spoilerBg=(LayerDrawable) spoilerEdit.getBackground().mutate();
|
||||||
spoilerBg.setDrawableByLayerId(R.id.left_drawable, new SpoilerStripesDrawable());
|
spoilerBg.setDrawableByLayerId(R.id.left_drawable, new SpoilerStripesDrawable(false));
|
||||||
spoilerBg.setDrawableByLayerId(R.id.right_drawable, new SpoilerStripesDrawable());
|
spoilerBg.setDrawableByLayerId(R.id.right_drawable, new SpoilerStripesDrawable(false));
|
||||||
spoilerEdit.setBackground(spoilerBg);
|
spoilerEdit.setBackground(spoilerBg);
|
||||||
if((savedInstanceState!=null && savedInstanceState.getBoolean("hasSpoiler", false)) || hasSpoiler){
|
if((savedInstanceState!=null && savedInstanceState.getBoolean("hasSpoiler", false)) || hasSpoiler){
|
||||||
hasSpoiler=true;
|
hasSpoiler=true;
|
||||||
|
|||||||
@@ -336,6 +336,8 @@ public class OnboardingFollowSuggestionsFragment extends BaseRecyclerFragment<Pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setActionProgressVisible(boolean visible){
|
private void setActionProgressVisible(boolean visible){
|
||||||
|
if(visible)
|
||||||
|
actionProgress.setIndeterminateTintList(actionButton.getTextColors());
|
||||||
actionButton.setTextVisible(!visible);
|
actionButton.setTextVisible(!visible);
|
||||||
actionProgress.setVisibility(visible ? View.VISIBLE : View.GONE);
|
actionProgress.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||||
actionButton.setClickable(!visible);
|
actionButton.setClickable(!visible);
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ public class Attachment extends BaseModel{
|
|||||||
public PointF focus;
|
public PointF focus;
|
||||||
public SizeMetadata original;
|
public SizeMetadata original;
|
||||||
public SizeMetadata small;
|
public SizeMetadata small;
|
||||||
|
public ColorsMetadata colors;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
@@ -138,6 +139,7 @@ public class Attachment extends BaseModel{
|
|||||||
", focus="+focus+
|
", focus="+focus+
|
||||||
", original="+original+
|
", original="+original+
|
||||||
", small="+small+
|
", 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());
|
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){
|
public static ViewOutlineProvider roundedRect(int dp){
|
||||||
ViewOutlineProvider provider=roundedRects.get(dp);
|
ViewOutlineProvider provider=roundedRects.get(dp);
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
package org.joinmastodon.android.ui.displayitems;
|
package org.joinmastodon.android.ui.displayitems;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
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.os.SystemClock;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@@ -13,16 +23,27 @@ import org.joinmastodon.android.R;
|
|||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.model.Attachment;
|
import org.joinmastodon.android.model.Attachment;
|
||||||
import org.joinmastodon.android.model.Status;
|
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.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 class AudioStatusDisplayItem extends StatusDisplayItem{
|
||||||
public final Status status;
|
public final Status status;
|
||||||
public final Attachment attachment;
|
public final Attachment attachment;
|
||||||
|
private final ImageLoaderRequest imageRequest;
|
||||||
|
|
||||||
public AudioStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status, Attachment attachment){
|
public AudioStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status, Attachment attachment){
|
||||||
super(parentID, parentFragment);
|
super(parentID, parentFragment);
|
||||||
this.status=status;
|
this.status=status;
|
||||||
this.attachment=attachment;
|
this.attachment=attachment;
|
||||||
|
imageRequest=new UrlImageLoaderRequest(TextUtils.isEmpty(attachment.previewUrl) ? status.account.avatarStatic : attachment.previewUrl, V.dp(100), V.dp(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -30,25 +51,38 @@ public class AudioStatusDisplayItem extends StatusDisplayItem{
|
|||||||
return Type.AUDIO;
|
return Type.AUDIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Holder extends StatusDisplayItem.Holder<AudioStatusDisplayItem> implements AudioPlayerService.Callback{
|
@Override
|
||||||
private final ImageButton playPauseBtn;
|
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 TextView time;
|
||||||
private final SeekBar seekBar;
|
private final ImageView image;
|
||||||
|
private final FrameLayout content;
|
||||||
|
private final AudioAttachmentBackgroundDrawable bgDrawable;
|
||||||
|
|
||||||
private int lastKnownPosition;
|
private int lastKnownPosition;
|
||||||
private long lastKnownPositionTime;
|
private long lastKnownPositionTime;
|
||||||
private boolean playing;
|
private int lastPosSeconds=-1;
|
||||||
private int lastRemainingSeconds=-1;
|
private AudioPlayerService.PlayState state;
|
||||||
private boolean seekbarBeingDragged;
|
|
||||||
|
|
||||||
private Runnable positionUpdater=this::updatePosition;
|
private final Runnable positionUpdater=this::updatePosition;
|
||||||
|
|
||||||
public Holder(Context context, ViewGroup parent){
|
public Holder(Context context, ViewGroup parent){
|
||||||
super(context, R.layout.display_item_audio, parent);
|
super(context, R.layout.display_item_audio, parent);
|
||||||
playPauseBtn=findViewById(R.id.play_pause_btn);
|
playPauseBtn=findViewById(R.id.play_pause_btn);
|
||||||
time=findViewById(R.id.time);
|
time=findViewById(R.id.time);
|
||||||
seekBar=findViewById(R.id.seekbar);
|
image=findViewById(R.id.image);
|
||||||
seekBar.setThumb(new SeekBarThumbDrawable(context));
|
content=findViewById(R.id.content);
|
||||||
|
forwardBtn=findViewById(R.id.forward_btn);
|
||||||
|
rewindBtn=findViewById(R.id.rewind_btn);
|
||||||
playPauseBtn.setOnClickListener(this::onPlayPauseClick);
|
playPauseBtn.setOnClickListener(this::onPlayPauseClick);
|
||||||
itemView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener(){
|
itemView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener(){
|
||||||
@Override
|
@Override
|
||||||
@@ -61,76 +95,71 @@ public class AudioStatusDisplayItem extends StatusDisplayItem{
|
|||||||
AudioPlayerService.unregisterCallback(Holder.this);
|
AudioPlayerService.unregisterCallback(Holder.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){
|
forwardBtn.setOnClickListener(this::onSeekButtonClick);
|
||||||
@Override
|
rewindBtn.setOnClickListener(this::onSeekButtonClick);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
image.setOutlineProvider(OutlineProviders.OVAL);
|
||||||
public void onStartTrackingTouch(SeekBar seekBar){
|
image.setClipToOutline(true);
|
||||||
seekbarBeingDragged=true;
|
content.setBackground(bgDrawable=new AudioAttachmentBackgroundDrawable());
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(AudioStatusDisplayItem item){
|
public void onBind(AudioStatusDisplayItem item){
|
||||||
int seconds=(int)item.attachment.getDuration();
|
int seconds=(int)item.attachment.getDuration();
|
||||||
String duration=formatDuration(seconds);
|
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();
|
AudioPlayerService service=AudioPlayerService.getInstance();
|
||||||
if(service!=null && service.getAttachmentID().equals(item.attachment.id)){
|
if(service!=null && service.getAttachmentID().equals(item.attachment.id)){
|
||||||
seekBar.setEnabled(true);
|
forwardBtn.setVisibility(View.VISIBLE);
|
||||||
onPlayStateChanged(item.attachment.id, service.isPlaying(), service.getPosition());
|
rewindBtn.setVisibility(View.VISIBLE);
|
||||||
|
onPlayStateChanged(item.attachment.id, service.getPlayState(), service.getPosition());
|
||||||
|
actuallyUpdatePosition();
|
||||||
}else{
|
}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){
|
private void onPlayPauseClick(View v){
|
||||||
AudioPlayerService service=AudioPlayerService.getInstance();
|
AudioPlayerService service=AudioPlayerService.getInstance();
|
||||||
if(service!=null && service.getAttachmentID().equals(item.attachment.id)){
|
if(service!=null && service.getAttachmentID().equals(item.attachment.id)){
|
||||||
if(playing)
|
if(state!=AudioPlayerService.PlayState.PAUSED)
|
||||||
service.pause(true);
|
service.pause(true);
|
||||||
else
|
else
|
||||||
service.play();
|
service.play();
|
||||||
}else{
|
}else{
|
||||||
AudioPlayerService.start(v.getContext(), item.status, item.attachment);
|
AudioPlayerService.start(v.getContext(), item.status, item.attachment);
|
||||||
onPlayStateChanged(item.attachment.id, true, 0);
|
onPlayStateChanged(item.attachment.id, AudioPlayerService.PlayState.BUFFERING, 0);
|
||||||
seekBar.setEnabled(true);
|
forwardBtn.setVisibility(View.VISIBLE);
|
||||||
|
rewindBtn.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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)){
|
if(attachmentID.equals(item.attachment.id)){
|
||||||
this.lastKnownPosition=position;
|
this.lastKnownPosition=position;
|
||||||
lastKnownPositionTime=SystemClock.uptimeMillis();
|
lastKnownPositionTime=SystemClock.uptimeMillis();
|
||||||
this.playing=playing;
|
this.state=state;
|
||||||
playPauseBtn.setImageResource(playing ? R.drawable.ic_fluent_pause_circle_24_filled : R.drawable.ic_fluent_play_circle_24_filled);
|
setPlayButtonPlaying(state!=AudioPlayerService.PlayState.PAUSED, true);
|
||||||
if(!playing){
|
if(state==AudioPlayerService.PlayState.PLAYING){
|
||||||
lastRemainingSeconds=-1;
|
|
||||||
time.setText(formatDuration((int) item.attachment.getDuration()));
|
|
||||||
}else{
|
|
||||||
itemView.postOnAnimation(positionUpdater);
|
itemView.postOnAnimation(positionUpdater);
|
||||||
|
}else if(state==AudioPlayerService.PlayState.BUFFERING){
|
||||||
|
actuallyUpdatePosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,14 +167,15 @@ public class AudioStatusDisplayItem extends StatusDisplayItem{
|
|||||||
@Override
|
@Override
|
||||||
public void onPlaybackStopped(String attachmentID){
|
public void onPlaybackStopped(String attachmentID){
|
||||||
if(attachmentID.equals(item.attachment.id)){
|
if(attachmentID.equals(item.attachment.id)){
|
||||||
playing=false;
|
state=null;
|
||||||
playPauseBtn.setImageResource(R.drawable.ic_fluent_play_circle_24_filled);
|
setPlayButtonPlaying(false, true);
|
||||||
seekBar.setProgress(0);
|
forwardBtn.setVisibility(View.INVISIBLE);
|
||||||
seekBar.setEnabled(false);
|
rewindBtn.setVisibility(View.INVISIBLE);
|
||||||
time.setText(formatDuration((int)item.attachment.getDuration()));
|
time.setText(formatDuration((int)item.attachment.getDuration()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
private String formatDuration(int seconds){
|
private String formatDuration(int seconds){
|
||||||
if(seconds>=3600)
|
if(seconds>=3600)
|
||||||
return String.format("%d:%02d:%02d", seconds/3600, seconds%3600/60, seconds%60);
|
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(){
|
private void updatePosition(){
|
||||||
if(!playing || seekbarBeingDragged)
|
if(state!=AudioPlayerService.PlayState.PLAYING)
|
||||||
return;
|
return;
|
||||||
double pos=lastKnownPosition/1000.0+(SystemClock.uptimeMillis()-lastKnownPositionTime)/1000.0;
|
actuallyUpdatePosition();
|
||||||
seekBar.setProgress((int)Math.round(pos/item.attachment.getDuration()*10000.0));
|
|
||||||
itemView.postOnAnimation(positionUpdater);
|
itemView.postOnAnimation(positionUpdater);
|
||||||
int remainingSeconds=(int)(item.attachment.getDuration()-pos);
|
}
|
||||||
if(remainingSeconds!=lastRemainingSeconds){
|
|
||||||
lastRemainingSeconds=remainingSeconds;
|
@SuppressLint("SetTextI18n")
|
||||||
time.setText("-"+formatDuration(remainingSeconds));
|
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.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -45,6 +47,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
public static class Holder extends StatusDisplayItem.Holder<FooterStatusDisplayItem>{
|
public static class Holder extends StatusDisplayItem.Holder<FooterStatusDisplayItem>{
|
||||||
private final TextView reply, boost, favorite;
|
private final TextView reply, boost, favorite;
|
||||||
private final ImageView share;
|
private final ImageView share;
|
||||||
|
private final ColorStateList buttonColors;
|
||||||
|
|
||||||
private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){
|
private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){
|
||||||
@Override
|
@Override
|
||||||
@@ -61,6 +64,27 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
boost=findViewById(R.id.boost);
|
boost=findViewById(R.id.boost);
|
||||||
favorite=findViewById(R.id.favorite);
|
favorite=findViewById(R.id.favorite);
|
||||||
share=findViewById(R.id.share);
|
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){
|
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N){
|
||||||
UiUtils.fixCompoundDrawableTintOnAndroid6(reply);
|
UiUtils.fixCompoundDrawableTintOnAndroid6(reply);
|
||||||
UiUtils.fixCompoundDrawableTintOnAndroid6(boost);
|
UiUtils.fixCompoundDrawableTintOnAndroid6(boost);
|
||||||
@@ -94,7 +118,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
private void bindButton(TextView btn, long count){
|
private void bindButton(TextView btn, long count){
|
||||||
if(count>0 && !item.hideCounts){
|
if(count>0 && !item.hideCounts){
|
||||||
btn.setText(UiUtils.abbreviateNumber(count));
|
btn.setText(UiUtils.abbreviateNumber(count));
|
||||||
btn.setCompoundDrawablePadding(V.dp(8));
|
btn.setCompoundDrawablePadding(V.dp(6));
|
||||||
}else{
|
}else{
|
||||||
btn.setText("");
|
btn.setText("");
|
||||||
btn.setCompoundDrawablePadding(0);
|
btn.setCompoundDrawablePadding(0);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.joinmastodon.android.ui.displayitems;
|
package org.joinmastodon.android.ui.displayitems;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.graphics.Outline;
|
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.Attachment;
|
||||||
import org.joinmastodon.android.model.Relationship;
|
import org.joinmastodon.android.model.Relationship;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
|
import org.joinmastodon.android.ui.OutlineProviders;
|
||||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
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{
|
public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||||
private final TextView name, username, timestamp, extraText;
|
private final TextView name, timeAndUsername, extraText;
|
||||||
private final ImageView avatar, more, visibility;
|
private final ImageView avatar, more;
|
||||||
private final PopupMenu optionsMenu;
|
private final PopupMenu optionsMenu;
|
||||||
private Relationship relationship;
|
private Relationship relationship;
|
||||||
private APIRequest<?> currentRelationshipRequest;
|
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){
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
super(activity, R.layout.display_item_header, parent);
|
super(activity, R.layout.display_item_header, parent);
|
||||||
name=findViewById(R.id.name);
|
name=findViewById(R.id.name);
|
||||||
username=findViewById(R.id.username);
|
timeAndUsername=findViewById(R.id.time_and_username);
|
||||||
timestamp=findViewById(R.id.timestamp);
|
|
||||||
avatar=findViewById(R.id.avatar);
|
avatar=findViewById(R.id.avatar);
|
||||||
more=findViewById(R.id.more);
|
more=findViewById(R.id.more);
|
||||||
visibility=findViewById(R.id.visibility);
|
|
||||||
extraText=findViewById(R.id.extra_text);
|
extraText=findViewById(R.id.extra_text);
|
||||||
avatar.setOnClickListener(this::onAvaClick);
|
avatar.setOnClickListener(this::onAvaClick);
|
||||||
avatar.setOutlineProvider(roundCornersOutline);
|
avatar.setOutlineProvider(OutlineProviders.roundedRect(10));
|
||||||
avatar.setClipToOutline(true);
|
avatar.setClipToOutline(true);
|
||||||
more.setOnClickListener(this::onMoreClick);
|
more.setOnClickListener(this::onMoreClick);
|
||||||
visibility.setOnClickListener(v->item.parentFragment.onVisibilityIconClick(this));
|
|
||||||
|
|
||||||
optionsMenu=new PopupMenu(activity, more);
|
optionsMenu=new PopupMenu(activity, more);
|
||||||
optionsMenu.inflate(R.menu.post);
|
optionsMenu.inflate(R.menu.post);
|
||||||
@@ -200,22 +192,17 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
@Override
|
@Override
|
||||||
public void onBind(HeaderStatusDisplayItem item){
|
public void onBind(HeaderStatusDisplayItem item){
|
||||||
name.setText(item.parsedName);
|
name.setText(item.parsedName);
|
||||||
username.setText('@'+item.user.acct);
|
String time;
|
||||||
if(item.status==null || item.status.editedAt==null)
|
if(item.status==null || item.status.editedAt==null)
|
||||||
timestamp.setText(UiUtils.formatRelativeTimestamp(itemView.getContext(), item.createdAt));
|
time=UiUtils.formatRelativeTimestamp(itemView.getContext(), item.createdAt);
|
||||||
else
|
else
|
||||||
timestamp.setText(item.parentFragment.getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(itemView.getContext(), item.status.editedAt)));
|
time=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){
|
timeAndUsername.setText(time+" · @"+item.user.acct);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), item.needBottomPadding ? V.dp(16) : 0);
|
itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), item.needBottomPadding ? V.dp(16) : 0);
|
||||||
if(TextUtils.isEmpty(item.extraText)){
|
if(TextUtils.isEmpty(item.extraText)){
|
||||||
extraText.setVisibility(View.GONE);
|
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.ImageLoaderRequest;
|
||||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||||
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
||||||
private static final String TAG="MediaGridDisplayItem";
|
private static final String TAG="MediaGridDisplayItem";
|
||||||
@@ -97,6 +98,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
|||||||
wrapper=(FrameLayout)itemView;
|
wrapper=(FrameLayout)itemView;
|
||||||
layout=new MediaGridLayout(activity);
|
layout=new MediaGridLayout(activity);
|
||||||
wrapper.addView(layout);
|
wrapper.addView(layout);
|
||||||
|
wrapper.setPadding(0, 0, 0, V.dp(8));
|
||||||
|
|
||||||
activity.getLayoutInflater().inflate(R.layout.overlay_image_alt_text, wrapper);
|
activity.getLayoutInflater().inflate(R.layout.overlay_image_alt_text, wrapper);
|
||||||
altTextWrapper=findViewById(R.id.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);
|
altTextClose=findViewById(R.id.alt_text_close);
|
||||||
altText=findViewById(R.id.alt_text);
|
altText=findViewById(R.id.alt_text);
|
||||||
altTextClose.setOnClickListener(this::onAltTextCloseClick);
|
altTextClose.setOnClickListener(this::onAltTextCloseClick);
|
||||||
|
wrapper.setClipToPadding(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -158,11 +161,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
|||||||
|
|
||||||
private void onViewClick(View v){
|
private void onViewClick(View v){
|
||||||
int index=(Integer)v.getTag();
|
int index=(Integer)v.getTag();
|
||||||
if(!item.status.spoilerRevealed){
|
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, index, this);
|
||||||
item.parentFragment.onRevealSpoilerClick(this);
|
|
||||||
}else if(item.parentFragment instanceof PhotoViewerHost){
|
|
||||||
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, index, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAltTextClick(View v){
|
private void onAltTextClick(View v){
|
||||||
|
|||||||
@@ -37,9 +37,11 @@ public class PollFooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(PollFooterStatusDisplayItem item){
|
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()){
|
if(item.poll.expiresAt!=null && !item.poll.isExpired()){
|
||||||
text+=" · "+UiUtils.formatTimeLeft(itemView.getContext(), item.poll.expiresAt);
|
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()){
|
}else if(item.poll.isExpired()){
|
||||||
text+=" · "+item.parentFragment.getString(R.string.poll_closed);
|
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.R;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.model.Poll;
|
import org.joinmastodon.android.model.Poll;
|
||||||
|
import org.joinmastodon.android.ui.OutlineProviders;
|
||||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||||
|
|
||||||
@@ -25,11 +26,13 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
|||||||
private boolean showResults;
|
private boolean showResults;
|
||||||
private float votesFraction; // 0..1
|
private float votesFraction; // 0..1
|
||||||
private boolean isMostVoted;
|
private boolean isMostVoted;
|
||||||
|
private final int optionIndex;
|
||||||
public final Poll poll;
|
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);
|
super(parentID, parentFragment);
|
||||||
this.option=option;
|
this.optionIndex=optionIndex;
|
||||||
|
option=poll.options.get(optionIndex);
|
||||||
this.poll=poll;
|
this.poll=poll;
|
||||||
text=HtmlParser.parseCustomEmoji(option.title, poll.emojis);
|
text=HtmlParser.parseCustomEmoji(option.title, poll.emojis);
|
||||||
emojiHelper.setText(text);
|
emojiHelper.setText(text);
|
||||||
@@ -61,23 +64,24 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
|||||||
|
|
||||||
public static class Holder extends StatusDisplayItem.Holder<PollOptionStatusDisplayItem> implements ImageLoaderViewHolder{
|
public static class Holder extends StatusDisplayItem.Holder<PollOptionStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||||
private final TextView text, percent;
|
private final TextView text, percent;
|
||||||
private final View icon, button;
|
private final View check, button;
|
||||||
private final Drawable progressBg;
|
private final Drawable progressBg;
|
||||||
|
|
||||||
public Holder(Activity activity, ViewGroup parent){
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
super(activity, R.layout.display_item_poll_option, parent);
|
super(activity, R.layout.display_item_poll_option, parent);
|
||||||
text=findViewById(R.id.text);
|
text=findViewById(R.id.text);
|
||||||
percent=findViewById(R.id.percent);
|
percent=findViewById(R.id.percent);
|
||||||
icon=findViewById(R.id.icon);
|
check=findViewById(R.id.checkbox);
|
||||||
button=findViewById(R.id.button);
|
button=findViewById(R.id.button);
|
||||||
progressBg=activity.getResources().getDrawable(R.drawable.bg_poll_option_voted, activity.getTheme()).mutate();
|
progressBg=activity.getResources().getDrawable(R.drawable.bg_poll_option_voted, activity.getTheme()).mutate();
|
||||||
itemView.setOnClickListener(this::onButtonClick);
|
itemView.setOnClickListener(this::onButtonClick);
|
||||||
|
button.setOutlineProvider(OutlineProviders.roundedRect(20));
|
||||||
|
button.setClipToOutline(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(PollOptionStatusDisplayItem item){
|
public void onBind(PollOptionStatusDisplayItem item){
|
||||||
text.setText(item.text);
|
text.setText(item.text);
|
||||||
icon.setVisibility(item.showResults ? View.GONE : View.VISIBLE);
|
|
||||||
percent.setVisibility(item.showResults ? View.VISIBLE : View.GONE);
|
percent.setVisibility(item.showResults ? View.VISIBLE : View.GONE);
|
||||||
itemView.setClickable(!item.showResults);
|
itemView.setClickable(!item.showResults);
|
||||||
if(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 GAP -> new GapStatusDisplayItem.Holder(activity, parent);
|
||||||
case EXTENDED_FOOTER -> new ExtendedFooterStatusDisplayItem.Holder(activity, parent);
|
case EXTENDED_FOOTER -> new ExtendedFooterStatusDisplayItem.Holder(activity, parent);
|
||||||
case MEDIA_GRID -> new MediaGridStatusDisplayItem.Holder(activity, parent);
|
case MEDIA_GRID -> new MediaGridStatusDisplayItem.Holder(activity, parent);
|
||||||
|
case SPOILER -> new SpoilerStatusDisplayItem.Holder(activity, parent);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,32 +73,43 @@ public abstract class StatusDisplayItem{
|
|||||||
ArrayList<StatusDisplayItem> items=new ArrayList<>();
|
ArrayList<StatusDisplayItem> items=new ArrayList<>();
|
||||||
Status statusForContent=status.getContentStatus();
|
Status statusForContent=status.getContentStatus();
|
||||||
if(status.reblog!=null){
|
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)){
|
}else if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId)){
|
||||||
Account account=Objects.requireNonNull(knownAccounts.get(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;
|
HeaderStatusDisplayItem header;
|
||||||
items.add(header=new HeaderStatusDisplayItem(parentID, statusForContent.account, statusForContent.createdAt, fragment, accountID, statusForContent, null));
|
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))
|
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
|
else
|
||||||
header.needBottomPadding=true;
|
header.needBottomPadding=true;
|
||||||
|
|
||||||
List<Attachment> imageAttachments=statusForContent.mediaAttachments.stream().filter(att->att.type.isImage()).collect(Collectors.toList());
|
List<Attachment> imageAttachments=statusForContent.mediaAttachments.stream().filter(att->att.type.isImage()).collect(Collectors.toList());
|
||||||
if(!imageAttachments.isEmpty()){
|
if(!imageAttachments.isEmpty()){
|
||||||
PhotoLayoutHelper.TiledLayoutResult layout=PhotoLayoutHelper.processThumbs(imageAttachments);
|
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){
|
for(Attachment att:statusForContent.mediaAttachments){
|
||||||
if(att.type==Attachment.Type.AUDIO){
|
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){
|
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)){
|
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){
|
if(addFooter){
|
||||||
items.add(new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID));
|
items.add(new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID));
|
||||||
@@ -109,12 +121,20 @@ public abstract class StatusDisplayItem{
|
|||||||
item.inset=inset;
|
item.inset=inset;
|
||||||
item.index=i++;
|
item.index=i++;
|
||||||
}
|
}
|
||||||
|
if(items!=contentItems){
|
||||||
|
for(StatusDisplayItem item:contentItems){
|
||||||
|
item.inset=inset;
|
||||||
|
item.index=i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){
|
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){
|
||||||
|
int i=0;
|
||||||
for(Poll.Option opt:poll.options){
|
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));
|
items.add(new PollFooterStatusDisplayItem(parentID, fragment, poll));
|
||||||
}
|
}
|
||||||
@@ -133,7 +153,8 @@ public abstract class StatusDisplayItem{
|
|||||||
HASHTAG,
|
HASHTAG,
|
||||||
GAP,
|
GAP,
|
||||||
EXTENDED_FOOTER,
|
EXTENDED_FOOTER,
|
||||||
MEDIA_GRID
|
MEDIA_GRID,
|
||||||
|
SPOILER
|
||||||
}
|
}
|
||||||
|
|
||||||
public static abstract class Holder<T extends StatusDisplayItem> extends BindableViewHolder<T> implements UsableRecyclerView.DisableableClickable{
|
public static abstract class Holder<T extends StatusDisplayItem> extends BindableViewHolder<T> implements UsableRecyclerView.DisableableClickable{
|
||||||
|
|||||||
@@ -3,15 +3,11 @@ package org.joinmastodon.android.ui.displayitems;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.graphics.drawable.Animatable;
|
import android.graphics.drawable.Animatable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.model.Status;
|
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.utils.CustomEmojiHelper;
|
||||||
import org.joinmastodon.android.ui.views.LinkedTextView;
|
import org.joinmastodon.android.ui.views.LinkedTextView;
|
||||||
|
|
||||||
@@ -21,8 +17,7 @@ import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
|||||||
|
|
||||||
public class TextStatusDisplayItem extends StatusDisplayItem{
|
public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||||
private CharSequence text;
|
private CharSequence text;
|
||||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper(), spoilerEmojiHelper;
|
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
||||||
private CharSequence parsedSpoilerText;
|
|
||||||
public boolean textSelectable;
|
public boolean textSelectable;
|
||||||
public final Status status;
|
public final Status status;
|
||||||
|
|
||||||
@@ -31,11 +26,6 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||||||
this.text=text;
|
this.text=text;
|
||||||
this.status=status;
|
this.status=status;
|
||||||
emojiHelper.setText(text);
|
emojiHelper.setText(text);
|
||||||
if(!TextUtils.isEmpty(status.spoilerText)){
|
|
||||||
parsedSpoilerText=HtmlParser.parseCustomEmoji(status.spoilerText, status.emojis);
|
|
||||||
spoilerEmojiHelper=new CustomEmojiHelper();
|
|
||||||
spoilerEmojiHelper.setText(parsedSpoilerText);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -45,29 +35,20 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getImageCount(){
|
public int getImageCount(){
|
||||||
if(spoilerEmojiHelper!=null && !status.spoilerRevealed)
|
|
||||||
return spoilerEmojiHelper.getImageCount();
|
|
||||||
return emojiHelper.getImageCount();
|
return emojiHelper.getImageCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImageLoaderRequest getImageRequest(int index){
|
public ImageLoaderRequest getImageRequest(int index){
|
||||||
if(spoilerEmojiHelper!=null && !status.spoilerRevealed)
|
|
||||||
return spoilerEmojiHelper.getImageRequest(index);
|
|
||||||
return emojiHelper.getImageRequest(index);
|
return emojiHelper.getImageRequest(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Holder extends StatusDisplayItem.Holder<TextStatusDisplayItem> implements ImageLoaderViewHolder{
|
public static class Holder extends StatusDisplayItem.Holder<TextStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||||
private final LinkedTextView text;
|
private final LinkedTextView text;
|
||||||
private final TextView spoilerTitle;
|
|
||||||
private final View spoilerOverlay;
|
|
||||||
|
|
||||||
public Holder(Activity activity, ViewGroup parent){
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
super(activity, R.layout.display_item_text, parent);
|
super(activity, R.layout.display_item_text, parent);
|
||||||
text=findViewById(R.id.text);
|
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
|
@Override
|
||||||
@@ -75,29 +56,13 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||||||
text.setText(item.text);
|
text.setText(item.text);
|
||||||
text.setTextIsSelectable(item.textSelectable);
|
text.setTextIsSelectable(item.textSelectable);
|
||||||
text.setInvalidateOnEveryFrame(false);
|
text.setInvalidateOnEveryFrame(false);
|
||||||
if(!TextUtils.isEmpty(item.status.spoilerText)){
|
itemView.setClickable(false);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setImage(int index, Drawable image){
|
public void setImage(int index, Drawable image){
|
||||||
getEmojiHelper().setImageDrawable(index, image);
|
getEmojiHelper().setImageDrawable(index, image);
|
||||||
text.invalidate();
|
text.invalidate();
|
||||||
spoilerTitle.invalidate();
|
|
||||||
if(image instanceof Animatable){
|
if(image instanceof Animatable){
|
||||||
((Animatable) image).start();
|
((Animatable) image).start();
|
||||||
if(image instanceof MovieDrawable)
|
if(image instanceof MovieDrawable)
|
||||||
@@ -112,7 +77,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CustomEmojiHelper getEmojiHelper(){
|
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{
|
public class SpoilerStripesDrawable extends Drawable{
|
||||||
private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
|
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.setColor(0xff000000);
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
paint.setStrokeWidth(3);
|
paint.setStrokeWidth(3);
|
||||||
|
this.flipped=flipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -34,7 +39,7 @@ public class SpoilerStripesDrawable extends Drawable{
|
|||||||
float y1=6.80133f;
|
float y1=6.80133f;
|
||||||
float y2=-1.22874f;
|
float y2=-1.22874f;
|
||||||
while(y2<height){
|
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;
|
y1+=8.03007f;
|
||||||
y2+=8.03007f;
|
y2+=8.03007f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public class LinkSpan extends CharacterStyle {
|
|||||||
@Override
|
@Override
|
||||||
public void updateDrawState(TextPaint tp) {
|
public void updateDrawState(TextPaint tp) {
|
||||||
tp.setColor(color=tp.linkColor);
|
tp.setColor(color=tp.linkColor);
|
||||||
|
tp.setUnderlineText(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClick(Context context){
|
public void onClick(Context context){
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public class FrameLayoutThatOnlyMeasuresFirstChild extends FrameLayout{
|
|||||||
return;
|
return;
|
||||||
View child0=getChildAt(0);
|
View child0=getChildAt(0);
|
||||||
measureChild(child0, widthMeasureSpec, heightMeasureSpec);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
mastodon/src/main/res/drawable/bg_audio_play_button.xml
Normal file
13
mastodon/src/main/res/drawable/bg_audio_play_button.xml
Normal file
@@ -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">
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
|
||||||
<item>
|
<item>
|
||||||
<shape>
|
<shape>
|
||||||
<solid android:color="?android:colorBackground"/>
|
<stroke android:width="1dp" android:color="?colorM3Outline"/>
|
||||||
<corners android:radius="10dp"/>
|
<corners android:radius="20dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:id="@android:id/mask">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="#000"/>
|
||||||
|
<corners android:radius="20dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
</ripple>
|
</ripple>
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item>
|
<item>
|
||||||
<shape>
|
<scale android:scaleGravity="start|fill_vertical" android:scaleWidth="100%">
|
||||||
<solid android:color="?android:colorBackground"/>
|
<shape>
|
||||||
<corners android:radius="10dp"/>
|
<solid android:color="?colorM3SecondaryContainer"/>
|
||||||
</shape>
|
<corners android:radius="20dp"/>
|
||||||
|
</shape>
|
||||||
|
</scale>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<clip android:clipOrientation="horizontal" android:gravity="start">
|
<shape>
|
||||||
<shape>
|
<stroke android:width="1dp" android:color="?colorM3Outline"/>
|
||||||
<solid android:color="@color/poll_option_progress"/>
|
<corners android:radius="20dp"/>
|
||||||
<corners android:radius="10dp"/>
|
</shape>
|
||||||
</shape>
|
|
||||||
</clip>
|
|
||||||
</item>
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
8
mastodon/src/main/res/drawable/bg_round_ripple.xml
Normal file
8
mastodon/src/main/res/drawable/bg_round_ripple.xml
Normal file
@@ -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>
|
||||||
31
mastodon/src/main/res/drawable/bg_spoiler.xml
Normal file
31
mastodon/src/main/res/drawable/bg_spoiler.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_check_20px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_check_20px.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_forward_10_48px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_forward_10_48px.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_more_vert_20px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_more_vert_20px.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_pause_48px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_pause_48px.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_play_arrow_48px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_play_arrow_48px.xml
Normal file
@@ -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>
|
||||||
4
mastodon/src/main/res/drawable/ic_poll_check.xml
Normal file
4
mastodon/src/main/res/drawable/ic_poll_check.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_repeat_20px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_repeat_20px.xml
Normal file
@@ -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>
|
||||||
5
mastodon/src/main/res/drawable/ic_repeat_selector.xml
Normal file
5
mastodon/src/main/res/drawable/ic_repeat_selector.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_replay_5_48px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_replay_5_48px.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_reply_20px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_reply_20px.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_share_20px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_share_20px.xml
Normal file
@@ -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>
|
||||||
9
mastodon/src/main/res/drawable/ic_star_20px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_star_20px.xml
Normal file
@@ -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>
|
||||||
5
mastodon/src/main/res/drawable/ic_star_selector.xml
Normal file
5
mastodon/src/main/res/drawable/ic_star_selector.xml
Normal file
@@ -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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="-8dp"
|
|
||||||
android:layout_marginBottom="-8dp"
|
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:paddingRight="16dp"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:clipToPadding="false">
|
android:clipToPadding="false">
|
||||||
|
|
||||||
<LinearLayout
|
<FrameLayout
|
||||||
|
android:id="@+id/content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="40dp"
|
android:layout_height="188dp">
|
||||||
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"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/time"
|
android:id="@+id/time"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="20dp"
|
||||||
android:textAppearance="@style/m3_label_medium"
|
android:layout_margin="8dp"
|
||||||
|
android:layout_gravity="bottom|start"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
android:textColor="?colorButtonText"
|
android:textColor="?colorButtonText"
|
||||||
android:gravity="end"
|
android:gravity="center_vertical"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
|
android:fontFeatureSettings="'tnum'"
|
||||||
tools:text="1:23"/>
|
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>
|
</FrameLayout>
|
||||||
@@ -3,25 +3,30 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="42dp"
|
||||||
android:paddingLeft="20dp"
|
android:paddingBottom="8dp"
|
||||||
android:paddingRight="20dp">
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/reply_btn"
|
android:id="@+id/reply_btn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:minWidth="56dp">
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:background="?android:actionBarItemBackground"
|
||||||
|
android:minWidth="34dp">
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/reply"
|
android:id="@+id/reply"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:drawableStart="@drawable/ic_fluent_chat_multiple_24_regular"
|
android:drawableStart="@drawable/ic_reply_20px"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="6dp"
|
||||||
android:drawableTint="?android:textColorSecondary"
|
android:drawableTint="?colorM3OnSurfaceVariant"
|
||||||
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAppearance="@style/m3_label_large"
|
android:textAppearance="@style/m3_label_medium"
|
||||||
tools:text="123"/>
|
tools:text="123"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@@ -34,18 +39,21 @@
|
|||||||
android:id="@+id/boost_btn"
|
android:id="@+id/boost_btn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:minWidth="56dp">
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:background="?android:actionBarItemBackground"
|
||||||
|
android:minWidth="34dp">
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/boost"
|
android:id="@+id/boost"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:drawableStart="@drawable/ic_boost"
|
android:drawableStart="@drawable/ic_repeat_selector"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="6dp"
|
||||||
android:drawableTint="@color/boost_icon"
|
android:drawableTint="?colorM3OnSurfaceVariant"
|
||||||
android:textColor="@color/boost_icon"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAppearance="@style/m3_label_large"
|
android:textAppearance="@style/m3_label_medium"
|
||||||
tools:text="123"/>
|
tools:text="123"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@@ -58,18 +66,21 @@
|
|||||||
android:id="@+id/favorite_btn"
|
android:id="@+id/favorite_btn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:minWidth="56dp">
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:background="?android:actionBarItemBackground"
|
||||||
|
android:minWidth="34dp">
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/favorite"
|
android:id="@+id/favorite"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:drawableStart="@drawable/ic_fluent_star_24_selector"
|
android:drawableStart="@drawable/ic_star_selector"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="6dp"
|
||||||
android:drawableTint="@color/favorite_icon"
|
android:drawableTint="?colorM3OnSurfaceVariant"
|
||||||
android:textColor="@color/favorite_icon"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAppearance="@style/m3_label_large"
|
android:textAppearance="@style/m3_label_medium"
|
||||||
tools:text="123"/>
|
tools:text="123"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@@ -82,14 +93,17 @@
|
|||||||
android:id="@+id/share_btn"
|
android:id="@+id/share_btn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:minWidth="56dp">
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:background="?android:actionBarItemBackground"
|
||||||
|
android:minWidth="34dp">
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/share"
|
android:id="@+id/share"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:src="@drawable/ic_fluent_share_24_regular"
|
android:src="@drawable/ic_share_20px"
|
||||||
android:tint="?android:textColorSecondary"
|
android:tint="?colorM3OnSurfaceVariant"
|
||||||
android:gravity="center_vertical"/>
|
android:gravity="center_vertical"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -13,30 +13,22 @@
|
|||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginTop="-2dp"
|
||||||
|
android:layout_marginEnd="-2dp"
|
||||||
android:background="?android:selectableItemBackgroundBorderless"
|
android:background="?android:selectableItemBackgroundBorderless"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:tint="?android:textColorSecondary"
|
android:tint="?colorM3OnSurfaceVariant"
|
||||||
android:contentDescription="@string/more_options"
|
android:contentDescription="@string/more_options"
|
||||||
android:src="@drawable/ic_post_more" />
|
android:src="@drawable/ic_more_vert_20px" />
|
||||||
|
|
||||||
<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" />
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/avatar"
|
android:id="@+id/avatar"
|
||||||
android:layout_width="46dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="46dp"
|
android:layout_height="40dp"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginEnd="12dp" />
|
android:layout_marginTop="2dp"
|
||||||
|
android:layout_marginEnd="8dp" />
|
||||||
|
|
||||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||||
android:id="@+id/name_wrap"
|
android:id="@+id/name_wrap"
|
||||||
@@ -53,7 +45,8 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textAppearance="@style/m3_title_medium"
|
android:textAppearance="@style/m3_title_medium"
|
||||||
android:textAlignment="viewStart"
|
android:textColor="?colorM3OnSurface"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
tools:text="Eugen" />
|
tools:text="Eugen" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -66,46 +59,22 @@
|
|||||||
android:textAppearance="@style/m3_title_medium"
|
android:textAppearance="@style/m3_title_medium"
|
||||||
android:fontFamily="sans-serif"
|
android:fontFamily="sans-serif"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
|
android:textColor="?colorM3OnSurface"
|
||||||
tools:text="boosted your cat picture" />
|
tools:text="boosted your cat picture" />
|
||||||
|
|
||||||
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>
|
</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_width="match_parent"
|
||||||
android:layout_height="20dp"
|
android:layout_height="20dp"
|
||||||
android:layout_below="@id/name_wrap"
|
android:layout_below="@id/name_wrap"
|
||||||
android:layout_toEndOf="@id/avatar"
|
android:layout_toEndOf="@id/avatar"
|
||||||
android:layout_toStartOf="@id/visibility"
|
android:singleLine="true"
|
||||||
android:layoutDirection="locale"
|
android:ellipsize="end"
|
||||||
android:orientation="horizontal">
|
android:textAppearance="@style/m3_title_small"
|
||||||
|
android:gravity="center_vertical"
|
||||||
<TextView
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:id="@+id/username"
|
tools:text="9h ago · \@Gargron@mastodon.social"/>
|
||||||
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>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="22dp"
|
android:layout_height="22dp"
|
||||||
android:layout_gravity="start|bottom"
|
android:layout_gravity="start|bottom"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="8dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:importantForAccessibility="no"
|
android:importantForAccessibility="no"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@@ -8,20 +9,24 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="20dp"
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="16dp"
|
android:paddingRight="16dp"
|
||||||
android:paddingBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:textAppearance="@style/m3_label_large"
|
android:textAppearance="@style/m3_body_medium"
|
||||||
android:textColor="?android:textColorPrimary" />
|
android:gravity="center_vertical"
|
||||||
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
|
tools:text="fdsafdsafsdafds"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/vote_btn"
|
android:id="@+id/vote_btn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
|
style="@style/Widget.Mastodon.M3.Button.Filled"
|
||||||
android:text="@string/action_vote"/>
|
android:text="@string/action_vote"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -5,53 +5,60 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="16dp"
|
android:paddingRight="16dp"
|
||||||
android:paddingTop="5dp"
|
android:paddingBottom="8dp"
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:clipToPadding="false">
|
android:clipToPadding="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/button"
|
android:id="@+id/button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="40dp"
|
||||||
android:outlineProvider="background"
|
|
||||||
android:elevation="2dp"
|
|
||||||
android:background="@drawable/bg_poll_option_clickable"
|
android:background="@drawable/bg_poll_option_clickable"
|
||||||
android:duplicateParentState="true"
|
android:duplicateParentState="true"
|
||||||
android:layoutDirection="locale">
|
android:layoutDirection="locale">
|
||||||
|
|
||||||
<ImageView
|
<LinearLayout
|
||||||
android:id="@+id/icon"
|
android:layout_width="0dp"
|
||||||
android:layout_width="24dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="24dp"
|
android:layout_weight="1"
|
||||||
android:layout_marginStart="12dp"
|
android:orientation="horizontal">
|
||||||
android:layout_gravity="center_vertical"
|
<TextView
|
||||||
android:duplicateParentState="true"
|
android:id="@+id/text"
|
||||||
android:tint="?colorDarkIcon"
|
android:layout_width="wrap_content"
|
||||||
android:src="@drawable/ic_poll_option_button"/>
|
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
|
<TextView
|
||||||
android:id="@+id/percent"
|
android:id="@+id/percent"
|
||||||
android:layout_width="46dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginStart="16dp"
|
android:textAppearance="@style/m3_label_large"
|
||||||
android:textAppearance="@style/m3_title_medium"
|
android:textColor="?colorM3OnSecondaryContainer"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
android:gravity="end"
|
||||||
tools:visibility="visible"
|
tools:visibility="visible"
|
||||||
tools:text="00.0%"/>
|
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>
|
</LinearLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="-6dp"
|
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="16dp"
|
android:paddingRight="16dp"
|
||||||
android:paddingTop="16dp">
|
android:paddingTop="16dp">
|
||||||
@@ -11,9 +10,10 @@
|
|||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@style/m3_title_small"
|
android:textAppearance="@style/m3_label_large"
|
||||||
android:drawableStart="@drawable/ic_fluent_arrow_repeat_all_20_filled"
|
android:drawableStart="@drawable/ic_repeat_20px"
|
||||||
android:drawableTint="?android:textColorSecondary"
|
android:drawableTint="?colorM3OnSurfaceVariant"
|
||||||
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:drawablePadding="6dp"
|
android:drawablePadding="6dp"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="end"/>
|
android:ellipsize="end"/>
|
||||||
|
|||||||
42
mastodon/src/main/res/layout/display_item_spoiler.xml
Normal file
42
mastodon/src/main/res/layout/display_item_spoiler.xml
Normal file
@@ -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:layout_height="wrap_content"
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingRight="16dp"
|
android:paddingRight="16dp"
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="16dp"
|
||||||
android:paddingBottom="12dp">
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
<org.joinmastodon.android.ui.views.LinkedTextView
|
<org.joinmastodon.android.ui.views.LinkedTextView
|
||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
|
android:textColor="?colorM3OnSurface"
|
||||||
android:textAppearance="@style/m3_body_large"/>
|
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>
|
</FrameLayout>
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="start|bottom"
|
android:layout_gravity="start|bottom"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="8dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:importantForAccessibility="noHideDescendants"
|
android:importantForAccessibility="noHideDescendants"
|
||||||
|
|||||||
@@ -103,9 +103,9 @@
|
|||||||
<item quantity="one">%d day left</item>
|
<item quantity="one">%d day left</item>
|
||||||
<item quantity="other">%d days left</item>
|
<item quantity="other">%d days left</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<plurals name="x_voters">
|
<plurals name="x_votes">
|
||||||
<item quantity="one">%,d voter</item>
|
<item quantity="one">%,d vote</item>
|
||||||
<item quantity="other">%,d voters</item>
|
<item quantity="other">%,d votes</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="poll_closed">Closed</string>
|
<string name="poll_closed">Closed</string>
|
||||||
<string name="confirm_mute_title">Mute Account</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. -->
|
<!-- %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_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="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>
|
</resources>
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
<!-- needed to disable scrim on API 29+ -->
|
<!-- needed to disable scrim on API 29+ -->
|
||||||
<item name="android:enforceNavigationBarContrast" tools:ignore="NewApi">false</item>
|
<item name="android:enforceNavigationBarContrast" tools:ignore="NewApi">false</item>
|
||||||
<item name="android:enforceStatusBarContrast" 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:splitMotionEvents">false</item>
|
||||||
<item name="android:windowBackground">?colorWindowBackground</item>
|
<item name="android:windowBackground">?colorWindowBackground</item>
|
||||||
<item name="android:editTextStyle">@style/Widget.Mastodon.EditText</item>
|
<item name="android:editTextStyle">@style/Widget.Mastodon.EditText</item>
|
||||||
@@ -23,7 +22,6 @@
|
|||||||
<item name="colorBackgroundLight">@color/gray_50</item>
|
<item name="colorBackgroundLight">@color/gray_50</item>
|
||||||
<item name="colorBackgroundLightest">@color/gray_25</item>
|
<item name="colorBackgroundLightest">@color/gray_25</item>
|
||||||
<item name="colorDarkIcon">@color/gray_900</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:statusBarColor">@color/gray_50</item>
|
||||||
<item name="android:navigationBarColor">@color/navigation_bar_bg</item>
|
<item name="android:navigationBarColor">@color/navigation_bar_bg</item>
|
||||||
<item name="android:actionBarTheme">@style/Theme.Mastodon.Toolbar</item>
|
<item name="android:actionBarTheme">@style/Theme.Mastodon.Toolbar</item>
|
||||||
@@ -70,13 +68,14 @@
|
|||||||
<item name="colorM3OnError">#FFF</item>
|
<item name="colorM3OnError">#FFF</item>
|
||||||
<item name="colorM3ErrorContainer">#F9DEDC</item>
|
<item name="colorM3ErrorContainer">#F9DEDC</item>
|
||||||
<item name="colorM3OnErrorContainer">#410E0B</item>
|
<item name="colorM3OnErrorContainer">#410E0B</item>
|
||||||
|
|
||||||
|
<item name="colorWindowBackground">?colorM3Background</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Mastodon.Dark" parent="Theme.AppKit">
|
<style name="Theme.Mastodon.Dark" parent="Theme.AppKit">
|
||||||
<!-- needed to disable scrim on API 29+ -->
|
<!-- needed to disable scrim on API 29+ -->
|
||||||
<item name="android:enforceNavigationBarContrast" tools:ignore="NewApi">false</item>
|
<item name="android:enforceNavigationBarContrast" tools:ignore="NewApi">false</item>
|
||||||
<item name="android:enforceStatusBarContrast" 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:splitMotionEvents">false</item>
|
||||||
<item name="android:windowBackground">?colorWindowBackground</item>
|
<item name="android:windowBackground">?colorWindowBackground</item>
|
||||||
<item name="android:editTextStyle">@style/Widget.Mastodon.EditText</item>
|
<item name="android:editTextStyle">@style/Widget.Mastodon.EditText</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user