diff --git a/.drone.yml b/.drone.yml
index 7bbce823..c3b82520 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -66,7 +66,7 @@ steps:
- name: build
image: nextcloudci/android:android-49
commands:
- - ./gradlew build
+ - ./gradlew assembleFreeRelease
- name: sign
image: nextcloudci/android:android-49
@@ -78,7 +78,7 @@ steps:
KEY_PASS:
from_secret: KEY_PASS
OUTPUT: signed.apk
- GITEA: https://gitea.com
+ INSTANCE: https://codeberg.org
KS_FILE: ci_keystore.jks
KS_REPO:
from_secret: KS_REPO
diff --git a/.gitignore b/.gitignore
index bdebb1e1..93cf4a2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,9 @@
# Release dir
app/release/*
+# Pro dir
+app/pro/*
+
# Files for the ART/Dalvik VM
*.dex
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 87f8685d..53608c4d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -20,7 +20,7 @@ build:
- master
- tags
script:
- - ./gradlew build
+ - ./gradlew assembleFreeRelease
artifacts:
paths:
- app/build/outputs/
@@ -34,7 +34,7 @@ sign:
- tags
variables:
OUTPUT: "signed.apk"
- GITEA: "https://gitea.com"
+ INSTANCE: "https://codeberg.org"
KS_FILE: "ci_keystore.jks"
script:
- ./scripts/sign-build.sh
@@ -48,6 +48,7 @@ latest:
stage: publish
only:
- master
+ - tags
variables:
WEBDAV_USERNAME: "GitNexBot"
PLUGIN_FILE: "signed.apk"
diff --git a/README.md b/README.md
index 535fb875..f9f3f54f 100644
--- a/README.md
+++ b/README.md
@@ -4,13 +4,13 @@
# GitNex - Android client for Gitea
-GitNex is a free, open-source Android client for Git repository management tool Gitea. Gitea is a community managed fork of Gogs, lightweight code hosting solution written in Go.
+GitNex is a free/paid, open-source Android client for Git repository management tool Gitea. Gitea is a community managed fork of Gogs, lightweight code hosting solution written in Go.
GitNex is licensed under GPLv3 License. See the LICENSE file for the full license text. No trackers are used and source code is available here for anyone to audit.
## Downloads
[
](https://f-droid.org/en/packages/org.mian.gitnex/)
-[
](https://play.google.com/store/apps/details?id=org.mian.gitnex)
+[
](https://play.google.com/store/apps/details?id=org.mian.gitnex.pro)
[
](https://cloud.swatian.com/s/DN7E5xxtaw4fRbE)
## Note about Gitea version
@@ -21,11 +21,10 @@ Check the versions [compatibility page](https://codeberg.org/gitnex/GitNex/wiki/
## Build from source
Option 1 - Download the source code, open it in Android Studio and build it there.
-Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew build`.
+Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew assembleFree`.
## Features
- Multiple accounts support
-- Repositories / issues/ org list
- File and directory browser
- File viewer
- Create files
@@ -34,6 +33,7 @@ Option 2 - Open terminal(Linux) and cd to the project dir. Run `./gradlew build`
- Files diff for PRs
- Notifications
- Drafts
+- Repositories / issues / org list
- [MANY MORE](https://codeberg.org/gitnex/GitNex/wiki/Features)
## Contributing
diff --git a/app/build.gradle b/app/build.gradle
index 24fca5fa..76a1495e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,15 +1,28 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 29
+ compileSdkVersion 30
defaultConfig {
applicationId "org.mian.gitnex"
minSdkVersion 21
- targetSdkVersion 29
- versionCode 317
- versionName "3.2.0-dev"
+ targetSdkVersion 30
+ versionCode 320
+ versionName "3.2.0"
+ multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
+ dexOptions {
+ javaMaxHeapSize "4g"
+ }
+ flavorDimensions "default"
+ productFlavors {
+ free {
+ applicationId "org.mian.gitnex"
+ }
+ pro {
+ applicationId "org.mian.gitnex.pro"
+ }
+ }
buildFeatures {
viewBinding = true
}
@@ -40,7 +53,7 @@ configurations {
dependencies {
def lifecycle_version = '2.3.0-alpha07'
- def markwon_version = '4.5.1'
+ def markwon_version = '4.6.0'
def work_version = "2.4.0"
def acra = "5.5.0"
@@ -54,14 +67,14 @@ dependencies {
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation "com.github.vihtarb:tooltip:0.2.0"
- implementation 'com.squareup.okhttp3:okhttp:4.8.1'
+ implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation "com.google.code.gson:gson:2.8.6"
implementation "com.squareup.picasso:picasso:2.71828"
implementation "com.amulyakhare:com.amulyakhare.textdrawable:1.0.1"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
- implementation 'com.squareup.okhttp3:logging-interceptor:4.8.1'
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
implementation 'org.ocpsoft.prettytime:prettytime:4.0.5.Final'
implementation "com.vdurmont:emoji-java:5.1.1"
implementation "com.pes.materialcolorpicker:library:1.2.5"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index da640a82..d7a57f36 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -85,6 +85,7 @@
+
diff --git a/app/src/main/app_logo-playstore.png b/app/src/main/app_logo-playstore.png
new file mode 100644
index 00000000..f78fac3d
Binary files /dev/null and b/app/src/main/app_logo-playstore.png differ
diff --git a/app/src/main/app_logo-web.png b/app/src/main/app_logo-web.png
deleted file mode 100644
index 68a598c8..00000000
Binary files a/app/src/main/app_logo-web.png and /dev/null differ
diff --git a/app/src/main/java/org/mian/gitnex/activities/AddNewAccountActivity.java b/app/src/main/java/org/mian/gitnex/activities/AddNewAccountActivity.java
index 6f757200..cc89cb43 100644
--- a/app/src/main/java/org/mian/gitnex/activities/AddNewAccountActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/AddNewAccountActivity.java
@@ -114,10 +114,7 @@ public class AddNewAccountActivity extends BaseActivity {
URI rawInstanceUrl = UrlBuilder.fromString(UrlHelper.fixScheme(instanceUrlET, "http")).toUri();
- URI instanceUrlWithProtocol = UrlBuilder.fromUri(rawInstanceUrl).withPath(PathsHelper.join(rawInstanceUrl.getPath()))
- .withScheme(protocol.toLowerCase()).toUri();
-
- URI instanceUrl = UrlBuilder.fromUri(instanceUrlWithProtocol).withPath(PathsHelper.join(instanceUrlWithProtocol.getPath(), "/api/v1/"))
+ URI instanceUrl = UrlBuilder.fromUri(rawInstanceUrl).withScheme(protocol.toLowerCase()).withPath(PathsHelper.join(rawInstanceUrl.getPath(), "/api/v1/"))
.toUri();
versionCheck(instanceUrl.toString(), loginToken);
diff --git a/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java b/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java
index 4c2a0939..e6f4c608 100644
--- a/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java
@@ -136,11 +136,6 @@ public abstract class BaseActivity extends AppCompatActivity {
tinyDb.putString("draftsCommentsDeletionEnabledInit", "yes");
}
- if(!tinyDb.getString("instanceUrlWithProtocol").endsWith("/")) {
-
- tinyDb.putString("instanceUrlWithProtocol", tinyDb.getString("instanceUrlWithProtocol") + "/");
- }
-
if (tinyDb.getBoolean("crashReportingEnabled")) {
CoreConfigurationBuilder ACRABuilder = new CoreConfigurationBuilder(this);
diff --git a/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java b/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java
new file mode 100644
index 00000000..e066deb5
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java
@@ -0,0 +1,431 @@
+package org.mian.gitnex.activities;
+
+import android.app.DatePickerDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import androidx.annotation.NonNull;
+import org.mian.gitnex.R;
+import org.mian.gitnex.adapters.LabelsListAdapter;
+import org.mian.gitnex.clients.RetrofitClient;
+import org.mian.gitnex.databinding.ActivityCreatePrBinding;
+import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
+import org.mian.gitnex.helpers.AppUtil;
+import org.mian.gitnex.helpers.Authorization;
+import org.mian.gitnex.helpers.StaticGlobalVariables;
+import org.mian.gitnex.helpers.TinyDB;
+import org.mian.gitnex.helpers.Toasty;
+import org.mian.gitnex.helpers.Version;
+import org.mian.gitnex.models.Branches;
+import org.mian.gitnex.models.CreatePullRequest;
+import org.mian.gitnex.models.Labels;
+import org.mian.gitnex.models.Milestones;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+
+/**
+ * Author M M Arif
+ */
+
+public class CreatePullRequestActivity extends BaseActivity implements LabelsListAdapter.LabelsListAdapterListener {
+
+ private View.OnClickListener onClickListener;
+ private Context ctx = this;
+ private Context appCtx;
+ private TinyDB tinyDb;
+ private ActivityCreatePrBinding viewBinding;
+ private CustomLabelsSelectionDialogBinding labelsBinding;
+ private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
+ private Dialog dialogLabels;
+ private String labelsSetter;
+ private ArrayList labelsIds = new ArrayList<>();
+ private ArrayList assignees = new ArrayList<>();
+ private int milestoneId;
+
+ private String instanceUrl;
+ private String loginUid;
+ private String instanceToken;
+ private String repoOwner;
+ private String repoName;
+
+ private LabelsListAdapter labelsAdapter;
+
+ List milestonesList = new ArrayList<>();
+ List branchesList = new ArrayList<>();
+ List labelsList = new ArrayList<>();
+
+ public CreatePullRequestActivity() {
+ }
+
+ @Override
+ protected int getLayoutResourceId(){
+ return R.layout.activity_create_pr;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ appCtx = getApplicationContext();
+ tinyDb = new TinyDB(appCtx);
+
+ viewBinding = ActivityCreatePrBinding.inflate(getLayoutInflater());
+ View view = viewBinding.getRoot();
+ setContentView(view);
+
+ instanceUrl = tinyDb.getString("instanceUrl");
+ loginUid = tinyDb.getString("loginUid");
+ String repoFullName = tinyDb.getString("repoFullName");
+ String[] parts = repoFullName.split("/");
+ repoOwner = parts[0];
+ repoName = parts[1];
+ instanceToken = "token " + tinyDb.getString(loginUid + "-token");
+
+ // require gitea 1.12 or higher
+ if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
+ resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
+ }
+
+ labelsAdapter = new LabelsListAdapter(labelsList, CreatePullRequestActivity.this);
+
+ ImageView closeActivity = findViewById(R.id.close);
+
+ initCloseListener();
+ closeActivity.setOnClickListener(onClickListener);
+
+ viewBinding.prDueDate.setOnClickListener(dueDate ->
+ setDueDate()
+ );
+
+ disableProcessButton();
+
+ getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid, resultLimit);
+ getBranches(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
+
+ viewBinding.prLabels.setOnClickListener(prLabels ->
+ showLabels()
+ );
+
+ viewBinding.createPr.setOnClickListener(createPr ->
+ processPullRequest()
+ );
+ }
+
+ private void processPullRequest() {
+
+ String prTitle = String.valueOf(viewBinding.prTitle.getText());
+ String prDescription = String.valueOf(viewBinding.prBody.getText());
+ String mergeInto = viewBinding.mergeIntoBranchSpinner.getText().toString();
+ String pullFrom = viewBinding.pullFromBranchSpinner.getText().toString();
+ String dueDate = String.valueOf(viewBinding.prDueDate.getText());
+
+ assignees.add("");
+
+ if (labelsIds.size() == 0) {
+ labelsIds.add(0);
+ }
+
+ if (dueDate.matches("")) {
+ dueDate = null;
+ }
+ else {
+ dueDate = AppUtil.customDateCombine(AppUtil.customDateFormat(dueDate));
+ }
+
+ if(prTitle.matches("")) {
+
+ Toasty.error(ctx, getString(R.string.titleError));
+ }
+ else if(mergeInto.matches("")) {
+
+ Toasty.error(ctx, getString(R.string.mergeIntoError));
+ }
+ else if(pullFrom.matches("")) {
+
+ Toasty.error(ctx, getString(R.string.pullFromError));
+ }
+ else if(pullFrom.equals(mergeInto)) {
+
+ Toasty.error(ctx, getString(R.string.sameBranchesError));
+ }
+ else {
+ createPullRequest(prTitle, prDescription, mergeInto, pullFrom, milestoneId, dueDate, assignees);
+ }
+ //Log.e("processPullRequest", String.valueOf(milestoneId));
+ }
+
+ private void createPullRequest(String prTitle, String prDescription, String mergeInto, String pullFrom, int milestoneId, String dueDate, ArrayList assignees) {
+
+ CreatePullRequest createPullRequest = new CreatePullRequest(prTitle, prDescription, loginUid, mergeInto, pullFrom, milestoneId, dueDate, assignees, labelsIds);
+
+ Call transferCall = RetrofitClient
+ .getInstance(instanceUrl, ctx)
+ .getApiInterface()
+ .createPullRequest(instanceToken, repoOwner, repoName, createPullRequest);
+
+ transferCall.enqueue(new Callback() {
+
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) {
+
+ disableProcessButton();
+
+ if (response.code() == 201) {
+
+ Toasty.success(ctx, getString(R.string.prCreateSuccess));
+ finish();
+ }
+ else if (response.code() == 409 && response.message().equals("Conflict")) {
+
+ enableProcessButton();
+ Toasty.error(ctx, getString(R.string.prAlreadyExists));
+ }
+ else if (response.code() == 404) {
+
+ enableProcessButton();
+ Toasty.error(ctx, getString(R.string.apiNotFound));
+ }
+ else {
+
+ enableProcessButton();
+ Toasty.error(ctx, getString(R.string.genericError));
+ }
+
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call, @NonNull Throwable t) {
+
+ enableProcessButton();
+ Toasty.error(ctx, getString(R.string.genericServerResponseError));
+ }
+ });
+ }
+
+ @Override
+ public void labelsStringData(ArrayList data) {
+
+ labelsSetter = String.valueOf(data);
+ viewBinding.prLabels.setText(labelsSetter.replace("]", "").replace("[", ""));
+ }
+
+ @Override
+ public void labelsIdsData(ArrayList data) {
+
+ labelsIds = data;
+ }
+
+ private void showLabels() {
+
+ dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
+
+ if (dialogLabels.getWindow() != null) {
+ dialogLabels.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+ }
+
+ labelsBinding = CustomLabelsSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
+
+ View view = labelsBinding.getRoot();
+ dialogLabels.setContentView(view);
+
+ labelsBinding.cancel.setOnClickListener(editProperties ->
+ dialogLabels.dismiss()
+ );
+
+ Call> call = RetrofitClient
+ .getInstance(instanceUrl, ctx)
+ .getApiInterface()
+ .getlabels(instanceToken, repoOwner, repoName);
+
+ call.enqueue(new Callback>() {
+
+ @Override
+ public void onResponse(@NonNull Call> call, @NonNull retrofit2.Response> response) {
+
+ labelsList.clear();
+ List labelsList_ = response.body();
+
+ labelsBinding.progressBar.setVisibility(View.GONE);
+ labelsBinding.dialogFrame.setVisibility(View.VISIBLE);
+
+ if (response.code() == 200) {
+
+ assert labelsList_ != null;
+ if(labelsList_.size() > 0) {
+ for (int i = 0; i < labelsList_.size(); i++) {
+
+ labelsList.add(new Labels(labelsList_.get(i).getId(), labelsList_.get(i).getName()));
+
+ }
+ }
+ else {
+
+ dialogLabels.dismiss();
+ Toasty.warning(ctx, getString(R.string.noLabelsFound));
+ }
+
+ labelsBinding.labelsRecyclerView.setAdapter(labelsAdapter);
+
+ }
+ else {
+
+ Toasty.error(ctx, getString(R.string.genericError));
+ }
+
+ }
+
+ @Override
+ public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
+
+ Toasty.error(ctx, getString(R.string.genericServerResponseError));
+ }
+ });
+
+ dialogLabels.show();
+
+ }
+
+ private void getBranches(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
+
+ Call> call = RetrofitClient
+ .getInstance(instanceUrl, ctx)
+ .getApiInterface()
+ .getBranches(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
+
+ call.enqueue(new Callback>() {
+
+ @Override
+ public void onResponse(@NonNull Call> call, @NonNull retrofit2.Response> response) {
+
+ if(response.isSuccessful()) {
+ if(response.code() == 200) {
+
+ List branchesList_ = response.body();
+
+ assert branchesList_ != null;
+ if(branchesList_.size() > 0) {
+ for (int i = 0; i < branchesList_.size(); i++) {
+
+ Branches data = new Branches(
+ branchesList_.get(i).getName()
+ );
+ branchesList.add(data);
+
+ }
+ }
+
+ ArrayAdapter adapter = new ArrayAdapter<>(CreatePullRequestActivity.this,
+ R.layout.list_spinner_items, branchesList);
+
+ viewBinding.mergeIntoBranchSpinner.setAdapter(adapter);
+ viewBinding.pullFromBranchSpinner.setAdapter(adapter);
+ enableProcessButton();
+
+ }
+ }
+
+ }
+
+ @Override
+ public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
+
+ Toasty.error(ctx, getString(R.string.genericServerResponseError));
+ }
+ });
+
+ }
+
+ private void getMilestones(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid, int resultLimit) {
+
+ String msState = "open";
+ Call> call = RetrofitClient
+ .getInstance(instanceUrl, ctx)
+ .getApiInterface()
+ .getMilestones(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, 1, resultLimit, msState);
+
+ call.enqueue(new Callback>() {
+
+ @Override
+ public void onResponse(@NonNull Call> call, @NonNull retrofit2.Response> response) {
+
+ if(response.code() == 200) {
+
+ List milestonesList_ = response.body();
+
+ milestonesList.add(new Milestones(0,getString(R.string.issueCreatedNoMilestone)));
+ assert milestonesList_ != null;
+ if(milestonesList_.size() > 0) {
+ for (int i = 0; i < milestonesList_.size(); i++) {
+
+ //Don't translate "open" is a enum
+ if(milestonesList_.get(i).getState().equals("open")) {
+ Milestones data = new Milestones(
+ milestonesList_.get(i).getId(),
+ milestonesList_.get(i).getTitle()
+ );
+ milestonesList.add(data);
+ }
+
+ }
+ }
+
+ ArrayAdapter adapter = new ArrayAdapter<>(CreatePullRequestActivity.this,
+ R.layout.list_spinner_items, milestonesList);
+
+ viewBinding.milestonesSpinner.setAdapter(adapter);
+ enableProcessButton();
+
+ viewBinding.milestonesSpinner.setOnItemClickListener ((parent, view, position, id) ->
+
+ milestoneId = milestonesList.get(position).getId()
+ );
+
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
+
+ Toasty.error(ctx, getString(R.string.genericServerResponseError));
+ }
+ });
+
+ }
+
+ private void setDueDate() {
+
+ final Calendar c = Calendar.getInstance();
+ int mYear = c.get(Calendar.YEAR);
+ final int mMonth = c.get(Calendar.MONTH);
+ final int mDay = c.get(Calendar.DAY_OF_MONTH);
+
+ DatePickerDialog datePickerDialog = new DatePickerDialog(this,
+ (view, year, monthOfYear, dayOfMonth) -> viewBinding.prDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
+ datePickerDialog.show();
+ }
+
+ private void initCloseListener() {
+
+ onClickListener = view -> finish();
+ }
+
+ private void disableProcessButton() {
+
+ viewBinding.createPr.setEnabled(false);
+ }
+
+ private void enableProcessButton() {
+
+ viewBinding.createPr.setEnabled(true);
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java b/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java
index f55d67e8..cac8891c 100644
--- a/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java
@@ -167,16 +167,12 @@ public class LoginActivity extends BaseActivity {
URI rawInstanceUrl = UrlBuilder.fromString(UrlHelper.fixScheme(instanceUrlET.getText().toString(), "http")).toUri();
- URI instanceUrlWithProtocol = UrlBuilder.fromUri(rawInstanceUrl).withPath(PathsHelper.join(rawInstanceUrl.getPath()))
- .withScheme(protocol.name().toLowerCase()).toUri();
-
- URI instanceUrl = UrlBuilder.fromUri(instanceUrlWithProtocol).withPath(PathsHelper.join(instanceUrlWithProtocol.getPath(), "/api/v1/"))
+ URI instanceUrl = UrlBuilder.fromUri(rawInstanceUrl).withScheme(protocol.name().toLowerCase()).withPath(PathsHelper.join(rawInstanceUrl.getPath(), "/api/v1/"))
.toUri();
tinyDB.putString("loginType", loginType.name().toLowerCase());
tinyDB.putString("instanceUrlRaw", instanceUrlET.getText().toString());
tinyDB.putString("instanceUrl", instanceUrl.toString());
- tinyDB.putString("instanceUrlWithProtocol", instanceUrlWithProtocol.toString());
if(instanceUrlET.getText().toString().equals("")) {
diff --git a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java
index 5187649c..61922179 100644
--- a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java
@@ -1,15 +1,14 @@
package org.mian.gitnex.activities;
import android.app.Activity;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
-import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
+import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -32,11 +31,10 @@ import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
-import org.mian.gitnex.fragments.AboutFragment;
import org.mian.gitnex.fragments.AdministrationFragment;
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
import org.mian.gitnex.fragments.DraftsFragment;
-import org.mian.gitnex.fragments.ExploreRepositoriesFragment;
+import org.mian.gitnex.fragments.ExploreFragment;
import org.mian.gitnex.fragments.MyRepositoriesFragment;
import org.mian.gitnex.fragments.NotificationsFragment;
import org.mian.gitnex.fragments.OrganizationsFragment;
@@ -55,6 +53,7 @@ import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.GiteaVersion;
+import org.mian.gitnex.models.NotificationCount;
import org.mian.gitnex.models.UserInfo;
import java.util.ArrayList;
import java.util.List;
@@ -82,6 +81,14 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
private Context appCtx;
private Typeface myTypeface;
+ private String instanceUrl;
+ private String loginUid;
+ private String instanceToken;
+
+ private View hView;
+ private MenuItem navNotifications;
+ private TextView notificationCounter;
+
@Override
protected int getLayoutResourceId() {
@@ -100,9 +107,9 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
Intent mainIntent = getIntent();
String launchFragment = mainIntent.getStringExtra("launchFragment");
- final String instanceUrl = tinyDb.getString("instanceUrl");
- final String loginUid = tinyDb.getString("loginUid");
- final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
+ instanceUrl = tinyDb.getString("instanceUrl");
+ loginUid = tinyDb.getString("loginUid");
+ instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getString("dateFormat").isEmpty()) {
tinyDb.putString("dateFormat", "pretty");
@@ -169,7 +176,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
else if(fragmentById instanceof OrganizationsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
}
- else if(fragmentById instanceof ExploreRepositoriesFragment) {
+ else if(fragmentById instanceof ExploreFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
}
else if(fragmentById instanceof NotificationsFragment) {
@@ -178,9 +185,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
else if(fragmentById instanceof ProfileFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
}
- else if(fragmentById instanceof AboutFragment) {
- toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
- }
else if(fragmentById instanceof DraftsFragment) {
toolbarTitle.setText(getResources().getString(R.string.titleDrafts));
}
@@ -191,10 +195,15 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
toolbarTitle.setText(getResources().getString(R.string.pageTitleUserAccounts));
}
+ getNotificationsCount(instanceUrl, instanceToken);
+
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
- final View hView = navigationView.getHeaderView(0);
+ hView = navigationView.getHeaderView(0);
+
+ Menu menu = navigationView.getMenu();
+ navNotifications = menu.findItem(R.id.nav_notifications);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
@@ -204,6 +213,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
@Override
public void onDrawerOpened(@NonNull View drawerView) {
+ getNotificationsCount(instanceUrl, instanceToken);
}
@Override
@@ -295,6 +305,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
+ navigationView.setCheckedItem(R.id.nav_profile);
drawer.closeDrawers();
});
@@ -374,7 +385,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
case 5:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
- getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreRepositoriesFragment()).commit();
+ getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore);
break;
@@ -439,6 +450,11 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
}
}
+ public void setActionBarTitle(String title) {
+
+ toolbarTitle.setText(title);
+ }
+
@Override
public void onButtonClicked(String text) {
@@ -528,15 +544,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break;
- case R.id.nav_about:
- toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
- getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AboutFragment()).commit();
- break;
-
- case R.id.nav_rate_app:
- rateThisApp();
- break;
-
case R.id.nav_starred_repos:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
@@ -544,7 +551,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
case R.id.nav_explore:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
- getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreRepositoriesFragment()).commit();
+ getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
break;
case R.id.nav_notifications:
@@ -568,16 +575,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
return true;
}
- public void rateThisApp() {
-
- try {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())));
- }
- catch(ActivityNotFoundException e) {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName())));
- }
- }
-
public static void logout(Activity activity, Context ctx) {
TinyDB tinyDb = new TinyDB(ctx.getApplicationContext());
@@ -705,4 +702,31 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
}
+ private void getNotificationsCount(String instanceUrl, String token) {
+
+ Call call = RetrofitClient.getInstance(instanceUrl, ctx).getApiInterface().checkUnreadNotifications(token);
+
+ call.enqueue(new Callback() {
+
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) {
+
+ NotificationCount notificationCount = response.body();
+
+ if(response.code() == 200) {
+
+ assert notificationCount != null;
+ notificationCounter = navNotifications.getActionView().findViewById(R.id.counterBadgeNotification);
+ notificationCounter.setText(String.valueOf(notificationCount.getCounter()));
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call, @NonNull Throwable t) {
+
+ Log.e("onFailure-notification", t.toString());
+ }
+ });
+ }
+
}
diff --git a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
index e3743446..80b00689 100644
--- a/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/RepoDetailActivity.java
@@ -406,6 +406,10 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
startActivity(new Intent(RepoDetailActivity.this, RepositorySettingsActivity.class));
break;
+ case "newPullRequest":
+ startActivity(new Intent(RepoDetailActivity.this, CreatePullRequestActivity.class));
+ break;
+
}
}
diff --git a/app/src/main/java/org/mian/gitnex/activities/RepositorySettingsActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepositorySettingsActivity.java
index d6dff0b5..e4c0ff96 100644
--- a/app/src/main/java/org/mian/gitnex/activities/RepositorySettingsActivity.java
+++ b/app/src/main/java/org/mian/gitnex/activities/RepositorySettingsActivity.java
@@ -394,6 +394,9 @@ public class RepositorySettingsActivity extends BaseActivity {
if (response.code() == 200) {
+ tinyDb.putBoolean("hasIssues", repoEnableIssues);
+ tinyDb.putBoolean("hasPullRequests", repoEnablePr);
+
dialogProp.dismiss();
Toasty.success(ctx, getString(R.string.repoPropertiesSaveSuccess));
diff --git a/app/src/main/java/org/mian/gitnex/adapters/ExploreRepositoriesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/ExploreRepositoriesAdapter.java
index 5cc2e917..92be07df 100644
--- a/app/src/main/java/org/mian/gitnex/adapters/ExploreRepositoriesAdapter.java
+++ b/app/src/main/java/org/mian/gitnex/adapters/ExploreRepositoriesAdapter.java
@@ -318,4 +318,9 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter {
+
+ private List labels;
+ private ArrayList labelsStrings = new ArrayList<>();
+ private ArrayList labelsIds = new ArrayList<>();
+
+ private LabelsListAdapterListener labelsListener;
+
+ public interface LabelsListAdapterListener {
+
+ void labelsStringData(ArrayList data);
+ void labelsIdsData(ArrayList data);
+ }
+
+ public LabelsListAdapter(List labelsMain, LabelsListAdapterListener labelsListener) {
+
+ this.labels = labelsMain;
+ this.labelsListener = labelsListener;
+ }
+
+ static class LabelsViewHolder extends RecyclerView.ViewHolder {
+
+ private CheckBox labelSelection;
+
+ private LabelsViewHolder(View itemView) {
+ super(itemView);
+
+ labelSelection = itemView.findViewById(R.id.labelSelection);
+
+ }
+ }
+
+ @NonNull
+ @Override
+ public LabelsListAdapter.LabelsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+
+ View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_labels_list, parent, false);
+ return new LabelsListAdapter.LabelsViewHolder(v);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull LabelsListAdapter.LabelsViewHolder holder, int position) {
+
+ Labels currentItem = labels.get(position);
+
+ holder.labelSelection.setText(currentItem.getName());
+
+ for(int i = 0; i < labelsIds.size(); i++) {
+
+ if(labelsStrings.contains(currentItem.getName())) {
+
+ holder.labelSelection.setChecked(true);
+ }
+ }
+
+ holder.labelSelection.setOnCheckedChangeListener((buttonView, isChecked) -> {
+
+ if(isChecked) {
+
+ labelsStrings.add(currentItem.getName());
+ labelsIds.add(currentItem.getId());
+ }
+ else {
+
+ labelsStrings.remove(currentItem.getName());
+ labelsIds.remove(Integer.valueOf(currentItem.getId()));
+ }
+
+ labelsListener.labelsStringData(labelsStrings);
+ labelsListener.labelsIdsData(labelsIds);
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return labels.size();
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/adapters/SearchIssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/SearchIssuesAdapter.java
new file mode 100644
index 00000000..379029e4
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/adapters/SearchIssuesAdapter.java
@@ -0,0 +1,172 @@
+package org.mian.gitnex.adapters;
+
+import android.content.Context;
+import android.content.Intent;
+import android.text.Html;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import org.mian.gitnex.R;
+import org.mian.gitnex.activities.IssueDetailActivity;
+import org.mian.gitnex.clients.PicassoService;
+import org.mian.gitnex.database.api.RepositoriesApi;
+import org.mian.gitnex.database.models.Repository;
+import org.mian.gitnex.helpers.ClickListener;
+import org.mian.gitnex.helpers.RoundedTransformation;
+import org.mian.gitnex.helpers.TimeHelper;
+import org.mian.gitnex.helpers.TinyDB;
+import org.mian.gitnex.models.Issues;
+import org.ocpsoft.prettytime.PrettyTime;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Author M M Arif
+ */
+
+public class SearchIssuesAdapter extends RecyclerView.Adapter {
+
+ private List searchedList;
+ private Context mCtx;
+ private TinyDB tinyDb;
+
+ public SearchIssuesAdapter(List dataList, Context mCtx) {
+
+ this.mCtx = mCtx;
+ this.searchedList = dataList;
+ this.tinyDb = new TinyDB(mCtx);
+ }
+
+ class SearchViewHolder extends RecyclerView.ViewHolder {
+
+ private TextView issueNumber;
+ private ImageView issueAssigneeAvatar;
+ private TextView issueTitle;
+ private TextView issueCreatedTime;
+ private TextView issueCommentsCount;
+ private TextView repoFullName;
+
+ private SearchViewHolder(View itemView) {
+
+ super(itemView);
+
+ issueNumber = itemView.findViewById(R.id.issueNumber);
+ issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
+ issueTitle = itemView.findViewById(R.id.issueTitle);
+ issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
+ issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
+ repoFullName = itemView.findViewById(R.id.repoFullName);
+
+ issueTitle.setOnClickListener(v -> {
+
+ Context context = v.getContext();
+
+ Intent intent = new Intent(context, IssueDetailActivity.class);
+ intent.putExtra("issueNumber", issueNumber.getText());
+
+ tinyDb.putString("issueNumber", issueNumber.getText().toString());
+ tinyDb.putString("issueType", "Issue");
+
+ tinyDb.putString("repoFullName", repoFullName.getText().toString());
+
+ String[] parts = repoFullName.getText().toString().split("/");
+ final String repoOwner = parts[0];
+ final String repoName = parts[1];
+
+ int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
+ RepositoriesApi repositoryData = new RepositoriesApi(context);
+
+ Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
+
+ if(count == 0) {
+
+ long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
+ tinyDb.putLong("repositoryId", id);
+
+ }
+ else {
+
+ Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
+ tinyDb.putLong("repositoryId", data.getRepositoryId());
+
+ }
+
+ context.startActivity(intent);
+ });
+ }
+
+ }
+
+ @NonNull
+ @Override
+ public SearchIssuesAdapter.SearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+
+ View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_issues, parent, false);
+ return new SearchIssuesAdapter.SearchViewHolder(v);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull final SearchIssuesAdapter.SearchViewHolder holder, int position) {
+
+ Issues currentItem = searchedList.get(position);
+
+ String locale = tinyDb.getString("locale");
+ String timeFormat = tinyDb.getString("dateFormat");
+
+ if(!currentItem.getUser().getFull_name().equals("")) {
+ holder.issueAssigneeAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCreator) + currentItem.getUser().getFull_name(), mCtx));
+ }
+ else {
+ holder.issueAssigneeAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCreator) + currentItem.getUser().getLogin(), mCtx));
+ }
+
+ PicassoService
+ .getInstance(mCtx).get().load(currentItem.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueAssigneeAvatar);
+
+ String issueNumber_ = "" + currentItem.getRepository().getFull_name() + mCtx.getResources().getString(R.string.hash) + currentItem.getNumber() + "";
+ holder.issueTitle.setText(Html.fromHtml(issueNumber_ + " " + currentItem.getTitle()));
+
+ holder.issueNumber.setText(String.valueOf(currentItem.getNumber()));
+ holder.issueCommentsCount.setText(String.valueOf(currentItem.getComments()));
+ holder.repoFullName.setText(currentItem.getRepository().getFull_name());
+
+ switch(timeFormat) {
+ case "pretty": {
+ PrettyTime prettyTime = new PrettyTime(new Locale(locale));
+ String createdTime = prettyTime.format(currentItem.getCreated_at());
+ holder.issueCreatedTime.setText(createdTime);
+ holder.issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getCreated_at()), mCtx));
+ break;
+ }
+ case "normal": {
+ DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + mCtx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
+ String createdTime = formatter.format(currentItem.getCreated_at());
+ holder.issueCreatedTime.setText(createdTime);
+ break;
+ }
+ case "normal1": {
+ DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + mCtx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
+ String createdTime = formatter.format(currentItem.getCreated_at());
+ holder.issueCreatedTime.setText(createdTime);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+
+ return searchedList.size();
+ }
+
+ public void notifyDataChanged() {
+
+ notifyDataSetChanged();
+ }
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/AboutFragment.java b/app/src/main/java/org/mian/gitnex/fragments/AboutFragment.java
index 1f888ee2..9f43bd12 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/AboutFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/AboutFragment.java
@@ -6,14 +6,13 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import org.mian.gitnex.R;
+import org.mian.gitnex.activities.MainActivity;
+import org.mian.gitnex.databinding.FragmentAboutBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
-import java.util.Objects;
/**
* Author M M Arif
@@ -21,30 +20,19 @@ import java.util.Objects;
public class AboutFragment extends Fragment {
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
-
- View v = inflater.inflate(R.layout.fragment_about, container, false);
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ FragmentAboutBinding viewBinding = FragmentAboutBinding.inflate(inflater, container, false);
TinyDB tinyDb = new TinyDB(getContext());
- final TextView appVerBuild;
- final TextView donationLink;
- final TextView donationLinkPatreon;
- final TextView translateLink;
- final TextView appWebsite;
- final TextView appRepo;
+ viewBinding.appVersion.setText(AppUtil.getAppVersion(requireContext()));
+ viewBinding.userServerVersion.setText(tinyDb.getString("giteaVersion"));
+ viewBinding.appBuild.setText(String.valueOf(AppUtil.getAppBuildNo(requireContext())));
- appVerBuild = v.findViewById(R.id.appVerBuild);
- TextView viewTextGiteaVersion = v.findViewById(R.id.giteaVersion);
- donationLink = v.findViewById(R.id.donationLink);
- donationLinkPatreon = v.findViewById(R.id.donationLinkPatreon);
- translateLink = v.findViewById(R.id.translateLink);
- appWebsite = v.findViewById(R.id.appWebsite);
- appRepo = v.findViewById(R.id.appRepo);
+ ((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.pageTitleAbout));
- appVerBuild.setText(getString(R.string.appVerBuild, AppUtil.getAppVersion(Objects.requireNonNull(getContext())), AppUtil.getAppBuildNo(getContext())));
-
- donationLink.setOnClickListener(v1 -> {
+ viewBinding.donationLinkLiberapay.setOnClickListener(v1 -> {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
@@ -53,7 +41,7 @@ public class AboutFragment extends Fragment {
startActivity(intent);
});
- donationLinkPatreon.setOnClickListener(v12 -> {
+ viewBinding.donationLinkPatreon.setOnClickListener(v12 -> {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
@@ -62,7 +50,7 @@ public class AboutFragment extends Fragment {
startActivity(intent);
});
- translateLink.setOnClickListener(v13 -> {
+ viewBinding.translateLink.setOnClickListener(v13 -> {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
@@ -71,7 +59,7 @@ public class AboutFragment extends Fragment {
startActivity(intent);
});
- appWebsite.setOnClickListener(v14 -> {
+ viewBinding.appWebsite.setOnClickListener(v14 -> {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
@@ -80,19 +68,15 @@ public class AboutFragment extends Fragment {
startActivity(intent);
});
- appRepo.setOnClickListener(v15 -> {
+ if(AppUtil.isPro(requireContext())) {
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_VIEW);
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- intent.setData(Uri.parse(getResources().getString(R.string.appRepoLink)));
- startActivity(intent);
- });
+ viewBinding.supportHeader.setVisibility(View.GONE);
+ viewBinding.dividerSupport.setVisibility(View.GONE);
+ viewBinding.donationLinkLiberapay.setVisibility(View.GONE);
+ viewBinding.donationLinkPatreon.setVisibility(View.GONE);
+ }
- String commit = getResources().getString(R.string.commitPage) + tinyDb.getString("giteaVersion");
- viewTextGiteaVersion.setText(commit);
-
- return v;
+ return viewBinding.getRoot();
}
}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java
index dd097632..f99ea3a1 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/BottomSheetRepoFragment.java
@@ -43,6 +43,7 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
TextView copyRepoUrl = v.findViewById(R.id.copyRepoUrl);
View repoSettingsDivider = v.findViewById(R.id.repoSettingsDivider);
TextView repoSettings = v.findViewById(R.id.repoSettings);
+ TextView createPullRequest = v.findViewById(R.id.createPullRequest);
createLabel.setOnClickListener(v112 -> {
@@ -64,6 +65,20 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
createIssue.setVisibility(View.GONE);
}
+ if(tinyDb.getBoolean("hasPullRequests")) {
+
+ createPullRequest.setVisibility(View.VISIBLE);
+ createPullRequest.setOnClickListener(vPr -> {
+
+ bmListener.onButtonClicked("newPullRequest");
+ dismiss();
+ });
+ }
+ else {
+
+ createPullRequest.setVisibility(View.GONE);
+ }
+
createMilestone.setOnClickListener(v13 -> {
bmListener.onButtonClicked("newMilestone");
diff --git a/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java b/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java
new file mode 100644
index 00000000..47d3c23e
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java
@@ -0,0 +1,129 @@
+package org.mian.gitnex.fragments;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+import com.google.android.material.tabs.TabLayout;
+import org.mian.gitnex.R;
+import org.mian.gitnex.activities.MainActivity;
+import org.mian.gitnex.helpers.TinyDB;
+
+/**
+ * Author M M Arif
+ */
+
+public class ExploreFragment extends Fragment {
+
+ private Context ctx;
+ private TinyDB tinyDB;
+
+ private int tabsCount;
+ public ViewPager mViewPager;
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+
+ View v = inflater.inflate(R.layout.fragment_explore, container,false);
+ ctx = getContext();
+ tinyDB = new TinyDB(ctx);
+
+ ((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navExplore));
+
+ TabLayout tabLayout = v.findViewById(R.id.tabsExplore);
+
+ ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0);
+ tabsCount = viewGroup.getChildCount();
+
+ Typeface myTypeface;
+
+ switch(tinyDB.getInt("customFontId", -1)) {
+
+ case 0:
+ myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
+ break;
+
+ case 2:
+ myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
+ break;
+
+ default:
+ myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
+ break;
+
+ }
+
+ for(int j = 0; j < tabsCount; j++) {
+
+ ViewGroup vgTab = (ViewGroup) viewGroup.getChildAt(j);
+ int tabChildCount = vgTab.getChildCount();
+
+ for(int i = 0; i < tabChildCount; i++) {
+
+ View tabViewChild = vgTab.getChildAt(i);
+
+ if(tabViewChild instanceof TextView) {
+ ((TextView) tabViewChild).setTypeface(myTypeface);
+ }
+ }
+ }
+
+ mViewPager = v.findViewById(R.id.containerExplore);
+
+ mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
+ tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
+
+ SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
+ mViewPager.setAdapter(mSectionsPagerAdapter);
+
+ return v;
+ }
+
+ public class SectionsPagerAdapter extends FragmentPagerAdapter {
+
+ SectionsPagerAdapter(FragmentManager fm) {
+
+ super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
+ }
+
+ @NonNull
+ @Override
+ public Fragment getItem(int position) {
+
+ Fragment fragment = null;
+
+ switch(position) {
+
+ case 0: // Repositories
+ fragment = new ExploreRepositoriesFragment();
+ break;
+
+ case 1: // Issues
+ fragment = new SearchIssuesFragment();
+ break;
+ }
+
+ assert fragment != null;
+ return fragment;
+
+ }
+
+ @Override
+ public int getCount() {
+
+ return tabsCount;
+ }
+
+ }
+
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/ExploreRepositoriesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/ExploreRepositoriesFragment.java
index dc354883..75bf2c84 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/ExploreRepositoriesFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/ExploreRepositoriesFragment.java
@@ -1,27 +1,37 @@
package org.mian.gitnex.fragments;
+import android.app.Dialog;
import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
-import android.widget.ProgressBar;
-import android.widget.TextView;
+import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
-import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.ExploreRepositoriesAdapter;
import org.mian.gitnex.clients.RetrofitClient;
+import org.mian.gitnex.databinding.CustomExploreRepositoriesDialogBinding;
+import org.mian.gitnex.databinding.FragmentExploreRepoBinding;
+import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
+import org.mian.gitnex.helpers.InfiniteScrollListener;
+import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
+import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.ExploreRepositories;
import org.mian.gitnex.models.UserRepositories;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
@@ -29,189 +39,300 @@ import retrofit2.Callback;
import retrofit2.Response;
/**
- * Template Author Author M M Arif
+ * Template Author M M Arif
* Author 6543
*/
public class ExploreRepositoriesFragment extends Fragment {
- private static String repoNameF = "param2";
- private static String repoOwnerF = "param1";
- private ProgressBar mProgressBar;
- private RecyclerView mRecyclerView;
- private TextView noData;
- private TextView searchKeyword;
- private Boolean repoTypeInclude = true;
+ private FragmentExploreRepoBinding viewBinding;
+ private Context ctx;
+ private TinyDB tinyDb;
+
+ private int pageCurrentIndex = 1;
+ private boolean repoTypeInclude = true;
private String sort = "updated";
private String order = "desc";
- private int limit = 50;
+ private int limit = 10;
+ private List dataList;
+ private ExploreRepositoriesAdapter adapter;
- private OnFragmentInteractionListener mListener;
+ private String instanceUrl;
+ private String loginUid;
+ private String instanceToken;
- public ExploreRepositoriesFragment() {
-
- }
-
- public static ExploreRepositoriesFragment newInstance(String param1, String param2) {
-
- ExploreRepositoriesFragment fragment = new ExploreRepositoriesFragment();
- Bundle args = new Bundle();
- args.putString(repoOwnerF, param1);
- args.putString(repoNameF, param2);
- fragment.setArguments(args);
- return fragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
-
- super.onCreate(savedInstanceState);
- if(getArguments() != null) {
- String repoName = getArguments().getString(repoNameF);
- String repoOwner = getArguments().getString(repoOwnerF);
- }
- }
+ private Dialog dialogFilterOptions;
+ private CustomExploreRepositoriesDialogBinding filterBinding;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final View v = inflater.inflate(R.layout.fragment_explore_repo, container, false);
- //setHasOptionsMenu(true);
+ viewBinding = FragmentExploreRepoBinding.inflate(inflater, container, false);
+ setHasOptionsMenu(true);
- TinyDB tinyDb = new TinyDB(getContext());
- final String instanceUrl = tinyDb.getString("instanceUrl");
- final String loginUid = tinyDb.getString("loginUid");
- final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
+ ctx = getContext();
+ tinyDb = new TinyDB(getContext());
- searchKeyword = v.findViewById(R.id.searchKeyword);
- noData = v.findViewById(R.id.noData);
- mProgressBar = v.findViewById(R.id.progress_bar);
- mRecyclerView = v.findViewById(R.id.recyclerViewReposSearch);
+ instanceUrl = tinyDb.getString("instanceUrl");
+ loginUid = tinyDb.getString("loginUid");
+ instanceToken = "token " + tinyDb.getString(loginUid + "-token");
- mProgressBar.setVisibility(View.VISIBLE);
+ dataList = new ArrayList<>();
+ adapter = new ExploreRepositoriesAdapter(dataList, ctx);
- searchKeyword.setOnEditorActionListener((v1, actionId, event) -> {
+ tinyDb.putBoolean("exploreRepoIncludeTopic", false);
+ tinyDb.putBoolean("exploreRepoIncludeDescription", false);
+ tinyDb.putBoolean("exploreRepoIncludeTemplate", false);
+ tinyDb.putBoolean("exploreRepoOnlyArchived", false);
+
+ // if gitea is 1.12 or higher use the new limit
+ if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
+ limit = StaticGlobalVariables.resultLimitNewGiteaInstances;
+ }
+
+ LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ctx);
+
+ viewBinding.recyclerViewReposSearch.setHasFixedSize(true);
+ viewBinding.recyclerViewReposSearch.setLayoutManager(linearLayoutManager);
+ viewBinding.recyclerViewReposSearch.setAdapter(adapter);
+
+ viewBinding.searchKeyword.setOnEditorActionListener((v1, actionId, event) -> {
if(actionId == EditorInfo.IME_ACTION_SEND) {
- if(!searchKeyword.getText().toString().equals("")) {
- mProgressBar.setVisibility(View.VISIBLE);
- mRecyclerView.setVisibility(View.GONE);
- loadSearchReposList(instanceUrl, instanceToken, loginUid, searchKeyword.getText().toString(), repoTypeInclude, sort, order, getContext(), limit);
+
+ if(!Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString().equals("")) {
+
+ InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(viewBinding.searchKeyword.getWindowToken(), 0);
+
+ // if gitea is 1.12 or higher use the new limit
+ if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
+ limit = StaticGlobalVariables.resultLimitNewGiteaInstances;
+ }
+ else {
+ limit = 10;
+ }
+
+ pageCurrentIndex = 1;
+ viewBinding.progressBar.setVisibility(View.VISIBLE);
+ loadData(false, viewBinding.searchKeyword.getText().toString(), tinyDb.getBoolean("exploreRepoIncludeTopic"), tinyDb.getBoolean("exploreRepoIncludeDescription"), tinyDb.getBoolean("exploreRepoIncludeTemplate"), tinyDb.getBoolean("exploreRepoOnlyArchived"));
}
}
return false;
});
- int limitDefault = 25;
- loadDefaultList(instanceUrl, instanceToken, loginUid, repoTypeInclude, sort, order, getContext(), limitDefault);
-
- return v;
-
- }
-
- private void loadDefaultList(String instanceUrl, String instanceToken, String loginUid, Boolean repoTypeInclude, String sort, String order, final Context context, int limit) {
-
- Call call = RetrofitClient.getInstance(instanceUrl, getContext()).getApiInterface().queryRepos(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), null, repoTypeInclude, sort, order, limit);
-
- call.enqueue(new Callback() {
+ viewBinding.recyclerViewReposSearch.addOnScrollListener(new InfiniteScrollListener(pageCurrentIndex, linearLayoutManager) {
@Override
- public void onResponse(@NonNull Call call, @NonNull Response response) {
-
- if(response.isSuccessful()) {
- assert response.body() != null;
- getReposList(response.body().getSearchedData(), context);
- }
- else {
- Log.i("onResponse", String.valueOf(response.code()));
- }
+ public void onScrolledToEnd(int firstVisibleItemPosition) {
+ pageCurrentIndex++;
+ loadData(true, Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString(), tinyDb.getBoolean("exploreRepoIncludeTopic"), tinyDb.getBoolean("exploreRepoIncludeDescription"), tinyDb.getBoolean("exploreRepoIncludeTemplate"), tinyDb.getBoolean("exploreRepoOnlyArchived"));
}
-
- @Override
- public void onFailure(@NonNull Call call, @NonNull Throwable t) {
-
- Log.i("onFailure", Objects.requireNonNull(t.getMessage()));
- }
-
});
- }
+ viewBinding.pullToRefresh.setOnRefreshListener(() -> {
- private void loadSearchReposList(String instanceUrl, String instanceToken, String loginUid, String searchKeyword, Boolean repoTypeInclude, String sort, String order, final Context context, int limit) {
-
- Call call = RetrofitClient.getInstance(instanceUrl, getContext()).getApiInterface().queryRepos(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), searchKeyword, repoTypeInclude, sort, order, limit);
-
- call.enqueue(new Callback() {
-
- @Override
- public void onResponse(@NonNull Call call, @NonNull Response response) {
-
- if(response.isSuccessful()) {
- assert response.body() != null;
- getReposList(response.body().getSearchedData(), context);
- }
- else {
- Log.i("onResponse", String.valueOf(response.code()));
- }
+ pageCurrentIndex = 1;
+ // if gitea is 1.12 or higher use the new limit
+ if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
+ limit = StaticGlobalVariables.resultLimitNewGiteaInstances;
+ }
+ else {
+ limit = 10;
}
- @Override
- public void onFailure(@NonNull Call call, @NonNull Throwable t) {
-
- Log.i("onFailure", Objects.requireNonNull(t.getMessage()));
- }
-
+ loadData(false, Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString(), tinyDb.getBoolean("exploreRepoIncludeTopic"), tinyDb.getBoolean("exploreRepoIncludeDescription"), tinyDb.getBoolean("exploreRepoIncludeTemplate"), tinyDb.getBoolean("exploreRepoOnlyArchived"));
});
+ loadData(false, "", tinyDb.getBoolean("exploreRepoIncludeTopic"), tinyDb.getBoolean("exploreRepoIncludeDescription"), tinyDb.getBoolean("exploreRepoIncludeTemplate"), tinyDb.getBoolean("exploreRepoOnlyArchived"));
+
+ return viewBinding.getRoot();
+
}
- private void getReposList(List dataList, Context context) {
+ private void loadData(boolean append, String searchKeyword, boolean exploreRepoIncludeTopic, boolean exploreRepoIncludeDescription, boolean exploreRepoIncludeTemplate, boolean exploreRepoOnlyArchived) {
- ExploreRepositoriesAdapter adapter = new ExploreRepositoriesAdapter(dataList, context);
+ viewBinding.noData.setVisibility(View.GONE);
- mRecyclerView.setVisibility(View.VISIBLE);
+ int apiCallDefaultLimit = 10;
+ // if gitea is 1.12 or higher use the new limit
+ if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
+ apiCallDefaultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
+ }
- mRecyclerView.setHasFixedSize(true);
- mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
- DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL);
- mRecyclerView.addItemDecoration(dividerItemDecoration);
+ if(apiCallDefaultLimit > limit) {
+ return;
+ }
- if(adapter.getItemCount() > 0) {
-
- mRecyclerView.setAdapter(adapter);
- noData.setVisibility(View.GONE);
- mProgressBar.setVisibility(View.GONE);
+ if(pageCurrentIndex == 1 || !append) {
+ dataList.clear();
+ adapter.notifyDataSetChanged();
+ viewBinding.pullToRefresh.setRefreshing(false);
+ viewBinding.progressBar.setVisibility(View.VISIBLE);
}
else {
- noData.setVisibility(View.VISIBLE);
- mProgressBar.setVisibility(View.GONE);
-
+ viewBinding.loadingMoreView.setVisibility(View.VISIBLE);
}
+ Call call = RetrofitClient.getInstance(instanceUrl, getContext()).getApiInterface().queryRepos(Authorization.returnAuthentication(getContext(), loginUid, instanceToken), searchKeyword, repoTypeInclude, sort, order, exploreRepoIncludeTopic, exploreRepoIncludeDescription, exploreRepoIncludeTemplate, exploreRepoOnlyArchived, limit, pageCurrentIndex);
+
+ call.enqueue(new Callback() {
+
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
+
+ if(response.code() == 200) {
+
+ assert response.body() != null;
+
+ limit = response.body().getSearchedData().size();
+
+ if(!append) {
+
+ dataList.clear();
+ }
+
+ dataList.addAll(response.body().getSearchedData());
+ adapter.notifyDataSetChanged();
+
+ }
+ else {
+
+ dataList.clear();
+ adapter.notifyDataChanged();
+ viewBinding.noData.setVisibility(View.VISIBLE);
+
+ }
+
+ onCleanup();
+
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call, @NonNull Throwable t) {
+
+ Log.e("onFailure", Objects.requireNonNull(t.getMessage()));
+ onCleanup();
+
+ }
+
+ private void onCleanup() {
+
+ AppUtil.setMultiVisibility(View.GONE, viewBinding.loadingMoreView, viewBinding.progressBar);
+
+ if(dataList.isEmpty()) {
+
+ viewBinding.noData.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
+
+ menu.clear();
+ inflater.inflate(R.menu.filter_menu, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+
+ MenuItem filter = menu.findItem(R.id.filter);
+
+ filter.setOnMenuItemClickListener(filter_ -> {
+
+ showFilterOptions();
+ return false;
+ });
+
}
- public void onButtonPressed(Uri uri) {
+ private void showFilterOptions() {
- if(mListener != null) {
- mListener.onFragmentInteraction(uri);
+ dialogFilterOptions = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
+
+ if (dialogFilterOptions.getWindow() != null) {
+
+ dialogFilterOptions.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
+
+ filterBinding = CustomExploreRepositoriesDialogBinding.inflate(LayoutInflater.from(ctx));
+
+ View view = filterBinding.getRoot();
+ dialogFilterOptions.setContentView(view);
+
+ filterBinding.includeTopic.setOnClickListener(includeTopic -> {
+
+ if(filterBinding.includeTopic.isChecked()) {
+
+ tinyDb.putBoolean("exploreRepoIncludeTopic", true);
+ }
+ else {
+
+ tinyDb.putBoolean("exploreRepoIncludeTopic", false);
+ }
+ });
+
+ filterBinding.includeDesc.setOnClickListener(includeDesc -> {
+
+ if(filterBinding.includeDesc.isChecked()) {
+
+ tinyDb.putBoolean("exploreRepoIncludeDescription", true);
+ }
+ else {
+
+ tinyDb.putBoolean("exploreRepoIncludeDescription", false);
+ }
+ });
+
+ filterBinding.includeTemplate.setOnClickListener(includeTemplate -> {
+
+ if(filterBinding.includeTemplate.isChecked()) {
+
+ tinyDb.putBoolean("exploreRepoIncludeTemplate", true);
+ }
+ else {
+
+ tinyDb.putBoolean("exploreRepoIncludeTemplate", false);
+ }
+ });
+
+ filterBinding.onlyArchived.setOnClickListener(onlyArchived -> {
+
+ if(filterBinding.onlyArchived.isChecked()) {
+
+ tinyDb.putBoolean("exploreRepoOnlyArchived", true);
+ }
+ else {
+
+ tinyDb.putBoolean("exploreRepoOnlyArchived", false);
+ }
+ });
+
+
+ filterBinding.includeTopic.setChecked(tinyDb.getBoolean("exploreRepoIncludeTopic"));
+ filterBinding.includeDesc.setChecked(tinyDb.getBoolean("exploreRepoIncludeDescription"));
+ filterBinding.includeTemplate.setChecked(tinyDb.getBoolean("exploreRepoIncludeTemplate"));
+ filterBinding.onlyArchived.setChecked(tinyDb.getBoolean("exploreRepoOnlyArchived"));
+
+ filterBinding.cancel.setOnClickListener(editProperties -> {
+ dialogFilterOptions.dismiss();
+ });
+
+ dialogFilterOptions.show();
}
@Override
public void onDetach() {
super.onDetach();
- mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
-
}
}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java
index 77a68ab9..4ab393d3 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/IssuesFragment.java
@@ -32,7 +32,6 @@ import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.models.Issues;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@@ -112,7 +111,7 @@ public class IssuesFragment extends Fragment {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.setAdapter(adapter);
- ((RepoDetailActivity) Objects.requireNonNull(getActivity())).setFragmentRefreshListener(issueState -> {
+ ((RepoDetailActivity) requireActivity()).setFragmentRefreshListener(issueState -> {
if(issueState.equals("closed")) {
menu.getItem(1).setIcon(R.drawable.ic_filter_closed);
diff --git a/app/src/main/java/org/mian/gitnex/fragments/MilestonesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MilestonesFragment.java
index 91323f7f..ea15a89f 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/MilestonesFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/MilestonesFragment.java
@@ -27,7 +27,6 @@ import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.models.Milestones;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@@ -104,7 +103,7 @@ public class MilestonesFragment extends Fragment {
}, 50));
- ((RepoDetailActivity) Objects.requireNonNull(getActivity())).setFragmentRefreshListenerMilestone(milestoneState -> {
+ ((RepoDetailActivity) requireActivity()).setFragmentRefreshListenerMilestone(milestoneState -> {
if(milestoneState.equals("closed")) {
menu.getItem(1).setIcon(R.drawable.ic_filter_closed);
diff --git a/app/src/main/java/org/mian/gitnex/fragments/NotificationsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/NotificationsFragment.java
index a07f442a..1fb685d3 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/NotificationsFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/NotificationsFragment.java
@@ -36,7 +36,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@@ -79,7 +78,7 @@ public class NotificationsFragment extends Fragment implements NotificationsAdap
View v = inflater.inflate(R.layout.fragment_notifications, container, false);
setHasOptionsMenu(true);
- activity = Objects.requireNonNull(getActivity());
+ activity = requireActivity();
context = getContext();
tinyDB = new TinyDB(context);
diff --git a/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java b/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java
index bdf79e30..58e96a16 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java
@@ -351,6 +351,13 @@ public class RepoInfoFragment extends Fragment {
tinyDb.putBoolean("hasIssues", true);
}
+ if(repoInfo.isHas_pull_requests()) {
+ tinyDb.putBoolean("hasPullRequests", repoInfo.isHas_pull_requests());
+ }
+ else {
+ tinyDb.putBoolean("hasPullRequests", false);
+ }
+
tinyDb.putString("repoHtmlUrl", repoInfo.getHtml_url());
mProgressBar.setVisibility(View.GONE);
diff --git a/app/src/main/java/org/mian/gitnex/fragments/SearchIssuesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/SearchIssuesFragment.java
new file mode 100644
index 00000000..5bb77e07
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/fragments/SearchIssuesFragment.java
@@ -0,0 +1,190 @@
+package org.mian.gitnex.fragments;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import org.mian.gitnex.adapters.SearchIssuesAdapter;
+import org.mian.gitnex.clients.RetrofitClient;
+import org.mian.gitnex.databinding.FragmentSearchIssuesBinding;
+import org.mian.gitnex.helpers.AppUtil;
+import org.mian.gitnex.helpers.Authorization;
+import org.mian.gitnex.helpers.InfiniteScrollListener;
+import org.mian.gitnex.helpers.TinyDB;
+import org.mian.gitnex.models.Issues;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * Author M M Arif
+ */
+
+public class SearchIssuesFragment extends Fragment {
+
+ private Context ctx;
+ private TinyDB tinyDb;
+ private FragmentSearchIssuesBinding viewBinding;
+ private SearchIssuesAdapter adapter;
+ private List dataList;
+
+ private String instanceUrl;
+ private String loginUid;
+ private String instanceToken;
+
+ private int apiCallCurrentValue = 10;
+ private int pageCurrentIndex = 1;
+ private String type = "issues";
+ private String state = "open";
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ viewBinding = FragmentSearchIssuesBinding.inflate(inflater, container, false);
+ setHasOptionsMenu(true);
+
+ ctx = getContext();
+ tinyDb = new TinyDB(getContext());
+
+ instanceUrl = tinyDb.getString("instanceUrl");
+ loginUid = tinyDb.getString("loginUid");
+ instanceToken = "token " + tinyDb.getString(loginUid + "-token");
+
+ dataList = new ArrayList<>();
+ adapter = new SearchIssuesAdapter(dataList, ctx);
+
+ LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ctx);
+
+ viewBinding.recyclerViewSearchIssues.setHasFixedSize(true);
+ viewBinding.recyclerViewSearchIssues.setLayoutManager(linearLayoutManager);
+ viewBinding.recyclerViewSearchIssues.setAdapter(adapter);
+
+ viewBinding.searchKeyword.setOnEditorActionListener((v1, actionId, event) -> {
+
+ if(actionId == EditorInfo.IME_ACTION_SEND) {
+
+ if(!Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString().equals("")) {
+
+ InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(viewBinding.searchKeyword.getWindowToken(), 0);
+
+ pageCurrentIndex = 1;
+ apiCallCurrentValue = 10;
+ viewBinding.progressBar.setVisibility(View.VISIBLE);
+ loadData(false, viewBinding.searchKeyword.getText().toString());
+ }
+ }
+
+ return false;
+ });
+
+ viewBinding.recyclerViewSearchIssues.addOnScrollListener(new InfiniteScrollListener(pageCurrentIndex, linearLayoutManager) {
+
+ @Override
+ public void onScrolledToEnd(int firstVisibleItemPosition) {
+
+ pageCurrentIndex++;
+ loadData(true, Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString());
+
+ }
+ });
+
+ viewBinding.pullToRefresh.setOnRefreshListener(() -> {
+
+ pageCurrentIndex = 1;
+ apiCallCurrentValue = 10;
+ loadData(false, Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString());
+
+ });
+
+ loadData(false, "");
+
+ return viewBinding.getRoot();
+ }
+
+ private void loadData(boolean append, String searchKeyword) {
+
+ viewBinding.noData.setVisibility(View.GONE);
+
+ int apiCallDefaultLimit = 10;
+ if(apiCallDefaultLimit > apiCallCurrentValue) {
+ return;
+ }
+
+ if(pageCurrentIndex == 1 || !append) {
+
+ dataList.clear();
+ adapter.notifyDataSetChanged();
+ viewBinding.pullToRefresh.setRefreshing(false);
+ viewBinding.progressBar.setVisibility(View.VISIBLE);
+ }
+ else {
+
+ viewBinding.loadingMoreView.setVisibility(View.VISIBLE);
+ }
+
+ Call> call = RetrofitClient.getInstance(instanceUrl, getContext()).getApiInterface().queryIssues(
+ Authorization.returnAuthentication(getContext(), loginUid, instanceToken), searchKeyword, type, state, pageCurrentIndex);
+
+ call.enqueue(new Callback>() {
+
+ @Override
+ public void onResponse(@NonNull Call> call, @NonNull Response> response) {
+
+ if(response.code() == 200) {
+
+ assert response.body() != null;
+ apiCallCurrentValue = response.body().size();
+
+ if(!append) {
+
+ dataList.clear();
+ }
+
+ dataList.addAll(response.body());
+ adapter.notifyDataSetChanged();
+
+ }
+ else {
+
+ dataList.clear();
+ adapter.notifyDataChanged();
+ viewBinding.noData.setVisibility(View.VISIBLE);
+
+ }
+
+ onCleanup();
+
+ }
+
+ @Override
+ public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
+
+ Log.e("onFailure", Objects.requireNonNull(t.getMessage()));
+ onCleanup();
+
+ }
+
+ private void onCleanup() {
+
+ AppUtil.setMultiVisibility(View.GONE, viewBinding.loadingMoreView, viewBinding.progressBar);
+
+ if(dataList.isEmpty()) {
+
+ viewBinding.noData.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ }
+
+}
diff --git a/app/src/main/java/org/mian/gitnex/fragments/SettingsFragment.java b/app/src/main/java/org/mian/gitnex/fragments/SettingsFragment.java
index 2548857d..93bc84f5 100644
--- a/app/src/main/java/org/mian/gitnex/fragments/SettingsFragment.java
+++ b/app/src/main/java/org/mian/gitnex/fragments/SettingsFragment.java
@@ -1,6 +1,8 @@
package org.mian.gitnex.fragments;
+import android.content.ActivityNotFoundException;
import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -17,7 +19,6 @@ import org.mian.gitnex.activities.SettingsReportsActivity;
import org.mian.gitnex.activities.SettingsSecurityActivity;
import org.mian.gitnex.activities.SettingsTranslationActivity;
import org.mian.gitnex.helpers.TinyDB;
-import java.util.Objects;
/**
* Author M M Arif
@@ -37,6 +38,8 @@ public class SettingsFragment extends Fragment {
LinearLayout securityFrame = v.findViewById(R.id.securityFrame);
LinearLayout languagesFrame = v.findViewById(R.id.languagesFrame);
LinearLayout reportsFrame = v.findViewById(R.id.reportsFrame);
+ LinearLayout rateAppFrame = v.findViewById(R.id.rateAppFrame);
+ LinearLayout aboutAppFrame = v.findViewById(R.id.aboutAppFrame);
appearanceFrame.setOnClickListener(v1 -> startActivity(new Intent(getContext(), SettingsAppearanceActivity.class)));
@@ -50,10 +53,24 @@ public class SettingsFragment extends Fragment {
reportsFrame.setOnClickListener(v1 -> startActivity(new Intent(getContext(), SettingsReportsActivity.class)));
+ rateAppFrame.setOnClickListener(aboutApp -> rateThisApp());
+
+ aboutAppFrame.setOnClickListener(aboutApp -> requireActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AboutFragment()).commit());
+
return v;
}
+ public void rateThisApp() {
+
+ try {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + requireActivity().getPackageName())));
+ }
+ catch(ActivityNotFoundException e) {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + requireActivity().getPackageName())));
+ }
+ }
+
@Override
public void onResume() {
@@ -62,8 +79,8 @@ public class SettingsFragment extends Fragment {
TinyDB tinyDb = new TinyDB(getContext());
if(tinyDb.getBoolean("refreshParent")) {
- Objects.requireNonNull(getActivity()).recreate();
- getActivity().overridePendingTransition(0, 0);
+ requireActivity().recreate();
+ requireActivity().overridePendingTransition(0, 0);
tinyDb.putBoolean("refreshParent", false);
}
diff --git a/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java b/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java
index 79b37417..6eedfa4b 100644
--- a/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java
+++ b/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java
@@ -76,6 +76,10 @@ public class AppUtil {
}
}
+ public static boolean isPro(Context context) {
+ return context.getPackageName().equals("org.mian.gitnex.pro");
+ }
+
public int charactersLength(String str) {
return str.length();
diff --git a/app/src/main/java/org/mian/gitnex/helpers/ClickListener.java b/app/src/main/java/org/mian/gitnex/helpers/ClickListener.java
index 8c950a95..78a298ff 100644
--- a/app/src/main/java/org/mian/gitnex/helpers/ClickListener.java
+++ b/app/src/main/java/org/mian/gitnex/helpers/ClickListener.java
@@ -3,7 +3,6 @@ package org.mian.gitnex.helpers;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import org.mian.gitnex.R;
@@ -18,17 +17,16 @@ public class ClickListener implements View.OnClickListener {
private Context mCtx;
public ClickListener(String infoText, Context mCtx) {
+
this.infoText = infoText;
this.mCtx = mCtx;
}
@Override
- public void onClick(View v)
- {
+ public void onClick(View v) {
LayoutInflater inflater1 = LayoutInflater.from(mCtx);
- View layout = inflater1.inflate(R.layout.custom_toast_success,
- (ViewGroup) v.findViewById(R.id.custom_toast_container));
+ View layout = inflater1.inflate(R.layout.custom_toast_info, v.findViewById(R.id.custom_toast_container));
TextView text = layout.findViewById(R.id.toastText);
text.setText(infoText);
diff --git a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java
index 6d109af7..dcf3ab38 100644
--- a/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java
+++ b/app/src/main/java/org/mian/gitnex/interfaces/ApiInterface.java
@@ -7,6 +7,7 @@ import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Commits;
import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.CreateLabel;
+import org.mian.gitnex.models.CreatePullRequest;
import org.mian.gitnex.models.DeleteFile;
import org.mian.gitnex.models.EditFile;
import org.mian.gitnex.models.Emails;
@@ -19,6 +20,7 @@ import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.MergePullRequest;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.models.NewFile;
+import org.mian.gitnex.models.NotificationCount;
import org.mian.gitnex.models.NotificationThread;
import org.mian.gitnex.models.OrgOwner;
import org.mian.gitnex.models.Organization;
@@ -93,7 +95,7 @@ public interface ApiInterface {
Call markNotificationThreadsAsRead(@Header("Authorization") String token, @Query("last_read_at") String last_read_at, @Query("all") Boolean all, @Query("status-types") String[] statusTypes, @Query("to-status") String toStatus);
@GET("notifications/new") // Check if unread notifications exist
- Call checkUnreadNotifications(@Header("Authorization") String token);
+ Call checkUnreadNotifications(@Header("Authorization") String token);
@GET("notifications/threads/{id}") // Get notification thread by ID
Call getNotificationThread(@Header("Authorization") String token, @Path("id") Integer id);
@@ -264,7 +266,10 @@ public interface ApiInterface {
Call> getRepoWatchers(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@GET("repos/search") // get all the repos which match the query string
- Call queryRepos(@Header("Authorization") String token, @Query("q") String searchKeyword, @Query("private") Boolean repoTypeInclude, @Query("sort") String sort, @Query("order") String order, @Query("limit") int limit);
+ Call queryRepos(@Header("Authorization") String token, @Query("q") String searchKeyword, @Query("private") Boolean repoTypeInclude, @Query("sort") String sort, @Query("order") String order, @Query("topic") boolean topic, @Query("includeDesc") boolean includeDesc, @Query("template") boolean template, @Query("archived") boolean archived, @Query("limit") int limit, @Query("page") int page);
+
+ @GET("repos/issues/search") // get all the issues which match the query string
+ Call> queryIssues(@Header("Authorization") String token, @Query("q") String searchKeyword, @Query("type") String type, @Query("state") String state, @Query("page") int page);
@POST("repos/{owner}/{repo}/contents/{file}") // create new file
Call createNewFile(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("file") String fileName, @Body NewFile jsonStr);
@@ -320,6 +325,9 @@ public interface ApiInterface {
@POST("repos/{owner}/{repo}/pulls/{index}/merge") // merge a pull request
Call mergePullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("index") int index, @Body MergePullRequest jsonStr);
+ @POST("repos/{owner}/{repo}/pulls") // create a pull request
+ Call createPullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Body CreatePullRequest jsonStr);
+
@GET("repos/{owner}/{repo}/commits") // get all commits
Call> getRepositoryCommits(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("sha") String branchName, @Query("limit") int limit);
diff --git a/app/src/main/java/org/mian/gitnex/models/CreatePullRequest.java b/app/src/main/java/org/mian/gitnex/models/CreatePullRequest.java
new file mode 100644
index 00000000..91c4b074
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/models/CreatePullRequest.java
@@ -0,0 +1,36 @@
+package org.mian.gitnex.models;
+
+import java.util.ArrayList;
+
+/**
+ * Author M M Arif
+ */
+
+public class CreatePullRequest {
+
+ private String title;
+ private String body;
+ private String assignee;
+ private String base;
+ private String head;
+ private int milestone;
+ private String due_date;
+ private String message;
+
+ private ArrayList assignees;
+ private ArrayList labels;
+
+ public CreatePullRequest(String title, String body, String assignee, String base, String head, int milestone, String due_date, ArrayList assignees, ArrayList labels) {
+
+ this.title = title;
+ this.body = body;
+ this.assignee = assignee;
+ this.base = base; // merge into branch
+ this.head = head; // pull from branch
+ this.milestone = milestone;
+ this.due_date = due_date;
+ this.assignees = assignees;
+ this.labels = labels;
+ }
+
+}
diff --git a/app/src/main/java/org/mian/gitnex/models/Issues.java b/app/src/main/java/org/mian/gitnex/models/Issues.java
index 940592a8..b5269176 100644
--- a/app/src/main/java/org/mian/gitnex/models/Issues.java
+++ b/app/src/main/java/org/mian/gitnex/models/Issues.java
@@ -27,6 +27,7 @@ public class Issues {
private pullRequestObject pull_request;
private milestoneObject milestone;
private List assignees;
+ private repositoryObject repository;
public Issues(String body) {
this.body = body;
@@ -193,6 +194,35 @@ public class Issues {
}
}
+ public static class repositoryObject {
+
+ private int id;
+ private String full_name;
+ private String name;
+ private String owner;
+
+ public int getId() {
+
+ return id;
+ }
+
+ public String getFull_name() {
+
+ return full_name;
+ }
+
+ public String getName() {
+
+ return name;
+ }
+
+ public String getOwner() {
+
+ return owner;
+ }
+
+ }
+
public int getId() {
return id;
}
@@ -267,4 +297,9 @@ public class Issues {
this.html_url = html_url;
}
+ public repositoryObject getRepository() {
+
+ return repository;
+ }
+
}
diff --git a/app/src/main/java/org/mian/gitnex/models/Labels.java b/app/src/main/java/org/mian/gitnex/models/Labels.java
index 0569a8f9..87ca1aaa 100644
--- a/app/src/main/java/org/mian/gitnex/models/Labels.java
+++ b/app/src/main/java/org/mian/gitnex/models/Labels.java
@@ -21,6 +21,11 @@ public class Labels {
this.labels = labels;
}
+ public Labels(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
public int getId() {
return id;
}
diff --git a/app/src/main/java/org/mian/gitnex/models/NotificationCount.java b/app/src/main/java/org/mian/gitnex/models/NotificationCount.java
new file mode 100644
index 00000000..840a00cb
--- /dev/null
+++ b/app/src/main/java/org/mian/gitnex/models/NotificationCount.java
@@ -0,0 +1,19 @@
+package org.mian.gitnex.models;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Author M M Arif
+ */
+
+public class NotificationCount {
+
+ @SerializedName("new")
+ private int counter;
+
+ public int getCounter() {
+
+ return counter;
+ }
+
+}
diff --git a/app/src/main/res/drawable/app_logo_background.xml b/app/src/main/res/drawable/app_logo_background.xml
index fd4d71c7..e009ebe7 100644
--- a/app/src/main/res/drawable/app_logo_background.xml
+++ b/app/src/main/res/drawable/app_logo_background.xml
@@ -1,46 +1,78 @@
+
-
-
-
-
-
-
-
-
-
-
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_create_pr.xml b/app/src/main/res/layout/activity_create_pr.xml
new file mode 100644
index 00000000..72dae40a
--- /dev/null
+++ b/app/src/main/res/layout/activity_create_pr.xml
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_profile_email.xml b/app/src/main/res/layout/activity_profile_email.xml
index 1a5287b9..36a60dce 100644
--- a/app/src/main/res/layout/activity_profile_email.xml
+++ b/app/src/main/res/layout/activity_profile_email.xml
@@ -1,8 +1,8 @@
-
@@ -50,27 +50,30 @@
android:padding="16dp"
android:orientation="vertical">
-
-
-
+ app:hintTextColor="?attr/hintColor"
+ app:boxStrokeErrorColor="@color/darkRed"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ app:endIconMode="clear_text"
+ app:endIconTint="?attr/iconsColor"
+ android:hint="@string/profileEmailTitle">
+
+
+
+
-
+
diff --git a/app/src/main/res/layout/fragment_explore.xml b/app/src/main/res/layout/fragment_explore.xml
new file mode 100644
index 00000000..652f3dad
--- /dev/null
+++ b/app/src/main/res/layout/fragment_explore.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_explore_repo.xml b/app/src/main/res/layout/fragment_explore_repo.xml
index a5d1035d..94235585 100644
--- a/app/src/main/res/layout/fragment_explore_repo.xml
+++ b/app/src/main/res/layout/fragment_explore_repo.xml
@@ -7,30 +7,58 @@
android:orientation="vertical">
+
+
-
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="10dp">
+
+
+
+
+
+
+
+
-
+ android:layout_height="match_parent">
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_repo_info.xml b/app/src/main/res/layout/fragment_repo_info.xml
index d4ccea8a..2c447b88 100644
--- a/app/src/main/res/layout/fragment_repo_info.xml
+++ b/app/src/main/res/layout/fragment_repo_info.xml
@@ -272,7 +272,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
index 399f1ce8..af07824b 100644
--- a/app/src/main/res/layout/fragment_settings.xml
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -5,7 +5,7 @@
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
-
@@ -208,8 +208,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/app/src/main/res/layout/list_issues.xml b/app/src/main/res/layout/list_issues.xml
index 6cb864ac..ce2d427d 100644
--- a/app/src/main/res/layout/list_issues.xml
+++ b/app/src/main/res/layout/list_issues.xml
@@ -12,6 +12,12 @@
android:layout_height="wrap_content"
android:visibility="invisible" />
+
+
diff --git a/app/src/main/res/menu/drawer_menu.xml b/app/src/main/res/menu/drawer_menu.xml
index 5d517bbe..22a04944 100644
--- a/app/src/main/res/menu/drawer_menu.xml
+++ b/app/src/main/res/menu/drawer_menu.xml
@@ -1,6 +1,7 @@
Collaboratori
Pull Requests
Nessun problema trovato
- Sito Web
Dimensione
Branch predefinito
SSH URL
@@ -421,7 +424,6 @@ autorizzazione
Al momento non possiamo raggiungere il server, controlla lo stato del tuo server e riprova
Copy URL
- Traduci GitNex con Crowdin
Esplora i repository
Repository star
Unstar Repository
@@ -506,7 +508,7 @@ autorizzazione
Abilita Rapporti Crash
GitNex ha smesso di funzionare :(
Rapporti crash
- Puoi premere il pulsante OK per inviare la segnalazione di crash via email. Aiuterà a risolvere il problema :)\n\nPuoi anche aggiungere altri dettagli nell\'email. Grazie!
+ It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you!
Per favore accedi di nuovo
A causa di alcune modifiche importanti riguardanti il funzionamento interno dell\'app, abbiamo bisogno che tu effettui nuovamente il login. Queste modifiche ci permettono di rendere l\'applicazione più flessibile in futuro.\n\nGrazie per la pazienza e ci scusiamo per il disagio.
Elimina Tutte Le Bozze
@@ -520,6 +522,8 @@ autorizzazione
Certificati SSL, cache, ricerca di notifiche
Lingue
Rapporti crash
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Archiviato
Account eliminato con successo
Remove Account
@@ -562,4 +566,26 @@ autorizzazione
Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
Repository name does not match
Repository deleted successfully
+ Transfer Ownership
+ Transfer this repository to a user or to an organization for which you have administrator rights
+ Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation
+ Perform Transfer
+ New Owner
+ Repository transferred successfully
+ New owner is required
+ There is a problem with the owner name. Make sure that the new owner exists
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml
index b32a4be4..2018a98b 100644
--- a/app/src/main/res/values-lv/strings.xml
+++ b/app/src/main/res/values-lv/strings.xml
@@ -12,6 +12,7 @@
Logout
Izpētīt
Administration
+ Search Issues
Par
@@ -37,6 +38,7 @@
Izpētīt
Gitea Administration
Manage Accounts
+ New Pull Request
Demo repo
Repo with ORG
@@ -62,6 +64,7 @@
Open Navigation Drawer
Close Navigation Drawer
Login to Gitea
+ Protocol
1- Choose the correct protocol(https or http). \n2- Enter Gitea url e.g: try.gitea.io. \n3- If you have enabled 2FA for your account, enter the code in the OTP Code field. \n4- For HTTP basic auth use USERNAME@DOMAIN.COM in the URL field.
Couldn\'t connect to host. Please check your URL or port for any errors
It is not recommended to use HTTP protocol unless you are testing on local network
@@ -69,6 +72,7 @@
Instance URL is required
Username is required
Password is required
+ Protocol is required
Cannot access network, please check your Internet connection
Yay, We have Internet connection!
Repository name is empty
@@ -106,7 +110,6 @@
Collaborators
Pull Requests
No issues found
- Website
Size
Default Branch
SSH URL
@@ -419,7 +422,6 @@
We cannot reach the server at the moment, please check your server status and try again
Copy URL
- Translate GitNex with Crowdin
Explore repositories
Star Repository
Unstar Repository
@@ -504,7 +506,7 @@
Enable Crash Reports
GitNex has stopped :(
Crash reports
- You can tap the OK button to send the crash report by email. It will help to fix it :)\n\nYou can also add additional content in the email. Thank you!
+ It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you!
Please sign in again
Due to some major changes regarding the internal functioning of the app, we require you to login again. These changes allow us to make the app more flexible in the future.\n\nThank you for your patience and sorry for the inconvenience.
Delete All Drafts
@@ -518,6 +520,8 @@
SSL certificates, cache, polling delay
Languages
Crash reports
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Archived
Account deleted successfully
Remove Account
@@ -560,4 +564,26 @@
Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
Repository name does not match
Repository deleted successfully
+ Transfer Ownership
+ Transfer this repository to a user or to an organization for which you have administrator rights
+ Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation
+ Perform Transfer
+ New Owner
+ Repository transferred successfully
+ New owner is required
+ There is a problem with the owner name. Make sure that the new owner exists
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index c0b19c4c..d7ee0eaa 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -12,6 +12,7 @@
Wyloguj się
Przeglądaj
Administration
+ Search Issues
O programie
@@ -37,6 +38,7 @@
Przeglądaj
Gitea Administration
Manage Accounts
+ New Pull Request
Repozytorium demo
Repozytorium z ORG
@@ -62,6 +64,7 @@
Otwórz szufladę nawigacji
Zamknij szufladę nawigacji
Zaloguj się do Gitea
+ Protocol
1- Wybierz poprawny protokół (https lub http). \n2- Wprowadź adres URL Gitea np: try.gitea.io. \n3- Jeśli włączyłeś 2FA dla swojego konta, wprowadź kod w polu OTP Code. \n4 - Dla podstawowej autoryzacji HTTP użyj NAZWAUŻYTKOWNIKA@STRONA.PL w polu URL.
Couldn\'t connect to host. Please check your URL or port for any errors
It is not recommended to use HTTP protocol unless you are testing on local network
@@ -69,6 +72,7 @@
Adres URL instancji jest wymagany
Nazwa użytkownika jest wymagana
Hasło jest wymagane
+ Protocol is required
Nie można uzyskać dostępu do sieci, sprawdź swoje połączenie internetowe
Jej, mamy połączenie z Internetem!
Nazwa repozytorium jest pusta
@@ -106,7 +110,6 @@
Współpracownicy
Pull Requesty
Nie znaleziono problemów
- Strona internetowa
Rozmiar
Domyślna gałąź
Adres URL SSH
@@ -419,7 +422,6 @@
We cannot reach the server at the moment, please check your server status and try again
Copy URL
- Przetłumacz GitNex z Crowdin
Przeglądaj repozytoria
Ogwiazdkuj repozytorium
Odgwiazdkuj repozytorium
@@ -504,7 +506,7 @@
Włącz raporty awarii
GitNex zatrzymał się :(
Raporty awarii
- Możesz nacisnąć przycisk OK, aby wysłać raport o awarii pocztą elektroniczną. Pomoże to naprawić to :)\n\nMożesz również dodać dodatkowe treści w wiadomości e-mail. Dziękujemy!
+ It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you!
Please sign in again
Due to some major changes regarding the internal functioning of the app, we require you to login again. These changes allow us to make the app more flexible in the future.\n\nThank you for your patience and sorry for the inconvenience.
Delete All Drafts
@@ -518,6 +520,8 @@
SSL certificates, cache, polling delay
Languages
Crash reports
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Archived
Account deleted successfully
Remove Account
@@ -560,4 +564,26 @@
Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
Repository name does not match
Repository deleted successfully
+ Transfer Ownership
+ Transfer this repository to a user or to an organization for which you have administrator rights
+ Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation
+ Perform Transfer
+ New Owner
+ Repository transferred successfully
+ New owner is required
+ There is a problem with the owner name. Make sure that the new owner exists
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 9fdcd713..04c11ba0 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -12,6 +12,7 @@
Sair
Explorar
Administração
+ Search Issues
Sobre
@@ -37,6 +38,7 @@
Explorar
Administração de Gitea
Gerenciar contas
+ New Pull Request
Repo demo
Repo com ORG
@@ -62,6 +64,7 @@
Abrir painel de navegação
Fechar painel de navegação
Conectar no Gitea
+ Protocol
1- Escolha o protocolo correto (https ou http). \n2- Insira a url do Gitea. Por exemplo: try.gitea.io. \n3 - Se você habilitou 2FA para sua conta, digite o código no campo de código OTP. \n4- Para autenticação básica HTTP use USUARIO@DOMINIO.COM no campo URL.
Não foi possível conectar-se ao host. Por favor verifique sua URL ou porta para ver se há algum erro
Não é recomendado usar o protocolo HTTP a menos que você esteja testando na rede local
@@ -69,6 +72,7 @@
A URL da instância é necessária
Nome de usuário é necessário
A senha é necessária
+ Protocol is required
Não é possível acessar a rede, por favor, verifique sua conexão com a Internet
Opa, temos conexão com a Internet!
Nome do repositório está vazio
@@ -106,7 +110,6 @@
Colaboradores
Pull requests
Nenhum incidente encontrado
- Site da Web
Tamanho
Branch padrão
URL de SSH
@@ -419,7 +422,6 @@
Não conseguimos encontrar o servidor no momento, por favor, verifique o status do seu servidor e tente novamente
Copiar URL
- Traduza o GitNex com Crowdin
Explorar repositórios
Favoritar repositório
Desfavoritar repositório
@@ -504,7 +506,7 @@
Ativar relatórios de erros
GitNex parou :(
Relatórios de erros
- Você pode tocar no botão OK para enviar o relatório de erro por e-mail. Ajudará a consertá-lo :)\n\nVocê também pode adicionar conteúdo adicional no e-mail. Obrigado!
+ It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you!
Por favor, faça o login novamente
Devido a algumas mudanças principais no funcionamento interno do aplicativo, exigimos que você faça o login novamente. Essas alterações nos permitem tornar o aplicativo mais flexível no futuro.\n\nAgradecemos por sua paciência e lamentamos o inconveniente.
Excluir Todos os Rascunhos
@@ -518,6 +520,8 @@
Certificados SSL, cache e atraso de pesquisa
Idiomas
Relatórios de erros
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Arquivado
Conta excluída com êxito
Excluir Conta
@@ -560,4 +564,26 @@
Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
Repository name does not match
Repository deleted successfully
+ Transfer Ownership
+ Transfer this repository to a user or to an organization for which you have administrator rights
+ Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation
+ Perform Transfer
+ New Owner
+ Repository transferred successfully
+ New owner is required
+ There is a problem with the owner name. Make sure that the new owner exists
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 55c08066..2e273c46 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -12,6 +12,7 @@
Выход
Обзор
Администрирование
+ Search Issues
О программе
@@ -37,6 +38,7 @@
Обзор
Администрирование Gitea
Управление аккаунтами
+ New Pull Request
Демо репозиторий
Репозиторий с организацией
@@ -62,6 +64,7 @@
Открыть навигацию
Закрыть навигацию
Войти в Gitea
+ Protocol
1. Выберите протокол (https или http) \n2. Укажите URL Gitea, например: try.gitea.io \n3. Если для учетной записи включена 2FA, введите код OTP в соответствующее поле. \n4. Для базовой аутентификации HTTP укажите USERNAME@DOMAIN.COM в поле URL.
Не удалось подключиться к хосту. Пожалуйста, проверьте URL-адрес или порт на наличие ошибок
Не рекомендуется использовать протокол HTTP, если вы не тестируете в локальной сети
@@ -69,6 +72,7 @@
Требуется URL экземпляра
Требуется имя пользователя
Требуется пароль
+ Protocol is required
Нет подключения к интернету, проверьте наличие связи.
Ура, у нас есть интернет!
Название репозитория пустое.
@@ -106,7 +110,6 @@
Сотрудники
Запросы на слияние
Задач не обнаружено
- Сайт
Размер
Ветка по умолчанию
SSH/URL
@@ -419,7 +422,6 @@
На данный момент мы не можем подключиться к серверу, пожалуйста, проверьте статус вашего сервера и повторите попытку
Копировать URL
- Перевести GitNex на Crowdin
Просмотреть репозитории
Репозиторий в избранное
Убрать из избранного
@@ -504,7 +506,7 @@
Включить отчёты об ошибках
GitNex остановлен :(
Отчёты об ошибках
- Вы можете нажать на кнопку ОК, чтобы отправить отчёт об ошибке по электронной почте. Это поможет исправить это :)\n\nВы также можете добавить дополнительный контент в электронную почту. Спасибо!
+ It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you!
Пожалуйста, войдите снова
В связи с некоторыми существенными изменениями, касающимися внутренней работы приложения, мы просим вас снова войти в систему. Эти изменения позволяют сделать приложение более гибким в будущем.\n\nБлагодарим вас за терпение и приносим извинения за неудобства.
Удалить все черновики
@@ -518,6 +520,8 @@
SSL-сертификаты, кэш, задержка опроса
Языки
Отчёты об ошибках
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Архивировано
Учётная запись успешно удалена
Удалить учётную запись
@@ -560,4 +564,26 @@
Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
Repository name does not match
Repository deleted successfully
+ Transfer Ownership
+ Transfer this repository to a user or to an organization for which you have administrator rights
+ Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation
+ Perform Transfer
+ New Owner
+ Repository transferred successfully
+ New owner is required
+ There is a problem with the owner name. Make sure that the new owner exists
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml
index 12165a71..a2efc188 100644
--- a/app/src/main/res/values-sr/strings.xml
+++ b/app/src/main/res/values-sr/strings.xml
@@ -12,6 +12,7 @@
Одјави ме
Претражи репозиторијуме
Administration
+ Search Issues
О програму
@@ -37,6 +38,7 @@
Претражи репозиторијуме
Gitea Administration
Manage Accounts
+ New Pull Request
Демо репозиторијум
Репозиторијум са ORG
@@ -62,6 +64,7 @@
Отвори навигацију
Затвори навигацију
Пријави ме
+ Protocol
1. Одабери одговарајући протокол (HTTPS или HTTP).\n2. Унеси URL инстанце, нпр. try.gitea.io.\n3. Ако користиш 2FA, унеси OTP код.\n4. Ако користиш HTTP протокол, унеси URL инстанце у формату korisnickoime@domen.com.
Couldn\'t connect to host. Please check your URL or port for any errors
It is not recommended to use HTTP protocol unless you are testing on local network
@@ -69,6 +72,7 @@
URL инстанце је обавезан
Корисничко име је обавезно
Лозинка је обавезна
+ Protocol is required
Не могу да приступим мрежи, провери интернет конекцију
Yay, We have Internet connection!
Назив репозиторијума је обавезан
@@ -106,7 +110,6 @@
Сарадници
Пул захтеви
Ниједан задатак није пронађен
- Веб-сајт
Величина
Подразумевана грана
SSH URL
@@ -419,7 +422,6 @@
We cannot reach the server at the moment, please check your server status and try again
Copy URL
- Преведи GitNex на платформи Crowdin
Претражи репозиторијуме
Додај у омиљене
Уклони из омиљених
@@ -504,7 +506,7 @@
Enable Crash Reports
GitNex has stopped :(
Crash reports
- You can tap the OK button to send the crash report by email. It will help to fix it :)\n\nYou can also add additional content in the email. Thank you!
+ It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you!
Please sign in again
Due to some major changes regarding the internal functioning of the app, we require you to login again. These changes allow us to make the app more flexible in the future.\n\nThank you for your patience and sorry for the inconvenience.
Delete All Drafts
@@ -518,6 +520,8 @@
SSL certificates, cache, polling delay
Languages
Crash reports
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Archived
Account deleted successfully
Remove Account
@@ -560,4 +564,26 @@
Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
Repository name does not match
Repository deleted successfully
+ Transfer Ownership
+ Transfer this repository to a user or to an organization for which you have administrator rights
+ Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation
+ Perform Transfer
+ New Owner
+ Repository transferred successfully
+ New owner is required
+ There is a problem with the owner name. Make sure that the new owner exists
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index 269d339c..095aa684 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -12,6 +12,7 @@
Çıkış Yap
Keşfet
Administration
+ Search Issues
Hakkında
@@ -37,6 +38,7 @@
Keşfet
Gitea Administration
Manage Accounts
+ New Pull Request
Demo deposu
ORG ile Depo
@@ -62,6 +64,7 @@
Gezinme Çekmecesini Aç
Gezinme Çekmecesini Kapat
Gitea\'ya Giriş Yap
+ Protocol
1- Doğru protokolü seçin (https veya http). \n2- Gitea url girin, örneğin: try.gitea.io. \n3- Hesabınız için 2FA\'yı etkinleştirdiyseniz, kodu OTP Kodu alanına girin. \n4- HTTP temel kimlik doğrulaması için, URL alanında KULLANICIADI@DOMAIN.COM adresini kullanın.
Couldn\'t connect to host. Please check your URL or port for any errors
It is not recommended to use HTTP protocol unless you are testing on local network
@@ -69,6 +72,7 @@
Örnek URL gerekli
Kullanıcı adı gerekli
Parola gerekli
+ Protocol is required
Ağa erişilemiyor, lütfen internet bağlantınızı kontrol edin
Yay, We have Internet connection!
Depo adı boş
@@ -106,7 +110,6 @@
İşbirlikçiler
İstekleri Çek
Konu bulunamadı
- Website
Boyut
Varsayılan Dal
SSH Adresi
@@ -419,7 +422,6 @@
We cannot reach the server at the moment, please check your server status and try again
Copy URL
- Crowdin\'de GitNex için Çeviri Yap
Depoları keşfet
Depoyu Yıldızla
Depo Yıldızını Kaldır
@@ -504,7 +506,7 @@
Enable Crash Reports
GitNex has stopped :(
Crash reports
- You can tap the OK button to send the crash report by email. It will help to fix it :)\n\nYou can also add additional content in the email. Thank you!
+ It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you!
Please sign in again
Due to some major changes regarding the internal functioning of the app, we require you to login again. These changes allow us to make the app more flexible in the future.\n\nThank you for your patience and sorry for the inconvenience.
Delete All Drafts
@@ -518,6 +520,8 @@
SSL certificates, cache, polling delay
Languages
Crash reports
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Archived
Account deleted successfully
Remove Account
@@ -560,4 +564,26 @@
Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
Repository name does not match
Repository deleted successfully
+ Transfer Ownership
+ Transfer this repository to a user or to an organization for which you have administrator rights
+ Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation
+ Perform Transfer
+ New Owner
+ Repository transferred successfully
+ New owner is required
+ There is a problem with the owner name. Make sure that the new owner exists
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 786f6510..837d70b4 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -12,6 +12,7 @@
Вийти
Огляд
Адміністрування
+ Search Issues
Про додаток
@@ -37,6 +38,7 @@
Огляд
Адміністрування Gitea
Manage Accounts
+ New Pull Request
Демо-репозиторій
Репозиторій з організацією
@@ -62,6 +64,7 @@
Відкрити панель навігації
Закрити панель навігації
Увійти до Gitea
+ Protocol
1. Оберіть правильний протокол (https або http). \n2. Введіть URL Gitea, наприклад: try.gitea.io. \n3. Якщо для вашого облікового запису увімкнено двофакторну аутентифікацію, введіть код OTP у відповідне поле. \n4. Для базової автентифікації HTTP використовуйте USERNAME@DOMAIN.COM в полі URL.
Couldn\'t connect to host. Please check your URL or port for any errors
It is not recommended to use HTTP protocol unless you are testing on local network
@@ -69,6 +72,7 @@
Потрібен URL екземпляра
Ім\'я користувача є обов\'язковим
Пароль є обов\'язковим
+ Protocol is required
Неможливо отримати доступ до мережі, будь ласка, перевірте підключення до Інтернету
Ура! Ми маємо підключення до Інтернету!
Назва репозиторія порожня
@@ -106,7 +110,6 @@
Співавтори
Запити на злиття
Проблем не знайдено
- Веб-сайт
Розмір
Головна гілка
URL SSH
@@ -419,7 +422,6 @@
На даний момент ми не можемо зв\'язатися з сервером, будь ласка, перевірте статус вашого сервера і спробуйте ще раз
Copy URL
- Перекласти GitNex на Crowdin
Переглянути репозиторії
Репозиторій у обране
Вилучити репозиторій з обраного
@@ -504,7 +506,7 @@
Увімкнути повідомлення про падіння
GitNex зупинено :(
Звіти про падіння
- Ви можете натиснути ОК кнопку, щоб надіслати звіт про аварію електронною поштою. Це допоможе виправити проблему :)\n\nВи також можете прикріпити додатковий вміст до листа. Дякуємо!
+ It is encouraged to open an issue at the project repository with how to reproduce this bug. It is easier to debug and fix the problem that way.\n\nTap the OK button to send the crash report by email instead. Additional content could be added in the email.\nThank you!
Please sign in again
Due to some major changes regarding the internal functioning of the app, we require you to login again. These changes allow us to make the app more flexible in the future.\n\nThank you for your patience and sorry for the inconvenience.
Delete All Drafts
@@ -518,6 +520,8 @@
SSL certificates, cache, polling delay
Мови
Звіти про падіння
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Архівовано
Account deleted successfully
Remove Account
@@ -560,4 +564,26 @@
Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
Repository name does not match
Repository deleted successfully
+ Transfer Ownership
+ Transfer this repository to a user or to an organization for which you have administrator rights
+ Things to know before transfer:\n\n- You will lose access to the repository if you transfer it to an individual user.\n- You will keep access to the repository if you transfer it to an organization that you (co-)own.\n\nEnter the repository name as confirmation
+ Perform Transfer
+ New Owner
+ Repository transferred successfully
+ New owner is required
+ There is a problem with the owner name. Make sure that the new owner exists
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index e9511eac..dbc8db06 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -12,6 +12,7 @@
退出
探索
管理
+ 搜索问题
关于
@@ -37,6 +38,7 @@
探索
Gitea 管理
管理账户
+ 新拉取请求
演示仓库
有组织的存储库
@@ -62,6 +64,7 @@
打开导航栏
关闭导航栏
登录到 Gitea
+ 协议
1- 选择协议 (https 或 http). \n2- 输入Gitea访问地址(可带端口) 例如: try.gitea.io:3000. \n3- 如已启用双重验证,请在OTP输入有效代码。 \n4- 在 URL 字段中使用 USERNAME@DOMAIN.COM 进行 HTTP 基本身份验证。
无法连接到主机。请检查您的 URL 或端口是否有任何错误
除非您正在本地网络上测试,否则不建议使用 HTTP 协议
@@ -69,6 +72,7 @@
未填写 Gitea访问地址
未填写 用户名
未填写 密码
+ 协议是必需的
无法连接,请检查您的网络情况
有网了,奥力给!
仓库名称为空
@@ -106,7 +110,6 @@
协作者
拉取请求
没有工单
- 网站
尺寸
默认分支
SSH URL
@@ -258,7 +261,7 @@
访问控制
成员可以查看并克隆团队仓库
会员可以读取并推送到团队仓库
- 会员可以拉取和推送到团队仓库并添加合作者
+ 成员可以拉取和推送到团队仓库并添加合作者
请输入团队名称
团队名称只能包含字母数字、 破折号 (-), 下划线 (_) 和 dot (.) 字符
请选择权限
@@ -419,7 +422,6 @@
目前我们无法访问服务器,请检查您的服务器状态,然后重试
复制 URL
- 使用 Crowdin 翻译 GitNex
探索仓库
星级仓库
从仓库中删除星星
@@ -456,8 +458,8 @@
该分支属于一个分叉存储库
合并评论
拉取请求已成功合并
- 拉取请求不可用于合并
- 合并请求
+ 用于合并的拉取请求不可用
+ 合并拉取请求
重建并合并
重建合并 (--no-ff)
压缩提交并合并
@@ -476,7 +478,7 @@
分享拉取请求
共享存储库
创建仓库
- Commits
+ 提交
由 %1$s提交
查看提交
@@ -504,7 +506,7 @@
启用崩溃报告
GitNex 已停止 :(
崩溃报告
- 您可以点击确定按钮通过电子邮件发送崩溃报告。 这将有助于修复它:)\n\n您也可以在电子邮件中添加额外的内容。谢谢!
+ 鼓励在项目存储库中提出一个问题,并说明如何重现这个bug。这样更容易调试和修复问题。\n\n点击OK按钮,通过电子邮件发送崩溃报告。可以在电子邮件中添加其他内容,\n谢谢!
请重新登录
由于应用内部功能发生了一些重大变化,我们要求您重新登录。这些变化使我们能够使应用程序在未来更具灵活性。\n\n感谢您的耐心,对给您带来的不便我们深表歉意
删除所有草稿
@@ -518,6 +520,8 @@
SSL 证书、缓存、轮询延迟
语言
崩溃报告
+ 如果你喜欢GitNex,你可以给它点赞
+ 应用程序版本、构建、用户gitea版本
已存档
帐户删除成功
删除账户
@@ -541,23 +545,45 @@
成功将所有通知标记为已读
已读
未读
- Repository Settings
- Edit Properties
- Delete Repository
- Be careful, this operation CANNOT be undone!
- Set as Template
- Enable Issues
- External Issue Tracker Url
- Enable Wiki
- External Wiki Url
- Enable Pull Requests
- Enable Time Tracker
- Enable Merge Commits
- Enable Rebase
- Enable Squash and Merge
- Enable Rebase with Merge Commits (——no-ff)
- Repository properties updated successfully
- Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation
- Repository name does not match
- Repository deleted successfully
+ 存储库设置
+ 编辑属性
+ 删除存储库
+ 小心,这个操作无法撤销!
+ 设置为模板
+ 启用问题
+ 外部问题跟踪网址
+ 启用 Wiki
+ 外部 Wiki 网址
+ 允许拉取请求
+ 启用时间追踪器
+ 启用合并提交
+ 启用代码变基
+ 启用压扁和合并
+ 用合并提交(——no-ff)启用代码变基
+ 成功更新存储库属性
+ 删除前要知道的事:\n\n-此操作无法撤消。\n-此操作将永久删除存储库,包括代码、问题、注释、Wiki数据和协作者设置。\n\n输入存储库名称作为确认
+ 存储库名称不匹配
+ 成功删除存储库
+ 转移所有权
+ 将此存储库传输给您具有管理员权限的用户或组织
+ 转移所有权之前需要注意的事项:\n\n- 如果将存储库移交给单个用户,您将失去对该存储库的访问权。\n- 如果您将存储库转移到您和他人(共同)拥有的组织,那么您将保留对该存储库的访问权。\n\n输入存储库名称作为确认
+ 执行移交
+ 新所有者
+ 成功移交存储库
+ 需要新的所有者
+ 所有者名称有问题。确保新所有者存在
+ 过滤仓库
+ 仅在话题中搜索
+ 在描述中搜索
+ 仅存档仓库
+ 仅私有仓库
+ 在模板仓库中搜索
+ 合并到
+ 拉取自
+ 这些分支是相等的。 无需创建拉取请求
+ 必须合并到分支
+ 需要从分支下拉
+ 标题不可为空
+ 拉取请求创建成功
+ 这些分支之间的拉取请求已存在
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 51f40637..259139da 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -4,18 +4,21 @@
gitnex@swatian.com
Source code
https://codeberg.org/gitnex/GitNex
- Website
https://gitnex.com/
- Your Gitea version\n
+ Your Gitea Version
https://liberapay.com/mmarif/donate
https://www.patreon.com/mmarif
- %1$s / build %2$d
+ Version
+ Build
GitNex is a free, open-source Android client for Git repository management tool Gitea. GitNex is Licensed under GPLv3.\n\nThanks to all the contributors and donators for your generous work and donations.
https://crowdin.com/project/gitnex
[GitNex] - Crash Report #%1$d
+ Crowdin
+ Translate
+ Support
- Support the App on Liberapay
- Become a Patreon
+ Liberapay
+ Patreon
My Repositories
@@ -29,6 +32,7 @@
Logout
Explore
Administration
+ Search Issues
@@ -55,6 +59,7 @@
Explore
Gitea Administration
Manage Accounts
+ New Pull Request
Demo repo
@@ -143,7 +148,6 @@
No issues found
- Website
Size
Default Branch
SSH URL
@@ -518,7 +522,6 @@
Copy URL
- Translate GitNex with Crowdin
Explore repositories
Star Repository
Unstar Repository
@@ -632,6 +635,8 @@
SSL certificates, cache, polling delay
Languages
Crash reports
+ If you like GitNex you can give it a thumbs up
+ App version, build, user gitea version
Archived
@@ -693,4 +698,20 @@
Assign Team
+ Filter Repositories
+ Search ONLY in Topic
+ Search in Description
+ Only Archived Repositories
+ Only Private Repositories
+ Search in Template Repositories
+
+ Merge Into
+ Pull From
+ These branches are equal. There is no need to create a pull request
+ Merge into branch is required
+ Pull from branch is required
+ Title is required
+ Pull Request created successfully
+ A pull request between these branches already exists
+
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 558dc38d..49bdb68e 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -210,7 +210,7 @@
diff --git a/app/src/main/res/xml/changelog.xml b/app/src/main/res/xml/changelog.xml
index f2292420..e9d6e7e9 100644
--- a/app/src/main/res/xml/changelog.xml
+++ b/app/src/main/res/xml/changelog.xml
@@ -1,8 +1,19 @@
-
- Under development
+
+ New: Create pull request
+ New: Edit repository properties (Admins only)
+ New: Delete repository (Admins only)
+ New: Transfer repository ownership (Admins only)
+ New: Notification badge in navigation menu
+ New: Search issues across all repositories
+ New: Show issues/pr states in single view mode
+ New: Explore repositories filter
+ New: Android 11 support
+ New: Commits under Files branches
+ Bugfix: Fix crash when create issue with labels removed
+ Bugfix: Fix active account selector
diff --git a/fastlane/metadata/android/en-US/changelogs/317.txt b/fastlane/metadata/android/en-US/changelogs/317.txt
new file mode 100644
index 00000000..aced6d1f
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/317.txt
@@ -0,0 +1,5 @@
+3.2.0-rc1
+
+3.2.0 RC1 release brings create pr, repository settings for admins and many more new features.
+
+Detailed release notes will be published with stable release.
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/320.txt b/fastlane/metadata/android/en-US/changelogs/320.txt
new file mode 100644
index 00000000..cedcec74
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/320.txt
@@ -0,0 +1,14 @@
+3.2.0
+
+New: Create pull request
+New: Edit repository properties (Admins only)
+New: Delete repository (Admins only)
+New: Transfer repository ownership (Admins only)
+New: Notification badge in navigation menu
+New: Search issues across all repositories
+New: Show issues/pr states in single view mode
+New: Explore repositories filters
+New: Android 11 support
+New: Commits under Files branches
+
+Release Notes: https://codeberg.org/gitnex/GitNex/releases
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt
index 2f2c2eb9..35fba695 100644
--- a/fastlane/metadata/android/en-US/full_description.txt
+++ b/fastlane/metadata/android/en-US/full_description.txt
@@ -1,7 +1,8 @@
-GitNex is a free, open-source Android client for Git repository management tool Gitea. Gitea is a community managed fork of Gogs, lightweight code hosting solution written in Go.
+GitNex is a free/paid, open-source Android client for Git repository management tool Gitea. Gitea is a community managed fork of Gogs, lightweight code hosting solution written in Go.
# Features
+- Multiple accounts support
- File and directory browser
- File viewer
- Create files
diff --git a/fastlane/metadata/android/en-US/images/featureGraphic.png b/fastlane/metadata/android/en-US/images/featureGraphic.png
new file mode 100644
index 00000000..3895d5b5
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/featureGraphic.png differ
diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png
new file mode 100644
index 00000000..62ab04d5
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/icon.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/001.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/001.png
index 85b81b77..cb001a0a 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/001.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/001.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/002.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/002.png
index 55c38cb7..643fed31 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/002.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/002.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/003.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/003.png
index 50ca3702..d04cef06 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/003.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/003.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/004.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/004.png
index 7dcacd9b..872f3483 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/004.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/004.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png
index 4ef4315f..434c94b7 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/005.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png
index 8072b892..ea7431b6 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/006.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png
index 214e57a3..70590b02 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/007.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png
index 9908f84e..5da2010a 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/008.png differ
diff --git a/fastlane/metadata/android/en-US/title.txt b/fastlane/metadata/android/en-US/title.txt
index 72def081..6d0bbfa4 100644
--- a/fastlane/metadata/android/en-US/title.txt
+++ b/fastlane/metadata/android/en-US/title.txt
@@ -1 +1 @@
-GitNex
+GitNex for Gitea
diff --git a/scripts/sign-build.sh b/scripts/sign-build.sh
index 6b4e520d..2b8b3304 100755
--- a/scripts/sign-build.sh
+++ b/scripts/sign-build.sh
@@ -1,16 +1,15 @@
#!/usr/bin/env bash
-#make sure needed var's are here
-[ -z "${BOT_TOKEN}" ] && { echo "missing BOT_TOKEN"; exit 1; }
-[ -z "${KS_PASS}" ] && { echo "missing KS_PASS"; exit 1; }
-[ -z "${KEY_PASS}" ] && { echo "missing KEY_PASS"; exit 1; }
-[ -z "${GITEA}" ] && { echo "missing GITEA"; exit 1; }
-[ -z "${KS_REPO}" ] && { echo "missing KS_REPO"; exit 1; }
-[ -z "${KS_FILE}" ] && { echo "missing KS_FILE"; exit 1; }
-[ -z "${OUTPUT}" ] && { echo "missing OUTPUT"; exit 1; }
-
+# Make sure needed var's are here
+[ -z "${BOT_TOKEN}" ] && { echo "Token is missing (BOT_TOKEN)"; exit 1; }
+[ -z "${KS_PASS}" ] && { echo "Missing keystore password (KS_PASS)"; exit 1; }
+[ -z "${KEY_PASS}" ] && { echo "Missing KEY_PASS"; exit 1; }
+[ -z "${INSTANCE}" ] && { echo "Instance url is missing (INSTANCE)"; exit 1; }
+[ -z "${KS_REPO}" ] && { echo "Missing repo of keystore (KS_REPO)"; exit 1; }
+[ -z "${KS_FILE}" ] && { echo "Filename of keystore is missing (KS_FILE)"; exit 1; }
+[ -z "${OUTPUT}" ] && { echo "Missing filename of signed output (OUTPUT)"; exit 1; }
KEYFILE=$(mktemp)
-curl -X GET "${GITEA}/api/v1/repos/${KS_REPO}/contents/${KS_FILE}?token=${BOT_TOKEN}" -H "accept: application/json" | sed 's|"content":"|#|g' | cut -d '#' -f 2 | cut -d '"' -f 1 | base64 -d > ${KEYFILE}
+curl -X GET "${INSTANCE}/api/v1/repos/${KS_REPO}/contents/${KS_FILE}?token=${BOT_TOKEN}" -H "accept: application/json" | sed 's|"content":"|#|g' | cut -d '#' -f 2 | cut -d '"' -f 1 | base64 -d > ${KEYFILE}
/opt/android-sdk-linux/build-tools/*/apksigner sign -v --ks-pass pass:$KS_PASS --key-pass pass:$KEY_PASS --ks-key-alias GitNexBot --ks ${KEYFILE} --out signed.apk $(find . -name "*release*.apk")