package com.alorma.github.ui.activity.repo;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.AppCompatDrawableManager;
import android.support.v7.widget.ListPopupWindow;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.alorma.github.GitskariosSettings;
import com.alorma.github.R;
import com.alorma.github.injector.component.ApiComponent;
import com.alorma.github.injector.component.ApplicationComponent;
import com.alorma.github.injector.component.DaggerApiComponent;
import com.alorma.github.injector.module.ApiModule;
import com.alorma.github.injector.module.repository.RepoDetailModule;
import com.alorma.github.presenter.repo.RepositoryPresenter;
import com.alorma.github.sdk.bean.info.RepoInfo;
import com.alorma.github.ui.actions.ShareAction;
import com.alorma.github.ui.actions.ViewInAction;
import com.alorma.github.ui.fragment.base.BaseFragment;
import com.alorma.github.utils.RoundedBackgroundSpan;
import com.alorma.github.utils.ShortcutUtils;
import com.alorma.github.utils.TimeUtils;
import core.repositories.Branch;
import core.repositories.License;
import core.repositories.Repo;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
public class RepoAboutFragment extends BaseFragment implements RepositoryPresenter.RepoView {
private static final String REPO_INFO = "REPO_INFO";
@Inject RepositoryPresenter presenter;
private RepoInfo repoInfo;
@BindView(R.id.repoDetailNumbersLayout) View repoDetailNumbersLayout;
@BindView(R.id.repoDetailNumbersStar) Button repoDetailNumbersStar;
@BindView(R.id.repoDetailNumbersWatch) Button repoDetailNumbersWatch;
@BindView(R.id.repoDescriptionTextView) TextView repoDescriptionTextView;
@BindView(R.id.repoDetailBranchesLayout) View repoDetailBranchesLayout;
@BindView(R.id.repoDefaultBranchTextView) TextView repoDefaultBranchTextView;
@BindView(R.id.repoDefaultBranchInfo) TextView repoDefaultBranchInfo;
@BindView(R.id.repoDefaultBranchCodeButton) Button repoDefaultBranchCodeButton;
@BindView(R.id.repoDefaultBranchCommits) Button repoDefaultBranchCommits;
@BindView(R.id.repoDefaultBranchExpandableIcon) ImageView repoDefaultBranchExpandableIcon;
@BindView(R.id.repoDefaultOpenReadme) View repoDefaultOpenReadme;
@BindView(R.id.repoDetailTagsCount) TextView repoDetailTagsCount;
@BindView(R.id.repoDetailLicense) TextView repoDetailLicense;
private Repo currentRepo;
public static RepoAboutFragment newInstance(RepoInfo repoInfo) {
Bundle bundle = new Bundle();
bundle.putParcelable(REPO_INFO, repoInfo);
RepoAboutFragment f = new RepoAboutFragment();
f.setArguments(bundle);
return f;
}
@Override
protected int getLightTheme() {
return R.style.AppTheme_Repository;
}
@Override
protected int getDarkTheme() {
return R.style.AppTheme_Dark_Repository;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
presenter.attachView(this);
}
@Override
public void onDestroy() {
presenter.detachView();
super.onDestroy();
}
@Override
protected void injectComponents(ApplicationComponent applicationComponent) {
super.injectComponents(applicationComponent);
ApiComponent apiComponent = DaggerApiComponent.builder().applicationComponent(applicationComponent).apiModule(new ApiModule()).build();
apiComponent.plus(new RepoDetailModule()).inject(this);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.repo_overview_fragment, null, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
repoInfo = getArguments().getParcelable(REPO_INFO);
presenter.execute(repoInfo);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.repo_detail, menu);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem shareItem = menu.findItem(R.id.share_repo);
if (shareItem != null) {
Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.ic_menu_share_mtrl_alpha);
shareItem.setIcon(icon);
}
MenuItem openItem = menu.findItem(R.id.action_open_in_browser);
if (openItem != null) {
Drawable drawable = AppCompatDrawableManager.get().getDrawable(getContext(), R.drawable.ic_globe);
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable, Color.WHITE);
openItem.setIcon(drawable);
}
/*
if (currentRepo != null && currentRepo.permissions != null) {
if (currentRepo.permissions.admin) {
if (menu.findItem(R.id.action_manage_repo) == null) {
getMenuInflater().inflate(R.menu.repo_detail_activity_permissions, menu);
}
if (menu.findItem(R.id.action_subscribe_push) == null) {
getMenuInflater().inflate(R.menu.repo_detail_activity_push, menu);
}
}
}
*/
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (currentRepo != null) {
if (item.getItemId() == R.id.share_repo) {
String title = currentRepo.getFullName();
String url = currentRepo.svn_url;
new ShareAction(getContext(), title, url).setType("Repository").execute();
} else if (item.getItemId() == R.id.action_open_in_browser) {
new ViewInAction(getContext(), currentRepo.getHtmlUrl()).setType("Repository").execute();
} else if (item.getItemId() == R.id.action_add_shortcut) {
ShortcutUtils.addShortcut(getContext(), repoInfo);
}
}
/*
if (item.getItemId() == R.id.action_manage_repo) {
if (currentRepo != null) {
Intent intent = ManageRepositoryActivity.createIntent(this, requestRepoInfo, createRepoRequest());
startActivityForResult(intent, EDIT_REPO);
}
} else if (item.getItemId() == R.id.action_subscribe_push) {
}
*/
return super.onOptionsItemSelected(item);
}
/*
private RepoRequestDTO createRepoRequest() {
RepoRequestDTO dto = new RepoRequestDTO();
dto.isPrivate = currentRepo.isPrivateRepo();
dto.name = currentRepo.name;
dto.description = currentRepo.description;
dto.default_branch = currentRepo.getDefaultBranch();
dto.has_downloads = currentRepo.hasDownloads;
dto.has_wiki = currentRepo.hasWiki;
dto.has_issues = currentRepo.hasIssues;
dto.homepage = currentRepo.homepage;
return dto;
}
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
/*
if (requestCode == EDIT_REPO) {
if (resultCode == RESULT_OK && data != null) {
RepoRequestDTO repoRequestDTO = data.getParcelableExtra(ManageRepositoryActivity.CONTENT);
showProgressDialog(R.string.edit_repo_loading);
EditRepoClient editRepositoryClient = new EditRepoClient(requestRepoInfo, repoRequestDTO);
editRepositoryClient.observable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Repo>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Repo repo) {
onDataReceived(repo, false);
}
});
} else if (resultCode == RESULT_CANCELED) {
finish();
}
}
*/
}
@Override
public void showLoading() {
}
@Override
public void hideLoading() {
}
@Override
public void onDataReceived(Repo repo, boolean isFromPaginated) {
this.currentRepo = repo;
this.repoInfo = repo.toInfo();
populateDescription(repo.getDescription(), repo.getHomepage());
populateBranches(repo.getDefaultBranchObject(), repo.getBranches());
populateStar(repo.isStarred(), repo.getStargazersCount());
populateWatch(repo.isWatched(), repo.getSubscribersCount());
populateReadme();
populateLicense(repo.getLicense());
}
private void populateDescription(String description, String homepage) {
if (!TextUtils.isEmpty(description) && !TextUtils.isEmpty(homepage)) {
repoDescriptionTextView.setText(description + " - " + homepage);
} else if (!TextUtils.isEmpty(description)) {
repoDescriptionTextView.setText(description);
} else if (!TextUtils.isEmpty(homepage)) {
repoDescriptionTextView.setText(homepage);
} else {
repoDescriptionTextView.setVisibility(View.GONE);
}
}
private void populateBranches(Branch defaultBranch, List<Branch> branches) {
if (defaultBranch != null) {
repoDefaultBranchTextView.setText(defaultBranch.name);
String timeAgoString = "";
if (!TextUtils.isEmpty(defaultBranch.commit.getCommit().getAuthor().getDate())) {
timeAgoString = TimeUtils.getLongTimeAgoString(defaultBranch.commit.getCommit().getAuthor().getDate());
}
String login = defaultBranch.commit.author != null ? defaultBranch.commit.author.getLogin() : "";
String time = getResources().getString(R.string.commit_time_ago, login, timeAgoString);
repoDefaultBranchInfo.setText(Html.fromHtml(time));
repoDefaultBranchCodeButton.setOnClickListener(v -> openBranchCode(defaultBranch));
repoDefaultBranchCommits.setOnClickListener(v -> openBranchCommits(defaultBranch));
if (branches != null) {
List<Branch> visibleBranches = new ArrayList<>();
for (Branch branch : branches) {
if (!defaultBranch.name.equals(branch.name)) {
visibleBranches.add(branch);
}
}
if (visibleBranches.size() > 1) {
repoDefaultBranchExpandableIcon.setVisibility(View.VISIBLE);
repoDefaultBranchExpandableIcon.setOnClickListener(v -> showBranchSelector(visibleBranches));
}
}
}
}
private void openBranchCommits(Branch defaultBranch) {
RepoInfo repoInfo = new RepoInfo();
repoInfo.owner = this.repoInfo.owner;
repoInfo.name = this.repoInfo.name;
repoInfo.branch = defaultBranch.getName();
Intent intent = BranchCommitsActivity.createLauncherIntent(getContext(), repoInfo);
startActivity(intent);
}
private void openBranchCode(Branch branch) {
Intent intent = RepositorySourceActivity.launcherIntent(getContext(), currentRepo, branch);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
private void showBranchSelector(List<Branch> branches) {
if (branches.size() > 1) {
// TODO Show max to 5 branches, or "open all branches"
ListPopupWindow listPopupWindow = new ListPopupWindow(getContext());
BranchesAdapter branchesAdapter = new BranchesAdapter(getContext());
branchesAdapter.addAll(branches);
listPopupWindow.setAdapter(branchesAdapter);
listPopupWindow.setAnchorView(repoDefaultBranchTextView);
listPopupWindow.setOnItemClickListener((parent, view, position, id) -> {
openBranchCode(branches.get(position));
listPopupWindow.dismiss();
});
listPopupWindow.show();
}
}
private void populateStar(boolean starred, int stargazersCount) {
if (stargazersCount > 0) {
@StringRes int text = R.string.repo_detail_no_starred;
if (starred) {
text = R.string.repo_detail_starred;
}
String format = " " + DecimalFormat.getNumberInstance().format(stargazersCount) + " ";
String textStr = getString(text, format);
int backgroundColor = ContextCompat.getColor(getContext(), R.color.md_grey_400);
int textColor = ContextCompat.getColor(getContext(), R.color.md_grey_800);
float radius = getResources().getDimension(R.dimen.materialize_baseline_grid_small);
RoundedBackgroundSpan span = new RoundedBackgroundSpan(backgroundColor, textColor, radius);
SpannableStringBuilder builder = new SpannableStringBuilder(textStr);
builder.setSpan(span, textStr.indexOf(format), textStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
repoDetailNumbersStar.setText(builder);
} else {
@StringRes int text = R.string.repo_detail_starred_no_number;
if (starred) {
text = R.string.repo_detail_no_starred_no_number;
}
repoDetailNumbersStar.setText(text);
}
repoDetailNumbersStar.setOnClickListener(v -> presenter.toggleStar());
}
private void populateWatch(boolean watched, int watchedCount) {
if (watchedCount > 0) {
@StringRes int text = R.string.repo_detail_no_watched;
if (watched) {
text = R.string.repo_detail_watched;
}
String format = " " + DecimalFormat.getNumberInstance().format(watchedCount) + " ";
String textStr = getString(text, format);
int backgroundColor = ContextCompat.getColor(getContext(), R.color.md_grey_400);
int textColor = ContextCompat.getColor(getContext(), R.color.md_grey_800);
float radius = getResources().getDimension(R.dimen.materialize_baseline_grid_small);
RoundedBackgroundSpan span = new RoundedBackgroundSpan(backgroundColor, textColor, radius);
SpannableStringBuilder builder = new SpannableStringBuilder(textStr);
builder.setSpan(span, textStr.indexOf(format), textStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
repoDetailNumbersWatch.setText(builder);
} else {
@StringRes int text = R.string.repo_detail_watched_no_number;
if (watched) {
text = R.string.repo_detail_no_watched_no_number;
}
repoDetailNumbersWatch.setText(text);
}
repoDetailNumbersWatch.setOnClickListener(v -> presenter.toggleWatch());
}
private void populateReadme() {
boolean fullReadme = new GitskariosSettings(getContext()).getFullReadme();
RepoReadmeFragment repoReadmeFragment = RepoReadmeFragment.newInstance(repoInfo, !fullReadme);
FragmentTransaction ft = getChildFragmentManager().beginTransaction();
ft.replace(R.id.repoDetailReadmeContent, repoReadmeFragment);
ft.commit();
repoDefaultOpenReadme.setOnClickListener(v -> {
Intent intent = RepoReadmeActivity.createIntent(getContext(), repoInfo);
startActivity(intent);
});
}
private void populateLicense(License license) {
if (license != null) {
repoDetailLicense.setVisibility(View.VISIBLE);
repoDetailLicense.setText(license.spdxId);
repoDetailLicense.setOnClickListener(v -> openLicense(license));
} else {
repoDetailLicense.setOnClickListener(null);
repoDetailLicense.setVisibility(View.INVISIBLE);
}
}
private void openLicense(License license) {
}
@Override
public void showError(Throwable throwable) {
}
@Override
public void showTagsCount(int tagsCount) {
repoDetailTagsCount.setText(getString(R.string.repo_detail_tags, tagsCount));
if (tagsCount > 0) {
repoDetailTagsCount.setOnClickListener(v -> {
Intent intent = RepoReleasesActivity.createIntent(getContext(), repoInfo);
startActivity(intent);
});
}
}
private class BranchesAdapter extends ArrayAdapter<Branch> {
private final LayoutInflater inflater;
public BranchesAdapter(Context context) {
super(context, 0);
inflater = LayoutInflater.from(context);
}
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
TextView text = (TextView) view.findViewById(android.R.id.text1);
text.setText(getItem(position).name);
return view;
}
}
}