/* * Copyright (c) 2015 PocketHub * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.pockethub.android.ui; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.afollestad.materialdialogs.MaterialDialog; import com.meisolsson.githubsdk.model.Gist; import com.meisolsson.githubsdk.model.GitHubEvent; import com.meisolsson.githubsdk.model.Issue; import com.meisolsson.githubsdk.model.Release; import com.meisolsson.githubsdk.model.Repository; import com.meisolsson.githubsdk.model.User; import com.github.kevinsawicki.wishlist.SingleTypeAdapter; import com.github.pockethub.android.R; import com.github.pockethub.android.core.gist.GistEventMatcher; import com.github.pockethub.android.core.issue.IssueEventMatcher; import com.github.pockethub.android.core.repo.RepositoryEventMatcher; import com.github.pockethub.android.core.user.UserEventMatcher; import com.github.pockethub.android.core.user.UserEventMatcher.UserPair; import com.github.pockethub.android.ui.commit.CommitCompareViewActivity; import com.github.pockethub.android.ui.commit.CommitViewActivity; import com.github.pockethub.android.ui.gist.GistsViewActivity; import com.github.pockethub.android.ui.issue.IssuesViewActivity; import com.github.pockethub.android.ui.repo.RepositoryViewActivity; import com.github.pockethub.android.ui.user.NewsListAdapter; import com.github.pockethub.android.util.AvatarLoader; import com.github.pockethub.android.util.ConvertUtils; import com.github.pockethub.android.util.InfoUtils; import com.meisolsson.githubsdk.model.git.GitComment; import com.meisolsson.githubsdk.model.git.GitCommit; import com.meisolsson.githubsdk.model.payload.CommitCommentPayload; import com.meisolsson.githubsdk.model.payload.PushPayload; import com.meisolsson.githubsdk.model.payload.ReleasePayload; import com.google.inject.Inject; import java.util.List; import static android.content.Intent.ACTION_VIEW; import static android.content.Intent.CATEGORY_BROWSABLE; import static com.meisolsson.githubsdk.model.GitHubEventType.CommitCommentEvent; import static com.meisolsson.githubsdk.model.GitHubEventType.DownloadEvent; import static com.meisolsson.githubsdk.model.GitHubEventType.PushEvent; /** * Base news fragment class with utilities for subclasses to built on */ public abstract class NewsFragment extends PagedItemFragment<GitHubEvent> { /** * Matcher for finding an {@link Issue} from an {@link GitHubEvent} */ protected final IssueEventMatcher issueMatcher = new IssueEventMatcher(); /** * Matcher for finding a {@link Gist} from an {@link GitHubEvent} */ protected final GistEventMatcher gistMatcher = new GistEventMatcher(); /** * Matcher for finding a {@link Repository} from an {@link GitHubEvent} */ protected final RepositoryEventMatcher repoMatcher = new RepositoryEventMatcher(); /** * Matcher for finding a {@link User} from an {@link GitHubEvent} */ protected final UserEventMatcher userMatcher = new UserEventMatcher(); @Inject private AvatarLoader avatars; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setEmptyText(R.string.no_news); } @Override public void onListItemClick(ListView l, View v, int position, long id) { GitHubEvent event = (GitHubEvent) l.getItemAtPosition(position); if (DownloadEvent.equals(event.type())) { openDownload(event); return; } if (PushEvent.equals(event.type())) { openPush(event); return; } if (CommitCommentEvent.equals(event.type())) { openCommitComment(event); return; } Issue issue = issueMatcher.getIssue(event); if (issue != null) { Repository repo = ConvertUtils.eventRepoToRepo(event.repo()); viewIssue(issue, repo); return; } Gist gist = gistMatcher.getGist(event); if (gist != null) { startActivity(GistsViewActivity.createIntent(gist)); return; } Repository repo = repoMatcher.getRepository(event); if (repo != null) { viewRepository(repo); } UserPair users = userMatcher.getUsers(event); if (users != null) { viewUser(users); } } @Override public boolean onListItemLongClick(ListView l, View v, int position, long itemId) { if (!isUsable()) { return false; } final GitHubEvent event = (GitHubEvent) l.getItemAtPosition(position); final Repository repo = ConvertUtils.eventRepoToRepo(event.repo()); final User user = event.actor(); if (repo != null && user != null) { final MaterialDialog.Builder builder = new MaterialDialog.Builder(getActivity()) .title(R.string.navigate_to); // Hacky but necessary since material dialogs has a different API final MaterialDialog[] dialogHolder = new MaterialDialog[1]; View view = getActivity().getLayoutInflater().inflate( R.layout.nav_dialog, null); avatars.bind((ImageView) view.findViewById(R.id.iv_user_avatar), user); avatars.bind((ImageView) view.findViewById(R.id.iv_repo_avatar), repo.owner()); ((TextView) view.findViewById(R.id.tv_login)).setText(user.login()); ((TextView) view.findViewById(R.id.tv_repo_name)).setText(InfoUtils.createRepoId(repo)); view.findViewById(R.id.ll_user_area).setOnClickListener(v1 -> { dialogHolder[0].dismiss(); viewUser(user); }); view.findViewById(R.id.ll_repo_area).setOnClickListener(v1 -> { dialogHolder[0].dismiss(); viewRepository(repo); }); builder.customView(view, false); MaterialDialog dialog = builder.build(); dialogHolder[0] = dialog; dialog.setCanceledOnTouchOutside(true); dialog.show(); return true; } return false; } // https://developer.github.com/v3/repos/downloads/#downloads-api-is-deprecated private void openDownload(GitHubEvent event) { Release release = ((ReleasePayload) event.payload()).release(); if (release == null) { return; } String url = release.htmlUrl(); if (TextUtils.isEmpty(url)) { return; } Intent intent = new Intent(ACTION_VIEW, Uri.parse(url)); intent.addCategory(CATEGORY_BROWSABLE); startActivity(intent); } private void openCommitComment(GitHubEvent event) { Repository repo = ConvertUtils.eventRepoToRepo(event.repo()); if (repo == null) { return; } if(repo.name().contains("/")) { String[] repoId = repo.name().split("/"); repo = InfoUtils.createRepoFromData(repoId[0], repoId[1]); } CommitCommentPayload payload = ((CommitCommentPayload) event.payload()); GitComment comment = payload.comment(); if (comment == null) { return; } String sha = comment.commitId(); if (!TextUtils.isEmpty(sha)) { startActivity(CommitViewActivity.createIntent(repo, sha)); } } private void openPush(GitHubEvent event) { Repository repo = ConvertUtils.eventRepoToRepo(event.repo()); if (repo == null) { return; } PushPayload payload = ((PushPayload) event.payload()); List<GitCommit> commits = payload.commits(); if (commits == null || commits.isEmpty()) { return; } if (commits.size() > 1) { String base = payload.before(); String head = payload.head(); if (!TextUtils.isEmpty(base) && !TextUtils.isEmpty(head)) { startActivity(CommitCompareViewActivity.createIntent(repo, base, head)); } } else { GitCommit commit = commits.get(0); String sha = commit != null ? commit.sha() : null; if (!TextUtils.isEmpty(sha)) { startActivity(CommitViewActivity.createIntent(repo, sha)); } } } /** * Start an activity to view the given repository * * @param repository */ protected void viewRepository(Repository repository) { startActivity(RepositoryViewActivity.createIntent(repository)); } /** * Start an activity to view the given {@link UserPair} * <p> * This method does nothing by default, subclasses should override * * @param users */ protected void viewUser(UserPair users) { } /** * Start an activity to view the given {@link User} * * @param user * @return true if new activity started, false otherwise */ protected boolean viewUser(User user) { return false; } /** * Start an activity to view the given {@link Issue} * * @param issue * @param repository */ protected void viewIssue(Issue issue, Repository repository) { if (repository != null) { startActivity(IssuesViewActivity.createIntent(issue, repository)); } else { startActivity(IssuesViewActivity.createIntent(issue)); } } @Override protected SingleTypeAdapter<GitHubEvent> createAdapter(List<GitHubEvent> items) { return new NewsListAdapter(getActivity().getLayoutInflater(), items.toArray(new GitHubEvent[items.size()]), avatars); } @Override protected int getLoadingMessage() { return R.string.loading_news; } @Override protected int getErrorMessage(Exception exception) { return R.string.error_news_load; } }