Implementing BottomSheetFragment for commenting on issues and pull requests. ()

change to server error on onFailure

Fix keyboard move issue

Fix statusbar color, remove social, enhance other things

Merge branch 'master' into bottomsheet-issue-comments

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into bottomsheet-issue-comments

 Conflicts:
	app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java

Making it work.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into bottomsheet-issue-comments

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into bottomsheet-issue-comments

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into bottomsheet-issue-comments

First major changes.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into bottomsheet-issue-comments

Cleanup.

Simplifying title.

Adding BottomSheetFragment layout for future changes.

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: M M Arif <mmarif@noreply.codeberg.org>
Co-authored-by: opyale <opyale@noreply.gitea.io>
Co-authored-by: opyale <example@example.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/555
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
This commit is contained in:
opyale 2020-10-12 20:11:23 +02:00 committed by M M Arif
parent d346d68b4f
commit cafb29f8b7
39 changed files with 697 additions and 318 deletions

@ -0,0 +1,80 @@
package org.mian.gitnex.actions;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* @author opyale
*/
public class ActionResult<R> {
public enum Status { SUCCESS, FAILED }
private final BlockingQueue<Boolean> blockingQueue;
private final List<OnFinishedListener<R>> onFinishedListeners;
private boolean invalidated = false;
public ActionResult() {
blockingQueue = new ArrayBlockingQueue<>(1);
onFinishedListeners = new ArrayList<>();
}
public void finish(@NonNull Status status) {
finish(status, null);
}
public void finish(@NonNull Status status, R result) {
try {
if(blockingQueue.poll(5, TimeUnit.SECONDS)) {
for(OnFinishedListener<R> onFinishedListener : onFinishedListeners)
onFinishedListener.onFinished(status, result);
}
} catch (InterruptedException ignored) {}
}
public void invalidate() {
if(invalidated) throw new IllegalStateException("Already invalidated");
this.invalidated = true;
}
@SafeVarargs
public synchronized final void accept(@NonNull OnFinishedListener<R>... onFinishedListeners) {
invalidate();
this.blockingQueue.add(true);
this.onFinishedListeners.addAll(Arrays.asList(onFinishedListeners));
}
public synchronized final void discard() {
invalidate();
this.blockingQueue.add(false);
}
public static class None {}
public interface OnFinishedListener<R> {
void onFinished(Status status, R result);
}
}

@ -12,8 +12,10 @@ import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Permission;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -154,8 +156,55 @@ public class CollaboratorActions {
public void onFailure(@NonNull Call<Permission> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static ActionResult<List<Collaborators>> getCollaborators(Context context) {
ActionResult<List<Collaborators>> actionResult = new ActionResult<>();
TinyDB tinyDb = new TinyDB(context);
String instanceUrl = tinyDb.getString("instanceUrl");
String loginUid = tinyDb.getString("loginUid");
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
actionResult.finish(ActionResult.Status.SUCCESS, response.body());
}
else {
actionResult.finish(ActionResult.Status.FAILED);
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
actionResult.finish(ActionResult.Status.FAILED);
}
});
return actionResult;
}
}

@ -1,11 +1,9 @@
package org.mian.gitnex.actions;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.helpers.AlertDialogs;
@ -13,6 +11,7 @@ import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.UpdateIssueState;
import retrofit2.Call;
import retrofit2.Callback;
@ -53,8 +52,6 @@ public class IssueActions {
DraftsApi draftsApi = new DraftsApi(ctx);
draftsApi.deleteSingleDraft((int) draftIdOnCreate);
((ReplyToIssueActivity) ctx).finish();
}
}
else if(response.code() == 401) {
@ -83,7 +80,7 @@ public class IssueActions {
@Override
public void onFailure(@NonNull Call<IssueComments> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
@ -157,7 +154,7 @@ public class IssueActions {
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
@ -217,7 +214,7 @@ public class IssueActions {
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.success(ctx, ctx.getString(R.string.unsubscribedSuccessfully));
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
@ -277,9 +274,69 @@ public class IssueActions {
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.unsubscriptionError));
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
public static ActionResult<ActionResult.None> reply(Context context, String comment, int issueIndex) {
ActionResult<ActionResult.None> actionResult = new ActionResult<>();
TinyDB tinyDb = new TinyDB(context);
String instanceUrl = tinyDb.getString("instanceUrl");
String loginUid = tinyDb.getString("loginUid");
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
Issues issueComment = new Issues(comment);
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl, context)
.getApiInterface()
.replyCommentToIssue(Authorization.returnAuthentication(context, loginUid, instanceToken), repoOwner, repoName, issueIndex, issueComment);
call.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 201) {
actionResult.finish(ActionResult.Status.SUCCESS);
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("resumePullRequests", true);
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(context, context.getString(R.string.alertDialogTokenRevokedTitle),
context.getString(R.string.alertDialogTokenRevokedMessage),
context.getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
context.getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
actionResult.finish(ActionResult.Status.FAILED);
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Toasty.error(context, context.getResources().getString(R.string.genericServerResponseError));
}
});
return actionResult;
}
}

@ -4,6 +4,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@ -75,7 +76,7 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
AdminGetUsersViewModel.loadUsersList(ctx, instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken));
@ -116,7 +117,7 @@ public class AdminGetUsersActivity extends BaseActivity implements BottomSheetAd
final MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
new Handler().postDelayed(() -> {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
if(searchFilter) {

@ -17,7 +17,9 @@ import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.notifications.NotificationsMaster;
import static org.acra.ReportField.*;
import static org.acra.ReportField.ANDROID_VERSION;
import static org.acra.ReportField.PHONE_MODEL;
import static org.acra.ReportField.STACK_TRACE;
/**
* Author M M Arif
@ -145,7 +147,6 @@ public abstract class BaseActivity extends AppCompatActivity {
ACRA.init(getApplication(), ACRABuilder);
}
}
protected abstract int getLayoutResourceId();

@ -3,6 +3,7 @@ package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
@ -101,7 +102,7 @@ public class CommitsActivity extends BaseActivity {
recyclerView = findViewById(R.id.recyclerView);
commitsList = new ArrayList<>();
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, branchName, resultLimit);

@ -122,7 +122,7 @@ public class FileDiffActivity extends BaseActivity {
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount)));
}
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, fileContentsArray);
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, getSupportFragmentManager(), fileContentsArray);
mListView.setAdapter(adapter);
mProgressBar.setVisibility(View.GONE);

@ -2,7 +2,6 @@ package org.mian.gitnex.activities;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
@ -43,6 +42,7 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityIssueDetailBinding;
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.fragments.BottomSheetSingleIssueFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
@ -162,7 +162,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(viewBinding.recyclerView.getContext(), DividerItemDecoration.VERTICAL);
viewBinding.recyclerView.addItemDecoration(dividerItemDecoration);
viewBinding.addNewComment.setOnClickListener(v -> startActivity(new Intent(ctx, ReplyToIssueActivity.class)));
viewBinding.addNewComment.setOnClickListener(v -> BottomSheetReplyFragment.newInstance(new Bundle()).show(getSupportFragmentManager(), "replyBottomSheet"));
labelsAdapter = new LabelsListAdapter(labelsList, IssueDetailActivity.this, currentLabelsIds);
assigneesAdapter = new AssigneesListAdapter(ctx, assigneesList, IssueDetailActivity.this, currentAssignees);
@ -542,7 +542,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.divider.setVisibility(View.VISIBLE);
}
adapter = new IssueCommentsAdapter(ctx, issueCommentsMain);
adapter = new IssueCommentsAdapter(ctx, getSupportFragmentManager(), issueCommentsMain);
viewBinding.recyclerView.setAdapter(adapter);
});

@ -218,7 +218,6 @@ public class ReplyToIssueActivity extends BaseActivity {
DraftsApi.updateDraft(draftText, (int) draftIdOnCreate, commentId); //updateDraftByIssueIdAsyncTask(draftText, issueNumber, repositoryId, commentId);
}
}
private long returnDraftId(String draftText) {

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
@ -106,7 +107,7 @@ public class RepoForksActivity extends BaseActivity {
DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(dividerItemDecoration);
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, pageSize, resultLimit);

@ -12,8 +12,6 @@ import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.FilesData;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
@ -21,7 +19,6 @@ import org.mian.gitnex.helpers.ssl.MemorizingTrustManager;
import org.mian.gitnex.notifications.NotificationsMaster;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
/**
* Author M M Arif
@ -99,10 +96,7 @@ public class SettingsSecurityActivity extends BaseActivity {
// clear cache setter
File cacheDir = appCtx.getCacheDir();
long size__ = FilesData.getFileSizeRecursively(new HashSet<>(), cacheDir);
if(size__ > 0) {
clearCacheSelected.setText(String.valueOf(AppUtil.formatFileSizeInDetail(size__)));
}
clearCacheSelected.setText(FileUtils.byteCountToDisplaySize((int) FileUtils.sizeOfDirectory(cacheDir)));
// clear cache
clearCacheFrame.setOnClickListener(v1 -> {

@ -2,7 +2,7 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
@ -11,11 +11,12 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.database.models.DraftWithRepository;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.List;
@ -27,6 +28,7 @@ import java.util.List;
public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsViewHolder> {
private List<DraftWithRepository> draftsList;
private FragmentManager fragmentManager;
private Context mCtx;
class DraftsViewHolder extends RecyclerView.ViewHolder {
@ -69,16 +71,17 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
itemView.setOnClickListener(itemEdit -> {
Intent intent = new Intent(mCtx, ReplyToIssueActivity.class);
intent.putExtra("commentBody", draftText.getText().toString());
intent.putExtra("issueNumber", issueNumber.getText().toString());
intent.putExtra("repositoryId", repoId.getText().toString());
intent.putExtra("draftTitle", repoInfo.getText().toString());
intent.putExtra("commentId", commentId.getText().toString());
intent.putExtra("draftId", draftId.getText().toString());
Bundle bundle = new Bundle();
if(!commentId.getText().toString().equalsIgnoreCase("")) {
intent.putExtra("commentAction", "edit");
bundle.putString("commentBody", draftText.getText().toString());
bundle.putString("issueNumber", issueNumber.getText().toString());
bundle.putString("repositoryId", repoId.getText().toString());
bundle.putString("draftTitle", repoInfo.getText().toString());
bundle.putString("commentId", commentId.getText().toString());
bundle.putString("draftId", draftId.getText().toString());
if(!commentId.getText().toString().isEmpty()) {
bundle.putString("commentAction", "edit");
}
TinyDB tinyDb = new TinyDB(mCtx);
@ -86,7 +89,7 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
tinyDb.putLong("repositoryId", Long.parseLong(repoId.getText().toString()));
//tinyDb.putString("issueType", issueType.getText().toString());
mCtx.startActivity(intent);
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
});
@ -94,8 +97,9 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
}
public DraftsAdapter(Context mCtx, List<DraftWithRepository> draftsListMain) {
public DraftsAdapter(Context mCtx, FragmentManager fragmentManager, List<DraftWithRepository> draftsListMain) {
this.mCtx = mCtx;
this.fragmentManager = fragmentManager;
this.draftsList = draftsListMain;
}

@ -10,8 +10,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Files;
import java.util.ArrayList;
@ -165,7 +165,7 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
holder.dirTypeImage.setVisibility(View.GONE);
holder.unknownTypeImage.setVisibility(View.GONE);
holder.fileInfo.setVisibility(View.VISIBLE);
holder.fileInfo.setText(AppUtil.formatFileSizeInDetail(currentItem.getSize()));
holder.fileInfo.setText(FileUtils.byteCountToDisplaySize(currentItem.getSize()));
}
else if(currentItem.getType().equals("dir")) {
holder.dirTypeImage.setVisibility(View.VISIBLE);

@ -2,8 +2,8 @@ package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@ -12,8 +12,9 @@ import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.fragment.app.FragmentManager;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.DiffTextView;
import org.mian.gitnex.models.FileDiffView;
import java.util.List;
@ -36,11 +37,13 @@ public class FilesDiffAdapter extends BaseAdapter {
private static int COLOR_FONT;
private Context context;
private FragmentManager fragmentManager;
private List<FileDiffView> fileDiffViews;
public FilesDiffAdapter(Context context, List<FileDiffView> fileDiffViews) {
public FilesDiffAdapter(Context context, FragmentManager fragmentManager, List<FileDiffView> fileDiffViews) {
this.context = context;
this.fragmentManager = fragmentManager;
this.fileDiffViews = fileDiffViews;
selectedViews = new ConcurrentSkipListMap<>();
@ -201,12 +204,11 @@ public class FilesDiffAdapter extends BaseAdapter {
selectedViews.clear();
Intent intent = new Intent(context, ReplyToIssueActivity.class);
intent.putExtra("commentBody", stringBuilder.toString());
intent.putExtra("cursorToEnd", true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle bundle = new Bundle();
bundle.putString("commentBody", stringBuilder.toString());
bundle.putBoolean("cursorToEnd", true);
context.startActivity(intent);
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
}

@ -7,6 +7,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
@ -14,14 +15,15 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;
@ -60,11 +62,13 @@ import retrofit2.Callback;
public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdapter.IssueCommentViewHolder> {
private List<IssueComments> issuesComments;
private FragmentManager fragmentManager;
private Context mCtx;
public IssueCommentsAdapter(Context mCtx, List<IssueComments> issuesCommentsMain) {
public IssueCommentsAdapter(Context mCtx, FragmentManager fragmentManager, List<IssueComments> issuesCommentsMain) {
this.mCtx = mCtx;
this.fragmentManager = fragmentManager;
this.issuesComments = issuesCommentsMain;
}
@ -126,11 +130,12 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
commentMenuEdit.setOnClickListener(ediComment -> {
Intent intent = new Intent(ctx, ReplyToIssueActivity.class);
intent.putExtra("commentId", commendId.getText());
intent.putExtra("commentAction", "edit");
intent.putExtra("commentBody", commendBodyRaw.getText());
ctx.startActivity(intent);
Bundle bundle = new Bundle();
bundle.putString("commentId", commendId.getText().toString());
bundle.putString("commentAction", "edit");
bundle.putString("commentBody", commendBodyRaw.getText().toString());
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
dialog.dismiss();
});
@ -187,13 +192,12 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
stringBuilder.append("\n");
Intent intent = new Intent(ctx, ReplyToIssueActivity.class);
intent.putExtra("commentBody", stringBuilder.toString());
intent.putExtra("cursorToEnd", true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle bundle = new Bundle();
bundle.putString("commentBody", stringBuilder.toString());
bundle.putBoolean("cursorToEnd", true);
dialog.dismiss();
ctx.startActivity(intent);
BottomSheetReplyFragment.newInstance(bundle).show(fragmentManager, "replyBottomSheet");
});

@ -0,0 +1,214 @@
package org.mian.gitnex.fragments;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.ActionResult;
import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.Objects;
/**
* @author opyale
*/
public class BottomSheetReplyFragment extends BottomSheetDialogFragment {
private TinyDB tinyDB;
private DraftsApi draftsApi;
private int repositoryId;
private int currentActiveAccountId;
private int issueNumber;
private long draftId;
private TextView draftsHint;
@Override
public void onAttach(@NonNull Context context) {
tinyDB = new TinyDB(context);
draftsApi = new DraftsApi(context);
repositoryId = (int) tinyDB.getLong("repositoryId", 0);
currentActiveAccountId = tinyDB.getInt("currentActiveAccountId");
issueNumber = Integer.parseInt(tinyDB.getString("issueNumber"));
super.onAttach(context);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_reply_layout, container, false);
Bundle arguments = requireArguments();
draftsHint = view.findViewById(R.id.drafts_hint);
EditText commentContent = view.findViewById(R.id.comment);
TextView toolbarTitle = view.findViewById(R.id.toolbar_title);
ImageButton close = view.findViewById(R.id.close);
ImageButton drafts = view.findViewById(R.id.drafts);
ImageButton send = view.findViewById(R.id.send);
send.setEnabled(false);
if(Objects.equals(arguments.getString("commentAction"), "edit")) {
send.setVisibility(View.GONE);
}
if(arguments.getString("draftId") != null) {
draftId = Long.parseLong(arguments.getString("draftId"));
}
if(!tinyDB.getString("issueTitle").isEmpty()) {
toolbarTitle.setText(tinyDB.getString("issueTitle"));
}
else if(arguments.getString("draftTitle") != null) {
toolbarTitle.setText(arguments.getString("draftTitle"));
}
if(arguments.getString("commentBody") != null) {
send.setEnabled(true);
send.setAlpha(1f);
commentContent.setText(arguments.getString("commentBody"));
if(arguments.getBoolean("cursorToEnd", false)) {
commentContent.setSelection(commentContent.length());
}
}
commentContent.requestFocus();
commentContent.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
String text = commentContent.getText().toString();
if(text.isEmpty()) {
send.setEnabled(false);
send.setAlpha(0.5f);
saveDraft(null, true);
}
else {
send.setEnabled(true);
send.setAlpha(1f);
saveDraft(text, false);
}
}
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
close.setOnClickListener(v -> dismiss());
drafts.setOnClickListener(v -> {
Intent intent = new Intent(getContext(), MainActivity.class);
intent.putExtra("launchFragment", "drafts");
startActivity(intent);
dismiss();
});
send.setOnClickListener(v -> IssueActions
.reply(getContext(), commentContent.getText().toString(), issueNumber)
.accept((status, result) -> {
if(status == ActionResult.Status.SUCCESS) {
Toasty.success(getContext(), getString(R.string.commentSuccess));
tinyDB.putBoolean("commentPosted", true);
tinyDB.putBoolean("resumeIssues", true);
tinyDB.putBoolean("resumePullRequests", true);
if(draftId != 0 && tinyDB.getBoolean("draftsCommentsDeletionEnabled")) {
draftsApi.deleteSingleDraft((int) draftId);
}
dismiss();
}
else {
Toasty.error(getContext(), getString(R.string.commentError));
dismiss();
}
}));
return view;
}
private void saveDraft(String text, boolean remove) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
valueAnimator.setDuration(500);
valueAnimator.addUpdateListener(animation -> {
float value = (Float) animation.getAnimatedValue();
if(value == 0f) {
draftsHint.setVisibility((remove) ? View.GONE : View.VISIBLE);
}
draftsHint.setAlpha(value);
});
if(remove) {
draftsApi.deleteSingleDraft((int) draftId);
draftId = 0;
valueAnimator.reverse();
}
else {
if(draftId == 0) {
draftId = draftsApi.insertDraft(repositoryId, currentActiveAccountId, issueNumber, text, StaticGlobalVariables.draftTypeComment, "TODO");
} else {
DraftsApi.updateDraft(text, (int) draftId, "TODO");
}
draftsHint.setVisibility(View.VISIBLE);
valueAnimator.start();
}
}
public static BottomSheetReplyFragment newInstance(Bundle bundle) {
BottomSheetReplyFragment fragment = new BottomSheetReplyFragment();
fragment.setArguments(bundle);
return fragment;
}
}

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -66,11 +67,9 @@ public class DraftsFragment extends Fragment {
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
adapter = new DraftsAdapter(getContext(), draftsList_);
adapter = new DraftsAdapter(getContext(), getChildFragmentManager(), draftsList_);
currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
draftsList_.clear();
fetchDataAsync(currentActiveAccountId);

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@ -87,7 +88,7 @@ public class IssuesFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
noDataIssues = v.findViewById(R.id.noDataIssues);
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(instanceToken, repoOwner, repoName, resultLimit, requestType, tinyDb.getString("repoIssuesState"));

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -87,18 +88,12 @@ public class LabelsFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
LabelsViewModel.loadLabelsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getContext());
}
}, 200);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
LabelsViewModel.loadLabelsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getContext());
}, 200));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@ -94,7 +95,7 @@ public class MilestonesFragment extends Fragment {
viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
viewBinding.recyclerView.setAdapter(adapter);
viewBinding.pullToRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
viewBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
dataList.clear();
viewBinding.pullToRefresh.setRefreshing(false);

@ -4,6 +4,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -130,10 +131,11 @@ public class MyRepositoriesFragment extends Fragment {
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
MyRepositoriesViewModel.loadMyReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), userLogin, getContext(), pageSize, resultLimit);
}, 50));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), userLogin, pageSize, resultLimit);

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -99,18 +100,12 @@ public class OrganizationsFragment extends Fragment {
}
});
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
OrganizationListViewModel.loadOrgsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 50);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
OrganizationListViewModel.loadOrgsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}, 50));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -88,18 +89,12 @@ public class ProfileEmailsFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
ProfileEmailsViewModel.loadEmailsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 200);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
ProfileEmailsViewModel.loadEmailsList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}, 200));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -88,18 +89,12 @@ public class ProfileFollowersFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
ProfileFollowersViewModel.loadFollowersList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 200);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
ProfileFollowersViewModel.loadFollowersList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}, 200));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -88,18 +89,12 @@ public class ProfileFollowingFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
ProfileFollowingViewModel.loadFollowingList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}
}, 200);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
ProfileFollowingViewModel.loadFollowingList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext());
}, 200));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken));

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@ -88,7 +89,7 @@ public class PullRequestsFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
noData = v.findViewById(R.id.noData);
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
loadInitial(instanceToken, repoOwner, repoName, pageSize, tinyDb.getString("repoPrState"), resultLimit);

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -88,18 +89,12 @@ public class ReleasesFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
ReleasesViewModel.loadReleasesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getContext());
}
}, 50);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
ReleasesViewModel.loadReleasesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName, getContext());
}, 50));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);

@ -18,13 +18,13 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.TimeHelper;
@ -283,13 +283,7 @@ public class RepoInfoFragment extends Fragment {
repoMetaForks.setText(repoInfo.getForks_count());
repoMetaWatchers.setText(repoInfo.getWatchers_count());
if(repoInfo.getSize() != 0) {
repoMetaSize.setText(AppUtil.formatFileSize(repoInfo.getSize()));
}
else {
repoMetaSize.setText("0 B");
}
repoMetaSize.setText(FileUtils.byteCountToDisplaySize((int) repoInfo.getSize()));
repoMetaCreatedAt.setText(TimeHelper.formatTime(repoInfo.getCreated_at(), new Locale(locale), timeFormat, ctx));
if(timeFormat.equals("pretty")) {

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -92,18 +93,12 @@ public class RepositoriesByOrgFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
RepositoriesByOrgViewModel.loadOrgRepos(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext(), pageSize, resultLimit);
}
}, 200);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
RepositoriesByOrgViewModel.loadOrgRepos(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext(), pageSize, resultLimit);
}, 200));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, pageSize, resultLimit);

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -98,10 +99,11 @@ public class RepositoriesFragment extends Fragment {
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
RepositoriesListViewModel.loadReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext(), pageSize, resultLimit);
}, 50));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), pageSize, resultLimit);

@ -4,6 +4,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -127,18 +128,12 @@ public class StarredRepositoriesFragment extends Fragment {
}
});
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
StarredRepositoriesViewModel.loadStarredReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext(), pageSize, resultLimit);
}
}, 50);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
StarredRepositoriesViewModel.loadStarredReposList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), getContext(), pageSize, resultLimit);
}, 50));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), pageSize, resultLimit);

@ -3,6 +3,7 @@ package org.mian.gitnex.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -90,18 +91,12 @@ public class TeamsByOrgFragment extends Fragment {
mProgressBar = v.findViewById(R.id.progress_bar);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
TeamsByOrgViewModel.loadTeamsByOrgList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext());
}
}, 200);
}
});
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
TeamsByOrgViewModel.loadTeamsByOrgList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName, getContext());
}, 200));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), orgName);

@ -4,6 +4,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -57,7 +58,7 @@ public class UserAccountsFragment extends Fragment {
adapter = new UserAccountsAdapter(getContext(), userAccountsList);
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
userAccountsList.clear();
swipeRefresh.setRefreshing(false);

@ -13,7 +13,6 @@ import android.view.View;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
@ -123,33 +122,6 @@ public class AppUtil {
}
public static String formatFileSize(long size) {
String repoSize = size + " B";
double m = size / 1024.0;
double g = ((size / 1024.0) / 1024.0);
double t = (((size / 1024.0) / 1024.0) / 1024.0);
DecimalFormat dec = new DecimalFormat("0.00");
if(t > 1) {
repoSize = dec.format(t).concat(" TB");
}
else if(g > 1) {
repoSize = dec.format(g).concat(" GB");
}
else if(m > 1) {
repoSize = dec.format(m).concat(" MB");
}
else if((double) size > 1) {
repoSize = dec.format((double) size).concat(" KB");
}
return repoSize;
}
public static String getTimestampFromDate(Context context, Date date) {
TinyDB tinyDB = new TinyDB(context);
@ -159,37 +131,6 @@ public class AppUtil {
}
public static String formatFileSizeInDetail(long size) {
String fileSize = null;
double k = size / 1024.0;
double m = ((size / 1024.0) / 1024.0);
double g = (((size / 1024.0) / 1024.0) / 1024.0);
double t = ((((size / 1024.0) / 1024.0) / 1024.0) / 1024.0);
DecimalFormat dec = new DecimalFormat("0.00");
if(t > 1) {
fileSize = dec.format(t).concat(" TB");
}
else if(g > 1) {
fileSize = dec.format(g).concat(" GB");
}
else if(m > 1) {
fileSize = dec.format(m).concat(" MB");
}
else if(k > 1) {
fileSize = dec.format(k).concat(" KB");
}
else if((double) size > 1) {
fileSize = dec.format((double) size).concat(" B");
}
return fileSize;
}
public static String customDateFormat(String customDate) {
String[] parts = customDate.split("-");

@ -1,12 +1,5 @@
package org.mian.gitnex.helpers;
import java.io.File;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
/**
* Author M M Arif
*/
@ -16,69 +9,5 @@ public class FilesData {
public static int returnOnlyNumber(String fileSize) {
return Integer.parseInt(fileSize.substring(0, fileSize.indexOf(" ")));
}
public static long getFileSizeRecursively(Set<File> alreadySeen, File dirDirectory) {
long fileSize = 0;
for (File filItem : Objects.requireNonNull(dirDirectory.listFiles())) {
if (filItem.isDirectory()) {
fileSize += getFileSize(filItem);
}
else {
alreadySeen.add(new File(filItem.getName()));
fileSize += filItem.length();
}
}
return fileSize;
}
private static long getFileSize(File subDirectory) {
long fileSize = 0;
Deque<File> unprocessedDirs = new ArrayDeque<>();
unprocessedDirs.add(subDirectory);
Set<File> alreadySeen = new HashSet<>();
while (!unprocessedDirs.isEmpty()) {
File dir = unprocessedDirs.removeFirst();
for (File filItem : Objects.requireNonNull(dir.listFiles())) {
if (filItem.isDirectory()) {
unprocessedDirs.addFirst(filItem);
}
else {
if (! alreadySeen.contains(filItem.getName())) {
alreadySeen.add(new File(filItem.getName()));
fileSize += filItem.length();
}
}
}
}
return fileSize;
}
}

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M22,2L11,13"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M22,2l-7,20l-4,-9l-9,-4l20,-7z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
app:contentInsetEnd="15dp"
app:contentInsetStart="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageButton
android:id="@+id/close"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_marginEnd="15dp"
android:layout_weight="0"
android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/close"
android:src="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:maxLines="1"
android:text="@string/commentButtonText"
android:textColor="?attr/primaryTextColor"
android:textSize="20sp" />
<ImageButton
android:id="@+id/drafts"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_marginStart="15dp"
android:layout_weight="0"
android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/close"
android:src="@drawable/ic_drafts" />
<ImageButton
android:id="@+id/send"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_marginStart="15dp"
android:layout_weight="0"
android:alpha=".5"
android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/close"
android:enabled="false"
android:src="@drawable/ic_send" />
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:isScrollContainer="true"
android:padding="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/comment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_inputs"
android:inputType="textMultiLine|textImeMultiLine"
android:maxLines="5"
android:padding="10dp"
android:scrollbars="vertical"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/primaryTextColor"
android:textColorHint="?attr/primaryBackgroundColor"
android:textSize="16sp"
android:labelFor="@+id/comment"
android:autofillHints="@string/commentButtonText" />
<TextView
android:id="@+id/drafts_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="@string/draftSaved"
android:textColor="?attr/hintColor"
android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
</ScrollView>
</LinearLayout>

@ -628,7 +628,7 @@
<string name="draftsDeleteSuccess">Drafts deleted successfully</string>
<string name="draftsSingleDeleteSuccess">Draft deleted successfully</string>
<string name="deleteAllDraftsDialogMessage">This will delete all the drafts for this account. \n\nProceed with deletion?</string>
<string name="draftSaved">Draft saved</string>
<string name="draftSaved">Draft was saved automatically.</string>
<string name="appearanceHintText">Themes, fonts, badges, code block theme</string>
<string name="fileViewerHintText">PDF mode, source code theme</string>

@ -133,15 +133,22 @@
</style>
<style name="AppThemeDarkBottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<item name="bottomSheetStyle">@style/AppBottomSheetModalStyle</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="AppThemeLightBottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<item name="bottomSheetStyle">@style/AppBottomSheetModalStyle</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="AppBottomSheetModalStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@drawable/shape_bottom_sheet_top_corners</item>
<item name="behavior_peekHeight">420dp</item>
</style>
<style name="AppThemeLightSearchAutoCompleteTextView" parent="Widget.AppCompat.Light.AutoCompleteTextView">