Improve file type handling. (#841)

Removing file size selection dialog in favor of hardcoded value.

Adding warning to file size picker and minor improvements.

Bump dependencies and gradle

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition

Improving credits, adding symlink and submodule icons to FilesAdapter and removing unused libraries.

Minor improvements and bug fixes.

Add true progress indication routine for copying streams.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition

Performance and memory usage improvements

Notification improvements

Renaming StaticGlobalVariables to Constants

Overall improvements and fixes.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition

Add additional image formats.

Adding audio and video categories.

Merge branch 'master' of https://codeberg.org/gitnex/GitNex into improve-filetype-recognition

Improve file type handling.

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/841
Reviewed-by: M M Arif <mmarif@noreply.codeberg.org>
Co-Authored-By: opyale <opyale@noreply.codeberg.org>
Co-Committed-By: opyale <opyale@noreply.codeberg.org>
This commit is contained in:
opyale 2021-03-21 16:56:54 +01:00 committed by M M Arif
parent ef3108db14
commit 98cf1a1976
61 changed files with 1387 additions and 1519 deletions

View File

@ -69,26 +69,31 @@ We use [Crowdin](https://crowdin.com/project/gitnex) for translation. If your la
Thanks to all the open source libraries, contributors and donators.
#### Open source libraries
- Retrofit
- Gson
- Okhttp
- Picasso
- Markwon
- Prism4j
- Prettytime
- Amulyakhare/textdrawable
- Vdurmont/emoji-java
- Pes/materialcolorpicker
- HamidrezaAmz/BreadcrumbsView
- Chrisbanes/PhotoView
- Pddstudio/highlightjs-android
- Apache/commons-io
- Caverock/androidsvg
- Droidsonroids.gif/android-gif-drawable
- Barteksc/androidPdfViewer
- Ge0rg/memorizingTrustManager
- Dimezis/blurView
- Mikaelhg/urlbuilder
- [square/retrofit](https://github.com/square/retrofit)
- [google/gson](https://github.com/google/gson)
- [square/okhttp](https://github.com/square/okhttp)
- [square/picasso](https://github.com/square/picasso)
- [wasabeef/picasso-transformations](https://github.com/wasabeef/picasso-transformations)
- [cats-oss/android-gpuimage](https://github.com/cats-oss/android-gpuimage)
- [noties/Markwon](https://github.com/noties/Markwon)
- [noties/Prism4j](https://github.com/noties/Prism4j)
- [ocpsoft/prettytime](https://github.com/ocpsoft/prettytime)
- [amulyakhare/TextDrawable](https://github.com/amulyakhare/TextDrawable)
- [vdurmont/emoji-java](https://github.com/vdurmont/emoji-java)
- [Pes8/android-material-color-picker-dialog](https://github.com/Pes8/android-material-color-picker-dialog)
- [HamidrezaAmz/BreadcrumbsView](https://github.com/HamidrezaAmz/BreadcrumbsView)
- [Baseflow/PhotoView](https://github.com/Baseflow/PhotoView)
- [PDDStudio/highlightjs-android](https://github.com/PDDStudio/highlightjs-android)
- [apache/commons](https://github.com/apache/commons-io)
- [barteksc/AndroidPdfViewer](https://github.com/barteksc/AndroidPdfViewer)
- [ge0rg/MemorizingTrustManager](https://github.com/ge0rg/MemorizingTrustManager)
- [mikaelhg/urlbuilder](https://github.com/mikaelhg/urlbuilder)
- [ACRA/acra](https://github.com/ACRA/acra)
#### Icon sets
- [feathericons/feather](https://github.com/feathericons/feather)
- [primer/octicons](https://github.com/primer/octicons)
- [google/material-design-icons](https://github.com/google/material-design-icons)
[Follow me on Fediverse - mastodon.social/@mmarif](https://mastodon.social/@mmarif)

View File

@ -30,7 +30,7 @@ android {
release {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
@ -55,7 +55,7 @@ configurations {
dependencies {
def lifecycle_version = '2.3.0'
def markwon_version = '4.6.1'
def markwon_version = '4.6.2'
def work_version = "2.5.0"
def acra = "5.7.0"
@ -65,17 +65,19 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
testImplementation 'junit:junit:4.13.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
implementation "com.google.code.gson:gson:2.8.6"
implementation "com.squareup.picasso:picasso:2.71828"
implementation 'jp.wasabeef:picasso-transformations:2.4.0'
implementation 'jp.co.cyberagent.android:gpuimage:2.1.0'
implementation "com.amulyakhare:com.amulyakhare.textdrawable:1.0.1"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'
implementation 'org.ocpsoft.prettytime:prettytime:5.0.0.Final'
implementation "com.pes.materialcolorpicker:library:1.2.5"
implementation "io.noties.markwon:core:$markwon_version"
@ -94,11 +96,9 @@ dependencies {
implementation "io.noties.markwon:image-picasso:$markwon_version"
implementation "io.noties:prism4j:2.0.0"
annotationProcessor "io.noties:prism4j-bundler:2.0.0"
implementation "com.caverock:androidsvg:1.4"
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.21"
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
implementation "commons-io:commons-io:20030203.000550"
implementation 'org.apache.commons:commons-lang3:3.11'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation "com.github.chrisbanes:PhotoView:2.3.0"
implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1"
implementation "ch.acra:acra-mail:$acra"
@ -107,11 +107,10 @@ dependencies {
implementation 'androidx.room:room-runtime:2.2.6'
annotationProcessor 'androidx.room:room-compiler:2.2.6'
implementation "androidx.work:work-runtime:$work_version"
implementation "com.eightbitlab:blurview:1.6.4"
implementation "io.mikael:urlbuilder:2.0.9"
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
implementation "org.codeberg.gitnex:tea4j:1.0.1"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.1"
implementation "org.codeberg.gitnex:tea4j:1.0.5"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation 'androidx.biometric:biometric:1.1.0'
}

View File

@ -7,7 +7,6 @@ import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
import java.io.IOException;
import java.util.Date;
import okhttp3.ResponseBody;
import retrofit2.Call;
/**
@ -35,7 +34,7 @@ public class NotificationsActions {
public void setNotificationStatus(NotificationThread notificationThread, NotificationStatus notificationStatus) throws IOException {
Call<ResponseBody> call = RetrofitClient.getApiInterface(context)
Call<Void> call = RetrofitClient.getApiInterface(context)
.markNotificationThreadAsRead(instanceToken, notificationThread.getId(), notificationStatus.name());
if(!call.execute().isSuccessful()) {
@ -46,7 +45,7 @@ public class NotificationsActions {
public boolean setAllNotificationsRead(Date date) throws IOException {
Call<ResponseBody> call = RetrofitClient.getApiInterface(context)
Call<Void> call = RetrofitClient.getApiInterface(context)
.markNotificationThreadsAsRead(instanceToken, AppUtil.getTimestampFromDate(context, date), true,
new String[]{"unread", "pinned"}, "read");

View File

@ -24,7 +24,7 @@ import org.mian.gitnex.adapters.CommitsAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCommitsBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
@ -43,7 +43,7 @@ public class CommitsActivity extends BaseActivity {
private TextView noData;
private ProgressBar progressBar;
private String TAG = "CommitsActivity";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private int pageSize = 1;
private RecyclerView recyclerView;
@ -85,7 +85,7 @@ public class CommitsActivity extends BaseActivity {
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
recyclerView = activityCommitsBinding.recyclerView;

View File

@ -8,10 +8,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
@ -38,16 +34,7 @@ import retrofit2.Callback;
public class CreateFileActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private Button newFileCreate;
private EditText newFileName;
private EditText newFileContent;
private EditText newFileCommitMessage;
private AutoCompleteTextView newFileBranches;
private String filePath;
private String fileSha;
private ActivityCreateFileBinding binding;
public static final int FILE_ACTION_CREATE = 0;
public static final int FILE_ACTION_DELETE = 1;
@ -55,6 +42,9 @@ public class CreateFileActivity extends BaseActivity {
private int fileAction = FILE_ACTION_CREATE;
private String filePath;
private String fileSha;
private final List<String> branches = new ArrayList<>();
private String repoOwner;
@ -66,154 +56,127 @@ public class CreateFileActivity extends BaseActivity {
super.onCreate(savedInstanceState);
ActivityCreateFileBinding activityCreateFileBinding = ActivityCreateFileBinding.inflate(getLayoutInflater());
setContentView(activityCreateFileBinding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
binding = ActivityCreateFileBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/");
repoOwner = parts[0];
repoName = parts[1];
closeActivity = activityCreateFileBinding.close;
newFileName = activityCreateFileBinding.newFileName;
newFileContent = activityCreateFileBinding.newFileContent;
newFileCommitMessage = activityCreateFileBinding.newFileCommitMessage;
TextView toolbarTitle = activityCreateFileBinding.toolbarTitle;
TextView toolbarTitle = binding.toolbarTitle;
newFileName.requestFocus();
assert imm != null;
imm.showSoftInput(newFileName, InputMethodManager.SHOW_IMPLICIT);
binding.newFileName.requestFocus();
initCloseListener();
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
assert inputMethodManager != null;
inputMethodManager.showSoftInput(binding.newFileName, InputMethodManager.SHOW_IMPLICIT);
closeActivity.setOnClickListener(onClickListener);
newFileCreate = activityCreateFileBinding.newFileCreate;
newFileContent.setOnTouchListener((touchView, motionEvent) -> {
binding.close.setOnClickListener(view -> finish());
binding.newFileContent.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 && (motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
if ((motionEvent.getAction() & MotionEvent.ACTION_UP) != 0 &&
(motionEvent.getActionMasked() & MotionEvent.ACTION_UP) != 0) {
touchView.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
});
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE) == FILE_ACTION_DELETE) {
fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE);
filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.deleteFileText, filePath));
newFileCreate.setText(R.string.deleteFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
binding.newFileCreate.setText(R.string.deleteFile);
newFileContent.setText(fileContents);
newFileContent.setEnabled(false);
newFileContent.setFocusable(false);
binding.newFileNameLayout.setVisibility(View.GONE);
binding.newFileContentLayout.setVisibility(View.GONE);
}
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT) == FILE_ACTION_EDIT) {
fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT);
filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.editFileText, filePath));
newFileCreate.setText(R.string.editFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
binding.newFileCreate.setText(R.string.editFile);
binding.newFileName.setText(filePath);
binding.newFileName.setEnabled(false);
binding.newFileName.setFocusable(false);
newFileContent.setText(fileContents);
binding.newFileContent.setText(getIntent().getStringExtra("fileContents"));
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
newFileBranches = activityCreateFileBinding.newFileBranches;
getBranches(repoOwner, repoName);
disableProcessButton();
NetworkStatusObserver networkStatusObserver = NetworkStatusObserver.getInstance(ctx);
networkStatusObserver.registerNetworkStatusListener(hasNetworkConnection -> newFileCreate.setEnabled(hasNetworkConnection));
networkStatusObserver.registerNetworkStatusListener(binding.newFileCreate::setEnabled);
newFileCreate.setOnClickListener(createFileListener);
binding.newFileCreate.setOnClickListener(v -> processNewFile());
}
private final View.OnClickListener createFileListener = v -> processNewFile();
private void processNewFile() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newFileName_ = newFileName.getText().toString();
String newFileContent_ = newFileContent.getText().toString();
String newFileBranchName_ = newFileBranches.getText().toString();
String newFileCommitMessage_ = newFileCommitMessage.getText().toString();
if(!connToInternet) {
String newFileName = binding.newFileName.getText() != null ? binding.newFileName.getText().toString() : "";
String newFileContent = binding.newFileContent.getText() != null ? binding.newFileContent.getText().toString() : "";
String newFileBranchName = binding.newFileBranches.getText() != null ? binding.newFileBranches.getText().toString() : "";
String newFileCommitMessage = binding.newFileCommitMessage.getText() != null ? binding.newFileCommitMessage.getText().toString() : "";
if(!AppUtil.hasNetworkConnection(appCtx)) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if(newFileName_.equals("") || newFileContent_.equals("") || newFileCommitMessage_.equals("")) {
if(((newFileName.isEmpty() || newFileContent.isEmpty()) && fileAction != FILE_ACTION_DELETE) || newFileCommitMessage.isEmpty()) {
Toasty.error(ctx, getString(R.string.newFileRequiredFields));
return;
}
if(!AppUtil.checkStringsWithDash(newFileBranchName_)) {
if(!AppUtil.checkStringsWithDash(newFileBranchName)) {
Toasty.error(ctx, getString(R.string.newFileInvalidBranchName));
return;
}
if(newFileCommitMessage_.length() > 255) {
if(newFileCommitMessage.length() > 255) {
Toasty.warning(ctx, getString(R.string.newFileCommitMessageError));
return;
}
else {
disableProcessButton();
disableProcessButton();
switch(fileAction) {
switch(fileAction) {
case FILE_ACTION_CREATE:
createNewFile(Authorization.get(ctx), repoOwner, repoName, newFileName_, AppUtil.encodeBase64(newFileContent_), newFileCommitMessage_, newFileBranchName_);
break;
case FILE_ACTION_CREATE:
createNewFile(repoOwner, repoName, newFileName, AppUtil.encodeBase64(newFileContent), newFileCommitMessage, newFileBranchName);
break;
case FILE_ACTION_DELETE:
deleteFile(Authorization.get(ctx), repoOwner, repoName, filePath, newFileCommitMessage_, newFileBranchName_, fileSha);
break;
case FILE_ACTION_DELETE:
deleteFile(repoOwner, repoName, filePath, newFileCommitMessage, newFileBranchName, fileSha);
break;
case FILE_ACTION_EDIT:
editFile(Authorization.get(ctx), repoOwner, repoName, filePath,
AppUtil.encodeBase64(newFileContent_), newFileCommitMessage_, newFileBranchName_, fileSha);
break;
case FILE_ACTION_EDIT:
editFile(repoOwner, repoName, filePath, AppUtil.encodeBase64(newFileContent), newFileCommitMessage, newFileBranchName, fileSha);
break;
}
}
}
private void createNewFile(final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileCommitMessage, String branchName) {
private void createNewFile(String repoOwner, String repoName, String fileName, String fileContent, String fileCommitMessage, String branchName) {
NewFile createNewFileJsonStr = branches.contains(branchName) ?
new NewFile(branchName, fileContent, fileCommitMessage, "") :
@ -221,7 +184,7 @@ public class CreateFileActivity extends BaseActivity {
Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx)
.createNewFile(token, repoOwner, repoName, fileName, createNewFileJsonStr);
.createNewFile(Authorization.get(ctx), repoOwner, repoName, fileName, createNewFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@ -268,7 +231,7 @@ public class CreateFileActivity extends BaseActivity {
}
private void deleteFile(final String token, String repoOwner, String repoName, String fileName, String fileCommitMessage, String branchName, String fileSha) {
private void deleteFile(String repoOwner, String repoName, String fileName, String fileCommitMessage, String branchName, String fileSha) {
DeleteFile deleteFileJsonStr = branches.contains(branchName) ?
new DeleteFile(branchName, fileCommitMessage, "", fileSha) :
@ -276,42 +239,42 @@ public class CreateFileActivity extends BaseActivity {
Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx)
.deleteFile(token, repoOwner, repoName, fileName, deleteFileJsonStr);
.deleteFile(Authorization.get(ctx), repoOwner, repoName, fileName, deleteFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
switch(response.code()) {
enableProcessButton();
Toasty.info(ctx, getString(R.string.deleteFileMessage, tinyDB.getString("repoBranch")));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
finish();
}
else if(response.code() == 401) {
case 200:
enableProcessButton();
Toasty.info(ctx, getString(R.string.deleteFileMessage, tinyDB.getString("repoBranch")));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
finish();
break;
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
if(response.code() == 404) {
case 401:
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 404:
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
}
else {
break;
default:
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
}
break;
}
}
@ -325,7 +288,7 @@ public class CreateFileActivity extends BaseActivity {
}
private void editFile(final String token, String repoOwner, String repoName, String fileName, String fileContent, String fileCommitMessage, String branchName, String fileSha) {
private void editFile(String repoOwner, String repoName, String fileName, String fileContent, String fileCommitMessage, String branchName, String fileSha) {
EditFile editFileJsonStr = branches.contains(branchName) ?
new EditFile(branchName, fileCommitMessage, "", fileSha, fileContent) :
@ -333,7 +296,7 @@ public class CreateFileActivity extends BaseActivity {
Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx)
.editFile(token, repoOwner, repoName, fileName, editFileJsonStr);
.editFile(Authorization.get(ctx), repoOwner, repoName, fileName, editFileJsonStr);
call.enqueue(new Callback<JsonElement>() {
@ -402,8 +365,8 @@ public class CreateFileActivity extends BaseActivity {
ArrayAdapter<String> adapter = new ArrayAdapter<>(CreateFileActivity.this, R.layout.list_spinner_items, branches);
newFileBranches.setAdapter(adapter);
newFileBranches.setText(tinyDB.getString("repoBranch"), false);
binding.newFileBranches.setAdapter(adapter);
binding.newFileBranches.setText(tinyDB.getString("repoBranch"), false);
enableProcessButton();
@ -419,19 +382,7 @@ public class CreateFileActivity extends BaseActivity {
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
newFileCreate.setEnabled(false);
}
private void enableProcessButton() {
newFileCreate.setEnabled(true);
}
private void disableProcessButton() { binding.newFileCreate.setEnabled(false); }
private void enableProcessButton() { binding.newFileCreate.setEnabled(true); }
}

View File

@ -30,7 +30,7 @@ import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
@ -51,7 +51,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private CustomLabelsSelectionDialogBinding labelsBinding;
private CustomAssigneesSelectionDialogBinding assigneesBinding;
private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private Dialog dialogLabels;
private Dialog dialogAssignees;
private String labelsSetter;
@ -93,7 +93,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
// require gitea 1.12 or higher
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
viewBinding.newIssueTitle.requestFocus();

View File

@ -24,13 +24,12 @@ import org.mian.gitnex.databinding.ActivityCreatePrBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
@ -43,7 +42,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
private View.OnClickListener onClickListener;
private ActivityCreatePrBinding viewBinding;
private CustomLabelsSelectionDialogBinding labelsBinding;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private Dialog dialogLabels;
private String labelsSetter;
private List<Integer> labelsIds = new ArrayList<>();
@ -80,7 +79,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
// require gitea 1.12 or higher
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
viewBinding.prBody.setOnTouchListener((touchView, motionEvent) -> {
@ -165,14 +164,14 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
CreatePullRequest createPullRequest = new CreatePullRequest(prTitle, prDescription, loginUid, mergeInto, pullFrom, milestoneId, dueDate, assignees, labelsIds);
Call<ResponseBody> transferCall = RetrofitClient
Call<Void> transferCall = RetrofitClient
.getApiInterface(appCtx)
.createPullRequest(instanceToken, repoOwner, repoName, createPullRequest);
transferCall.enqueue(new Callback<ResponseBody>() {
transferCall.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
public void onResponse(@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
disableProcessButton();
@ -199,7 +198,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericServerResponseError));

View File

@ -27,7 +27,7 @@ import org.mian.gitnex.databinding.ActivityEditIssueBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.text.DateFormat;
@ -45,7 +45,7 @@ import retrofit2.Callback;
public class EditIssueActivity extends BaseActivity implements View.OnClickListener {
private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private EditText editIssueTitle;
private EditText editIssueDescription;
@ -93,7 +93,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
editIssueTitle.requestFocus();

View File

@ -1,13 +1,11 @@
package org.mian.gitnex.activities;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import org.gitnex.tea4j.models.FileDiffView;
import org.mian.gitnex.R;
@ -15,6 +13,7 @@ import org.mian.gitnex.adapters.FilesDiffAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityFileDiffBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.ParseDiff;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
@ -23,7 +22,7 @@ import java.io.IOException;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -52,8 +51,6 @@ public class FileDiffActivity extends BaseActivity {
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = activityFileDiffBinding.close;
toolbarTitle = activityFileDiffBinding.toolbarTitle;
@ -71,80 +68,69 @@ public class FileDiffActivity extends BaseActivity {
String pullIndex = tinyDb.getString("issueNumber");
boolean apiCall = !new Version(tinyDb.getString("giteaVersion")).less("1.13.0");
getPullDiffContent(repoOwner, repoName, pullIndex, instanceToken, apiCall);
getPullDiffContent(repoOwner, repoName, pullIndex, apiCall);
}
private void getPullDiffContent(String owner, String repo, String pullIndex, String token, boolean apiCall) {
private void getPullDiffContent(String owner, String repo, String pullIndex, boolean apiCall) {
Call<ResponseBody> call;
if(apiCall) {
Thread thread = new Thread(() -> {
call = RetrofitClient.getApiInterface(ctx).getPullDiffContent(token, owner, repo, pullIndex);
}
else {
Call<ResponseBody> call = apiCall ?
RetrofitClient.getApiInterface(ctx).getPullDiffContent(Authorization.get(ctx), owner, repo, pullIndex) :
RetrofitClient.getWebInterface(ctx).getPullDiffContent(Authorization.getWeb(ctx), owner, repo, pullIndex);
call = RetrofitClient.getWebInterface(ctx).getPullDiffContent(owner, repo, pullIndex);
}
try {
call.enqueue(new Callback<ResponseBody>() {
Response<ResponseBody> response = call.execute();
assert response.body() != null;
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
switch(response.code()) {
if(response.code() == 200) {
case 200:
List<FileDiffView> fileDiffViews = ParseDiff.getFileDiffViewArray(response.body().string());
try {
int filesCount = fileDiffViews.size();
assert response.body() != null;
String toolbarTitleText = (filesCount > 1) ?
getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)) :
getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount));
List<FileDiffView> fileContentsArray = ParseDiff.getFileDiffViewArray(response.body().string());
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, getSupportFragmentManager(), fileDiffViews);
int filesCount = fileContentsArray.size();
if(filesCount > 1) {
runOnUiThread(() -> {
toolbarTitle.setText(toolbarTitleText);
mListView.setAdapter(adapter);
mProgressBar.setVisibility(View.GONE);
});
break;
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeader, Integer.toString(filesCount)));
}
else {
case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx,
getString(R.string.alertDialogTokenRevokedTitle),
getString(R.string.alertDialogTokenRevokedMessage),
getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
toolbarTitle.setText(getResources().getString(R.string.fileDiffViewHeaderSingle, Integer.toString(filesCount)));
}
case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
break;
FilesDiffAdapter adapter = new FilesDiffAdapter(ctx, getSupportFragmentManager(), fileContentsArray);
mListView.setAdapter(adapter);
case 404:
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
break;
mProgressBar.setVisibility(View.GONE);
}
catch(IOException e) {
default:
Toasty.error(ctx, getString(R.string.labelGeneralError));
e.printStackTrace();
}
}
else if(response.code() == 401) {
} catch(IOException ignored) {}
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
thread.start();
}
private void initCloseListener() {
@ -153,6 +139,7 @@ public class FileDiffActivity extends BaseActivity {
getIntent().removeExtra("singleFileName");
finish();
};
}

View File

@ -1,29 +1,21 @@
package org.mian.gitnex.activities;
import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Base64;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import com.github.barteksc.pdfviewer.PDFView;
import androidx.core.app.NotificationCompat;
import com.github.barteksc.pdfviewer.util.FitPolicy;
import com.github.chrisbanes.photoview.PhotoView;
import com.vdurmont.emoji.EmojiParser;
import org.apache.commons.io.FileUtils;
import org.gitnex.tea4j.models.Files;
@ -33,19 +25,19 @@ import org.mian.gitnex.databinding.ActivityFileViewBinding;
import org.mian.gitnex.fragments.BottomSheetFileViewerFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Images;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.highlightjs.HighlightJsView;
import org.mian.gitnex.helpers.highlightjs.models.Theme;
import java.io.File;
import org.mian.gitnex.notifications.Notifications;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Objects;
import java.util.Arrays;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
@ -53,74 +45,38 @@ import retrofit2.Callback;
public class FileViewActivity extends BaseActivity implements BottomSheetFileViewerFragment.BottomSheetListener {
private View.OnClickListener onClickListener;
private TextView singleFileContents;
private LinearLayout singleFileContentsFrame;
private HighlightJsView singleCodeContents;
private PhotoView imageView;
private ProgressBar mProgressBar;
private byte[] imageData;
private PDFView pdfView;
private LinearLayout pdfViewFrame;
private byte[] decodedPdf;
private ActivityFileViewBinding binding;
private Boolean pdfNightMode;
private String singleFileName;
private String fileSha;
private Files file;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityFileViewBinding activityFileViewBinding = ActivityFileViewBinding.inflate(getLayoutInflater());
setContentView(activityFileViewBinding.getRoot());
binding = ActivityFileViewBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Toolbar toolbar = activityFileViewBinding.toolbar;
setSupportActionBar(toolbar);
setSupportActionBar(binding.toolbar);
tinyDB.putBoolean("enableMarkdownInFileView", false);
file = (Files) getIntent().getSerializableExtra("file");
binding.close.setOnClickListener(view -> finish());
binding.toolbarTitle.setMovementMethod(new ScrollingMovementMethod());
binding.toolbarTitle.setText(file.getPath());
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String loginUid = tinyDB.getString("loginUid");
final String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
String repoOwner = parts[0];
String repoName = parts[1];
tinyDB.putBoolean("enableMarkdownInFileView", false);
getSingleFileContents(repoOwner, repoName, file.getPath(), repoBranch);
ImageView closeActivity = activityFileViewBinding.close;
singleFileContents = activityFileViewBinding.singleFileContents;
singleCodeContents = activityFileViewBinding.singleCodeContents;
imageView = activityFileViewBinding.imageView;
mProgressBar = activityFileViewBinding.progressBar;
pdfView = activityFileViewBinding.pdfView;
pdfViewFrame = activityFileViewBinding.pdfViewFrame;
singleFileContentsFrame = activityFileViewBinding.singleFileContentsFrame;
singleFileName = getIntent().getStringExtra("singleFileName");
TextView toolbar_title = activityFileViewBinding.toolbarTitle;
toolbar_title.setMovementMethod(new ScrollingMovementMethod());
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
tinyDB.putString("downloadFileContents", "");
try {
singleFileName = URLDecoder.decode(singleFileName, "UTF-8");
singleFileName = singleFileName.replaceAll("//", "/");
singleFileName = singleFileName.startsWith("/") ? singleFileName.substring(1) : singleFileName;
}
catch(UnsupportedEncodingException e) {
Log.i("singleFileName", singleFileName);
}
toolbar_title.setText(singleFileName);
getSingleFileContents(instanceToken, repoOwner, repoName, singleFileName, repoBranch);
}
@Override
@ -128,166 +84,201 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
super.onResume();
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
String loginUid = tinyDB.getString("loginUid");
String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
if(tinyDB.getBoolean("fileModified")) {
getSingleFileContents(instanceToken, repoOwner, repoName, singleFileName, repoBranch);
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
getSingleFileContents(repoOwner, repoName, file.getPath(), repoBranch);
tinyDB.putBoolean("fileModified", false);
}
}
private void getSingleFileContents(final String owner, String repo, final String filename, String ref) {
private void getSingleFileContents(String token, final String owner, String repo, final String filename, String ref) {
Thread thread = new Thread(() -> {
Call<Files> call = RetrofitClient.getApiInterface(ctx).getSingleFileContents(token, owner, repo, filename, ref);
Call<ResponseBody> call = RetrofitClient
.getWebInterface(ctx)
.getFileContents(Authorization.getWeb(ctx), owner, repo, ref, filename);
call.enqueue(new Callback<Files>() {
try {
@Override
public void onResponse(@NonNull Call<Files> call, @NonNull retrofit2.Response<Files> response) {
Response<ResponseBody> response = call.execute();
if(response.code() == 200) {
assert response.body() != null;
ResponseBody responseBody = response.body();
if(!response.body().getContent().equals("")) {
if(responseBody != null) {
runOnUiThread(() -> binding.progressBar.setVisibility(View.GONE));
String fileExtension = FileUtils.getExtension(filename);
mProgressBar.setVisibility(View.GONE);
fileSha = response.body().getSha();
// download file meta
tinyDB.putString("downloadFileName", filename);
tinyDB.putString("downloadFileContents", response.body().getContent());
boolean unknown = false;
boolean processable = false;
switch(AppUtil.getFileType(fileExtension)) {
case IMAGE:
singleFileContentsFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
// See https://developer.android.com/guide/topics/media/media-formats#core
if(Arrays.asList("bmp", "gif", "jpg", "jpeg", "png", "webp", "heic", "heif").contains(fileExtension.toLowerCase())) {
imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT);
imageView.setImageBitmap(Images.scaleImage(imageData, 1920));
processable = true;
byte[] pictureBytes = responseBody.bytes();
runOnUiThread(() -> {
binding.contents.setVisibility(View.GONE);
binding.pdfViewFrame.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.GONE);
binding.photoView.setVisibility(View.VISIBLE);
binding.photoView.setImageBitmap(Images.scaleImage(pictureBytes, 1920));
});
}
break;
case UNKNOWN:
case TEXT:
imageView.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
switch(tinyDB.getInt("fileviewerSourceCodeThemeId")) {
case 1: singleCodeContents.setTheme(Theme.ARDUINO_LIGHT); break;
case 2: singleCodeContents.setTheme(Theme.GITHUB); break;
case 3: singleCodeContents.setTheme(Theme.FAR); break;
case 4: singleCodeContents.setTheme(Theme.IR_BLACK); break;
case 5: singleCodeContents.setTheme(Theme.ANDROID_STUDIO); break;
default: singleCodeContents.setTheme(Theme.MONOKAI_SUBLIME);
if(file.getSize() > Constants.maximumFileViewerSize) {
break;
}
singleCodeContents.setSource(AppUtil.decodeBase64(response.body().getContent()));
processable = true;
String text = responseBody.string();
runOnUiThread(() -> {
binding.photoView.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.GONE);
binding.pdfViewFrame.setVisibility(View.GONE);
switch(tinyDB.getInt("fileviewerSourceCodeThemeId")) {
case 1: binding.contents.setTheme(Theme.ARDUINO_LIGHT); break;
case 2: binding.contents.setTheme(Theme.GITHUB); break;
case 3: binding.contents.setTheme(Theme.FAR); break;
case 4: binding.contents.setTheme(Theme.IR_BLACK); break;
case 5: binding.contents.setTheme(Theme.ANDROID_STUDIO); break;
default: binding.contents.setTheme(Theme.MONOKAI_SUBLIME);
}
binding.contents.setVisibility(View.VISIBLE);
binding.contents.setContent(text);
});
break;
case DOCUMENT:
if(fileExtension.equalsIgnoreCase("pdf")) {
imageView.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.VISIBLE);
processable = true;
pdfNightMode = tinyDB.getBoolean("enablePdfMode");
decodedPdf = Base64.decode(response.body().getContent(), Base64.DEFAULT);
byte[] documentBytes = responseBody.bytes();
pdfView.fromBytes(decodedPdf)
.enableSwipe(true)
.swipeHorizontal(false)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(false)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true)
.spacing(0)
.autoSpacing(true)
.pageFitPolicy(FitPolicy.WIDTH)
.fitEachPage(true)
.pageSnap(false)
.pageFling(true)
.nightMode(pdfNightMode).load();
runOnUiThread(() -> {
binding.photoView.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.GONE);
binding.contents.setVisibility(View.GONE);
pdfNightMode = tinyDB.getBoolean("enablePdfMode");
binding.pdfViewFrame.setVisibility(View.VISIBLE);
binding.pdfView.fromBytes(documentBytes)
.enableSwipe(true)
.swipeHorizontal(false)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(false)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true)
.spacing(0)
.autoSpacing(true)
.pageFitPolicy(FitPolicy.WIDTH)
.fitEachPage(true)
.pageSnap(false)
.pageFling(true)
.nightMode(pdfNightMode).load();
});
}
else {
unknown = true;
}
break;
case UNKNOWN:
default:
unknown = true;
break;
}
if(unknown) { // While the file could still be non-binary,
if(!processable) { // While the file could still be non-binary,
// it's better we don't show it (to prevent any crashes and/or unwanted behavior) and let the user download it instead.
imageView.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
responseBody.close();
singleFileContents.setText(getString(R.string.excludeFilesInFileViewer));
singleFileContents.setGravity(Gravity.CENTER);
singleFileContents.setTypeface(null, Typeface.BOLD);
runOnUiThread(() -> {
binding.photoView.setVisibility(View.GONE);
binding.contents.setVisibility(View.GONE);
binding.pdfViewFrame.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.VISIBLE);
binding.markdown.setText(getString(R.string.excludeFilesInFileViewer));
binding.markdown.setGravity(Gravity.CENTER);
binding.markdown.setTypeface(null, Typeface.BOLD);
});
}
}
else {
} else {
runOnUiThread(() -> {
binding.markdown.setText("");
binding.progressBar.setVisibility(View.GONE);
});
}
} else {
switch(response.code()) {
case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx,
getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
break;
case 404:
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
break;
default:
Toasty.error(ctx, getString(R.string.labelGeneralError));
singleFileContents.setText("");
mProgressBar.setVisibility(View.GONE);
}
}
else if(response.code() == 401) {
} catch(IOException ignored) {}
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<Files> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
thread.start();
}
@Override
@ -297,11 +288,11 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
inflater.inflate(R.menu.files_view_menu, menu);
String fileExtension = FileUtils.getExtension(singleFileName);
if(!FileUtils.getExtension(file.getName())
.equalsIgnoreCase("md")) {
if(!fileExtension.equalsIgnoreCase("md")) {
menu.getItem(0).setVisible(false);
menu.getItem(0)
.setVisible(false);
}
return true;
@ -316,35 +307,36 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
finish();
return true;
}
else if(id == R.id.genericMenu) {
} else if(id == R.id.genericMenu) {
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true;
}
else if(id == R.id.markdown) {
new Markdown(ctx, EmojiParser.parseToUnicode(AppUtil.decodeBase64(tinyDB.getString("downloadFileContents"))), singleFileContents);
} else if(id == R.id.markdown) {
if(!tinyDB.getBoolean("enableMarkdownInFileView")) {
singleCodeContents.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setVisibility(View.VISIBLE);
tinyDB.putBoolean("enableMarkdownInFileView", true);
}
else {
new Markdown(ctx, EmojiParser.parseToUnicode(binding.contents.getContent()), binding.markdown);
binding.contents.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.VISIBLE);
tinyDB.putBoolean("enableMarkdownInFileView", true);
} else {
binding.markdownFrame.setVisibility(View.GONE);
binding.contents.setVisibility(View.VISIBLE);
singleCodeContents.setVisibility(View.VISIBLE);
singleFileContentsFrame.setVisibility(View.GONE);
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setSource(AppUtil.decodeBase64(tinyDB.getString("downloadFileContents")));
tinyDB.putBoolean("enableMarkdownInFileView", false);
}
return true;
}
else {
} else {
return super.onOptionsItemSelected(item);
}
@ -360,102 +352,118 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
if("deleteFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
String data = AppUtil.getFileType(fileExtension) == AppUtil.FileType.TEXT ?
AppUtil.decodeBase64(tinyDB.getString("downloadFileContents")) : "";
Intent intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", CreateFileActivity.FILE_ACTION_DELETE);
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
intent.putExtra("fileContents", data);
intent.putExtra("filePath", file.getPath());
intent.putExtra("fileSha", file.getSha());
ctx.startActivity(intent);
}
if("editFile".equals(text)) {
String fileExtension = FileUtils.getExtension(singleFileName);
if(binding.contents.getContent() != null &&
!binding.contents.getContent().isEmpty()) {
switch(AppUtil.getFileType(fileExtension)) {
Intent intent = new Intent(ctx, CreateFileActivity.class);
case TEXT:
intent.putExtra("fileAction", CreateFileActivity.FILE_ACTION_EDIT);
intent.putExtra("filePath", file.getPath());
intent.putExtra("fileSha", file.getSha());
intent.putExtra("fileContents", binding.contents.getContent());
Intent intent = new Intent(ctx, CreateFileActivity.class);
ctx.startActivity(intent);
intent.putExtra("fileAction", CreateFileActivity.FILE_ACTION_EDIT);
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
intent.putExtra("fileContents", AppUtil.decodeBase64(tinyDB.getString("downloadFileContents")));
} else {
ctx.startActivity(intent);
break;
default:
Toasty.error(ctx, getString(R.string.fileTypeCannotBeEdited));
Toasty.error(ctx, getString(R.string.fileTypeCannotBeEdited));
}
}
}
private void requestFileDownload() {
if(!tinyDB.getString("downloadFileContents").isEmpty()) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
File outputFileName = new File(tinyDB.getString("downloadFileName"));
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_TITLE, file.getName());
intent.setType("*/*");
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
activityResultLauncher.launch(intent);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_TITLE, outputFileName.getName());
fileDownloadActivityResultLauncher.launch(intent);
}
else {
Toasty.warning(ctx, getString(R.string.waitLoadingDownloadFile));
}
}
ActivityResultLauncher<Intent> fileDownloadActivityResultLauncher =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
assert result.getData() != null;
try {
try {
assert data != null;
Uri uri = data.getData();
OutputStream outputStream = getContentResolver().openOutputStream(result.getData().getData());
assert uri != null;
OutputStream outputStream = getContentResolver().openOutputStream(uri);
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, ctx.getPackageName())
.setContentTitle(getString(R.string.fileViewerNotificationTitleStarted))
.setContentText(getString(R.string.fileViewerNotificationDescriptionStarted, file.getName()))
.setSmallIcon(R.drawable.gitnex_transparent)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setChannelId(Constants.downloadNotificationChannelId)
.setProgress(100, 0, false)
.setOngoing(true);
byte[] dataAsBytes = Base64.decode(tinyDB.getString("downloadFileContents"), 0);
int notificationId = Notifications.uniqueNotificationId(ctx);
assert outputStream != null;
outputStream.write(dataAsBytes);
outputStream.close();
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);;
notificationManager.notify(notificationId, builder.build());
Toasty.success(ctx, getString(R.string.downloadFileSaved));
}
catch(IOException e) {
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
Log.e("errorFileDownloading", Objects.requireNonNull(e.getMessage()));
}
}
Thread thread = new Thread(() -> {
});
try {
private void initCloseListener() {
Call<ResponseBody> call = RetrofitClient
.getWebInterface(ctx)
.getFileContents(Authorization.getWeb(ctx), repoOwner, repoName, repoBranch, file.getPath());
onClickListener = view -> {
Response<ResponseBody> response = call.execute();
getIntent().removeExtra("singleFileName");
finish();
};
}
assert response.body() != null;
AppUtil.copyProgress(response.body().byteStream(), outputStream, file.getSize(), progress -> {
builder.setProgress(100, progress, false);
notificationManager.notify(notificationId, builder.build());
});
builder.setContentTitle(getString(R.string.fileViewerNotificationTitleFinished))
.setContentText(getString(R.string.fileViewerNotificationDescriptionFinished, file.getName()));
} catch(IOException ignored) {
builder.setContentTitle(getString(R.string.fileViewerNotificationTitleFailed))
.setContentText(getString(R.string.fileViewerNotificationDescriptionFailed, file.getName()));
} finally {
builder.setProgress(0,0,false)
.setOngoing(false);
notificationManager.notify(notificationId, builder.build());
}
});
thread.start();
} catch(IOException ignored) {}
}
});
}

View File

@ -10,7 +10,6 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -61,8 +60,7 @@ import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
import jp.wasabeef.picasso.transformations.BlurTransformation;
import retrofit2.Call;
import retrofit2.Callback;
@ -73,12 +71,10 @@ import retrofit2.Callback;
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, BottomSheetDraftsFragment.BottomSheetListener {
private DrawerLayout drawer;
private BlurView blurView;
private TextView userFullName;
private TextView userEmail;
private ImageView userAvatar;
private ImageView userAvatarBackground;
private ViewGroup navHeaderFrame;
private TextView toolbarTitle;
private Typeface myTypeface;
@ -273,12 +269,10 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
String userFullNameNav = tinyDB.getString("userFullname");
String userAvatarNav = tinyDB.getString("userAvatar");
blurView = hView.findViewById(R.id.blurView);
userEmail = hView.findViewById(R.id.userEmail);
userFullName = hView.findViewById(R.id.userFullname);
userAvatar = hView.findViewById(R.id.userAvatar);
userAvatarBackground = hView.findViewById(R.id.userAvatarBackground);
navHeaderFrame = hView.findViewById(R.id.navHeaderFrame);
List<UserAccount> userAccountsList;
userAccountsList = new ArrayList<>();
@ -323,24 +317,18 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
PicassoService.getInstance(ctx).get()
.load(userAvatarNav)
.transform(new BlurTransformation(ctx))
.into(userAvatarBackground, new com.squareup.picasso.Callback() {
@Override
public void onSuccess() {
int textColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground);
int textColor = new ColorInverter().getImageViewContrastColor(userAvatar);
userFullName.setTextColor(textColor);
userEmail.setTextColor(textColor);
blurView.setupWith(navHeaderFrame)
.setBlurAlgorithm(new RenderScriptBlur(ctx))
.setBlurRadius(5)
.setHasFixedTransformationMatrix(false);
}
@Override
public void onError(Exception e) {}
@Override public void onError(Exception e) {}
});
}
@ -350,6 +338,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
drawer.closeDrawers();
});
getNotificationsCount(instanceToken);
@ -403,22 +392,21 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
switch(launchFragmentByHandler) {
case "repos":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
return;
case "org":
case "org":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
return;
case "notification":
case "notification":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications);
return;
case "explore":
case "explore":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore);
return;
@ -438,49 +426,48 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
switch(tinyDB.getInt("homeScreenId")) {
case 1:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos);
break;
case 2:
case 2:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
break;
case 3:
case 3:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
break;
case 4:
case 4:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
break;
case 5:
case 5:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore);
break;
case 6:
case 6:
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_comments_draft);
break;
case 7:
case 7:
toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications);
break;
default:
default:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);

View File

@ -21,7 +21,6 @@ import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
import java.util.Objects;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
@ -170,12 +169,12 @@ public class MergePullRequestActivity extends BaseActivity {
MergePullRequest mergePR = new MergePullRequest(Do, mergePRDT, mergeTitle);
Call<ResponseBody> call = RetrofitClient.getApiInterface(ctx).mergePullRequest(Authorization.get(ctx), repoOwner, repoName, prIndex, mergePR);
Call<Void> call = RetrofitClient.getApiInterface(ctx).mergePullRequest(Authorization.get(ctx), repoOwner, repoName, prIndex, mergePR);
call.enqueue(new Callback<ResponseBody>() {
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull retrofit2.Response<ResponseBody> response) {
public void onResponse(@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
if(response.code() == 200) {
@ -244,7 +243,7 @@ public class MergePullRequestActivity extends BaseActivity {
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();

View File

@ -27,7 +27,7 @@ import org.mian.gitnex.adapters.RepoForksAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityRepoForksBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
@ -46,7 +46,7 @@ public class RepoForksActivity extends BaseActivity {
private TextView noData;
private ProgressBar progressBar;
private String TAG = "RepositoryForks";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private int pageSize = 1;
private RecyclerView recyclerView;
@ -90,7 +90,7 @@ public class RepoForksActivity extends BaseActivity {
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
recyclerView = activityRepoForksBinding.recyclerView;

View File

@ -1,12 +1,8 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsFileviewerBinding;
import org.mian.gitnex.helpers.Toasty;
@ -17,40 +13,29 @@ import org.mian.gitnex.helpers.Toasty;
public class SettingsFileViewerActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private static final String[] fileViewerSourceCodeThemesList = {"Sublime", "Arduino Light", "Github", "Far ", "Ir Black", "Android Studio"};
private static int fileViewerSourceCodeThemesSelectedChoice = 0;
@SuppressLint("DefaultLocale")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivitySettingsFileviewerBinding activitySettingsFileviewerBinding = ActivitySettingsFileviewerBinding.inflate(getLayoutInflater());
setContentView(activitySettingsFileviewerBinding.getRoot());
ActivitySettingsFileviewerBinding binding = ActivitySettingsFileviewerBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
ImageView closeActivity = activitySettingsFileviewerBinding.close;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
TextView fileViewerSourceCodeThemesSelected = activitySettingsFileviewerBinding.sourceCodeThemeSelected; // setter for fileviewer theme
LinearLayout sourceCodeThemeFrame = activitySettingsFileviewerBinding.sourceCodeThemeFrame;
SwitchMaterial pdfModeSwitch = activitySettingsFileviewerBinding.switchPdfMode;
if(!tinyDB.getString("fileviewerSourceCodeThemeStr").isEmpty()) {
fileViewerSourceCodeThemesSelected.setText(tinyDB.getString("fileviewerSourceCodeThemeStr"));
}
binding.close.setOnClickListener(view -> finish());
if(fileViewerSourceCodeThemesSelectedChoice == 0) {
fileViewerSourceCodeThemesSelectedChoice = tinyDB.getInt("fileviewerThemeId");
}
pdfModeSwitch.setChecked(tinyDB.getBoolean("enablePdfMode"));
binding.sourceCodeThemeSelected.setText(tinyDB.getString("fileviewerSourceCodeThemeStr", fileViewerSourceCodeThemesList[0]));
binding.switchPdfMode.setChecked(tinyDB.getBoolean("enablePdfMode"));
// fileviewer srouce code theme selection dialog
sourceCodeThemeFrame.setOnClickListener(view -> {
// fileviewer source code theme selection dialog
binding.sourceCodeThemeFrame.setOnClickListener(view -> {
AlertDialog.Builder fvtsBuilder = new AlertDialog.Builder(SettingsFileViewerActivity.this);
@ -60,7 +45,7 @@ public class SettingsFileViewerActivity extends BaseActivity {
fvtsBuilder.setSingleChoiceItems(fileViewerSourceCodeThemesList, fileViewerSourceCodeThemesSelectedChoice, (dialogInterfaceTheme, i) -> {
fileViewerSourceCodeThemesSelectedChoice = i;
fileViewerSourceCodeThemesSelected.setText(fileViewerSourceCodeThemesList[i]);
binding.sourceCodeThemeSelected.setText(fileViewerSourceCodeThemesList[i]);
tinyDB.putString("fileviewerSourceCodeThemeStr", fileViewerSourceCodeThemesList[i]);
tinyDB.putInt("fileviewerSourceCodeThemeId", i);
@ -69,21 +54,20 @@ public class SettingsFileViewerActivity extends BaseActivity {
});
AlertDialog cfDialog = fvtsBuilder.create();
cfDialog.show();
AlertDialog alertDialog = fvtsBuilder.create();
alertDialog.show();
});
// pdf night mode switcher
pdfModeSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
binding.switchPdfMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("enablePdfMode", isChecked);
tinyDB.putString("enablePdfModeInit", "yes");
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
}
private void initCloseListener() {
onClickListener = view -> finish();
});
}
}

View File

@ -8,7 +8,7 @@ import androidx.appcompat.app.AlertDialog;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsNotificationsBinding;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.notifications.Notifications;
@ -33,7 +33,7 @@ public class SettingsNotificationsActivity extends BaseActivity {
viewBinding.close.setOnClickListener(onClickListener);
viewBinding.pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), tinyDB.getInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay)));
viewBinding.pollingDelaySelected.setText(String.format(getString(R.string.pollingDelaySelectedText), tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay)));
viewBinding.chooseColorState.setCardBackgroundColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
viewBinding.enableNotificationsMode.setChecked(tinyDB.getBoolean("notificationsEnabled", true));
@ -52,9 +52,9 @@ public class SettingsNotificationsActivity extends BaseActivity {
viewBinding.pollingDelayFrame.setOnClickListener(v -> {
NumberPicker numberPicker = new NumberPicker(ctx);
numberPicker.setMinValue(StaticGlobalVariables.minimumPollingDelay);
numberPicker.setMaxValue(StaticGlobalVariables.maximumPollingDelay);
numberPicker.setValue(tinyDB.getInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay));
numberPicker.setMinValue(Constants.minimumPollingDelay);
numberPicker.setMaxValue(Constants.maximumPollingDelay);
numberPicker.setValue(tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay));
numberPicker.setWrapSelectorWheel(true);
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
@ -76,6 +76,7 @@ public class SettingsNotificationsActivity extends BaseActivity {
builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
builder.setView(numberPicker);
builder.create().show();
});
// lights switcher

View File

@ -14,7 +14,6 @@ import androidx.recyclerview.widget.RecyclerView;
import org.apache.commons.io.FileUtils;
import org.gitnex.tea4j.models.Files;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import java.util.ArrayList;
import java.util.List;
@ -33,13 +32,12 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
public interface FilesAdapterListener {
void onClickDir(String str);
void onClickFile(String str);
void onClickFile(Files file);
}
class FilesViewHolder extends RecyclerView.ViewHolder {
private String fileType;
private Files file;
private final ImageView fileTypeIs;
private final TextView fileName;
@ -55,21 +53,7 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
//ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu);
fileName.setOnClickListener(v -> {
Context context = v.getContext();
if(fileType.equals("file")) {
filesListener.onClickFile(fileName.getText().toString());
}
else if(fileType.equals("dir")) {
filesListener.onClickDir(fileName.getText().toString());
}
else {
Toasty.warning(context, context.getString(R.string.filesGenericError));
}
});
fileName.setOnClickListener(v -> filesListener.onClickFile(file));
/*filesDropdownMenu.setOnClickListener(new View.OnClickListener() {
@ -170,25 +154,36 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
Files currentItem = alteredFiles.get(position);
holder.fileType = currentItem.getType();
holder.file = currentItem;
holder.fileName.setText(currentItem.getName());
if(currentItem.getType().equals("file")) {
switch(currentItem.getType()) {
case "file":
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(mCtx, R.drawable.ic_file));
holder.fileInfo.setVisibility(View.VISIBLE);
holder.fileInfo.setText(FileUtils.byteCountToDisplaySize(currentItem.getSize()));
break;
case "dir":
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(mCtx, R.drawable.ic_directory));
holder.fileInfo.setVisibility(View.GONE);
break;
case "submodule":
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(mCtx, R.drawable.ic_submodule));
holder.fileInfo.setVisibility(View.GONE);
break;
case "symlink":
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(mCtx, R.drawable.ic_symlink));
holder.fileInfo.setVisibility(View.GONE);
break;
default:
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(mCtx, R.drawable.ic_question));
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(mCtx, R.drawable.ic_file));
holder.fileInfo.setVisibility(View.VISIBLE);
holder.fileInfo.setText(FileUtils.byteCountToDisplaySize(currentItem.getSize()));
}
else if(currentItem.getType().equals("dir")) {
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(mCtx, R.drawable.ic_directory));
holder.fileInfo.setVisibility(View.GONE);
}
else {
holder.fileTypeIs.setImageDrawable(AppCompatResources.getDrawable(mCtx, R.drawable.ic_question));
}
}
@Override
@ -224,6 +219,7 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
results.values = filteredList;
return results;
}
@Override

View File

@ -102,9 +102,8 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
class IssuesHolder extends RecyclerView.ViewHolder {
private String userLoginId;
private Issues issue;
private final TextView issueNumber;
private final ImageView issueAssigneeAvatar;
private final TextView issueTitle;
private final TextView issueCreatedTime;
@ -114,7 +113,6 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
super(itemView);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
@ -126,10 +124,10 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
Context context = title.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
intent.putExtra("issueNumber", issue.getNumber());
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueNumber", String.valueOf(issue.getNumber()));
tinyDb.putString("issueType", "Issue");
context.startActivity(intent);
@ -140,18 +138,18 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
Context context = commentsCount.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
intent.putExtra("issueNumber", issue.getNumber());
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueNumber", String.valueOf(issue.getNumber()));
tinyDb.putString("issueType", "Issue");
context.startActivity(intent);
});
issueAssigneeAvatar.setOnClickListener(loginId -> {
Context context = loginId.getContext();
issueAssigneeAvatar.setOnClickListener(v -> {
Context context = v.getContext();
String userLoginId = issue.getUser().getLogin();
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
});
@ -159,40 +157,44 @@ public class IssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
}
@SuppressLint("SetTextI18n")
void bindData(Issues issuesModel) {
void bindData(Issues issue) {
final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
TinyDB tinyDb = TinyDB.getInstance(context);
String locale = tinyDb.getString("locale");
String timeFormat = tinyDb.getString("dateFormat");
userLoginId = issuesModel.getUser().getLogin();
PicassoService.getInstance(context).get()
.load(issue.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0))
.resize(120, 120)
.centerCrop()
.into(issueAssigneeAvatar);
PicassoService.getInstance(context).get().load(issuesModel.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(issueAssigneeAvatar);
String issueNumber_ = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + issue.getNumber() + "</font>";
issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + EmojiParser.parseToUnicode(issue.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
String issueNumber_ = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + issuesModel.getNumber() + "</font>";
issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + EmojiParser.parseToUnicode(issuesModel.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
issueNumber.setText(String.valueOf(issuesModel.getNumber()));
issueCommentsCount.setText(String.valueOf(issuesModel.getComments()));
this.issue = issue;
this.issueCommentsCount.setText(String.valueOf(issue.getComments()));
switch(timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issuesModel.getCreated_at()), context));
String createdTime = prettyTime.format(issue.getCreated_at());
this.issueCreatedTime.setText(createdTime);
this.issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(issue.getCreated_at()), context));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
String createdTime = formatter.format(issue.getCreated_at());
this.issueCreatedTime.setText(createdTime);
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + context.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(issuesModel.getCreated_at());
issueCreatedTime.setText(createdTime);
String createdTime = formatter.format(issue.getCreated_at());
this.issueCreatedTime.setText(createdTime);
break;
}
}

View File

@ -18,8 +18,8 @@ import org.gitnex.tea4j.models.Milestones;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.MilestoneActions;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import java.text.DateFormat;
@ -41,7 +41,7 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false;
private boolean isMoreDataAvailable = true;
private String TAG = StaticGlobalVariables.tagMilestonesAdapter;
private String TAG = Constants.tagMilestonesAdapter;
public MilestonesAdapter(Context context, List<Milestones> dataListMain) {

View File

@ -67,15 +67,11 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position) == TYPE_LOAD) {
((PullRequestsAdapter.PullRequestsHolder) holder).bindData(prList.get(position));
}
}
@Override
@ -87,7 +83,6 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
else {
return 1;
}
}
@Override
@ -99,13 +94,8 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
class PullRequestsHolder extends RecyclerView.ViewHolder {
private String userLoginId;
private PullRequests pullRequest;
private final TextView prNumber;
private final TextView prMergeable;
private final TextView prHeadBranch;
private final TextView prIsFork;
private final TextView prForkFullName;
private final ImageView assigneeAvatar;
private final TextView prTitle;
private final TextView prCreatedTime;
@ -115,11 +105,6 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
super(itemView);
prNumber = itemView.findViewById(R.id.prNumber);
prMergeable = itemView.findViewById(R.id.prMergeable);
prHeadBranch = itemView.findViewById(R.id.prHeadBranch);
prIsFork = itemView.findViewById(R.id.prIsFork);
prForkFullName = itemView.findViewById(R.id.prForkFullName);
assigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
prTitle = itemView.findViewById(R.id.prTitle);
prCommentsCount = itemView.findViewById(R.id.prCommentsCount);
@ -131,16 +116,25 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", prNumber.getText());
intent.putExtra("prMergeable", prMergeable.getText());
intent.putExtra("prHeadBranch", prHeadBranch.getText());
intent.putExtra("issueNumber", pullRequest.getNumber());
intent.putExtra("prMergeable", pullRequest.isMergeable());
intent.putExtra("prHeadBranch", pullRequest.getHead().getRef());
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", prNumber.getText().toString());
tinyDb.putString("prMergeable", prMergeable.getText().toString());
tinyDb.putString("prHeadBranch", prHeadBranch.getText().toString());
tinyDb.putString("prIsFork", prIsFork.getText().toString());
tinyDb.putString("prForkFullName", prForkFullName.getText().toString());
tinyDb.putString("issueNumber", String.valueOf(pullRequest.getNumber()));
tinyDb.putString("prMergeable", String.valueOf(pullRequest.isMergeable()));
tinyDb.putString("prHeadBranch", pullRequest.getHead().getRef());
if(pullRequest.getHead() != null && pullRequest.getHead().getRepo() != null) {
tinyDb.putString("prIsFork", String.valueOf(pullRequest.getHead().getRepo().isFork()));
tinyDb.putString("prForkFullName", pullRequest.getHead().getRepo().getFull_name());
}
else {
// pull was done from a deleted fork
tinyDb.putString("prIsFork", "true");
tinyDb.putString("prForkFullName", context.getString(R.string.prDeletedFork));
}
tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
@ -151,23 +145,33 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", prNumber.getText());
intent.putExtra("prMergeable", prMergeable.getText());
intent.putExtra("prHeadBranch", prHeadBranch.getText());
intent.putExtra("issueNumber", pullRequest.getNumber());
intent.putExtra("prMergeable", pullRequest.isMergeable());
intent.putExtra("prHeadBranch", pullRequest.getHead().getRef());
TinyDB tinyDb = TinyDB.getInstance(context);
tinyDb.putString("issueNumber", prNumber.getText().toString());
tinyDb.putString("prMergeable", prMergeable.getText().toString());
tinyDb.putString("prHeadBranch", prHeadBranch.getText().toString());
tinyDb.putString("prIsFork", prIsFork.getText().toString());
tinyDb.putString("prForkFullName", prForkFullName.getText().toString());
tinyDb.putString("issueNumber", String.valueOf(pullRequest.getNumber()));
tinyDb.putString("prMergeable", String.valueOf(pullRequest.isMergeable()));
tinyDb.putString("prHeadBranch", pullRequest.getHead().getRef());
if(pullRequest.getHead() != null && pullRequest.getHead().getRepo() != null) {
tinyDb.putString("prIsFork", String.valueOf(pullRequest.getHead().getRepo().isFork()));
tinyDb.putString("prForkFullName", pullRequest.getHead().getRepo().getFull_name());
}
else {
// pull was done from a deleted fork
tinyDb.putString("prIsFork", "true");
tinyDb.putString("prForkFullName", context.getString(R.string.prDeletedFork));
}
tinyDb.putString("issueType", "Pull");
context.startActivity(intent);
});
assigneeAvatar.setOnClickListener(loginId -> {
Context context = loginId.getContext();
assigneeAvatar.setOnClickListener(v -> {
Context context = v.getContext();
String userLoginId = pullRequest.getUser().getLogin();
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
});
@ -175,43 +179,32 @@ public class PullRequestsAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
@SuppressLint("SetTextI18n")
void bindData(PullRequests prModel) {
void bindData(PullRequests pullRequest) {
final TinyDB tinyDb = TinyDB.getInstance(context);
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
TinyDB tinyDb = TinyDB.getInstance(context);
String locale = tinyDb.getString("locale");
String timeFormat = tinyDb.getString("dateFormat");
userLoginId = prModel.getUser().getLogin();
PicassoService.getInstance(context).get()
.load(pullRequest.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0))
.resize(120, 120)
.centerCrop()
.into(this.assigneeAvatar);
PicassoService.getInstance(context).get().load(prModel.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
this.pullRequest = pullRequest;
String prNumber_ = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + prModel.getNumber() + "</font>";
prTitle.setText(HtmlCompat.fromHtml(prNumber_ + " " + EmojiParser.parseToUnicode(prModel.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
String prNumber_ = "<font color='" + ResourcesCompat.getColor(context.getResources(), R.color.lightGray, null) + "'>" + context.getResources().getString(R.string.hash) + pullRequest.getNumber() + "</font>";
prNumber.setText(String.valueOf(prModel.getNumber()));
prMergeable.setText(String.valueOf(prModel.isMergeable()));
if(prModel.getHead() != null) {
prHeadBranch.setText(prModel.getHead().getRef());
if(prModel.getHead().getRepo() != null) {
prIsFork.setText(String.valueOf(prModel.getHead().getRepo().isFork()));
prForkFullName.setText(prModel.getHead().getRepo().getFull_name());
}
else {
// pull was done from a deleted fork
prIsFork.setText("true");
prForkFullName.setText(context.getString(R.string.prDeletedFork));
}
}
prCommentsCount.setText(String.valueOf(prModel.getComments()));
prCreatedTime.setText(TimeHelper.formatTime(prModel.getCreated_at(), new Locale(locale), timeFormat, context));
this.prTitle.setText(HtmlCompat.fromHtml(prNumber_ + " " + EmojiParser.parseToUnicode(pullRequest.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
this.prCommentsCount.setText(String.valueOf(pullRequest.getComments()));
this.prCreatedTime.setText(TimeHelper.formatTime(pullRequest.getCreated_at(), new Locale(locale), timeFormat, context));
if(timeFormat.equals("pretty")) {
prCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(prModel.getCreated_at()), context));
this.prCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(pullRequest.getCreated_at()), context));
}
}
}
static class LoadHolder extends RecyclerView.ViewHolder {

View File

@ -47,39 +47,35 @@ public class SearchIssuesAdapter extends RecyclerView.Adapter<SearchIssuesAdapte
class SearchViewHolder extends RecyclerView.ViewHolder {
private String userLoginId;
private Issues issue;
private final TextView issueNumber;
private final ImageView issueAssigneeAvatar;
private final TextView issueTitle;
private final TextView issueCreatedTime;
private final TextView issueCommentsCount;
private final TextView repoFullName;
private SearchViewHolder(View itemView) {
super(itemView);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
repoFullName = itemView.findViewById(R.id.repoFullName);
issueTitle.setOnClickListener(v -> {
Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class);
intent.putExtra("issueNumber", issueNumber.getText());
intent.putExtra("issueNumber", issue.getNumber());
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putString("issueNumber", String.valueOf(issue.getNumber()));
tinyDb.putString("issueType", "Issue");
tinyDb.putString("repoFullName", repoFullName.getText().toString());
tinyDb.putString("repoFullName", issue.getRepository().getFull_name());
String[] parts = repoFullName.getText().toString().split("/");
String[] parts = issue.getRepository().getFull_name().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
@ -104,14 +100,13 @@ public class SearchIssuesAdapter extends RecyclerView.Adapter<SearchIssuesAdapte
context.startActivity(intent);
});
issueAssigneeAvatar.setOnClickListener(loginId -> {
Context context = loginId.getContext();
issueAssigneeAvatar.setOnClickListener(v -> {
Context context = v.getContext();
String userLoginId = issue.getUser().getLogin();
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
});
}
}
@NonNull
@ -130,17 +125,19 @@ public class SearchIssuesAdapter extends RecyclerView.Adapter<SearchIssuesAdapte
String locale = tinyDb.getString("locale");
String timeFormat = tinyDb.getString("dateFormat");
holder.userLoginId = currentItem.getUser().getLogin();
PicassoService
.getInstance(mCtx).get().load(currentItem.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueAssigneeAvatar);
PicassoService.getInstance(mCtx).get()
.load(currentItem.getUser().getAvatar_url())
.placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0))
.resize(120, 120)
.centerCrop()
.into(holder.issueAssigneeAvatar);
String issueNumber_ = "<font color='" + ResourcesCompat.getColor(mCtx.getResources(), R.color.lightGray, null) + "'>" + currentItem.getRepository().getFull_name() + mCtx.getResources().getString(R.string.hash) + currentItem.getNumber() + "</font>";
holder.issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + currentItem.getTitle(), HtmlCompat.FROM_HTML_MODE_LEGACY));
holder.issueNumber.setText(String.valueOf(currentItem.getNumber()));
holder.issue = currentItem;
holder.issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + currentItem.getTitle(), HtmlCompat.FROM_HTML_MODE_LEGACY));
holder.issueCommentsCount.setText(String.valueOf(currentItem.getComments()));
holder.repoFullName.setText(currentItem.getRepository().getFull_name());
switch(timeFormat) {
case "pretty": {

View File

@ -18,7 +18,6 @@ import javax.net.ssl.X509TrustManager;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
@ -32,15 +31,12 @@ public class RetrofitClient {
private static final Map<String, ApiInterface> apiInterfaces = new ConcurrentHashMap<>();
private static final Map<String, WebInterface> webInterfaces = new ConcurrentHashMap<>();
private static Retrofit createRetrofit(Context context, String instanceUrl) {
private static Retrofit createRetrofit(Context context, String instanceUrl, boolean cacheEnabled) {
TinyDB tinyDB = TinyDB.getInstance(context);
int cacheSize = FilesData.returnOnlyNumber(tinyDB.getString("cacheSizeStr")) * 1024 * 1024;
Cache cache = new Cache(new File(context.getCacheDir(), "responses"), cacheSize);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
// HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// logging.setLevel(HttpLoggingInterceptor.Level.BODY);
try {
@ -49,11 +45,17 @@ public class RetrofitClient {
MemorizingTrustManager memorizingTrustManager = new MemorizingTrustManager(context);
sslContext.init(null, new X509TrustManager[]{ memorizingTrustManager }, new SecureRandom());
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder().cache(cache)
//.addInterceptor(logging)
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder()
// .addInterceptor(logging)
.sslSocketFactory(sslContext.getSocketFactory(), memorizingTrustManager)
.hostnameVerifier(memorizingTrustManager.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier()))
.addInterceptor(chain -> {
.hostnameVerifier(memorizingTrustManager.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier()));
if(cacheEnabled) {
int cacheSize = FilesData.returnOnlyNumber(tinyDB.getString("cacheSizeStr")) * 1024 * 1024;
Cache cache = new Cache(new File(context.getCacheDir(), "responses"), cacheSize);
okHttpClient.cache(cache).addInterceptor(chain -> {
Request request = chain.request();
@ -64,6 +66,7 @@ public class RetrofitClient {
return chain.proceed(request);
});
}
return new Retrofit.Builder()
.baseUrl(instanceUrl)
@ -101,7 +104,7 @@ public class RetrofitClient {
synchronized(RetrofitClient.class) {
if(!apiInterfaces.containsKey(url)) {
ApiInterface apiInterface = createRetrofit(context, url).create(ApiInterface.class);
ApiInterface apiInterface = createRetrofit(context, url, true).create(ApiInterface.class);
apiInterfaces.put(url, apiInterface);
return apiInterface;
@ -119,7 +122,7 @@ public class RetrofitClient {
synchronized(RetrofitClient.class) {
if(!webInterfaces.containsKey(url)) {
WebInterface webInterface = createRetrofit(context, url).create(WebInterface.class);
WebInterface webInterface = createRetrofit(context, url, false).create(WebInterface.class);
webInterfaces.put(url, webInterface);
return webInterface;

View File

@ -14,8 +14,8 @@ import org.acra.config.MailSenderConfigurationBuilder;
import org.acra.data.StringFormat;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.notifications.Notifications;
@ -28,7 +28,9 @@ import org.mian.gitnex.notifications.Notifications;
resTitle = R.string.crashTitle,
resChannelName = R.string.setCrashReports,
resText = R.string.crashMessage)
@AcraCore(reportContent = { ReportField.ANDROID_VERSION, ReportField.PHONE_MODEL, ReportField.STACK_TRACE })
@AcraCore(reportContent = {
ReportField.ANDROID_VERSION, ReportField.PHONE_MODEL,
ReportField.STACK_TRACE, ReportField.AVAILABLE_MEM_SIZE, ReportField.BRAND })
public class MainApplication extends Application {
@ -81,6 +83,7 @@ public class MainApplication extends Application {
}
Notifications.createChannels(appCtx);
Notifications.startWorker(appCtx);
}
@ -121,7 +124,7 @@ public class MainApplication extends Application {
// setting default polling delay
if(tinyDB.getInt("pollingDelayMinutes", 0) <= 0) {
tinyDB.putInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay);
tinyDB.putInt("pollingDelayMinutes", Constants.defaultPollingDelay);
}
// disable biometric by default

View File

@ -7,7 +7,7 @@ import org.mian.gitnex.database.dao.DraftsDao;
import org.mian.gitnex.database.db.GitnexDatabase;
import org.mian.gitnex.database.models.Draft;
import org.mian.gitnex.database.models.DraftWithRepository;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import java.util.List;
/**
@ -51,7 +51,7 @@ public class DraftsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsApi, e.toString());
Log.e(Constants.draftsApi, e.toString());
}
return draftId;
@ -67,7 +67,7 @@ public class DraftsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsApi, e.toString());
Log.e(Constants.draftsApi, e.toString());
}
return draftId;
@ -83,7 +83,7 @@ public class DraftsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsApi, e.toString());
Log.e(Constants.draftsApi, e.toString());
}
return checkDraftFlag;

View File

@ -6,7 +6,7 @@ import androidx.lifecycle.LiveData;
import org.mian.gitnex.database.dao.RepositoriesDao;
import org.mian.gitnex.database.db.GitnexDatabase;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import java.util.List;
/**
@ -47,7 +47,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
Log.e(Constants.repositoriesApi, e.toString());
}
return repositoryId;
@ -63,7 +63,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
Log.e(Constants.repositoriesApi, e.toString());
}
return repository;
@ -89,7 +89,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
Log.e(Constants.repositoriesApi, e.toString());
}
return checkRepository;
@ -105,7 +105,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
Log.e(Constants.repositoriesApi, e.toString());
}
return repository;
@ -121,7 +121,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
Log.e(Constants.repositoriesApi, e.toString());
}
return repository;

View File

@ -6,7 +6,7 @@ import androidx.lifecycle.LiveData;
import org.mian.gitnex.database.dao.UserAccountsDao;
import org.mian.gitnex.database.db.GitnexDatabase;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import java.util.List;
/**
@ -50,7 +50,7 @@ public class UserAccountsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.userAccountsApi, e.toString());
Log.e(Constants.userAccountsApi, e.toString());
}
return accountId;
@ -81,7 +81,7 @@ public class UserAccountsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.userAccountsApi, e.toString());
Log.e(Constants.userAccountsApi, e.toString());
}
return userAccount;
@ -97,7 +97,7 @@ public class UserAccountsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.userAccountsApi, e.toString());
Log.e(Constants.userAccountsApi, e.toString());
}
return checkAccount;
@ -118,7 +118,7 @@ public class UserAccountsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.userAccountsApi, e.toString());
Log.e(Constants.userAccountsApi, e.toString());
}
return userAccounts;

View File

@ -10,7 +10,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.databinding.BottomSheetDraftsBinding;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
/**
* Author M M Arif
@ -18,7 +18,7 @@ import org.mian.gitnex.helpers.StaticGlobalVariables;
public class BottomSheetDraftsFragment extends BottomSheetDialogFragment {
private String TAG = StaticGlobalVariables.tagDraftsBottomSheet;
private String TAG = Constants.tagDraftsBottomSheet;
private BottomSheetDraftsFragment.BottomSheetListener bmListener;
@Nullable

View File

@ -25,7 +25,7 @@ import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.databinding.BottomSheetReplyLayoutBinding;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.Objects;
@ -266,11 +266,11 @@ public class BottomSheetReplyFragment extends BottomSheetDialogFragment {
String draftType;
if(tinyDB.getString("issueType").equalsIgnoreCase("Issue")) {
draftType = StaticGlobalVariables.draftTypeIssue;
draftType = Constants.draftTypeIssue;
}
else if(tinyDB.getString("issueType").equalsIgnoreCase("Pull")) {
draftType = StaticGlobalVariables.draftTypePull;
draftType = Constants.draftTypePull;
}
else {

View File

@ -28,8 +28,8 @@ import org.mian.gitnex.databinding.CustomExploreRepositoriesDialogBinding;
import org.mian.gitnex.databinding.FragmentExploreRepoBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.InfiniteScrollListener;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
@ -80,7 +80,7 @@ public class ExploreRepositoriesFragment extends Fragment {
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
limit = StaticGlobalVariables.resultLimitNewGiteaInstances;
limit = Constants.resultLimitNewGiteaInstances;
}
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ctx);
@ -104,7 +104,7 @@ public class ExploreRepositoriesFragment extends Fragment {
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
limit = StaticGlobalVariables.resultLimitNewGiteaInstances;
limit = Constants.resultLimitNewGiteaInstances;
}
else {
limit = 10;
@ -134,7 +134,7 @@ public class ExploreRepositoriesFragment extends Fragment {
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
limit = StaticGlobalVariables.resultLimitNewGiteaInstances;
limit = Constants.resultLimitNewGiteaInstances;
}
else {
limit = 10;
@ -156,7 +156,7 @@ public class ExploreRepositoriesFragment extends Fragment {
int apiCallDefaultLimit = 10;
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
apiCallDefaultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
apiCallDefaultLimit = Constants.resultLimitNewGiteaInstances;
}
if(apiCallDefaultLimit > limit) {

View File

@ -11,15 +11,12 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.gitnex.tea4j.models.Files;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.FileViewActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
@ -31,7 +28,6 @@ import org.mian.gitnex.helpers.Path;
import org.mian.gitnex.viewmodels.FilesViewModel;
import java.util.ArrayList;
import java.util.Collections;
import moe.feng.common.view.breadcrumbs.BreadcrumbsView;
import moe.feng.common.view.breadcrumbs.DefaultBreadcrumbsCallback;
import moe.feng.common.view.breadcrumbs.model.BreadcrumbItem;
@ -41,15 +37,11 @@ import moe.feng.common.view.breadcrumbs.model.BreadcrumbItem;
public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapterListener {
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
private TextView noDataFiles;
private LinearLayout filesFrame;
private FragmentFilesBinding binding;
private static final String repoNameF = "param2";
private static final String repoOwnerF = "param1";
private static final String repoRefF = "param3";
private BreadcrumbsView mBreadcrumbsView;
private String repoName;
private String repoOwner;
@ -92,28 +84,21 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
FragmentFilesBinding fragmentFilesBinding = FragmentFilesBinding.inflate(inflater, container, false);
binding = FragmentFilesBinding.inflate(inflater, container, false);
setHasOptionsMenu(true);
noDataFiles = fragmentFilesBinding.noDataFiles;
filesFrame = fragmentFilesBinding.filesFrame;
filesAdapter = new FilesAdapter(getContext(), this);
mRecyclerView = fragmentFilesBinding.recyclerView;
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.setAdapter(filesAdapter);
binding.recyclerView.setHasFixedSize(true);
binding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
binding.recyclerView.setAdapter(filesAdapter);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(binding.recyclerView.getContext(), DividerItemDecoration.VERTICAL);
binding.recyclerView.addItemDecoration(dividerItemDecoration);
mProgressBar = fragmentFilesBinding.progressBar;
mBreadcrumbsView = fragmentFilesBinding.breadcrumbsView;
mBreadcrumbsView.setItems(new ArrayList<>(Collections.singletonList(BreadcrumbItem.createSimpleItem(getResources().getString(R.string.filesBreadcrumbRoot) + getResources().getString(R.string.colonDivider) + ref))));
binding.breadcrumbsView.setItems(new ArrayList<>(Collections.singletonList(BreadcrumbItem.createSimpleItem(getResources().getString(R.string.filesBreadcrumbRoot) + getResources().getString(R.string.colonDivider) + ref))));
// noinspection unchecked
mBreadcrumbsView.setCallback(new DefaultBreadcrumbsCallback<BreadcrumbItem>() {
binding.breadcrumbsView.setCallback(new DefaultBreadcrumbsCallback<BreadcrumbItem>() {
@SuppressLint("SetTextI18n")
@Override
@ -140,14 +125,14 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
path.clear();
ref = repoBranch;
mBreadcrumbsView.setItems(new ArrayList<>(Collections.singletonList(BreadcrumbItem.createSimpleItem(getResources().getString(R.string.filesBreadcrumbRoot) + getResources().getString(R.string.colonDivider) + ref))));
binding.breadcrumbsView.setItems(new ArrayList<>(Collections.singletonList(BreadcrumbItem.createSimpleItem(getResources().getString(R.string.filesBreadcrumbRoot) + getResources().getString(R.string.colonDivider) + ref))));
fetchDataAsync(Authorization.get(getContext()), repoOwner, repoName, repoBranch);
});
fetchDataAsync(Authorization.get(getContext()), repoOwner, repoName, ref);
return fragmentFilesBinding.getRoot();
return binding.getRoot();
}
@Override
@ -157,40 +142,35 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
}
@Override
public void onClickDir(String dirName) {
public void onClickFile(Files file) {
path.add(dirName);
mBreadcrumbsView.addItem(new BreadcrumbItem(Collections.singletonList(dirName)));
switch(file.getType()) {
fetchDataAsyncSub(Authorization.get(getContext()), repoOwner, repoName, path.toString(), ref);
case "dir":
path.add(file.getName());
binding.breadcrumbsView.addItem(new BreadcrumbItem(Collections.singletonList(file.getName())));
}
fetchDataAsyncSub(Authorization.get(getContext()), repoOwner, repoName, path.toString(), ref);
break;
@Override
public void onClickFile(String fileName) {
case "file":
Intent intent = new Intent(getContext(), FileViewActivity.class);
intent.putExtra("file", file);
Intent intent = new Intent(getContext(), FileViewActivity.class);
requireContext().startActivity(intent);
break;
if(path.size() != 0) {
intent.putExtra("singleFileName", path.toString() + "/" + fileName);
}
else {
intent.putExtra("singleFileName", fileName);
}
requireContext().startActivity(intent);
}
private void fetchDataAsync(String instanceToken, String owner, String repo, String ref) {
mRecyclerView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
binding.recyclerView.setVisibility(View.GONE);
binding.progressBar.setVisibility(View.VISIBLE);
FilesViewModel filesModel = new ViewModelProvider(this).get(FilesViewModel.class);
filesModel.getFilesList(instanceToken, owner, repo, ref, getContext(), mProgressBar, noDataFiles).observe(getViewLifecycleOwner(), filesListMain -> {
filesModel.getFilesList(instanceToken, owner, repo, ref, getContext(), binding.progressBar, binding.noDataFiles).observe(getViewLifecycleOwner(), filesListMain -> {
filesAdapter.getOriginalFiles().clear();
filesAdapter.getOriginalFiles().addAll(filesListMain);
@ -198,16 +178,16 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
if(filesListMain.size() > 0) {
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame);
noDataFiles.setVisibility(View.GONE);
AppUtil.setMultiVisibility(View.VISIBLE, binding.recyclerView, binding.filesFrame);
binding.noDataFiles.setVisibility(View.GONE);
}
else {
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame, noDataFiles);
AppUtil.setMultiVisibility(View.VISIBLE, binding.recyclerView, binding.filesFrame, binding.noDataFiles);
}
filesFrame.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
binding.filesFrame.setVisibility(View.VISIBLE);
binding.progressBar.setVisibility(View.GONE);
});
@ -215,12 +195,12 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
private void fetchDataAsyncSub(String instanceToken, String owner, String repo, String filesDir, String ref) {
mRecyclerView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
binding.recyclerView.setVisibility(View.GONE);
binding.progressBar.setVisibility(View.VISIBLE);
FilesViewModel filesModel2 = new ViewModelProvider(this).get(FilesViewModel.class);
FilesViewModel filesModel = new ViewModelProvider(this).get(FilesViewModel.class);
filesModel2.getFilesList2(instanceToken, owner, repo, filesDir, ref, getContext(), mProgressBar, noDataFiles).observe(this, filesListMain2 -> {
filesModel.getFilesList2(instanceToken, owner, repo, filesDir, ref, getContext(), binding.progressBar, binding.noDataFiles).observe(this, filesListMain2 -> {
filesAdapter.getOriginalFiles().clear();
filesAdapter.getOriginalFiles().addAll(filesListMain2);
@ -228,15 +208,15 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
if(filesListMain2.size() > 0) {
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame);
noDataFiles.setVisibility(View.GONE);
AppUtil.setMultiVisibility(View.VISIBLE, binding.recyclerView, binding.filesFrame);
binding.noDataFiles.setVisibility(View.GONE);
}
else {
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame, noDataFiles);
AppUtil.setMultiVisibility(View.VISIBLE, binding.recyclerView, binding.filesFrame, binding.noDataFiles);
}
filesFrame.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
binding.filesFrame.setVisibility(View.VISIBLE);
binding.progressBar.setVisibility(View.GONE);
});
@ -259,7 +239,7 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
@Override
public boolean onQueryTextChange(String newText) {
if(mRecyclerView.getAdapter() != null) {
if(binding.recyclerView.getAdapter() != null) {
filesAdapter.getFilter().filter(newText);
}

View File

@ -28,7 +28,7 @@ import org.mian.gitnex.adapters.IssuesAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentIssuesBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
@ -49,12 +49,12 @@ public class IssuesFragment extends Fragment {
private List<Issues> issuesList;
private IssuesAdapter adapter;
private Context context;
private int pageSize = StaticGlobalVariables.issuesPageInit;
private int pageSize = Constants.issuesPageInit;
private ProgressBar mProgressBar;
private String TAG = StaticGlobalVariables.tagIssuesList;
private String TAG = Constants.tagIssuesList;
private TextView noDataIssues;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private String requestType = StaticGlobalVariables.issuesRequestType;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private String requestType = Constants.issuesRequestType;
private ProgressBar progressLoadMore;
@Nullable
@ -78,7 +78,7 @@ public class IssuesFragment extends Fragment {
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
recyclerView = fragmentIssuesBinding.recyclerView;

View File

@ -23,7 +23,7 @@ import org.mian.gitnex.adapters.MilestonesAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentMilestonesBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Version;
import java.util.ArrayList;
@ -44,9 +44,9 @@ public class MilestonesFragment extends Fragment {
private List<Milestones> dataList;
private MilestonesAdapter adapter;
private Context ctx;
private int pageSize = StaticGlobalVariables.milestonesPageInit;
private String TAG = StaticGlobalVariables.tagMilestonesFragment;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int pageSize = Constants.milestonesPageInit;
private String TAG = Constants.tagMilestonesFragment;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -68,7 +68,7 @@ public class MilestonesFragment extends Fragment {
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
dataList = new ArrayList<>();

View File

@ -29,8 +29,8 @@ import org.mian.gitnex.adapters.NotificationsAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentNotificationsBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.InfiniteScrollListener;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.io.IOException;
@ -83,7 +83,7 @@ public class NotificationsFragment extends Fragment implements NotificationsAdap
context = getContext();
tinyDB = TinyDB.getInstance(context);
pageResultLimit = StaticGlobalVariables.getCurrentResultLimit(context);
pageResultLimit = Constants.getCurrentResultLimit(context);
tinyDB.putString("notificationsFilterState", currentFilterMode);
markAllAsRead = fragmentNotificationsBinding.markAllAsRead;
@ -204,7 +204,7 @@ public class NotificationsFragment extends Fragment implements NotificationsAdap
Call<List<NotificationThread>> call = RetrofitClient
.getApiInterface(context)
.getNotificationThreads(instanceToken, false, filter,
StaticGlobalVariables.defaultOldestTimestamp, "",
Constants.defaultOldestTimestamp, "",
pageCurrentIndex, pageResultLimit);
call.enqueue(new Callback<List<NotificationThread>>() {

View File

@ -30,8 +30,7 @@ import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import java.util.Locale;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
import jp.wasabeef.picasso.transformations.BlurTransformation;
/**
* Author M M Arif
@ -54,7 +53,6 @@ public class ProfileFragment extends Fragment {
TinyDB tinyDb = TinyDB.getInstance(getContext());
BlurView blurView = v.findViewById(R.id.blurView);
TextView userFullName = v.findViewById(R.id.userFullName);
ImageView userAvatarBackground = v.findViewById(R.id.userAvatarBackground);
ImageView userAvatar = v.findViewById(R.id.userAvatar);
@ -77,10 +75,10 @@ public class ProfileFragment extends Fragment {
userLanguage.setText(R.string.notSupported);
}
userAvatar.setOnClickListener(loginId -> {
AppUtil.copyToClipboard(ctx, tinyDb.getString("userLogin"), ctx.getString(R.string.copyLoginIdToClipBoard, tinyDb.getString("userLogin")));
});
userAvatar.setOnClickListener(loginId ->
AppUtil.copyToClipboard(ctx,
tinyDb.getString("userLogin"),
ctx.getString(R.string.copyLoginIdToClipBoard, tinyDb.getString("userLogin"))));
userFullName.setText(Html.fromHtml(tinyDb.getString("userFullname")));
userLogin.setText(getString(R.string.usernameWithAt, tinyDb.getString("userLogin")));
@ -94,12 +92,12 @@ public class ProfileFragment extends Fragment {
PicassoService.getInstance(ctx).get()
.load(tinyDb.getString("userAvatar"))
.transform(new BlurTransformation(ctx))
.into(userAvatarBackground, new Callback() {
@Override
public void onSuccess() {
int invertedColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground);
int invertedColor = new ColorInverter().getImageViewContrastColor(userAvatar);
userFullName.setTextColor(invertedColor);
divider.setBackgroundColor(invertedColor);
@ -107,20 +105,11 @@ public class ProfileFragment extends Fragment {
userLanguage.setTextColor(invertedColor);
ImageViewCompat.setImageTintList(userLanguageIcon, ColorStateList.valueOf(invertedColor));
blurView.setupWith(aboutFrame)
.setBlurAlgorithm(new RenderScriptBlur(ctx))
.setBlurRadius(3)
.setHasFixedTransformationMatrix(true);
}
@Override
public void onError(Exception e) {}
@Override public void onError(Exception e) {}
});
ProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
ViewPager mViewPager = v.findViewById(R.id.container);
@ -181,8 +170,6 @@ public class ProfileFragment extends Fragment {
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0: // followers
@ -196,7 +183,7 @@ public class ProfileFragment extends Fragment {
}
return fragment;
return null;
}

View File

@ -28,7 +28,7 @@ import org.mian.gitnex.adapters.PullRequestsAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentPullRequestsBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
@ -49,11 +49,11 @@ public class PullRequestsFragment extends Fragment {
private RecyclerView recyclerView;
private List<PullRequests> prList;
private PullRequestsAdapter adapter;
private String TAG = StaticGlobalVariables.tagPullRequestsList;
private String TAG = Constants.tagPullRequestsList;
private Context context;
private int pageSize = StaticGlobalVariables.prPageInit;
private int pageSize = Constants.prPageInit;
private TextView noData;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private int resultLimit = Constants.resultLimitOldGiteaInstances;
private ProgressBar progressLoadMore;
@Nullable
@ -77,7 +77,7 @@ public class PullRequestsFragment extends Fragment {
// if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
resultLimit = Constants.resultLimitNewGiteaInstances;
}
recyclerView = fragmentPullRequestsBinding.recyclerView;

View File

@ -8,10 +8,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
@ -42,36 +39,18 @@ import retrofit2.Callback;
public class RepoInfoFragment extends Fragment {
private Context ctx;
private ProgressBar mProgressBar;
private LinearLayout pageContent;
private static String repoNameF = "param2";
private static String repoOwnerF = "param1";
private FragmentRepoInfoBinding binding;
private String repoName;
private String repoOwner;
private TextView repoMetaName;
private TextView repoMetaDescription;
private TextView repoMetaStars;
private TextView repoMetaPullRequests;
private LinearLayout repoMetaPullRequestsFrame;
private TextView repoMetaForks;
private TextView repoMetaSize;
private TextView repoMetaWatchers;
private TextView repoMetaCreatedAt;
private TextView repoMetaWebsite;
private Button repoAdditionalButton;
private TextView repoFileContents;
private LinearLayout repoMetaFrame;
private ImageView repoMetaDataExpandCollapse;
private ImageView repoFilenameExpandCollapse;
private LinearLayout fileContentsFrameHeader;
private LinearLayout fileContentsFrame;
private OnFragmentInteractionListener mListener;
public RepoInfoFragment() {
}
public RepoInfoFragment() {}
public static RepoInfoFragment newInstance(String param1, String param2) {
RepoInfoFragment fragment = new RepoInfoFragment();
@ -94,44 +73,18 @@ public class RepoInfoFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
FragmentRepoInfoBinding fragmentRepoInfoBinding = FragmentRepoInfoBinding.inflate(inflater, container, false);
binding = FragmentRepoInfoBinding.inflate(inflater, container, false);
TinyDB tinyDb = TinyDB.getInstance(getContext());
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
ctx = getContext();
ctx = getActivity();
pageContent = fragmentRepoInfoBinding.repoInfoLayout;
pageContent = binding.repoInfoLayout;
pageContent.setVisibility(View.GONE);
mProgressBar = fragmentRepoInfoBinding.progressBar;
repoMetaName = fragmentRepoInfoBinding.repoMetaName;
repoMetaDescription = fragmentRepoInfoBinding.repoMetaDescription;
repoMetaStars = fragmentRepoInfoBinding.repoMetaStars;
repoMetaPullRequests = fragmentRepoInfoBinding.repoMetaPullRequests;
repoMetaPullRequestsFrame = fragmentRepoInfoBinding.repoMetaPullRequestsFrame;
repoMetaForks = fragmentRepoInfoBinding.repoMetaForks;
repoMetaSize = fragmentRepoInfoBinding.repoMetaSize;
repoMetaWatchers = fragmentRepoInfoBinding.repoMetaWatchers;
repoMetaCreatedAt = fragmentRepoInfoBinding.repoMetaCreatedAt;
repoMetaWebsite = fragmentRepoInfoBinding.repoMetaWebsite;
repoAdditionalButton = fragmentRepoInfoBinding.repoAdditionalButton;
repoFileContents = fragmentRepoInfoBinding.repoFileContents;
repoMetaFrame = fragmentRepoInfoBinding.repoMetaFrame;
LinearLayout repoMetaFrameHeader = fragmentRepoInfoBinding.repoMetaFrameHeader;
repoMetaDataExpandCollapse = fragmentRepoInfoBinding.repoMetaDataExpandCollapse;
repoFilenameExpandCollapse = fragmentRepoInfoBinding.repoFilenameExpandCollapse;
fileContentsFrameHeader = fragmentRepoInfoBinding.fileContentsFrameHeader;
fileContentsFrame = fragmentRepoInfoBinding.fileContentsFrame;
LinearLayout repoMetaStarsFrame = fragmentRepoInfoBinding.repoMetaStarsFrame;
LinearLayout repoMetaForksFrame = fragmentRepoInfoBinding.repoMetaForksFrame;
LinearLayout repoMetaWatchersFrame = fragmentRepoInfoBinding.repoMetaWatchersFrame;
binding.repoMetaFrame.setVisibility(View.GONE);
repoMetaFrame.setVisibility(View.GONE);
getRepoInfo(Authorization.get(getContext()), repoOwner, repoName, locale, timeFormat);
getRepoInfo(Authorization.get(getContext()), repoOwner, repoName, tinyDb.getString("locale"), tinyDb.getString("dateFormat"));
getFileContents(Authorization.get(getContext()), repoOwner, repoName, getResources().getString(R.string.defaultFilename));
if(isExpandViewVisible()) {
@ -142,27 +95,26 @@ public class RepoInfoFragment extends Fragment {
toggleExpandViewMeta();
}
fileContentsFrameHeader.setOnClickListener(v1 -> toggleExpandView());
binding.fileContentsFrameHeader.setOnClickListener(v1 -> toggleExpandView());
binding.repoMetaFrameHeader.setOnClickListener(v12 -> toggleExpandViewMeta());
repoMetaFrameHeader.setOnClickListener(v12 -> toggleExpandViewMeta());
repoMetaStarsFrame.setOnClickListener(metaStars -> {
binding.repoMetaStarsFrame.setOnClickListener(metaStars -> {
Intent intent = new Intent(ctx, RepoStargazersActivity.class);
intent.putExtra("repoFullNameForStars", repoOwner + "/" + repoName);
ctx.startActivity(intent);
});
repoMetaWatchersFrame.setOnClickListener(metaWatchers -> {
binding.repoMetaWatchersFrame.setOnClickListener(metaWatchers -> {
Intent intent = new Intent(ctx, RepoWatchersActivity.class);
intent.putExtra("repoFullNameForWatchers", repoOwner + "/" + repoName);
ctx.startActivity(intent);
});
repoMetaPullRequestsFrame.setOnClickListener(metaPR -> RepoDetailActivity.mViewPager.setCurrentItem(3));
binding.repoMetaPullRequestsFrame.setOnClickListener(metaPR -> RepoDetailActivity.mViewPager.setCurrentItem(3));
return fragmentRepoInfoBinding.getRoot();
return binding.getRoot();
}
public void onButtonPressed(Uri uri) {
@ -183,42 +135,42 @@ public class RepoInfoFragment extends Fragment {
private void toggleExpandView() {
if (repoFileContents.getVisibility() == View.GONE) {
repoFilenameExpandCollapse.setImageResource(R.drawable.ic_chevron_up);
repoFileContents.setVisibility(View.VISIBLE);
if (binding.repoFileContents.getVisibility() == View.GONE) {
binding.repoFilenameExpandCollapse.setImageResource(R.drawable.ic_chevron_up);
binding.repoFileContents.setVisibility(View.VISIBLE);
//Animation slide_down = AnimationUtils.loadAnimation(getContext(), R.anim.slide_down);
//fileContentsFrame.startAnimation(slide_down);
//binding.fileContentsFrame.startAnimation(slide_down);
}
else {
repoFilenameExpandCollapse.setImageResource(R.drawable.ic_chevron_down);
repoFileContents.setVisibility(View.GONE);
binding.repoFilenameExpandCollapse.setImageResource(R.drawable.ic_chevron_down);
binding.repoFileContents.setVisibility(View.GONE);
//Animation slide_up = AnimationUtils.loadAnimation(getContext(), R.anim.slide_up);
//fileContentsFrame.startAnimation(slide_up);
//binding.fileContentsFrame.startAnimation(slide_up);
}
}
private boolean isExpandViewVisible() {
return repoFileContents.getVisibility() == View.VISIBLE;
return binding.repoFileContents.getVisibility() == View.VISIBLE;
}
private void toggleExpandViewMeta() {
if (repoMetaFrame.getVisibility() == View.GONE) {
repoMetaDataExpandCollapse.setImageResource(R.drawable.ic_chevron_up);
repoMetaFrame.setVisibility(View.VISIBLE);
if (binding.repoMetaFrame.getVisibility() == View.GONE) {
binding.repoMetaDataExpandCollapse.setImageResource(R.drawable.ic_chevron_up);
binding.repoMetaFrame.setVisibility(View.VISIBLE);
//Animation slide_down = AnimationUtils.loadAnimation(getContext(), R.anim.slide_down);
//repoMetaFrame.startAnimation(slide_down);
//binding.repoMetaFrame.startAnimation(slide_down);
}
else {
repoMetaDataExpandCollapse.setImageResource(R.drawable.ic_chevron_down);
repoMetaFrame.setVisibility(View.GONE);
binding.repoMetaDataExpandCollapse.setImageResource(R.drawable.ic_chevron_down);
binding.repoMetaFrame.setVisibility(View.GONE);
//Animation slide_up = AnimationUtils.loadAnimation(getContext(), R.anim.slide_up);
//repoMetaFrame.startAnimation(slide_up);
//binding.repoMetaFrame.startAnimation(slide_up);
}
}
private boolean isExpandViewMetaVisible() {
return repoMetaFrame.getVisibility() == View.VISIBLE;
return binding.repoMetaFrame.getVisibility() == View.VISIBLE;
}
private void getRepoInfo(String token, final String owner, String repo, final String locale, final String timeFormat) {
@ -243,39 +195,39 @@ public class RepoInfoFragment extends Fragment {
if (response.code() == 200) {
assert repoInfo != null;
repoMetaName.setText(repoInfo.getName());
binding.repoMetaName.setText(repoInfo.getName());
if(!repoInfo.getDescription().isEmpty()) {
repoMetaDescription.setText(repoInfo.getDescription());
binding.repoMetaDescription.setText(repoInfo.getDescription());
}
else {
repoMetaDescription.setText(getString(R.string.noDataDescription));
binding.repoMetaDescription.setText(getString(R.string.noDataDescription));
}
repoMetaStars.setText(repoInfo.getStars_count());
binding.repoMetaStars.setText(repoInfo.getStars_count());
if(repoInfo.getOpen_pull_count() != null) {
repoMetaPullRequests.setText(repoInfo.getOpen_pull_count());
binding.repoMetaPullRequests.setText(repoInfo.getOpen_pull_count());
}
else {
repoMetaPullRequestsFrame.setVisibility(View.GONE);
binding.repoMetaPullRequestsFrame.setVisibility(View.GONE);
}
repoMetaForks.setText(repoInfo.getForks_count());
repoMetaWatchers.setText(repoInfo.getWatchers_count());
repoMetaSize.setText(FileUtils.byteCountToDisplaySize((int) (repoInfo.getSize() * 1024)));
binding.repoMetaForks.setText(repoInfo.getForks_count());
binding.repoMetaWatchers.setText(repoInfo.getWatchers_count());
binding.repoMetaSize.setText(FileUtils.byteCountToDisplaySize((int) repoInfo.getSize() * 1024));
repoMetaCreatedAt.setText(TimeHelper.formatTime(repoInfo.getCreated_at(), new Locale(locale), timeFormat, ctx));
binding.repoMetaCreatedAt.setText(TimeHelper.formatTime(repoInfo.getCreated_at(), new Locale(locale), timeFormat, ctx));
if(timeFormat.equals("pretty")) {
repoMetaCreatedAt.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(repoInfo.getCreated_at()), ctx));
binding.repoMetaCreatedAt.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(repoInfo.getCreated_at()), ctx));
}
String repoMetaUpdatedAt = TimeHelper.formatTime(repoInfo.getUpdated_at(), new Locale(locale), timeFormat, ctx);
String website = (repoInfo.getWebsite().isEmpty()) ? getResources().getString(R.string.noDataWebsite) : repoInfo.getWebsite();
repoMetaWebsite.setText(website);
binding.repoMetaWebsite.setText(website);
repoAdditionalButton.setOnClickListener(v -> {
binding.repoAdditionalButton.setOnClickListener(v -> {
View view = LayoutInflater.from(ctx).inflate(R.layout.layout_repo_more_info, null);
@ -334,7 +286,7 @@ public class RepoInfoFragment extends Fragment {
tinyDb.putString("repoHtmlUrl", repoInfo.getHtml_url());
mProgressBar.setVisibility(View.GONE);
binding.progressBar.setVisibility(View.GONE);
pageContent.setVisibility(View.VISIBLE);
}
@ -369,39 +321,41 @@ public class RepoInfoFragment extends Fragment {
if (isAdded()) {
if (response.code() == 200) {
switch(response.code()) {
new Markdown(ctx, response.body(), repoFileContents);
case 200:
new Markdown(ctx, response.body(), binding.repoFileContents);
break;
} else if (response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
break;
} else if (response.code() == 403) {
case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
break;
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
case 404:
binding.fileContentsFrameHeader.setVisibility(View.GONE);
binding.fileContentsFrame.setVisibility(View.GONE);
break;
} else if (response.code() == 404) {
fileContentsFrameHeader.setVisibility(View.GONE);
fileContentsFrame.setVisibility(View.GONE);
} else {
Toasty.error(getContext(), getString(R.string.genericError));
default:
Toasty.error(getContext(), getString(R.string.genericError));
break;
}
}
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}

View File

@ -71,6 +71,7 @@ public class SettingsFragment extends Fragment {
fragmentSettingsBinding.aboutAppFrame.setOnClickListener(aboutApp -> requireActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AboutFragment()).commit());
return fragmentSettingsBinding.getRoot();
}
public void rateThisApp() {

View File

@ -13,15 +13,16 @@ import android.util.TypedValue;
import android.view.View;
import androidx.annotation.ColorInt;
import androidx.core.content.pm.PackageInfoCompat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@ -31,31 +32,38 @@ import java.util.Objects;
public class AppUtil {
public enum FileType { IMAGE, DOCUMENT, TEXT, UNKNOWN }
public enum FileType { IMAGE, AUDIO, VIDEO, DOCUMENT, TEXT, EXECUTABLE, UNKNOWN }
private static final HashMap<List<String>, FileType> extensions = new HashMap<>();
private static final HashMap<String[], FileType> extensions = new HashMap<>();
// AppUtil should not be instantiated.
private AppUtil() {}
static {
extensions.put(Arrays.asList("jpg", "jpeg", "gif", "png", "ico"), FileType.IMAGE);
extensions.put(Arrays.asList("doc", "docx", "ppt", "pptx", "xls", "xlsx", "xlsm", "odt", "ott", "odf", "ods", "ots", "exe", "jar", "odg", "otg", "odp", "otp", "bin", "dmg", "psd", "xcf", "pdf"), FileType.DOCUMENT);
extensions.put(Arrays.asList("txt", "md", "json", "java", "go", "php", "c", "cc", "cpp", "h", "cxx", "cyc", "m", "cs", "bash", "sh", "bsh", "cv", "python", "perl", "pm", "rb", "ruby", "javascript", "coffee", "rc", "rs", "rust", "basic", "clj", "css", "dart", "lisp", "erl", "hs", "lsp", "rkt", "ss", "llvm", "ll", "lua", "matlab", "pascal", "r", "scala", "sql", "latex", "tex", "vb", "vbs", "vhd", "tcl", "wiki.meta", "yaml", "yml", "markdown", "xml", "proto", "regex", "py", "pl", "js", "html", "htm", "volt", "ini", "htaccess", "conf", "gitignore", "gradle", "txt", "properties", "bat", "twig", "cvs", "cmake", "in", "info", "spec", "m4", "am", "dist", "pam", "hx", "ts"), FileType.TEXT);
extensions.put(new String[]{"jpg", "jpeg", "gif", "png", "ico", "tif", "tiff", "bmp"}, FileType.IMAGE);
extensions.put(new String[]{"mp3", "wav", "opus", "flac", "wma", "aac", "m4a", "oga", "mpc", "ogg"}, FileType.AUDIO);
extensions.put(new String[]{"mp4", "mkv", "avi", "mov", "wmv", "qt", "mts", "m2ts", "webm", "flv", "ogv", "amv", "mpg", "mpeg", "mpv", "m4v", "3gp", "wmv"}, FileType.VIDEO);
extensions.put(new String[]{"doc", "docx", "ppt", "pptx", "xls", "xlsx", "xlsm", "odt", "ott", "odf", "ods", "ots", "odg", "otg", "odp", "otp", "bin", "psd", "xcf", "pdf"}, FileType.DOCUMENT);
extensions.put(new String[]{"exe", "msi", "jar", "dmg", "deb", "apk"}, FileType.EXECUTABLE);
extensions.put(new String[]{"txt", "md", "json", "java", "go", "php", "c", "cc", "cpp", "h", "cxx", "cyc", "m", "cs", "bash", "sh", "bsh", "cv", "python", "perl", "pm", "rb", "ruby", "javascript", "coffee", "rc", "rs", "rust", "basic", "clj", "css", "dart", "lisp", "erl", "hs", "lsp", "rkt", "ss", "llvm", "ll", "lua", "matlab", "pascal", "r", "scala", "sql", "latex", "tex", "vb", "vbs", "vhd", "tcl", "wiki.meta", "yaml", "yml", "markdown", "xml", "proto", "regex", "py", "pl", "js", "html", "htm", "volt", "ini", "htaccess", "conf", "gitignore", "gradle", "txt", "properties", "bat", "twig", "cvs", "cmake", "in", "info", "spec", "m4", "am", "dist", "pam", "hx", "ts", "kt", "kts"}, FileType.TEXT);
}
public static FileType getFileType(String extension) {
for(List<String> e : extensions.keySet()) {
if(extension != null && !extension.isEmpty()) {
for(String[] testExtensions : extensions.keySet()) {
for(String testExtension : testExtensions) {
if(e.contains(extension)) {
return extensions.get(e);
if(testExtension.equalsIgnoreCase(extension))
return extensions.get(testExtensions);
}
}
}
return FileType.UNKNOWN;
}
public static boolean hasNetworkConnection(Context context) {
@ -63,6 +71,45 @@ public class AppUtil {
return NetworkStatusObserver.getInstance(context).hasNetworkConnection();
}
public static void copyProgress(InputStream inputStream, OutputStream outputStream, long totalSize, ProgressListener progressListener) throws IOException {
byte[] buffer = new byte[4096];
int read;
long totalSteps = (long) Math.ceil((double) totalSize / buffer.length);
long stepsPerPercent = (long) Math.floor((double) totalSteps / 100);
short percent = 0;
long stepCount = 0;
progressListener.onActionStarted();
while((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
stepCount++;
if(stepCount == stepsPerPercent) {
percent++;
if(percent <= 100) progressListener.onProgressChanged(percent);
stepCount = 0;
}
}
if(percent < 100) {
progressListener.onProgressChanged((short) 100);
}
progressListener.onActionFinished();
}
public interface ProgressListener {
default void onActionStarted() {}
default void onActionFinished() {}
void onProgressChanged(short progress);
}
public static int getAppBuildNo(Context context) {
try {

View File

@ -23,4 +23,12 @@ public class Authorization {
return "token " + tinyDb.getString(loginUid + "-token");
}
public static String getWeb(Context context) {
TinyDB tinyDb = TinyDB.getInstance(context);
return Credentials.basic("", tinyDb.getString(tinyDb.getString("loginUid") + "-token"));
}
}

View File

@ -5,6 +5,7 @@ import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.widget.ImageView;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
/**
* Author M M Arif
@ -17,45 +18,36 @@ public class ColorInverter {
double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
int d;
if (a < 0.5) {
d = 30; // almost black
} else {
d = 255; // white
}
int d = (a < 0.30) ?
30 : // almost black
255; // white
return Color.rgb(d, d, d);
}
@ColorInt
public int getImageViewContrastColor(ImageView imageView) {
public int getBitmapContrastColor(@NonNull Bitmap bitmap) {
if(imageView != null) {
int colorSum = 0;
int divisionValue = 0;
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
for(int height=0; height<bitmap.getHeight(); height += 10) {
for(int width=0; width<bitmap.getWidth(); width += 10) {
int colorSum = 0;
int divisionValue = 0;
for(int height=0; height<bitmap.getHeight(); height += 10) {
for(int width=0; width<bitmap.getWidth(); width += 10) {
colorSum += bitmap.getPixel(width, height);
divisionValue++;
}
colorSum += bitmap.getPixel(width, height);
divisionValue++;
}
// Calculate average color
return getContrastColor(colorSum / divisionValue);
}
else {
return Color.rgb(255, 255, 255);
}
// Calculate average color
return getContrastColor(colorSum / divisionValue);
}
@ColorInt
public int getImageViewContrastColor(@NonNull ImageView imageView) {
return getBitmapContrastColor(((BitmapDrawable) imageView.getDrawable()).getBitmap());
}
}

View File

@ -0,0 +1,61 @@
package org.mian.gitnex.helpers;
import android.content.Context;
/**
* Author M M Arif
*/
public class Constants {
// generic values
public static final int resultLimitNewGiteaInstances = 25; // Gitea 1.12 and above
public static final int resultLimitOldGiteaInstances = 10; // Gitea 1.11 and below
public static final String defaultOldestTimestamp = "1970-01-01T00:00:00+00:00";
public static int getCurrentResultLimit(Context context) {
Version version = new Version(TinyDB.getInstance(context).getString("giteaVersion"));
return version.higherOrEqual("1.12") ? resultLimitNewGiteaInstances : resultLimitOldGiteaInstances;
}
// tags
public static final String tagMilestonesFragment = "MilestonesFragment";
public static final String tagPullRequestsList = "PullRequestsListFragment";
public static final String tagIssuesList = "IssuesListFragment";
public static final String tagMilestonesAdapter = "MilestonesAdapter";
public static final String draftsApi = "DraftsApi";
public static final String repositoriesApi = "RepositoriesApi";
public static final String replyToIssueActivity = "ReplyToIssueActivity";
public static final String tagDraftsBottomSheet = "BottomSheetDraftsFragment";
public static final String userAccountsApi = "UserAccountsApi";
// issues variables
public static final int issuesPageInit = 1;
public static final String issuesRequestType = "issues";
// pull request
public static final int prPageInit = 1;
// milestone
public static final int milestonesPageInit = 1;
// drafts
public static final String draftTypeComment = "comment";
public static final String draftTypeIssue = "Issue";
public static final String draftTypePull = "Pull";
// polling - notifications
public static final int minimumPollingDelay = 1;
public static final int defaultPollingDelay = 15;
public static final int maximumPollingDelay = 720;
public static final int maximumFileViewerSize = 3 * 1024 * 1024;
public static final String mainNotificationChannelId = "main_channel";
public static final String downloadNotificationChannelId = "dl_channel";
public static final String[] fallbackReactions = new String[]{"+1", "-1", "laugh", "hooray", "confused", "heart", "rocket", "eyes"};
}

View File

@ -113,7 +113,7 @@ public class ParseDiff {
// parse "-1,2 +2,3" and "-1 -3" and so on
int oldStart = 0, newStart = 0;
String diffPos[] = statsLine.split(" \\+");
String[] diffPos = statsLine.split(" \\+");
if(diffPos.length == 2) {
oldStart = Integer.parseInt(diffPos[0].split(",")[0]);
newStart = Integer.parseInt(diffPos[1].split(",")[0]);

View File

@ -1,53 +0,0 @@
package org.mian.gitnex.helpers;
import android.content.Context;
/**
* Author M M Arif
*/
public abstract class StaticGlobalVariables {
// generic values
public static int resultLimitNewGiteaInstances = 25; // Gitea 1.12 and above
public static int resultLimitOldGiteaInstances = 10; // Gitea 1.11 and below
public static String defaultOldestTimestamp = "1970-01-01T00:00:00+00:00";
public static int getCurrentResultLimit(Context context) {
Version version = new Version(TinyDB.getInstance(context).getString("giteaVersion"));
return version.higherOrEqual("1.12") ? resultLimitNewGiteaInstances : resultLimitOldGiteaInstances;
}
// tags
public static String tagMilestonesFragment = "MilestonesFragment";
public static String tagPullRequestsList = "PullRequestsListFragment";
public static String tagIssuesList = "IssuesListFragment";
public static String tagMilestonesAdapter = "MilestonesAdapter";
public static String draftsApi = "DraftsApi";
public static String repositoriesApi = "RepositoriesApi";
public static String replyToIssueActivity = "ReplyToIssueActivity";
public static String tagDraftsBottomSheet = "BottomSheetDraftsFragment";
public static String userAccountsApi = "UserAccountsApi";
// issues variables
public static int issuesPageInit = 1;
public static String issuesRequestType = "issues";
// pull request
public static int prPageInit = 1;
// milestone
public static int milestonesPageInit = 1;
// drafts
public static String draftTypeComment = "comment";
public static String draftTypeIssue = "Issue";
public static String draftTypePull = "Pull";
// polling - notifications
public static int minimumPollingDelay = 1;
public static int defaultPollingDelay = 15;
public static int maximumPollingDelay = 720;
}

View File

@ -6,7 +6,6 @@ import android.util.AttributeSet;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import org.mian.gitnex.helpers.highlightjs.models.Language;
import org.mian.gitnex.helpers.highlightjs.models.Theme;
import org.mian.gitnex.helpers.highlightjs.utils.SourceUtils;
@ -25,6 +24,8 @@ public class HighlightJsView extends WebView {
private boolean showLineNumbers = true;
private TextWrap textWrap = TextWrap.NO_WRAP;
private String source = "";
public HighlightJsView(Context context) {
super(context);
@ -63,11 +64,15 @@ public class HighlightJsView extends WebView {
getSettings().setSupportZoom(enable);
}
public void setSource(String source) {
public String getContent() {
return source;
}
source = (source == null) ? " " : source;
public void setContent(String source) {
String html_content = SourceUtils.generateContent(source, theme.getName(), language.getName(), zoomSupport, showLineNumbers, textWrap);
this.source = (source == null) ? "" : source;
String html_content = SourceUtils.generateContent(this.source, theme.getName(), language.getName(), zoomSupport, showLineNumbers, textWrap);
loadDataWithBaseURL("file:///android_asset/", html_content, "text/html", "utf-8", null);
}

View File

@ -1,13 +1,17 @@
package org.mian.gitnex.notifications;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Version;
import java.util.concurrent.TimeUnit;
@ -20,13 +24,52 @@ public class Notifications {
private static int notificationsSupported = -1;
private static void checkVersion(TinyDB tinyDB) {
public static int uniqueNotificationId(Context context) {
String currentVersion = tinyDB.getString("giteaVersion");
TinyDB tinyDB = TinyDB.getInstance(context);
if(tinyDB.getBoolean("loggedInMode") && !currentVersion.isEmpty()) {
int previousNotificationId = tinyDB.getInt("previousNotificationId", 0);
int nextPreviousNotificationId = previousNotificationId == Integer.MAX_VALUE ? 0 : previousNotificationId + 1;
tinyDB.putInt("previousNotificationId", nextPreviousNotificationId);
return previousNotificationId;
}
public static void createChannels(Context context) {
TinyDB tinyDB = TinyDB.getInstance(context);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Delete old notification channels
notificationManager.deleteNotificationChannel(context.getPackageName()); // TODO Can be removed in future versions
// Create new notification channels
NotificationChannel mainChannel = new NotificationChannel(Constants.mainNotificationChannelId, context.getString(R.string.mainNotificationChannelName), NotificationManager.IMPORTANCE_DEFAULT);
mainChannel.setDescription(context.getString(R.string.mainNotificationChannelDescription));
if(tinyDB.getBoolean("notificationsEnableVibration", true)) {
mainChannel.setVibrationPattern(new long[] { 1000, 1000 });
mainChannel.enableVibration(true);
} else {
mainChannel.enableVibration(false);
}
if(tinyDB.getBoolean("notificationsEnableLights", true)) {
mainChannel.setLightColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
mainChannel.enableLights(true);
} else {
mainChannel.enableLights(false);
}
NotificationChannel downloadChannel = new NotificationChannel(Constants.downloadNotificationChannelId, context.getString(R.string.fileViewerNotificationChannelName), NotificationManager.IMPORTANCE_LOW);
downloadChannel.setDescription(context.getString(R.string.fileViewerNotificationChannelDescription));
notificationManager.createNotificationChannel(mainChannel);
notificationManager.createNotificationChannel(downloadChannel);
notificationsSupported = new Version(currentVersion).higherOrEqual("1.12.3") ? 1 : 0;
}
}
@ -56,7 +99,7 @@ public class Notifications {
constraints.setRequiresDeviceIdle(false);
}
int pollingDelayMinutes = Math.max(tinyDB.getInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay), 15);
int pollingDelayMinutes = Math.max(tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay), 15);
PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(NotificationsWorker.class, pollingDelayMinutes, TimeUnit.MINUTES)
.setConstraints(constraints.build())
@ -68,4 +111,15 @@ public class Notifications {
}
}
}
private static void checkVersion(TinyDB tinyDB) {
String currentVersion = tinyDB.getString("giteaVersion");
if(tinyDB.getBoolean("loggedInMode") && !currentVersion.isEmpty()) {
notificationsSupported = new Version(currentVersion).higherOrEqual("1.12.3") ? 1 : 0;
}
}
}

View File

@ -1,15 +1,11 @@
package org.mian.gitnex.notifications;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.media.RingtoneManager;
import android.os.Build;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
@ -20,7 +16,8 @@ import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import java.util.Date;
import java.util.List;
@ -34,7 +31,6 @@ import retrofit2.Response;
public class NotificationsWorker extends Worker {
private static final int MAXIMUM_NOTIFICATIONS = 100;
private static final long[] VIBRATION_PATTERN = new long[]{ 1000, 1000 };
private final Context context;
private final TinyDB tinyDB;
@ -45,17 +41,16 @@ public class NotificationsWorker extends Worker {
this.context = context;
this.tinyDB = TinyDB.getInstance(context);
}
@NonNull
@Override
public Result doWork() {
String token = "token " + tinyDB.getString(tinyDB.getString("loginUid") + "-token");
int notificationLoops = tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay) >= 15 ? 1 : Math.min(15 - tinyDB.getInt("pollingDelayMinutes"), 10);
int notificationLoops = tinyDB.getInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay) >= 15 ? 1 : Math.min(15 - tinyDB.getInt("pollingDelayMinutes"), 10);
for(int i=0; i<notificationLoops; i++) {
for(int i = 0; i < notificationLoops; i++) {
long startPollingTime = System.currentTimeMillis();
@ -65,7 +60,7 @@ public class NotificationsWorker extends Worker {
Call<List<NotificationThread>> call = RetrofitClient
.getApiInterface(context)
.getNotificationThreads(token, false, new String[]{"unread"}, previousRefreshTimestamp,
.getNotificationThreads(Authorization.get(context), false, new String[]{"unread"}, previousRefreshTimestamp,
null, 1, MAXIMUM_NOTIFICATIONS);
Response<List<NotificationThread>> response = call.execute();
@ -76,34 +71,24 @@ public class NotificationsWorker extends Worker {
List<NotificationThread> notificationThreads = response.body();
if(!notificationThreads.isEmpty()) {
if(!notificationThreads.isEmpty())
sendNotification(notificationThreads);
}
tinyDB.putString("previousRefreshTimestamp", AppUtil.getTimestampFromDate(context, new Date()));
}
else {
Log.e("onError", String.valueOf(response.code()));
}
}
catch(Exception e) {
Log.e("onError", e.toString());
}
} catch(Exception ignored) {}
try {
if(notificationLoops > 1 && i < (notificationLoops - 1)) {
Thread.sleep(60000 - (System.currentTimeMillis() - startPollingTime));
}
}
catch (InterruptedException ignored) {}
} catch (InterruptedException ignored) {}
}
return Result.success();
}
private void sendNotification(List<NotificationThread> notificationThreads) {
@ -112,7 +97,6 @@ public class NotificationsWorker extends Worker {
PendingIntent pendingIntent = getPendingIntent();
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
attachNotificationChannel(notificationManagerCompat);
Notification summaryNotification = new NotificationCompat.Builder(context, context.getPackageName())
.setContentTitle(context.getString(R.string.newMessages))
@ -122,15 +106,13 @@ public class NotificationsWorker extends Worker {
.setGroupSummary(true)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setChannelId(Constants.mainNotificationChannelId)
.build();
notificationManagerCompat.notify(summaryId, summaryNotification);
for(NotificationThread notificationThread : notificationThreads) {
NotificationManagerCompat notificationManagerCompat1 = NotificationManagerCompat.from(context);
attachNotificationChannel(notificationManagerCompat1);
String subjectUrl = notificationThread.getSubject().getUrl();
String issueId = context.getResources().getString(R.string.hash) + subjectUrl.substring(subjectUrl.lastIndexOf("/") + 1);
String notificationHeader = issueId + " " + notificationThread.getSubject().getTitle() + " " + String.format(context.getResources().getString(R.string.notificationExtraInfo), notificationThread.getRepository().getFull_name(), notificationThread.getSubject().getType());
@ -140,49 +122,8 @@ public class NotificationsWorker extends Worker {
.setGroup(context.getPackageName())
.setContentIntent(pendingIntent);
pushNotification(notificationManagerCompat1, builder1.build());
}
}
notificationManagerCompat.notify(Notifications.uniqueNotificationId(context), builder1.build());
private void pushNotification(NotificationManagerCompat notificationManagerCompat, Notification notification) {
int previousNotificationId = tinyDB.getInt("previousNotificationId", 0);
int nextPreviousNotificationId = previousNotificationId > 71951418 ? 0 : previousNotificationId + 1;
tinyDB.putInt("previousNotificationId", nextPreviousNotificationId);
notificationManagerCompat.notify(previousNotificationId, notification);
}
private void attachNotificationChannel(NotificationManagerCompat notificationManagerCompat) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(context.getPackageName(), context.getString(R.string.appName),
NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.setDescription(context.getString(R.string.notificationChannelDescription));
if(tinyDB.getBoolean("notificationsEnableVibration", true)) {
notificationChannel.setVibrationPattern(VIBRATION_PATTERN);
notificationChannel.enableVibration(true);
}
else {
notificationChannel.enableVibration(false);
}
if(tinyDB.getBoolean("notificationsEnableLights", true)) {
notificationChannel.setLightColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
notificationChannel.enableLights(true);
}
else {
notificationChannel.enableLights(false);
}
notificationManagerCompat.createNotificationChannel(notificationChannel);
}
}
@ -193,6 +134,7 @@ public class NotificationsWorker extends Worker {
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setChannelId(Constants.mainNotificationChannelId)
.setAutoCancel(true);
if(tinyDB.getBoolean("notificationsEnableLights", true)) {
@ -201,11 +143,8 @@ public class NotificationsWorker extends Worker {
}
if(tinyDB.getBoolean("notificationsEnableVibration", true)) {
builder.setVibrate(VIBRATION_PATTERN);
}
else {
builder.setVibrate(new long[]{ 1000, 1000 });
} else {
builder.setVibrate(null);
}
@ -219,5 +158,6 @@ public class NotificationsWorker extends Worker {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return PendingIntent.getActivity(context, 0, intent, 0);
}
}

View File

@ -18,6 +18,7 @@ import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import java.io.IOException;
import java.util.ArrayList;
@ -222,7 +223,7 @@ public class ReactionSpinner extends HorizontalScrollView {
if(response.isSuccessful() && response.body() != null) {
allowedReactions.addAll(Arrays.asList(response.body().getAllowed_reactions()));
} else {
allowedReactions.addAll(Arrays.asList("+1", "-1", "laugh", "hooray", "confused", "heart", "rocket", "eyes"));
allowedReactions.addAll(Arrays.asList(Constants.fallbackReactions));
}
return allowedReactions;

View File

@ -4,10 +4,7 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M22,19a2,2 0,0 1,-2 2H4a2,2 0,0 1,-2 -2V5a2,2 0,0 1,2 -2h5l2,3h9a2,2 0,0 1,2 2z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
android:fillColor="?attr/iconsColor"
android:pathData="M3.75,4.5a0.25,0.25 0,0 0,-0.25 0.25v14.5c0,0.138 0.112,0.25 0.25,0.25h16.5a0.25,0.25 0,0 0,0.25 -0.25V7.687a0.25,0.25 0,0 0,-0.25 -0.25h-8.471a1.75,1.75 0,0 1,-1.447 -0.765L8.928,4.61a0.25,0.25 0,0 0,-0.208 -0.11H3.75zM2,4.75C2,3.784 2.784,3 3.75,3h4.971c0.58,0 1.12,0.286 1.447,0.765l1.404,2.063a0.25,0.25 0,0 0,0.207 0.11h8.471c0.966,0 1.75,0.783 1.75,1.75V19.25A1.75,1.75 0,0 1,20.25 21H3.75A1.75,1.75 0,0 1,2 19.25V4.75z"
android:fillType="evenOdd"/>
</vector>

View File

@ -4,17 +4,7 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M13,2H6a2,2 0,0 0,-2 2v16a2,2 0,0 0,2 2h12a2,2 0,0 0,2 -2V9z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M13,2l0,7l7,0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
android:fillColor="?attr/iconsColor"
android:pathData="M5,2.5a0.5,0.5 0,0 0,-0.5 0.5v18a0.5,0.5 0,0 0,0.5 0.5h14a0.5,0.5 0,0 0,0.5 -0.5L19.5,8.5h-4a2,2 0,0 1,-2 -2v-4L5,2.5zM15,2.5v4a0.5,0.5 0,0 0,0.5 0.5h4a0.5,0.5 0,0 0,-0.146 -0.336l-4.018,-4.018A0.5,0.5 0,0 0,15 2.5zM3,3a2,2 0,0 1,2 -2h9.982a2,2 0,0 1,1.414 0.586l4.018,4.018A2,2 0,0 1,21 7.018L21,21a2,2 0,0 1,-2 2L5,23a2,2 0,0 1,-2 -2L3,3z"
android:fillType="evenOdd"/>
</vector>

View File

@ -4,24 +4,10 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
android:fillColor="?attr/iconsColor"
android:pathData="M10.97,8.265a1.45,1.45 0,0 0,-0.487 0.57,0.75 0.75,0 0,1 -1.341,-0.67c0.2,-0.402 0.513,-0.826 0.997,-1.148C10.627,6.69 11.244,6.5 12,6.5c0.658,0 1.369,0.195 1.934,0.619a2.45,2.45 0,0 1,1.004 2.006c0,1.033 -0.513,1.72 -1.027,2.215 -0.19,0.183 -0.399,0.358 -0.579,0.508l-0.147,0.123a4.329,4.329 0,0 0,-0.435 0.409v1.37a0.75,0.75 0,1 1,-1.5 0v-1.473c0,-0.237 0.067,-0.504 0.247,-0.736 0.22,-0.28 0.486,-0.517 0.718,-0.714l0.183,-0.153 0.001,-0.001c0.172,-0.143 0.324,-0.27 0.47,-0.412 0.368,-0.355 0.569,-0.676 0.569,-1.136a0.953,0.953 0,0 0,-0.404 -0.806C12.766,8.118 12.384,8 12,8c-0.494,0 -0.814,0.121 -1.03,0.265zM13,17a1,1 0,1 1,-2 0,1 1,0 0,1 2,0z"/>
<path
android:pathData="M9.09,9a3,3 0,0 1,5.83 1c0,2 -3,3 -3,3"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M12,17L12.01,17"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
android:fillColor="?attr/iconsColor"
android:pathData="M12,1C5.925,1 1,5.925 1,12s4.925,11 11,11 11,-4.925 11,-11S18.075,1 12,1zM2.5,12a9.5,9.5 0,1 1,19 0,9.5 9.5,0 0,1 -19,0z"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/iconsColor"
android:pathData="M2,4.75C2,3.784 2.784,3 3.75,3h4.965a1.75,1.75 0,0 1,1.456 0.78l1.406,2.109a0.25,0.25 0,0 0,0.208 0.111h8.465c0.966,0 1.75,0.784 1.75,1.75v11.5A1.75,1.75 0,0 1,20.25 21L3.75,21A1.75,1.75 0,0 1,2 19.25L2,4.75zM14.78,9.72a0.75,0.75 0,1 0,-1.06 1.06l1.72,1.72L6.75,12.5a0.75,0.75 0,0 0,0 1.5h8.69l-1.72,1.72a0.75,0.75 0,1 0,1.06 1.06l3,-3a0.75,0.75 0,0 0,0 -1.06l-3,-3z"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/iconsColor"
android:pathData="M3,3a2,2 0,0 1,2 -2h9.982a2,2 0,0 1,1.414 0.586l4.018,4.018A2,2 0,0 1,21 7.018L21,21a2,2 0,0 1,-2 2L4.75,23a0.75,0.75 0,0 1,0 -1.5L19,21.5a0.5,0.5 0,0 0,0.5 -0.5L19.5,8.5h-4a2,2 0,0 1,-2 -2v-4L5,2.5a0.5,0.5 0,0 0,-0.5 0.5v6.25a0.75,0.75 0,0 1,-1.5 0L3,3zM15,2.5v4a0.5,0.5 0,0 0,0.5 0.5h4a0.5,0.5 0,0 0,-0.146 -0.336l-4.018,-4.018A0.5,0.5 0,0 0,15 2.5zM9.308,14.5l-2.104,-2.236a0.75,0.75 0,1 1,1.092 -1.028l3.294,3.5a0.75,0.75 0,0 1,0 1.028l-3.294,3.5a0.75,0.75 0,1 1,-1.092 -1.028L9.308,16L4.09,16a2.59,2.59 0,0 0,-2.59 2.59v3.16a0.75,0.75 0,0 1,-1.5 0v-3.16a4.09,4.09 0,0 1,4.09 -4.09h5.218z"
android:fillType="evenOdd"/>
</vector>

View File

@ -64,20 +64,21 @@
android:orientation="vertical">
<LinearLayout
android:id="@+id/singleFileContentsFrame"
android:id="@+id/markdownFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical"
android:padding="16dp"
android:orientation="vertical">
android:visibility="gone">
<TextView
android:id="@+id/singleFileContents"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp"
android:textIsSelectable="true" />
<TextView
android:id="@+id/markdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="14sp" />
</LinearLayout>
@ -86,7 +87,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
android:orientation="vertical"
android:visibility="gone">
<com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfView"
@ -97,14 +99,14 @@
</LinearLayout>
<org.mian.gitnex.helpers.highlightjs.HighlightJsView
android:id="@+id/singleCodeContents"
android:id="@+id/contents"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:visibility="gone" />
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/imageView"
android:id="@+id/photo_view"
android:visibility="gone"
android:padding="16dp"
android:layout_width="match_parent"

View File

@ -69,7 +69,6 @@
android:textSize="14sp"
android:layout_marginStart="44dp"
android:layout_marginEnd="24dp"
android:text="@string/settingsFileViewerSourceCodeSelectedText"
android:textColor="?attr/selectedTextColor"/>
</LinearLayout>

View File

@ -46,10 +46,11 @@
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_bar"
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@id/filesFrame"
android:indeterminate="true"
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
</RelativeLayout>

View File

@ -21,80 +21,72 @@
android:contentDescription="@string/generalImgContentText"
android:scaleType="centerCrop" />
<eightbitlab.com.blurview.BlurView
android:id="@+id/blurView"
<LinearLayout
android:id="@+id/layoutFrameAccount"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:blurOverlayColor="@color/blurColor">
android:gravity="center"
android:orientation="vertical"
android:padding="16dp">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/generalImgContentText"
android:src="@mipmap/app_logo_round" />
<TextView
android:id="@+id/userFullName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="18sp" />
<TextView
android:id="@+id/userLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="14sp" />
<View
android:id="@+id/divider"
android:layout_width="50dp"
android:layout_height="1dp"
android:layout_marginBottom="10dp"
android:background="@color/colorWhite" />
<LinearLayout
android:id="@+id/layoutFrameAccount"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_marginBottom="8dp"
android:id="@+id/userLanguageIcon"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:layout_marginEnd="2dp"
android:contentDescription="@string/generalImgContentText"
android:src="@mipmap/app_logo_round" />
android:src="@drawable/ic_language"
app:tint="@color/colorWhite" />
<TextView
android:id="@+id/userFullName"
android:id="@+id/userLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="18sp" />
<TextView
android:id="@+id/userLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="14sp" />
<View
android:id="@+id/divider"
android:layout_width="50dp"
android:layout_height="1dp"
android:layout_marginBottom="10dp"
android:background="@color/colorWhite" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
android:id="@+id/userLanguageIcon"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:layout_marginEnd="2dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_language"
app:tint="@color/colorWhite" />
<TextView
android:id="@+id/userLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</eightbitlab.com.blurview.BlurView>
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,61 @@
<?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:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="15dp"
android:paddingTop="10dp"
android:paddingRight="15dp"
android:paddingBottom="10dp">
<ImageView
android:id="@+id/commiter_avatar"
android:layout_width="35dp"
android:layout_height="35dp"
android:contentDescription="@string/generalImgContentText"
tools:srcCompat="@tools:sample/avatars" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:orientation="vertical">
<TextView
android:id="@+id/commit_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:textColor="?attr/primaryTextColor"
android:textStyle="bold"
tools:text="Voluptatem vero ad quia voluptatum quisquam. Nihil earum et praesentium." />
<TextView
android:id="@+id/commit_sha"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:singleLine="true"
android:textColor="?attr/primaryTextColor"
app:drawableStartCompat="@drawable/ic_commit"
app:drawableTint="?attr/primaryTextColor"
tools:text="afcfb7c15a" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dividerColor" />
</LinearLayout>

View File

@ -4,102 +4,83 @@
android:id="@+id/relativeLayoutFrameIssuesList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_margin="15dp"
android:orientation="vertical"
android:background="?attr/primaryBackgroundColor">
<TextView
android:id="@+id/issueNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible" />
<ImageView
android:id="@+id/assigneeAvatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="15dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_android" />
<TextView
android:id="@+id/repoFullName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible" />
<RelativeLayout
android:id="@+id/mainFrame"
<LinearLayout
android:id="@+id/infoSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_margin="15dp"
android:layout_toEndOf="@+id/assigneeAvatar"
android:orientation="vertical">
<ImageView
android:id="@+id/assigneeAvatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="15dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_android" />
<LinearLayout
android:id="@+id/infoSection"
android:id="@+id/frameIssueNameStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/assigneeAvatar"
android:orientation="vertical">
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/issueTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top|center_vertical"
android:textAlignment="gravity"
android:text="@string/strFilter"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/frameCreatedDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/frameIssueNameStatus"
android:layout_width="match_parent"
android:id="@+id/frameCommentsCount"
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/issueTitle"
android:id="@+id/issueCommentsCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top|center_vertical"
android:textAlignment="gravity"
android:text="@string/strFilter"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/frameCreatedDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/frameCommentsCount"
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/issueCommentsCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:drawablePadding="5dp"
app:drawableStartCompat="@drawable/ic_comment"
android:layout_gravity="center_horizontal"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:id="@+id/issueCreatedTime"
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:gravity="end"
android:gravity="start"
android:drawablePadding="5dp"
app:drawableStartCompat="@drawable/ic_comment"
android:layout_gravity="center_horizontal"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:id="@+id/issueCreatedTime"
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:gravity="end"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -5,119 +5,82 @@
android:id="@+id/relativeLayoutFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_margin="15dp"
android:orientation="vertical"
android:background="?attr/primaryBackgroundColor">
<TextView
android:id="@+id/prNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"/>
<ImageView
android:id="@+id/assigneeAvatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="15dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_android" />
<TextView
android:id="@+id/prMergeable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"/>
<TextView
android:id="@+id/prHeadBranch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"/>
<TextView
android:id="@+id/prIsFork"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"/>
<TextView
android:id="@+id/prForkFullName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"/>
<RelativeLayout
android:id="@+id/mainFrame"
<LinearLayout
android:id="@+id/infoSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_margin="15dp"
android:layout_toEndOf="@+id/assigneeAvatar"
android:orientation="vertical">
<ImageView
android:id="@+id/assigneeAvatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="15dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_android" />
<LinearLayout
android:id="@+id/infoSection"
android:id="@+id/framePrNameStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/assigneeAvatar"
android:orientation="vertical">
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/framePrNameStatus"
android:layout_width="match_parent"
<TextView
android:id="@+id/prTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/prTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top|center_vertical"
android:textAlignment="gravity"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/frameCreatedDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/frameCommentsCount"
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/prCommentsCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:drawablePadding="5dp"
android:layout_gravity="center_horizontal"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp"
app:drawableStartCompat="@drawable/ic_comment" />
</LinearLayout>
<TextView
android:id="@+id/prCreatedTime"
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:gravity="end"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
android:gravity="top|center_vertical"
android:textAlignment="gravity"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/frameCreatedDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/frameCommentsCount"
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/prCommentsCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:drawablePadding="5dp"
android:layout_gravity="center_horizontal"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp"
app:drawableStartCompat="@drawable/ic_comment" />
</LinearLayout>
<TextView
android:id="@+id/prCreatedTime"
android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content"
android:gravity="end"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:id="@+id/navHeaderFrame"
android:layout_width="match_parent"
android:layout_height="200dp">
@ -10,106 +11,79 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/generalImgContentText"
android:scaleType="centerCrop" />
android:scaleType="centerCrop"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<eightbitlab.com.blurview.BlurView
android:id="@+id/blurView"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:blurOverlayColor="@color/blurColor">
android:gravity="bottom"
android:orientation="vertical"
android:paddingStart="20dp"
android:paddingTop="20dp"
android:paddingEnd="20dp"
android:paddingBottom="20dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
android:paddingTop="16dp">
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/userAvatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="24dp"
android:maxWidth="24dp"
android:paddingStart="20dp"
android:paddingEnd="5dp"
android:contentDescription="@string/generalImgContentText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:paddingEnd="25dp"
android:paddingStart="15dp"
android:paddingTop="6dp"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/navRecyclerViewUserAccounts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:reverseLayout="true"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</LinearLayout>
<LinearLayout
<ImageView
android:id="@+id/userAvatar"
android:layout_width="60dp"
android:layout_height="60dp"
android:contentDescription="@string/generalImgContentText"
tools:srcCompat="@tools:sample/avatars" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/navRecyclerViewUserAccounts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:layout_marginTop="5dp"
android:baselineAligned="false">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".82"
android:orientation="vertical"
android:layout_marginTop="5dp">
<TextView
android:id="@+id/userFullname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:textSize="18sp"
android:textIsSelectable="true"
android:textColor="@color/colorWhite"
android:paddingStart="20dp"
android:paddingEnd="5dp" />
<TextView
android:id="@+id/userEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textIsSelectable="true"
android:textColor="@color/colorWhite"
android:gravity="start"
android:layout_gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="5dp" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:background="?attr/dividerColor" />
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:reverseLayout="true" />
</LinearLayout>
</eightbitlab.com.blurview.BlurView>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:baselineAligned="false"
android:orientation="vertical">
<TextView
android:id="@+id/userFullname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="18sp"
tools:text="Test user" />
<TextView
android:id="@+id/userEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="start"
android:textColor="@color/colorWhite"
android:textIsSelectable="true"
android:textSize="14sp"
tools:text="example@example.com" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:layout_marginTop="16dp"
android:background="?attr/dividerColor" />
</RelativeLayout>

View File

@ -578,7 +578,7 @@
<string name="downloadFile">Download This File</string>
<string name="waitLoadingDownloadFile">Please wait for the file to load to memory</string>
<string name="downloadFileSaved">File saved successfully</string>
<string name="excludeFilesInFileViewer">This file type is not supported in file viewer. Download it instead from the three dotted menu?</string>
<string name="excludeFilesInFileViewer">This file type/size is not supported in file viewer. You can download it from the menu.</string>
<string name="deleteFile">Delete This File</string>
<string name="editFile">Edit This File</string>
<string name="deleteFileText">Delete %1$s</string>
@ -674,7 +674,8 @@
<string name="chooseColorSelectorHeader">Choose Color</string>
<string name="newMessages">New messages</string>
<string name="youHaveGotNewNotifications">You\'ve got %d new notifications.</string>
<string name="notificationChannelDescription" translatable="false">This is the main notification channel of GitNex.</string>
<string name="mainNotificationChannelName">Notifications</string>
<string name="mainNotificationChannelDescription">This is the main notification channel of GitNex.</string>
<string name="notificationExtraInfo" translatable="false">- %s (%s)</string>
<string name="isRead">Read</string>
@ -742,4 +743,15 @@
<string name="copyLoginIdToClipBoard">Login ID \'%s\' copied to clipboard</string>
<!-- file viewer activity -->
<string name="fileViewerNotificationTitleStarted">Download in progress</string>
<string name="fileViewerNotificationDescriptionStarted">Downloading %s</string>
<string name="fileViewerNotificationTitleFinished">Download successful</string>
<string name="fileViewerNotificationDescriptionFinished">Downloaded %s</string>
<string name="fileViewerNotificationTitleFailed">Download failed</string>
<string name="fileViewerNotificationDescriptionFailed">Couldn\'t download %s</string>
<string name="fileViewerNotificationChannelName">Download manager</string>
<string name="fileViewerNotificationChannelDescription">Indicates the progress of ongoing downloads</string>
</resources>

View File

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.2'
classpath 'com.android.tools.build:gradle:4.1.3'
}
}