From 255ec2e8c0edb68ec6272cfdb422ee6a70e119ca Mon Sep 17 00:00:00 2001 From: Kosh Sergani Date: Wed, 9 Aug 2017 18:16:26 +0800 Subject: [PATCH] added GitHub's profile pinned repo --- README.md | 3 +- app/src/main/graphql/pr/PinnedRepos.graphql | 28 ++++++ .../ui/adapter/ProfilePinnedReposAdapter.kt | 24 +++++ .../ProfilePinnedReposViewHolder.kt | 50 ++++++++++ .../viewholder/PullRequestEventViewHolder.kt | 4 +- .../overview/ProfileOverviewFragment.java | 31 +++++- .../profile/overview/ProfileOverviewMvp.java | 6 ++ .../overview/ProfileOverviewPresenter.java | 43 +++++++- .../PullRequestTimelinePresenter.java | 4 - .../res/drawable/ic_pull_requests_small.xml | 9 ++ .../layout/profile_overview_layout.xml | 38 ++++++++ .../layout/profile_pinned_repo_row_item.xml | 97 +++++++++++++++++++ 12 files changed, 324 insertions(+), 13 deletions(-) create mode 100644 app/src/main/graphql/pr/PinnedRepos.graphql create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/ProfilePinnedReposAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt create mode 100644 app/src/main/res/drawable/ic_pull_requests_small.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/profile_pinned_repo_row_item.xml diff --git a/README.md b/README.md index 6a4eeb05..dbea73aa 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ We have configured snapshots of FastHub, which can be downloaded from [AppVeyor - Markdown and code highlighting support - Notifications overview and "Mark all as read" - Search users/orgs, repos, issues/prs & code. - - Pinned Repos + - FastHub & GitHub Pinned Repos - Trending - Wiki - **Repositories** @@ -73,6 +73,7 @@ We have configured snapshots of FastHub, which can be downloaded from [AppVeyor - Teams & Teams repos - Repos - **Users** + - GitHub Pinned Repos - Follow/Unfollow users - View user feeds - Contribution graph. diff --git a/app/src/main/graphql/pr/PinnedRepos.graphql b/app/src/main/graphql/pr/PinnedRepos.graphql new file mode 100644 index 00000000..cd91505c --- /dev/null +++ b/app/src/main/graphql/pr/PinnedRepos.graphql @@ -0,0 +1,28 @@ +query getPinnedRepos($login: String!) { + user(login: $login) { + pinnedRepositories(first: 100) { + edges { + node { + name + url + issues(states: OPEN) { + totalCount + } + pullRequests(states: OPEN) { + totalCount + } + stargazers { + totalCount + } + forks { + totalCount + } + primaryLanguage { + name + color + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/ProfilePinnedReposAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/ProfilePinnedReposAdapter.kt new file mode 100644 index 00000000..f6ad0808 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/ProfilePinnedReposAdapter.kt @@ -0,0 +1,24 @@ +package com.fastaccess.ui.adapter + +import android.view.ViewGroup +import com.fastaccess.ui.adapter.viewholder.ProfilePinnedReposViewHolder +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder +import pr.GetPinnedReposQuery + +/** + * Created by kosh on 09/08/2017. + */ + +class ProfilePinnedReposAdapter(data: List) : BaseRecyclerAdapter>(data) { + + override fun viewHolder(parent: ViewGroup, viewType: Int): ProfilePinnedReposViewHolder { + return ProfilePinnedReposViewHolder.newInstance(parent, this) + } + + override fun onBindView(holder: ProfilePinnedReposViewHolder, position: Int) { + holder.bind(data[position]) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt new file mode 100644 index 00000000..b53c9982 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt @@ -0,0 +1,50 @@ +package com.fastaccess.ui.adapter.viewholder + +import android.graphics.Color +import android.view.View +import android.view.ViewGroup +import butterknife.BindView +import com.fastaccess.R +import com.fastaccess.ui.widgets.FontTextView +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder +import pr.GetPinnedReposQuery + +/** + * Created by kosh on 09/08/2017. + */ +class ProfilePinnedReposViewHolder private constructor(view: View, adapter: BaseRecyclerAdapter<*, *, *>) : + BaseViewHolder(view, adapter) { + + @BindView(R.id.title) lateinit var title: FontTextView + @BindView(R.id.issues) lateinit var issues: FontTextView + @BindView(R.id.pullRequests) lateinit var pullRequest: FontTextView + @BindView(R.id.language) lateinit var language: FontTextView + @BindView(R.id.stars) lateinit var stars: FontTextView + @BindView(R.id.forks) lateinit var forks: FontTextView + + override fun bind(t: GetPinnedReposQuery.Node) { + title.text = t.name() + issues.text = "${t.issues().totalCount()}" + pullRequest.text = "${t.pullRequests().totalCount()}" + forks.text = "${t.forks().totalCount()}" + stars.text = "${t.stargazers().totalCount()}" + t.primaryLanguage()?.let { + language.text = it.name() + it.color()?.let { + if (it.startsWith("#")) { + language.tintDrawables(Color.parseColor(it)) + } else { + val color = "#$it" + language.tintDrawables(Color.parseColor(color)) + } + } + } + } + + companion object { + fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>): ProfilePinnedReposViewHolder { + return ProfilePinnedReposViewHolder(getView(parent, R.layout.profile_pinned_repo_row_item), adapter) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestEventViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestEventViewHolder.kt index 2a61c4a0..28e7b942 100644 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestEventViewHolder.kt +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestEventViewHolder.kt @@ -26,7 +26,7 @@ import pr.PullRequestTimelineQuery * Created by kosh on 03/08/2017. */ -class PullRequestEventViewHolder private constructor(private val view: View, adapter: BaseRecyclerAdapter<*, *, *>) : +class PullRequestEventViewHolder private constructor(view: View, adapter: BaseRecyclerAdapter<*, *, *>) : BaseViewHolder(view, adapter) { @BindView(R.id.stateImage) lateinit var stateImage: ForegroundImageView @@ -316,7 +316,7 @@ class PullRequestEventViewHolder private constructor(private val view: View, ada private fun commitEvent(event: PullRequestTimelineQuery.AsCommit) { event.author()?.let { stateText.text = SpannableBuilder.builder()//Review[k0shk0sh] We may want to suppress more then 3 or 4 commits. since it will clog the it - .bold(if(it.user() == null) it.name() else it.user()?.login()) + .bold(if (it.user() == null) it.name() else it.user()?.login()) .append(" ") .append("committed") .append(" ") diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewFragment.java index aa7d6db6..ccd9e760 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewFragment.java +++ b/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewFragment.java @@ -34,13 +34,16 @@ import com.fastaccess.helper.Bundler; import com.fastaccess.helper.InputHelper; import com.fastaccess.helper.ParseDateFormat; import com.fastaccess.provider.emoji.EmojiParser; +import com.fastaccess.provider.scheme.SchemeParser; import com.fastaccess.ui.adapter.ProfileOrgsAdapter; +import com.fastaccess.ui.adapter.ProfilePinnedReposAdapter; import com.fastaccess.ui.base.BaseFragment; import com.fastaccess.ui.modules.profile.ProfilePagerMvp; import com.fastaccess.ui.widgets.AvatarLayout; import com.fastaccess.ui.widgets.FontTextView; import com.fastaccess.ui.widgets.SpannableBuilder; import com.fastaccess.ui.widgets.contributions.GitHubContributionsView; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; import com.fastaccess.ui.widgets.recyclerview.layout_manager.GridManager; @@ -48,6 +51,7 @@ import java.util.List; import butterknife.BindView; import butterknife.OnClick; +import pr.GetPinnedReposQuery; import static android.view.Gravity.TOP; import static android.view.View.GONE; @@ -78,12 +82,15 @@ public class ProfileOverviewFragment extends BaseFragment nodes) { + if (!nodes.isEmpty()) { + pinnedReposTextView.setVisibility(VISIBLE); + pinnedReposCard.setVisibility(VISIBLE); + ProfilePinnedReposAdapter adapter = new ProfilePinnedReposAdapter(nodes); + adapter.setListener(new BaseViewHolder.OnItemClickListener() { + @Override public void onItemClick(int position, View v, GetPinnedReposQuery.Node item) { + SchemeParser.launchUri(getContext(), item.url().toString()); + } + + @Override public void onItemLongClick(int position, View v, GetPinnedReposQuery.Node item) {} + }); + pinnedList.addDivider(); + pinnedList.setAdapter(adapter); + } else { + pinnedReposTextView.setVisibility(GONE); + pinnedReposCard.setVisibility(GONE); + } + } + @Override public void showProgress(@StringRes int resId) { progress.setVisibility(VISIBLE); } @@ -331,5 +359,4 @@ public class ProfileOverviewFragment extends BaseFragment nodes); } interface Presenter extends BaseMvp.FAPresenter { @@ -57,6 +61,8 @@ public interface ProfileOverviewMvp { @NonNull ArrayList getContributions(); + @NonNull ArrayList getNodes(); + @NonNull String getLogin(); } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewPresenter.java index 726363e8..fcc43eba 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewPresenter.java +++ b/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewPresenter.java @@ -6,6 +6,9 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; +import com.apollographql.apollo.ApolloCall; +import com.apollographql.apollo.rx2.Rx2Apollo; +import com.fastaccess.App; import com.fastaccess.data.dao.model.Login; import com.fastaccess.data.dao.model.User; import com.fastaccess.helper.BundleConstant; @@ -21,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import io.reactivex.Observable; +import pr.GetPinnedReposQuery; /** * Created by Kosh on 03 Dec 2016, 9:16 AM @@ -30,7 +34,8 @@ class ProfileOverviewPresenter extends BasePresenter im @com.evernote.android.state.State boolean isSuccessResponse; @com.evernote.android.state.State boolean isFollowing; @com.evernote.android.state.State String login; - @com.evernote.android.state.State ArrayList userOrgs = new ArrayList<>(); + private ArrayList userOrgs = new ArrayList<>(); + private ArrayList nodes = new ArrayList<>(); private ArrayList contributions = new ArrayList<>(); private static final String URL = "https://github.com/users/%s/contributions"; @@ -83,9 +88,12 @@ class ProfileOverviewPresenter extends BasePresenter im } login = bundle.getString(BundleConstant.EXTRA); if (login != null) { - loadOrgs(); -// loadUrlBackgroundImage(); - makeRestCall(RestProvider.getUserService(isEnterprise()).getUser(login), userModel -> { + makeRestCall(RestProvider.getUserService(isEnterprise()) + .getUser(login) + .doOnComplete(() -> { + loadPinnedRepos(login); + loadOrgs(); + }), userModel -> { onSendUserToView(userModel); if (userModel != null) { userModel.save(userModel); @@ -97,6 +105,29 @@ class ProfileOverviewPresenter extends BasePresenter im } } + @SuppressWarnings("ConstantConditions") private void loadPinnedRepos(@NonNull String login) { + ApolloCall apolloCall = App.getInstance().getApolloClient() + .query(GetPinnedReposQuery.builder() + .login(login) + .build()); + manageObservable(Rx2Apollo.from(apolloCall) + .filter(dataResponse -> !dataResponse.hasErrors()) + .flatMap(dataResponse -> { + if (dataResponse.data() != null && dataResponse.data().user() != null) { + return Observable.fromIterable(dataResponse.data().user().pinnedRepositories().edges()); + } + return Observable.empty(); + }) + .map(GetPinnedReposQuery.Edge::node) + .toList() + .toObservable() + .doOnNext(nodes1 -> { + nodes.clear(); + nodes.addAll(nodes1); + sendToView(view -> view.onInitPinnedRepos(nodes)); + })); + } + @Override public void onWorkOffline(@NonNull String login) { User userModel = User.getUser(login); if (userModel == null) { @@ -134,6 +165,10 @@ class ProfileOverviewPresenter extends BasePresenter im return contributions; } + @NonNull @Override public ArrayList getNodes() { + return nodes; + } + @NonNull @Override public String getLogin() { return login; } diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelinePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelinePresenter.java index b24d03bc..e9deb08a 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelinePresenter.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelinePresenter.java @@ -314,10 +314,6 @@ public class PullRequestTimelinePresenter extends BasePresenter apolloCall = App.getInstance().getApolloClient().query(query); Observable observable = Rx2Apollo.from(apolloCall) .flatMap(response -> { diff --git a/app/src/main/res/drawable/ic_pull_requests_small.xml b/app/src/main/res/drawable/ic_pull_requests_small.xml new file mode 100644 index 00000000..6ce1a1ba --- /dev/null +++ b/app/src/main/res/drawable/ic_pull_requests_small.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/profile_overview_layout.xml b/app/src/main/res/layouts/row_layouts/layout/profile_overview_layout.xml index e893d0d4..238c8511 100644 --- a/app/src/main/res/layouts/row_layouts/layout/profile_overview_layout.xml +++ b/app/src/main/res/layouts/row_layouts/layout/profile_overview_layout.xml @@ -277,12 +277,50 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:nestedScrollingEnabled="false" app:layoutManager="@string/grid_layout_manager" app:spanCount="3" tools:listitem="@layout/profile_org_row_item"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file