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. Thanks to all the open source libraries, contributors and donators.
#### Open source libraries #### Open source libraries
- Retrofit - [square/retrofit](https://github.com/square/retrofit)
- Gson - [google/gson](https://github.com/google/gson)
- Okhttp - [square/okhttp](https://github.com/square/okhttp)
- Picasso - [square/picasso](https://github.com/square/picasso)
- Markwon - [wasabeef/picasso-transformations](https://github.com/wasabeef/picasso-transformations)
- Prism4j - [cats-oss/android-gpuimage](https://github.com/cats-oss/android-gpuimage)
- Prettytime - [noties/Markwon](https://github.com/noties/Markwon)
- Amulyakhare/textdrawable - [noties/Prism4j](https://github.com/noties/Prism4j)
- Vdurmont/emoji-java - [ocpsoft/prettytime](https://github.com/ocpsoft/prettytime)
- Pes/materialcolorpicker - [amulyakhare/TextDrawable](https://github.com/amulyakhare/TextDrawable)
- HamidrezaAmz/BreadcrumbsView - [vdurmont/emoji-java](https://github.com/vdurmont/emoji-java)
- Chrisbanes/PhotoView - [Pes8/android-material-color-picker-dialog](https://github.com/Pes8/android-material-color-picker-dialog)
- Pddstudio/highlightjs-android - [HamidrezaAmz/BreadcrumbsView](https://github.com/HamidrezaAmz/BreadcrumbsView)
- Apache/commons-io - [Baseflow/PhotoView](https://github.com/Baseflow/PhotoView)
- Caverock/androidsvg - [PDDStudio/highlightjs-android](https://github.com/PDDStudio/highlightjs-android)
- Droidsonroids.gif/android-gif-drawable - [apache/commons](https://github.com/apache/commons-io)
- Barteksc/androidPdfViewer - [barteksc/AndroidPdfViewer](https://github.com/barteksc/AndroidPdfViewer)
- Ge0rg/memorizingTrustManager - [ge0rg/MemorizingTrustManager](https://github.com/ge0rg/MemorizingTrustManager)
- Dimezis/blurView - [mikaelhg/urlbuilder](https://github.com/mikaelhg/urlbuilder)
- 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) [Follow me on Fediverse - mastodon.social/@mmarif](https://mastodon.social/@mmarif)

View File

@ -30,7 +30,7 @@ android {
release { release {
minifyEnabled false minifyEnabled false
shrinkResources false shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
lintOptions { lintOptions {
@ -55,7 +55,7 @@ configurations {
dependencies { dependencies {
def lifecycle_version = '2.3.0' 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 work_version = "2.5.0"
def acra = "5.7.0" def acra = "5.7.0"
@ -65,17 +65,19 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" 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:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.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.google.code.gson:gson:2.8.6"
implementation "com.squareup.picasso:picasso:2.71828" 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.amulyakhare:com.amulyakhare.textdrawable:1.0.1"
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars: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 'org.ocpsoft.prettytime:prettytime:5.0.0.Final'
implementation "com.pes.materialcolorpicker:library:1.2.5" implementation "com.pes.materialcolorpicker:library:1.2.5"
implementation "io.noties.markwon:core:$markwon_version" implementation "io.noties.markwon:core:$markwon_version"
@ -94,11 +96,9 @@ dependencies {
implementation "io.noties.markwon:image-picasso:$markwon_version" implementation "io.noties.markwon:image-picasso:$markwon_version"
implementation "io.noties:prism4j:2.0.0" implementation "io.noties:prism4j:2.0.0"
annotationProcessor "io.noties:prism4j-bundler: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 "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
implementation "commons-io:commons-io:20030203.000550" 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.chrisbanes:PhotoView:2.3.0"
implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1" implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1"
implementation "ch.acra:acra-mail:$acra" implementation "ch.acra:acra-mail:$acra"
@ -107,11 +107,10 @@ dependencies {
implementation 'androidx.room:room-runtime:2.2.6' implementation 'androidx.room:room-runtime:2.2.6'
annotationProcessor 'androidx.room:room-compiler:2.2.6' annotationProcessor 'androidx.room:room-compiler:2.2.6'
implementation "androidx.work:work-runtime:$work_version" implementation "androidx.work:work-runtime:$work_version"
implementation "com.eightbitlab:blurview:1.6.4"
implementation "io.mikael:urlbuilder:2.0.9" implementation "io.mikael:urlbuilder:2.0.9"
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2" implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
implementation "org.codeberg.gitnex:tea4j:1.0.1" implementation "org.codeberg.gitnex:tea4j:1.0.5"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.1" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation 'androidx.biometric:biometric:1.1.0' 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 org.mian.gitnex.helpers.TinyDB;
import java.io.IOException; import java.io.IOException;
import java.util.Date; import java.util.Date;
import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
/** /**
@ -35,7 +34,7 @@ public class NotificationsActions {
public void setNotificationStatus(NotificationThread notificationThread, NotificationStatus notificationStatus) throws IOException { 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()); .markNotificationThreadAsRead(instanceToken, notificationThread.getId(), notificationStatus.name());
if(!call.execute().isSuccessful()) { if(!call.execute().isSuccessful()) {
@ -46,7 +45,7 @@ public class NotificationsActions {
public boolean setAllNotificationsRead(Date date) throws IOException { 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, .markNotificationThreadsAsRead(instanceToken, AppUtil.getTimestampFromDate(context, date), true,
new String[]{"unread", "pinned"}, "read"); 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.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCommitsBinding; import org.mian.gitnex.databinding.ActivityCommitsBinding;
import org.mian.gitnex.helpers.Authorization; 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.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import java.util.ArrayList; import java.util.ArrayList;
@ -43,7 +43,7 @@ public class CommitsActivity extends BaseActivity {
private TextView noData; private TextView noData;
private ProgressBar progressBar; private ProgressBar progressBar;
private String TAG = "CommitsActivity"; private String TAG = "CommitsActivity";
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private int pageSize = 1; private int pageSize = 1;
private RecyclerView recyclerView; 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 gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12")) { if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances; resultLimit = Constants.resultLimitNewGiteaInstances;
} }
recyclerView = activityCommitsBinding.recyclerView; recyclerView = activityCommitsBinding.recyclerView;

View File

@ -8,10 +8,6 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter; 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 android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
@ -38,16 +34,7 @@ import retrofit2.Callback;
public class CreateFileActivity extends BaseActivity { public class CreateFileActivity extends BaseActivity {
public ImageView closeActivity; private ActivityCreateFileBinding binding;
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;
public static final int FILE_ACTION_CREATE = 0; public static final int FILE_ACTION_CREATE = 0;
public static final int FILE_ACTION_DELETE = 1; public static final int FILE_ACTION_DELETE = 1;
@ -55,6 +42,9 @@ public class CreateFileActivity extends BaseActivity {
private int fileAction = FILE_ACTION_CREATE; private int fileAction = FILE_ACTION_CREATE;
private String filePath;
private String fileSha;
private final List<String> branches = new ArrayList<>(); private final List<String> branches = new ArrayList<>();
private String repoOwner; private String repoOwner;
@ -66,154 +56,127 @@ public class CreateFileActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityCreateFileBinding activityCreateFileBinding = ActivityCreateFileBinding.inflate(getLayoutInflater()); binding = ActivityCreateFileBinding.inflate(getLayoutInflater());
setContentView(activityCreateFileBinding.getRoot()); setContentView(binding.getRoot());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
String repoFullName = tinyDB.getString("repoFullName"); String repoFullName = tinyDB.getString("repoFullName");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
repoOwner = parts[0]; repoOwner = parts[0];
repoName = parts[1]; repoName = parts[1];
closeActivity = activityCreateFileBinding.close; TextView toolbarTitle = binding.toolbarTitle;
newFileName = activityCreateFileBinding.newFileName;
newFileContent = activityCreateFileBinding.newFileContent;
newFileCommitMessage = activityCreateFileBinding.newFileCommitMessage;
TextView toolbarTitle = activityCreateFileBinding.toolbarTitle;
newFileName.requestFocus(); binding.newFileName.requestFocus();
assert imm != null;
imm.showSoftInput(newFileName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener(); InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
assert inputMethodManager != null;
inputMethodManager.showSoftInput(binding.newFileName, InputMethodManager.SHOW_IMPLICIT);
closeActivity.setOnClickListener(onClickListener); binding.close.setOnClickListener(view -> finish());
binding.newFileContent.setOnTouchListener((touchView, motionEvent) -> {
newFileCreate = activityCreateFileBinding.newFileCreate;
newFileContent.setOnTouchListener((touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true); 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); touchView.getParent().requestDisallowInterceptTouchEvent(false);
} }
return false; return false;
}); });
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE) == FILE_ACTION_DELETE) { if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE) == FILE_ACTION_DELETE) {
fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE); fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_DELETE);
filePath = getIntent().getStringExtra("filePath"); filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha"); fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.deleteFileText, filePath)); toolbarTitle.setText(getString(R.string.deleteFileText, filePath));
newFileCreate.setText(R.string.deleteFile); binding.newFileCreate.setText(R.string.deleteFile);
newFileName.setText(filePath);
newFileName.setEnabled(false);
newFileName.setFocusable(false);
newFileContent.setText(fileContents); binding.newFileNameLayout.setVisibility(View.GONE);
newFileContent.setEnabled(false); binding.newFileContentLayout.setVisibility(View.GONE);
newFileContent.setFocusable(false);
} }
if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT) == FILE_ACTION_EDIT) { if(getIntent().getStringExtra("filePath") != null && getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT) == FILE_ACTION_EDIT) {
fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT); fileAction = getIntent().getIntExtra("fileAction", FILE_ACTION_EDIT);
filePath = getIntent().getStringExtra("filePath"); filePath = getIntent().getStringExtra("filePath");
String fileContents = getIntent().getStringExtra("fileContents");
fileSha = getIntent().getStringExtra("fileSha"); fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.editFileText, filePath)); toolbarTitle.setText(getString(R.string.editFileText, filePath));
newFileCreate.setText(R.string.editFile); binding.newFileCreate.setText(R.string.editFile);
newFileName.setText(filePath); binding.newFileName.setText(filePath);
newFileName.setEnabled(false); binding.newFileName.setEnabled(false);
newFileName.setFocusable(false); binding.newFileName.setFocusable(false);
newFileContent.setText(fileContents); binding.newFileContent.setText(getIntent().getStringExtra("fileContents"));
} }
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
newFileBranches = activityCreateFileBinding.newFileBranches;
getBranches(repoOwner, repoName); getBranches(repoOwner, repoName);
disableProcessButton(); disableProcessButton();
NetworkStatusObserver networkStatusObserver = NetworkStatusObserver.getInstance(ctx); 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() { private void processNewFile() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx); String newFileName = binding.newFileName.getText() != null ? binding.newFileName.getText().toString() : "";
String newFileContent = binding.newFileContent.getText() != null ? binding.newFileContent.getText().toString() : "";
String newFileName_ = newFileName.getText().toString(); String newFileBranchName = binding.newFileBranches.getText() != null ? binding.newFileBranches.getText().toString() : "";
String newFileContent_ = newFileContent.getText().toString(); String newFileCommitMessage = binding.newFileCommitMessage.getText() != null ? binding.newFileCommitMessage.getText().toString() : "";
String newFileBranchName_ = newFileBranches.getText().toString();
String newFileCommitMessage_ = newFileCommitMessage.getText().toString();
if(!connToInternet) {
if(!AppUtil.hasNetworkConnection(appCtx)) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection)); Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return; 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)); Toasty.error(ctx, getString(R.string.newFileRequiredFields));
return; return;
} }
if(!AppUtil.checkStringsWithDash(newFileBranchName_)) { if(!AppUtil.checkStringsWithDash(newFileBranchName)) {
Toasty.error(ctx, getString(R.string.newFileInvalidBranchName)); Toasty.error(ctx, getString(R.string.newFileInvalidBranchName));
return; return;
} }
if(newFileCommitMessage_.length() > 255) { if(newFileCommitMessage.length() > 255) {
Toasty.warning(ctx, getString(R.string.newFileCommitMessageError)); Toasty.warning(ctx, getString(R.string.newFileCommitMessageError));
return;
} }
else {
disableProcessButton(); disableProcessButton();
switch(fileAction) { switch(fileAction) {
case FILE_ACTION_CREATE: case FILE_ACTION_CREATE:
createNewFile(Authorization.get(ctx), repoOwner, repoName, newFileName_, AppUtil.encodeBase64(newFileContent_), newFileCommitMessage_, newFileBranchName_); createNewFile(repoOwner, repoName, newFileName, AppUtil.encodeBase64(newFileContent), newFileCommitMessage, newFileBranchName);
break; break;
case FILE_ACTION_DELETE: case FILE_ACTION_DELETE:
deleteFile(Authorization.get(ctx), repoOwner, repoName, filePath, newFileCommitMessage_, newFileBranchName_, fileSha); deleteFile(repoOwner, repoName, filePath, newFileCommitMessage, newFileBranchName, fileSha);
break; break;
case FILE_ACTION_EDIT: case FILE_ACTION_EDIT:
editFile(Authorization.get(ctx), repoOwner, repoName, filePath, editFile(repoOwner, repoName, filePath, AppUtil.encodeBase64(newFileContent), newFileCommitMessage, newFileBranchName, fileSha);
AppUtil.encodeBase64(newFileContent_), newFileCommitMessage_, newFileBranchName_, fileSha); break;
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) ? NewFile createNewFileJsonStr = branches.contains(branchName) ?
new NewFile(branchName, fileContent, fileCommitMessage, "") : new NewFile(branchName, fileContent, fileCommitMessage, "") :
@ -221,7 +184,7 @@ public class CreateFileActivity extends BaseActivity {
Call<JsonElement> call = RetrofitClient Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx) .getApiInterface(ctx)
.createNewFile(token, repoOwner, repoName, fileName, createNewFileJsonStr); .createNewFile(Authorization.get(ctx), repoOwner, repoName, fileName, createNewFileJsonStr);
call.enqueue(new Callback<JsonElement>() { 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) ? DeleteFile deleteFileJsonStr = branches.contains(branchName) ?
new DeleteFile(branchName, fileCommitMessage, "", fileSha) : new DeleteFile(branchName, fileCommitMessage, "", fileSha) :
@ -276,42 +239,42 @@ public class CreateFileActivity extends BaseActivity {
Call<JsonElement> call = RetrofitClient Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx) .getApiInterface(ctx)
.deleteFile(token, repoOwner, repoName, fileName, deleteFileJsonStr); .deleteFile(Authorization.get(ctx), repoOwner, repoName, fileName, deleteFileJsonStr);
call.enqueue(new Callback<JsonElement>() { call.enqueue(new Callback<JsonElement>() {
@Override @Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) { public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) { switch(response.code()) {
enableProcessButton(); case 200:
Toasty.info(ctx, getString(R.string.deleteFileMessage, tinyDB.getString("repoBranch"))); enableProcessButton();
getIntent().removeExtra("filePath"); Toasty.info(ctx, getString(R.string.deleteFileMessage, tinyDB.getString("repoBranch")));
getIntent().removeExtra("fileSha"); getIntent().removeExtra("filePath");
getIntent().removeExtra("fileContents"); getIntent().removeExtra("fileSha");
finish(); getIntent().removeExtra("fileContents");
} finish();
else if(response.code() == 401) { break;
enableProcessButton(); case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle), enableProcessButton();
getResources().getString(R.string.alertDialogTokenRevokedMessage), AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
} getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
else { break;
if(response.code() == 404) {
case 404:
enableProcessButton(); enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound)); Toasty.info(ctx, getString(R.string.apiNotFound));
} break;
else {
default:
enableProcessButton(); enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError)); 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) ? EditFile editFileJsonStr = branches.contains(branchName) ?
new EditFile(branchName, fileCommitMessage, "", fileSha, fileContent) : new EditFile(branchName, fileCommitMessage, "", fileSha, fileContent) :
@ -333,7 +296,7 @@ public class CreateFileActivity extends BaseActivity {
Call<JsonElement> call = RetrofitClient Call<JsonElement> call = RetrofitClient
.getApiInterface(ctx) .getApiInterface(ctx)
.editFile(token, repoOwner, repoName, fileName, editFileJsonStr); .editFile(Authorization.get(ctx), repoOwner, repoName, fileName, editFileJsonStr);
call.enqueue(new Callback<JsonElement>() { 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); ArrayAdapter<String> adapter = new ArrayAdapter<>(CreateFileActivity.this, R.layout.list_spinner_items, branches);
newFileBranches.setAdapter(adapter); binding.newFileBranches.setAdapter(adapter);
newFileBranches.setText(tinyDB.getString("repoBranch"), false); binding.newFileBranches.setText(tinyDB.getString("repoBranch"), false);
enableProcessButton(); enableProcessButton();
@ -419,19 +382,7 @@ public class CreateFileActivity extends BaseActivity {
} }
private void initCloseListener() { private void disableProcessButton() { binding.newFileCreate.setEnabled(false); }
private void enableProcessButton() { binding.newFileCreate.setEnabled(true); }
onClickListener = view -> finish();
}
private void disableProcessButton() {
newFileCreate.setEnabled(false);
}
private void enableProcessButton() {
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.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; 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.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
@ -51,7 +51,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private CustomLabelsSelectionDialogBinding labelsBinding; private CustomLabelsSelectionDialogBinding labelsBinding;
private CustomAssigneesSelectionDialogBinding assigneesBinding; private CustomAssigneesSelectionDialogBinding assigneesBinding;
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private Dialog dialogLabels; private Dialog dialogLabels;
private Dialog dialogAssignees; private Dialog dialogAssignees;
private String labelsSetter; private String labelsSetter;
@ -93,7 +93,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
// require gitea 1.12 or higher // require gitea 1.12 or higher
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) { if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances; resultLimit = Constants.resultLimitNewGiteaInstances;
} }
viewBinding.newIssueTitle.requestFocus(); 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.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; 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.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -43,7 +42,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private ActivityCreatePrBinding viewBinding; private ActivityCreatePrBinding viewBinding;
private CustomLabelsSelectionDialogBinding labelsBinding; private CustomLabelsSelectionDialogBinding labelsBinding;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private Dialog dialogLabels; private Dialog dialogLabels;
private String labelsSetter; private String labelsSetter;
private List<Integer> labelsIds = new ArrayList<>(); private List<Integer> labelsIds = new ArrayList<>();
@ -80,7 +79,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
// require gitea 1.12 or higher // require gitea 1.12 or higher
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) { if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances; resultLimit = Constants.resultLimitNewGiteaInstances;
} }
viewBinding.prBody.setOnTouchListener((touchView, motionEvent) -> { 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); CreatePullRequest createPullRequest = new CreatePullRequest(prTitle, prDescription, loginUid, mergeInto, pullFrom, milestoneId, dueDate, assignees, labelsIds);
Call<ResponseBody> transferCall = RetrofitClient Call<Void> transferCall = RetrofitClient
.getApiInterface(appCtx) .getApiInterface(appCtx)
.createPullRequest(instanceToken, repoOwner, repoName, createPullRequest); .createPullRequest(instanceToken, repoOwner, repoName, createPullRequest);
transferCall.enqueue(new Callback<ResponseBody>() { transferCall.enqueue(new Callback<Void>() {
@Override @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(); disableProcessButton();
@ -199,7 +198,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
} }
@Override @Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
enableProcessButton(); enableProcessButton();
Toasty.error(ctx, getString(R.string.genericServerResponseError)); 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.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; 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.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import java.text.DateFormat; import java.text.DateFormat;
@ -45,7 +45,7 @@ import retrofit2.Callback;
public class EditIssueActivity extends BaseActivity implements View.OnClickListener { public class EditIssueActivity extends BaseActivity implements View.OnClickListener {
private View.OnClickListener onClickListener; private View.OnClickListener onClickListener;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private EditText editIssueTitle; private EditText editIssueTitle;
private EditText editIssueDescription; 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 gitea is 1.12 or higher use the new limit
if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) { if(new Version(tinyDB.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances; resultLimit = Constants.resultLimitNewGiteaInstances;
} }
editIssueTitle.requestFocus(); editIssueTitle.requestFocus();

View File

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

View File

@ -1,29 +1,21 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.app.Activity; import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.method.ScrollingMovementMethod; import android.text.method.ScrollingMovementMethod;
import android.util.Base64;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; 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.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat;
import androidx.appcompat.widget.Toolbar;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.util.FitPolicy; import com.github.barteksc.pdfviewer.util.FitPolicy;
import com.github.chrisbanes.photoview.PhotoView;
import com.vdurmont.emoji.EmojiParser; import com.vdurmont.emoji.EmojiParser;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.gitnex.tea4j.models.Files; 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.fragments.BottomSheetFileViewerFragment;
import org.mian.gitnex.helpers.AlertDialogs; import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil; 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.Images;
import org.mian.gitnex.helpers.Markdown; import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.highlightjs.HighlightJsView;
import org.mian.gitnex.helpers.highlightjs.models.Theme; 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.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.util.Arrays;
import java.net.URLDecoder; import okhttp3.ResponseBody;
import java.util.Objects;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Response;
/** /**
* Author M M Arif * Author M M Arif
@ -53,74 +45,38 @@ import retrofit2.Callback;
public class FileViewActivity extends BaseActivity implements BottomSheetFileViewerFragment.BottomSheetListener { public class FileViewActivity extends BaseActivity implements BottomSheetFileViewerFragment.BottomSheetListener {
private View.OnClickListener onClickListener; private ActivityFileViewBinding binding;
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 Boolean pdfNightMode; private Boolean pdfNightMode;
private String singleFileName;
private String fileSha; private Files file;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivityFileViewBinding activityFileViewBinding = ActivityFileViewBinding.inflate(getLayoutInflater()); binding = ActivityFileViewBinding.inflate(getLayoutInflater());
setContentView(activityFileViewBinding.getRoot()); setContentView(binding.getRoot());
Toolbar toolbar = activityFileViewBinding.toolbar; setSupportActionBar(binding.toolbar);
setSupportActionBar(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 repoFullName = tinyDB.getString("repoFullName");
String repoBranch = tinyDB.getString("repoBranch"); String repoBranch = tinyDB.getString("repoBranch");
String[] parts = repoFullName.split("/"); String[] parts = repoFullName.split("/");
final String repoOwner = parts[0]; String repoOwner = parts[0];
final String repoName = parts[1]; String repoName = parts[1];
final String loginUid = tinyDB.getString("loginUid");
final String instanceToken = "token " + tinyDB.getString(loginUid + "-token");
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 @Override
@ -128,166 +84,201 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
super.onResume(); 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")) { 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); 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 Response<ResponseBody> response = call.execute();
public void onResponse(@NonNull Call<Files> call, @NonNull retrofit2.Response<Files> response) {
if(response.code() == 200) { 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); String fileExtension = FileUtils.getExtension(filename);
mProgressBar.setVisibility(View.GONE);
fileSha = response.body().getSha(); boolean processable = false;
// download file meta
tinyDB.putString("downloadFileName", filename);
tinyDB.putString("downloadFileContents", response.body().getContent());
boolean unknown = false;
switch(AppUtil.getFileType(fileExtension)) { switch(AppUtil.getFileType(fileExtension)) {
case IMAGE: case IMAGE:
singleFileContentsFrame.setVisibility(View.GONE); // See https://developer.android.com/guide/topics/media/media-formats#core
singleCodeContents.setVisibility(View.GONE); if(Arrays.asList("bmp", "gif", "jpg", "jpeg", "png", "webp", "heic", "heif").contains(fileExtension.toLowerCase())) {
pdfViewFrame.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
imageData = Base64.decode(response.body().getContent(), Base64.DEFAULT); processable = true;
imageView.setImageBitmap(Images.scaleImage(imageData, 1920));
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; break;
case UNKNOWN:
case TEXT: case TEXT:
imageView.setVisibility(View.GONE); if(file.getSize() > Constants.maximumFileViewerSize) {
singleFileContentsFrame.setVisibility(View.GONE); break;
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);
} }
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; break;
case DOCUMENT: case DOCUMENT:
if(fileExtension.equalsIgnoreCase("pdf")) { if(fileExtension.equalsIgnoreCase("pdf")) {
imageView.setVisibility(View.GONE); processable = true;
singleFileContentsFrame.setVisibility(View.GONE);
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.VISIBLE);
pdfNightMode = tinyDB.getBoolean("enablePdfMode"); byte[] documentBytes = responseBody.bytes();
decodedPdf = Base64.decode(response.body().getContent(), Base64.DEFAULT);
pdfView.fromBytes(decodedPdf) runOnUiThread(() -> {
.enableSwipe(true)
.swipeHorizontal(false) binding.photoView.setVisibility(View.GONE);
.enableDoubletap(true) binding.markdownFrame.setVisibility(View.GONE);
.defaultPage(0) binding.contents.setVisibility(View.GONE);
.enableAnnotationRendering(false)
.password(null) pdfNightMode = tinyDB.getBoolean("enablePdfMode");
.scrollHandle(null)
.enableAntialiasing(true) binding.pdfViewFrame.setVisibility(View.VISIBLE);
.spacing(0) binding.pdfView.fromBytes(documentBytes)
.autoSpacing(true) .enableSwipe(true)
.pageFitPolicy(FitPolicy.WIDTH) .swipeHorizontal(false)
.fitEachPage(true) .enableDoubletap(true)
.pageSnap(false) .defaultPage(0)
.pageFling(true) .enableAnnotationRendering(false)
.nightMode(pdfNightMode).load(); .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; 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. // 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); responseBody.close();
singleCodeContents.setVisibility(View.GONE);
pdfViewFrame.setVisibility(View.GONE);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setText(getString(R.string.excludeFilesInFileViewer)); runOnUiThread(() -> {
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);
});
}
} 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 @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.generic_nav_dotted_menu, menu);
inflater.inflate(R.menu.files_view_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; return true;
@ -316,35 +307,36 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
finish(); finish();
return true; return true;
}
else if(id == R.id.genericMenu) { } else if(id == R.id.genericMenu) {
BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment(); BottomSheetFileViewerFragment bottomSheet = new BottomSheetFileViewerFragment();
bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet"); bottomSheet.show(getSupportFragmentManager(), "fileViewerBottomSheet");
return true; 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")) { if(!tinyDB.getBoolean("enableMarkdownInFileView")) {
singleCodeContents.setVisibility(View.GONE); new Markdown(ctx, EmojiParser.parseToUnicode(binding.contents.getContent()), binding.markdown);
singleFileContentsFrame.setVisibility(View.VISIBLE);
singleFileContents.setVisibility(View.VISIBLE); binding.contents.setVisibility(View.GONE);
tinyDB.putBoolean("enableMarkdownInFileView", true); binding.markdownFrame.setVisibility(View.VISIBLE);
}
else { 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); tinyDB.putBoolean("enableMarkdownInFileView", false);
} }
return true; return true;
}
else { } else {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@ -360,102 +352,118 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
if("deleteFile".equals(text)) { 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 intent = new Intent(ctx, CreateFileActivity.class);
intent.putExtra("fileAction", CreateFileActivity.FILE_ACTION_DELETE); intent.putExtra("fileAction", CreateFileActivity.FILE_ACTION_DELETE);
intent.putExtra("filePath", singleFileName); intent.putExtra("filePath", file.getPath());
intent.putExtra("fileSha", fileSha); intent.putExtra("fileSha", file.getSha());
intent.putExtra("fileContents", data);
ctx.startActivity(intent); ctx.startActivity(intent);
} }
if("editFile".equals(text)) { 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); } else {
intent.putExtra("filePath", singleFileName);
intent.putExtra("fileSha", fileSha);
intent.putExtra("fileContents", AppUtil.decodeBase64(tinyDB.getString("downloadFileContents")));
ctx.startActivity(intent); Toasty.error(ctx, getString(R.string.fileTypeCannotBeEdited));
break;
default:
Toasty.error(ctx, getString(R.string.fileTypeCannotBeEdited));
} }
} }
} }
private void requestFileDownload() { 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 = ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
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; OutputStream outputStream = getContentResolver().openOutputStream(result.getData().getData());
Uri uri = data.getData();
assert uri != null; NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, ctx.getPackageName())
OutputStream outputStream = getContentResolver().openOutputStream(uri); .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; NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);;
outputStream.write(dataAsBytes); notificationManager.notify(notificationId, builder.build());
outputStream.close();
Toasty.success(ctx, getString(R.string.downloadFileSaved)); String repoFullName = tinyDB.getString("repoFullName");
} String repoBranch = tinyDB.getString("repoBranch");
catch(IOException e) { 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"); assert response.body() != null;
finish();
}; 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.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -61,8 +60,7 @@ import org.mian.gitnex.helpers.Version;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import eightbitlab.com.blurview.BlurView; import jp.wasabeef.picasso.transformations.BlurTransformation;
import eightbitlab.com.blurview.RenderScriptBlur;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -73,12 +71,10 @@ import retrofit2.Callback;
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, BottomSheetDraftsFragment.BottomSheetListener { public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, BottomSheetDraftsFragment.BottomSheetListener {
private DrawerLayout drawer; private DrawerLayout drawer;
private BlurView blurView;
private TextView userFullName; private TextView userFullName;
private TextView userEmail; private TextView userEmail;
private ImageView userAvatar; private ImageView userAvatar;
private ImageView userAvatarBackground; private ImageView userAvatarBackground;
private ViewGroup navHeaderFrame;
private TextView toolbarTitle; private TextView toolbarTitle;
private Typeface myTypeface; private Typeface myTypeface;
@ -273,12 +269,10 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
String userFullNameNav = tinyDB.getString("userFullname"); String userFullNameNav = tinyDB.getString("userFullname");
String userAvatarNav = tinyDB.getString("userAvatar"); String userAvatarNav = tinyDB.getString("userAvatar");
blurView = hView.findViewById(R.id.blurView);
userEmail = hView.findViewById(R.id.userEmail); userEmail = hView.findViewById(R.id.userEmail);
userFullName = hView.findViewById(R.id.userFullname); userFullName = hView.findViewById(R.id.userFullname);
userAvatar = hView.findViewById(R.id.userAvatar); userAvatar = hView.findViewById(R.id.userAvatar);
userAvatarBackground = hView.findViewById(R.id.userAvatarBackground); userAvatarBackground = hView.findViewById(R.id.userAvatarBackground);
navHeaderFrame = hView.findViewById(R.id.navHeaderFrame);
List<UserAccount> userAccountsList; List<UserAccount> userAccountsList;
userAccountsList = new ArrayList<>(); userAccountsList = new ArrayList<>();
@ -323,24 +317,18 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
PicassoService.getInstance(ctx).get() PicassoService.getInstance(ctx).get()
.load(userAvatarNav) .load(userAvatarNav)
.transform(new BlurTransformation(ctx))
.into(userAvatarBackground, new com.squareup.picasso.Callback() { .into(userAvatarBackground, new com.squareup.picasso.Callback() {
@Override @Override
public void onSuccess() { public void onSuccess() {
int textColor = new ColorInverter().getImageViewContrastColor(userAvatar);
int textColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground);
userFullName.setTextColor(textColor); userFullName.setTextColor(textColor);
userEmail.setTextColor(textColor); userEmail.setTextColor(textColor);
blurView.setupWith(navHeaderFrame)
.setBlurAlgorithm(new RenderScriptBlur(ctx))
.setBlurRadius(5)
.setHasFixedTransformationMatrix(false);
} }
@Override @Override public void onError(Exception e) {}
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(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile); navigationView.setCheckedItem(R.id.nav_profile);
drawer.closeDrawers(); drawer.closeDrawers();
}); });
getNotificationsCount(instanceToken); getNotificationsCount(instanceToken);
@ -403,22 +392,21 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
switch(launchFragmentByHandler) { switch(launchFragmentByHandler) {
case "repos": case "repos":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories); navigationView.setCheckedItem(R.id.nav_repositories);
return; return;
case "org":
case "org":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations); navigationView.setCheckedItem(R.id.nav_organizations);
return; return;
case "notification":
case "notification":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications); navigationView.setCheckedItem(R.id.nav_notifications);
return; return;
case "explore":
case "explore":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore); navigationView.setCheckedItem(R.id.nav_explore);
return; return;
@ -438,49 +426,48 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
switch(tinyDB.getInt("homeScreenId")) { switch(tinyDB.getInt("homeScreenId")) {
case 1: case 1:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos)); toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos); navigationView.setCheckedItem(R.id.nav_starred_repos);
break; break;
case 2:
case 2:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations)); toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations); navigationView.setCheckedItem(R.id.nav_organizations);
break; break;
case 3:
case 3:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories)); toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories); navigationView.setCheckedItem(R.id.nav_repositories);
break; break;
case 4:
case 4:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile)); toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile); navigationView.setCheckedItem(R.id.nav_profile);
break; break;
case 5:
case 5:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore)); toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore); navigationView.setCheckedItem(R.id.nav_explore);
break; break;
case 6:
case 6:
toolbarTitle.setText(getResources().getString(R.string.titleDrafts)); toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new DraftsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_comments_draft); navigationView.setCheckedItem(R.id.nav_comments_draft);
break; break;
case 7:
case 7:
toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications)); toolbarTitle.setText(getResources().getString(R.string.pageTitleNotifications));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications); navigationView.setCheckedItem(R.id.nav_notifications);
break; break;
default:
default:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos)); toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home); 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 org.mian.gitnex.helpers.Version;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -170,12 +169,12 @@ public class MergePullRequestActivity extends BaseActivity {
MergePullRequest mergePR = new MergePullRequest(Do, mergePRDT, mergeTitle); 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 @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) { if(response.code() == 200) {
@ -244,7 +243,7 @@ public class MergePullRequestActivity extends BaseActivity {
} }
@Override @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()); Log.e("onFailure", t.toString());
enableProcessButton(); enableProcessButton();

View File

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

View File

@ -1,12 +1,8 @@
package org.mian.gitnex.activities; package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.os.Bundle; 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 androidx.appcompat.app.AlertDialog;
import com.google.android.material.switchmaterial.SwitchMaterial;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsFileviewerBinding; import org.mian.gitnex.databinding.ActivitySettingsFileviewerBinding;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
@ -17,40 +13,29 @@ import org.mian.gitnex.helpers.Toasty;
public class SettingsFileViewerActivity extends BaseActivity { 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 final String[] fileViewerSourceCodeThemesList = {"Sublime", "Arduino Light", "Github", "Far ", "Ir Black", "Android Studio"};
private static int fileViewerSourceCodeThemesSelectedChoice = 0; private static int fileViewerSourceCodeThemesSelectedChoice = 0;
@SuppressLint("DefaultLocale")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActivitySettingsFileviewerBinding activitySettingsFileviewerBinding = ActivitySettingsFileviewerBinding.inflate(getLayoutInflater()); ActivitySettingsFileviewerBinding binding = ActivitySettingsFileviewerBinding.inflate(getLayoutInflater());
setContentView(activitySettingsFileviewerBinding.getRoot()); setContentView(binding.getRoot());
ImageView closeActivity = activitySettingsFileviewerBinding.close; binding.close.setOnClickListener(view -> finish());
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"));
}
if(fileViewerSourceCodeThemesSelectedChoice == 0) { if(fileViewerSourceCodeThemesSelectedChoice == 0) {
fileViewerSourceCodeThemesSelectedChoice = tinyDB.getInt("fileviewerThemeId"); 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 // fileviewer source code theme selection dialog
sourceCodeThemeFrame.setOnClickListener(view -> { binding.sourceCodeThemeFrame.setOnClickListener(view -> {
AlertDialog.Builder fvtsBuilder = new AlertDialog.Builder(SettingsFileViewerActivity.this); AlertDialog.Builder fvtsBuilder = new AlertDialog.Builder(SettingsFileViewerActivity.this);
@ -60,7 +45,7 @@ public class SettingsFileViewerActivity extends BaseActivity {
fvtsBuilder.setSingleChoiceItems(fileViewerSourceCodeThemesList, fileViewerSourceCodeThemesSelectedChoice, (dialogInterfaceTheme, i) -> { fvtsBuilder.setSingleChoiceItems(fileViewerSourceCodeThemesList, fileViewerSourceCodeThemesSelectedChoice, (dialogInterfaceTheme, i) -> {
fileViewerSourceCodeThemesSelectedChoice = i; fileViewerSourceCodeThemesSelectedChoice = i;
fileViewerSourceCodeThemesSelected.setText(fileViewerSourceCodeThemesList[i]); binding.sourceCodeThemeSelected.setText(fileViewerSourceCodeThemesList[i]);
tinyDB.putString("fileviewerSourceCodeThemeStr", fileViewerSourceCodeThemesList[i]); tinyDB.putString("fileviewerSourceCodeThemeStr", fileViewerSourceCodeThemesList[i]);
tinyDB.putInt("fileviewerSourceCodeThemeId", i); tinyDB.putInt("fileviewerSourceCodeThemeId", i);
@ -69,21 +54,20 @@ public class SettingsFileViewerActivity extends BaseActivity {
}); });
AlertDialog cfDialog = fvtsBuilder.create(); AlertDialog alertDialog = fvtsBuilder.create();
cfDialog.show(); alertDialog.show();
}); });
// pdf night mode switcher // pdf night mode switcher
pdfModeSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { binding.switchPdfMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
tinyDB.putBoolean("enablePdfMode", isChecked); tinyDB.putBoolean("enablePdfMode", isChecked);
tinyDB.putString("enablePdfModeInit", "yes"); tinyDB.putString("enablePdfModeInit", "yes");
Toasty.success(appCtx, getResources().getString(R.string.settingsSave)); 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 com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsNotificationsBinding; 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.helpers.Toasty;
import org.mian.gitnex.notifications.Notifications; import org.mian.gitnex.notifications.Notifications;
@ -33,7 +33,7 @@ public class SettingsNotificationsActivity extends BaseActivity {
viewBinding.close.setOnClickListener(onClickListener); 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.chooseColorState.setCardBackgroundColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
viewBinding.enableNotificationsMode.setChecked(tinyDB.getBoolean("notificationsEnabled", true)); viewBinding.enableNotificationsMode.setChecked(tinyDB.getBoolean("notificationsEnabled", true));
@ -52,9 +52,9 @@ public class SettingsNotificationsActivity extends BaseActivity {
viewBinding.pollingDelayFrame.setOnClickListener(v -> { viewBinding.pollingDelayFrame.setOnClickListener(v -> {
NumberPicker numberPicker = new NumberPicker(ctx); NumberPicker numberPicker = new NumberPicker(ctx);
numberPicker.setMinValue(StaticGlobalVariables.minimumPollingDelay); numberPicker.setMinValue(Constants.minimumPollingDelay);
numberPicker.setMaxValue(StaticGlobalVariables.maximumPollingDelay); numberPicker.setMaxValue(Constants.maximumPollingDelay);
numberPicker.setValue(tinyDB.getInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay)); numberPicker.setValue(tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay));
numberPicker.setWrapSelectorWheel(true); numberPicker.setWrapSelectorWheel(true);
AlertDialog.Builder builder = new AlertDialog.Builder(ctx); 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.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss());
builder.setView(numberPicker); builder.setView(numberPicker);
builder.create().show(); builder.create().show();
}); });
// lights switcher // lights switcher

View File

@ -14,7 +14,6 @@ import androidx.recyclerview.widget.RecyclerView;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.gitnex.tea4j.models.Files; import org.gitnex.tea4j.models.Files;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Toasty;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -33,13 +32,12 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
public interface FilesAdapterListener { public interface FilesAdapterListener {
void onClickDir(String str); void onClickFile(Files file);
void onClickFile(String str);
} }
class FilesViewHolder extends RecyclerView.ViewHolder { class FilesViewHolder extends RecyclerView.ViewHolder {
private String fileType; private Files file;
private final ImageView fileTypeIs; private final ImageView fileTypeIs;
private final TextView fileName; private final TextView fileName;
@ -55,21 +53,7 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
//ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu); //ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu);
fileName.setOnClickListener(v -> { fileName.setOnClickListener(v -> filesListener.onClickFile(file));
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));
}
});
/*filesDropdownMenu.setOnClickListener(new View.OnClickListener() { /*filesDropdownMenu.setOnClickListener(new View.OnClickListener() {
@ -170,25 +154,36 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
Files currentItem = alteredFiles.get(position); Files currentItem = alteredFiles.get(position);
holder.fileType = currentItem.getType(); holder.file = currentItem;
holder.fileName.setText(currentItem.getName()); 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 @Override
@ -224,6 +219,7 @@ public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHol
results.values = filteredList; results.values = filteredList;
return results; return results;
} }
@Override @Override

View File

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

View File

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

View File

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

View File

@ -47,39 +47,35 @@ public class SearchIssuesAdapter extends RecyclerView.Adapter<SearchIssuesAdapte
class SearchViewHolder extends RecyclerView.ViewHolder { class SearchViewHolder extends RecyclerView.ViewHolder {
private String userLoginId; private Issues issue;
private final TextView issueNumber;
private final ImageView issueAssigneeAvatar; private final ImageView issueAssigneeAvatar;
private final TextView issueTitle; private final TextView issueTitle;
private final TextView issueCreatedTime; private final TextView issueCreatedTime;
private final TextView issueCommentsCount; private final TextView issueCommentsCount;
private final TextView repoFullName;
private SearchViewHolder(View itemView) { private SearchViewHolder(View itemView) {
super(itemView); super(itemView);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar); issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
issueTitle = itemView.findViewById(R.id.issueTitle); issueTitle = itemView.findViewById(R.id.issueTitle);
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount); issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime); issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
repoFullName = itemView.findViewById(R.id.repoFullName);
issueTitle.setOnClickListener(v -> { issueTitle.setOnClickListener(v -> {
Context context = v.getContext(); Context context = v.getContext();
Intent intent = new Intent(context, IssueDetailActivity.class); 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("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 repoOwner = parts[0];
final String repoName = parts[1]; final String repoName = parts[1];
@ -104,14 +100,13 @@ public class SearchIssuesAdapter extends RecyclerView.Adapter<SearchIssuesAdapte
context.startActivity(intent); context.startActivity(intent);
}); });
issueAssigneeAvatar.setOnClickListener(loginId -> { issueAssigneeAvatar.setOnClickListener(v -> {
Context context = v.getContext();
Context context = loginId.getContext(); String userLoginId = issue.getUser().getLogin();
AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId)); AppUtil.copyToClipboard(context, userLoginId, context.getString(R.string.copyLoginIdToClipBoard, userLoginId));
}); });
} }
} }
@NonNull @NonNull
@ -130,17 +125,19 @@ public class SearchIssuesAdapter extends RecyclerView.Adapter<SearchIssuesAdapte
String locale = tinyDb.getString("locale"); String locale = tinyDb.getString("locale");
String timeFormat = tinyDb.getString("dateFormat"); String timeFormat = tinyDb.getString("dateFormat");
holder.userLoginId = currentItem.getUser().getLogin(); PicassoService.getInstance(mCtx).get()
.load(currentItem.getUser().getAvatar_url())
PicassoService .placeholder(R.drawable.loader_animated)
.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); .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>"; 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.issueCommentsCount.setText(String.valueOf(currentItem.getComments()));
holder.repoFullName.setText(currentItem.getRepository().getFull_name());
switch(timeFormat) { switch(timeFormat) {
case "pretty": { case "pretty": {

View File

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

View File

@ -14,8 +14,8 @@ import org.acra.config.MailSenderConfigurationBuilder;
import org.acra.data.StringFormat; import org.acra.data.StringFormat;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.FontsOverride; import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.notifications.Notifications; import org.mian.gitnex.notifications.Notifications;
@ -28,7 +28,9 @@ import org.mian.gitnex.notifications.Notifications;
resTitle = R.string.crashTitle, resTitle = R.string.crashTitle,
resChannelName = R.string.setCrashReports, resChannelName = R.string.setCrashReports,
resText = R.string.crashMessage) 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 { public class MainApplication extends Application {
@ -81,6 +83,7 @@ public class MainApplication extends Application {
} }
Notifications.createChannels(appCtx);
Notifications.startWorker(appCtx); Notifications.startWorker(appCtx);
} }
@ -121,7 +124,7 @@ public class MainApplication extends Application {
// setting default polling delay // setting default polling delay
if(tinyDB.getInt("pollingDelayMinutes", 0) <= 0) { if(tinyDB.getInt("pollingDelayMinutes", 0) <= 0) {
tinyDB.putInt("pollingDelayMinutes", StaticGlobalVariables.defaultPollingDelay); tinyDB.putInt("pollingDelayMinutes", Constants.defaultPollingDelay);
} }
// disable biometric by default // 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.db.GitnexDatabase;
import org.mian.gitnex.database.models.Draft; import org.mian.gitnex.database.models.Draft;
import org.mian.gitnex.database.models.DraftWithRepository; import org.mian.gitnex.database.models.DraftWithRepository;
import org.mian.gitnex.helpers.StaticGlobalVariables; import org.mian.gitnex.helpers.Constants;
import java.util.List; import java.util.List;
/** /**
@ -51,7 +51,7 @@ public class DraftsApi {
} }
catch(InterruptedException e) { catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsApi, e.toString()); Log.e(Constants.draftsApi, e.toString());
} }
return draftId; return draftId;
@ -67,7 +67,7 @@ public class DraftsApi {
} }
catch(InterruptedException e) { catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsApi, e.toString()); Log.e(Constants.draftsApi, e.toString());
} }
return draftId; return draftId;
@ -83,7 +83,7 @@ public class DraftsApi {
} }
catch(InterruptedException e) { catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsApi, e.toString()); Log.e(Constants.draftsApi, e.toString());
} }
return checkDraftFlag; return checkDraftFlag;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,15 +11,12 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; 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.R;
import org.mian.gitnex.activities.FileViewActivity; import org.mian.gitnex.activities.FileViewActivity;
import org.mian.gitnex.activities.RepoDetailActivity; import org.mian.gitnex.activities.RepoDetailActivity;
@ -31,7 +28,6 @@ import org.mian.gitnex.helpers.Path;
import org.mian.gitnex.viewmodels.FilesViewModel; import org.mian.gitnex.viewmodels.FilesViewModel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import moe.feng.common.view.breadcrumbs.BreadcrumbsView;
import moe.feng.common.view.breadcrumbs.DefaultBreadcrumbsCallback; import moe.feng.common.view.breadcrumbs.DefaultBreadcrumbsCallback;
import moe.feng.common.view.breadcrumbs.model.BreadcrumbItem; 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 { public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapterListener {
private ProgressBar mProgressBar; private FragmentFilesBinding binding;
private RecyclerView mRecyclerView;
private TextView noDataFiles;
private LinearLayout filesFrame;
private static final String repoNameF = "param2"; private static final String repoNameF = "param2";
private static final String repoOwnerF = "param1"; private static final String repoOwnerF = "param1";
private static final String repoRefF = "param3"; private static final String repoRefF = "param3";
private BreadcrumbsView mBreadcrumbsView;
private String repoName; private String repoName;
private String repoOwner; private String repoOwner;
@ -92,28 +84,21 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 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); setHasOptionsMenu(true);
noDataFiles = fragmentFilesBinding.noDataFiles;
filesFrame = fragmentFilesBinding.filesFrame;
filesAdapter = new FilesAdapter(getContext(), this); filesAdapter = new FilesAdapter(getContext(), this);
mRecyclerView = fragmentFilesBinding.recyclerView; binding.recyclerView.setHasFixedSize(true);
mRecyclerView.setHasFixedSize(true); binding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); binding.recyclerView.setAdapter(filesAdapter);
mRecyclerView.setAdapter(filesAdapter);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL); DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(binding.recyclerView.getContext(), DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration); binding.recyclerView.addItemDecoration(dividerItemDecoration);
mProgressBar = fragmentFilesBinding.progressBar; binding.breadcrumbsView.setItems(new ArrayList<>(Collections.singletonList(BreadcrumbItem.createSimpleItem(getResources().getString(R.string.filesBreadcrumbRoot) + getResources().getString(R.string.colonDivider) + ref))));
mBreadcrumbsView = fragmentFilesBinding.breadcrumbsView;
mBreadcrumbsView.setItems(new ArrayList<>(Collections.singletonList(BreadcrumbItem.createSimpleItem(getResources().getString(R.string.filesBreadcrumbRoot) + getResources().getString(R.string.colonDivider) + ref))));
// noinspection unchecked // noinspection unchecked
mBreadcrumbsView.setCallback(new DefaultBreadcrumbsCallback<BreadcrumbItem>() { binding.breadcrumbsView.setCallback(new DefaultBreadcrumbsCallback<BreadcrumbItem>() {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@Override @Override
@ -140,14 +125,14 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
path.clear(); path.clear();
ref = repoBranch; 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, repoBranch);
}); });
fetchDataAsync(Authorization.get(getContext()), repoOwner, repoName, ref); fetchDataAsync(Authorization.get(getContext()), repoOwner, repoName, ref);
return fragmentFilesBinding.getRoot(); return binding.getRoot();
} }
@Override @Override
@ -157,40 +142,35 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
} }
@Override @Override
public void onClickDir(String dirName) { public void onClickFile(Files file) {
path.add(dirName); switch(file.getType()) {
mBreadcrumbsView.addItem(new BreadcrumbItem(Collections.singletonList(dirName)));
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 case "file":
public void onClickFile(String fileName) { 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) { private void fetchDataAsync(String instanceToken, String owner, String repo, String ref) {
mRecyclerView.setVisibility(View.GONE); binding.recyclerView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE); binding.progressBar.setVisibility(View.VISIBLE);
FilesViewModel filesModel = new ViewModelProvider(this).get(FilesViewModel.class); 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().clear();
filesAdapter.getOriginalFiles().addAll(filesListMain); filesAdapter.getOriginalFiles().addAll(filesListMain);
@ -198,16 +178,16 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
if(filesListMain.size() > 0) { if(filesListMain.size() > 0) {
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame); AppUtil.setMultiVisibility(View.VISIBLE, binding.recyclerView, binding.filesFrame);
noDataFiles.setVisibility(View.GONE); binding.noDataFiles.setVisibility(View.GONE);
} }
else { else {
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame, noDataFiles); AppUtil.setMultiVisibility(View.VISIBLE, binding.recyclerView, binding.filesFrame, binding.noDataFiles);
} }
filesFrame.setVisibility(View.VISIBLE); binding.filesFrame.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE); 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) { private void fetchDataAsyncSub(String instanceToken, String owner, String repo, String filesDir, String ref) {
mRecyclerView.setVisibility(View.GONE); binding.recyclerView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE); 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().clear();
filesAdapter.getOriginalFiles().addAll(filesListMain2); filesAdapter.getOriginalFiles().addAll(filesListMain2);
@ -228,15 +208,15 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
if(filesListMain2.size() > 0) { if(filesListMain2.size() > 0) {
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame); AppUtil.setMultiVisibility(View.VISIBLE, binding.recyclerView, binding.filesFrame);
noDataFiles.setVisibility(View.GONE); binding.noDataFiles.setVisibility(View.GONE);
} }
else { else {
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame, noDataFiles); AppUtil.setMultiVisibility(View.VISIBLE, binding.recyclerView, binding.filesFrame, binding.noDataFiles);
} }
filesFrame.setVisibility(View.VISIBLE); binding.filesFrame.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE); binding.progressBar.setVisibility(View.GONE);
}); });
@ -259,7 +239,7 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
@Override @Override
public boolean onQueryTextChange(String newText) { public boolean onQueryTextChange(String newText) {
if(mRecyclerView.getAdapter() != null) { if(binding.recyclerView.getAdapter() != null) {
filesAdapter.getFilter().filter(newText); 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.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentIssuesBinding; import org.mian.gitnex.databinding.FragmentIssuesBinding;
import org.mian.gitnex.helpers.Authorization; 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.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
@ -49,12 +49,12 @@ public class IssuesFragment extends Fragment {
private List<Issues> issuesList; private List<Issues> issuesList;
private IssuesAdapter adapter; private IssuesAdapter adapter;
private Context context; private Context context;
private int pageSize = StaticGlobalVariables.issuesPageInit; private int pageSize = Constants.issuesPageInit;
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
private String TAG = StaticGlobalVariables.tagIssuesList; private String TAG = Constants.tagIssuesList;
private TextView noDataIssues; private TextView noDataIssues;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private String requestType = StaticGlobalVariables.issuesRequestType; private String requestType = Constants.issuesRequestType;
private ProgressBar progressLoadMore; private ProgressBar progressLoadMore;
@Nullable @Nullable
@ -78,7 +78,7 @@ public class IssuesFragment extends Fragment {
// if gitea is 1.12 or higher use the new limit // if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) { if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances; resultLimit = Constants.resultLimitNewGiteaInstances;
} }
recyclerView = fragmentIssuesBinding.recyclerView; 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.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentMilestonesBinding; import org.mian.gitnex.databinding.FragmentMilestonesBinding;
import org.mian.gitnex.helpers.Authorization; 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.TinyDB;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import java.util.ArrayList; import java.util.ArrayList;
@ -44,9 +44,9 @@ public class MilestonesFragment extends Fragment {
private List<Milestones> dataList; private List<Milestones> dataList;
private MilestonesAdapter adapter; private MilestonesAdapter adapter;
private Context ctx; private Context ctx;
private int pageSize = StaticGlobalVariables.milestonesPageInit; private int pageSize = Constants.milestonesPageInit;
private String TAG = StaticGlobalVariables.tagMilestonesFragment; private String TAG = Constants.tagMilestonesFragment;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 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 gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) { if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances; resultLimit = Constants.resultLimitNewGiteaInstances;
} }
dataList = new ArrayList<>(); 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.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentNotificationsBinding; import org.mian.gitnex.databinding.FragmentNotificationsBinding;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.InfiniteScrollListener; import org.mian.gitnex.helpers.InfiniteScrollListener;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import java.io.IOException; import java.io.IOException;
@ -83,7 +83,7 @@ public class NotificationsFragment extends Fragment implements NotificationsAdap
context = getContext(); context = getContext();
tinyDB = TinyDB.getInstance(context); tinyDB = TinyDB.getInstance(context);
pageResultLimit = StaticGlobalVariables.getCurrentResultLimit(context); pageResultLimit = Constants.getCurrentResultLimit(context);
tinyDB.putString("notificationsFilterState", currentFilterMode); tinyDB.putString("notificationsFilterState", currentFilterMode);
markAllAsRead = fragmentNotificationsBinding.markAllAsRead; markAllAsRead = fragmentNotificationsBinding.markAllAsRead;
@ -204,7 +204,7 @@ public class NotificationsFragment extends Fragment implements NotificationsAdap
Call<List<NotificationThread>> call = RetrofitClient Call<List<NotificationThread>> call = RetrofitClient
.getApiInterface(context) .getApiInterface(context)
.getNotificationThreads(instanceToken, false, filter, .getNotificationThreads(instanceToken, false, filter,
StaticGlobalVariables.defaultOldestTimestamp, "", Constants.defaultOldestTimestamp, "",
pageCurrentIndex, pageResultLimit); pageCurrentIndex, pageResultLimit);
call.enqueue(new Callback<List<NotificationThread>>() { 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.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import java.util.Locale; import java.util.Locale;
import eightbitlab.com.blurview.BlurView; import jp.wasabeef.picasso.transformations.BlurTransformation;
import eightbitlab.com.blurview.RenderScriptBlur;
/** /**
* Author M M Arif * Author M M Arif
@ -54,7 +53,6 @@ public class ProfileFragment extends Fragment {
TinyDB tinyDb = TinyDB.getInstance(getContext()); TinyDB tinyDb = TinyDB.getInstance(getContext());
BlurView blurView = v.findViewById(R.id.blurView);
TextView userFullName = v.findViewById(R.id.userFullName); TextView userFullName = v.findViewById(R.id.userFullName);
ImageView userAvatarBackground = v.findViewById(R.id.userAvatarBackground); ImageView userAvatarBackground = v.findViewById(R.id.userAvatarBackground);
ImageView userAvatar = v.findViewById(R.id.userAvatar); ImageView userAvatar = v.findViewById(R.id.userAvatar);
@ -77,10 +75,10 @@ public class ProfileFragment extends Fragment {
userLanguage.setText(R.string.notSupported); userLanguage.setText(R.string.notSupported);
} }
userAvatar.setOnClickListener(loginId -> { userAvatar.setOnClickListener(loginId ->
AppUtil.copyToClipboard(ctx,
AppUtil.copyToClipboard(ctx, tinyDb.getString("userLogin"), ctx.getString(R.string.copyLoginIdToClipBoard, tinyDb.getString("userLogin"))); tinyDb.getString("userLogin"),
}); ctx.getString(R.string.copyLoginIdToClipBoard, tinyDb.getString("userLogin"))));
userFullName.setText(Html.fromHtml(tinyDb.getString("userFullname"))); userFullName.setText(Html.fromHtml(tinyDb.getString("userFullname")));
userLogin.setText(getString(R.string.usernameWithAt, tinyDb.getString("userLogin"))); userLogin.setText(getString(R.string.usernameWithAt, tinyDb.getString("userLogin")));
@ -94,12 +92,12 @@ public class ProfileFragment extends Fragment {
PicassoService.getInstance(ctx).get() PicassoService.getInstance(ctx).get()
.load(tinyDb.getString("userAvatar")) .load(tinyDb.getString("userAvatar"))
.transform(new BlurTransformation(ctx))
.into(userAvatarBackground, new Callback() { .into(userAvatarBackground, new Callback() {
@Override @Override
public void onSuccess() { public void onSuccess() {
int invertedColor = new ColorInverter().getImageViewContrastColor(userAvatar);
int invertedColor = new ColorInverter().getImageViewContrastColor(userAvatarBackground);
userFullName.setTextColor(invertedColor); userFullName.setTextColor(invertedColor);
divider.setBackgroundColor(invertedColor); divider.setBackgroundColor(invertedColor);
@ -107,20 +105,11 @@ public class ProfileFragment extends Fragment {
userLanguage.setTextColor(invertedColor); userLanguage.setTextColor(invertedColor);
ImageViewCompat.setImageTintList(userLanguageIcon, ColorStateList.valueOf(invertedColor)); ImageViewCompat.setImageTintList(userLanguageIcon, ColorStateList.valueOf(invertedColor));
blurView.setupWith(aboutFrame)
.setBlurAlgorithm(new RenderScriptBlur(ctx))
.setBlurRadius(3)
.setHasFixedTransformationMatrix(true);
} }
@Override @Override public void onError(Exception e) {}
public void onError(Exception e) {}
}); });
ProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager()); ProfileFragment.SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
ViewPager mViewPager = v.findViewById(R.id.container); ViewPager mViewPager = v.findViewById(R.id.container);
@ -181,8 +170,6 @@ public class ProfileFragment extends Fragment {
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) { switch (position) {
case 0: // followers 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.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentPullRequestsBinding; import org.mian.gitnex.databinding.FragmentPullRequestsBinding;
import org.mian.gitnex.helpers.Authorization; 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.TinyDB;
import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
@ -49,11 +49,11 @@ public class PullRequestsFragment extends Fragment {
private RecyclerView recyclerView; private RecyclerView recyclerView;
private List<PullRequests> prList; private List<PullRequests> prList;
private PullRequestsAdapter adapter; private PullRequestsAdapter adapter;
private String TAG = StaticGlobalVariables.tagPullRequestsList; private String TAG = Constants.tagPullRequestsList;
private Context context; private Context context;
private int pageSize = StaticGlobalVariables.prPageInit; private int pageSize = Constants.prPageInit;
private TextView noData; private TextView noData;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances; private int resultLimit = Constants.resultLimitOldGiteaInstances;
private ProgressBar progressLoadMore; private ProgressBar progressLoadMore;
@Nullable @Nullable
@ -77,7 +77,7 @@ public class PullRequestsFragment extends Fragment {
// if gitea is 1.12 or higher use the new limit // if gitea is 1.12 or higher use the new limit
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) { if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances; resultLimit = Constants.resultLimitNewGiteaInstances;
} }
recyclerView = fragmentPullRequestsBinding.recyclerView; recyclerView = fragmentPullRequestsBinding.recyclerView;

View File

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

View File

@ -13,15 +13,16 @@ import android.util.TypedValue;
import android.view.View; import android.view.View;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.core.content.pm.PackageInfoCompat; 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.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
@ -31,31 +32,38 @@ import java.util.Objects;
public class AppUtil { 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. // AppUtil should not be instantiated.
private AppUtil() {} private AppUtil() {}
static { static {
extensions.put(Arrays.asList("jpg", "jpeg", "gif", "png", "ico"), FileType.IMAGE); extensions.put(new String[]{"jpg", "jpeg", "gif", "png", "ico", "tif", "tiff", "bmp"}, 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(new String[]{"mp3", "wav", "opus", "flac", "wma", "aac", "m4a", "oga", "mpc", "ogg"}, FileType.AUDIO);
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[]{"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) { 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)) { if(testExtension.equalsIgnoreCase(extension))
return extensions.get(testExtensions);
return extensions.get(e); }
} }
} }
return FileType.UNKNOWN; return FileType.UNKNOWN;
} }
public static boolean hasNetworkConnection(Context context) { public static boolean hasNetworkConnection(Context context) {
@ -63,6 +71,45 @@ public class AppUtil {
return NetworkStatusObserver.getInstance(context).hasNetworkConnection(); 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) { public static int getAppBuildNo(Context context) {
try { try {

View File

@ -23,4 +23,12 @@ public class Authorization {
return "token " + tinyDb.getString(loginUid + "-token"); 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.graphics.drawable.BitmapDrawable;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
/** /**
* Author M M Arif * 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; double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
int d; int d = (a < 0.30) ?
if (a < 0.5) { 30 : // almost black
d = 30; // almost black 255; // white
} else {
d = 255; // white
}
return Color.rgb(d, d, d); return Color.rgb(d, d, d);
} }
@ColorInt @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; colorSum += bitmap.getPixel(width, height);
int divisionValue = 0; divisionValue++;
for(int height=0; height<bitmap.getHeight(); height += 10) {
for(int width=0; width<bitmap.getWidth(); width += 10) {
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 // parse "-1,2 +2,3" and "-1 -3" and so on
int oldStart = 0, newStart = 0; int oldStart = 0, newStart = 0;
String diffPos[] = statsLine.split(" \\+"); String[] diffPos = statsLine.split(" \\+");
if(diffPos.length == 2) { if(diffPos.length == 2) {
oldStart = Integer.parseInt(diffPos[0].split(",")[0]); oldStart = Integer.parseInt(diffPos[0].split(",")[0]);
newStart = Integer.parseInt(diffPos[1].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.view.View;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import org.mian.gitnex.helpers.highlightjs.models.Language; import org.mian.gitnex.helpers.highlightjs.models.Language;
import org.mian.gitnex.helpers.highlightjs.models.Theme; import org.mian.gitnex.helpers.highlightjs.models.Theme;
import org.mian.gitnex.helpers.highlightjs.utils.SourceUtils; import org.mian.gitnex.helpers.highlightjs.utils.SourceUtils;
@ -25,6 +24,8 @@ public class HighlightJsView extends WebView {
private boolean showLineNumbers = true; private boolean showLineNumbers = true;
private TextWrap textWrap = TextWrap.NO_WRAP; private TextWrap textWrap = TextWrap.NO_WRAP;
private String source = "";
public HighlightJsView(Context context) { public HighlightJsView(Context context) {
super(context); super(context);
@ -63,11 +64,15 @@ public class HighlightJsView extends WebView {
getSettings().setSupportZoom(enable); 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); loadDataWithBaseURL("file:///android_asset/", html_content, "text/html", "utf-8", null);
} }
@ -109,4 +114,4 @@ public class HighlightJsView extends WebView {
NO_WRAP, WORD_WRAP, BREAK_ALL NO_WRAP, WORD_WRAP, BREAK_ALL
} }
} }

View File

@ -1,13 +1,17 @@
package org.mian.gitnex.notifications; package org.mian.gitnex.notifications;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.os.Build; import android.os.Build;
import androidx.work.Constraints; import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy; import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.NetworkType; import androidx.work.NetworkType;
import androidx.work.PeriodicWorkRequest; import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager; 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.TinyDB;
import org.mian.gitnex.helpers.Version; import org.mian.gitnex.helpers.Version;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -20,13 +24,52 @@ public class Notifications {
private static int notificationsSupported = -1; 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); 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) PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(NotificationsWorker.class, pollingDelayMinutes, TimeUnit.MINUTES)
.setConstraints(constraints.build()) .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; package org.mian.gitnex.notifications;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.os.Build;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
@ -20,7 +16,8 @@ import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity; import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AppUtil; 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 org.mian.gitnex.helpers.TinyDB;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -34,7 +31,6 @@ import retrofit2.Response;
public class NotificationsWorker extends Worker { public class NotificationsWorker extends Worker {
private static final int MAXIMUM_NOTIFICATIONS = 100; private static final int MAXIMUM_NOTIFICATIONS = 100;
private static final long[] VIBRATION_PATTERN = new long[]{ 1000, 1000 };
private final Context context; private final Context context;
private final TinyDB tinyDB; private final TinyDB tinyDB;
@ -45,17 +41,16 @@ public class NotificationsWorker extends Worker {
this.context = context; this.context = context;
this.tinyDB = TinyDB.getInstance(context); this.tinyDB = TinyDB.getInstance(context);
} }
@NonNull @NonNull
@Override @Override
public Result doWork() { 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(); long startPollingTime = System.currentTimeMillis();
@ -65,7 +60,7 @@ public class NotificationsWorker extends Worker {
Call<List<NotificationThread>> call = RetrofitClient Call<List<NotificationThread>> call = RetrofitClient
.getApiInterface(context) .getApiInterface(context)
.getNotificationThreads(token, false, new String[]{"unread"}, previousRefreshTimestamp, .getNotificationThreads(Authorization.get(context), false, new String[]{"unread"}, previousRefreshTimestamp,
null, 1, MAXIMUM_NOTIFICATIONS); null, 1, MAXIMUM_NOTIFICATIONS);
Response<List<NotificationThread>> response = call.execute(); Response<List<NotificationThread>> response = call.execute();
@ -76,34 +71,24 @@ public class NotificationsWorker extends Worker {
List<NotificationThread> notificationThreads = response.body(); List<NotificationThread> notificationThreads = response.body();
if(!notificationThreads.isEmpty()) { if(!notificationThreads.isEmpty())
sendNotification(notificationThreads); sendNotification(notificationThreads);
}
tinyDB.putString("previousRefreshTimestamp", AppUtil.getTimestampFromDate(context, new Date())); tinyDB.putString("previousRefreshTimestamp", AppUtil.getTimestampFromDate(context, new Date()));
} }
else {
Log.e("onError", String.valueOf(response.code())); } catch(Exception ignored) {}
}
}
catch(Exception e) {
Log.e("onError", e.toString());
}
try { try {
if(notificationLoops > 1 && i < (notificationLoops - 1)) { if(notificationLoops > 1 && i < (notificationLoops - 1)) {
Thread.sleep(60000 - (System.currentTimeMillis() - startPollingTime)); Thread.sleep(60000 - (System.currentTimeMillis() - startPollingTime));
} }
} } catch (InterruptedException ignored) {}
catch (InterruptedException ignored) {}
} }
return Result.success(); return Result.success();
} }
private void sendNotification(List<NotificationThread> notificationThreads) { private void sendNotification(List<NotificationThread> notificationThreads) {
@ -112,7 +97,6 @@ public class NotificationsWorker extends Worker {
PendingIntent pendingIntent = getPendingIntent(); PendingIntent pendingIntent = getPendingIntent();
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context); NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
attachNotificationChannel(notificationManagerCompat);
Notification summaryNotification = new NotificationCompat.Builder(context, context.getPackageName()) Notification summaryNotification = new NotificationCompat.Builder(context, context.getPackageName())
.setContentTitle(context.getString(R.string.newMessages)) .setContentTitle(context.getString(R.string.newMessages))
@ -122,15 +106,13 @@ public class NotificationsWorker extends Worker {
.setGroupSummary(true) .setGroupSummary(true)
.setAutoCancel(true) .setAutoCancel(true)
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setChannelId(Constants.mainNotificationChannelId)
.build(); .build();
notificationManagerCompat.notify(summaryId, summaryNotification); notificationManagerCompat.notify(summaryId, summaryNotification);
for(NotificationThread notificationThread : notificationThreads) { for(NotificationThread notificationThread : notificationThreads) {
NotificationManagerCompat notificationManagerCompat1 = NotificationManagerCompat.from(context);
attachNotificationChannel(notificationManagerCompat1);
String subjectUrl = notificationThread.getSubject().getUrl(); String subjectUrl = notificationThread.getSubject().getUrl();
String issueId = context.getResources().getString(R.string.hash) + subjectUrl.substring(subjectUrl.lastIndexOf("/") + 1); 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()); 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()) .setGroup(context.getPackageName())
.setContentIntent(pendingIntent); .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)) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setCategory(NotificationCompat.CATEGORY_MESSAGE) .setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setPriority(NotificationCompat.PRIORITY_DEFAULT) .setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setChannelId(Constants.mainNotificationChannelId)
.setAutoCancel(true); .setAutoCancel(true);
if(tinyDB.getBoolean("notificationsEnableLights", true)) { if(tinyDB.getBoolean("notificationsEnableLights", true)) {
@ -201,11 +143,8 @@ public class NotificationsWorker extends Worker {
} }
if(tinyDB.getBoolean("notificationsEnableVibration", true)) { if(tinyDB.getBoolean("notificationsEnableVibration", true)) {
builder.setVibrate(new long[]{ 1000, 1000 });
builder.setVibrate(VIBRATION_PATTERN); } else {
}
else {
builder.setVibrate(null); builder.setVibrate(null);
} }
@ -219,5 +158,6 @@ public class NotificationsWorker extends Worker {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return PendingIntent.getActivity(context, 0, intent, 0); 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.clients.RetrofitClient;
import org.mian.gitnex.helpers.AppUtil; import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization; import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB; import org.mian.gitnex.helpers.TinyDB;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -222,7 +223,7 @@ public class ReactionSpinner extends HorizontalScrollView {
if(response.isSuccessful() && response.body() != null) { if(response.isSuccessful() && response.body() != null) {
allowedReactions.addAll(Arrays.asList(response.body().getAllowed_reactions())); allowedReactions.addAll(Arrays.asList(response.body().getAllowed_reactions()));
} else { } else {
allowedReactions.addAll(Arrays.asList("+1", "-1", "laugh", "hooray", "confused", "heart", "rocket", "eyes")); allowedReactions.addAll(Arrays.asList(Constants.fallbackReactions));
} }
return allowedReactions; return allowedReactions;

View File

@ -4,10 +4,7 @@
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <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:fillColor="?attr/iconsColor"
android:strokeLineJoin="round" 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:strokeWidth="2" android:fillType="evenOdd"/>
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector> </vector>

View File

@ -4,17 +4,7 @@
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path
android:pathData="M13,2H6a2,2 0,0 0,-2 2v16a2,2 0,0 0,2 2h12a2,2 0,0 0,2 -2V9z" android:fillColor="?attr/iconsColor"
android:strokeLineJoin="round" 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:strokeWidth="2" android:fillType="evenOdd"/>
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"/>
</vector> </vector>

View File

@ -4,24 +4,10 @@
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path
android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0" android:fillColor="?attr/iconsColor"
android:strokeLineJoin="round" 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"/>
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path <path
android:pathData="M9.09,9a3,3 0,0 1,5.83 1c0,2 -3,3 -3,3" android:fillColor="?attr/iconsColor"
android:strokeLineJoin="round" 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:strokeWidth="2" android:fillType="evenOdd"/>
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"/>
</vector> </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"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:id="@+id/singleFileContentsFrame" android:id="@+id/markdownFrame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor" android:background="?attr/primaryBackgroundColor"
android:orientation="vertical"
android:padding="16dp" android:padding="16dp"
android:orientation="vertical"> android:visibility="gone">
<TextView <TextView
android:id="@+id/singleFileContents" android:id="@+id/markdown"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="14sp" android:textIsSelectable="true"
android:textIsSelectable="true" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@ -86,7 +87,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor" android:background="?attr/primaryBackgroundColor"
android:orientation="vertical"> android:orientation="vertical"
android:visibility="gone">
<com.github.barteksc.pdfviewer.PDFView <com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfView" android:id="@+id/pdfView"
@ -97,14 +99,14 @@
</LinearLayout> </LinearLayout>
<org.mian.gitnex.helpers.highlightjs.HighlightJsView <org.mian.gitnex.helpers.highlightjs.HighlightJsView
android:id="@+id/singleCodeContents" android:id="@+id/contents"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="14sp" android:textSize="14sp"
android:visibility="gone" /> android:visibility="gone" />
<com.github.chrisbanes.photoview.PhotoView <com.github.chrisbanes.photoview.PhotoView
android:id="@+id/imageView" android:id="@+id/photo_view"
android:visibility="gone" android:visibility="gone"
android:padding="16dp" android:padding="16dp"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

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

View File

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

View File

@ -21,80 +21,72 @@
android:contentDescription="@string/generalImgContentText" android:contentDescription="@string/generalImgContentText"
android:scaleType="centerCrop" /> android:scaleType="centerCrop" />
<eightbitlab.com.blurview.BlurView <LinearLayout
android:id="@+id/blurView" android:id="@+id/layoutFrameAccount"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="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 <LinearLayout
android:id="@+id/layoutFrameAccount" android:layout_width="wrap_content"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="match_parent" android:gravity="center_vertical">
android:gravity="center"
android:orientation="vertical"
android:padding="16dp">
<ImageView <ImageView
android:id="@+id/userAvatar" android:id="@+id/userLanguageIcon"
android:layout_width="54dp" android:layout_width="wrap_content"
android:layout_height="54dp" android:layout_height="18dp"
android:layout_marginBottom="8dp" android:layout_marginEnd="2dp"
android:contentDescription="@string/generalImgContentText" android:contentDescription="@string/generalImgContentText"
android:src="@mipmap/app_logo_round" /> android:src="@drawable/ic_language"
app:tint="@color/colorWhite" />
<TextView <TextView
android:id="@+id/userFullName" android:id="@+id/userLanguage"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/colorWhite" android:textColor="@color/colorWhite"
android:textIsSelectable="true" 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" /> 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> </LinearLayout>
</eightbitlab.com.blurview.BlurView> </LinearLayout>
</RelativeLayout> </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:id="@+id/relativeLayoutFrameIssuesList"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_margin="15dp"
android:orientation="vertical"
android:background="?attr/primaryBackgroundColor"> android:background="?attr/primaryBackgroundColor">
<TextView <ImageView
android:id="@+id/issueNumber" android:id="@+id/assigneeAvatar"
android:layout_width="wrap_content" android:layout_width="48dp"
android:layout_height="wrap_content" android:layout_height="48dp"
android:visibility="invisible" /> android:layout_marginEnd="15dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_android" />
<TextView <LinearLayout
android:id="@+id/repoFullName" android:id="@+id/infoSection"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible" />
<RelativeLayout
android:id="@+id/mainFrame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:layout_toEndOf="@+id/assigneeAvatar"
android:layout_margin="15dp"
android:orientation="vertical"> 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 <LinearLayout
android:id="@+id/infoSection" android:id="@+id/frameIssueNameStatus"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toEndOf="@+id/assigneeAvatar" android:layout_marginBottom="10dp"
android:orientation="vertical"> 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 <LinearLayout
android:id="@+id/frameIssueNameStatus" android:id="@+id/frameCommentsCount"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_weight=".25"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/issueTitle" android:id="@+id/issueCommentsCount"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="top|center_vertical" android:gravity="start"
android:textAlignment="gravity" android:drawablePadding="5dp"
android:text="@string/strFilter" app:drawableStartCompat="@drawable/ic_comment"
android:textColor="?attr/primaryTextColor" android:layout_gravity="center_horizontal"
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:textColor="?attr/primaryTextColor" android:textColor="?attr/primaryTextColor"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </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> </LinearLayout>
</RelativeLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -5,119 +5,82 @@
android:id="@+id/relativeLayoutFrame" android:id="@+id/relativeLayoutFrame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_margin="15dp"
android:orientation="vertical"
android:background="?attr/primaryBackgroundColor"> android:background="?attr/primaryBackgroundColor">
<TextView <ImageView
android:id="@+id/prNumber" android:id="@+id/assigneeAvatar"
android:layout_width="wrap_content" android:layout_width="48dp"
android:layout_height="wrap_content" android:layout_height="48dp"
android:visibility="invisible"/> android:layout_marginEnd="15dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_android" />
<TextView <LinearLayout
android:id="@+id/prMergeable" android:id="@+id/infoSection"
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"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:layout_toEndOf="@+id/assigneeAvatar"
android:layout_margin="15dp"
android:orientation="vertical"> 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 <LinearLayout
android:id="@+id/infoSection" android:id="@+id/framePrNameStatus"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toEndOf="@+id/assigneeAvatar" android:layout_marginBottom="10dp"
android:orientation="vertical"> android:orientation="horizontal">
<LinearLayout <TextView
android:id="@+id/framePrNameStatus" android:id="@+id/prTitle"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="10dp" android:gravity="top|center_vertical"
android:orientation="horizontal"> android:textAlignment="gravity"
android:textColor="?attr/primaryTextColor"
<TextView android:textSize="18sp" />
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>
</LinearLayout> </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> </RelativeLayout>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/navHeaderFrame" android:id="@+id/navHeaderFrame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp"> android:layout_height="200dp">
@ -10,106 +11,79 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/generalImgContentText" android:contentDescription="@string/generalImgContentText"
android:scaleType="centerCrop" /> android:scaleType="centerCrop"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<eightbitlab.com.blurview.BlurView <LinearLayout
android:id="@+id/blurView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="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 <LinearLayout
android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:gravity="bottom" android:orientation="horizontal">
android:paddingTop="16dp">
<LinearLayout <ImageView
android:layout_width="match_parent" android:id="@+id/userAvatar"
android:layout_height="wrap_content" android:layout_width="60dp"
android:orientation="horizontal"> android:layout_height="60dp"
android:contentDescription="@string/generalImgContentText"
<ImageView tools:srcCompat="@tools:sample/avatars" />
android:id="@+id/userAvatar"
android:layout_width="wrap_content" <androidx.recyclerview.widget.RecyclerView
android:layout_height="wrap_content" android:id="@+id/navRecyclerViewUserAccounts"
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
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_marginTop="5dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:baselineAligned="false"> app:reverseLayout="true" />
<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" />
</LinearLayout> </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> </RelativeLayout>

View File

@ -578,7 +578,7 @@
<string name="downloadFile">Download This File</string> <string name="downloadFile">Download This File</string>
<string name="waitLoadingDownloadFile">Please wait for the file to load to memory</string> <string name="waitLoadingDownloadFile">Please wait for the file to load to memory</string>
<string name="downloadFileSaved">File saved successfully</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="deleteFile">Delete This File</string>
<string name="editFile">Edit This File</string> <string name="editFile">Edit This File</string>
<string name="deleteFileText">Delete %1$s</string> <string name="deleteFileText">Delete %1$s</string>
@ -674,7 +674,8 @@
<string name="chooseColorSelectorHeader">Choose Color</string> <string name="chooseColorSelectorHeader">Choose Color</string>
<string name="newMessages">New messages</string> <string name="newMessages">New messages</string>
<string name="youHaveGotNewNotifications">You\'ve got %d new notifications.</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="notificationExtraInfo" translatable="false">- %s (%s)</string>
<string name="isRead">Read</string> <string name="isRead">Read</string>
@ -742,4 +743,15 @@
<string name="copyLoginIdToClipBoard">Login ID \'%s\' copied to clipboard</string> <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> </resources>

View File

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