Merge upstream redesign (#714)

* merge toolbar fragment

* Fix store screenshot generator

* Fix alert color

* Fix #609

* Fix crash

* bigger hitbox for chips

* support mastodon languages

* merge ui utils

* merge stuff

* fix icon

* ensure 48dp touch target

* init local prefs, add helper function for enum values

* update compose action layout

* merge compose-adj files

* update extended footer

* fix poll wrong option checked

closes sk22#641

* no border when disabled

closes sk22#640

* Fix #610

* Minor fixes

* Fix alert color

* Fix #609

* Fix crash

* Fix #610

* Minor fixes

* add resources

* more compatible mastodon language

* fix html parser

* mark as read on refresh

* update tab bar

* tweak m3 buttons

* update compose-adj files

* tweak and update styles

* m3 expand button

* flag icon should be 18dp, actually

* More minor fixes

closes #612

* More minor fixes

closes #612

* Bump version

* fix no create status event when redrafting

* add material 3 assets

* New translations strings.xml (Greek)

* New translations strings.xml (Greek)

* New translations strings.xml (Italian)

* New translations strings.xml (Greek)

* New translations strings.xml (Italian)

* New translations strings.xml (Thai)

* New translations strings.xml (Thai)

* New translations strings.xml (Italian)

* New translations strings.xml (Thai)

* use new buttons for profile fragment

* merge compose fragment

* merge all the styles! oh dear

* New translations full_description.txt (Indonesian)

* New translations full_description.txt (Chinese Simplified)

* New translations strings.xml (Chinese Simplified)

* New translations full_description.txt (Chinese Simplified)

* Fix #615

* Minor fixes

* Fix #611

* A bunch of crash fixes

* New translations strings.xml (Greek)

* Make the default server configurable

* Pass the system timezone to server when signing up

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Japanese)

* Fix #615

* Minor fixes

* Fix #611

* A bunch of crash fixes

* Make the default server configurable

* Pass the system timezone to server when signing up

* oops. accidentally pasted the commit message in the code

* Remove unused code that caused a crash for some users ¯\_(ツ)_/¯

* New translations strings.xml (Japanese)

* New translations strings.xml (Japanese)

* Remove unused code that caused a crash for some users ¯\_(ツ)_/¯

* New translations strings.xml (Polish)

* New translations strings.xml (Polish)

* New translations strings.xml (Turkish)

* New translations strings.xml (Belarusian)

* prepare merging profile fragment

* merge profile fragment

* New translations strings.xml (Belarusian)

* New translations strings.xml (Greek)

* fix icon padding

* apply post header changes

* minor margin tweaks

* fix footer buttons

* fix header announcement buttons

* New translations strings.xml (Japanese)

* New translations strings.xml (Japanese)

* New translations strings.xml (Japanese)

* New translations strings.xml (Japanese)

* New translations strings.xml (Japanese)

* New translations strings.xml (Japanese)

* New translations full_description.txt (Japanese)

* New translations strings.xml (Icelandic)

* New translations strings.xml (Icelandic)

* New translations strings.xml (Icelandic)

* fix replying

* New translations strings.xml (Icelandic)

* fix translate button

* fix more button visibility

* fix counts label styling

* fix disabled boost button opacity

* fix tab layouts

* fix notification icon color crash

* New translations strings.xml (Greek)

* implement elevation listener in home tab

* fix elevation and listener in home tab

* add elevation scroll listener to notifications

* New translations strings.xml (Scottish Gaelic)

* Add editorconfig

So that PRs like #625 don't happen again

* Crash fix

* 🤔

* New translations strings.xml (Greek)

* New translations strings.xml (Japanese)

* New translations strings.xml (French)

* New translations strings.xml (French)

* New translations strings.xml (French)

* fix notification elevation and integrate divider

* 🤔

* Crash fix

* Add editorconfig

So that PRs like #625 don't happen again

* New translations strings.xml (Turkish)

* save interactions in cache

* New translations strings.xml (Turkish)

* merge new discover/search

* New translations strings.xml (Bengali)

* New translations strings.xml (Scottish Gaelic)

* New translations strings.xml (Bengali)

* merge new settings fragments

* fix no auth callback always being executed

* allow opening server info from profile

closes sk22#593

* fix hide boosts icon color

closes sk22#676

* New translations strings.xml (Turkish)

* New translations strings.xml (Turkish)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (German)

* New translations strings.xml (German)

* New translations strings.xml (Turkish)

* update fedinuke list

from source; doesn't contain any modifications regarding a recent issue

* New translations strings.xml (Turkish)

* remove unused class

* fix crash

* darken m3 outline color a bit

* use m3 outline again

* fix misalignment

closes sk22#682

* New translations strings.xml (Turkish)

* New translations full_description.txt (Turkish)

* New translations short_description.txt (Turkish)

* fix crash

* fix metadata sorting

* show pronouns in header/account lists

* fix broken divider line

closes sk22#679

* trim pronouns

* improve pronoun display

* New translations strings.xml (French)

* New translations strings.xml (Japanese)

* fix broken federated timeline

closes sk22#685

* fix broken -1 fallback behavior

closes sk22#681

* don't display nothing if server about request fails

closes sk22#678

* New translations strings.xml (Ukrainian)

* migrate global prefs to local prefs

* do confirm unfollow by default

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Ukrainian)

* New translations full_description.txt (Ukrainian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Vietnamese)

* New translations full_description.txt (Ukrainian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Ukrainian)

* make sure list in prefs are always mutable and nut null

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Russian)

* fix pronouns edge case

* add back fix for stretched images

closes sk22#636

* fix null pointer on missing default posting language

* fix default posting language not being applied

* bigger username hitbox

closes sk22#688

* fix rtl header username alignment

closes sk22#689

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Ukrainian)

* hopefully fix crashes

closes sk22#692

* New translations strings.xml (Ukrainian)

* New translations full_description.txt (Ukrainian)

* fix pronoun crash

* New translations strings.xml (Persian)

* New translations strings.xml (Ukrainian)

* re-add true black mode

* asterisk can be a pronoun

* New translations strings.xml (Persian)

* true black mode fixes and clean-ups

* material 3 button background for switcher

* darker tab bar selected background

* better align follow/following button widths

* restore rainbow refresh colors

* fix search transition

* fix min width issue with switcher button

* fix no elevation when true black is enabled in light theme

* use statusForContent to determine spoilerRevealed

closes sk22#694

* New translations strings.xml (Persian)

* New translations strings.xml (Persian)

* New translations strings.xml (Persian)

* New translations strings.xml (Persian)

* New translations strings.xml (Persian)

* New translations strings.xml (Persian)

* fix profile tab bar in true black theme

* fix m3 default button style

closes sk22#697

* prettier role badges

closes sk22#663

* fix translate button spacing

closes sk22#655

* use m3 switches in dialogs

closes sk22#653

* implement color palette switcher

* fix color palettes being overwritten

* add display and notification settings

* clean up code

* per-account single notification setting

* add missing items to notification types

* add prefix replies setting

* add show replies/boosts and reply visibility

* add load/see new posts settings

* fix spectator mode missing spoiler padding

* add a bunch of display settings

* update fedinuke

* add content type settings

* add settings for local-onlu

* add missing settings items

* fix visibility button icon tint

* hopefully fix some crashes

* normalize padding above edit text

* apparently, some people don't like pills

closes sk22#706

* fix play button color

closes sk22#705
This commit is contained in:
sk22
2023-07-16 18:01:42 +02:00
committed by GitHub
parent 3cfea0e660
commit 7677ad39ca
744 changed files with 24873 additions and 13485 deletions

View File

@@ -5,7 +5,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.view.View;
@@ -26,15 +26,21 @@ import me.grishka.appkit.views.FragmentRootLinearLayout;
public class ElevationOnScrollListener extends RecyclerView.OnScrollListener implements View.OnScrollChangeListener{
private boolean isAtTop;
private Animator currentPanelsAnim;
private View[] views;
private List<View> views;
private View divider;
private FragmentRootLinearLayout fragmentRootLayout;
private Rect tmpRect=new Rect();
public ElevationOnScrollListener(FragmentRootLinearLayout fragmentRootLayout, View... views){
this(fragmentRootLayout, Arrays.asList(views));
}
public ElevationOnScrollListener(FragmentRootLinearLayout fragmentRootLayout, List<View> views){
isAtTop=true;
this.fragmentRootLayout=fragmentRootLayout;
this.views=views;
for(View v:views){
Drawable bg=v.getBackground().mutate();
Drawable bg=v.getContext().getDrawable(R.drawable.bg_onboarding_panel).mutate();
v.setBackground(bg);
if(bg instanceof LayerDrawable ld){
Drawable overlay=ld.findDrawableByLayerId(R.id.color_overlay);
@@ -45,13 +51,21 @@ public class ElevationOnScrollListener extends RecyclerView.OnScrollListener imp
}
}
public void setDivider(View divider) {
this.divider = divider;
}
public void setViews(View... views){
List<View> oldViews=Arrays.asList(this.views);
setViews(Arrays.asList(views));
}
public void setViews(List<View> views){
List<View> oldViews=this.views;
this.views=views;
for(View v:views){
if(oldViews.contains(v))
continue;
Drawable bg=v.getBackground().mutate();
Drawable bg=v.getContext().getDrawable(R.drawable.bg_onboarding_panel).mutate();
v.setBackground(bg);
if(bg instanceof LayerDrawable ld){
Drawable overlay=ld.findDrawableByLayerId(R.id.color_overlay);
@@ -63,9 +77,14 @@ public class ElevationOnScrollListener extends RecyclerView.OnScrollListener imp
}
}
private int getRecyclerChildDecoratedTop(RecyclerView rv, View child){
rv.getDecoratedBoundsWithMargins(child, tmpRect);
return tmpRect.top;
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){
boolean newAtTop=recyclerView.getChildCount()==0 || (recyclerView.getChildAdapterPosition(recyclerView.getChildAt(0))==0 && recyclerView.getChildAt(0).getTop()==recyclerView.getPaddingTop());
boolean newAtTop=recyclerView.getChildCount()==0 || (recyclerView.getChildAdapterPosition(recyclerView.getChildAt(0))==0 && getRecyclerChildDecoratedTop(recyclerView, recyclerView.getChildAt(0))==recyclerView.getPaddingTop());
handleScroll(recyclerView.getContext(), newAtTop);
}
@@ -74,7 +93,8 @@ public class ElevationOnScrollListener extends RecyclerView.OnScrollListener imp
handleScroll(v.getContext(), scrollY<=0);
}
private void handleScroll(Context context, boolean newAtTop){
public void handleScroll(Context context, boolean newAtTop){
if(UiUtils.isTrueBlackTheme()) newAtTop=true;
if(newAtTop!=isAtTop){
isAtTop=newAtTop;
if(currentPanelsAnim!=null)
@@ -86,20 +106,23 @@ public class ElevationOnScrollListener extends RecyclerView.OnScrollListener imp
if(v.getBackground() instanceof LayerDrawable ld){
Drawable overlay=ld.findDrawableByLayerId(R.id.color_overlay);
if(overlay!=null){
anims.add(ObjectAnimator.ofInt(overlay, "alpha", isAtTop ? 0 : 20));
anims.add(ObjectAnimator.ofInt(overlay, "alpha", newAtTop ? 0 : 20));
}
}
anims.add(ObjectAnimator.ofFloat(v, View.TRANSLATION_Z, isAtTop ? 0 : V.dp(3)));
anims.add(ObjectAnimator.ofFloat(v, View.TRANSLATION_Z, newAtTop ? 0 : V.dp(3)));
}
if(fragmentRootLayout!=null){
int color;
if(isAtTop){
color=UiUtils.getThemeColor(context, R.attr.toolbarBackground);
if(newAtTop){
color=UiUtils.getThemeColor(context, R.attr.colorM3Background);
}else{
color=UiUtils.alphaBlendColors(UiUtils.getThemeColor(context, R.attr.toolbarBackground), UiUtils.getThemeColor(context, R.attr.colorWindowBackground), 0.07843137f);
color=UiUtils.alphaBlendColors(UiUtils.getThemeColor(context, R.attr.colorM3Background), UiUtils.getThemeColor(context, R.attr.colorM3Primary), 0.07843137f);
}
anims.add(ObjectAnimator.ofArgb(fragmentRootLayout, "statusBarColor", color));
}
if(divider!=null){
anims.add(ObjectAnimator.ofFloat(divider, View.ALPHA, newAtTop ? 1 : 0));
}
set.playTogether(anims);
set.setDuration(150);
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
@@ -113,4 +136,8 @@ public class ElevationOnScrollListener extends RecyclerView.OnScrollListener imp
currentPanelsAnim=set;
}
}
public int getCurrentStatusBarColor(){
return fragmentRootLayout.getStatusBarColor();
}
}

View File

@@ -3,12 +3,14 @@ package org.joinmastodon.android.utils;
import static org.joinmastodon.android.api.MastodonAPIController.gson;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.os.LocaleList;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.model.Instance;
import org.parceler.Parcel;
import java.util.ArrayList;
import java.util.Collections;
@@ -16,8 +18,10 @@ import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@Parcel
public class MastodonLanguage {
// On an up-to-date Mastodon instance:
// copy(JSON.stringify(JSON.stringify(JSON.parse(document.getElementById('initial-state').textContent).languages)))
@@ -50,10 +54,12 @@ public class MastodonLanguage {
.collect(Collectors.toList());
}
public final String languageTag, name, englishName;
public final Locale locale;
public String languageTag, name, englishName;
public Locale locale;
private MastodonLanguage(String languageTag, String englishName, String name) {
protected MastodonLanguage() {}
protected MastodonLanguage(String languageTag, String englishName, String name) {
this.locale = new Locale(languageTag);
this.languageTag = languageTag.toLowerCase(Locale.ROOT);
this.name = name;
@@ -69,6 +75,10 @@ public class MastodonLanguage {
public String getLanguage() { return languageTag; }
public String getDisplayName(Context context) {
return context.getString(R.string.sk_language_name, getDefaultName(), getLanguageName());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -91,14 +101,18 @@ public class MastodonLanguage {
.orElse(ENGLISH);
}
public MastodonLanguage from(String language) {
public MastodonLanguage fromOrFallback(String language) {
return from(language).orElse(fallbackLanguage);
}
public Optional<MastodonLanguage> from(String language) {
return allLanguages.stream()
.filter(l->l.locale.equals(new Locale(language))).findAny()
.orElse(fallbackLanguage);
.filter(l->l.locale.equals(new Locale(language)))
.findAny();
}
public MastodonLanguage getDefault() {
return from(Locale.getDefault().getLanguage());
return fromOrFallback(Locale.getDefault().getLanguage());
}
}
}

View File

@@ -0,0 +1,18 @@
package org.joinmastodon.android.utils;
import java.util.Comparator;
public class ObjectIdComparator implements Comparator<String>{
public static final ObjectIdComparator INSTANCE=new ObjectIdComparator();
@Override
public int compare(String o1, String o2){
int l1=o1==null ? 0 : o1.length();
int l2=o2==null ? 0 : o2.length();
if(l1!=l2)
return Integer.compare(l1, l2);
if(l1==0)
return 0;
return o1.compareTo(o2);
}
}

View File

@@ -1,7 +1,9 @@
package org.joinmastodon.android.utils;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.LegacyFilter;
import org.joinmastodon.android.model.FilterAction;
import org.joinmastodon.android.model.FilterContext;
import org.joinmastodon.android.model.Status;
import java.time.Instant;
@@ -12,24 +14,24 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StatusFilterPredicate implements Predicate<Status>{
private final List<Filter> filters;
private final Filter.FilterContext context;
private final Filter.FilterAction action;
private Filter applyingFilter;
private final List<LegacyFilter> filters;
private final FilterContext context;
private final FilterAction action;
private LegacyFilter applyingFilter;
/**
* @param context null makes the predicate pass automatically
* @param action defines what the predicate should check:
* status should not be hidden or should not display with warning
*/
public StatusFilterPredicate(List<Filter> filters, Filter.FilterContext context, Filter.FilterAction action){
public StatusFilterPredicate(List<LegacyFilter> filters, FilterContext context, FilterAction action){
this.filters = filters;
this.context = context;
this.action = action;
}
public StatusFilterPredicate(List<Filter> filters, Filter.FilterContext context){
this(filters, context, Filter.FilterAction.HIDE);
public StatusFilterPredicate(List<LegacyFilter> filters, FilterContext context){
this(filters, context, FilterAction.HIDE);
}
/**
@@ -37,7 +39,7 @@ public class StatusFilterPredicate implements Predicate<Status>{
* @param action defines what the predicate should check:
* status should not be hidden or should not display with warning
*/
public StatusFilterPredicate(String accountID, Filter.FilterContext context, Filter.FilterAction action){
public StatusFilterPredicate(String accountID, FilterContext context, FilterAction action){
filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(context)).collect(Collectors.toList());
this.context = context;
this.action = action;
@@ -46,8 +48,8 @@ public class StatusFilterPredicate implements Predicate<Status>{
/**
* @param context null makes the predicate pass automatically
*/
public StatusFilterPredicate(String accountID, Filter.FilterContext context){
this(accountID, context, Filter.FilterAction.HIDE);
public StatusFilterPredicate(String accountID, FilterContext context){
this(accountID, context, FilterAction.HIDE);
}
/**
@@ -60,26 +62,26 @@ public class StatusFilterPredicate implements Predicate<Status>{
public boolean test(Status status){
if (context == null) return true;
Stream<Filter> matchingFilters = status.filtered != null
Stream<LegacyFilter> matchingFilters = status.filtered != null
// use server-provided per-status info (status.filtered) if available
? status.filtered.stream().map(f -> f.filter)
// or fall back to cached filters
: filters.stream().filter(filter -> filter.matches(status));
Optional<Filter> applyingFilter = matchingFilters
Optional<LegacyFilter> applyingFilter = matchingFilters
// discard expired filters
.filter(filter -> filter.expiresAt == null || filter.expiresAt.isAfter(Instant.now()))
// only apply filters for given context
.filter(filter -> filter.context.contains(context))
// treating filterAction = null (from filters list) as FilterAction.HIDE
.filter(filter -> filter.filterAction == null ? action == Filter.FilterAction.HIDE : filter.filterAction == action)
.filter(filter -> filter.filterAction == null ? action == FilterAction.HIDE : filter.filterAction == action)
.findAny();
this.applyingFilter = applyingFilter.orElse(null);
return applyingFilter.isEmpty();
}
public Filter getApplyingFilter() {
public LegacyFilter getApplyingFilter() {
return applyingFilter;
}
}

View File

@@ -0,0 +1,31 @@
package org.joinmastodon.android.utils;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.ViewImageLoader;
public class ViewImageLoaderHolderTarget implements ViewImageLoader.Target{
private final ImageLoaderViewHolder holder;
private final int imageIndex;
public ViewImageLoaderHolderTarget(ImageLoaderViewHolder holder, int imageIndex){
this.holder=holder;
this.imageIndex=imageIndex;
}
@Override
public void setImageDrawable(Drawable d){
if(d==null)
holder.clearImage(imageIndex);
else
holder.setImage(imageIndex, d);
}
@Override
public View getView(){
return ((RecyclerView.ViewHolder)holder).itemView;
}
}