/* * 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.issue; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import com.meisolsson.githubsdk.core.ServiceGenerator; import com.meisolsson.githubsdk.model.Issue; import com.meisolsson.githubsdk.model.Repository; import com.meisolsson.githubsdk.model.User; import com.github.pockethub.android.Intents.Builder; import com.github.pockethub.android.R; import com.github.pockethub.android.core.issue.IssueStore; import com.github.pockethub.android.core.issue.IssueUtils; import com.github.pockethub.android.ui.FragmentProvider; import com.github.pockethub.android.ui.PagerActivity; import com.github.pockethub.android.ui.ViewPager; import com.github.pockethub.android.ui.repo.RepositoryViewActivity; import com.github.pockethub.android.ui.user.UriLauncherActivity; import com.github.pockethub.android.util.AvatarLoader; import com.github.pockethub.android.util.InfoUtils; import com.meisolsson.githubsdk.service.repositories.RepositoryService; import com.google.inject.Inject; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.concurrent.atomic.AtomicReference; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP; import static com.github.pockethub.android.Intents.EXTRA_ISSUE_NUMBERS; import static com.github.pockethub.android.Intents.EXTRA_POSITION; import static com.github.pockethub.android.Intents.EXTRA_REPOSITORIES; import static com.github.pockethub.android.Intents.EXTRA_REPOSITORY; /** * 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.number(); 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<Repository> repos = new ArrayList<>(count); int index = 0; for (Issue issue : issues) { numbers[index] = issue.number(); pullRequests[index] = IssueUtils.isPullRequest(issue); index++; Repository repoId = null; Repository issueRepo = issue.repository(); if (issueRepo != null) { User owner = issueRepo.owner(); if (owner != null) { repoId = InfoUtils.createRepoFromData(owner.login(), issueRepo.name()); } } if (repoId == null) { repoId = InfoUtils.createRepoFromUrl(issue.htmlUrl()); } 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<Repository> repoIds; private Repository repo; @Inject private AvatarLoader avatars; @Inject private IssueStore store; private final AtomicReference<User> user = new AtomicReference<>(); private boolean canWrite; private IssuesPagerAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); issueNumbers = getIntArrayExtra(EXTRA_ISSUE_NUMBERS); pullRequests = getBooleanArrayExtra(EXTRA_PULL_REQUESTS); repoIds = getIntent().getParcelableArrayListExtra(EXTRA_REPOSITORIES); repo = getParcelableExtra(EXTRA_REPOSITORY); setContentView(R.layout.activity_pager); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); getSupportActionBar().setDisplayHomeAsUpEnabled(true); if (repo != null) { ActionBar actionBar = getSupportActionBar(); actionBar.setSubtitle(InfoUtils.createRepoId(repo)); user.set(repo.owner()); avatars.bind(actionBar, user); } // Load avatar if single issue and user is currently unset or missing // avatar URL if (repo == null) { Repository temp = repo != null ? repo : repoIds.get(0); ServiceGenerator.createService(this, RepositoryService.class) .getRepository(temp.owner().login(), temp.name()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .compose(this.bindToLifecycle()) .subscribe(response -> repositoryLoaded(response.body())); } else { repositoryLoaded(repo); } } private void repositoryLoaded(Repository repo) { if (issueNumbers.length == 1 && (user.get() == null || user.get().avatarUrl() == null)) { avatars.bind(getSupportActionBar(), repo.owner()); } canWrite = repo.permissions() != null && (repo.permissions().admin() || repo.permissions().push()); invalidateOptionsMenu(); configurePager(); } private void configurePager() { int initialPosition = getIntExtra(EXTRA_POSITION); pager = (ViewPager) findViewById(R.id.vp_pages); if (repo != null) { adapter = new IssuesPagerAdapter(this, repo, issueNumbers, canWrite); } else { adapter = new IssuesPagerAdapter(this, repoIds, issueNumbers, store, canWrite); } 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(R.string.pull_request_title) + number); } else { getSupportActionBar().setTitle( getString(R.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(); repo = repoIds.get(position); if (repo != null) { updateTitle(position); actionBar.setSubtitle(InfoUtils.createRepoId(repo)); Issue issue = store.getIssue(repo, issueNumbers[position]); if (issue != null) { Repository fullRepo = issue.repository(); if (fullRepo != null && fullRepo.owner() != null) { user.set(fullRepo.owner()); 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 = UriLauncherActivity.convert(intent); if (converted != null) { super.startActivity(converted); } else { super.startActivity(intent); } } @Override protected FragmentProvider getProvider() { return adapter; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Repository repository = repo; if (repository == null) { int position = pager.getCurrentItem(); Repository repoId = repoIds.get(position); if (repoId != null) { Issue issue = store.getIssue(repoId, issueNumbers[position]); if (issue != null) { repository = issue.repository(); } } } 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); } } }