Add pinned status tab (#994)

* Add pinned status tab

* Make TabLayout scrollable.
main
kyori19 6 years ago committed by Konrad Pozniak
parent 0230f79a42
commit b3a8d00093
  1. 20
      app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt
  2. 16
      app/src/main/java/com/keylesspalace/tusky/ReportActivity.java
  3. 14
      app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt
  4. 8
      app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java
  5. 6
      app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.java
  6. 11
      app/src/main/java/com/keylesspalace/tusky/pager/AccountPagerAdapter.java
  7. 2
      app/src/main/res/layout/activity_account.xml
  8. 1
      app/src/main/res/values/strings.xml

@ -16,27 +16,27 @@
package com.keylesspalace.tusky package com.keylesspalace.tusky
import android.animation.ArgbEvaluator import android.animation.ArgbEvaluator
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.Px import androidx.annotation.Px
import androidx.emoji.text.EmojiCompat import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityOptionsCompat import androidx.core.app.ActivityOptionsCompat
import androidx.fragment.app.Fragment
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.appcompat.app.AlertDialog import androidx.emoji.text.EmojiCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.appbar.CollapsingToolbarLayout
import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
@ -251,7 +251,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
// Setup the tabs and timeline pager. // Setup the tabs and timeline pager.
val adapter = AccountPagerAdapter(supportFragmentManager, accountId) val adapter = AccountPagerAdapter(supportFragmentManager, accountId)
val pageTitles = arrayOf(getString(R.string.title_statuses), getString(R.string.title_statuses_with_replies), getString(R.string.title_media)) val pageTitles = arrayOf(getString(R.string.title_statuses), getString(R.string.title_statuses_with_replies), getString(R.string.title_statuses_pinned), getString(R.string.title_media))
adapter.setPageTitles(pageTitles) adapter.setPageTitles(pageTitles)
accountFragmentViewPager.pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin) accountFragmentViewPager.pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin)
val pageMarginDrawable = ThemeUtils.getDrawable(this, R.attr.tab_page_margin_drawable, val pageMarginDrawable = ThemeUtils.getDrawable(this, R.attr.tab_page_margin_drawable,

@ -18,19 +18,13 @@ package com.keylesspalace.tusky;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.ActionBar;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.appcompat.widget.Toolbar;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import com.google.android.material.snackbar.Snackbar;
import com.keylesspalace.tusky.adapter.ReportAdapter; import com.keylesspalace.tusky.adapter.ReportAdapter;
import com.keylesspalace.tusky.di.Injectable; import com.keylesspalace.tusky.di.Injectable;
import com.keylesspalace.tusky.entity.Status; import com.keylesspalace.tusky.entity.Status;
@ -44,6 +38,12 @@ import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -189,7 +189,7 @@ public class ReportActivity extends BaseActivity implements Injectable {
onFetchStatusesFailure((Exception) t); onFetchStatusesFailure((Exception) t);
} }
}; };
mastodonApi.accountStatuses(accountId, null, null, null, null, null) mastodonApi.accountStatuses(accountId, null, null, null, null, null, null)
.enqueue(callback); .enqueue(callback);
} }

@ -17,14 +17,14 @@ package com.keylesspalace.tusky.fragment
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import androidx.core.app.ActivityOptionsCompat
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import androidx.core.app.ActivityOptionsCompat
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
@ -157,10 +157,10 @@ class AccountMediaFragment : BaseFragment(), Injectable {
if (fetchingStatus != FetchingStatus.NOT_FETCHING) return@setOnRefreshListener if (fetchingStatus != FetchingStatus.NOT_FETCHING) return@setOnRefreshListener
currentCall = if (statuses.isEmpty()) { currentCall = if (statuses.isEmpty()) {
fetchingStatus = FetchingStatus.INITIAL_FETCHING fetchingStatus = FetchingStatus.INITIAL_FETCHING
api.accountStatuses(accountId, null, null, null, null, true) api.accountStatuses(accountId, null, null, null, null, true, null)
} else { } else {
fetchingStatus = FetchingStatus.REFRESHING fetchingStatus = FetchingStatus.REFRESHING
api.accountStatuses(accountId, null, statuses[0].id, null, null, true) api.accountStatuses(accountId, null, statuses[0].id, null, null, true, null)
} }
currentCall?.enqueue(callback) currentCall?.enqueue(callback)
@ -180,7 +180,7 @@ class AccountMediaFragment : BaseFragment(), Injectable {
statuses.lastOrNull()?.let { last -> statuses.lastOrNull()?.let { last ->
Log.d(TAG, "Requesting statuses with max_id: ${last.id}, (bottom)") Log.d(TAG, "Requesting statuses with max_id: ${last.id}, (bottom)")
fetchingStatus = FetchingStatus.FETCHING_BOTTOM fetchingStatus = FetchingStatus.FETCHING_BOTTOM
currentCall = api.accountStatuses(accountId, last.id, null, null, null, true) currentCall = api.accountStatuses(accountId, last.id, null, null, null, true, null)
currentCall?.enqueue(bottomCallback) currentCall?.enqueue(bottomCallback)
} }
} }
@ -196,7 +196,7 @@ class AccountMediaFragment : BaseFragment(), Injectable {
val accountId = arguments?.getString(ACCOUNT_ID_ARG) val accountId = arguments?.getString(ACCOUNT_ID_ARG)
if (fetchingStatus == FetchingStatus.NOT_FETCHING && statuses.isEmpty()) { if (fetchingStatus == FetchingStatus.NOT_FETCHING && statuses.isEmpty()) {
fetchingStatus = FetchingStatus.INITIAL_FETCHING fetchingStatus = FetchingStatus.INITIAL_FETCHING
currentCall = api.accountStatuses(accountId, null, null, null, null, true) currentCall = api.accountStatuses(accountId, null, null, null, null, true, null)
currentCall?.enqueue(callback) currentCall?.enqueue(callback)
} }
} }

@ -110,6 +110,7 @@ public class TimelineFragment extends SFragment implements
PUBLIC_FEDERATED, PUBLIC_FEDERATED,
TAG, TAG,
USER, USER,
USER_PINNED,
USER_WITH_REPLIES, USER_WITH_REPLIES,
FAVOURITES, FAVOURITES,
LIST LIST
@ -201,6 +202,7 @@ public class TimelineFragment extends SFragment implements
kind = Kind.valueOf(arguments.getString(KIND_ARG)); kind = Kind.valueOf(arguments.getString(KIND_ARG));
if (kind == Kind.TAG if (kind == Kind.TAG
|| kind == Kind.USER || kind == Kind.USER
|| kind == Kind.USER_PINNED
|| kind == Kind.USER_WITH_REPLIES || kind == Kind.USER_WITH_REPLIES
|| kind == Kind.LIST) { || kind == Kind.LIST) {
hashtagOrId = arguments.getString(HASHTAG_OR_ID_ARG); hashtagOrId = arguments.getString(HASHTAG_OR_ID_ARG);
@ -847,9 +849,11 @@ public class TimelineFragment extends SFragment implements
case TAG: case TAG:
return api.hashtagTimeline(tagOrId, null, fromId, uptoId, LOAD_AT_ONCE); return api.hashtagTimeline(tagOrId, null, fromId, uptoId, LOAD_AT_ONCE);
case USER: case USER:
return api.accountStatuses(tagOrId, fromId, uptoId, LOAD_AT_ONCE, true, null); return api.accountStatuses(tagOrId, fromId, uptoId, LOAD_AT_ONCE, true, null, null);
case USER_PINNED:
return api.accountStatuses(tagOrId, fromId, uptoId, LOAD_AT_ONCE, null, null, true);
case USER_WITH_REPLIES: case USER_WITH_REPLIES:
return api.accountStatuses(tagOrId, fromId, uptoId, LOAD_AT_ONCE, null, null); return api.accountStatuses(tagOrId, fromId, uptoId, LOAD_AT_ONCE, null, null, null);
case FAVOURITES: case FAVOURITES:
return api.favourites(fromId, uptoId, LOAD_AT_ONCE); return api.favourites(fromId, uptoId, LOAD_AT_ONCE);
case LIST: case LIST:

@ -15,8 +15,6 @@
package com.keylesspalace.tusky.network; package com.keylesspalace.tusky.network;
import androidx.annotation.Nullable;
import com.keylesspalace.tusky.entity.AccessToken; import com.keylesspalace.tusky.entity.AccessToken;
import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.entity.Account;
import com.keylesspalace.tusky.entity.AppCredentials; import com.keylesspalace.tusky.entity.AppCredentials;
@ -33,6 +31,7 @@ import com.keylesspalace.tusky.entity.StatusContext;
import java.util.List; import java.util.List;
import androidx.annotation.Nullable;
import io.reactivex.Single; import io.reactivex.Single;
import okhttp3.MultipartBody; import okhttp3.MultipartBody;
import okhttp3.RequestBody; import okhttp3.RequestBody;
@ -219,7 +218,8 @@ public interface MastodonApi {
@Query("since_id") String sinceId, @Query("since_id") String sinceId,
@Query("limit") Integer limit, @Query("limit") Integer limit,
@Nullable @Query("exclude_replies") Boolean excludeReplies, @Nullable @Query("exclude_replies") Boolean excludeReplies,
@Nullable @Query("only_media") Boolean onlyMedia); @Nullable @Query("only_media") Boolean onlyMedia,
@Nullable @Query("pinned") Boolean pinned);
@GET("api/v1/accounts/{id}/followers") @GET("api/v1/accounts/{id}/followers")
Call<List<Account>> accountFollowers( Call<List<Account>> accountFollowers(

@ -15,13 +15,13 @@
package com.keylesspalace.tusky.pager; package com.keylesspalace.tusky.pager;
import com.keylesspalace.tusky.fragment.AccountMediaFragment;
import com.keylesspalace.tusky.fragment.TimelineFragment;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter; import androidx.fragment.app.FragmentPagerAdapter;
import com.keylesspalace.tusky.fragment.AccountMediaFragment;
import com.keylesspalace.tusky.fragment.TimelineFragment;
public class AccountPagerAdapter extends FragmentPagerAdapter { public class AccountPagerAdapter extends FragmentPagerAdapter {
private String accountId; private String accountId;
private String[] pageTitles; private String[] pageTitles;
@ -45,6 +45,9 @@ public class AccountPagerAdapter extends FragmentPagerAdapter {
return TimelineFragment.newInstance(TimelineFragment.Kind.USER_WITH_REPLIES, accountId); return TimelineFragment.newInstance(TimelineFragment.Kind.USER_WITH_REPLIES, accountId);
} }
case 2: { case 2: {
return TimelineFragment.newInstance(TimelineFragment.Kind.USER_PINNED, accountId);
}
case 3: {
return AccountMediaFragment.newInstance(accountId); return AccountMediaFragment.newInstance(accountId);
} }
default: { default: {
@ -55,7 +58,7 @@ public class AccountPagerAdapter extends FragmentPagerAdapter {
@Override @Override
public int getCount() { public int getCount() {
return 3; return 4;
} }
@Override @Override

@ -281,7 +281,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:colorBackground" android:background="?android:colorBackground"
app:tabGravity="center" app:tabGravity="center"
app:tabMode="fixed" app:tabMode="scrollable"
app:tabTextAppearance="@style/TuskyTabAppearance" /> app:tabTextAppearance="@style/TuskyTabAppearance" />
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>

@ -30,6 +30,7 @@
<string name="title_tag">#%s</string> <string name="title_tag">#%s</string>
<string name="title_statuses">Posts</string> <string name="title_statuses">Posts</string>
<string name="title_statuses_with_replies">With replies</string> <string name="title_statuses_with_replies">With replies</string>
<string name="title_statuses_pinned">Pinned</string>
<string name="title_follows">Follows</string> <string name="title_follows">Follows</string>
<string name="title_followers">Followers</string> <string name="title_followers">Followers</string>
<string name="title_favourites">Favourites</string> <string name="title_favourites">Favourites</string>

Loading…
Cancel
Save