From 3e605253e99a27519f6b5b469a05e1896c5c6c8c Mon Sep 17 00:00:00 2001 From: Grishka Date: Fri, 11 Feb 2022 18:16:56 +0300 Subject: [PATCH] Thread view --- .../requests/statuses/GetStatusContext.java | 10 +++ .../fragments/AccountTimelineFragment.java | 9 ++- .../fragments/BaseStatusListFragment.java | 18 ++--- .../android/fragments/ComposeFragment.java | 3 +- .../android/fragments/HomeFragment.java | 4 +- .../fragments/HomeTimelineFragment.java | 9 ++- .../fragments/NotificationsFragment.java | 7 ++ .../android/fragments/StatusListFragment.java | 21 +++++ .../android/fragments/ThreadFragment.java | 79 +++++++++++++++++++ .../android/model/StatusContext.java | 21 +++++ .../android/ui/text/HtmlParser.java | 17 ++++ mastodon/src/main/res/values/strings.xml | 1 + 12 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/GetStatusContext.java create mode 100644 mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java create mode 100644 mastodon/src/main/java/org/joinmastodon/android/model/StatusContext.java diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/GetStatusContext.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/GetStatusContext.java new file mode 100644 index 00000000..b1b5020b --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/GetStatusContext.java @@ -0,0 +1,10 @@ +package org.joinmastodon.android.api.requests.statuses; + +import org.joinmastodon.android.api.MastodonAPIRequest; +import org.joinmastodon.android.model.StatusContext; + +public class GetStatusContext extends MastodonAPIRequest{ + public GetStatusContext(String id){ + super(HttpMethod.GET, "/statuses/"+id+"/context", StatusContext.class); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java index a04eb769..8f9827eb 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java @@ -40,8 +40,6 @@ public class AccountTimelineFragment extends StatusListFragment{ super.onAttach(activity); user=Parcels.unwrap(getArguments().getParcelable("profileAccount")); filter=GetAccountStatuses.Filter.valueOf(getArguments().getString("filter")); - if(!getArguments().getBoolean("noAutoLoad")) - loadData(); } @Override @@ -60,4 +58,11 @@ public class AccountTimelineFragment extends StatusListFragment{ public void onViewCreated(View view, Bundle savedInstanceState){ super.onViewCreated(view, savedInstanceState); } + + @Override + protected void onShown(){ + super.onShown(); + if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading) + loadData(); + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java index 679b6cc0..38353861 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java @@ -335,14 +335,14 @@ public abstract class BaseStatusListFragment exten return displayItems.get(position).getImageRequest(image); } - @Override - public void onViewDetachedFromWindow(@NonNull BindableViewHolder holder){ - if(holder instanceof ImageLoaderViewHolder){ - int count=holder.getItem().getImageCount(); - for(int i=0;i holder){ +// if(holder instanceof ImageLoaderViewHolder){ +// int count=holder.getItem().getImageCount(); +// for(int i=0;i0 ? getMaxID() : null, null, count) + currentRequest=new GetHomeTimeline(offset>0 ? getMaxID() : null, null, count) .setCallback(new SimpleCallback<>(this){ @Override public void onSuccess(List result){ @@ -90,6 +90,13 @@ public class HomeTimelineFragment extends StatusListFragment{ updateToolbarLogo(); } + @Override + protected void onShown(){ + super.onShown(); + if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading) + loadData(); + } + @Subscribe public void onStatusCreated(StatusCreatedEvent ev){ prependItems(Collections.singletonList(ev.status)); diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.java index fc4c5f45..2db0c96b 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.java @@ -60,4 +60,11 @@ public class NotificationsFragment extends BaseStatusListFragment{ }) .exec(accountID); } + + @Override + protected void onShown(){ + super.onShown(); + if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading) + loadData(); + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java index f822908f..f365ff20 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java @@ -9,10 +9,12 @@ import org.joinmastodon.android.events.StatusCountersUpdatedEvent; import org.joinmastodon.android.model.Status; import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.StatusDisplayItem; +import org.parceler.Parcels; import java.util.List; import androidx.recyclerview.widget.RecyclerView; +import me.grishka.appkit.Nav; public abstract class StatusListFragment extends BaseStatusListFragment{ protected List buildDisplayItems(Status s){ @@ -37,6 +39,25 @@ public abstract class StatusListFragment extends BaseStatusListFragment{ E.unregister(this); } + @Override + public void onItemClick(String id){ + Status status=null; + for(Status s:data){ + if(s.id.equals(id)){ + status=s.getContentStatus(); + break; + } + } + if(status==null) + return; + Bundle args=new Bundle(); + args.putString("account", accountID); + args.putParcelable("status", Parcels.wrap(status)); + if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId)) + args.putParcelable("inReplyToAccount", Parcels.wrap(knownAccounts.get(status.inReplyToAccountId))); + Nav.go(getActivity(), ThreadFragment.class, args); + } + @Subscribe public void onStatusCountersUpdated(StatusCountersUpdatedEvent ev){ for(Status s:data){ diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java new file mode 100644 index 00000000..fa93df6b --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java @@ -0,0 +1,79 @@ +package org.joinmastodon.android.fragments; + +import android.app.Activity; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.view.View; + +import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.statuses.GetStatusContext; +import org.joinmastodon.android.model.Account; +import org.joinmastodon.android.model.StatusContext; +import org.joinmastodon.android.model.Status; +import org.joinmastodon.android.ui.text.HtmlParser; +import org.joinmastodon.android.ui.utils.UiUtils; +import org.parceler.Parcels; + +import java.util.Collections; + +import me.grishka.appkit.api.SimpleCallback; + +public class ThreadFragment extends StatusListFragment{ + private Status mainStatus; + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + mainStatus=Parcels.unwrap(getArguments().getParcelable("status")); + Account inReplyToAccount=Parcels.unwrap(getArguments().getParcelable("inReplyToAccount")); + if(inReplyToAccount!=null) + knownAccounts.put(inReplyToAccount.id, inReplyToAccount); + setTitle(HtmlParser.parseCustomEmoji(getString(R.string.post_from_user, mainStatus.account.displayName), mainStatus.account.emojis)); + data.add(mainStatus); + onAppendItems(Collections.singletonList(mainStatus)); + } + + @Override + protected void doLoadData(int offset, int count){ + currentRequest=new GetStatusContext(mainStatus.id) + .setCallback(new SimpleCallback<>(this){ + @Override + public void onSuccess(StatusContext result){ + if(refreshing){ + data.clear(); + displayItems.clear(); + data.add(mainStatus); + onAppendItems(Collections.singletonList(mainStatus)); + } + footerProgress.setVisibility(View.GONE); + data.addAll(result.descendants); + onAppendItems(result.descendants); + int count=displayItems.size(); + prependItems(result.ancestors); + dataLoaded(); + if(refreshing) + refreshDone(); + list.scrollToPosition(displayItems.size()-count); + } + }) + .exec(accountID); + } + + @Override + protected void onShown(){ + super.onShown(); + if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading){ + dataLoading=true; + doLoadData(); + } + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState){ + super.onViewCreated(view, savedInstanceState); + UiUtils.loadCustomEmojiInTextView(toolbarTitleView); + showContent(); + if(!loaded) + footerProgress.setVisibility(View.VISIBLE); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/StatusContext.java b/mastodon/src/main/java/org/joinmastodon/android/model/StatusContext.java new file mode 100644 index 00000000..e3add43b --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/model/StatusContext.java @@ -0,0 +1,21 @@ +package org.joinmastodon.android.model; + +import org.joinmastodon.android.api.AllFieldsAreRequired; +import org.joinmastodon.android.api.ObjectValidationException; + +import java.util.List; + +@AllFieldsAreRequired +public class StatusContext extends BaseModel{ + public List ancestors; + public List descendants; + + @Override + public void postprocess() throws ObjectValidationException{ + super.postprocess(); + for(Status s:ancestors) + s.postprocess(); + for(Status s:descendants) + s.postprocess(); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java b/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java index 6e3c32e4..d2cd4854 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java @@ -2,8 +2,10 @@ package org.joinmastodon.android.ui.text; import android.text.SpannableStringBuilder; import android.text.Spanned; +import android.widget.TextView; import org.joinmastodon.android.model.Emoji; +import org.joinmastodon.android.ui.utils.UiUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Element; import org.jsoup.nodes.Node; @@ -117,4 +119,19 @@ public class HtmlParser{ ssb.setSpan(new CustomEmojiSpan(emoji), matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } + + public static SpannableStringBuilder parseCustomEmoji(String text, List emojis){ + SpannableStringBuilder ssb=new SpannableStringBuilder(text); + parseCustomEmoji(ssb, emojis); + return ssb; + } + + public static void setTextWithCustomEmoji(TextView view, String text, List emojis){ + if(!EMOJI_CODE_PATTERN.matcher(text).find()){ + view.setText(text); + return; + } + view.setText(parseCustomEmoji(text, emojis)); + UiUtils.loadCustomEmojiInTextView(view); + } } diff --git a/mastodon/src/main/res/values/strings.xml b/mastodon/src/main/res/values/strings.xml index 2bc0da40..aa838753 100644 --- a/mastodon/src/main/res/values/strings.xml +++ b/mastodon/src/main/res/values/strings.xml @@ -72,4 +72,5 @@ Label Content Saving… + Post from %s \ No newline at end of file