reply line below, compact above

This commit is contained in:
sk 2023-03-15 21:24:25 +01:00
parent 16f907c91f
commit e2193e8e3c
8 changed files with 116 additions and 44 deletions

View File

@ -44,7 +44,8 @@ public class GlobalUserPreferences{
public static boolean collapseLongPosts;
public static boolean spectatorMode;
public static boolean autoHideFab;
public static boolean replyLineBelowHeader;
public static boolean replyLineAboveHeader;
public static boolean compactReblogReplyLine;
public static String publishButtonText;
public static ThemePreference theme;
public static ColorPreference color;
@ -94,7 +95,8 @@ public class GlobalUserPreferences{
collapseLongPosts=prefs.getBoolean("collapseLongPosts", true);
spectatorMode=prefs.getBoolean("spectatorMode", false);
autoHideFab=prefs.getBoolean("autoHideFab", true);
replyLineBelowHeader=prefs.getBoolean("replyLineBelowHeader", true);
replyLineAboveHeader =prefs.getBoolean("replyLineAboveHeader", false);
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
publishButtonText=prefs.getString("publishButtonText", "");
theme=ThemePreference.values()[prefs.getInt("theme", 0)];
recentLanguages=fromJson(prefs.getString("recentLanguages", null), recentLanguagesType, new HashMap<>());
@ -136,9 +138,10 @@ public class GlobalUserPreferences{
.putBoolean("collapseLongPosts", collapseLongPosts)
.putBoolean("spectatorMode", spectatorMode)
.putBoolean("autoHideFab", autoHideFab)
.putBoolean("compactReblogReplyLine", compactReblogReplyLine)
.putString("publishButtonText", publishButtonText)
.putBoolean("bottomEncoding", bottomEncoding)
.putBoolean("replyLineBelowHeader", replyLineBelowHeader)
.putBoolean("replyLineAboveHeader", replyLineAboveHeader)
.putInt("theme", theme.ordinal())
.putString("color", color.name())
.putString("recentLanguages", gson.toJson(recentLanguages))

View File

@ -333,8 +333,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
scheduleTimeBtn=view.findViewById(R.id.scheduled_time_btn);
sensitiveIcon=view.findViewById(R.id.sensitive_icon);
sensitiveItem=view.findViewById(R.id.sensitive_item);
replyText=view.findViewById(GlobalUserPreferences.replyLineBelowHeader ? R.id.reply_text_below : R.id.reply_text);
view.findViewById(GlobalUserPreferences.replyLineBelowHeader ? R.id.reply_text : R.id.reply_text_below)
replyText=view.findViewById(GlobalUserPreferences.replyLineAboveHeader ? R.id.reply_text : R.id.reply_text_below);
view.findViewById(GlobalUserPreferences.replyLineAboveHeader ? R.id.reply_text_below : R.id.reply_text)
.setVisibility(View.GONE);
if (isPhotoPickerAvailable()) {

View File

@ -80,7 +80,7 @@ public class SettingsFragment extends MastodonToolbarFragment{
private ArrayList<Item> items=new ArrayList<>();
private ThemeItem themeItem;
private NotificationPolicyItem notificationPolicyItem;
private SwitchItem showNewPostsButtonItem, glitchModeItem;
private SwitchItem showNewPostsButtonItem, glitchModeItem, compactReblogReplyLineItem;
private String accountID;
private boolean needUpdateNotificationSettings;
private boolean needAppRestart;
@ -253,10 +253,19 @@ public class SettingsFragment extends MastodonToolbarFragment{
GlobalUserPreferences.save();
needAppRestart=true;
}));
items.add(new SwitchItem(R.string.sk_reply_line_below_avatar, R.drawable.ic_fluent_arrow_reply_24_regular, GlobalUserPreferences.replyLineBelowHeader, i->{
GlobalUserPreferences.replyLineBelowHeader=i.checked;
items.add(new SwitchItem(R.string.sk_reply_line_above_avatar, R.drawable.ic_fluent_arrow_reply_24_regular, GlobalUserPreferences.replyLineAboveHeader, i->{
GlobalUserPreferences.replyLineAboveHeader=i.checked;
GlobalUserPreferences.compactReblogReplyLine=i.checked;
compactReblogReplyLineItem.enabled=i.checked;
compactReblogReplyLineItem.checked= GlobalUserPreferences.replyLineAboveHeader;
if (list.findViewHolderForAdapterPosition(items.indexOf(compactReblogReplyLineItem)) instanceof SwitchViewHolder svh) svh.rebind();
GlobalUserPreferences.save();
}));
items.add(compactReblogReplyLineItem=new SwitchItem(R.string.sk_compact_reblog_reply_line, R.drawable.ic_fluent_re_order_24_regular, GlobalUserPreferences.compactReblogReplyLine, i->{
GlobalUserPreferences.compactReblogReplyLine=i.checked;
GlobalUserPreferences.save();;
}));
compactReblogReplyLineItem.enabled=GlobalUserPreferences.replyLineAboveHeader;
items.add(new SwitchItem(R.string.sk_settings_translate_only_opened, R.drawable.ic_fluent_translate_24_regular, GlobalUserPreferences.translateButtonOpenedOnly, i->{
GlobalUserPreferences.translateButtonOpenedOnly=i.checked;
GlobalUserPreferences.save();

View File

@ -39,6 +39,7 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
private View.OnClickListener handleClick;
boolean belowHeader, needBottomPadding;
ReblogOrReplyLineStatusDisplayItem secondary;
public ReblogOrReplyLineStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, CharSequence text, List<Emoji> emojis, @DrawableRes int icon, StatusPrivacy visibility, @Nullable View.OnClickListener handleClick) {
super(parentID, parentFragment);
@ -79,15 +80,17 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
}
public static class Holder extends StatusDisplayItem.Holder<ReblogOrReplyLineStatusDisplayItem> implements ImageLoaderViewHolder{
private final TextView text;
private final TextView text, secondaryText;
private final View secondaryWrap;
public Holder(Activity activity, ViewGroup parent){
super(activity, R.layout.display_item_reblog_or_reply_line, parent);
text=findViewById(R.id.text);
secondaryText=findViewById(R.id.secondary_text);
secondaryWrap=findViewById(R.id.secondary_wrap);
}
@Override
public void onBind(ReblogOrReplyLineStatusDisplayItem item){
private void bindLine(ReblogOrReplyLineStatusDisplayItem item, TextView text) {
text.setText(item.text);
text.setCompoundDrawablesRelativeWithIntrinsicBounds(item.icon, 0, item.iconEnd, 0);
text.setOnClickListener(item.handleClick);
@ -104,11 +107,18 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
if (visibilityText != 0) text.setContentDescription(item.text + " (" + ctx.getString(visibilityText) + ")");
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N)
UiUtils.fixCompoundDrawableTintOnAndroid6(text);
text.setTextAppearance(item.belowHeader ? R.style.m3_label_large : R.style.m3_title_small);
text.setCompoundDrawableTintList(text.getTextColors());
}
@Override
public void onBind(ReblogOrReplyLineStatusDisplayItem item){
bindLine(item, text);
if (item.secondary != null) bindLine(item.secondary, secondaryText);
secondaryWrap.setVisibility(item.secondary == null ? View.GONE : View.VISIBLE);
ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.bottomMargin = item.belowHeader ? V.dp(-6) : V.dp(-12);
params.topMargin = item.belowHeader ? V.dp(-6) : 0;
text.setTextAppearance(item.belowHeader ? R.style.m3_label_large : R.style.m3_title_small);
text.setCompoundDrawableTintList(text.getTextColors());
itemView.setLayoutParams(params);
itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), item.needBottomPadding ? V.dp(16) : 0);
}

View File

@ -32,6 +32,7 @@ import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import me.grishka.appkit.Nav;
@ -109,9 +110,35 @@ public abstract class StatusDisplayItem{
statusForContent.filterRevealed = filterPredicate.testWithWarning(status);
}
ReblogOrReplyLineStatusDisplayItem replyLine = null;
boolean threadReply = statusForContent.inReplyToAccountId != null &&
statusForContent.inReplyToAccountId.equals(status.account.id);
if(statusForContent.inReplyToAccountId!=null && !(threadReply && fragment instanceof ThreadFragment)){
Account account = knownAccounts.get(statusForContent.inReplyToAccountId);
View.OnClickListener handleClick = account == null || threadReply ? null : i -> {
args.putParcelable("profileAccount", Parcels.wrap(account));
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
};
String text = threadReply ? fragment.getString(R.string.sk_show_thread)
: account == null ? fragment.getString(R.string.sk_in_reply)
: GlobalUserPreferences.compactReblogReplyLine && status.reblog != null ? account.displayName
: fragment.getString(R.string.in_reply_to, account.displayName);
replyLine = new ReblogOrReplyLineStatusDisplayItem(
parentID, fragment, text, account == null ? List.of() : account.emojis,
R.drawable.ic_fluent_arrow_reply_20_filled, null, handleClick
);
}
if(status.reblog!=null){
boolean isOwnPost = AccountSessionManager.getInstance().isSelf(fragment.getAccountID(), status.account);
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, isOwnPost ? status.visibility : null, i->{
String text = GlobalUserPreferences.compactReblogReplyLine && replyLine != null
? status.account.displayName
: fragment.getString(R.string.user_boosted, status.account.displayName);
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, text, status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20_filled, isOwnPost ? status.visibility : null, i->{
args.putParcelable("profileAccount", Parcels.wrap(status.account));
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
}));
@ -134,42 +161,30 @@ public abstract class StatusDisplayItem{
)));
}
ReblogOrReplyLineStatusDisplayItem replyLine = null;
boolean threadReply = statusForContent.inReplyToAccountId != null &&
statusForContent.inReplyToAccountId.equals(status.account.id);
if (replyLine != null && GlobalUserPreferences.replyLineAboveHeader) {
Optional<ReblogOrReplyLineStatusDisplayItem> primaryLine = items.stream()
.filter(i -> i instanceof ReblogOrReplyLineStatusDisplayItem)
.map(ReblogOrReplyLineStatusDisplayItem.class::cast)
.findFirst();
if(statusForContent.inReplyToAccountId!=null && !(threadReply && fragment instanceof ThreadFragment)){
Account account = knownAccounts.get(statusForContent.inReplyToAccountId);
View.OnClickListener handleClick = account == null || threadReply ? null : i -> {
args.putParcelable("profileAccount", Parcels.wrap(account));
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
};
String text = threadReply ?
fragment.getString(R.string.sk_show_thread) : account != null ?
fragment.getString(R.string.in_reply_to, account.displayName) : fragment.getString(R.string.sk_in_reply);
replyLine = new ReblogOrReplyLineStatusDisplayItem(
parentID, fragment, text, account == null ? List.of() : account.emojis,
R.drawable.ic_fluent_arrow_reply_20_filled, null, handleClick
);
}
if (replyLine != null && !GlobalUserPreferences.replyLineBelowHeader) {
items.add(replyLine);
if (primaryLine.isPresent() && GlobalUserPreferences.compactReblogReplyLine) {
primaryLine.get().secondary = replyLine;
} else {
items.add(replyLine);
}
}
HeaderStatusDisplayItem header;
items.add(header=new HeaderStatusDisplayItem(parentID, statusForContent.account, statusForContent.createdAt, fragment, accountID, statusForContent, null, notification, scheduledStatus));
if (replyLine != null && GlobalUserPreferences.replyLineBelowHeader) {
if (replyLine != null && !GlobalUserPreferences.replyLineAboveHeader) {
replyLine.belowHeader = true;
items.add(replyLine);
}
if(!TextUtils.isEmpty(statusForContent.content))
items.add(new TextStatusDisplayItem(parentID, HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID), fragment, statusForContent, disableTranslate));
else if (GlobalUserPreferences.replyLineBelowHeader && replyLine != null)
else if (!GlobalUserPreferences.replyLineAboveHeader && replyLine != null)
replyLine.needBottomPadding=true;
else
header.needBottomPadding=true;

View File

@ -0,0 +1,3 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:pathData="M2.75 13.25h18.5c0.414 0 0.75 0.336 0.75 0.75 0 0.38-0.282 0.694-0.648 0.743L21.25 14.75H2.75C2.336 14.75 2 14.414 2 14c0-0.38 0.282-0.694 0.648-0.743L2.75 13.25h18.5-18.5zm0-4h18.5C21.664 9.25 22 9.586 22 10c0 0.38-0.282 0.694-0.648 0.743L21.25 10.75H2.75C2.336 10.75 2 10.414 2 10c0-0.38 0.282-0.694 0.648-0.743L2.75 9.25h18.5-18.5z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<org.joinmastodon.android.ui.views.AutoOrientationLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/frame"
android:paddingTop="16dp"
android:paddingHorizontal="10dp"
android:layout_marginBottom="-12dp">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:layout_marginStart="6dp"
android:paddingBottom="6dp"
android:textAppearance="@style/m3_title_small"
android:drawableStart="@drawable/ic_fluent_arrow_repeat_all_20_filled"
@ -19,4 +19,35 @@
android:singleLine="true"
android:ellipsize="end"/>
</FrameLayout>
<LinearLayout
android:id="@+id/secondary_wrap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="6dp"
android:paddingHorizontal="1dp"
android:textAppearance="@style/m3_title_small"
android:gravity="center_horizontal"
android:importantForAccessibility="no"
android:includeFontPadding="false"
android:text="@string/sk_separator" />
<TextView
android:id="@+id/secondary_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="6dp"
android:textAppearance="@style/m3_title_small"
android:drawableStart="@drawable/ic_fluent_arrow_reply_20_filled"
android:drawableTint="?android:textColorSecondary"
android:drawablePadding="6dp"
android:singleLine="true"
android:ellipsize="end"/>
</LinearLayout>
</org.joinmastodon.android.ui.views.AutoOrientationLinearLayout>

View File

@ -263,6 +263,7 @@
<string name="sk_followed_as">Followed from %s</string>
<string name="sk_settings_hide_fab">Auto-hide Compose button</string>
<string name="sk_in_reply">In reply</string>
<string name="sk_reply_line_below_avatar">“In reply to” line below avatar</string>
<string name="sk_reply_line_above_avatar">“In reply to” line above avatar</string>
<string name="sk_show_thread">Show thread</string>
<string name="sk_compact_reblog_reply_line">Compact reblog/reply line</string>
</resources>