/*
* 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.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static com.github.mobile.Intents.EXTRA_ISSUE_NUMBERS;
import static com.github.mobile.Intents.EXTRA_POSITION;
import static com.github.mobile.Intents.EXTRA_REPOSITORIES;
import static com.github.mobile.Intents.EXTRA_REPOSITORY;
import android.accounts.Account;
import android.content.Intent;
import android.os.Bundle;
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.string;
import com.github.mobile.accounts.AccountUtils;
import com.github.mobile.accounts.AuthenticatedUserTask;
import com.github.mobile.core.issue.IssueStore;
import com.github.mobile.core.issue.IssueUtils;
import com.github.mobile.core.repo.RefreshRepositoryTask;
import com.github.mobile.ui.FragmentProvider;
import com.github.mobile.ui.PagerActivity;
import com.github.mobile.ui.UrlLauncher;
import com.github.mobile.ui.ViewPager;
import com.github.mobile.ui.repo.RepositoryViewActivity;
import com.github.mobile.util.AvatarLoader;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.egit.github.core.Issue;
import org.eclipse.egit.github.core.Repository;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.RepositoryIssue;
import org.eclipse.egit.github.core.User;
import org.eclipse.egit.github.core.service.CollaboratorService;
/**
* Activity to display a collection of issues or pull requests in a pager
*/
public class IssuesViewActivity extends PagerActivity {
private static final String EXTRA_PULL_REQUESTS = "pullRequests";
/**
* Create an intent to show a single issue
*
* @param issue
* @return intent
*/
public static Intent createIntent(final Issue issue) {
return createIntent(Collections.singletonList(issue), 0);
}
/**
* Create an intent to show issue
*
* @param issue
* @param repository
* @return intent
*/
public static Intent createIntent(final Issue issue,
final Repository repository) {
return createIntent(Collections.singletonList(issue), repository, 0);
}
/**
* Create an intent to show issues with an initial selected issue
*
* @param issues
* @param repository
* @param position
* @return intent
*/
public static Intent createIntent(final Collection<? extends Issue> issues,
final Repository repository, final int position) {
int[] numbers = new int[issues.size()];
boolean[] pullRequests = new boolean[issues.size()];
int index = 0;
for (Issue issue : issues) {
numbers[index] = issue.getNumber();
pullRequests[index] = IssueUtils.isPullRequest(issue);
index++;
}
return new Builder("issues.VIEW").add(EXTRA_ISSUE_NUMBERS, numbers)
.add(EXTRA_REPOSITORY, repository)
.add(EXTRA_POSITION, position)
.add(EXTRA_PULL_REQUESTS, pullRequests).toIntent();
}
/**
* Create an intent to show issues with an initial selected issue
*
* @param issues
* @param position
* @return intent
*/
public static Intent createIntent(Collection<? extends Issue> issues,
int position) {
final int count = issues.size();
int[] numbers = new int[count];
boolean[] pullRequests = new boolean[count];
ArrayList<RepositoryId> repos = new ArrayList<RepositoryId>(count);
int index = 0;
for (Issue issue : issues) {
numbers[index] = issue.getNumber();
pullRequests[index] = IssueUtils.isPullRequest(issue);
index++;
RepositoryId repoId = null;
if (issue instanceof RepositoryIssue) {
Repository issueRepo = ((RepositoryIssue) issue)
.getRepository();
if (issueRepo != null) {
User owner = issueRepo.getOwner();
if (owner != null)
repoId = RepositoryId.create(owner.getLogin(),
issueRepo.getName());
}
}
if (repoId == null)
repoId = RepositoryId.createFromUrl(issue.getHtmlUrl());
repos.add(repoId);
}
Builder builder = new Builder("issues.VIEW");
builder.add(EXTRA_ISSUE_NUMBERS, numbers);
builder.add(EXTRA_REPOSITORIES, repos);
builder.add(EXTRA_POSITION, position);
builder.add(EXTRA_PULL_REQUESTS, pullRequests);
return builder.toIntent();
}
private ViewPager pager;
private int[] issueNumbers;
private boolean[] pullRequests;
private ArrayList<RepositoryId> repoIds;
private Repository repo;
@Inject
private AvatarLoader avatars;
@Inject
private IssueStore store;
@Inject
private CollaboratorService collaboratorService;
private final AtomicReference<User> user = new AtomicReference<User>();
private boolean isCollaborator;
private IssuesPagerAdapter adapter;
private final UrlLauncher urlLauncher = new UrlLauncher(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
issueNumbers = getIntArrayExtra(EXTRA_ISSUE_NUMBERS);
pullRequests = getBooleanArrayExtra(EXTRA_PULL_REQUESTS);
repoIds = getSerializableExtra(EXTRA_REPOSITORIES);
repo = getSerializableExtra(EXTRA_REPOSITORY);
setContentView(layout.pager);
if (repo != null) {
ActionBar actionBar = getSupportActionBar();
actionBar.setSubtitle(repo.generateId());
user.set(repo.getOwner());
avatars.bind(actionBar, user);
}
// Load avatar if single issue and user is currently unset or missing
// avatar URL
if (issueNumbers.length == 1
&& (user.get() == null || user.get().getAvatarUrl() == null))
new RefreshRepositoryTask(this, repo != null ? repo : repoIds.get(0)) {
@Override
protected void onSuccess(Repository fullRepository)
throws Exception {
super.onSuccess(fullRepository);
avatars.bind(getSupportActionBar(),
fullRepository.getOwner());
}
}.execute();
isCollaborator = false;
checkCollaboratorStatus();
}
private void configurePager() {
int initialPosition = getIntExtra(EXTRA_POSITION);
pager = finder.find(id.vp_pages);
if (repo != null)
adapter = new IssuesPagerAdapter(this, repo, issueNumbers, isCollaborator);
else
adapter = new IssuesPagerAdapter(this, repoIds, issueNumbers, store, isCollaborator);
pager.setAdapter(adapter);
pager.setOnPageChangeListener(this);
pager.scheduleSetItem(initialPosition, this);
onPageSelected(initialPosition);
}
private void updateTitle(final int position) {
int number = issueNumbers[position];
boolean pullRequest = pullRequests[position];
if (pullRequest)
getSupportActionBar().setTitle(
getString(string.pull_request_title) + number);
else
getSupportActionBar().setTitle(
getString(string.issue_title) + number);
}
@Override
public void onPageSelected(final int position) {
super.onPageSelected(position);
if (repo != null) {
updateTitle(position);
return;
}
if (repoIds == null)
return;
ActionBar actionBar = getSupportActionBar();
RepositoryId repoId = repoIds.get(position);
if (repoId != null) {
updateTitle(position);
actionBar.setSubtitle(repoId.generateId());
RepositoryIssue issue = store.getIssue(repoId,
issueNumbers[position]);
if (issue != null) {
Repository fullRepo = issue.getRepository();
if (fullRepo != null && fullRepo.getOwner() != null) {
user.set(fullRepo.getOwner());
avatars.bind(actionBar, user);
} else
actionBar.setLogo(null);
} else
actionBar.setLogo(null);
} else {
actionBar.setSubtitle(null);
actionBar.setLogo(null);
}
}
@Override
public void onDialogResult(int requestCode, int resultCode, Bundle arguments) {
adapter.onDialogResult(pager.getCurrentItem(), requestCode, resultCode,
arguments);
}
@Override
public void startActivity(Intent intent) {
Intent converted = urlLauncher.convert(intent);
if (converted != null)
super.startActivity(converted);
else
super.startActivity(intent);
}
@Override
protected FragmentProvider getProvider() {
return adapter;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem editItem = menu.findItem(id.m_edit);
MenuItem stateItem = menu.findItem(id.m_state);
if (editItem != null && stateItem != null) {
editItem.setVisible(isCollaborator);
stateItem.setVisible(isCollaborator);
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Repository repository = repo;
if (repository == null) {
int position = pager.getCurrentItem();
RepositoryId repoId = repoIds.get(position);
if (repoId != null) {
RepositoryIssue issue = store.getIssue(repoId,
issueNumbers[position]);
if (issue != null)
repository = issue.getRepository();
}
}
if (repository != null) {
Intent intent = RepositoryViewActivity.createIntent(repository);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP
| FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void checkCollaboratorStatus() {
new AuthenticatedUserTask<Boolean>(this) {
@Override
protected Boolean run(Account account) throws Exception {
return collaboratorService.isCollaborator(repo != null ? repo : repoIds.get(0),
AccountUtils.getLogin(IssuesViewActivity.this));
}
@Override
protected void onSuccess(Boolean collaborator) throws Exception {
super.onSuccess(collaborator);
isCollaborator = collaborator;
invalidateOptionsMenu();
configurePager();
}
}.execute();
}
}