/*
* Copyright 2012 GitHub Inc.
*
* 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.mobile.ui.issue;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static com.github.mobile.Intents.EXTRA_ISSUE;
import static com.github.mobile.Intents.EXTRA_REPOSITORY_NAME;
import static com.github.mobile.Intents.EXTRA_REPOSITORY_OWNER;
import static com.github.mobile.Intents.EXTRA_USER;
import static com.github.mobile.RequestCodes.ISSUE_ASSIGNEE_UPDATE;
import static com.github.mobile.RequestCodes.ISSUE_LABELS_UPDATE;
import static com.github.mobile.RequestCodes.ISSUE_MILESTONE_UPDATE;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.github.mobile.Intents.Builder;
import com.github.mobile.R.id;
import com.github.mobile.R.layout;
import com.github.mobile.R.menu;
import com.github.mobile.R.string;
import com.github.mobile.core.issue.IssueUtils;
import com.github.mobile.ui.DialogFragmentActivity;
import com.github.mobile.ui.StyledText;
import com.github.mobile.ui.TextWatcherAdapter;
import com.github.mobile.util.AvatarLoader;
import com.google.inject.Inject;
import java.util.List;
import org.eclipse.egit.github.core.Issue;
import org.eclipse.egit.github.core.Label;
import org.eclipse.egit.github.core.Milestone;
import org.eclipse.egit.github.core.Repository;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.User;
import org.eclipse.egit.github.core.service.CollaboratorService;
import org.eclipse.egit.github.core.service.LabelService;
import org.eclipse.egit.github.core.service.MilestoneService;
/**
* Activity to edit or create an issue
*/
public class EditIssueActivity extends DialogFragmentActivity {
/**
* Create intent to create an issue
*
* @param repository
* @return intent
*/
public static Intent createIntent(Repository repository) {
return createIntent(null, repository.getOwner().getLogin(),
repository.getName(), repository.getOwner());
}
/**
* Create intent to edit an issue
*
* @param issue
* @param repositoryOwner
* @param repositoryName
* @param user
* @return intent
*/
public static Intent createIntent(final Issue issue,
final String repositoryOwner, final String repositoryName,
final User user) {
Builder builder = new Builder("repo.issues.edit.VIEW");
if (user != null)
builder.add(EXTRA_USER, user);
builder.add(EXTRA_REPOSITORY_NAME, repositoryName);
builder.add(EXTRA_REPOSITORY_OWNER, repositoryOwner);
if (issue != null)
builder.issue(issue);
return builder.toIntent();
}
private EditText titleText;
private EditText bodyText;
private View milestoneGraph;
private TextView milestoneText;
private View milestoneClosed;
private ImageView assigneeAvatar;
private TextView assigneeText;
private TextView labelsText;
@Inject
private AvatarLoader avatars;
@Inject
private MilestoneService milestoneService;
@Inject
private CollaboratorService collaboratorService;
@Inject
private LabelService labelService;
private Issue issue;
private RepositoryId repository;
private MenuItem saveItem;
private MilestoneDialog milestoneDialog;
private AssigneeDialog assigneeDialog;
private LabelsDialog labelsDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout.issue_edit);
titleText = finder.find(id.et_issue_title);
bodyText = finder.find(id.et_issue_body);
milestoneGraph = finder.find(id.ll_milestone_graph);
milestoneText = finder.find(id.tv_milestone);
milestoneClosed = finder.find(id.v_closed);
assigneeAvatar = finder.find(id.iv_assignee_avatar);
assigneeText = finder.find(id.tv_assignee_name);
labelsText = finder.find(id.tv_labels);
Intent intent = getIntent();
if (savedInstanceState != null)
issue = (Issue) savedInstanceState.getSerializable(EXTRA_ISSUE);
if (issue == null)
issue = (Issue) intent.getSerializableExtra(EXTRA_ISSUE);
if (issue == null)
issue = new Issue();
repository = RepositoryId.create(
intent.getStringExtra(EXTRA_REPOSITORY_OWNER),
intent.getStringExtra(EXTRA_REPOSITORY_NAME));
ActionBar actionBar = getSupportActionBar();
if (issue.getNumber() > 0)
if (IssueUtils.isPullRequest(issue))
actionBar.setTitle(getString(string.pull_request_title)
+ issue.getNumber());
else
actionBar.setTitle(getString(string.issue_title)
+ issue.getNumber());
else
actionBar.setTitle(string.new_issue);
actionBar.setSubtitle(repository.generateId());
avatars.bind(actionBar, (User) intent.getSerializableExtra(EXTRA_USER));
findViewById(id.ll_milestone).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (milestoneDialog == null)
milestoneDialog = new MilestoneDialog(
EditIssueActivity.this, ISSUE_MILESTONE_UPDATE,
repository, milestoneService);
milestoneDialog.show(issue.getMilestone());
}
});
findViewById(id.ll_assignee).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (assigneeDialog == null)
assigneeDialog = new AssigneeDialog(EditIssueActivity.this,
ISSUE_ASSIGNEE_UPDATE, repository,
collaboratorService);
assigneeDialog.show(issue.getAssignee());
}
});
findViewById(id.ll_labels).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (labelsDialog == null)
labelsDialog = new LabelsDialog(EditIssueActivity.this,
ISSUE_LABELS_UPDATE, repository, labelService);
labelsDialog.show(issue.getLabels());
}
});
titleText.addTextChangedListener(new TextWatcherAdapter() {
@Override
public void afterTextChanged(Editable s) {
updateSaveMenu(s);
}
});
updateSaveMenu();
updateView();
}
@Override
public void onDialogResult(int requestCode, int resultCode, Bundle arguments) {
if (RESULT_OK != resultCode)
return;
switch (requestCode) {
case ISSUE_MILESTONE_UPDATE:
issue.setMilestone(MilestoneDialogFragment.getSelected(arguments));
updateMilestone();
break;
case ISSUE_ASSIGNEE_UPDATE:
User assignee = AssigneeDialogFragment.getSelected(arguments);
if (assignee != null)
issue.setAssignee(assignee);
else
issue.setAssignee(new User().setLogin(""));
updateAssignee();
break;
case ISSUE_LABELS_UPDATE:
issue.setLabels(LabelsDialogFragment.getSelected(arguments));
updateLabels();
break;
}
}
private void updateMilestone() {
Milestone milestone = issue.getMilestone();
if (milestone != null) {
milestoneText.setText(milestone.getTitle());
float closed = milestone.getClosedIssues();
float total = closed + milestone.getOpenIssues();
if (total > 0) {
((LayoutParams) milestoneClosed.getLayoutParams()).weight = closed
/ total;
milestoneClosed.setVisibility(VISIBLE);
} else
milestoneClosed.setVisibility(GONE);
milestoneGraph.setVisibility(VISIBLE);
} else {
milestoneText.setText(string.none);
milestoneGraph.setVisibility(GONE);
}
}
private void updateAssignee() {
User assignee = issue.getAssignee();
String login = assignee != null ? assignee.getLogin() : null;
if (!TextUtils.isEmpty(login)) {
assigneeText.setText(new StyledText().bold(login));
assigneeAvatar.setVisibility(VISIBLE);
avatars.bind(assigneeAvatar, assignee);
} else {
assigneeAvatar.setVisibility(GONE);
assigneeText.setText(string.unassigned);
}
}
private void updateLabels() {
List<Label> labels = issue.getLabels();
if (labels != null && !labels.isEmpty())
LabelDrawableSpan.setText(labelsText, labels);
else
labelsText.setText(string.none);
}
private void updateView() {
titleText.setText(issue.getTitle());
bodyText.setText(issue.getBody());
updateAssignee();
updateLabels();
updateMilestone();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(EXTRA_ISSUE, issue);
}
private void updateSaveMenu() {
if (titleText != null)
updateSaveMenu(titleText.getText());
}
private void updateSaveMenu(final CharSequence text) {
if (saveItem != null)
saveItem.setEnabled(!TextUtils.isEmpty(text));
}
@Override
public boolean onCreateOptionsMenu(Menu options) {
getSupportMenuInflater().inflate(menu.issue_edit, options);
saveItem = options.findItem(id.m_apply);
updateSaveMenu();
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case id.m_apply:
issue.setTitle(titleText.getText().toString());
issue.setBody(bodyText.getText().toString());
if (issue.getNumber() > 0)
new EditIssueTask(this, repository, issue) {
@Override
protected void onSuccess(Issue editedIssue)
throws Exception {
super.onSuccess(editedIssue);
Intent intent = new Intent();
intent.putExtra(EXTRA_ISSUE, editedIssue);
setResult(RESULT_OK, intent);
finish();
}
}.edit();
else
new CreateIssueTask(this, repository, issue) {
@Override
protected void onSuccess(Issue created) throws Exception {
super.onSuccess(created);
Intent intent = new Intent();
intent.putExtra(EXTRA_ISSUE, created);
setResult(RESULT_OK, intent);
finish();
}
}.create();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}