Pre-reply sheets
This commit is contained in:
parent
45cc531eec
commit
a438f633be
|
@ -3,6 +3,9 @@ package org.joinmastodon.android;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
|
||||
public class GlobalUserPreferences{
|
||||
public static boolean playGifs;
|
||||
public static boolean useCustomTabs;
|
||||
|
@ -13,6 +16,10 @@ public class GlobalUserPreferences{
|
|||
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
private static SharedPreferences getPreReplyPrefs(){
|
||||
return MastodonApp.context.getSharedPreferences("pre_reply_sheets", Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public static void load(){
|
||||
SharedPreferences prefs=getPrefs();
|
||||
playGifs=prefs.getBoolean("playGifs", true);
|
||||
|
@ -36,9 +43,42 @@ public class GlobalUserPreferences{
|
|||
.apply();
|
||||
}
|
||||
|
||||
public static boolean isOptedOutOfPreReplySheet(PreReplySheetType type, Account account, String accountID){
|
||||
if(getPreReplyPrefs().getBoolean("opt_out_"+type, false))
|
||||
return true;
|
||||
if(account==null)
|
||||
return false;
|
||||
String accountKey=account.acct;
|
||||
if(!accountKey.contains("@"))
|
||||
accountKey+="@"+AccountSessionManager.get(accountID).domain;
|
||||
return getPreReplyPrefs().getBoolean("opt_out_"+type+"_"+accountKey.toLowerCase(), false);
|
||||
}
|
||||
|
||||
public static void optOutOfPreReplySheet(PreReplySheetType type, Account account, String accountID){
|
||||
String key;
|
||||
if(account==null){
|
||||
key="opt_out_"+type;
|
||||
}else{
|
||||
String accountKey=account.acct;
|
||||
if(!accountKey.contains("@"))
|
||||
accountKey+="@"+AccountSessionManager.get(accountID).domain;
|
||||
key="opt_out_"+type+"_"+accountKey.toLowerCase();
|
||||
}
|
||||
getPreReplyPrefs().edit().putBoolean(key, true).apply();
|
||||
}
|
||||
|
||||
public static void resetPreReplySheets(){
|
||||
getPreReplyPrefs().edit().clear().apply();
|
||||
}
|
||||
|
||||
public enum ThemePreference{
|
||||
AUTO,
|
||||
LIGHT,
|
||||
DARK
|
||||
}
|
||||
|
||||
public enum PreReplySheetType{
|
||||
OLD_POST,
|
||||
NON_MUTUAL
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,12 @@ import android.view.WindowInsets;
|
|||
import android.widget.Toolbar;
|
||||
|
||||
import org.joinmastodon.android.E;
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
||||
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
|
||||
import org.joinmastodon.android.api.requests.statuses.TranslateStatus;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.events.PollUpdatedEvent;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.DisplayItemsParent;
|
||||
|
@ -27,6 +29,8 @@ import org.joinmastodon.android.model.Status;
|
|||
import org.joinmastodon.android.model.Translation;
|
||||
import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.NonMutualPreReplySheet;
|
||||
import org.joinmastodon.android.ui.OldPostPreReplySheet;
|
||||
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
|
||||
|
@ -43,6 +47,8 @@ import org.joinmastodon.android.ui.utils.MediaAttachmentViewController;
|
|||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.utils.TypedObjectPool;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -106,6 +112,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
for(T s:items){
|
||||
displayItems.addAll(buildDisplayItems(s));
|
||||
}
|
||||
loadRelationships(items.stream().map(DisplayItemsParent::getAccountID).filter(Objects::nonNull).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,6 +134,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
}
|
||||
if(notify)
|
||||
adapter.notifyItemRangeInserted(0, offset);
|
||||
loadRelationships(items.stream().map(DisplayItemsParent::getAccountID).filter(Objects::nonNull).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
protected String getMaxID(){
|
||||
|
@ -455,6 +463,9 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
}
|
||||
|
||||
protected void loadRelationships(Set<String> ids){
|
||||
if(ids.isEmpty())
|
||||
return;
|
||||
ids=ids.stream().filter(id->!relationships.containsKey(id)).collect(Collectors.toSet());
|
||||
if(ids.isEmpty())
|
||||
return;
|
||||
// TODO somehow manage these and cancel outstanding requests on refresh
|
||||
|
@ -641,6 +652,26 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void maybeShowPreReplySheet(Status status, Runnable proceed){
|
||||
Relationship rel=getRelationship(status.account.id);
|
||||
if(!GlobalUserPreferences.isOptedOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.NON_MUTUAL, status.account, accountID) &&
|
||||
!status.account.id.equals(AccountSessionManager.get(accountID).self.id) && rel!=null && !rel.followedBy && status.account.followingCount>=1){
|
||||
new NonMutualPreReplySheet(getActivity(), notAgain->{
|
||||
GlobalUserPreferences.optOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.NON_MUTUAL, notAgain ? null : status.account, accountID);
|
||||
proceed.run();
|
||||
}, status.account).show();
|
||||
}else if(!GlobalUserPreferences.isOptedOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.OLD_POST, null, null) &&
|
||||
status.createdAt.isBefore(Instant.now().minus(90, ChronoUnit.DAYS))){
|
||||
new OldPostPreReplySheet(getActivity(), notAgain->{
|
||||
if(notAgain)
|
||||
GlobalUserPreferences.optOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.OLD_POST, null, null);
|
||||
proceed.run();
|
||||
}, status).show();
|
||||
}else{
|
||||
proceed.run();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onModifyItemViewHolder(BindableViewHolder<StatusDisplayItem> holder){}
|
||||
|
||||
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
|
||||
|
|
|
@ -210,11 +210,13 @@ public class ThreadFragment extends StatusListFragment{
|
|||
}
|
||||
|
||||
private void openReply(){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putParcelable("replyTo", Parcels.wrap(mainStatus));
|
||||
args.putBoolean("fromThreadFragment", true);
|
||||
Nav.go(getActivity(), ComposeFragment.class, args);
|
||||
maybeShowPreReplySheet(mainStatus, ()->{
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putParcelable("replyTo", Parcels.wrap(mainStatus));
|
||||
args.putBoolean("fromThreadFragment", true);
|
||||
Nav.go(getActivity(), ComposeFragment.class, args);
|
||||
});
|
||||
}
|
||||
|
||||
public int getSnackbarOffset(){
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package org.joinmastodon.android.fragments.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.api.session.AccountActivationInfo;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
|
@ -28,7 +27,8 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
|
|||
new ListItem<>("Test email confirmation flow", null, this::onTestEmailConfirmClick),
|
||||
selfUpdateItem=new ListItem<>("Force self-update", null, this::onForceSelfUpdateClick),
|
||||
resetUpdateItem=new ListItem<>("Reset self-updater", null, this::onResetUpdaterClick),
|
||||
new ListItem<>("Reset search info banners", null, this::onResetDiscoverBannersClick)
|
||||
new ListItem<>("Reset search info banners", null, this::onResetDiscoverBannersClick),
|
||||
new ListItem<>("Reset pre-reply sheets", null, this::onResetPreReplySheetsClick)
|
||||
));
|
||||
if(!GithubSelfUpdater.needSelfUpdating()){
|
||||
resetUpdateItem.isEnabled=selfUpdateItem.isEnabled=false;
|
||||
|
@ -65,6 +65,11 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
|
|||
restartUI();
|
||||
}
|
||||
|
||||
private void onResetPreReplySheetsClick(ListItem<?> item){
|
||||
GlobalUserPreferences.resetPreReplySheets();
|
||||
Toast.makeText(getActivity(), "Pre-reply sheets were reset", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private void restartUI(){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
|
|
|
@ -5,4 +5,8 @@ package org.joinmastodon.android.model;
|
|||
*/
|
||||
public interface DisplayItemsParent{
|
||||
String getID();
|
||||
|
||||
default String getAccountID(){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,11 @@ public class Notification extends BaseModel implements DisplayItemsParent{
|
|||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccountID(){
|
||||
return status!=null ? account.id : null;
|
||||
}
|
||||
|
||||
public enum Type{
|
||||
@SerializedName("follow")
|
||||
FOLLOW,
|
||||
|
|
|
@ -34,10 +34,18 @@ public class SearchResult extends BaseModel implements DisplayItemsParent{
|
|||
generateID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID(){
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccountID(){
|
||||
if(type==Type.STATUS)
|
||||
return status.getAccountID();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
super.postprocess();
|
||||
|
|
|
@ -143,6 +143,11 @@ public class Status extends BaseModel implements DisplayItemsParent{
|
|||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccountID(){
|
||||
return getContentStatus().account.id;
|
||||
}
|
||||
|
||||
public void update(StatusCountersUpdatedEvent ev){
|
||||
favouritesCount=ev.favorites;
|
||||
reblogsCount=ev.reblogs;
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
package org.joinmastodon.android.ui;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.TextAppearanceSpan;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.AccountField;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import me.grishka.appkit.imageloader.ViewImageLoader;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class NonMutualPreReplySheet extends PreReplySheet{
|
||||
@SuppressLint("DefaultLocale")
|
||||
public NonMutualPreReplySheet(@NonNull Context context, ResultListener resultListener, Account account){
|
||||
super(context, resultListener);
|
||||
icon.setImageResource(R.drawable.ic_waving_hand_24px);
|
||||
title.setText(R.string.non_mutual_sheet_title);
|
||||
text.setText(R.string.non_mutual_sheet_text);
|
||||
|
||||
LinearLayout userInfo=new LinearLayout(context);
|
||||
userInfo.setOrientation(LinearLayout.HORIZONTAL);
|
||||
userInfo.setBackgroundResource(R.drawable.bg_user_info);
|
||||
UiUtils.setAllPaddings(userInfo, 12);
|
||||
|
||||
ImageView ava=new ImageView(context);
|
||||
ava.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
ava.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
ava.setOutlineProvider(OutlineProviders.roundedRect(12));
|
||||
ava.setClipToOutline(true);
|
||||
ava.setForeground(context.getResources().getDrawable(R.drawable.fg_user_info_ava, context.getTheme()));
|
||||
userInfo.addView(ava, UiUtils.makeLayoutParams(56, 56, 0, 0, 12, 0));
|
||||
ViewImageLoader.loadWithoutAnimation(ava, context.getResources().getDrawable(R.drawable.image_placeholder), new UrlImageLoaderRequest(account.avatarStatic, V.dp(56), V.dp(56)));
|
||||
|
||||
LinearLayout nameAndFields=new LinearLayout(context);
|
||||
nameAndFields.setOrientation(LinearLayout.VERTICAL);
|
||||
nameAndFields.setMinimumHeight(V.dp(56));
|
||||
nameAndFields.setGravity(Gravity.CENTER_VERTICAL);
|
||||
userInfo.addView(nameAndFields, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
TextView name=new TextView(context);
|
||||
name.setSingleLine();
|
||||
name.setEllipsize(TextUtils.TruncateAt.END);
|
||||
name.setTextAppearance(R.style.m3_title_medium);
|
||||
name.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3OnSurface));
|
||||
name.setText(account.displayName);
|
||||
name.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
|
||||
nameAndFields.addView(name, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(24)));
|
||||
if(account.fields!=null && !account.fields.isEmpty()){
|
||||
for(AccountField field:account.fields){
|
||||
LinearLayout fieldView=new LinearLayout(context);
|
||||
fieldView.setOrientation(LinearLayout.HORIZONTAL);
|
||||
TextView key=new TextView(context);
|
||||
key.setTextAppearance(R.style.m3_body_medium);
|
||||
key.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
|
||||
key.setSingleLine();
|
||||
key.setEllipsize(TextUtils.TruncateAt.END);
|
||||
key.setText(field.name);
|
||||
key.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
|
||||
key.setPaddingRelative(0, 0, V.dp(8), 0);
|
||||
fieldView.addView(key, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
TextView value=new TextView(context);
|
||||
value.setTextAppearance(R.style.m3_body_medium);
|
||||
value.setTypeface(Typeface.create("sans-serif-medium", Typeface.NORMAL));
|
||||
value.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
|
||||
value.setSingleLine();
|
||||
value.setEllipsize(TextUtils.TruncateAt.END);
|
||||
value.setText(HtmlParser.stripAndRemoveInvisibleSpans(field.value));
|
||||
value.setGravity(Gravity.CENTER_VERTICAL | Gravity.END);
|
||||
fieldView.addView(value, new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
|
||||
nameAndFields.addView(fieldView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(20)));
|
||||
}
|
||||
}else{
|
||||
TextView username=new TextView(context);
|
||||
username.setTextAppearance(R.style.m3_body_medium);
|
||||
username.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
|
||||
username.setSingleLine();
|
||||
username.setEllipsize(TextUtils.TruncateAt.END);
|
||||
username.setText(account.getDisplayUsername());
|
||||
username.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
|
||||
nameAndFields.addView(username, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(20)));
|
||||
}
|
||||
|
||||
contentWrap.addView(userInfo, UiUtils.makeLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0, 0, 8));
|
||||
|
||||
for(int i=0;i<3;i++){
|
||||
View item=context.getSystemService(LayoutInflater.class).inflate(R.layout.item_other_numbered_rule, contentWrap, false);
|
||||
TextView number=item.findViewById(R.id.number);
|
||||
number.setText(String.format("%d", i+1));
|
||||
TextView title=item.findViewById(R.id.title);
|
||||
TextView text=item.findViewById(R.id.text);
|
||||
title.setText(switch(i){
|
||||
case 0 -> R.string.non_mutual_title1;
|
||||
case 1 -> R.string.non_mutual_title2;
|
||||
case 2 -> R.string.non_mutual_title3;
|
||||
default -> throw new IllegalStateException("Unexpected value: "+i);
|
||||
});
|
||||
text.setText(switch(i){
|
||||
case 0 -> R.string.non_mutual_text1;
|
||||
case 1 -> R.string.non_mutual_text2;
|
||||
case 2 -> R.string.non_mutual_text3;
|
||||
default -> throw new IllegalStateException("Unexpected value: "+i);
|
||||
});
|
||||
contentWrap.addView(item);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.joinmastodon.android.ui;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class OldPostPreReplySheet extends PreReplySheet{
|
||||
public OldPostPreReplySheet(@NonNull Context context, ResultListener resultListener, Status status){
|
||||
super(context, resultListener);
|
||||
int months=(int)status.createdAt.atZone(ZoneId.systemDefault()).until(ZonedDateTime.now(), ChronoUnit.MONTHS);
|
||||
String monthsStr=months>24 ? context.getString(R.string.more_than_two_years) : context.getResources().getQuantityString(R.plurals.x_months, months, months);
|
||||
title.setText(context.getString(R.string.old_post_sheet_title, monthsStr));
|
||||
text.setText(R.string.old_post_sheet_text);
|
||||
icon.setImageResource(R.drawable.ic_history_24px);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package org.joinmastodon.android.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import me.grishka.appkit.views.BottomSheet;
|
||||
|
||||
public abstract class PreReplySheet extends BottomSheet{
|
||||
protected ImageView icon;
|
||||
protected TextView title, text;
|
||||
protected Button gotItButton, dontRemindButton;
|
||||
protected LinearLayout contentWrap;
|
||||
|
||||
public PreReplySheet(@NonNull Context context, ResultListener resultListener){
|
||||
super(context);
|
||||
|
||||
View content=context.getSystemService(LayoutInflater.class).inflate(R.layout.sheet_pre_reply, null);
|
||||
setContentView(content);
|
||||
|
||||
setNavigationBarBackground(new ColorDrawable(UiUtils.alphaBlendColors(UiUtils.getThemeColor(context, R.attr.colorM3Surface),
|
||||
UiUtils.getThemeColor(context, R.attr.colorM3Primary), 0.05f)), !UiUtils.isDarkTheme());
|
||||
|
||||
icon=findViewById(R.id.icon);
|
||||
title=findViewById(R.id.title);
|
||||
text=findViewById(R.id.text);
|
||||
gotItButton=findViewById(R.id.btn_got_it);
|
||||
dontRemindButton=findViewById(R.id.btn_dont_remind_again);
|
||||
contentWrap=findViewById(R.id.content_wrap);
|
||||
|
||||
gotItButton.setOnClickListener(v->{
|
||||
dismiss();
|
||||
resultListener.onButtonClicked(false);
|
||||
});
|
||||
dontRemindButton.setOnClickListener(v->{
|
||||
dismiss();
|
||||
resultListener.onButtonClicked(true);
|
||||
});
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ResultListener{
|
||||
void onButtonClicked(boolean notAgain);
|
||||
}
|
||||
}
|
|
@ -129,10 +129,12 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||
}
|
||||
|
||||
private void onReplyClick(View v){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", item.accountID);
|
||||
args.putParcelable("replyTo", Parcels.wrap(item.status));
|
||||
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
||||
item.parentFragment.maybeShowPreReplySheet(item.status, ()->{
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", item.accountID);
|
||||
args.putParcelable("replyTo", Parcels.wrap(item.status));
|
||||
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
||||
});
|
||||
}
|
||||
|
||||
private void onBoostClick(View v){
|
||||
|
|
|
@ -115,8 +115,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||
private final TextView name, timeAndUsername, extraText;
|
||||
private final ImageView avatar, more;
|
||||
private final PopupMenu optionsMenu;
|
||||
private Relationship relationship;
|
||||
private APIRequest<?> currentRelationshipRequest;
|
||||
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
this(activity, R.layout.display_item_header, parent);
|
||||
|
@ -140,6 +138,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||
optionsMenu.getMenu().setGroupDividerEnabled(true);
|
||||
optionsMenu.setOnMenuItemClickListener(menuItem->{
|
||||
Account account=item.user;
|
||||
Relationship relationship=item.parentFragment.getRelationship(account.id);
|
||||
int id=menuItem.getItemId();
|
||||
if(id==R.id.edit){
|
||||
final Bundle args=new Bundle();
|
||||
|
@ -192,7 +191,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||
else
|
||||
progress.dismiss();
|
||||
}, rel->{
|
||||
relationship=rel;
|
||||
item.parentFragment.putRelationship(account.id, rel);
|
||||
Toast.makeText(activity, activity.getString(rel.following ? R.string.followed_user : rel.requested ? R.string.following_user_requested : R.string.unfollowed_user, account.getDisplayUsername()), Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
}else if(id==R.id.bookmark){
|
||||
|
@ -235,10 +234,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||
more.setVisibility(item.inset ? View.GONE : View.VISIBLE);
|
||||
avatar.setClickable(!item.inset);
|
||||
avatar.setContentDescription(item.parentFragment.getString(R.string.avatar_description, item.user.acct));
|
||||
if(currentRelationshipRequest!=null){
|
||||
currentRelationshipRequest.cancel();
|
||||
}
|
||||
relationship=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -272,31 +267,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||
private void onMoreClick(View v){
|
||||
updateOptionsMenu();
|
||||
optionsMenu.show();
|
||||
if(relationship==null && currentRelationshipRequest==null){
|
||||
currentRelationshipRequest=new GetAccountRelationships(Collections.singletonList(item.user.id))
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<Relationship> result){
|
||||
if(!result.isEmpty()){
|
||||
relationship=result.get(0);
|
||||
updateOptionsMenu();
|
||||
}
|
||||
currentRelationshipRequest=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
currentRelationshipRequest=null;
|
||||
}
|
||||
})
|
||||
.exec(item.parentFragment.getAccountID());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateOptionsMenu(){
|
||||
if(item.parentFragment.getActivity()==null)
|
||||
return;
|
||||
Account account=item.user;
|
||||
Relationship relationship=item.parentFragment.getRelationship(account.id);
|
||||
Menu menu=optionsMenu.getMenu();
|
||||
boolean isOwnPost=AccountSessionManager.getInstance().isSelf(item.parentFragment.getAccountID(), account);
|
||||
boolean canTranslate=item.status!=null && item.status.getContentStatus().isEligibleForTranslation();
|
||||
|
|
|
@ -204,7 +204,7 @@ public class HtmlParser{
|
|||
Document doc=Jsoup.parseBodyFragment(html);
|
||||
doc.body().select("span.invisible").remove();
|
||||
Cleaner cleaner=new Cleaner(Safelist.none());
|
||||
return cleaner.clean(doc).body().html();
|
||||
return cleaner.clean(doc).body().text();
|
||||
}
|
||||
|
||||
public static CharSequence parseLinks(String text){
|
||||
|
|
|
@ -835,4 +835,18 @@ public class UiUtils{
|
|||
Toast.makeText(context, R.string.text_copied, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setAllPaddings(View view, int paddingDp){
|
||||
int pad=V.dp(paddingDp);
|
||||
view.setPadding(pad, pad, pad, pad);
|
||||
}
|
||||
|
||||
public static ViewGroup.MarginLayoutParams makeLayoutParams(int width, int height, int marginStart, int marginTop, int marginEnd, int marginBottom){
|
||||
ViewGroup.MarginLayoutParams lp=new ViewGroup.MarginLayoutParams(width>0 ? V.dp(width) : width, height>0 ? V.dp(height) : height);
|
||||
lp.topMargin=V.dp(marginTop);
|
||||
lp.bottomMargin=V.dp(marginBottom);
|
||||
lp.setMarginStart(V.dp(marginStart));
|
||||
lp.setMarginEnd(V.dp(marginEnd));
|
||||
return lp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="12dp"/>
|
||||
<solid android:color="?colorM3SurfaceVariant"/>
|
||||
<stroke android:color="?colorM3OutlineVariant" android:width="1dp"/>
|
||||
</shape>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<stroke android:width="1dp" android:color="?colorM3OutlineVariant"/>
|
||||
<corners android:radius="11dp"/>
|
||||
</shape>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M17,23Q19.5,23 21.25,21.25Q23,19.5 23,17H21.5Q21.5,18.875 20.188,20.188Q18.875,21.5 17,21.5ZM1,7H2.5Q2.5,5.125 3.812,3.812Q5.125,2.5 7,2.5V1Q4.5,1 2.75,2.75Q1,4.5 1,7ZM3.525,20.475Q1.025,17.975 1.025,14.475Q1.025,10.975 3.525,8.475L7.05,4.925Q7.775,4.2 8.812,4.2Q9.85,4.2 10.575,4.925Q10.675,5.025 10.763,5.125Q10.85,5.225 10.9,5.325L13.425,2.8Q14.15,2.075 15.188,2.075Q16.225,2.075 16.95,2.8Q17.075,2.925 17.15,3.025Q17.225,3.125 17.3,3.225Q18.025,2.725 18.925,2.8Q19.825,2.875 20.475,3.525Q21.05,4.1 21.175,4.837Q21.3,5.575 21,6.3Q21.15,6.375 21.288,6.475Q21.425,6.575 21.55,6.7Q22.275,7.425 22.275,8.463Q22.275,9.5 21.55,10.225L21.15,10.625Q21.25,10.675 21.35,10.762Q21.45,10.85 21.55,10.95Q22.275,11.675 22.275,12.712Q22.275,13.75 21.55,14.475L15.525,20.475Q13.025,22.975 9.525,22.975Q6.025,22.975 3.525,20.475ZM4.925,19.075Q5.875,20.025 7.075,20.5Q8.275,20.975 9.525,20.975Q10.775,20.975 11.975,20.5Q13.175,20.025 14.125,19.075L20.125,13.05Q20.275,12.9 20.275,12.7Q20.275,12.5 20.125,12.35Q19.975,12.2 19.775,12.2Q19.575,12.2 19.425,12.35L15.9,15.9L14.475,14.475L20.125,8.825Q20.275,8.675 20.275,8.462Q20.275,8.25 20.125,8.1Q19.975,7.975 19.775,7.962Q19.575,7.95 19.425,8.1L14.475,13.05L13.05,11.65L19.075,5.625Q19.225,5.475 19.225,5.275Q19.225,5.075 19.075,4.925Q18.925,4.775 18.725,4.775Q18.525,4.775 18.375,4.925L12.35,10.95L10.95,9.525L15.525,4.925Q15.675,4.775 15.675,4.575Q15.675,4.375 15.525,4.225Q15.4,4.075 15.188,4.075Q14.975,4.075 14.825,4.225L8.525,10.525Q9.05,11.875 8.775,13.337Q8.5,14.8 7.4,15.9L6,14.475Q6.875,13.6 6.875,12.35Q6.875,11.1 6,10.225L9.175,7.05Q9.325,6.9 9.325,6.7Q9.325,6.5 9.175,6.35Q9.025,6.2 8.825,6.212Q8.625,6.225 8.475,6.35L4.925,9.875Q3.975,10.825 3.5,12.025Q3.025,13.225 3.025,14.475Q3.025,15.725 3.5,16.925Q3.975,18.125 4.925,19.075Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="8dp"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/number"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="?colorM3Primary"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:textStyle="bold"
|
||||
android:textSize="22dp"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
tools:text="1"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/number"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
android:minHeight="20sp"
|
||||
android:gravity="center_vertical|start"
|
||||
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/number"
|
||||
android:layout_below="@id/title"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:paddingVertical="2sp"
|
||||
android:lineSpacingExtra="4sp"
|
||||
android:gravity="start"
|
||||
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.joinmastodon.android.ui.views.CustomScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_bottom_sheet">
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<View
|
||||
android:id="@+id/handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="36dp"
|
||||
android:background="@drawable/bg_bottom_sheet_handle"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_below="@id/handle"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/white_circle"
|
||||
android:backgroundTint="?colorM3PrimaryContainer"
|
||||
android:scaleType="center"
|
||||
android:tint="?colorM3OnPrimaryContainer"
|
||||
tools:src="@drawable/ic_waving_hand_24px"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/icon"
|
||||
android:layout_below="@id/handle"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textAppearance="@style/m3_title_large"
|
||||
android:fontFamily="sans-serif"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="@string/non_mutual_sheet_title"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_toEndOf="@id/icon"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
tools:text="@string/non_mutual_sheet_text"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/content_wrap"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/text"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:minHeight="8dp"
|
||||
android:orientation="vertical"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_got_it"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_below="@id/content_wrap"
|
||||
android:layout_marginBottom="8dp"
|
||||
style="@style/Widget.Mastodon.M3.Button.Tonal"
|
||||
android:text="@string/got_it"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_dont_remind_again"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_below="@id/btn_got_it"
|
||||
android:layout_marginBottom="8dp"
|
||||
style="@style/Widget.Mastodon.M3.Button.Text"
|
||||
android:text="@string/dont_remind_again"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</org.joinmastodon.android.ui.views.CustomScrollView>
|
|
@ -658,4 +658,22 @@
|
|||
<string name="list_find_users">Find users to add</string>
|
||||
<string name="reply_to_user">Reply to %s</string>
|
||||
<string name="posted_at">Posted at %s</string>
|
||||
<string name="non_mutual_sheet_title">Hello, new connection!</string>
|
||||
<string name="non_mutual_sheet_text">Looks like you’re about to reply to someone who isn’t a mutual connection yet. Let’s make a great first impression.</string>
|
||||
<string name="got_it">Got it</string>
|
||||
<string name="dont_remind_again">Don’t remind me again</string>
|
||||
<!-- %s is a time interval ("5 months") -->
|
||||
<string name="old_post_sheet_title">This post is %s old</string>
|
||||
<string name="old_post_sheet_text">You can still reply, but it may no longer be relevant.</string>
|
||||
<plurals name="x_months">
|
||||
<item quantity="one">%,d month</item>
|
||||
<item quantity="other">%,d months</item>
|
||||
</plurals>
|
||||
<string name="more_than_two_years">more than 2 years</string>
|
||||
<string name="non_mutual_title1">Stay respectful & relevant</string>
|
||||
<string name="non_mutual_text1">Ensure your reply is courteous and on-topic.</string>
|
||||
<string name="non_mutual_title2">Embrace kindness</string>
|
||||
<string name="non_mutual_text2">A positive tone is always appreciated.</string>
|
||||
<string name="non_mutual_title3">Be open</string>
|
||||
<string name="non_mutual_text3">Everyone’s conversation style is unique. Be ready to adapt.</string>
|
||||
</resources>
|
Loading…
Reference in New Issue