initial push

Signed-off-by: M M Arif <mmarif@swatian.com>
This commit is contained in:
M M Arif
2019-06-04 02:25:05 +05:00
parent a9b26e33e7
commit c3563dc861
379 changed files with 30478 additions and 620 deletions

View File

@@ -0,0 +1,144 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.UserSearchAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserSearch;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
* Author M M Arif
*/
public class AddCollaboratorToRepositoryActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
final Context ctx = this;
private TextView addCollaboratorSearch;
private TextView noData;
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_collaborator_to_repository);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
addCollaboratorSearch = findViewById(R.id.addCollaboratorSearch);
mRecyclerView = findViewById(R.id.recyclerViewUserSearch);
mProgressBar = findViewById(R.id.progress_bar);
noData = findViewById(R.id.noData);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
addCollaboratorSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEND) {
if(!addCollaboratorSearch.getText().toString().equals("")) {
loadUserSearchList(instanceUrl, instanceToken, addCollaboratorSearch.getText().toString(), getApplicationContext(), loginUid);
}
}
return false;
}
});
}
public void loadUserSearchList(String instanceUrl, String token, String searchKeyword, final Context context, String loginUid) {
Call<UserSearch> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getUserBySearch(Authorization.returnAuthentication(getApplicationContext(), loginUid, token), searchKeyword, 10);
call.enqueue(new Callback<UserSearch>() {
@Override
public void onResponse(@NonNull Call<UserSearch> call, @NonNull Response<UserSearch> response) {
if (response.isSuccessful()) {
assert response.body() != null;
getUsersList(response.body().getData(), context);
} else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<UserSearch> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
}
});
}
private void getUsersList(List<UserInfo> dataList, Context context) {
UserSearchAdapter adapter = new UserSearchAdapter(dataList, context);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
mProgressBar.setVisibility(View.VISIBLE);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
mProgressBar.setVisibility(View.GONE);
}
else {
noData.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@@ -0,0 +1,290 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.models.UpdateIssueAssignee;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class AddRemoveAssigneesActivity extends AppCompatActivity {
private ArrayList<MultiSelectModel> listOfCollaborators = new ArrayList<>();
private ArrayList<Integer> issueAssigneesIds = new ArrayList<>();
private Boolean assigneesFlag = false;
private MultiSelectDialog multiSelectDialogAssignees;
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_add_remove_assignees);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
getAssignees(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
}
private void getAssignees(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, final int issueIndex, final String loginUid) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull final Call<List<Collaborators>> call, @NonNull final retrofit2.Response<List<Collaborators>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
final List<Collaborators> collaboratorsList_ = response.body();
assert collaboratorsList_ != null;
if(collaboratorsList_.size() > 0) {
for (int i = 0; i < collaboratorsList_.size(); i++) {
listOfCollaborators.add(new MultiSelectModel(collaboratorsList_.get(i).getId(), collaboratorsList_.get(i).getUsername().trim()));
}
}
// get current issue assignees
Call<Issues> callSingleIssueAssignees = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
callSingleIssueAssignees.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 200) {
Issues issueAssigneesList = response.body();
assert issueAssigneesList != null;
if (issueAssigneesList.getAssignees() != null) {
if (issueAssigneesList.getAssignees().size() > 0) {
for (int i = 0; i < issueAssigneesList.getAssignees().size(); i++) {
issueAssigneesIds.add(issueAssigneesList.getAssignees().get(i).getId());
if(issueAssigneesList.getAssignees().get(i).getUsername().equals(loginUid)) {
listOfCollaborators.add(new MultiSelectModel(issueAssigneesList.getAssignees().get(i).getId(), issueAssigneesList.getAssignees().get(i).getUsername().trim()));
}
}
assigneesFlag = true;
}
}
else {
listOfCollaborators.add(new MultiSelectModel(tinyDb.getInt("userId"), loginUid));
}
if(assigneesFlag) {
multiSelectDialogAssignees = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectAssigneesListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.saveButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.preSelectIDsList(issueAssigneesIds)
.setMaxSelectionLimit(listOfCollaborators.size())
.multiSelectList(listOfCollaborators)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
Log.i("selectedNames", String.valueOf(selectedNames));
updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, loginUid, issueIndex, selectedNames);
tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity();
}
@Override
public void onCancel() {
CloseActivity();
}
});
}
else {
multiSelectDialogAssignees = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectAssigneesListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.saveButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.setMaxSelectionLimit(listOfCollaborators.size())
.multiSelectList(listOfCollaborators)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, loginUid, issueIndex, selectedNames);
tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity();
}
@Override
public void onCancel() {
CloseActivity();
}
});
}
multiSelectDialogAssignees.show(getSupportFragmentManager(), "issueMultiSelectDialog");
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
// get current issue assignees
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void CloseActivity() {
this.finish();
}
private void updateIssueAssignees(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, int issueIndex, List<String> issueAssigneesList) {
UpdateIssueAssignee updateAssigneeJson = new UpdateIssueAssignee(issueAssigneesList);
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.patchIssueAssignee(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, updateAssigneeJson);
call3.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response2) {
if(response2.code() == 201) {
Toasty.info(ctx, ctx.getString(R.string.assigneesUpdated));
}
else if(response2.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response2.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response2.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
}

View File

@@ -0,0 +1,303 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
/**
* Author M M Arif
*/
public class AddRemoveLabelsActivity extends AppCompatActivity {
private ArrayList<MultiSelectModel> listOfLabels = new ArrayList<>();
private ArrayList<Integer> issueLabelIds = new ArrayList<>();
private Boolean labelsFlag = false;
private MultiSelectDialog multiSelectDialogLabels;
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_add_remove_labels);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
getLabels(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
}
private void getLabels(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, final int issueIndex, final String loginUid) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getlabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Labels> labelsList_ = response.body();
assert labelsList_ != null;
if(labelsList_.size() > 0) {
for (int i = 0; i < labelsList_.size(); i++) {
listOfLabels.add(new MultiSelectModel(labelsList_.get(i).getId(), labelsList_.get(i).getName().trim()));
}
}
// get current issue labels
Call<List<Labels>> callSingleIssueLabels = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getIssueLabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
callSingleIssueLabels.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
if(response.code() == 200) {
List<Labels> issueLabelsList = response.body();
assert issueLabelsList != null;
if(issueLabelsList.size() > 0) {
for (int i = 0; i < issueLabelsList.size(); i++) {
issueLabelIds.add(issueLabelsList.get(i).getId());
}
labelsFlag = true;
}
if(labelsFlag) {
multiSelectDialogLabels = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectLabelsListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.saveButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.preSelectIDsList(issueLabelIds)
.setMaxSelectionLimit(listOfLabels.size())
.multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
String labelIds = selectedIds.toString();
int[] integers;
if (selectedIds.size() > 0) {
String[] items = labelIds.replaceAll("\\[", "").replaceAll("\\]", "").replaceAll("\\s", "").split(",");
integers = new int[items.length];
for (int i = 0; i < integers.length; i++) {
integers[i] = Integer.parseInt(items[i]);
}
}
else {
integers = new int[0];
}
updateIssueLabels(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, integers, loginUid);
tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity();
}
@Override
public void onCancel() {
CloseActivity();
}
});
}
else {
multiSelectDialogLabels = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectLabelsListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.saveButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.setMaxSelectionLimit(listOfLabels.size())
.multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
String labelIds = selectedIds.toString();
int[] integers;
if (selectedIds.size() > 0) {
String[] items = labelIds.replaceAll("\\[", "").replaceAll("\\]", "").replaceAll("\\s", "").split(",");
integers = new int[items.length];
for (int i = 0; i < integers.length; i++) {
integers[i] = Integer.parseInt(items[i]);
}
}
else {
integers = new int[0];
}
updateIssueLabels(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, integers, loginUid);
tinyDb.putBoolean("singleIssueUpdate", true);
CloseActivity();
}
@Override
public void onCancel() {
CloseActivity();
}
});
}
multiSelectDialogLabels.show(getSupportFragmentManager(), "issueMultiSelectDialog");
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
// get current issue labels
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void updateIssueLabels(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, int issueIndex, int[] issueLabels, String loginUid) {
Labels patchIssueLabels = new Labels(issueLabels);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.updateIssueLabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, patchIssueLabels);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 200) {
Toasty.info(ctx, ctx.getString(R.string.labelsUpdated));
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void CloseActivity() {
this.finish();
}
}

View File

@@ -0,0 +1,200 @@
package org.mian.gitnex.activities;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.AdminGetUsersAdapter;
import org.mian.gitnex.fragments.AdminUsersBottomSheetFragment;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.AdminGetUsersViewModel;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
*/
public class AdminGetUsersActivity extends AppCompatActivity implements AdminUsersBottomSheetFragment.BottomSheetListener {
private View.OnClickListener onClickListener;
final Context ctx = this;
private AdminGetUsersAdapter adapter;
private RecyclerView mRecyclerView;
private TextView noDataUsers;
private Boolean searchFilter = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin_get_users);
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
noDataUsers = findViewById(R.id.noDataUsers);
mRecyclerView = findViewById(R.id.recyclerView);
final SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
AdminGetUsersViewModel.loadUsersList(getApplicationContext(), instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken));
}
}, 500);
}
});
fetchDataAsync(getApplicationContext(), instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken));
}
private void fetchDataAsync(Context ctx, String instanceUrl, String instanceToken) {
AdminGetUsersViewModel usersModel = ViewModelProviders.of(this).get(AdminGetUsersViewModel.class);
usersModel.getUsersList(ctx, instanceUrl, instanceToken).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> usersListMain) {
adapter = new AdminGetUsersAdapter(getApplicationContext(), usersListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setAdapter(adapter);
noDataUsers.setVisibility(View.GONE);
searchFilter = true;
}
else {
//adapter.notifyDataSetChanged();
//mRecyclerView.setAdapter(adapter);
mRecyclerView.setVisibility(View.GONE);
noDataUsers.setVisibility(View.VISIBLE);
}
}
});
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
final MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if(searchFilter) {
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getApplicationContext()));
inflater.inflate(R.menu.search_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
if(!connToInternet) {
return;
}
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
}
}
}, 500);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
AdminUsersBottomSheetFragment bottomSheet = new AdminUsersBottomSheetFragment();
bottomSheet.show(getSupportFragmentManager(), "usersBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
switch (text) {
case "newUser":
startActivity(new Intent(AdminGetUsersActivity.this, CreateNewUserActivity.class));
break;
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@@ -0,0 +1,575 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.app.DatePickerDialog;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.gson.JsonElement;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.models.MultiSelectModel;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
/**
* Author M M Arif
*/
public class CreateIssueActivity extends AppCompatActivity implements View.OnClickListener {
private View.OnClickListener onClickListener;
MultiSelectDialog multiSelectDialog;
MultiSelectDialog multiSelectDialogLabels;
private TextView assigneesList;
private TextView newIssueLabels;
private TextView newIssueDueDate;
private Spinner newIssueMilestoneSpinner;
private EditText newIssueTitle;
private SocialAutoCompleteTextView newIssueDescription;
private Button createNewIssueButton;
private TextView labelsIdHolder;
private boolean assigneesFlag;
private boolean labelsFlag;
final Context ctx = this;
List<Milestones> milestonesList = new ArrayList<>();
ArrayList<MultiSelectModel> listOfAssignees = new ArrayList<>();
ArrayList<MultiSelectModel> listOfLabels= new ArrayList<>();
private ArrayAdapter<Mention> defaultMentionAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_issue);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
assigneesList = findViewById(R.id.newIssueAssigneesList);
newIssueLabels = findViewById(R.id.newIssueLabels);
newIssueDueDate = findViewById(R.id.newIssueDueDate);
createNewIssueButton = findViewById(R.id.createNewIssueButton);
newIssueTitle = findViewById(R.id.newIssueTitle);
newIssueDescription = findViewById(R.id.newIssueDescription);
labelsIdHolder = findViewById(R.id.labelsIdHolder);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
newIssueDescription.setMentionAdapter(defaultMentionAdapter);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
assigneesList.setOnClickListener(this);
newIssueLabels.setOnClickListener(this);
newIssueDueDate.setOnClickListener(this);
newIssueMilestoneSpinner = findViewById(R.id.newIssueMilestoneSpinner);
newIssueMilestoneSpinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getLabels(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getCollaborators(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
disableProcessButton();
if(!connToInternet) {
createNewIssueButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewIssueButton.setBackground(shape);
} else {
createNewIssueButton.setOnClickListener(this);
}
}
private void processNewIssue() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
Milestones mModel = (Milestones) newIssueMilestoneSpinner.getSelectedItem();
int newIssueMilestoneIdForm = mModel.getId();
String newIssueTitleForm = newIssueTitle.getText().toString();
String newIssueDescriptionForm = newIssueDescription.getText().toString();
String newIssueAssigneesListForm = assigneesList.getText().toString();
//String newIssueLabelsForm = newIssueLabels.getText().toString();
String newIssueDueDateForm = newIssueDueDate.getText().toString();
String newIssueLabelsIdHolderForm = labelsIdHolder.getText().toString();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if (newIssueTitleForm.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.issueTitleEmpty));
return;
}
/*if (newIssueDescriptionForm.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.issueDescriptionEmpty));
return;
}*/
if (newIssueDueDateForm.equals("")) {
newIssueDueDateForm = null;
} else {
newIssueDueDateForm = (AppUtil.customDateCombine(AppUtil.customDateFormat(newIssueDueDateForm)));
}
List<String> newIssueAssigneesListForm_ = new ArrayList<>(Arrays.asList(newIssueAssigneesListForm.split(",")));
for (int i = 0; i < newIssueAssigneesListForm_.size(); i++) {
newIssueAssigneesListForm_.set(i, newIssueAssigneesListForm_.get(i).trim());
}
int[] integers;
if (!newIssueLabelsIdHolderForm.equals("")) {
String[] items = newIssueLabelsIdHolderForm.replaceAll("\\[", "").replaceAll("\\]", "").replaceAll("\\s", "").split(",");
integers = new int[items.length];
for (int i = 0; i < integers.length; i++) {
integers[i] = Integer.parseInt(items[i]);
}
}
else {
integers = new int[0];
}
//Log.i("FormData", String.valueOf(newIssueLabelsForm));
disableProcessButton();
createNewIssueFunc(instanceUrl, instanceToken, repoOwner, repoName, loginUid, newIssueDescriptionForm, newIssueDueDateForm, newIssueMilestoneIdForm, newIssueTitleForm, newIssueAssigneesListForm_, integers);
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
} else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
}
});
}
private void createNewIssueFunc(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, String newIssueDescriptionForm, String newIssueDueDateForm, int newIssueMilestoneIdForm, String newIssueTitleForm, List<String> newIssueAssigneesListForm, int[] newIssueLabelsForm) {
CreateIssue createNewIssueJson = new CreateIssue(loginUid, newIssueDescriptionForm, false, newIssueDueDateForm, newIssueMilestoneIdForm, newIssueTitleForm, newIssueAssigneesListForm, newIssueLabelsForm);
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createNewIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, createNewIssueJson);
call3.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response2) {
if(response2.isSuccessful()) {
if(response2.code() == 201) {
//Log.i("isSuccessful1", String.valueOf(response2.body()));
TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("resumeIssues", true);
Toasty.info(getApplicationContext(), getString(R.string.issueCreated));
enableProcessButton();
finish();
}
}
else if(response2.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.issueCreatedError));
enableProcessButton();
//Log.i("isSuccessful2", String.valueOf(response2.body()));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private void getMilestones(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Milestones>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getMilestones(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Milestones>>() {
@Override
public void onResponse(@NonNull Call<List<Milestones>> call, @NonNull retrofit2.Response<List<Milestones>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Milestones> milestonesList_ = response.body();
milestonesList.add(new Milestones(0,"No milestone"));
assert milestonesList_ != null;
if(milestonesList_.size() > 0) {
for (int i = 0; i < milestonesList_.size(); i++) {
//String mStone = getString(R.string.spinnerMilestoneText, milestonesList_.get(i).getTitle(), milestonesList_.get(i).getState());
if(milestonesList_.get(i).getState().equals(getString(R.string.issueStatusOpen))) {
Milestones data = new Milestones(
milestonesList_.get(i).getId(),
milestonesList_.get(i).getTitle()
);
milestonesList.add(data);
}
}
}
ArrayAdapter<Milestones> adapter = new ArrayAdapter<>(getApplicationContext(),
R.layout.spinner_item, milestonesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
newIssueMilestoneSpinner.setAdapter(adapter);
enableProcessButton();
}
}
}
@Override
public void onFailure(@NonNull Call<List<Milestones>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void getCollaborators(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull retrofit2.Response<List<Collaborators>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Collaborators> assigneesList_ = response.body();
assert assigneesList_ != null;
if(assigneesList_.size() > 0) {
for (int i = 0; i < assigneesList_.size(); i++) {
/*String assigneesCopy;
if(!assigneesList_.get(i).getFull_name().equals("")) {
assigneesCopy = getString(R.string.dialogAssignessText, assigneesList_.get(i).getFull_name(), assigneesList_.get(i).getLogin());
}
else {
assigneesCopy = assigneesList_.get(i).getLogin();
}*/
listOfAssignees.add(new MultiSelectModel(assigneesList_.get(i).getId(), assigneesList_.get(i).getLogin().trim()));
}
assigneesFlag = true;
}
multiSelectDialog = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectAssigneesListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.okButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.setMaxSelectionLimit(listOfAssignees.size())
.multiSelectList(listOfAssignees)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
assigneesList.setText(dataString);
}
@Override
public void onCancel() {
//Log.d("multiSelect","Dialog cancelled");
}
});
}
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void getLabels(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getlabels(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Labels> labelsList_ = response.body();
assert labelsList_ != null;
if(labelsList_.size() > 0) {
for (int i = 0; i < labelsList_.size(); i++) {
listOfLabels.add(new MultiSelectModel(labelsList_.get(i).getId(), labelsList_.get(i).getName().trim()));
}
labelsFlag = true;
}
multiSelectDialogLabels = new MultiSelectDialog()
.title(getResources().getString(R.string.newIssueSelectLabelsListTitle))
.titleSize(25)
.positiveText(getResources().getString(R.string.okButton))
.negativeText(getResources().getString(R.string.cancelButton))
.setMinSelectionLimit(0)
.setMaxSelectionLimit(listOfLabels.size())
.multiSelectList(listOfLabels)
.onSubmit(new MultiSelectDialog.SubmitCallbackListener() {
@Override
public void onSelected(ArrayList<Integer> selectedIds, ArrayList<String> selectedNames, String dataString) {
newIssueLabels.setText(dataString.trim());
labelsIdHolder.setText(selectedIds.toString());
}
@Override
public void onCancel() {
//Log.d("multiSelect","Dialog cancelled");
}
});
}
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
@Override
public void onClick(View v) {
if (v == assigneesList) {
if(assigneesFlag) {
multiSelectDialog.show(getSupportFragmentManager(), "multiSelectDialog");
}
else {
Toasty.info(getApplicationContext(), getResources().getString(R.string.noAssigneesFound));
}
}
else if (v == newIssueLabels) {
if(labelsFlag) {
multiSelectDialogLabels.show(getSupportFragmentManager(), "multiSelectDialogLabels");
}
else {
Toasty.info(getApplicationContext(), getResources().getString(R.string.noLabelsFound));
}
}
else if (v == newIssueDueDate) {
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,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
newIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth));
}
}, mYear, mMonth, mDay);
datePickerDialog.show();
}
else if(v == createNewIssueButton) {
processNewIssue();
}
}
private void disableProcessButton() {
createNewIssueButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewIssueButton.setBackground(shape);
}
private void enableProcessButton() {
createNewIssueButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewIssueButton.setBackground(shape);
}
}

View File

@@ -0,0 +1,435 @@
package org.mian.gitnex.activities;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import com.pes.androidmaterialcolorpickerdialog.ColorPickerCallback;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.CreateLabel;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.LabelsViewModel;
/**
* Author M M Arif
*/
public class CreateLabelActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
private TextView colorPicker;
private EditText labelName;
private Button createLabelButton;
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_label);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(getIntent().getStringExtra("labelAction") != null && getIntent().getStringExtra("labelAction").equals("delete")) {
deleteLabel(instanceUrl, instanceToken, repoOwner, repoName, Integer.valueOf(getIntent().getStringExtra("labelId")), loginUid);
finish();
return;
}
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
ImageView closeActivity = findViewById(R.id.close);
colorPicker = findViewById(R.id.colorPicker);
labelName = findViewById(R.id.labelName);
createLabelButton = findViewById(R.id.createLabelButton);
final ColorPicker cp = new ColorPicker(CreateLabelActivity.this, 235, 113, 33);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
colorPicker.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cp.show();
}
});
cp.setCallback(new ColorPickerCallback() {
@Override
public void onColorChosen(@ColorInt int color) {
//Log.i("#Hex no alpha", String.format("#%06X", (0xFFFFFF & color)));
colorPicker.setBackgroundColor(color);
tinyDb.putString("labelColor", String.format("#%06X", (0xFFFFFF & color)));
cp.dismiss();
}
});
if(getIntent().getStringExtra("labelAction") != null && getIntent().getStringExtra("labelAction").equals("edit")) {
labelName.setText(getIntent().getStringExtra("labelTitle"));
int labelColor_ = Color.parseColor("#" + getIntent().getStringExtra("labelColor"));
colorPicker.setBackgroundColor(labelColor_);
tinyDb.putString("labelColorDefault", "#" + getIntent().getStringExtra("labelColor"));
TextView toolbar_title = findViewById(R.id.toolbar_title);
toolbar_title.setText(getResources().getString(R.string.pageTitleLabelUpdate));
createLabelButton.setText(getResources().getString(R.string.newUpdateButtonCopy));
createLabelButton.setOnClickListener(updateLabelListener);
return;
}
if(!connToInternet) {
createLabelButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createLabelButton.setBackground(shape);
} else {
createLabelButton.setOnClickListener(createLabelListener);
}
}
private View.OnClickListener createLabelListener = new View.OnClickListener() {
public void onClick(View v) {
processCreateLabel();
}
};
private View.OnClickListener updateLabelListener = new View.OnClickListener() {
public void onClick(View v) {
processUpdateLabel();
}
};
private void processUpdateLabel() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil();
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String updateLabelName = labelName.getText().toString();
String updateLabelColor;
if(tinyDb.getString("labelColor").isEmpty()) {
updateLabelColor = tinyDb.getString("labelColorDefault");
}
else {
updateLabelColor = tinyDb.getString("labelColor");
}
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(updateLabelName.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.labelEmptyError));
return;
}
if(!appUtil.checkStrings(updateLabelName)) {
Toasty.info(getApplicationContext(), getString(R.string.labelNameError));
return;
}
disableProcessButton();
patchLabel(instanceUrl, instanceToken, repoOwner, repoName, updateLabelName, updateLabelColor, Integer.valueOf(getIntent().getStringExtra("labelId")), loginUid);
}
private void processCreateLabel() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newLabelName = labelName.getText().toString();
String newLabelColor;
if(tinyDb.getString("labelColor").isEmpty()) {
newLabelColor = String.format("#%06X", (0xFFFFFF & ContextCompat.getColor(getApplicationContext(), R.color.releasePre)));
}
else {
newLabelColor = tinyDb.getString("labelColor");
}
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(newLabelName.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.labelEmptyError));
return;
}
if(!appUtil.checkStrings(newLabelName)) {
Toasty.info(getApplicationContext(), getString(R.string.labelNameError));
return;
}
disableProcessButton();
createNewLabel(instanceUrl, instanceToken, repoOwner, repoName, newLabelName, newLabelColor, loginUid);
}
private void createNewLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String newLabelName, String newLabelColor, String loginUid) {
CreateLabel createLabelFunc = new CreateLabel(newLabelName, newLabelColor);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<CreateLabel> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, createLabelFunc);
call.enqueue(new Callback<CreateLabel>() {
@Override
public void onResponse(@NonNull Call<CreateLabel> call, @NonNull retrofit2.Response<CreateLabel> response) {
if(response.code() == 201) {
Toasty.info(getApplicationContext(), getString(R.string.labelCreated));
tinyDb.putString("labelColor", "");
tinyDb.putBoolean("labelsRefresh", true);
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
tinyDb.putString("labelColor", "");
Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) {
tinyDb.putString("labelColor", "");
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void patchLabel(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String updateLabelName, String updateLabelColor, int labelId, String loginUid) {
CreateLabel createLabelFunc = new CreateLabel(updateLabelName, updateLabelColor);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<CreateLabel> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.patchLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, labelId, createLabelFunc);
call.enqueue(new Callback<CreateLabel>() {
@Override
public void onResponse(@NonNull Call<CreateLabel> call, @NonNull retrofit2.Response<CreateLabel> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
Toasty.info(getApplicationContext(), getString(R.string.labelUpdated));
tinyDb.putString("labelColor", "");
tinyDb.putBoolean("labelsRefresh", true);
tinyDb.putString("labelColorDefault", "");
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
getIntent().removeExtra("labelTitle");
getIntent().removeExtra("labelColor");
finish();
}
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
tinyDb.putString("labelColor", "");
tinyDb.putString("labelColorDefault", "");
Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<CreateLabel> call, @NonNull Throwable t) {
tinyDb.putString("labelColor", "");
tinyDb.putString("labelColorDefault", "");
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
getIntent().removeExtra("labelTitle");
getIntent().removeExtra("labelColor");
finish();
}
};
}
private void deleteLabel(final String instanceUrl, final String instanceToken, final String repoOwner, final String repoName, int labelId, String loginUid) {
Call<Labels> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.deleteLabel(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, labelId);
call.enqueue(new Callback<Labels>() {
@Override
public void onResponse(@NonNull Call<Labels> call, @NonNull retrofit2.Response<Labels> response) {
if(response.isSuccessful()) {
if(response.code() == 204) {
Toasty.info(getApplicationContext(), getString(R.string.labelDeleteText));
LabelsViewModel.loadLabelsList(instanceUrl, instanceToken, repoOwner, repoName);
getIntent().removeExtra("labelAction");
getIntent().removeExtra("labelId");
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.labelDeleteErrorText));
}
}
@Override
public void onFailure(@NonNull Call<Labels> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void disableProcessButton() {
createLabelButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createLabelButton.setBackground(shape);
}
private void enableProcessButton() {
createLabelButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createLabelButton.setBackground(shape);
}
}

View File

@@ -0,0 +1,226 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
/**
* Author M M Arif
*/
public class CreateNewUserActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
private EditText fullName;
private EditText userUserName;
private EditText userEmail;
private EditText userPassword;
private Button createUserButton;
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_new_user);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
ImageView closeActivity = findViewById(R.id.close);
createUserButton = findViewById(R.id.createUserButton);
fullName = findViewById(R.id.fullName);
userUserName = findViewById(R.id.userUserName);
userEmail = findViewById(R.id.userEmail);
userPassword = findViewById(R.id.userPassword);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(!connToInternet) {
disableProcessButton();
} else {
createUserButton.setOnClickListener(createNewUserListener);
}
}
private void processCreateNewUser() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newFullName = fullName.getText().toString().trim();
String newUserName = userUserName.getText().toString().trim();
String newUserEmail = userEmail.getText().toString().trim();
String newUserPassword = userPassword.getText().toString();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(newFullName.equals("") || newUserName.equals("") | newUserEmail.equals("") || newUserPassword.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFields));
return;
}
if(!appUtil.checkStrings(newFullName)) {
Toasty.info(getApplicationContext(), getString(R.string.userInvalidFullName));
return;
}
if(!appUtil.checkStringsWithAlphaNumeric(newUserName)) {
Toasty.info(getApplicationContext(), getString(R.string.userInvalidUserName));
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.info(getApplicationContext(), getString(R.string.userInvalidEmail));
return;
}
disableProcessButton();
createNewUser(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), newFullName, newUserName, newUserEmail, newUserPassword);
}
private void createNewUser(final String instanceUrl, final String instanceToken, String newFullName, String newUserName, String newUserEmail, String newUserPassword) {
UserInfo createUser = new UserInfo(newUserEmail, newFullName, newUserName, newUserPassword, newUserName, 0, true);
Call<UserInfo> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createNewUser(instanceToken, createUser);
call.enqueue(new Callback<UserInfo>() {
@Override
public void onResponse(@NonNull Call<UserInfo> call, @NonNull retrofit2.Response<UserInfo> response) {
if(response.code() == 201) {
Toasty.info(getApplicationContext(), getString(R.string.userCreatedText));
enableProcessButton();
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.userExistsError));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<UserInfo> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private View.OnClickListener createNewUserListener = new View.OnClickListener() {
public void onClick(View v) {
processCreateNewUser();
}
};
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private void disableProcessButton() {
createUserButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createUserButton.setBackground(shape);
}
private void enableProcessButton() {
createUserButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createUserButton.setBackground(shape);
}
}

View File

@@ -0,0 +1,310 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Branches;
import org.mian.gitnex.models.Releases;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
/**
* Author M M Arif
*/
public class CreateReleaseActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
public ImageView closeActivity;
private EditText releaseTagName;
private Spinner releaseBranch;
private EditText releaseTitle;
private EditText releaseContent;
private CheckBox releaseType;
private CheckBox releaseDraft;
private Button createNewRelease;
final Context ctx = this;
List<Branches> branchesList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_release);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
closeActivity = findViewById(R.id.close);
releaseTagName = findViewById(R.id.releaseTagName);
releaseTitle = findViewById(R.id.releaseTitle);
releaseContent = findViewById(R.id.releaseContent);
releaseType = findViewById(R.id.releaseType);
releaseDraft = findViewById(R.id.releaseDraft);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
releaseBranch = findViewById(R.id.releaseBranch);
releaseBranch.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getBranches(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
releaseBranch.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Branches branch = (Branches) parent.getSelectedItem();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
createNewRelease = findViewById(R.id.createNewRelease);
disableProcessButton();
if(!connToInternet) {
disableProcessButton();
} else {
createNewRelease.setOnClickListener(createReleaseListener);
}
}
private View.OnClickListener createReleaseListener = new View.OnClickListener() {
public void onClick(View v) {
processNewRelease();
}
};
private void processNewRelease() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
String newReleaseTagName = releaseTagName.getText().toString();
String newReleaseTitle = releaseTitle.getText().toString();
String newReleaseContent = releaseContent.getText().toString();
String newReleaseBranch = releaseBranch.getSelectedItem().toString();
boolean newReleaseType = releaseType.isChecked();
boolean newReleaseDraft = releaseDraft.isChecked();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(newReleaseTagName.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.tagNameErrorEmpty));
return;
}
if(newReleaseTitle.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.titleErrorEmpty));
return;
}
disableProcessButton();
createNewReleaseFunc(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, newReleaseTagName, newReleaseTitle, newReleaseContent, newReleaseBranch, newReleaseType, newReleaseDraft);
}
private void createNewReleaseFunc(final String instanceUrl, final String token, String repoOwner, String repoName, String newReleaseTagName, String newReleaseTitle, String newReleaseContent, String newReleaseBranch, boolean newReleaseType, boolean newReleaseDraft) {
Releases createReleaseJson = new Releases(newReleaseContent, newReleaseDraft, newReleaseTitle, newReleaseType, newReleaseTagName, newReleaseBranch);
Call<Releases> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createNewRelease(token, repoOwner, repoName, createReleaseJson);
call.enqueue(new Callback<Releases>() {
@Override
public void onResponse(@NonNull Call<Releases> call, @NonNull retrofit2.Response<Releases> response) {
if (response.code() == 201) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("updateReleases", true);
Toasty.info(getApplicationContext(), getString(R.string.releaseCreatedText));
enableProcessButton();
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, ctx.getResources().getString(R.string.alertDialogTokenRevokedTitle),
ctx.getResources().getString(R.string.alertDialogTokenRevokedMessage),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
ctx.getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Releases> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void getBranches(String instanceUrl, String instanceToken, final String repoOwner, final String repoName) {
Call<List<Branches>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getBranches(instanceToken, repoOwner, repoName);
call.enqueue(new Callback<List<Branches>>() {
@Override
public void onResponse(@NonNull Call<List<Branches>> call, @NonNull retrofit2.Response<List<Branches>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<Branches> 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<Branches> adapter = new ArrayAdapter<>(getApplicationContext(),
R.layout.spinner_item, branchesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
releaseBranch.setAdapter(adapter);
enableProcessButton();
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
}
@Override
public void onFailure(@NonNull Call<List<Branches>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private void disableProcessButton() {
createNewRelease.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewRelease.setBackground(shape);
}
private void enableProcessButton() {
createNewRelease.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewRelease.setBackground(shape);
}
}

View File

@@ -0,0 +1,378 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Teams;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.util.Log;
/**
* Author M M Arif
*/
public class CreateTeamByOrgActivity extends AppCompatActivity implements View.OnClickListener {
final Context ctx = CreateTeamByOrgActivity.this;
private View.OnClickListener onClickListener;
private TextView teamName;
private TextView teamDesc;
private TextView teamPermission;
private TextView teamPermissionDetail;
private TextView teamAccessControls;
private TextView teamAccessControlsArray;
private Button createTeamButton;
private String[] permissionList = {"Read", "Write", "Admin"};
public int permissionSelectedChoice = -1;
private String[] accessControlsList = new String[] {
"Code",
"Issues",
"Pull Request",
"Releases",
"Wiki",
"External Wiki",
"External Issues"
};
private List<String> pushAccessList;
private boolean[] selectedAccessControlsTrueFalse = new boolean[]{
false,
false,
false,
false,
false,
false,
false
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_team_by_org);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
ImageView closeActivity = findViewById(R.id.close);
teamName = findViewById(R.id.teamName);
teamDesc = findViewById(R.id.teamDesc);
teamPermission = findViewById(R.id.teamPermission);
teamPermissionDetail = findViewById(R.id.teamPermissionDetail);
teamAccessControls = findViewById(R.id.teamAccessControls);
teamAccessControlsArray = findViewById(R.id.teamAccessControlsArray);
createTeamButton = findViewById(R.id.createTeamButton);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
teamPermission.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder pBuilder = new AlertDialog.Builder(ctx, R.style.confirmDialog);
pBuilder.setTitle(R.string.newTeamPermission);
if(permissionSelectedChoice != -1) {
pBuilder.setCancelable(true);
}
else {
pBuilder.setCancelable(false);
}
pBuilder.setSingleChoiceItems(permissionList, permissionSelectedChoice, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
permissionSelectedChoice = i;
teamPermission.setText(permissionList[i]);
if(permissionList[i].equals("Read")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionRead);
}
else if(permissionList[i].equals("Write")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionWrite);
}
else if(permissionList[i].equals("Admin")) {
teamPermissionDetail.setVisibility(View.VISIBLE);
teamPermissionDetail.setText(R.string.newTeamPermissionAdmin);
}
else {
teamPermissionDetail.setVisibility(View.GONE);
}
dialogInterface.dismiss();
}
});
AlertDialog pDialog = pBuilder.create();
pDialog.show();
}
});
teamAccessControls.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
teamAccessControls.setText("");
teamAccessControlsArray.setText("");
pushAccessList = Arrays.asList(accessControlsList);
AlertDialog.Builder aDialogBuilder = new AlertDialog.Builder(ctx, R.style.confirmDialog);
aDialogBuilder.setMultiChoiceItems(accessControlsList, selectedAccessControlsTrueFalse, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
}
})
.setCancelable(false)
.setTitle(R.string.newTeamAccessControls)
.setPositiveButton(R.string.okButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int selectedVal = 0;
while(selectedVal < selectedAccessControlsTrueFalse.length)
{
boolean value = selectedAccessControlsTrueFalse[selectedVal];
String repoCode = "";
if(selectedVal == 0) {
repoCode = "repo.code";
}
if(selectedVal == 1) {
repoCode = "repo.issues";
}
if(selectedVal == 2) {
repoCode = "repo.pulls";
}
if(selectedVal == 3) {
repoCode = "repo.releases";
}
if(selectedVal == 4) {
repoCode = "repo.wiki";
}
if(selectedVal == 5) {
repoCode = "repo.ext_wiki";
}
if(selectedVal == 6) {
repoCode = "repo.ext_issues";
}
if(value){
teamAccessControls.setText(getString(R.string.newTeamPermissionValues, teamAccessControls.getText(), pushAccessList.get(selectedVal)));
teamAccessControlsArray.setText(getString(R.string.newTeamPermissionValuesFinal, teamAccessControlsArray.getText(), repoCode));
}
selectedVal++;
}
String data = String.valueOf(teamAccessControls.getText());
if(!data.equals("")) {
teamAccessControls.setText(data.substring(0, data.length() - 2));
}
String dataArray = String.valueOf(teamAccessControlsArray.getText());
if(!dataArray.equals("")) {
teamAccessControlsArray.setText(dataArray.substring(0, dataArray.length() - 2));
}
//Log.i("orgName", String.valueOf(teamAccessControlsArray.getText()));
}
});
AlertDialog aDialog = aDialogBuilder.create();
aDialog.show();
}
});
createTeamButton.setEnabled(false);
if(!connToInternet) {
createTeamButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createTeamButton.setBackground(shape);
} else {
createTeamButton.setEnabled(true);
createTeamButton.setOnClickListener(this);
}
}
private void processCreateTeam() {
AppUtil appUtil = new AppUtil();
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final String orgName = tinyDb.getString("orgName");;
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
String newTeamName = teamName.getText().toString();
String newTeamDesc = teamDesc.getText().toString();
String newTeamPermission = teamPermission.getText().toString().toLowerCase();
String newTeamAccessControls = teamAccessControlsArray.getText().toString();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if (newTeamName.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.teamNameEmpty));
return;
}
if(!appUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) {
Toasty.info(getApplicationContext(), getString(R.string.teamNameError));
return;
}
if(!newTeamDesc.equals("")) {
if(!appUtil.checkStrings(newTeamDesc)) {
Toasty.info(getApplicationContext(), getString(R.string.teamDescError));
return;
}
if(newTeamDesc.length() > 100) {
Toasty.info(getApplicationContext(), getString(R.string.teamDescLimit));
return;
}
}
if (newTeamPermission.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.teamPermissionEmpty));
return;
}
List<String> newTeamAccessControls_ = new ArrayList<>(Arrays.asList(newTeamAccessControls.split(",")));
for (int i = 0; i < newTeamAccessControls_.size(); i++) {
newTeamAccessControls_.set(i, newTeamAccessControls_.get(i).trim());
}
createNewTeamCall(instanceUrl, instanceToken, orgName, newTeamName, newTeamDesc, newTeamPermission, newTeamAccessControls_, loginUid);
}
private void createNewTeamCall(final String instanceUrl, final String instanceToken, String orgName, String newTeamName, String newTeamDesc, String newTeamPermission, List<String> newTeamAccessControls, String loginUid) {
Teams createNewTeamJson = new Teams(newTeamName, newTeamDesc, newTeamPermission, newTeamAccessControls);
Call<Teams> call3;
call3 = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createTeamsByOrg(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), orgName, createNewTeamJson);
call3.enqueue(new Callback<Teams>() {
@Override
public void onResponse(@NonNull Call<Teams> call, @NonNull retrofit2.Response<Teams> response2) {
if(response2.isSuccessful()) {
if(response2.code() == 201) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("resumeTeams", true);
Toasty.info(getApplicationContext(), getString(R.string.teamCreated));
finish();
}
}
else if(response2.code() == 404) {
Toasty.info(getApplicationContext(), getString(R.string.apiNotFound));
}
else if(response2.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.teamCreatedError));
}
}
@Override
public void onFailure(@NonNull Call<Teams> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
@Override
public void onClick(View v) {
if(v == createTeamButton) {
processCreateTeam();
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@@ -0,0 +1,43 @@
package org.mian.gitnex.activities;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
/**
* Author M M Arif
*/
public class CreditsActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_credits);
TextView creditKasun = findViewById(R.id.creditKasun);
ImageView closeActivity = findViewById(R.id.close);
creditKasun.setMovementMethod(LinkMovementMethod.getInstance());
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@@ -0,0 +1,367 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.gson.JsonElement;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.CreateIssue;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
/**
* Author M M Arif
*/
public class EditIssueActivity extends AppCompatActivity implements View.OnClickListener {
final Context ctx = this;
private View.OnClickListener onClickListener;
private EditText editIssueTitle;
private SocialAutoCompleteTextView editIssueDescription;
private TextView editIssueDueDate;
private Button editIssueButton;
private Spinner editIssueMilestoneSpinner;
private ArrayAdapter<Mention> defaultMentionAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_issue);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
ImageView closeActivity = findViewById(R.id.close);
editIssueButton = findViewById(R.id.editIssueButton);
TextView toolbar_title = findViewById(R.id.toolbar_title);
editIssueTitle = findViewById(R.id.editIssueTitle);
editIssueDescription = findViewById(R.id.editIssueDescription);
editIssueDueDate = findViewById(R.id.editIssueDueDate);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
editIssueDescription.setMentionAdapter(defaultMentionAdapter);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
editIssueDueDate.setOnClickListener(this);
editIssueButton.setOnClickListener(this);
if(!tinyDb.getString("issueNumber").isEmpty()) {
toolbar_title.setText(getString(R.string.editIssueNavHeader, String.valueOf(issueIndex)));
}
disableProcessButton();
getIssue(instanceUrl, instanceToken, loginUid, repoOwner, repoName, issueIndex);
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
} else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private void processEditIssue() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
String editIssueTitleForm = editIssueTitle.getText().toString();
String editIssueDescriptionForm = editIssueDescription.getText().toString();
String editIssueDueDateForm = editIssueDueDate.getText().toString();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if (editIssueTitleForm.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.issueTitleEmpty));
return;
}
/*if (editIssueDescriptionForm.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.issueDescriptionEmpty));
return;
}*/
if (editIssueDueDateForm.equals("")) {
editIssueDueDateForm = null;
} else {
editIssueDueDateForm = (AppUtil.customDateCombine(AppUtil.customDateFormat(editIssueDueDateForm)));
}
//Log.i("editIssueDueDateForm", String.valueOf(editIssueDueDateForm));
disableProcessButton();
editIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid, editIssueTitleForm, editIssueDescriptionForm, editIssueDueDateForm);
}
private void editIssue(String instanceUrl, String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid, String title, String description, String dueDate) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
CreateIssue issueData = new CreateIssue(title, description, dueDate);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.patchIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, issueData);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 201) {
Toasty.info(getApplicationContext(), getString(R.string.editIssueSuccessMessage));
tinyDb.putBoolean("issueEdited", true);
tinyDb.putBoolean("resumeIssues", true);
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
@Override
public void onClick(View v) {
if (v == editIssueDueDate) {
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,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
editIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth));
}
}, mYear, mMonth, mDay);
datePickerDialog.show();
}
else if(v == editIssueButton) {
processEditIssue();
}
}
private void getIssue(String instanceUrl, String instanceToken, String loginUid, String repoOwner, String repoName, int issueIndex) {
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
call.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 200) {
assert response.body() != null;
editIssueTitle.setText(response.body().getTitle());
editIssueDescription.setText(response.body().getBody());
if(response.body().getDue_date() != null) {
@SuppressLint("SimpleDateFormat") DateFormat formatter = new SimpleDateFormat("yyyy-M-dd");
String dueDate = formatter.format(response.body().getDue_date());
editIssueDueDate.setText(dueDate);
}
enableProcessButton();
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.info(getApplicationContext(), getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void disableProcessButton() {
editIssueButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
editIssueButton.setBackground(shape);
}
private void enableProcessButton() {
editIssueButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
editIssueButton.setBackground(shape);
}
}

View File

@@ -0,0 +1,501 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.Markwon;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import ru.noties.markwon.ext.tables.TablePlugin;
import ru.noties.markwon.ext.tasklist.TaskListPlugin;
import ru.noties.markwon.html.HtmlPlugin;
import ru.noties.markwon.image.ImagesPlugin;
import ru.noties.markwon.image.gif.GifPlugin;
import ru.noties.markwon.image.okhttp.OkHttpImagesPlugin;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.squareup.picasso.Picasso;
import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.IssueCommentsAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.SingleIssueBottomSheetFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.UserMentions;
import org.mian.gitnex.models.IssueComments;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.viewmodels.IssueCommentsViewModel;
import org.ocpsoft.prettytime.PrettyTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
/**
* Author M M Arif
*/
public class IssueDetailActivity extends AppCompatActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private IssueCommentsAdapter adapter;
private RecyclerView mRecyclerView;
private ImageView assigneeAvatar;
private TextView issueTitle;
private TextView issueDescription;
private TextView issueMilestone;
private TextView issueDueDate;
private TextView issueCreatedTime;
private HorizontalScrollView labelsScrollView;
private HorizontalScrollView assigneesScrollView;
private ScrollView scrollViewComments;
private TextView issueModified;
final Context ctx = this;
private LinearLayout labelsLayout;
private LinearLayout assigneesLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_issue_detail);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
final SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
closeActivity = findViewById(R.id.close);
assigneeAvatar = findViewById(R.id.assigneeAvatar);
issueTitle = findViewById(R.id.issueTitle);
issueDescription = findViewById(R.id.issueDescription);
issueMilestone = findViewById(R.id.issueMilestone);
issueDueDate = findViewById(R.id.issueDueDate);
issueCreatedTime = findViewById(R.id.issueCreatedTime);
labelsScrollView = findViewById(R.id.labelsScrollView);
assigneesScrollView = findViewById(R.id.assigneesScrollView);
scrollViewComments = findViewById(R.id.scrollViewComments);
issueModified = findViewById(R.id.issueModified);
labelsLayout = findViewById(R.id.frameLabels);
assigneesLayout = findViewById(R.id.frameAssignees);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefresh.setRefreshing(false);
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
}
}, 500);
}
});
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
fetchDataAsync(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.genericMenu:
SingleIssueBottomSheetFragment bottomSheet = new SingleIssueBottomSheetFragment();
bottomSheet.show(getSupportFragmentManager(), "singleIssueBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onResume() {
super.onResume();
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
if(tinyDb.getBoolean("commentPosted")) {
scrollViewComments.post(new Runnable() {
@Override
public void run() {
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
scrollViewComments.fullScroll(ScrollView.FOCUS_DOWN);
}
}, 1000);
tinyDb.putBoolean("commentPosted", false);
}
});
}
if(tinyDb.getBoolean("commentEdited")) {
scrollViewComments.post(new Runnable() {
@Override
public void run() {
IssueCommentsViewModel.loadIssueComments(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
tinyDb.putBoolean("commentEdited", false);
}
});
}
if(tinyDb.getBoolean("singleIssueUpdate")) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
assigneesLayout.removeAllViews();
labelsLayout.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
tinyDb.putBoolean("singleIssueUpdate", false);
}
}, 500);
}
if(tinyDb.getBoolean("issueEdited")) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
assigneesLayout.removeAllViews();
labelsLayout.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
tinyDb.putBoolean("issueEdited", false);
}
}, 500);
}
}
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo, int index, String loginUid) {
IssueCommentsViewModel issueCommentsModel = ViewModelProviders.of(this).get(IssueCommentsViewModel.class);
issueCommentsModel.getIssueCommentList(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), owner, repo, index).observe(this, new Observer<List<IssueComments>>() {
@Override
public void onChanged(@Nullable List<IssueComments> issueCommentsMain) {
adapter = new IssueCommentsAdapter(getApplicationContext(), issueCommentsMain);
mRecyclerView.setAdapter(adapter);
}
});
}
private void getSingleIssue(String instanceUrl, String instanceToken, String repoOwner, String repoName, int issueIndex, String loginUid) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex);
call.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull Response<Issues> response) {
if (response.isSuccessful()) {
if (response.code() == 200) {
Issues singleIssue = response.body();
assert singleIssue != null;
final Markwon markwon = Markwon.builder(Objects.requireNonNull(getApplicationContext()))
.usePlugin(CorePlugin.create())
.usePlugin(OkHttpImagesPlugin.create(new OkHttpClient()))
.usePlugin(ImagesPlugin.createWithAssets(getApplicationContext()))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder
.codeTextColor(tinyDb.getInt("codeBlockColor"))
.codeBackgroundColor(tinyDb.getInt("codeBlockBackground"))
.linkColor(getApplicationContext().getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(getApplicationContext()))
.usePlugin(TaskListPlugin.create(getApplicationContext()))
.usePlugin(HtmlPlugin.create())
.usePlugin(GifPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.build();
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String locale = tinyDb.getString("locale");
final String timeFormat = tinyDb.getString("dateFormat");
tinyDb.putString("issueState", singleIssue.getState());
tinyDb.putString("issueTitle", singleIssue.getTitle());
Picasso.get().load(singleIssue.getUser().getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(200, 200).centerCrop().into(assigneeAvatar);
issueTitle.setText(getString(R.string.issueTitleWithId, singleIssue.getNumber(), singleIssue.getTitle()));
String cleanIssueDescription = singleIssue.getBody().trim();
final CharSequence bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription));
issueDescription.setText(UserMentions.UserMentionsFunc(getApplicationContext(), bodyWithMD, cleanIssueDescription));
RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams)issueDescription.getLayoutParams();
LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(80, 80);
params1.setMargins(15, 0, 0, 0);
if(singleIssue.getAssignees() != null) {
assigneesScrollView.setVisibility(View.VISIBLE);
for (int i = 0; i < singleIssue.getAssignees().size(); i++) {
ImageView assigneesView = new ImageView(getApplicationContext());
Picasso.get().load(singleIssue.getAssignees().get(i).getAvatar_url()).transform(new RoundedTransformation(100, 0)).resize(80, 80).centerCrop().into(assigneesView);
assigneesLayout.addView(assigneesView);
assigneesView.setLayoutParams(params1);
if (!singleIssue.getAssignees().get(i).getFull_name().equals("")) {
assigneesView.setOnClickListener(new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getFull_name()), getApplicationContext()));
} else {
assigneesView.setOnClickListener(new ClickListener(getString(R.string.assignedTo, singleIssue.getAssignees().get(i).getLogin()), getApplicationContext()));
}
}
}
else {
assigneesScrollView.setVisibility(View.GONE);
}
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(0, 0, 15, 0);
if(singleIssue.getLabels() != null) {
labelsScrollView.setVisibility(View.VISIBLE);
int width = 33;
for (int i = 0; i < singleIssue.getLabels().size(); i++) {
String labelColor = singleIssue.getLabels().get(i).getColor();
String labelName = singleIssue.getLabels().get(i).getName();
int color = Color.parseColor("#" + labelColor);
ImageView labelsView = new ImageView(getApplicationContext());
labelsLayout.setOrientation(LinearLayout.HORIZONTAL);
labelsLayout.setGravity(Gravity.START | Gravity.TOP);
labelsView.setLayoutParams(params);
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.useFont(Typeface.DEFAULT)
.textColor(new ColorInverter().getContrastColor(color))
.fontSize(36)
.width((width * labelName.length()) - ((width / 4) * labelName.length()))
.height(60)
.endConfig()
.buildRoundRect(labelName, color, 8);
labelsView.setImageDrawable(drawable);
labelsLayout.addView(labelsView);
}
}
else {
labelsScrollView.setVisibility(View.GONE);
}
if(singleIssue.getDue_date() != null) {
if (timeFormat.equals("normal") || timeFormat.equals("pretty")) {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", new Locale(locale));
String dueDate = formatter.format(singleIssue.getDue_date());
issueDueDate.setText(getString(R.string.dueDate, dueDate));
issueDueDate.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getDue_date()), getApplicationContext()));
} else if (timeFormat.equals("normal1")) {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale));
String dueDate = formatter.format(singleIssue.getDue_date());
issueDueDate.setText(getString(R.string.dueDate, dueDate));
}
}
else {
issueDueDate.setVisibility(View.GONE);
}
String edited;
if(!singleIssue.getUpdated_at().equals(singleIssue.getCreated_at())) {
edited = getString(R.string.colorfulBulletSpan) + getString(R.string.modifiedText);
issueModified.setVisibility(View.VISIBLE);
issueModified.setText(edited);
issueModified.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getUpdated_at()), ctx));
}
else {
issueModified.setVisibility(View.INVISIBLE);
}
if((singleIssue.getDue_date() == null && singleIssue.getMilestone() == null) && singleIssue.getAssignees() != null) {
paramsDesc.setMargins(0, 35, 0, 0);
issueDescription.setLayoutParams(paramsDesc);
}
else if(singleIssue.getDue_date() == null && singleIssue.getMilestone() == null) {
paramsDesc.setMargins(0, 55, 0, 0);
issueDescription.setLayoutParams(paramsDesc);
}
else if(singleIssue.getAssignees() == null) {
paramsDesc.setMargins(0, 35, 0, 0);
issueDescription.setLayoutParams(paramsDesc);
}
else {
paramsDesc.setMargins(0, 15, 0, 0);
issueDescription.setLayoutParams(paramsDesc);
}
switch (timeFormat) {
case "pretty": {
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
String createdTime = prettyTime.format(singleIssue.getCreated_at());
issueCreatedTime.setText(getString(R.string.createdTime, createdTime));
issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getCreated_at()), getApplicationContext()));
break;
}
case "normal": {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(singleIssue.getCreated_at());
issueCreatedTime.setText(getString(R.string.createdTime, createdTime));
break;
}
case "normal1": {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
String createdTime = formatter.format(singleIssue.getCreated_at());
issueCreatedTime.setText(getString(R.string.createdTime, createdTime));
break;
}
}
if(singleIssue.getMilestone() != null) {
issueMilestone.setText(getString(R.string.issueMilestone, singleIssue.getMilestone().getTitle()));
}
else {
issueMilestone.setVisibility(View.GONE);
}
if (!singleIssue.getUser().getFull_name().equals("")) {
assigneeAvatar.setOnClickListener(new ClickListener(getApplicationContext().getResources().getString(R.string.issueCreator) + singleIssue.getUser().getFull_name(), getApplicationContext()));
} else {
assigneeAvatar.setOnClickListener(new ClickListener(getApplicationContext().getResources().getString(R.string.issueCreator) + singleIssue.getUser().getLogin(), getApplicationContext()));
}
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@@ -0,0 +1,436 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.res.Resources;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import com.tooltip.Tooltip;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserTokens;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.R;
import org.mian.gitnex.util.TinyDB;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Objects;
import okhttp3.Credentials;
import okhttp3.Headers;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private Button login_button;
private EditText instance_url, login_uid, login_passwd, otpCode;
private Spinner protocolSpinner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
TinyDB tinyDb = new TinyDB(getApplicationContext());
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
login_button = findViewById(R.id.login_button);
instance_url = findViewById(R.id.instance_url);
login_uid = findViewById(R.id.login_uid);
login_passwd = findViewById(R.id.login_passwd);
otpCode = findViewById(R.id.otpCode);
ImageView info_button = findViewById(R.id.info);
final TextView viewTextGiteaVersion = findViewById(R.id.appVersion);
protocolSpinner = findViewById(R.id.httpsSpinner);
viewTextGiteaVersion.setText(AppUtil.getAppVersion(getApplicationContext()));
Resources res = getResources();
String[] allProtocols = res.getStringArray(R.array.protocolValues);
final ArrayAdapter<String> adapterProtocols = new ArrayAdapter<String>(Objects.requireNonNull(getApplicationContext()),
R.layout.spinner_item, allProtocols);
adapterProtocols.setDropDownViewResource(R.layout.spinner_dropdown_item);
protocolSpinner.setAdapter(adapterProtocols);
protocolSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
String value = getResources().getStringArray(R.array.protocolValues)[pos];
if(value.toLowerCase().equals("http")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.protocolError));
}
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
info_button.setOnClickListener(infoListener);
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
//login_button.setOnClickListener(this);
if(!tinyDb.getString("instanceUrlRaw").isEmpty()) {
instance_url.setText(tinyDb.getString("instanceUrlRaw"));
}
if(!tinyDb.getString("loginUid").isEmpty()) {
login_uid.setText(tinyDb.getString("loginUid"));
}
if(tinyDb.getBoolean("loggedInMode")) {
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
}
login_button.setOnClickListener(loginListener);
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.login_button:
login();
break;
default:
}
}
private View.OnClickListener loginListener = new View.OnClickListener() {
public void onClick(View v) {
disableProcessButton();
login_button.setText(R.string.processingText);
login();
}
};
private View.OnClickListener infoListener = new View.OnClickListener() {
public void onClick(View v) {
new Tooltip.Builder(v)
.setText(R.string.urlInfoTooltip)
.setTextColor(getResources().getColor(R.color.white))
.setBackgroundColor(getResources().getColor(R.color.tooltipBackground))
.setCancelable(true)
.setDismissOnClick(true)
.setPadding(30)
.setCornerRadius(R.dimen.tooltipCornor)
.setGravity(Gravity.BOTTOM)
.show();
}
};
@SuppressLint("ResourceAsColor")
private void login() {
TinyDB tinyDb = new TinyDB(getApplicationContext());
AppUtil appUtil = new AppUtil();
boolean connToInternet = AppUtil.haveNetworkConnection(LoginActivity.this);
String instanceUrl = instance_url.getText().toString().trim();
String loginUid = login_uid.getText().toString();
String loginPass = login_passwd.getText().toString();
String protocol = protocolSpinner.getSelectedItem().toString();
String loginOTP_ = otpCode.getText().toString().trim();
if(instanceUrl.contains("@")) {
String[] urlForHttpAuth = instanceUrl.split("@");
tinyDb.putString("basicAuthPassword", loginPass);
tinyDb.putBoolean("basicAuthFlag", true);
instanceUrl = urlForHttpAuth[1];
loginUid = urlForHttpAuth[0];
}
String instanceHost;
if(AppUtil.httpCheck(instanceUrl)) {
URI uri = null;
try {
uri = new URI(instanceUrl);
} catch (URISyntaxException e) {
e.printStackTrace();
}
assert uri != null;
instanceHost = uri.getHost();
}
else {
instanceHost = instanceUrl;
}
if(protocol.toLowerCase().equals("https")) {
instanceUrl = "https://" + instanceHost + "/api/v1/";
}
else {
instanceUrl = "http://" + instanceHost + "/api/v1/";
}
tinyDb.putString("instanceUrlRaw", instanceHost);
tinyDb.putString("loginUid", loginUid);
tinyDb.putString("instanceUrl", instanceUrl);
if(connToInternet) {
if(instance_url.getText().toString().equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldURL));
enableProcessButton();
login_button.setText(R.string.btnLogin);
return;
}
if(loginUid.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldUsername));
enableProcessButton();
login_button.setText(R.string.btnLogin);
return;
}
if(login_passwd.getText().toString().equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emptyFieldPassword));
enableProcessButton();
login_button.setText(R.string.btnLogin);
return;
}
int loginOTP = 0;
if(loginOTP_.length() == 6) {
if(appUtil.checkIntegers(loginOTP_)) {
loginOTP = Integer.valueOf(loginOTP_);
}
else {
Toasty.info(getApplicationContext(), getString(R.string.loginOTPTypeError));
enableProcessButton();
login_button.setText(R.string.btnLogin);
return;
}
}
letTheUserIn(instanceUrl, loginUid, loginPass, loginOTP);
}
else {
Toasty.info(getApplicationContext(), getString(R.string.checkNetConnection));
}
}
private void letTheUserIn(final String instanceUrl, final String loginUid, final String loginPass, final int loginOTP) {
final String credential = Credentials.basic(loginUid, loginPass);
Call<List<UserTokens>> call;
if(loginOTP != 0) {
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getUserTokensWithOTP(credential, loginOTP, loginUid);
}
else {
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getUserTokens(credential, loginUid);
}
call.enqueue(new Callback<List<UserTokens>>() {
@Override
public void onResponse(@NonNull Call<List<UserTokens>> call, @NonNull retrofit2.Response<List<UserTokens>> response) {
List<UserTokens> userTokens = response.body();
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Headers responseHeaders = response.headers();
if (response.isSuccessful()) {
if (response.code() == 200) {
boolean setTokenFlag = false;
assert userTokens != null;
if (userTokens.size() > 0) {
for (int i = 0; i < userTokens.size(); i++) {
if (userTokens.get(i).getSha1().equals(tinyDb.getString(loginUid + "-token"))) {
setTokenFlag = true;
break;
}
//Log.i("Tokens: ", userTokens.get(i).getSha1());
}
}
if(tinyDb.getString(loginUid + "-token").isEmpty() || !setTokenFlag) {
UserTokens createUserToken = new UserTokens("gitnex-app-token");
Call<UserTokens> callCreateToken;
if(loginOTP != 0) {
callCreateToken = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createNewTokenWithOTP(credential, loginOTP, loginUid, createUserToken);
}
else {
callCreateToken = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createNewToken(credential, loginUid, createUserToken);
}
callCreateToken.enqueue(new Callback<UserTokens>() {
@Override
public void onResponse(@NonNull Call<UserTokens> callCreateToken, @NonNull retrofit2.Response<UserTokens> responseCreate) {
if (responseCreate.isSuccessful()) {
if(responseCreate.code() == 201) {
UserTokens newToken = responseCreate.body();
assert newToken != null;
//Log.i("Tokens-NEW", "new:" + newToken.getSha1());
if (!newToken.getSha1().equals("")) {
tinyDb.remove("loginPass");
tinyDb.putBoolean("loggedInMode", true);
tinyDb.putString(loginUid + "-token", newToken.getSha1());
//Log.i("Tokens", "new:" + newToken.getSha1() + " old:" + tinyDb.getString(loginUid + "-token"));
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
}
}
}
else if(responseCreate.code() == 500) {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(responseCreate.code());
Toasty.info(getApplicationContext(), toastError);
enableProcessButton();
login_button.setText(R.string.btnLogin);
}
}
@Override
public void onFailure(@NonNull Call<UserTokens> createUserToken, Throwable t) {
}
});
}
else {
//Log.i("Current Token", tinyDb.getString(loginUid + "-token"));
tinyDb.putBoolean("loggedInMode", true);
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
}
}
}
else if(response.code() == 500) {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(response.code());
Toasty.info(getApplicationContext(), toastError);
enableProcessButton();
login_button.setText(R.string.btnLogin);
}
else {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(response.code());
//Log.i("error message else4", String.valueOf(response.code()));
Toasty.info(getApplicationContext(), toastError);
enableProcessButton();
login_button.setText(R.string.btnLogin);
}
}
@Override
public void onFailure(@NonNull Call<List<UserTokens>> call, @NonNull Throwable t) {
Log.e("onFailure-login", t.toString());
Toasty.info(getApplicationContext(), getResources().getString(R.string.malformedJson));
enableProcessButton();
login_button.setText(R.string.btnLogin);
}
});
}
private void disableProcessButton() {
login_button.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
login_button.setBackground(shape);
}
private void enableProcessButton() {
login_button.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
login_button.setBackground(shape);
}
}

View File

@@ -0,0 +1,411 @@
package org.mian.gitnex.activities;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import com.google.android.material.navigation.NavigationView;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.NetworkPolicy;
import com.squareup.picasso.Picasso;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.AboutFragment;
import org.mian.gitnex.fragments.MyRepositoriesFragment;
import org.mian.gitnex.fragments.NavSubMenuBottomSheetFragment;
import org.mian.gitnex.fragments.OrganizationsFragment;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.fragments.StarredRepositoriesFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.fragments.ProfileFragment;
import org.mian.gitnex.fragments.RepositoriesFragment;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private DrawerLayout drawer;
private TextView userFullName;
private TextView userEmail;
private ImageView userAvatar;
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("noConnection", false);
//userAvatar = findViewById(R.id.userAvatar);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getString("dateFormat").isEmpty()) {
tinyDb.putString("dateFormat", "pretty");
}
if(tinyDb.getString("codeBlockStr").isEmpty()) {
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorLightGreen));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
}
if(tinyDb.getString("enableCounterIssueBadgeInit").isEmpty()) {
tinyDb.putBoolean("enableCounterIssueBadge", true);
}
if(tinyDb.getString("homeScreenStr").isEmpty()) {
tinyDb.putInt("homeScreenId", 0);
}
String appLocale = tinyDb.getString("locale");
AppUtil.setAppLocale(getResources(), appLocale);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!tinyDb.getBoolean("loggedInMode")) {
logout();
return;
}
androidx.appcompat.widget.Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
final View hView = navigationView.getHeaderView(0);
ImageView navSubMenu = hView.findViewById(R.id.navSubMenu);
navSubMenu.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
NavSubMenuBottomSheetFragment bottomSheet = new NavSubMenuBottomSheetFragment();
bottomSheet.show(getSupportFragmentManager(), "adminMenuBottomSheet");
}
});
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar,
R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.white));
drawer.addDrawerListener(toggle);
drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
}
@Override
public void onDrawerOpened(@NonNull View drawerView) {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
if(!connToInternet) {
if(!tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
}
tinyDb.putBoolean("noConnection", true);
String userEmailNav = tinyDb.getString("userEmail");
String userFullNameNav = tinyDb.getString("userFullname");
String userAvatarNav = tinyDb.getString("userAvatar");
userEmail = hView.findViewById(R.id.userEmail);
if (!userEmailNav.equals("")) {
userEmail.setText(userEmailNav);
}
userFullName = hView.findViewById(R.id.userFullname);
if (!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
}
userAvatar = hView.findViewById(R.id.userAvatar);
if (!userAvatarNav.equals("")) {
Picasso.get().load(userAvatarNav).networkPolicy(NetworkPolicy.OFFLINE).transform(new RoundedTransformation(100, 0)).resize(180, 180).centerCrop().into(userAvatar);
}
} else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
tinyDb.putBoolean("noConnection", false);
}
}
@Override
public void onDrawerClosed(@NonNull View drawerView) {
// Called when a drawer has settled in a completely closed state.
}
@Override
public void onDrawerStateChanged(int newState) {
// Called when the drawer motion state changes. The new state will be one of STATE_IDLE, STATE_DRAGGING or STATE_SETTLING.
}
});
toggle.syncState();
if(savedInstanceState == null) {
if(tinyDb.getInt("homeScreenId") == 0) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
}
else if(tinyDb.getInt("homeScreenId") == 1) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos);
}
else if(tinyDb.getInt("homeScreenId") == 2) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
}
else if(tinyDb.getInt("homeScreenId") == 3) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
}
else if(tinyDb.getInt("homeScreenId") == 4) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
}
else {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
}
}
if(!connToInternet) {
if(!tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
}
tinyDb.putBoolean("noConnection", true);
} else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
tinyDb.putBoolean("noConnection", false);
}
}
public void setActionBarTitle (@NonNull String title) {
Objects.requireNonNull(getSupportActionBar()).setTitle(title);
}
@Override
public void onBackPressed() {
if(drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
else {
super.onBackPressed();
}
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.nav_home:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
break;
case R.id.nav_organizations:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new OrganizationsFragment()).commit();
break;
case R.id.nav_profile:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
break;
case R.id.nav_repositories:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new RepositoriesFragment()).commit();
break;
case R.id.nav_settings:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new SettingsFragment()).commit();
break;
case R.id.nav_logout:
logout();
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break;
case R.id.nav_about:
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:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new StarredRepositoriesFragment()).commit();
break;
}
drawer.closeDrawer(GravityCompat.START);
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 void logout() {
TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
//tinyDb.clear();
finish();
startActivity(new Intent(MainActivity.this, LoginActivity.class));
}
private void displayUserInfo(String instanceUrl, String token, String loginUid) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<UserInfo> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getUserInfo(Authorization.returnAuthentication(getApplicationContext(), loginUid, token));
NavigationView navigationView = findViewById(R.id.nav_view);
final View hView = navigationView.getHeaderView(0);
call.enqueue(new Callback<UserInfo>() {
@Override
public void onResponse(@NonNull Call<UserInfo> call, @NonNull retrofit2.Response<UserInfo> response) {
UserInfo userDetails = response.body();
if (response.isSuccessful()) {
if (response.code() == 200) {
assert userDetails != null;
tinyDb.putString("userLogin", userDetails.getLogin());
tinyDb.putInt("userId", userDetails.getId());
if(!userDetails.getFullname().equals("")) {
tinyDb.putString("userFullname", userDetails.getFullname());
}
else {
tinyDb.putString("userFullname", "...");
}
tinyDb.putString("userEmail", userDetails.getEmail());
tinyDb.putString("userAvatar", userDetails.getAvatar());
if(userDetails.getLang() != null) {
tinyDb.putString("userLang", userDetails.getLang());
}
else
{
tinyDb.putString("userLang", "...");
}
userAvatar = hView.findViewById(R.id.userAvatar);
if (!Objects.requireNonNull(userDetails).getAvatar().equals("")) {
Picasso.get().load(userDetails.getAvatar()).transform(new RoundedTransformation(100, 0)).resize(180, 180).centerCrop().into(userAvatar);
} else {
userAvatar.setImageResource(R.mipmap.ic_launcher_round);
}
userFullName = hView.findViewById(R.id.userFullname);
if (!userDetails.getFullname().equals("")) {
userFullName.setText(userDetails.getFullname());
} else if (!userDetails.getLogin().equals("")) {
userFullName.setText(userDetails.getLogin());
} else {
userFullName.setText("...");
}
userEmail = hView.findViewById(R.id.userEmail);
if (!userDetails.getEmail().equals("")) {
userEmail.setText(userDetails.getEmail());
} else {
userEmail.setText("...");
}
userAvatar.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
drawer.closeDrawers();
}
});
}
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(response.code());
Toasty.info(getApplicationContext(), toastError);
}
}
@Override
public void onFailure(@NonNull Call<UserInfo> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
}

View File

@@ -0,0 +1,242 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.app.DatePickerDialog;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Milestones;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Calendar;
/**
* Author M M Arif
*/
public class NewMilestoneActivity extends AppCompatActivity implements View.OnClickListener {
private EditText milestoneDueDate;
private View.OnClickListener onClickListener;
private EditText milestoneTitle;
private EditText milestoneDescription;
private Button createNewMilestoneButton;
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_milestone);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
milestoneDueDate = findViewById(R.id.milestoneDueDate);
ImageView closeActivity = findViewById(R.id.close);
createNewMilestoneButton = findViewById(R.id.createNewMilestoneButton);
milestoneTitle = findViewById(R.id.milestoneTitle);
milestoneDescription = findViewById(R.id.milestoneDescription);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
milestoneDueDate.setOnClickListener(this);
if(!connToInternet) {
createNewMilestoneButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewMilestoneButton.setBackground(shape);
} else {
createNewMilestoneButton.setOnClickListener(createMilestoneListener);
}
}
private View.OnClickListener createMilestoneListener = new View.OnClickListener() {
public void onClick(View v) {
processNewMilestone();
}
};
private void processNewMilestone() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
//String appLocale = tinyDb.getString("locale");
String newMilestoneTitle = milestoneTitle.getText().toString();
String newMilestoneDescription = milestoneDescription.getText().toString();
String newMilestoneDueDate = milestoneDueDate.getText().toString();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(newMilestoneTitle.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.milestoneNameErrorEmpty));
return;
}
if(!newMilestoneDescription.equals("")) {
if (appUtil.charactersLength(newMilestoneDescription) > 255) {
Toasty.info(getApplicationContext(), getString(R.string.milestoneDescError));
return;
}
}
if(newMilestoneDueDate.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.milestoneDateEmpty));
return;
}
disableProcessButton();
String finalMilestoneDueDate = (AppUtil.customDateCombine(AppUtil.customDateFormat(newMilestoneDueDate)));
createNewMilestone(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, newMilestoneTitle, newMilestoneDescription, finalMilestoneDueDate);
}
private void createNewMilestone(final String instanceUrl, final String token, String repoOwner, String repoName, String newMilestoneTitle, String newMilestoneDescription, String newMilestoneDueDate) {
Milestones createMilestone = new Milestones(newMilestoneDescription, newMilestoneTitle, newMilestoneDueDate);
Call<Milestones> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createMilestone(token, repoOwner, repoName, createMilestone);
call.enqueue(new Callback<Milestones>() {
@Override
public void onResponse(@NonNull Call<Milestones> call, @NonNull retrofit2.Response<Milestones> response) {
if(response.isSuccessful()) {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("milestoneCreated", true);
Toasty.info(getApplicationContext(), getString(R.string.milestoneCreated));
enableProcessButton();
finish();
}
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.milestoneCreatedError));
}
}
@Override
public void onFailure(@NonNull Call<Milestones> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
@Override
public void onClick(View v) {
if (v == milestoneDueDate) {
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,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
milestoneDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth));
}
}, mYear, mMonth, mDay);
datePickerDialog.show();
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private void disableProcessButton() {
createNewMilestoneButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createNewMilestoneButton.setBackground(shape);
}
private void enableProcessButton() {
createNewMilestoneButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createNewMilestoneButton.setBackground(shape);
}
}

View File

@@ -0,0 +1,220 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserOrganizations;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class NewOrganizationActivity extends AppCompatActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private Button createOrganizationButton;
private EditText orgName;
private EditText orgDesc;
final Context ctx = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_organization);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
closeActivity = findViewById(R.id.close);
orgName = findViewById(R.id.newOrganizationName);
orgDesc = findViewById(R.id.newOrganizationDescription);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
createOrganizationButton = findViewById(R.id.createNewOrganizationButton);
if(!connToInternet) {
createOrganizationButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createOrganizationButton.setBackground(shape);
} else {
createOrganizationButton.setOnClickListener(createOrgListener);
}
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private View.OnClickListener createOrgListener = new View.OnClickListener() {
public void onClick(View v) {
processNewOrganization();
}
};
private void processNewOrganization() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newOrgName = orgName.getText().toString();
String newOrgDesc = orgDesc.getText().toString();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(!newOrgDesc.equals("")) {
if (appUtil.charactersLength(newOrgDesc) > 255) {
Toasty.info(getApplicationContext(), getString(R.string.orgDescError));
return;
}
}
if(newOrgName.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.orgNameErrorEmpty));
}
else if(!appUtil.checkStrings(newOrgName)) {
Toasty.info(getApplicationContext(), getString(R.string.orgNameErrorInvalid));
}
else {
disableProcessButton();
createNewOrganization(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), newOrgName, newOrgDesc);
}
}
private void createNewOrganization(final String instanceUrl, final String token, String orgName, String orgDesc) {
UserOrganizations createOrganization = new UserOrganizations(orgName, null, orgDesc, null, null);
Call<UserOrganizations> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createNewOrganization(token, createOrganization);
call.enqueue(new Callback<UserOrganizations>() {
@Override
public void onResponse(@NonNull Call<UserOrganizations> call, @NonNull retrofit2.Response<UserOrganizations> response) {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("orgCreated", true);
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.orgCreated));
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 409) {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.orgExistsError));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.orgExistsError));
}
else {
if(response.code() == 404) {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.apiNotFound));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.orgCreatedError));
}
}
}
@Override
public void onFailure(@NonNull Call<UserOrganizations> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void disableProcessButton() {
createOrganizationButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createOrganizationButton.setBackground(shape);
}
private void enableProcessButton() {
createOrganizationButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createOrganizationButton.setBackground(shape);
}
}

View File

@@ -0,0 +1,314 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.OrgOwner;
import org.mian.gitnex.models.OrganizationRepository;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class NewRepoActivity extends AppCompatActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private Spinner spinner;
private Button createRepo;
private EditText repoName;
private EditText repoDesc;
private CheckBox repoAccess;
final Context ctx = this;
List<OrgOwner> orgsList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_repo);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String userLogin = tinyDb.getString("userLogin");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
closeActivity = findViewById(R.id.close);
repoName = findViewById(R.id.newRepoName);
repoDesc = findViewById(R.id.newRepoDescription);
repoAccess = findViewById(R.id.newRepoPrivate);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
spinner = findViewById(R.id.ownerSpinner);
spinner.getBackground().setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_ATOP);
getOrgs(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), userLogin);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
OrgOwner user = (OrgOwner) parent.getSelectedItem();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
createRepo = findViewById(R.id.createNewRepoButton);
disableProcessButton();
if(!connToInternet) {
disableProcessButton();
}
else {
createRepo.setOnClickListener(createRepoListener);
}
}
private View.OnClickListener createRepoListener = new View.OnClickListener() {
public void onClick(View v) {
processNewRepo();
}
};
private void processNewRepo() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
AppUtil appUtil = new AppUtil();
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newRepoName = repoName.getText().toString();
String newRepoDesc = repoDesc.getText().toString();
String repoOwner = spinner.getSelectedItem().toString();
boolean newRepoAccess = repoAccess.isChecked();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(!newRepoDesc.equals("")) {
if (appUtil.charactersLength(newRepoDesc) > 255) {
Toasty.info(getApplicationContext(), getString(R.string.repoDescError));
return;
}
}
if(newRepoName.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.repoNameErrorEmpty));
}
else if(!appUtil.checkStrings(newRepoName)) {
Toasty.info(getApplicationContext(), getString(R.string.repoNameErrorInvalid));
}
else {
//Log.i("repoOwner", String.valueOf(repoOwner));
disableProcessButton();
createNewRepository(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), loginUid, newRepoName, newRepoDesc, repoOwner, newRepoAccess);
}
}
private void createNewRepository(final String instanceUrl, final String token, String loginUid, String repoName, String repoDesc, String repoOwner, boolean isPrivate) {
OrganizationRepository createRepository = new OrganizationRepository(true, repoDesc, null, null, repoName, isPrivate, "Default");
Call<OrganizationRepository> call;
if(repoOwner.equals(loginUid)) {
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createNewUserRepository(token, createRepository);
}
else {
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.createNewUserOrgRepository(token, repoOwner, createRepository);
}
call.enqueue(new Callback<OrganizationRepository>() {
@Override
public void onResponse(@NonNull Call<OrganizationRepository> call, @NonNull retrofit2.Response<OrganizationRepository> response) {
if(response.code() == 201) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("repoCreated", true);
Toasty.info(getApplicationContext(), getString(R.string.repoCreated));
enableProcessButton();
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 409) {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.repoExistsError));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.repoCreatedError));
}
}
@Override
public void onFailure(@NonNull Call<OrganizationRepository> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void getOrgs(String instanceUrl, String instanceToken, final String userLogin) {
Call<List<OrgOwner>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getOrgOwners(instanceToken);
call.enqueue(new Callback<List<OrgOwner>>() {
@Override
public void onResponse(@NonNull Call<List<OrgOwner>> call, @NonNull retrofit2.Response<List<OrgOwner>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
List<OrgOwner> orgsList_ = response.body();
orgsList.add(new OrgOwner(userLogin));
assert orgsList_ != null;
if(orgsList_.size() > 0) {
for (int i = 0; i < orgsList_.size(); i++) {
OrgOwner data = new OrgOwner(
orgsList_.get(i).getUsername()
);
orgsList.add(data);
}
}
ArrayAdapter<OrgOwner> adapter = new ArrayAdapter<>(getApplicationContext(),
R.layout.spinner_item, orgsList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner.setAdapter(adapter);
enableProcessButton();
}
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
}
@Override
public void onFailure(@NonNull Call<List<OrgOwner>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private void disableProcessButton() {
createRepo.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
createRepo.setBackground(shape);
}
private void enableProcessButton() {
createRepo.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
createRepo.setBackground(shape);
}
}

View File

@@ -0,0 +1,134 @@
package org.mian.gitnex.activities;
import com.google.android.material.tabs.TabLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import org.mian.gitnex.R;
import org.mian.gitnex.fragments.MembersByOrgFragment;
import org.mian.gitnex.fragments.OrgBottomSheetFragment;
import org.mian.gitnex.fragments.OrganizationInfoFragment;
import org.mian.gitnex.fragments.RepositoriesByOrgFragment;
import org.mian.gitnex.fragments.TeamsByOrgFragment;
import org.mian.gitnex.util.TinyDB;
import java.util.Objects;
/**
* Author M M Arif
*/
public class OrgDetailActivity extends AppCompatActivity implements OrgBottomSheetFragment.BottomSheetListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_org_detail);
TinyDB tinyDb = new TinyDB(getApplicationContext());
String orgName = tinyDb.getString("orgName");
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(orgName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
OrgDetailActivity.SectionsPagerAdapter mSectionsPagerAdapter = new OrgDetailActivity.SectionsPagerAdapter(getSupportFragmentManager());
ViewPager mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = findViewById(R.id.tabs);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.repo_dotted_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
OrgBottomSheetFragment bottomSheet = new OrgBottomSheetFragment();
bottomSheet.show(getSupportFragmentManager(), "orgBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
switch (text) {
case "team":
startActivity(new Intent(OrgDetailActivity.this, CreateTeamByOrgActivity.class));
break;
}
//Log.i("clicked", text);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@NonNull
@Override
public Fragment getItem(int position) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
String orgName;
if(getIntent().getStringExtra("orgName") != null || !getIntent().getStringExtra("orgName").equals("")) {
orgName = getIntent().getStringExtra("orgName");
}
else {
orgName = tinyDb.getString("orgName");
}
Fragment fragment = null;
switch (position) {
case 0: // info
return OrganizationInfoFragment.newInstance(orgName);
case 1: // repos
return RepositoriesByOrgFragment.newInstance(orgName);
case 2: // teams
return TeamsByOrgFragment.newInstance(orgName);
case 3: // members
return MembersByOrgFragment.newInstance(orgName);
}
return fragment;
}
@Override
public int getCount() {
return 4;
}
}
}

View File

@@ -0,0 +1,102 @@
package org.mian.gitnex.activities;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.TeamMembersByOrgAdapter;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.TeamMembersByOrgViewModel;
import java.util.List;
/**
* Author M M Arif
*/
public class OrgTeamMembersActivity extends AppCompatActivity {
private TextView noDataMembers;
private View.OnClickListener onClickListener;
private TeamMembersByOrgAdapter adapter;
private GridView mGridView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_org_team_members);
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
TextView toolbarTitle = findViewById(R.id.toolbar_title);
noDataMembers = findViewById(R.id.noDataMembers);
mGridView = findViewById(R.id.gridView);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(getIntent().getStringExtra("teamTitle") != null && !getIntent().getStringExtra("teamTitle").equals("")) {
toolbarTitle.setText(getIntent().getStringExtra("teamTitle"));
}
else {
toolbarTitle.setText(R.string.orgTeamMembers);
}
String teamId;
if(getIntent().getStringExtra("teamId") != null && !getIntent().getStringExtra("teamId").equals("")){
teamId = getIntent().getStringExtra("teamId");
}
else {
teamId = "0";
}
getIntent().getStringExtra("teamId");
Log.i("teamId", getIntent().getStringExtra("teamId"));
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), Integer.valueOf(teamId));
}
private void fetchDataAsync(String instanceUrl, String instanceToken, int teamId) {
TeamMembersByOrgViewModel teamMembersModel = ViewModelProviders.of(this).get(TeamMembersByOrgViewModel.class);
teamMembersModel.getMembersByOrgList(instanceUrl, instanceToken, teamId).observe(this, new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> teamMembersListMain) {
adapter = new TeamMembersByOrgAdapter(getApplicationContext(), teamMembersListMain);
if(adapter.getCount() > 0) {
mGridView.setAdapter(adapter);
noDataMembers.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mGridView.setAdapter(adapter);
noDataMembers.setVisibility(View.VISIBLE);
}
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}

View File

@@ -0,0 +1,208 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.AddEmail;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author M M Arif
*/
public class ProfileEmailActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
private EditText userEmail;
final Context ctx = this;
private Button addEmailButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile_email);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
ImageView closeActivity = findViewById(R.id.close);
userEmail = findViewById(R.id.userEmail);
addEmailButton = findViewById(R.id.addEmailButton);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if(!connToInternet) {
disableProcessButton();
} else {
addEmailButton.setOnClickListener(addEmailListener);
}
}
private View.OnClickListener addEmailListener = new View.OnClickListener() {
public void onClick(View v) {
processAddNewEmail();
}
};
private void processAddNewEmail() {
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String newUserEmail = userEmail.getText().toString().trim();
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(newUserEmail.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.emailErrorEmpty));
return;
}
else if(!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.info(getApplicationContext(), getString(R.string.emailErrorInvalid));
return;
}
List<String> newEmailList = new ArrayList<>(Arrays.asList(newUserEmail.split(",")));
disableProcessButton();
addNewEmail(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), newEmailList);
}
private void addNewEmail(final String instanceUrl, final String token, List<String> newUserEmail) {
AddEmail addEmailFunc = new AddEmail(newUserEmail);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
Call<JsonElement> call;
call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.addNewEmail(token, addEmailFunc);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
if(response.code() == 201) {
Toasty.info(getApplicationContext(), getString(R.string.emailAddedText));
tinyDb.putBoolean("emailsRefresh", true);
enableProcessButton();
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 403) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
}
else if(response.code() == 422) {
enableProcessButton();
Toasty.info(ctx, ctx.getString(R.string.emailErrorInUse));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private void disableProcessButton() {
addEmailButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
addEmailButton.setBackground(shape);
}
private void enableProcessButton() {
addEmailButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
addEmailButton.setBackground(shape);
}
}

View File

@@ -0,0 +1,278 @@
package org.mian.gitnex.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.hendraanggrian.appcompat.socialview.Mention;
import com.hendraanggrian.appcompat.widget.MentionArrayAdapter;
import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
* Author M M Arif
*/
public class ReplyToIssueActivity extends AppCompatActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
final Context ctx = this;
private SocialAutoCompleteTextView addComment;
private ArrayAdapter<Mention> defaultMentionAdapter;
private Button replyButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reply_to_issue);
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
TinyDB tinyDb = new TinyDB(getApplicationContext());
addComment = findViewById(R.id.addComment);
addComment.setShowSoftInputOnFocus(true);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
addComment.setMentionAdapter(defaultMentionAdapter);
closeActivity = findViewById(R.id.close);
TextView toolbar_title = findViewById(R.id.toolbar_title);
if(!tinyDb.getString("issueTitle").isEmpty()) {
toolbar_title.setText(tinyDb.getString("issueTitle"));
}
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
replyButton = findViewById(R.id.replyButton);
if(getIntent().getStringExtra("commentAction") != null && getIntent().getStringExtra("commentAction").equals("edit")) {
addComment.setText(getIntent().getStringExtra("commentBody"));
final String commentId = getIntent().getStringExtra("commentId");
toolbar_title.setText(getResources().getString(R.string.editCommentTitle));
replyButton.setText(getResources().getString(R.string.editCommentButtonText));
replyButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
IssueActions.editIssueComment(ctx, Integer.valueOf(commentId), addComment.getText().toString());
}
});
return;
}
if(!connToInternet) {
disableProcessButton();
} else {
replyButton.setOnClickListener(replyToIssue);
}
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull Response<List<Collaborators>> response) {
if (response.isSuccessful()) {
assert response.body() != null;
String fullName = "";
for (int i = 0; i < response.body().size(); i++) {
if(!response.body().get(i).getFull_name().equals("")) {
fullName = response.body().get(i).getFull_name();
}
defaultMentionAdapter.add(
new Mention(response.body().get(i).getUsername(), fullName, response.body().get(i).getAvatar_url()));
}
} else {
Log.i("onResponse", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
}
});
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
private View.OnClickListener replyToIssue = new View.OnClickListener() {
public void onClick(View v) {
processNewCommentReply();
}
};
private void processNewCommentReply() {
String newReplyDT = addComment.getText().toString();
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
if(!connToInternet) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
return;
}
if(newReplyDT.equals("")) {
Toasty.info(getApplicationContext(), getString(R.string.commentEmptyError));
}
else {
disableProcessButton();
replyComment(newReplyDT);
}
}
private void replyComment(String newReplyDT) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final int issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
Issues issueComment = new Issues(newReplyDT);
Call<Issues> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.replyCommentToIssue(Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName, issueIndex, issueComment);
call.enqueue(new Callback<Issues>() {
@Override
public void onResponse(@NonNull Call<Issues> call, @NonNull retrofit2.Response<Issues> response) {
if(response.code() == 201) {
Toasty.info(getApplicationContext(), getString(R.string.commentSuccess));
tinyDb.putBoolean("commentPosted", true);
tinyDb.putBoolean("resumeIssues", true);
finish();
}
else if(response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
enableProcessButton();
Toasty.info(getApplicationContext(), getString(R.string.commentError));
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void disableProcessButton() {
replyButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.hintColor));
replyButton.setBackground(shape);
}
private void enableProcessButton() {
replyButton.setEnabled(true);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
shape.setColor(getResources().getColor(R.color.btnBackground));
replyButton.setBackground(shape);
}
}

View File

@@ -0,0 +1,245 @@
package org.mian.gitnex.activities;
import com.google.android.material.tabs.TabLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import retrofit2.Call;
import retrofit2.Callback;
import android.content.Intent;
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.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.fragments.BranchesFragment;
import org.mian.gitnex.fragments.ClosedIssuesFragment;
import org.mian.gitnex.fragments.CollaboratorsFragment;
import org.mian.gitnex.fragments.IssuesFragment;
import org.mian.gitnex.fragments.LabelsFragment;
import org.mian.gitnex.fragments.MilestonesFragment;
import org.mian.gitnex.fragments.ReleasesFragment;
import org.mian.gitnex.fragments.RepoBottomSheetFragment;
import org.mian.gitnex.fragments.RepoInfoFragment;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Objects;
/**
* Author M M Arif
*/
public class RepoDetailActivity extends AppCompatActivity implements RepoBottomSheetFragment.BottomSheetListener {
private TextView textViewBadge;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_repo_detail);
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoName1 = parts[1];
final String instanceUrl = tinyDb.getString("instanceUrl");
final String repoOwner = parts[0];
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String appLocale = tinyDb.getString("locale");
AppUtil.setAppLocale(getResources(), appLocale);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName1);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
ViewPager mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = findViewById(R.id.tabs);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
if(tinyDb.getBoolean("enableCounterIssueBadge")) {
View tabHeader = LayoutInflater.from(this).inflate(R.layout.badge, null);
textViewBadge = tabHeader.findViewById(R.id.counterBadge);
if(!tinyDb.getString("issuesCounter").isEmpty()) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName1);
}
Objects.requireNonNull(tabLayout.getTabAt(1)).setCustomView(tabHeader);
}
}
@Override
public void onResume() {
super.onResume();
TinyDB tinyDb = new TinyDB(getApplicationContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getBoolean("enableCounterIssueBadge")) {
getRepoInfo(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.repo_dotted_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
RepoBottomSheetFragment bottomSheet = new RepoBottomSheetFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onButtonClicked(String text) {
switch (text) {
case "label":
startActivity(new Intent(RepoDetailActivity.this, CreateLabelActivity.class));
break;
case "newIssue":
startActivity(new Intent(RepoDetailActivity.this, CreateIssueActivity.class));
break;
case "newMilestone":
startActivity(new Intent(RepoDetailActivity.this, NewMilestoneActivity.class));
break;
case "addCollaborator":
startActivity(new Intent(RepoDetailActivity.this, AddCollaboratorToRepositoryActivity.class));
break;
case "createRelease":
startActivity(new Intent(RepoDetailActivity.this, CreateReleaseActivity.class));
break;
}
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@NonNull
@Override
public Fragment getItem(int position) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
String repoOwner = parts[0];
String repoName = parts[1];
Fragment fragment = null;
switch (position) {
case 0: // information
return RepoInfoFragment.newInstance(repoOwner, repoName);
case 1: // issues
fragment = new IssuesFragment();
break;
case 2: // closed issues
fragment = new ClosedIssuesFragment();
break;
case 3: // milestones
return MilestonesFragment.newInstance(repoOwner, repoName);
case 4: // labels
return LabelsFragment.newInstance(repoOwner, repoName);
case 5: // branches
return BranchesFragment.newInstance(repoOwner, repoName);
case 6: // releases
return ReleasesFragment.newInstance(repoOwner, repoName);
case 7: // collaborators
return CollaboratorsFragment.newInstance(repoOwner, repoName);
}
return fragment;
}
@Override
public int getCount() {
return 8;
}
}
private void getRepoInfo(String instanceUrl, String token, final String owner, String repo) {
Call<UserRepositories> call = RetrofitClient
.getInstance(instanceUrl)
.getApiInterface()
.getUserRepository(token, owner, repo);
call.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
UserRepositories repoInfo = response.body();
if (response.isSuccessful()) {
if (response.code() == 200) {
assert repoInfo != null;
textViewBadge.setText(repoInfo.getOpen_issues_count());
}
}
else {
Log.e("onFailure", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
}

View File

@@ -0,0 +1,37 @@
package org.mian.gitnex.activities;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import org.mian.gitnex.R;
/**
* Author M M Arif
*/
public class SponsorsActivity extends AppCompatActivity {
private View.OnClickListener onClickListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sponsors);
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
}
private void initCloseListener() {
onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
};
}
}