/*
* Copyright 2011 Azwan Adli Abdullah
*
* 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.gh4a.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.StringRes;
import android.support.v4.content.Loader;
import android.text.SpannableStringBuilder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.gh4a.Gh4Application;
import com.gh4a.R;
import com.gh4a.activities.EditIssueCommentActivity;
import com.gh4a.activities.EditPullRequestCommentActivity;
import com.gh4a.activities.RepositoryActivity;
import com.gh4a.loader.CommitStatusLoader;
import com.gh4a.loader.IssueEventHolder;
import com.gh4a.loader.LoaderCallbacks;
import com.gh4a.loader.LoaderResult;
import com.gh4a.loader.PullRequestCommentListLoader;
import com.gh4a.utils.ApiHelpers;
import com.gh4a.utils.IntentUtils;
import com.gh4a.utils.StringUtils;
import com.gh4a.utils.UiUtils;
import com.gh4a.widget.IntentSpan;
import com.gh4a.widget.StyleableTextView;
import org.eclipse.egit.github.core.Comment;
import org.eclipse.egit.github.core.CommitComment;
import org.eclipse.egit.github.core.CommitStatus;
import org.eclipse.egit.github.core.Issue;
import org.eclipse.egit.github.core.PullRequest;
import org.eclipse.egit.github.core.PullRequestMarker;
import org.eclipse.egit.github.core.Repository;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.service.IssueService;
import org.eclipse.egit.github.core.service.PullRequestService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PullRequestFragment extends IssueFragmentBase {
private PullRequest mPullRequest;
private final LoaderCallbacks<List<CommitStatus>> mStatusCallback =
new LoaderCallbacks<List<CommitStatus>>(this) {
@Override
protected Loader<LoaderResult<List<CommitStatus>>> onCreateLoader() {
return new CommitStatusLoader(getActivity(), mRepoOwner, mRepoName,
mPullRequest.getHead().getSha());
}
@Override
protected void onResultReady(List<CommitStatus> result) {
fillStatus(result);
}
};
public static PullRequestFragment newInstance(PullRequest pr, Issue issue,
boolean isCollaborator, IntentUtils.InitialCommentMarker initialComment) {
PullRequestFragment f = new PullRequestFragment();
Repository repo = pr.getBase().getRepo();
Bundle args = buildArgs(repo.getOwner().getLogin(), repo.getName(),
issue, isCollaborator, initialComment);
args.putSerializable("pr", pr);
f.setArguments(args);
return f;
}
public void updateState(PullRequest pr) {
mIssue.setState(pr.getState());
mPullRequest.setState(pr.getState());
mPullRequest.setMerged(pr.isMerged());
assignHighlightColor();
loadStatusIfOpen();
reloadEvents(false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
mPullRequest = (PullRequest) getArguments().getSerializable("pr");
super.onCreate(savedInstanceState);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
loadStatusIfOpen();
}
@Override
public void onRefresh() {
if (mListHeaderView != null) {
fillStatus(new ArrayList<CommitStatus>());
}
hideContentAndRestartLoaders(1);
super.onRefresh();
}
@Override
protected void bindSpecialViews(View headerView) {
View branchGroup = headerView.findViewById(R.id.pr_container);
branchGroup.setVisibility(View.VISIBLE);
StyleableTextView fromBranch = (StyleableTextView) branchGroup.findViewById(R.id.tv_pr_from);
formatMarkerText(fromBranch, R.string.pull_request_from, mPullRequest.getHead());
StyleableTextView toBranch = (StyleableTextView) branchGroup.findViewById(R.id.tv_pr_to);
formatMarkerText(toBranch, R.string.pull_request_to, mPullRequest.getBase());
}
@Override
protected void assignHighlightColor() {
if (mPullRequest.isMerged()) {
setHighlightColors(R.attr.colorPullRequestMerged, R.attr.colorPullRequestMergedDark);
} else if (ApiHelpers.IssueState.CLOSED.equals(mPullRequest.getState())) {
setHighlightColors(R.attr.colorIssueClosed, R.attr.colorIssueClosedDark);
} else {
setHighlightColors(R.attr.colorIssueOpen, R.attr.colorIssueOpenDark);
}
}
private void formatMarkerText(StyleableTextView view,
@StringRes int formatResId, final PullRequestMarker marker) {
SpannableStringBuilder builder = StringUtils.applyBoldTags(getActivity(),
getString(formatResId), view.getTypefaceValue());
int pos = builder.toString().indexOf("[ref]");
if (pos >= 0) {
builder.replace(pos, pos + 5, marker.getLabel());
builder.setSpan(new IntentSpan(getActivity()) {
@Override
protected Intent getIntent() {
return RepositoryActivity.makeIntent(getActivity(),
marker.getRepo(), marker.getRef());
}
}, pos, pos + marker.getLabel().length(), 0);
}
view.setText(builder);
view.setMovementMethod(UiUtils.CHECKING_LINK_METHOD);
}
private void loadStatusIfOpen() {
if (ApiHelpers.IssueState.OPEN.equals(mPullRequest.getState())) {
getLoaderManager().initLoader(1, null, mStatusCallback);
}
}
private void fillStatus(List<CommitStatus> statuses) {
Map<String, CommitStatus> statusByContext = new HashMap<>();
for (CommitStatus status : statuses) {
if (!statusByContext.containsKey(status.getContext())) {
statusByContext.put(status.getContext(), status);
}
}
final int statusIconDrawableAttrId, statusLabelResId;
if (PullRequest.MERGEABLE_STATE_CLEAN.equals(mPullRequest.getMergeableState())) {
statusIconDrawableAttrId = R.attr.pullRequestMergeOkIcon;
statusLabelResId = R.string.pull_merge_status_clean;
} else if (PullRequest.MERGEABLE_STATE_UNSTABLE.equals(mPullRequest.getMergeableState())) {
statusIconDrawableAttrId = R.attr.pullRequestMergeUnstableIcon;
statusLabelResId = R.string.pull_merge_status_unstable;
} else if (PullRequest.MERGEABLE_STATE_DIRTY.equals(mPullRequest.getMergeableState())) {
statusIconDrawableAttrId = R.attr.pullRequestMergeDirtyIcon;
statusLabelResId = R.string.pull_merge_status_dirty;
} else if (statusByContext.isEmpty()) {
// unknwon status, no commit statuses -> nothing to display
return;
} else {
statusIconDrawableAttrId = R.attr.pullRequestMergeUnknownIcon;
statusLabelResId = R.string.pull_merge_status_unknown;
}
ImageView statusIcon = (ImageView) mListHeaderView.findViewById(R.id.iv_merge_status_icon);
statusIcon.setImageResource(UiUtils.resolveDrawable(getActivity(),
statusIconDrawableAttrId));
TextView statusLabel = (TextView) mListHeaderView.findViewById(R.id.merge_status_label);
statusLabel.setText(statusLabelResId);
ViewGroup statusContainer = (ViewGroup)
mListHeaderView.findViewById(R.id.merge_commit_status_container);
LayoutInflater inflater = getLayoutInflater(null);
statusContainer.removeAllViews();
for (CommitStatus status : statusByContext.values()) {
View statusRow = inflater.inflate(R.layout.row_commit_status, statusContainer, false);
String state = status.getState();
final int iconDrawableAttrId;
if (CommitStatus.STATE_ERROR.equals(state) || CommitStatus.STATE_FAILURE.equals(state)) {
iconDrawableAttrId = R.attr.commitStatusFailIcon;
} else if (CommitStatus.STATE_SUCCESS.equals(state)) {
iconDrawableAttrId = R.attr.commitStatusOkIcon;
} else {
iconDrawableAttrId = R.attr.commitStatusUnknownIcon;
}
ImageView icon = (ImageView) statusRow.findViewById(R.id.iv_status_icon);
icon.setImageResource(UiUtils.resolveDrawable(getActivity(), iconDrawableAttrId));
TextView context = (TextView) statusRow.findViewById(R.id.tv_context);
context.setText(status.getContext());
TextView description = (TextView) statusRow.findViewById(R.id.tv_desc);
description.setText(status.getDescription());
statusContainer.addView(statusRow);
}
mListHeaderView.findViewById(R.id.merge_commit_no_status).setVisibility(
statusByContext.isEmpty() ? View.VISIBLE : View.GONE);
mListHeaderView.findViewById(R.id.merge_status_container).setVisibility(View.VISIBLE);
}
@Override
public Loader<LoaderResult<List<IssueEventHolder>>> onCreateLoader() {
return new PullRequestCommentListLoader(getActivity(),
mRepoOwner, mRepoName, mPullRequest.getNumber());
}
@Override
public void editComment(IssueEventHolder item) {
Intent intent = item.comment instanceof CommitComment
? EditPullRequestCommentActivity.makeIntent(getActivity(), mRepoOwner, mRepoName,
mPullRequest.getNumber(), (CommitComment) item.comment)
: EditIssueCommentActivity.makeIntent(getActivity(), mRepoOwner, mRepoName,
mIssue.getNumber(), item.comment);
startActivityForResult(intent, REQUEST_EDIT);
}
@Override
protected void deleteCommentInBackground(RepositoryId repoId, Comment comment) throws Exception {
Gh4Application app = Gh4Application.get();
if (comment instanceof CommitComment) {
PullRequestService pullService =
(PullRequestService) app.getService(Gh4Application.PULL_SERVICE);
pullService.deleteComment(repoId, comment.getId());
} else {
IssueService issueService = (IssueService) app.getService(Gh4Application.ISSUE_SERVICE);
issueService.deleteComment(repoId, comment.getId());
}
}
@Override
public int getCommentEditorHintResId() {
return R.string.pull_request_comment_hint;
}
}