Merge remote-tracking branch 'megalodon_main/main'
# Conflicts: # mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java # mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsDisplayFragment.java
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package org.joinmastodon.android;
|
package org.joinmastodon.android;
|
||||||
|
|
||||||
import static org.joinmastodon.android.api.MastodonAPIController.gson;
|
import static org.joinmastodon.android.api.MastodonAPIController.gson;
|
||||||
|
import static org.joinmastodon.android.api.session.AccountLocalPreferences.ColorPreference.MATERIAL3;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@@ -13,6 +14,7 @@ import com.google.gson.JsonSyntaxException;
|
|||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
import org.joinmastodon.android.api.session.AccountLocalPreferences;
|
import org.joinmastodon.android.api.session.AccountLocalPreferences;
|
||||||
|
import org.joinmastodon.android.api.session.AccountLocalPreferences.ColorPreference;
|
||||||
import org.joinmastodon.android.api.session.AccountSession;
|
import org.joinmastodon.android.api.session.AccountSession;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.model.ContentType;
|
import org.joinmastodon.android.model.ContentType;
|
||||||
@@ -62,6 +64,7 @@ public class GlobalUserPreferences{
|
|||||||
public static boolean overlayMedia;
|
public static boolean overlayMedia;
|
||||||
public static boolean showSuicideHelp;
|
public static boolean showSuicideHelp;
|
||||||
public static boolean underlinedLinks;
|
public static boolean underlinedLinks;
|
||||||
|
public static ColorPreference color;
|
||||||
|
|
||||||
// MOSHIDON
|
// MOSHIDON
|
||||||
public static boolean showDividers;
|
public static boolean showDividers;
|
||||||
@@ -138,6 +141,7 @@ public class GlobalUserPreferences{
|
|||||||
overlayMedia=prefs.getBoolean("overlayMedia", false);
|
overlayMedia=prefs.getBoolean("overlayMedia", false);
|
||||||
showSuicideHelp=prefs.getBoolean("showSuicideHelp", true);
|
showSuicideHelp=prefs.getBoolean("showSuicideHelp", true);
|
||||||
underlinedLinks=prefs.getBoolean("underlinedLinks", true);
|
underlinedLinks=prefs.getBoolean("underlinedLinks", true);
|
||||||
|
color=ColorPreference.valueOf(prefs.getString("color", MATERIAL3.name()));
|
||||||
|
|
||||||
// MOSHIDON
|
// MOSHIDON
|
||||||
uniformNotificationIcon=prefs.getBoolean("uniformNotificationIcon", false);
|
uniformNotificationIcon=prefs.getBoolean("uniformNotificationIcon", false);
|
||||||
@@ -171,8 +175,6 @@ public class GlobalUserPreferences{
|
|||||||
int migrationLevel=prefs.getInt("migrationLevel", BuildConfig.VERSION_CODE);
|
int migrationLevel=prefs.getInt("migrationLevel", BuildConfig.VERSION_CODE);
|
||||||
if(migrationLevel < 61)
|
if(migrationLevel < 61)
|
||||||
migrateToUpstreamVersion61();
|
migrateToUpstreamVersion61();
|
||||||
if(migrationLevel < 102)
|
|
||||||
migrateToVersion102();
|
|
||||||
if(migrationLevel < BuildConfig.VERSION_CODE)
|
if(migrationLevel < BuildConfig.VERSION_CODE)
|
||||||
prefs.edit().putInt("migrationLevel", BuildConfig.VERSION_CODE).apply();
|
prefs.edit().putInt("migrationLevel", BuildConfig.VERSION_CODE).apply();
|
||||||
}
|
}
|
||||||
@@ -216,6 +218,7 @@ public class GlobalUserPreferences{
|
|||||||
.putBoolean("overlayMedia", overlayMedia)
|
.putBoolean("overlayMedia", overlayMedia)
|
||||||
.putBoolean("showSuicideHelp", showSuicideHelp)
|
.putBoolean("showSuicideHelp", showSuicideHelp)
|
||||||
.putBoolean("underlinedLinks", underlinedLinks)
|
.putBoolean("underlinedLinks", underlinedLinks)
|
||||||
|
.putString("color", color.name())
|
||||||
|
|
||||||
// MOSHIDON
|
// MOSHIDON
|
||||||
.putBoolean("defaultToUnlistedReplies", defaultToUnlistedReplies)
|
.putBoolean("defaultToUnlistedReplies", defaultToUnlistedReplies)
|
||||||
@@ -258,25 +261,6 @@ public class GlobalUserPreferences{
|
|||||||
|
|
||||||
//region preferences migrations
|
//region preferences migrations
|
||||||
|
|
||||||
private static void migrateToVersion102(){
|
|
||||||
Log.d(TAG, "Migrating preferences to version 102!! (copy current theme to local preferences)");
|
|
||||||
|
|
||||||
SharedPreferences prefs=getPrefs();
|
|
||||||
// only migrate if global prefs even contains a color (but like.. it should)
|
|
||||||
if(prefs.contains("color")){
|
|
||||||
AccountSessionManager asm=AccountSessionManager.getInstance();
|
|
||||||
for(AccountSession session : asm.getLoggedInAccounts()){
|
|
||||||
if(session.getRawLocalPreferences().contains("color")) continue;
|
|
||||||
AccountLocalPreferences localPrefs=session.getLocalPreferences();
|
|
||||||
localPrefs.color=AccountLocalPreferences.ColorPreference.valueOf(prefs.getString(
|
|
||||||
"color", AccountLocalPreferences.ColorPreference.MATERIAL3.name()
|
|
||||||
));
|
|
||||||
localPrefs.save();
|
|
||||||
}
|
|
||||||
prefs.edit().remove("color").apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void migrateToUpstreamVersion61(){
|
private static void migrateToUpstreamVersion61(){
|
||||||
Log.d(TAG, "Migrating preferences to upstream version 61!!");
|
Log.d(TAG, "Migrating preferences to upstream version 61!!");
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
@@ -69,7 +70,7 @@ public class CacheController{
|
|||||||
Status status=MastodonAPIController.gson.fromJson(cursor.getString(0), Status.class);
|
Status status=MastodonAPIController.gson.fromJson(cursor.getString(0), Status.class);
|
||||||
status.postprocess();
|
status.postprocess();
|
||||||
int flags=cursor.getInt(1);
|
int flags=cursor.getInt(1);
|
||||||
status.hasGapAfter=((flags & POST_FLAG_GAP_AFTER)!=0);
|
status.hasGapAfter=((flags & POST_FLAG_GAP_AFTER)!=0) ? status.id : null;
|
||||||
newMaxID=status.id;
|
newMaxID=status.id;
|
||||||
result.add(status);
|
result.add(status);
|
||||||
}while(cursor.moveToNext());
|
}while(cursor.moveToNext());
|
||||||
@@ -113,7 +114,7 @@ public class CacheController{
|
|||||||
values.put("id", s.id);
|
values.put("id", s.id);
|
||||||
values.put("json", MastodonAPIController.gson.toJson(s));
|
values.put("json", MastodonAPIController.gson.toJson(s));
|
||||||
int flags=0;
|
int flags=0;
|
||||||
if(s.hasGapAfter)
|
if(Objects.equals(s.hasGapAfter, s.id))
|
||||||
flags|=POST_FLAG_GAP_AFTER;
|
flags|=POST_FLAG_GAP_AFTER;
|
||||||
values.put("flags", flags);
|
values.put("flags", flags);
|
||||||
values.put("time", s.createdAt.getEpochSecond());
|
values.put("time", s.createdAt.getEpochSecond());
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import androidx.annotation.StringRes;
|
|||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.model.ContentType;
|
import org.joinmastodon.android.model.ContentType;
|
||||||
import org.joinmastodon.android.model.Emoji;
|
import org.joinmastodon.android.model.Emoji;
|
||||||
@@ -84,7 +85,7 @@ public class AccountLocalPreferences{
|
|||||||
keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false);
|
keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false);
|
||||||
emojiReactionsEnabled=prefs.getBoolean("emojiReactionsEnabled", session.getInstance().isPresent() && session.getInstance().get().isAkkoma());
|
emojiReactionsEnabled=prefs.getBoolean("emojiReactionsEnabled", session.getInstance().isPresent() && session.getInstance().get().isAkkoma());
|
||||||
showEmojiReactions=ShowEmojiReactions.valueOf(prefs.getString("showEmojiReactions", ShowEmojiReactions.HIDE_EMPTY.name()));
|
showEmojiReactions=ShowEmojiReactions.valueOf(prefs.getString("showEmojiReactions", ShowEmojiReactions.HIDE_EMPTY.name()));
|
||||||
color=ColorPreference.valueOf(prefs.getString("color", ColorPreference.MATERIAL3.name()));
|
color=prefs.contains("color") ? ColorPreference.valueOf(prefs.getString("color", null)) : null;
|
||||||
likeIcon=prefs.getBoolean("likeIcon", false);
|
likeIcon=prefs.getBoolean("likeIcon", false);
|
||||||
recentCustomEmoji=fromJson(prefs.getString("recentCustomEmoji", null), recentCustomEmojiType, new ArrayList<>());
|
recentCustomEmoji=fromJson(prefs.getString("recentCustomEmoji", null), recentCustomEmojiType, new ArrayList<>());
|
||||||
|
|
||||||
@@ -101,6 +102,10 @@ public class AccountLocalPreferences{
|
|||||||
prefs.edit().putLong("notificationsPauseTime", time).apply();
|
prefs.edit().putLong("notificationsPauseTime", time).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ColorPreference getCurrentColor(){
|
||||||
|
return color!=null ? color : GlobalUserPreferences.color!=null ? GlobalUserPreferences.color : ColorPreference.MATERIAL3;
|
||||||
|
}
|
||||||
|
|
||||||
public void save(){
|
public void save(){
|
||||||
prefs.edit()
|
prefs.edit()
|
||||||
.putBoolean("interactionCounts", showInteractionCounts)
|
.putBoolean("interactionCounts", showInteractionCounts)
|
||||||
@@ -124,7 +129,7 @@ public class AccountLocalPreferences{
|
|||||||
.putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification)
|
.putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification)
|
||||||
.putBoolean("emojiReactionsEnabled", emojiReactionsEnabled)
|
.putBoolean("emojiReactionsEnabled", emojiReactionsEnabled)
|
||||||
.putString("showEmojiReactions", showEmojiReactions.name())
|
.putString("showEmojiReactions", showEmojiReactions.name())
|
||||||
.putString("color", color.name())
|
.putString("color", color!=null ? color.name() : null)
|
||||||
.putBoolean("likeIcon", likeIcon)
|
.putBoolean("likeIcon", likeIcon)
|
||||||
.putString("recentCustomEmoji", gson.toJson(recentCustomEmoji))
|
.putString("recentCustomEmoji", gson.toJson(recentCustomEmoji))
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ public class AccountSession{
|
|||||||
if(s!=null && s.filtered!=null){
|
if(s!=null && s.filtered!=null){
|
||||||
localPreferences.serverSideFiltersSupported=true;
|
localPreferences.serverSideFiltersSupported=true;
|
||||||
localPreferences.save();
|
localPreferences.save();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,9 +280,17 @@ public class AccountSession{
|
|||||||
if(filterStatusContainingObject(o, extractor, context, profile)){
|
if(filterStatusContainingObject(o, extractor, context, profile)){
|
||||||
Status s=extractor.apply(o);
|
Status s=extractor.apply(o);
|
||||||
removeUs.add(o);
|
removeUs.add(o);
|
||||||
if(s!=null && s.hasGapAfter && i > 0){
|
if(s!=null && s.hasGapAfter!=null && i>0){
|
||||||
Status prev=extractor.apply(objects.get(i - 1));
|
// oops, we're about to remove an item that has a gap after...
|
||||||
if(prev!=null) prev.hasGapAfter=true;
|
// gotta find the previous status that's not also about to be removed
|
||||||
|
for(int j=i-1; j>=0; j--){
|
||||||
|
T p=objects.get(j);
|
||||||
|
Status prev=extractor.apply(objects.get(j));
|
||||||
|
if(prev!=null && !removeUs.contains(p)){
|
||||||
|
prev.hasGapAfter=s.hasGapAfter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ import org.joinmastodon.android.model.Translation;
|
|||||||
import org.joinmastodon.android.ui.BetterItemAnimator;
|
import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.EmojiReactionsStatusDisplayItem;
|
|
||||||
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
|
||||||
@@ -641,21 +640,21 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
|
|
||||||
public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder) {
|
public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder) {
|
||||||
Status status = holder.getItem().status;
|
Status status = holder.getItem().status;
|
||||||
MediaGridStatusDisplayItem.Holder mediaGrid = findHolderOfType(holder.getItemID(), MediaGridStatusDisplayItem.Holder.class);
|
|
||||||
if (mediaGrid != null) {
|
|
||||||
if (!status.sensitiveRevealed) mediaGrid.revealSensitive();
|
|
||||||
else mediaGrid.hideSensitive();
|
|
||||||
} else {
|
|
||||||
// media grid's methods normally change the status' state - we still want to be able
|
|
||||||
// to do this if the media grid is not bound, tho - so, doing it ourselves here
|
|
||||||
status.sensitiveRevealed = !status.sensitiveRevealed;
|
|
||||||
}
|
|
||||||
if(holder.getItem().hasVisibilityToggle) holder.animateVisibilityToggle(false);
|
if(holder.getItem().hasVisibilityToggle) holder.animateVisibilityToggle(false);
|
||||||
|
MediaGridStatusDisplayItem.Holder mediaGrid=findHolderOfType(holder.getItemID(), MediaGridStatusDisplayItem.Holder.class);
|
||||||
|
if(mediaGrid!=null){
|
||||||
|
if(!status.sensitiveRevealed) mediaGrid.revealSensitive();
|
||||||
|
else mediaGrid.hideSensitive();
|
||||||
|
}else{
|
||||||
|
status.sensitiveRevealed=false;
|
||||||
|
notifyItemChangedAfter(holder.getItem(), MediaGridStatusDisplayItem.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSensitiveRevealed(MediaGridStatusDisplayItem.Holder holder) {
|
public void onSensitiveRevealed(MediaGridStatusDisplayItem.Holder holder) {
|
||||||
HeaderStatusDisplayItem.Holder header = findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class);
|
HeaderStatusDisplayItem.Holder header=findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class);
|
||||||
if(header != null && header.getItem().hasVisibilityToggle) header.animateVisibilityToggle(true);
|
if(header!=null && header.getItem().hasVisibilityToggle) header.animateVisibilityToggle(true);
|
||||||
|
else notifyItemChangedBefore(holder.getItem(), HeaderStatusDisplayItem.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void toggleSpoiler(Status status, String itemID){
|
protected void toggleSpoiler(Status status, String itemID){
|
||||||
@@ -664,8 +663,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
status.sensitiveRevealed = false;
|
status.sensitiveRevealed = false;
|
||||||
|
|
||||||
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
|
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
|
||||||
if(spoiler!=null)
|
if(spoiler!=null) spoiler.rebind();
|
||||||
spoiler.rebind();
|
else notifyItemChanged(itemID, SpoilerStatusDisplayItem.class);
|
||||||
SpoilerStatusDisplayItem spoilerItem=Objects.requireNonNull(findItemOfType(itemID, SpoilerStatusDisplayItem.class));
|
SpoilerStatusDisplayItem spoilerItem=Objects.requireNonNull(findItemOfType(itemID, SpoilerStatusDisplayItem.class));
|
||||||
|
|
||||||
int index=displayItems.indexOf(spoilerItem);
|
int index=displayItems.indexOf(spoilerItem);
|
||||||
@@ -677,30 +676,29 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
adapter.notifyItemRangeRemoved(index+1, spoilerItem.contentItems.size());
|
adapter.notifyItemRangeRemoved(index+1, spoilerItem.contentItems.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
notifyItemChanged(itemID, TextStatusDisplayItem.class);
|
||||||
if(text!=null)
|
|
||||||
adapter.notifyItemChanged(text.getAbsoluteAdapterPosition()-getMainAdapterOffset());
|
|
||||||
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
|
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
|
||||||
if(header!=null)
|
if(header!=null) header.rebind();
|
||||||
header.rebind();
|
else notifyItemChanged(itemID, HeaderStatusDisplayItem.class);
|
||||||
|
|
||||||
list.invalidateItemDecorations();
|
list.invalidateItemDecorations();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onEnableExpandable(TextStatusDisplayItem.Holder holder, boolean expandable) {
|
public void onEnableExpandable(TextStatusDisplayItem.Holder holder, boolean expandable) {
|
||||||
if (holder.getItem().status.textExpandable != expandable && list != null) {
|
Status s=holder.getItem().status;
|
||||||
holder.getItem().status.textExpandable = expandable;
|
if(s.textExpandable!=expandable && list!=null) {
|
||||||
HeaderStatusDisplayItem.Holder header = findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class);
|
s.textExpandable=expandable;
|
||||||
if (header != null) header.rebind();
|
HeaderStatusDisplayItem.Holder header=findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class);
|
||||||
|
if(header!=null) header.bindCollapseButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onToggleExpanded(Status status, String itemID) {
|
public void onToggleExpanded(Status status, String itemID) {
|
||||||
status.textExpanded = !status.textExpanded;
|
status.textExpanded = !status.textExpanded;
|
||||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
notifyItemChanged(itemID, TextStatusDisplayItem.class);
|
||||||
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
|
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
|
||||||
if (text != null) text.rebind();
|
if(header!=null) header.animateExpandToggle();
|
||||||
if (header != null) header.rebind();
|
else notifyItemChanged(itemID, HeaderStatusDisplayItem.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onGapClick(GapStatusDisplayItem.Holder item, boolean downwards){}
|
public void onGapClick(GapStatusDisplayItem.Holder item, boolean downwards){}
|
||||||
@@ -759,9 +757,61 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this as a fallback if findHolderOfType fails to find the ViewHolder.
|
||||||
|
* It might still be bound but off-screen and therefore not a child of the RecyclerView -
|
||||||
|
* resulting in the ViewHolder displaying an outdated state once scrolled back into view.
|
||||||
|
*/
|
||||||
|
protected <I extends StatusDisplayItem> int notifyItemChanged(String id, Class<I> type){
|
||||||
|
boolean encounteredParent=false;
|
||||||
|
for(int i=0; i<displayItems.size(); i++){
|
||||||
|
StatusDisplayItem item=displayItems.get(i);
|
||||||
|
boolean idEquals=id.equals(item.parentID);
|
||||||
|
if(!encounteredParent && idEquals) encounteredParent=true; // reached top of the parent
|
||||||
|
else if(encounteredParent && !idEquals) break; // passed by bottom of the parent. man muss ja wissen wann schluss is
|
||||||
|
if(idEquals && type.isInstance(item)){
|
||||||
|
adapter.notifyItemChanged(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <I extends StatusDisplayItem> int notifyItemChangedAfter(StatusDisplayItem afterThis, Class<I> type){
|
||||||
|
int startIndex=displayItems.indexOf(afterThis);
|
||||||
|
if(startIndex == -1) throw new IllegalStateException("notifyItemChangedAfter didn't find the passed StatusDisplayItem");
|
||||||
|
String parentID=afterThis.parentID;
|
||||||
|
for(int i=startIndex; i<displayItems.size(); i++){
|
||||||
|
StatusDisplayItem item=displayItems.get(i);
|
||||||
|
if(!parentID.equals(item.parentID)) break; // didn't find anything
|
||||||
|
if(type.isInstance(item)){
|
||||||
|
// found it
|
||||||
|
adapter.notifyItemChanged(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <I extends StatusDisplayItem> int notifyItemChangedBefore(StatusDisplayItem beforeThis, Class<I> type){
|
||||||
|
int startIndex=displayItems.indexOf(beforeThis);
|
||||||
|
if(startIndex == -1) throw new IllegalStateException("notifyItemChangedBefore didn't find the passed StatusDisplayItem");
|
||||||
|
String parentID=beforeThis.parentID;
|
||||||
|
for(int i=startIndex; i>=0; i--){
|
||||||
|
StatusDisplayItem item=displayItems.get(i);
|
||||||
|
if(!parentID.equals(item.parentID)) break; // didn't find anything
|
||||||
|
if(type.isInstance(item)){
|
||||||
|
// found it
|
||||||
|
adapter.notifyItemChanged(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected <I extends StatusDisplayItem, H extends StatusDisplayItem.Holder<I>> H findHolderOfType(String id, Class<H> type){
|
protected <I extends StatusDisplayItem, H extends StatusDisplayItem.Holder<I>> H findHolderOfType(String id, Class<H> type){
|
||||||
for(int i=0;i<list.getChildCount();i++){
|
for(int i=0; i<list.getChildCount(); i++){
|
||||||
RecyclerView.ViewHolder holder=list.getChildViewHolder(list.getChildAt(i));
|
RecyclerView.ViewHolder holder=list.getChildViewHolder(list.getChildAt(i));
|
||||||
if(holder instanceof StatusDisplayItem.Holder<?> itemHolder && itemHolder.getItemID().equals(id) && type.isInstance(holder))
|
if(holder instanceof StatusDisplayItem.Holder<?> itemHolder && itemHolder.getItemID().equals(id) && type.isInstance(holder))
|
||||||
return type.cast(holder);
|
return type.cast(holder);
|
||||||
@@ -891,6 +941,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
if(text!=null){
|
if(text!=null){
|
||||||
text.updateTranslation(true);
|
text.updateTranslation(true);
|
||||||
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
||||||
|
}else{
|
||||||
|
notifyItemChanged(itemID, TextStatusDisplayItem.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,6 +954,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
||||||
if(text!=null){
|
if(text!=null){
|
||||||
text.updateTranslation(true);
|
text.updateTranslation(true);
|
||||||
|
}else{
|
||||||
|
notifyItemChanged(itemID, TextStatusDisplayItem.class);
|
||||||
}
|
}
|
||||||
new M3AlertDialogBuilder(getActivity())
|
new M3AlertDialogBuilder(getActivity())
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
@@ -918,6 +972,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
if(text!=null){
|
if(text!=null){
|
||||||
text.updateTranslation(true);
|
text.updateTranslation(true);
|
||||||
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
||||||
|
}else{
|
||||||
|
notifyItemChanged(itemID, TextStatusDisplayItem.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ public class ComposeImageDescriptionFragment extends MastodonToolbarFragment imp
|
|||||||
accountID=getArguments().getString("account");
|
accountID=getArguments().getString("account");
|
||||||
attachmentID=getArguments().getString("attachment");
|
attachmentID=getArguments().getString("attachment");
|
||||||
themeWrapper=new ContextThemeWrapper(activity, R.style.Theme_Mastodon_Dark);
|
themeWrapper=new ContextThemeWrapper(activity, R.style.Theme_Mastodon_Dark);
|
||||||
ColorPalette.palettes.get(AccountSessionManager.get(accountID).getLocalPreferences().color).apply(themeWrapper, GlobalUserPreferences.ThemePreference.DARK);
|
ColorPalette.palettes.get(AccountSessionManager.get(accountID).getLocalPreferences().getCurrentColor())
|
||||||
|
.apply(themeWrapper, GlobalUserPreferences.ThemePreference.DARK);
|
||||||
setTitle(R.string.add_alt_text);
|
setTitle(R.string.add_alt_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public class HomeTimelineFragment extends StatusListFragment {
|
|||||||
if(!data.isEmpty() && last.id.equals(data.get(0).id)){ // This part intersects with the existing one
|
if(!data.isEmpty() && last.id.equals(data.get(0).id)){ // This part intersects with the existing one
|
||||||
toAdd=new ArrayList<>(result.subList(0, result.size()-1)); // Remove the already known last post
|
toAdd=new ArrayList<>(result.subList(0, result.size()-1)); // Remove the already known last post
|
||||||
}else{
|
}else{
|
||||||
result.get(result.size()-1).hasGapAfter=true;
|
last.hasGapAfter=last.id;
|
||||||
toAdd=result;
|
toAdd=result;
|
||||||
}
|
}
|
||||||
List<String> existingIds=data.stream().map(Status::getID).collect(Collectors.toList());
|
List<String> existingIds=data.stream().map(Status::getID).collect(Collectors.toList());
|
||||||
@@ -176,10 +176,10 @@ public class HomeTimelineFragment extends StatusListFragment {
|
|||||||
gap.loading=true;
|
gap.loading=true;
|
||||||
dataLoading=true;
|
dataLoading=true;
|
||||||
|
|
||||||
String maxID = null;
|
String maxID=null;
|
||||||
String minID = null;
|
String minID=null;
|
||||||
if (downwards) {
|
if (downwards) {
|
||||||
maxID = item.getItemID();
|
maxID=item.getItem().getMaxID();
|
||||||
} else {
|
} else {
|
||||||
int gapPos=displayItems.indexOf(gap);
|
int gapPos=displayItems.indexOf(gap);
|
||||||
StatusDisplayItem nextItem=displayItems.get(gapPos + 1);
|
StatusDisplayItem nextItem=displayItems.get(gapPos + 1);
|
||||||
@@ -196,12 +196,13 @@ public class HomeTimelineFragment extends StatusListFragment {
|
|||||||
int gapPos=displayItems.indexOf(gap);
|
int gapPos=displayItems.indexOf(gap);
|
||||||
if(gapPos==-1)
|
if(gapPos==-1)
|
||||||
return;
|
return;
|
||||||
|
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext());
|
||||||
if(result.isEmpty()){
|
if(result.isEmpty()){
|
||||||
displayItems.remove(gapPos);
|
displayItems.remove(gapPos);
|
||||||
adapter.notifyItemRemoved(getMainAdapterOffset()+gapPos);
|
adapter.notifyItemRemoved(getMainAdapterOffset()+gapPos);
|
||||||
Status gapStatus=getStatusByID(gap.parentID);
|
Status gapStatus=getStatusByID(gap.parentID);
|
||||||
if(gapStatus!=null){
|
if(gapStatus!=null){
|
||||||
gapStatus.hasGapAfter=false;
|
gapStatus.hasGapAfter=null;
|
||||||
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus), false);
|
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus), false);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -214,7 +215,7 @@ public class HomeTimelineFragment extends StatusListFragment {
|
|||||||
idsBelowGap.add(s.id);
|
idsBelowGap.add(s.id);
|
||||||
}else if(s.id.equals(gap.parentID)){
|
}else if(s.id.equals(gap.parentID)){
|
||||||
belowGap=true;
|
belowGap=true;
|
||||||
s.hasGapAfter=false;
|
s.hasGapAfter=null;
|
||||||
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(s), false);
|
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(s), false);
|
||||||
}else{
|
}else{
|
||||||
gapPostIndex++;
|
gapPostIndex++;
|
||||||
@@ -227,7 +228,8 @@ public class HomeTimelineFragment extends StatusListFragment {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(endIndex==result.size()){
|
if(endIndex==result.size()){
|
||||||
result.get(result.size()-1).hasGapAfter=true;
|
Status last=result.get(result.size()-1);
|
||||||
|
last.hasGapAfter=last.id;
|
||||||
}else{
|
}else{
|
||||||
result=result.subList(0, endIndex);
|
result=result.subList(0, endIndex);
|
||||||
}
|
}
|
||||||
@@ -272,7 +274,7 @@ public class HomeTimelineFragment extends StatusListFragment {
|
|||||||
.filter(s->Objects.equals(s.id, gap.parentID))
|
.filter(s->Objects.equals(s.id, gap.parentID))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
if (gapStatus.isPresent()) {
|
if (gapStatus.isPresent()) {
|
||||||
gapStatus.get().hasGapAfter=false;
|
gapStatus.get().hasGapAfter=null;
|
||||||
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus.get()), false);
|
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus.get()), false);
|
||||||
}
|
}
|
||||||
targetList.clear();
|
targetList.clear();
|
||||||
|
|||||||
@@ -104,8 +104,8 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
|
|||||||
else
|
else
|
||||||
selectedIDs.add(id);
|
selectedIDs.add(id);
|
||||||
CheckableHeaderStatusDisplayItem.Holder holder=findHolderOfType(id, CheckableHeaderStatusDisplayItem.Holder.class);
|
CheckableHeaderStatusDisplayItem.Holder holder=findHolderOfType(id, CheckableHeaderStatusDisplayItem.Holder.class);
|
||||||
if(holder!=null)
|
if(holder!=null) holder.rebind();
|
||||||
holder.rebind();
|
else notifyItemChanged(id, CheckableHeaderStatusDisplayItem.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.joinmastodon.android.fragments.settings;
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -29,6 +30,8 @@ import org.joinmastodon.android.ui.views.TextInputFrameLayout;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
import me.grishka.appkit.FragmentStackActivity;
|
import me.grishka.appkit.FragmentStackActivity;
|
||||||
@@ -152,19 +155,11 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private @StringRes int getColorPaletteValue(){
|
private String getColorPaletteValue(){
|
||||||
return switch(AccountSessionManager.get(accountID).getLocalPreferences().color){
|
ColorPreference color=AccountSessionManager.get(accountID).getLocalPreferences().color;
|
||||||
case MATERIAL3 -> R.string.sk_color_palette_material3;
|
return color==null
|
||||||
case PINK -> R.string.sk_color_palette_pink;
|
? getString(R.string.sk_settings_color_palette_default, getString(GlobalUserPreferences.color.getName()))
|
||||||
case PURPLE -> R.string.sk_color_palette_purple;
|
: getString(color.getName());
|
||||||
case GREEN -> R.string.sk_color_palette_green;
|
|
||||||
case BLUE -> R.string.sk_color_palette_blue;
|
|
||||||
case BROWN -> R.string.sk_color_palette_brown;
|
|
||||||
case RED -> R.string.sk_color_palette_red;
|
|
||||||
case YELLOW -> R.string.sk_color_palette_yellow;
|
|
||||||
case NORD -> R.string.mo_color_palette_nord;
|
|
||||||
case WHITE -> R.string.mo_color_palette_black_and_white;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPublishButtonText() {
|
private String getPublishButtonText() {
|
||||||
@@ -220,26 +215,40 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onColorClick(){
|
private void onColorClick(){
|
||||||
int selected=lp.color.ordinal();
|
boolean multiple=AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1;
|
||||||
|
int indexOffset=multiple ? 1 : 0;
|
||||||
|
int selected=lp.color==null ? 0 : lp.color.ordinal() + indexOffset;
|
||||||
int[] newSelected={selected};
|
int[] newSelected={selected};
|
||||||
String[] names=Arrays.stream(ColorPreference.values()).map(ColorPreference::getName).map(this::getString).toArray(String[]::new);
|
List<String> items=Arrays.stream(ColorPreference.values()).map(ColorPreference::getName).map(this::getString).collect(Collectors.toList());
|
||||||
new M3AlertDialogBuilder(getActivity())
|
if(multiple)
|
||||||
|
items.add(0, getString(R.string.sk_settings_color_palette_default, items.get(GlobalUserPreferences.color.ordinal())));
|
||||||
|
|
||||||
|
Consumer<Boolean> save=(asDefault)->{
|
||||||
|
boolean defaultSelected=multiple && newSelected[0]==0;
|
||||||
|
ColorPreference pref=defaultSelected ? null : ColorPreference.values()[newSelected[0]-indexOffset];
|
||||||
|
if(pref!=lp.color){
|
||||||
|
ColorPreference prev=lp.color;
|
||||||
|
lp.color=asDefault ? null : pref;
|
||||||
|
lp.save();
|
||||||
|
if((asDefault || !multiple) && pref!=null){
|
||||||
|
GlobalUserPreferences.color=pref;
|
||||||
|
GlobalUserPreferences.save();
|
||||||
|
}
|
||||||
|
colorItem.subtitle=getColorPaletteValue();
|
||||||
|
rebindItem(colorItem);
|
||||||
|
if(prev==null && pref!=null) restartActivityToApplyNewTheme();
|
||||||
|
else maybeApplyNewThemeRightNow(null, prev, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AlertDialog.Builder alert=new M3AlertDialogBuilder(getActivity())
|
||||||
.setTitle(R.string.sk_settings_color_palette)
|
.setTitle(R.string.sk_settings_color_palette)
|
||||||
.setSingleChoiceItems(names,
|
.setSingleChoiceItems(items.toArray(String[]::new),
|
||||||
selected, (dlg, item)->newSelected[0]=item)
|
selected, (dlg, item)->newSelected[0]=item)
|
||||||
.setPositiveButton(R.string.ok, (dlg, item)->{
|
.setPositiveButton(R.string.ok, (dlg, item)->save.accept(false))
|
||||||
ColorPreference pref=ColorPreference.values()[newSelected[0]];
|
.setNegativeButton(R.string.cancel, null);
|
||||||
if(pref!=lp.color){
|
if(multiple) alert.setNeutralButton(R.string.sk_set_as_default, (dlg, item)->save.accept(true));
|
||||||
ColorPreference prev=lp.color;
|
alert.show();
|
||||||
lp.color=pref;
|
|
||||||
GlobalUserPreferences.save();
|
|
||||||
colorItem.subtitleRes=getColorPaletteValue();
|
|
||||||
rebindItem(colorItem);
|
|
||||||
maybeApplyNewThemeRightNow(null, prev, null);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPublishTextClick(){
|
private void onPublishTextClick(){
|
||||||
@@ -284,14 +293,14 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
|
|||||||
private void maybeApplyNewThemeRightNow(GlobalUserPreferences.ThemePreference prevTheme, ColorPreference prevColor, Boolean prevTrueBlack){
|
private void maybeApplyNewThemeRightNow(GlobalUserPreferences.ThemePreference prevTheme, ColorPreference prevColor, Boolean prevTrueBlack){
|
||||||
if(prevTheme==null) prevTheme=GlobalUserPreferences.theme;
|
if(prevTheme==null) prevTheme=GlobalUserPreferences.theme;
|
||||||
if(prevTrueBlack==null) prevTrueBlack=GlobalUserPreferences.trueBlackTheme;
|
if(prevTrueBlack==null) prevTrueBlack=GlobalUserPreferences.trueBlackTheme;
|
||||||
if(prevColor==null) prevColor=lp.color;
|
if(prevColor==null) prevColor=lp.getCurrentColor();
|
||||||
|
|
||||||
boolean isCurrentDark=prevTheme==GlobalUserPreferences.ThemePreference.DARK ||
|
boolean isCurrentDark=prevTheme==GlobalUserPreferences.ThemePreference.DARK ||
|
||||||
(prevTheme==GlobalUserPreferences.ThemePreference.AUTO && Build.VERSION.SDK_INT>=30 && getResources().getConfiguration().isNightModeActive());
|
(prevTheme==GlobalUserPreferences.ThemePreference.AUTO && Build.VERSION.SDK_INT>=30 && getResources().getConfiguration().isNightModeActive());
|
||||||
boolean isNewDark=GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.DARK ||
|
boolean isNewDark=GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.DARK ||
|
||||||
(GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.AUTO && Build.VERSION.SDK_INT>=30 && getResources().getConfiguration().isNightModeActive());
|
(GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.AUTO && Build.VERSION.SDK_INT>=30 && getResources().getConfiguration().isNightModeActive());
|
||||||
boolean isNewBlack=GlobalUserPreferences.trueBlackTheme;
|
boolean isNewBlack=GlobalUserPreferences.trueBlackTheme;
|
||||||
if(isCurrentDark!=isNewDark || prevColor!=lp.color || (isNewDark && prevTrueBlack!=isNewBlack)){
|
if(isCurrentDark!=isNewDark || prevColor!=lp.getCurrentColor() || (isNewDark && prevTrueBlack!=isNewBlack)){
|
||||||
restartActivityToApplyNewTheme();
|
restartActivityToApplyNewTheme();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
|||||||
public transient boolean spoilerRevealed;
|
public transient boolean spoilerRevealed;
|
||||||
public transient boolean sensitiveRevealed;
|
public transient boolean sensitiveRevealed;
|
||||||
public transient boolean textExpanded, textExpandable;
|
public transient boolean textExpanded, textExpandable;
|
||||||
public transient boolean hasGapAfter;
|
public transient String hasGapAfter;
|
||||||
private transient String strippedText;
|
private transient String strippedText;
|
||||||
public transient TranslationState translationState=TranslationState.HIDDEN;
|
public transient TranslationState translationState=TranslationState.HIDDEN;
|
||||||
public transient Translation translation;
|
public transient Translation translation;
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ public class GapStatusDisplayItem extends StatusDisplayItem{
|
|||||||
this.status=status;
|
this.status=status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMaxID(){
|
||||||
|
return status.hasGapAfter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType(){
|
public Type getType(){
|
||||||
return Type.GAP;
|
return Type.GAP;
|
||||||
@@ -54,6 +58,8 @@ public class GapStatusDisplayItem extends StatusDisplayItem{
|
|||||||
if(!item.loading){
|
if(!item.loading){
|
||||||
progressBottom.setVisibility(View.GONE);
|
progressBottom.setVisibility(View.GONE);
|
||||||
progressTop.setVisibility(View.GONE);
|
progressTop.setVisibility(View.GONE);
|
||||||
|
textTop.setAlpha(1);
|
||||||
|
textBottom.setAlpha(1);
|
||||||
}
|
}
|
||||||
top.setClickable(!item.loading);
|
top.setClickable(!item.loading);
|
||||||
bottom.setClickable(!item.loading);
|
bottom.setClickable(!item.loading);
|
||||||
|
|||||||
@@ -381,21 +381,32 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||||||
markAsRead.setVisibility(View.GONE);
|
markAsRead.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.status == null || !item.status.textExpandable) {
|
bindCollapseButton();
|
||||||
collapseBtn.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
String collapseText = item.parentFragment.getString(item.status.textExpanded ? R.string.sk_collapse : R.string.sk_expand);
|
|
||||||
collapseBtn.setVisibility(item.status.textExpandable ? View.VISIBLE : View.GONE);
|
|
||||||
collapseBtn.setContentDescription(collapseText);
|
|
||||||
if (GlobalUserPreferences.reduceMotion) collapseBtnIcon.setScaleY(item.status.textExpanded ? -1 : 1);
|
|
||||||
else collapseBtnIcon.animate().scaleY(item.status.textExpanded ? -1 : 1).start();
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) collapseBtn.setTooltipText(collapseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
itemView.setPaddingRelative(itemView.getPaddingStart(), itemView.getPaddingTop(),
|
itemView.setPaddingRelative(itemView.getPaddingStart(), itemView.getPaddingTop(),
|
||||||
item.inset ? V.dp(10) : V.dp(4), itemView.getPaddingBottom());
|
item.inset ? V.dp(10) : V.dp(4), itemView.getPaddingBottom());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void bindCollapseButton(){
|
||||||
|
boolean expandable=item.status!=null && item.status.textExpandable;
|
||||||
|
collapseBtn.setVisibility(expandable ? View.VISIBLE : View.GONE);
|
||||||
|
if(expandable) {
|
||||||
|
bindCollapseButtonText();
|
||||||
|
collapseBtnIcon.setScaleY(item.status.textExpanded ? -1 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindCollapseButtonText(){
|
||||||
|
String collapseText = item.parentFragment.getString(item.status.textExpanded ? R.string.sk_collapse : R.string.sk_expand);
|
||||||
|
collapseBtn.setContentDescription(collapseText);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) collapseBtn.setTooltipText(collapseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void animateExpandToggle(){
|
||||||
|
bindCollapseButtonText();
|
||||||
|
collapseBtnIcon.animate().scaleY(item.status.textExpanded ? -1 : 1).start();
|
||||||
|
}
|
||||||
|
|
||||||
public void animateVisibilityToggle(boolean visible){
|
public void animateVisibilityToggle(boolean visible){
|
||||||
visibility.animate()
|
visibility.animate()
|
||||||
.alpha(visible ? 1 : 0)
|
.alpha(visible ? 1 : 0)
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ public abstract class StatusDisplayItem{
|
|||||||
footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID);
|
footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID);
|
||||||
footer.hideCounts=hideCounts;
|
footer.hideCounts=hideCounts;
|
||||||
items.add(footer);
|
items.add(footer);
|
||||||
if(status.hasGapAfter && !(fragment instanceof ThreadFragment))
|
if(status.hasGapAfter!=null && !(fragment instanceof ThreadFragment))
|
||||||
items.add(new GapStatusDisplayItem(parentID, fragment, status));
|
items.add(new GapStatusDisplayItem(parentID, fragment, status));
|
||||||
}
|
}
|
||||||
int i=1;
|
int i=1;
|
||||||
|
|||||||
@@ -1032,8 +1032,8 @@ public class UiUtils {
|
|||||||
default -> R.style.Theme_Mastodon_AutoLightDark;
|
default -> R.style.Theme_Mastodon_AutoLightDark;
|
||||||
});
|
});
|
||||||
|
|
||||||
AccountLocalPreferences prefs=session != null ? session.getLocalPreferences() : null;
|
AccountLocalPreferences prefs=session!=null ? session.getLocalPreferences() : null;
|
||||||
AccountLocalPreferences.ColorPreference color=prefs != null ? prefs.color : AccountLocalPreferences.ColorPreference.MATERIAL3;
|
AccountLocalPreferences.ColorPreference color=prefs!=null ? prefs.getCurrentColor() : AccountLocalPreferences.ColorPreference.MATERIAL3;
|
||||||
ColorPalette palette = ColorPalette.palettes.get(color);
|
ColorPalette palette = ColorPalette.palettes.get(color);
|
||||||
if (palette != null) palette.apply(context, theme);
|
if (palette != null) palette.apply(context, theme);
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
<string name="sk_notification_type_status">Posts</string>
|
<string name="sk_notification_type_status">Posts</string>
|
||||||
<string name="sk_notification_type_posts">Post notifications</string>
|
<string name="sk_notification_type_posts">Post notifications</string>
|
||||||
<string name="sk_settings_color_palette">Color palette</string>
|
<string name="sk_settings_color_palette">Color palette</string>
|
||||||
|
<string name="sk_settings_color_palette_default">Default (%s)</string>
|
||||||
<string name="sk_color_palette_material3">System</string>
|
<string name="sk_color_palette_material3">System</string>
|
||||||
<string name="sk_color_palette_pink">Pink</string>
|
<string name="sk_color_palette_pink">Pink</string>
|
||||||
<string name="sk_color_palette_purple">Purple</string>
|
<string name="sk_color_palette_purple">Purple</string>
|
||||||
@@ -409,4 +410,5 @@
|
|||||||
<string name="sk_settings_like_icon">Use heart as favorite icon</string>
|
<string name="sk_settings_like_icon">Use heart as favorite icon</string>
|
||||||
<string name="sk_recently_used">Recently used</string>
|
<string name="sk_recently_used">Recently used</string>
|
||||||
<string name="sk_settings_underlined_links">Underlined links</string>
|
<string name="sk_settings_underlined_links">Underlined links</string>
|
||||||
|
<string name="sk_set_as_default">Set as default</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user