GitNex/app/src/main/java/org/mian/gitnex/fragments/CommitDetailFragment.java

252 lines
9.9 KiB
Java

package org.mian.gitnex.fragments;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.text.HtmlCompat;
import androidx.fragment.app.Fragment;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.models.Commits;
import org.gitnex.tea4j.models.FileDiffView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.BaseActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.adapters.DiffFilesAdapter;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.CustomCommitHeaderBinding;
import org.mian.gitnex.databinding.FragmentCommitDetailsBinding;
import org.mian.gitnex.helpers.*;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* @author qwerty287
*/
public class CommitDetailFragment extends Fragment {
private FragmentCommitDetailsBinding binding;
private String repoOwner;
private String repoName;
private String sha;
private int loadingFinished = 0;
public static CommitDetailFragment newInstance() {
return new CommitDetailFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
binding = FragmentCommitDetailsBinding.inflate(getLayoutInflater(), container, false);
RepositoryContext repository = RepositoryContext.fromIntent(requireActivity().getIntent());
repoOwner = repository.getOwner();
repoName = repository.getName();
sha = requireActivity().getIntent().getStringExtra("sha");
binding.toolbarTitle.setText(sha.substring(0, Math.min(sha.length(), 10)));
getCommit();
getDiff();
binding.close.setOnClickListener((v) -> requireActivity().finish());
binding.diffFiles.setOnItemClickListener((parent, view, position, id) -> requireActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, DiffFragment.newInstance((FileDiffView) parent.getItemAtPosition(position), "commit"))
.commit());
return binding.getRoot();
}
private void getDiff() {
Call<ResponseBody> call = new Version(TinyDB.getInstance(requireContext()).getString("giteaVersion")).higherOrEqual("1.16.0") ?
RetrofitClient.getApiInterface(requireContext()).getCommitDiff(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repoOwner, repoName, sha) :
RetrofitClient.getWebInterface(requireContext()).getCommitDiff(((BaseActivity) requireActivity()).getAccount().getWebAuthorization(), repoOwner, repoName, sha);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
checkLoading();
assert response.body() != null;
switch(response.code()) {
case 200:
List<FileDiffView> fileDiffViews;
try {
fileDiffViews = ParseDiff.getFileDiffViewArray(response.body().string());
} catch(IOException e) {
onFailure(call, e);
return;
}
DiffFilesAdapter adapter = new DiffFilesAdapter(requireContext(), fileDiffViews);
requireActivity().runOnUiThread(() -> binding.diffFiles.setAdapter(adapter));
break;
case 401:
requireActivity().runOnUiThread(() -> AlertDialogs.authorizationTokenRevokedDialog(requireContext(), getString(R.string.alertDialogTokenRevokedTitle),
getString(R.string.alertDialogTokenRevokedMessage), getString(R.string.cancelButton), getString(R.string.cancelButton)));
break;
case 403:
requireActivity().runOnUiThread(() -> Toasty.error(requireContext(), getString(R.string.authorizeError)));
break;
case 404:
requireActivity().runOnUiThread(() -> Toasty.warning(requireContext(), getString(R.string.apiNotFound)));
break;
default:
requireActivity().runOnUiThread(() -> Toasty.error(requireContext(), getString(R.string.genericError)));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
checkLoading();
Toasty.error(requireContext(), getString(R.string.genericError));
}
});
}
private void getCommit() {
RetrofitClient.getApiInterface(requireContext()).getCommit(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repoOwner, repoName, sha)
.enqueue(new Callback<Commits>() {
@Override
public void onResponse(@NonNull Call<Commits> call, @NonNull Response<Commits> response) {
checkLoading();
CustomCommitHeaderBinding binding = CustomCommitHeaderBinding.inflate(getLayoutInflater());
binding.getRoot().setOnClickListener((v) -> {
// we need a ClickListener here to prevent that the ItemClickListener of the diffFiles ListView handles clicks for the header
});
CommitDetailFragment.this.binding.diffFiles.addHeaderView(binding.getRoot());
assert response.body() != null;
Commits commitsModel = response.body();
String[] commitMessageParts = commitsModel.getCommit().getMessage().split("(\r\n|\n)", 2);
if(commitMessageParts.length > 1 && !commitMessageParts[1].trim().isEmpty()) {
binding.commitBody.setVisibility(View.VISIBLE);
binding.commitSubject.setText(EmojiParser.parseToUnicode(commitMessageParts[0].trim()));
binding.commitBody.setText(EmojiParser.parseToUnicode(commitMessageParts[1].trim()));
} else {
binding.commitSubject.setText(EmojiParser.parseToUnicode(commitMessageParts[0].trim()));
binding.commitBody.setVisibility(View.GONE);
}
if(!Objects.equals(commitsModel.getCommit().getCommitter().getEmail(), commitsModel.getCommit().getCommitter().getEmail())) {
binding.commitAuthorAndCommitter.setText(HtmlCompat.fromHtml(CommitDetailFragment.this
.getString(R.string.commitAuthoredByAndCommittedByWhen, commitsModel.getCommit().getAuthor().getName(), commitsModel.getCommit().getCommitter().getName(),
TimeHelper
.formatTime(commitsModel.getCommit().getCommitter().getDate(), getResources().getConfiguration().locale, "pretty",
requireContext())), HtmlCompat.FROM_HTML_MODE_COMPACT));
} else {
binding.commitAuthorAndCommitter.setText(HtmlCompat.fromHtml(CommitDetailFragment.this
.getString(R.string.commitCommittedByWhen, commitsModel.getCommit().getCommitter().getName(),
TimeHelper
.formatTime(commitsModel.getCommit().getCommitter().getDate(), getResources().getConfiguration().locale, "pretty",
requireContext())), HtmlCompat.FROM_HTML_MODE_COMPACT));
}
if(commitsModel.getAuthor() != null && commitsModel.getAuthor().getAvatar_url() != null &&
!commitsModel.getAuthor().getAvatar_url().isEmpty()) {
binding.commitAuthorAvatar.setVisibility(View.VISIBLE);
int imgRadius = AppUtil.getPixelsFromDensity(requireContext(), 3);
PicassoService.getInstance(requireContext()).get()
.load(commitsModel.getAuthor().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop().into(binding.commitAuthorAvatar);
binding.commitAuthorAvatar.setOnClickListener((v) -> {
Intent intent = new Intent(requireContext(), ProfileActivity.class);
intent.putExtra("username", commitsModel.getAuthor().getUsername());
startActivity(intent);
});
} else {
binding.commitAuthorAvatar.setImageDrawable(null);
binding.commitAuthorAvatar.setVisibility(View.GONE);
}
if(commitsModel.getCommitter() != null &&
!commitsModel.getAuthor().getLogin().equals(commitsModel.getCommitter().getLogin()) &&
commitsModel.getCommitter().getAvatar_url() != null &&
!commitsModel.getCommitter().getAvatar_url().isEmpty()) {
binding.commitCommitterAvatar.setVisibility(View.VISIBLE);
int imgRadius = AppUtil.getPixelsFromDensity(requireContext(), 3);
PicassoService.getInstance(requireContext()).get()
.load(commitsModel.getCommitter().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(imgRadius, 0))
.resize(120, 120)
.centerCrop().into(binding.commitCommitterAvatar);
binding.commitCommitterAvatar.setOnClickListener((v) -> {
Intent intent = new Intent(requireContext(), ProfileActivity.class);
intent.putExtra("username", commitsModel.getCommitter().getUsername());
startActivity(intent);
});
} else {
binding.commitCommitterAvatar.setImageDrawable(null);
binding.commitCommitterAvatar.setVisibility(View.GONE);
}
binding.commitSha.setText(commitsModel.getSha().substring(0, Math.min(commitsModel.getSha().length(), 10)));
binding.commitSha.setOnClickListener((v) -> {
ClipboardManager clipboard = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("commitSha", commitsModel.getSha());
assert clipboard != null;
clipboard.setPrimaryClip(clip);
Toasty.success(requireContext(), getString(R.string.copyShaToastMsg));
});
}
@Override
public void onFailure(@NonNull Call<Commits> call, @NonNull Throwable t) {
checkLoading();
Toasty.error(requireContext(), getString(R.string.genericError));
requireActivity().finish();
}
});
}
private void checkLoading() {
loadingFinished += 1;
if(loadingFinished >= 2) {
binding.progressBar.setVisibility(View.GONE);
}
}
}