diff --git a/mastodon/build.gradle b/mastodon/build.gradle index eb899785a..232c0561d 100644 --- a/mastodon/build.gradle +++ b/mastodon/build.gradle @@ -32,10 +32,12 @@ dependencies { implementation 'me.grishka.litex:recyclerview:1.2.1' implementation 'me.grishka.litex:swiperefreshlayout:1.1.0' implementation 'me.grishka.litex:browser:1.4.0' - implementation 'me.grishka.appkit:appkit:1.1.1' + implementation 'me.grishka.appkit:appkit:1.2' implementation 'com.google.code.gson:gson:2.8.9' implementation 'org.jsoup:jsoup:1.14.3' implementation 'com.squareup:otto:1.3.8' implementation 'de.psdev:async-otto:1.0.3' + implementation 'org.parceler:parceler-api:1.1.12' + annotationProcessor 'org.parceler:parceler:1.1.12' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' } \ No newline at end of file diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/GetAccountStatuses.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/GetAccountStatuses.java new file mode 100644 index 000000000..85f534ccc --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/GetAccountStatuses.java @@ -0,0 +1,20 @@ +package org.joinmastodon.android.api.requests.accounts; + +import com.google.gson.reflect.TypeToken; + +import org.joinmastodon.android.api.MastodonAPIRequest; +import org.joinmastodon.android.model.Status; + +import java.util.List; + +public class GetAccountStatuses extends MastodonAPIRequest>{ + public GetAccountStatuses(String id, String maxID, String minID, int limit){ + super(HttpMethod.GET, "/accounts/"+id+"/statuses", new TypeToken<>(){}); + if(maxID!=null) + addQueryParameter("max_id", maxID); + if(minID!=null) + addQueryParameter("min_id", minID); + if(limit>0) + addQueryParameter("limit", ""+limit); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java index b07ded75d..f2606413c 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java @@ -21,14 +21,12 @@ import me.grishka.appkit.Nav; import me.grishka.appkit.api.SimpleCallback; public class HomeTimelineFragment extends StatusListFragment{ - private String accountID; @Override public void onAttach(Activity activity){ super.onAttach(activity); setTitle(R.string.app_name); setHasOptionsMenu(true); - accountID=getArguments().getString("account"); loadData(); } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java new file mode 100644 index 000000000..388f3d5fb --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java @@ -0,0 +1,44 @@ +package org.joinmastodon.android.fragments; + +import android.app.Activity; +import android.os.Bundle; + +import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses; +import org.joinmastodon.android.model.Account; +import org.joinmastodon.android.model.Status; +import org.parceler.Parcels; + +import java.util.List; + +import me.grishka.appkit.api.SimpleCallback; + +public class ProfileFragment extends StatusListFragment{ + private Account user; + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + user=Parcels.unwrap(getArguments().getParcelable("profileAccount")); + setTitle("@"+user.acct); + loadData(); + } + + @Override + protected void doLoadData(int offset, int count){ + String maxID; + if(offset>0 && !preloadedData.isEmpty()) + maxID=preloadedData.get(preloadedData.size()-1).id; + else if(offset>0 && !data.isEmpty()) + maxID=data.get(data.size()-1).id; + else + maxID=null; + currentRequest=new GetAccountStatuses(user.id, maxID, null, count) + .setCallback(new SimpleCallback<>(this){ + @Override + public void onSuccess(List result){ + onDataLoaded(result, !result.isEmpty()); + } + }) + .exec(accountID); + } +} 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 5d92ffc8c..087aad61f 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java @@ -1,5 +1,6 @@ package org.joinmastodon.android.fragments; +import android.app.Activity; import android.view.ViewGroup; import org.joinmastodon.android.model.Status; @@ -19,7 +20,8 @@ import me.grishka.appkit.views.UsableRecyclerView; public abstract class StatusListFragment extends BaseRecyclerFragment{ protected ArrayList displayItems=new ArrayList<>(); - private DisplayItemsAdapter adapter; + protected DisplayItemsAdapter adapter; + protected String accountID; public StatusListFragment(){ super(20); @@ -30,11 +32,17 @@ public abstract class StatusListFragment extends BaseRecyclerFragment{ return adapter=new DisplayItemsAdapter(); } + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + accountID=getArguments().getString("account"); + } + @Override public void onAppendItems(List items){ super.onAppendItems(items); for(Status s:items){ - displayItems.addAll(StatusDisplayItem.buildItems(this, s)); + displayItems.addAll(StatusDisplayItem.buildItems(this, s, accountID)); } } @@ -48,7 +56,7 @@ public abstract class StatusListFragment extends BaseRecyclerFragment{ data.addAll(0, items); int offset=0; for(Status s:items){ - List toAdd=StatusDisplayItem.buildItems(this, s); + List toAdd=StatusDisplayItem.buildItems(this, s, accountID); displayItems.addAll(offset, toAdd); offset+=toAdd.size(); } diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/Account.java b/mastodon/src/main/java/org/joinmastodon/android/model/Account.java index a1239f7c7..4d64a053c 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/Account.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/Account.java @@ -2,6 +2,7 @@ package org.joinmastodon.android.model; import org.joinmastodon.android.api.ObjectValidationException; import org.joinmastodon.android.api.RequiredField; +import org.parceler.Parcel; import java.time.Instant; import java.time.LocalDate; @@ -10,6 +11,7 @@ import java.util.List; /** * Represents a user of Mastodon and their associated profile. */ +@Parcel public class Account extends BaseModel{ // Base attributes diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/AccountField.java b/mastodon/src/main/java/org/joinmastodon/android/model/AccountField.java index c3c8879f2..5e55301d7 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/AccountField.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/AccountField.java @@ -1,12 +1,14 @@ package org.joinmastodon.android.model; import org.joinmastodon.android.api.RequiredField; +import org.parceler.Parcel; import java.time.Instant; /** * Represents a profile field as a name-value pair with optional verification. */ +@Parcel public class AccountField extends BaseModel{ /** * The key of a given field's key-value pair. diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/Emoji.java b/mastodon/src/main/java/org/joinmastodon/android/model/Emoji.java index 18b78712b..88ccc19de 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/Emoji.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/Emoji.java @@ -1,10 +1,12 @@ package org.joinmastodon.android.model; import org.joinmastodon.android.api.RequiredField; +import org.parceler.Parcel; /** * Represents a custom emoji. */ +@Parcel public class Emoji extends BaseModel{ /** * The name of the custom emoji. diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/Source.java b/mastodon/src/main/java/org/joinmastodon/android/model/Source.java index 99ebf017e..6307d0ccd 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/Source.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/Source.java @@ -2,12 +2,14 @@ package org.joinmastodon.android.model; import org.joinmastodon.android.api.ObjectValidationException; import org.joinmastodon.android.api.RequiredField; +import org.parceler.Parcel; import java.util.List; /** * Represents display or publishing preferences of user's own account. Returned as an additional entity when verifying and updated credentials, as an attribute of Account. */ +@Parcel public class Source extends BaseModel{ /** * Profile bio. diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java index 63fce984a..c0dc75c81 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java @@ -1,19 +1,24 @@ package org.joinmastodon.android.ui.displayitems; import android.app.Activity; -import android.graphics.Bitmap; +import android.app.Fragment; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import org.joinmastodon.android.R; +import org.joinmastodon.android.fragments.ProfileFragment; import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Status; +import org.parceler.Parcels; import java.time.Instant; +import me.grishka.appkit.Nav; import me.grishka.appkit.imageloader.ImageLoaderViewHolder; import me.grishka.appkit.imageloader.requests.ImageLoaderRequest; import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest; @@ -23,12 +28,16 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ private Account user; private Instant createdAt; private ImageLoaderRequest avaRequest; + private Fragment parentFragment; + private String accountID; - public HeaderStatusDisplayItem(Status status, Account user, Instant createdAt){ + public HeaderStatusDisplayItem(Status status, Account user, Instant createdAt, Fragment parentFragment, String accountID){ super(status); this.user=user; this.createdAt=createdAt; avaRequest=new UrlImageLoaderRequest(user.avatar); + this.parentFragment=parentFragment; + this.accountID=accountID; } @Override @@ -54,6 +63,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ name=findViewById(R.id.name); subtitle=findViewById(R.id.subtitle); avatar=findViewById(R.id.avatar); + avatar.setOnClickListener(this::onAvaClick); } @Override @@ -73,5 +83,12 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ public void clearImage(int index){ avatar.setImageBitmap(null); } + + private void onAvaClick(View v){ + Bundle args=new Bundle(); + args.putString("account", item.accountID); + args.putParcelable("profileAccount", Parcels.wrap(item.user)); + Nav.go(item.parentFragment.getActivity(), ProfileFragment.class, args); + } } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java index e3fd309e4..652bae63d 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java @@ -42,13 +42,13 @@ public abstract class StatusDisplayItem{ }; } - public static List buildItems(Fragment fragment, Status status){ + public static List buildItems(Fragment fragment, Status status, String accountID){ ArrayList items=new ArrayList<>(); Status statusForContent=status.reblog==null ? status : status.reblog; if(status.reblog!=null){ items.add(new ReblogOrReplyLineStatusDisplayItem(status)); } - items.add(new HeaderStatusDisplayItem(status, statusForContent.account, statusForContent.createdAt)); + items.add(new HeaderStatusDisplayItem(status, statusForContent.account, statusForContent.createdAt, fragment, accountID)); if(!TextUtils.isEmpty(statusForContent.content)) items.add(new TextStatusDisplayItem(status, HtmlParser.parse(statusForContent.content, statusForContent.emojis), fragment)); for(Attachment attachment:statusForContent.mediaAttachments){