more options for showing emoji reactions

closes sk22#796
re: sk22#788
This commit is contained in:
sk 2023-09-01 14:23:38 +02:00
parent 3fd9dc1dcd
commit ea01b14ffb
5 changed files with 63 additions and 17 deletions

View File

@ -13,7 +13,6 @@ import org.joinmastodon.android.model.TimelineDefinition;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
public class AccountLocalPreferences{ public class AccountLocalPreferences{
private final SharedPreferences prefs; private final SharedPreferences prefs;
@ -39,7 +38,7 @@ public class AccountLocalPreferences{
public boolean keepOnlyLatestNotification; public boolean keepOnlyLatestNotification;
public boolean emojiReactionsEnabled; public boolean emojiReactionsEnabled;
public boolean emojiReactionsInTimelines; public ShowEmojiReactions showEmojiReactions;
private final static Type recentLanguagesType = new TypeToken<ArrayList<String>>() {}.getType(); private final static Type recentLanguagesType = new TypeToken<ArrayList<String>>() {}.getType();
private final static Type timelinesType = new TypeToken<ArrayList<TimelineDefinition>>() {}.getType(); private final static Type timelinesType = new TypeToken<ArrayList<TimelineDefinition>>() {}.getType();
@ -66,7 +65,7 @@ public class AccountLocalPreferences{
timelineReplyVisibility=prefs.getString("timelineReplyVisibility", null); timelineReplyVisibility=prefs.getString("timelineReplyVisibility", null);
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());
emojiReactionsInTimelines=prefs.getBoolean("emojiReactionsInTimelines", true); showEmojiReactions=ShowEmojiReactions.valueOf(prefs.getString("showEmojiReactions", ShowEmojiReactions.HIDE_EMPTY.name()));
} }
public long getNotificationsPauseEndTime(){ public long getNotificationsPauseEndTime(){
@ -99,7 +98,13 @@ public class AccountLocalPreferences{
.putString("timelineReplyVisibility", timelineReplyVisibility) .putString("timelineReplyVisibility", timelineReplyVisibility)
.putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification) .putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification)
.putBoolean("emojiReactionsEnabled", emojiReactionsEnabled) .putBoolean("emojiReactionsEnabled", emojiReactionsEnabled)
.putBoolean("emojiReactionsInTimelines", emojiReactionsInTimelines) .putString("showEmojiReactions", showEmojiReactions.name())
.apply(); .apply();
} }
public enum ShowEmojiReactions{
HIDE_EMPTY,
ONLY_OPENED,
ALWAYS
}
} }

View File

@ -1,5 +1,7 @@
package org.joinmastodon.android.fragments; package org.joinmastodon.android.fragments;
import static org.joinmastodon.android.api.session.AccountLocalPreferences.ShowEmojiReactions.ONLY_OPENED;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
@ -7,6 +9,7 @@ import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E; import org.joinmastodon.android.E;
import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.session.AccountLocalPreferences;
import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.EmojiReactionsUpdatedEvent; import org.joinmastodon.android.events.EmojiReactionsUpdatedEvent;
import org.joinmastodon.android.events.PollUpdatedEvent; import org.joinmastodon.android.events.PollUpdatedEvent;
@ -38,9 +41,10 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
protected List<StatusDisplayItem> buildDisplayItems(Status s){ protected List<StatusDisplayItem> buildDisplayItems(Status s){
boolean isMainThreadStatus = this instanceof ThreadFragment t && s.id.equals(t.mainStatus.id); boolean isMainThreadStatus = this instanceof ThreadFragment t && s.id.equals(t.mainStatus.id);
int flags = 0; int flags = 0;
AccountLocalPreferences lp=getLocalPrefs();
if (GlobalUserPreferences.spectatorMode) if (GlobalUserPreferences.spectatorMode)
flags |= StatusDisplayItem.FLAG_NO_FOOTER; flags |= StatusDisplayItem.FLAG_NO_FOOTER;
if (!getLocalPrefs().emojiReactionsInTimelines) if (!lp.emojiReactionsEnabled || lp.showEmojiReactions==ONLY_OPENED)
flags |= StatusDisplayItem.FLAG_NO_EMOJI_REACTIONS; flags |= StatusDisplayItem.FLAG_NO_EMOJI_REACTIONS;
return StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, getFilterContext(), isMainThreadStatus ? 0 : flags); return StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, getFilterContext(), isMainThreadStatus ? 0 : flags);
} }

View File

@ -2,10 +2,14 @@ package org.joinmastodon.android.fragments.settings;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.StringRes;
import org.joinmastodon.android.E;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountLocalPreferences; import org.joinmastodon.android.api.session.AccountLocalPreferences;
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.events.StatusDisplaySettingsChangedEvent;
import org.joinmastodon.android.fragments.HasAccountID; import org.joinmastodon.android.fragments.HasAccountID;
import org.joinmastodon.android.model.ContentType; import org.joinmastodon.android.model.ContentType;
import org.joinmastodon.android.model.viewmodel.CheckableListItem; import org.joinmastodon.android.model.viewmodel.CheckableListItem;
@ -15,12 +19,13 @@ import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.IntStream;
import me.grishka.appkit.Nav; import me.grishka.appkit.Nav;
public class SettingsInstanceFragment extends BaseSettingsFragment<Void> implements HasAccountID{ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> implements HasAccountID{
private CheckableListItem<Void> contentTypesItem, emojiReactionsItem, emojiReactionsInTimelinesItem, localOnlyItem, glitchModeItem; private CheckableListItem<Void> contentTypesItem, emojiReactionsItem, localOnlyItem, glitchModeItem;
private ListItem<Void> defaultContentTypeItem; private ListItem<Void> defaultContentTypeItem, showEmojiReactionsItem;
private AccountLocalPreferences lp; private AccountLocalPreferences lp;
@Override @Override
@ -37,14 +42,14 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
contentTypesItem=new CheckableListItem<>(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, CheckableListItem.Style.SWITCH, lp.contentTypesEnabled, R.drawable.ic_fluent_text_edit_style_24_regular, this::onContentTypeClick), contentTypesItem=new CheckableListItem<>(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, CheckableListItem.Style.SWITCH, lp.contentTypesEnabled, R.drawable.ic_fluent_text_edit_style_24_regular, this::onContentTypeClick),
defaultContentTypeItem=new ListItem<>(R.string.sk_settings_default_content_type, lp.defaultContentType.getName(), R.drawable.ic_fluent_text_bold_24_regular, this::onDefaultContentTypeClick, 0, true), defaultContentTypeItem=new ListItem<>(R.string.sk_settings_default_content_type, lp.defaultContentType.getName(), R.drawable.ic_fluent_text_bold_24_regular, this::onDefaultContentTypeClick, 0, true),
emojiReactionsItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions, R.string.sk_settings_emoji_reactions_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsEnabled, R.drawable.ic_fluent_emoji_laugh_24_regular, this::onEmojiReactionsClick), emojiReactionsItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions, R.string.sk_settings_emoji_reactions_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsEnabled, R.drawable.ic_fluent_emoji_laugh_24_regular, this::onEmojiReactionsClick),
emojiReactionsInTimelinesItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions_in_lists, R.string.sk_settings_emoji_reactions_in_lists_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsInTimelines, R.drawable.ic_fluent_emoji_24_regular, ()->toggleCheckableItem(emojiReactionsInTimelinesItem), true), showEmojiReactionsItem=new ListItem<>(R.string.sk_settings_show_emoji_reactions, getShowEmojiReactionsString(), R.drawable.ic_fluent_emoji_24_regular, this::onShowEmojiReactionsClick, 0, true),
localOnlyItem=new CheckableListItem<>(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, CheckableListItem.Style.SWITCH, lp.localOnlySupported, R.drawable.ic_fluent_eye_24_regular, this::onLocalOnlyClick), localOnlyItem=new CheckableListItem<>(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, CheckableListItem.Style.SWITCH, lp.localOnlySupported, R.drawable.ic_fluent_eye_24_regular, this::onLocalOnlyClick),
glitchModeItem=new CheckableListItem<>(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, CheckableListItem.Style.SWITCH, lp.glitchInstance, R.drawable.ic_fluent_eye_24_filled, ()->toggleCheckableItem(glitchModeItem)) glitchModeItem=new CheckableListItem<>(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, CheckableListItem.Style.SWITCH, lp.glitchInstance, R.drawable.ic_fluent_eye_24_filled, ()->toggleCheckableItem(glitchModeItem))
)); ));
contentTypesItem.checkedChangeListener=checked->onContentTypeClick(); contentTypesItem.checkedChangeListener=checked->onContentTypeClick();
defaultContentTypeItem.isEnabled=contentTypesItem.checked; defaultContentTypeItem.isEnabled=contentTypesItem.checked;
emojiReactionsItem.checkedChangeListener=checked->onEmojiReactionsClick(); emojiReactionsItem.checkedChangeListener=checked->onEmojiReactionsClick();
emojiReactionsInTimelinesItem.isEnabled=emojiReactionsItem.checked; showEmojiReactionsItem.isEnabled=emojiReactionsItem.checked;
localOnlyItem.checkedChangeListener=checked->onLocalOnlyClick(); localOnlyItem.checkedChangeListener=checked->onLocalOnlyClick();
glitchModeItem.isEnabled=localOnlyItem.checked; glitchModeItem.isEnabled=localOnlyItem.checked;
} }
@ -57,10 +62,10 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
super.onHidden(); super.onHidden();
lp.contentTypesEnabled=contentTypesItem.checked; lp.contentTypesEnabled=contentTypesItem.checked;
lp.emojiReactionsEnabled=emojiReactionsItem.checked; lp.emojiReactionsEnabled=emojiReactionsItem.checked;
lp.emojiReactionsInTimelines=emojiReactionsInTimelinesItem.checked;
lp.localOnlySupported=localOnlyItem.checked; lp.localOnlySupported=localOnlyItem.checked;
lp.glitchInstance=glitchModeItem.checked; lp.glitchInstance=glitchModeItem.checked;
lp.save(); lp.save();
E.post(new StatusDisplaySettingsChangedEvent(accountID));
} }
private void onServerClick(){ private void onServerClick(){
@ -107,10 +112,34 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
.show(); .show();
} }
private void onShowEmojiReactionsClick(){
int selected=lp.showEmojiReactions.ordinal();
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_show_emoji_reactions)
.setSingleChoiceItems((String[]) IntStream.of(R.string.sk_settings_show_emoji_reactions_hide_empty, R.string.sk_settings_show_emoji_reactions_only_opened, R.string.sk_settings_show_emoji_reactions_always).mapToObj(this::getString).toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
lp.showEmojiReactions=AccountLocalPreferences.ShowEmojiReactions.values()[newSelected[0]];
showEmojiReactionsItem.subtitleRes=getShowEmojiReactionsString();
rebindItem(showEmojiReactionsItem);
})
.setNegativeButton(R.string.cancel, null)
.show();
}
private @StringRes int getShowEmojiReactionsString(){
return switch(lp.showEmojiReactions){
case HIDE_EMPTY -> R.string.sk_settings_show_emoji_reactions_hide_empty;
case ONLY_OPENED -> R.string.sk_settings_show_emoji_reactions_only_opened;
case ALWAYS -> R.string.sk_settings_show_emoji_reactions_always;
};
}
private void onEmojiReactionsClick(){ private void onEmojiReactionsClick(){
toggleCheckableItem(emojiReactionsItem); toggleCheckableItem(emojiReactionsItem);
emojiReactionsInTimelinesItem.checked=emojiReactionsInTimelinesItem.isEnabled=emojiReactionsItem.checked; showEmojiReactionsItem.isEnabled=emojiReactionsItem.checked;
rebindItem(emojiReactionsInTimelinesItem); rebindItem(showEmojiReactionsItem);
} }
private void onLocalOnlyClick(){ private void onLocalOnlyClick(){

View File

@ -1,5 +1,8 @@
package org.joinmastodon.android.ui.displayitems; package org.joinmastodon.android.ui.displayitems;
import static org.joinmastodon.android.api.session.AccountLocalPreferences.ShowEmojiReactions.ALWAYS;
import static org.joinmastodon.android.api.session.AccountLocalPreferences.ShowEmojiReactions.ONLY_OPENED;
import android.app.Activity; import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
@ -12,6 +15,7 @@ import android.view.ViewGroup;
import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountLocalPreferences;
import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.fragments.HashtagTimelineFragment; import org.joinmastodon.android.fragments.HashtagTimelineFragment;
@ -277,10 +281,12 @@ public abstract class StatusDisplayItem{
if(contentItems!=items && statusForContent.spoilerRevealed){ if(contentItems!=items && statusForContent.spoilerRevealed){
items.addAll(contentItems); items.addAll(contentItems);
} }
if((flags & FLAG_NO_EMOJI_REACTIONS)==0 && fragment.getLocalPrefs().emojiReactionsEnabled && AccountLocalPreferences lp=fragment.getLocalPrefs();
(fragment.getLocalPrefs().emojiReactionsInTimelines || fragment instanceof ThreadFragment)){ if((flags & FLAG_NO_EMOJI_REACTIONS)==0 && lp.emojiReactionsEnabled &&
(lp.showEmojiReactions!=ONLY_OPENED || fragment instanceof ThreadFragment)){
boolean isMainStatus=fragment instanceof ThreadFragment t && t.getMainStatus().id.equals(statusForContent.id); boolean isMainStatus=fragment instanceof ThreadFragment t && t.getMainStatus().id.equals(statusForContent.id);
items.add(new EmojiReactionsStatusDisplayItem(parentID, fragment, statusForContent, accountID, !isMainStatus, false)); boolean showAddButton=lp.showEmojiReactions==ALWAYS || isMainStatus;
items.add(new EmojiReactionsStatusDisplayItem(parentID, fragment, statusForContent, accountID, !showAddButton, false));
} }
FooterStatusDisplayItem footer=null; FooterStatusDisplayItem footer=null;
if((flags & FLAG_NO_FOOTER)==0){ if((flags & FLAG_NO_FOOTER)==0){

View File

@ -352,8 +352,10 @@
<string name="sk_settings_show_labels_in_navigation_bar">Show tab labels in the navigation bar</string> <string name="sk_settings_show_labels_in_navigation_bar">Show tab labels in the navigation bar</string>
<string name="sk_settings_emoji_reactions">Enable emoji reactions</string> <string name="sk_settings_emoji_reactions">Enable emoji reactions</string>
<string name="sk_settings_emoji_reactions_explanation">Displays emoji reactions to posts and lets you interact with them. Some modified versions of Mastodon support this, but Mastodon doesn\'t.</string> <string name="sk_settings_emoji_reactions_explanation">Displays emoji reactions to posts and lets you interact with them. Some modified versions of Mastodon support this, but Mastodon doesn\'t.</string>
<string name="sk_settings_emoji_reactions_in_lists">Show emoji reactions in timelines</string> <string name="sk_settings_show_emoji_reactions">Show emoji reactions in timelines</string>
<string name="sk_settings_emoji_reactions_in_lists_explanation">Whether emoji reactions should be displayed on timelines. If this option is off, emoji reactions will only be displayed when viewing a thread.</string> <string name="sk_settings_show_emoji_reactions_hide_empty">Hide empty emoji reactions</string>
<string name="sk_settings_show_emoji_reactions_only_opened">Only when post is opened</string>
<string name="sk_settings_show_emoji_reactions_always">Always show add button</string>
<plurals name="sk_users_reacted_with"> <plurals name="sk_users_reacted_with">
<item quantity="one">One user reacted with %2$s</item> <item quantity="one">One user reacted with %2$s</item>
<item quantity="other">%1$,d users reacted with %2$s</item> <item quantity="other">%1$,d users reacted with %2$s</item>