Browse Source

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>
pull/848/head
opyale 5 months ago
committed by M M Arif
parent
commit
98cf1a1976
  1. 45
      README.md
  2. 21
      app/build.gradle
  3. 5
      app/src/main/java/org/mian/gitnex/actions/NotificationsActions.java
  4. 6
      app/src/main/java/org/mian/gitnex/activities/CommitsActivity.java
  5. 205
      app/src/main/java/org/mian/gitnex/activities/CreateFileActivity.java
  6. 6
      app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java
  7. 15
      app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java
  8. 6
      app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java
  9. 101
      app/src/main/java/org/mian/gitnex/activities/FileDiffActivity.java
  10. 512
      app/src/main/java/org/mian/gitnex/activities/FileViewActivity.java
  11. 43
      app/src/main/java/org/mian/gitnex/activities/MainActivity.java
  12. 9
      app/src/main/java/org/mian/gitnex/activities/MergePullRequestActivity.java
  13. 6
      app/src/main/java/org/mian/gitnex/activities/RepoForksActivity.java
  14. 46
      app/src/main/java/org/mian/gitnex/activities/SettingsFileViewerActivity.java
  15. 11
      app/src/main/java/org/mian/gitnex/activities/SettingsNotificationsActivity.java
  16. 60
      app/src/main/java/org/mian/gitnex/adapters/FilesAdapter.java
  17. 58
      app/src/main/java/org/mian/gitnex/adapters/IssuesAdapter.java
  18. 4
      app/src/main/java/org/mian/gitnex/adapters/MilestonesAdapter.java
  19. 119
      app/src/main/java/org/mian/gitnex/adapters/PullRequestsAdapter.java
  20. 37
      app/src/main/java/org/mian/gitnex/adapters/SearchIssuesAdapter.java
  21. 29
      app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java
  22. 9
      app/src/main/java/org/mian/gitnex/core/MainApplication.java
  23. 8
      app/src/main/java/org/mian/gitnex/database/api/DraftsApi.java
  24. 12
      app/src/main/java/org/mian/gitnex/database/api/RepositoriesApi.java
  25. 10
      app/src/main/java/org/mian/gitnex/database/api/UserAccountsApi.java
  26. 4
      app/src/main/java/org/mian/gitnex/fragments/BottomSheetDraftsFragment.java
  27. 6
      app/src/main/java/org/mian/gitnex/fragments/BottomSheetReplyFragment.java
  28. 10
      app/src/main/java/org/mian/gitnex/fragments/ExploreRepositoriesFragment.java
  29. 104
      app/src/main/java/org/mian/gitnex/fragments/FilesFragment.java
  30. 12
      app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java
  31. 10
      app/src/main/java/org/mian/gitnex/fragments/MilestonesFragment.java
  32. 6
      app/src/main/java/org/mian/gitnex/fragments/NotificationsFragment.java
  33. 31
      app/src/main/java/org/mian/gitnex/fragments/ProfileFragment.java
  34. 10
      app/src/main/java/org/mian/gitnex/fragments/PullRequestsFragment.java
  35. 172
      app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java
  36. 1
      app/src/main/java/org/mian/gitnex/fragments/SettingsFragment.java
  37. 69
      app/src/main/java/org/mian/gitnex/helpers/AppUtil.java
  38. 8
      app/src/main/java/org/mian/gitnex/helpers/Authorization.java
  39. 46
      app/src/main/java/org/mian/gitnex/helpers/ColorInverter.java
  40. 61
      app/src/main/java/org/mian/gitnex/helpers/Constants.java
  41. 2
      app/src/main/java/org/mian/gitnex/helpers/ParseDiff.java
  42. 53
      app/src/main/java/org/mian/gitnex/helpers/StaticGlobalVariables.java
  43. 15
      app/src/main/java/org/mian/gitnex/helpers/highlightjs/HighlightJsView.java
  44. 66
      app/src/main/java/org/mian/gitnex/notifications/Notifications.java
  45. 92
      app/src/main/java/org/mian/gitnex/notifications/NotificationsWorker.java
  46. 3
      app/src/main/java/org/mian/gitnex/views/ReactionSpinner.java
  47. 9
      app/src/main/res/drawable/ic_directory.xml
  48. 16
      app/src/main/res/drawable/ic_file.xml
  49. 24
      app/src/main/res/drawable/ic_question.xml
  50. 10
      app/src/main/res/drawable/ic_submodule.xml
  51. 10
      app/src/main/res/drawable/ic_symlink.xml
  52. 26
      app/src/main/res/layout/activity_file_view.xml
  53. 1
      app/src/main/res/layout/activity_settings_fileviewer.xml
  54. 3
      app/src/main/res/layout/fragment_files.xml
  55. 106
      app/src/main/res/layout/fragment_profile.xml
  56. 61
      app/src/main/res/layout/layout_last_commit.xml
  57. 119
      app/src/main/res/layout/list_issues.xml
  58. 137
      app/src/main/res/layout/list_pr.xml
  59. 148
      app/src/main/res/layout/nav_header.xml
  60. 16
      app/src/main/res/values/strings.xml
  61. 2
      build.gradle

45
README.md

@ -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)

21
app/build.gradle

@ -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'
}

5
app/src/main/java/org/mian/gitnex/actions/NotificationsActions.java

@ -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");

6
app/src/main/java/org/mian/gitnex/activities/CommitsActivity.java

@ -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;

205
app/src/main/java/org/mian/gitnex/activities/CreateFileActivity.java

@ -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) {
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) {
switch(response.code()) {
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 {
case 200:
enableProcessButton();
Toasty.info(ctx, getString(R.string.deleteFileMessage, tinyDB.getString("repoBranch")));
getIntent().removeExtra("filePath");
getIntent().removeExtra("fileSha");
getIntent().removeExtra("fileContents");
finish();
break;
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); }
}

6
app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java

@ -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();

15
app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java

@ -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));

6
app/src/main/java/org/mian/gitnex/activities/EditIssueActivity.java

@ -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();

101
app/src/main/java/org/mian/gitnex/activities/FileDiffActivity.java

@ -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();
};
}

512
app/src/main/java/org/mian/gitnex/activities/FileViewActivity.java

@ -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);
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");
setSupportActionBar(binding.toolbar);
tinyDB.putBoolean("enableMarkdownInFileView", false);
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());
file = (Files) getIntent().getSerializableExtra("file");
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
binding.close.setOnClickListener(view -> finish());
tinyDB.putString("downloadFileContents", "");
binding.toolbarTitle.setMovementMethod(new ScrollingMovementMethod());
binding.toolbarTitle.setText(file.getPath());
try {
singleFileName = URLDecoder.decode(singleFileName, "UTF-8");
singleFileName = singleFileName.replaceAll("//", "/");
singleFileName = singleFileName.startsWith("/") ? singleFileName.substring(1) : singleFileName;
}
catch(UnsupportedEncodingException e) {
Log.i("singleFileName", singleFileName);
}
String repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
toolbar_title.setText(singleFileName);
getSingleFileContents(repoOwner, repoName, file.getPath(), repoBranch);
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;
if(!response.body().getContent().equals("")) {
ResponseBody responseBody = response.body();
String fileExtension = FileUtils.getExtension(filename);
mProgressBar.setVisibility(View.GONE);
if(responseBody != null) {
fileSha = response.body().getSha();
runOnUiThread(() -> binding.progressBar.setVisibility(View.GONE));
// download file meta
tinyDB.putString("downloadFileName", filename);
tinyDB.putString("downloadFileContents", response.body().getContent());
String fileExtension = FileUtils.getExtension(filename);
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())) {
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));
imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT);
imageView.setImageBitmap(Images.scaleImage(imageData, 1920));
});
}
break;
case UNKNOWN:
case TEXT:
imageView.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.VISIBLE);
if(file.getSize() > Constants.maximumFileViewerSize) {
break;
}
switch(tinyDB.getInt("fileviewerSourceCodeThemeId")) {
processable = true;
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;
String text = responseBody.string();
default: singleCodeContents.setTheme(Theme.MONOKAI_SUBLIME);
runOnUiThread(() -> {
}
binding.photoView.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.GONE);
binding.pdfViewFrame.setVisibility(View.GONE);
switch(tinyDB.getInt("fileviewerSourceCodeThemeId")) {
singleCodeContents.setSource(AppUtil.decodeBase64(response.body().getContent()));
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);
pdfNightMode = tinyDB.getBoolean("enablePdfMode");
decodedPdf = Base64.decode(response.body().getContent(), Base64.DEFAULT);
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();
processable = true;
byte[] documentBytes = responseBody.bytes();
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();
runOnUiThread(() -> {
singleFileContents.setText(getString(R.string.excludeFilesInFileViewer));
singleFileContents.setGravity(Gravity.CENTER);
singleFileContents.setTypeface(null, Typeface.BOLD);
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);
});
singleFileContents.setText("");
mProgressBar.setVisibility(View.GONE);
}
}
else if(response.code() == 401) {
} else {
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) {
switch(response.code()) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
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;
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
break;
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
case 404:
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
break;
@Override
public void onFailure(@NonNull Call<Files> call, @NonNull Throwable t) {
default:
Toasty.error(ctx, getString(R.string.labelGeneralError));
}
}
} catch(IOException ignored) {}
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(!fileExtension.equalsIgnoreCase("md")) {
if(!FileUtils.getExtension(file.getName())
.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);
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 {
singleCodeContents.setVisibility(View.VISIBLE);
singleFileContentsFrame.setVisibility(View.GONE);
singleFileContents.setVisibility(View.GONE);
singleCodeContents.setSource(AppUtil.decodeBase64(tinyDB.getString("downloadFileContents")));
} else {
binding.markdownFrame.setVisibility(View.GONE);
binding.contents.setVisibility(View.VISIBLE);
tinyDB.putBoolean("enableMarkdownInFileView", false);
}
return true;
}
else {
} else {
return super.onOptionsItemSelected(item);
}
@ -360,102 +352,118 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie