Thread view
This commit is contained in:
parent
eed64f48fe
commit
3e605253e9
|
@ -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<StatusContext>{
|
||||
public GetStatusContext(String id){
|
||||
super(HttpMethod.GET, "/statuses/"+id+"/context", StatusContext.class);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -335,14 +335,14 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
return displayItems.get(position).getImageRequest(image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(@NonNull BindableViewHolder<StatusDisplayItem> holder){
|
||||
if(holder instanceof ImageLoaderViewHolder){
|
||||
int count=holder.getItem().getImageCount();
|
||||
for(int i=0;i<count;i++){
|
||||
((ImageLoaderViewHolder) holder).clearImage(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
// @Override
|
||||
// public void onViewDetachedFromWindow(@NonNull BindableViewHolder<StatusDisplayItem> holder){
|
||||
// if(holder instanceof ImageLoaderViewHolder){
|
||||
// int count=holder.getItem().getImageCount();
|
||||
// for(int i=0;i<count;i++){
|
||||
// ((ImageLoaderViewHolder) holder).clearImage(i);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.joinmastodon.android.model.Status;
|
|||
import org.joinmastodon.android.ui.CustomEmojiPopupKeyboard;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.PopupKeyboard;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.views.SizeListenerLinearLayout;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
|
@ -150,7 +151,7 @@ public class ComposeFragment extends ToolbarFragment implements OnBackPressedLis
|
|||
selfName=view.findViewById(R.id.name);
|
||||
selfUsername=view.findViewById(R.id.username);
|
||||
selfAvatar=view.findViewById(R.id.avatar);
|
||||
selfName.setText(self.displayName);
|
||||
HtmlParser.setTextWithCustomEmoji(selfName, self.displayName, self.emojis);
|
||||
selfUsername.setText('@'+self.username+'@'+instanceDomain);
|
||||
ViewImageLoader.load(selfAvatar, null, new UrlImageLoaderRequest(self.avatar));
|
||||
ViewOutlineProvider roundCornersOutline=new ViewOutlineProvider(){
|
||||
|
|
|
@ -80,6 +80,8 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
|
|||
args.putString("account", accountID);
|
||||
homeTimelineFragment=new HomeTimelineFragment();
|
||||
homeTimelineFragment.setArguments(args);
|
||||
args=new Bundle(args);
|
||||
args.putBoolean("noAutoLoad", true);
|
||||
searchFragment=new SearchFragment();
|
||||
searchFragment.setArguments(args);
|
||||
notificationsFragment=new NotificationsFragment();
|
||||
|
@ -150,7 +152,7 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
|
|||
getChildFragmentManager().beginTransaction().hide(fragmentForTab(currentTab)).show(newFragment).commit();
|
||||
if(newFragment instanceof LoaderFragment){
|
||||
LoaderFragment lf=(LoaderFragment) newFragment;
|
||||
if(!lf.loaded)
|
||||
if(!lf.loaded && !lf.dataLoading)
|
||||
lf.loadData();
|
||||
}
|
||||
currentTab=tab;
|
||||
|
|
|
@ -45,7 +45,7 @@ public class HomeTimelineFragment extends StatusListFragment{
|
|||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
new GetHomeTimeline(offset>0 ? getMaxID() : null, null, count)
|
||||
currentRequest=new GetHomeTimeline(offset>0 ? getMaxID() : null, null, count)
|
||||
.setCallback(new SimpleCallback<>(this){
|
||||
@Override
|
||||
public void onSuccess(List<Status> 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));
|
||||
|
|
|
@ -60,4 +60,11 @@ public class NotificationsFragment extends BaseStatusListFragment<Notification>{
|
|||
})
|
||||
.exec(accountID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShown(){
|
||||
super.onShown();
|
||||
if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading)
|
||||
loadData();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Status>{
|
||||
protected List<StatusDisplayItem> buildDisplayItems(Status s){
|
||||
|
@ -37,6 +39,25 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
|
|||
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){
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<Status> ancestors;
|
||||
public List<Status> descendants;
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
super.postprocess();
|
||||
for(Status s:ancestors)
|
||||
s.postprocess();
|
||||
for(Status s:descendants)
|
||||
s.postprocess();
|
||||
}
|
||||
}
|
|
@ -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<Emoji> emojis){
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder(text);
|
||||
parseCustomEmoji(ssb, emojis);
|
||||
return ssb;
|
||||
}
|
||||
|
||||
public static void setTextWithCustomEmoji(TextView view, String text, List<Emoji> emojis){
|
||||
if(!EMOJI_CODE_PATTERN.matcher(text).find()){
|
||||
view.setText(text);
|
||||
return;
|
||||
}
|
||||
view.setText(parseCustomEmoji(text, emojis));
|
||||
UiUtils.loadCustomEmojiInTextView(view);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,4 +72,5 @@
|
|||
<string name="field_label">Label</string>
|
||||
<string name="field_content">Content</string>
|
||||
<string name="saving">Saving…</string>
|
||||
<string name="post_from_user">Post from %s</string>
|
||||
</resources>
|
Loading…
Reference in New Issue